AppleScript Speed:Text Handling

Another speed stunner, but not so much, as AppleScript’s text manipulation is acknowledged to be quite slow.

The objective is to extract a piece of text from a string, specifically the ‘middle’ of the OS X version. This is part of a larger script that needs to know which version of OS X it is running on.

Here are two ways of getting that piece of text. First, using the offset command:

set osVers to (do shell script "sw_vers -productVersion")
set aDot to (offset of "." in osiers)
set myVers to (text (aDot + 1) thru -1 of osiers)
set aDot to (offset of "." in myVers)
set myVers to (text 1 thru (aDot - 1) of myVers)

Second, using text item delimiters:

set osVers to (do shell script "sw_vers -productVersion")
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to "."
set myVers to (text item 2 of osiers)
set AppleScript's text item delimiters to oldDelims

Using text item delimiters is about 20 times faster.

September 13, 2011

google_pluslinkedingoogle_pluslinkedinby feather

Send Mail from AppleScript

I once figured out the various ways to send mail using the *nix mail and sendmail commands. Then I lost that information, so after fooling around for three hours, here is what appears to me to be the best solution:

on mailAway(theReply) -- uses mail, not sendmail
   local MailSubject, MailBody, shellScript, theResult
   try
      set MailSubject to quoted form of ("Report from " & (computer name of (system info)))
      set MailBody to quoted form of ("Script Results" & linefeed & theReply)
      set shellScript to ("echo " & MailBody & " | mail -s " & MailSubject & ¬
          space & kSendTo) as string
      set theResult to (do shell script (shellScript))
   on error errmsg number errNum
      set theResult to ("Error " & errNum & space & errmsg)
   end try
   return theResult
end mailAway

The best resource I found was this Mac OS X Hints page.

To get the results mailed to you, use:

mail -s 'The Mail Log' to@domain.com < /var/log/mail.log
google_pluslinkedingoogle_pluslinkedinby feather

Send Mail from AppleScript

I once figured out the various ways to send mail using the *nix mail and sendmail commands. Then I lost that information, so after fooling around for three hours, here is what appears to me to be the best solution:

on mailAway(theReply) -- uses mail, not sendmail
   local MailSubject, MailBody, shellScript, theResult
   try
      set MailSubject to quoted form of ("Report from " & (computer name of (system info)))
      set MailBody to quoted form of ("Script Results" & linefeed & theReply)
      set shellScript to ("echo " & MailBody & " | mail -s " & MailSubject & space & kSendTo) as string
      set theResult to (do shell script (shellScript))
   on error errmsg number errNum
      set theResult to ("Error " & errNum & space & errmsg)
   end try
   return theResult
end mailAway

The best resource I found was this Mac OS X Hints page.

To get the results mailed to you, use:

mail -s 'The Mail Log' to@domain.com < /var/log/mail.log
google_pluslinkedingoogle_pluslinkedinby feather

AppleScript Timing Tests

I used to use Jon’s Commands to get ‘the ticks’ to do precise timing of routines. Now in the 64 bit world, I needed a replacement. Here it is, complete with my routine performance comparison test code.

property kPreciseTime : "perl -e 'use Time::HiRes qw(time); print time'"
on run
    try
        set iterate to 1000
        set t1 to do shell script (kPreciseTime)
        repeat iterate times
            -- block comment
        end repeat
        set t2 to do shell script (kPreciseTime)
        repeat iterate times
            -- insert test two here
        end repeat
        set t3 to do shell script (kPreciseTime)

        set ta1 to (t2 - t1)
        set ta2 to (t3 - t2)

    on error errMsg number errNum
        return errNum
    end try
    return 0
end run

From this I learned (most recently) that when writing to a file, it is better to concatenate text into a larger chunk and do fewer writes.

google_pluslinkedingoogle_pluslinkedinby feather

Getting Screen Sizes in AppleScript

Having finally bit the bullet and upgraded to a new Mac running OS X 10.6, I find I need to replace some old Scripting Additions. Not wanting to fall into the trap again of relying on third parties, I will search for ways to accomplish the same tasks from within the system.

First up is a need to replace the “screen list” command in Jon’s Commands. This code gets the dimensions of the active displays.

set kCR to (character id 13)
set command to "/usr/sbin/system_profiler SPDisplaysDataType  | grep Resolution"
set output to (do shell script command)

set oldDelims to AppleScript's text item delimiters
try
   set myDisplays to {}
   set AppleScript's text item delimiters to {kCR} -- return
   set myDisplays to (text items of output)
   
   set AppleScript's text item delimiters to {": ", " x ", " @ "}
   repeat with a from 1 to (count myDisplays)
      set thisDisplay to rest of (text items of (item a of myDisplays))
      set (item a of myDisplays) to (thisDisplay)
   end repeat
end try
set AppleScript's text item delimiters to oldDelims
return myDisplays

Reply is {{w, h, hz}, {w, h, hz}}

Note also that I am taking advantage of the ability to define multiple text item delimiters: a Snow Leopard first!

Aug 24, 2010

google_pluslinkedingoogle_pluslinkedinby feather