AppleScript


2
Jan 12

AppleScript-Cocoa Over PyObjC?

What’s more odd to me, is that Apple has dropped the PyObjC support but gave AppleScript a giant boost with Cocoa-AppleScript. Don’t get me wrong, I like AppleScript fine, but it sure isn’t as flexible as Python or Ruby[1].

Anyway, if your thinking about making any AppleScript-Cocoa projects, here’s a very good tutorial over at MacScripter.

 

UPDATE: There are also great resources over at MacAutomation.com, including what looks like a good book.


  1. I know about MacRuby and it’s the best reason yet for me to start thinking about Ruby over Python. I only have so much free time, and almost no work time to invest in learning a new language.  ↩

30
Dec 11

Junecloud Automator Actions

Junecloud makes the terrific Delivery Status widget and Delivery Status Touch for iOS. If you do a lot of package tracking, these are the best tools available.

But I noticed that they also provide a free set of Automator actions that are very handy.

  • “Save for Web” generates images with specific size and quality settings.
  • “Make Names Web-Friendly” replaces spaces and other special characters to web friendly characters such as underscores.
  • “Create Clean Archive” makes a zip archive but removes all of the resource forks and Mac specific cruft.
  • “Create Symbolic Link”

Good stuff.


26
Dec 11

Scripting Bridge Redirect

A funny thing happened when I was reading through references for Python on OS X. Dr.Drang had a link to Apple’s Scripting Bridge page. The funny part is that Apple appears to now redirect that page to the Automator page. It doesn’t give me a lot of confidence in learning the Scripting Bridge.

Here’s the new home.


22
Dec 11

Timestamps in AppleScript

AppleScript is easy for most basic file manipulations on the Mac. For example, I can get a files modification timestamp with the following bit of AppleScript:

set modificationDate to modification date of this_item

where “this_item” is a reference to a file. “modificationDate” now contains a value like “Wednesday, December 21, 2011 7:24:22 PM”

But that’s a pretty awkward timestamp if I want to use it to name a file. In AppleScript, reformatting a timestamp is awkward and tedious. I often resort to other options. I have two preferred methods.

AppleScript -> Shell

Embeding a bit of shell script into AppleScript is easy. Here’s an AppleScript handler that takes a date like the one above and returns a nicely formatting compact timestamp

on FormatTime(AS_Date)
        return (do shell script "date -j -f '%A, %B %e, %Y %l:%M:%S %p' '" & AS_Date & "' '+%Y%m%d_%H-%M-%S'")
end FormatTime

where “AS_Date” is the native AppleScript timestamp. This works, but it’s not very universal. The AS_Date must always be in the format of ”Wednesday, December 21, 2011 7:24:22 PM” or the script will throw an error.

So I have another bit of AppleScript that relies on Python to do the hard bit of parsing a date and returning a formatted timestamp

AppleScript -> Shell -> Python

That’s right, AppleScript runs a shell command, which in turn calls the Python processor. Now that Python is running within the AppleScript, I have access to some of the best date and time libraries around. Specifically, the dateutil never disappoints.

on pyFormatTime(AS_Date)
    set timeFormat to quoted form of "%Y%m%d_%H%M%S"
    return (do shell script "/usr/bin/python -c \"import time, dateutil.parser; print dateutil.parser.parse(" & AS_Date & ").strftime(" & timeFormat & "); \"")
end pyFormatTime

In this case, the AppleScript handler can accept any kind of date without knowledge of the format. It can then process the date and return a timestamp in my preferred format. For example all of the following dates will give the same timestamp:

  • “12-21-2011 7:24:22 PM”
  • “12-21-2011 19:24:22″
  • “12/21/2011 7:24:22 PM”
  • “Dec 21, 2011 7:24:22 PM”

If I wanted to get really fancy, I could also use parsedatetime to accept even more awkward date formats and return a specific timestamp. No need to go crazy though.


21
Dec 11

Great AppleScript Collection [Link]

There’s some very high quality AppleScript functions and tools on Brati’s Lover. Just look at this nicely compiled list of file handlers. The site is worth a visit just for the cute Mac-like design.


22
Nov 11

Finder Push and Pop

This might make the bash people out there smile a little bit. If you love the push and pop functions on unix, this pair of macros bring both to the OS X Finder.

The core of each macro is an AppleScript, so these could easily be ported to LaunchBar or Alfred.

Macro 1 – Push

The Push macro grabs the currently viewed folder path and saves it to a Keyboard Maestro macro.

Push Macro

tell application "Finder"
    try
        set myWindow to folder of front window as string
        return myWindow
    end try
end tell

 

Macro 2 – Pop

This macro reads the variable saved from the Push macro and then executes an AppleScript to open the Finder location

Pop  Macro

 

tell application "Keyboard Maestro Engine"
    set kmVarPush to (process tokens "%Variable%pushPath%")
end tell
tell application "Finder"
    try
        open kmVarPush
    end try
end tell

Usage

These macros live on my Finder palette in Keyboard Maestro.

Finder Palette

If I’m working in a Finder window that I may need to recall later, I hit ctrl-cmd-F to bring up my Finder palette for Keyboard Maestro. I then hit the 8 key for the “Push” macro.

Later, when my Finder windows are all out of order or closed completely, I hit ctrl-cmd-F and then the 9 key for the “Pop” macro. A shiny new Finder window is opened right to where I wanted it.


21
Nov 11

Keyboard Maestro Variables: Remember Current Application

I was recently wasting some time playing with an idea. I wanted an easy and quick way to grab some text in any arbitrary application and pop over to MultiMarkdown Composer to do some editing. I also wanted a way to pop the text back into the original app when I was done.

You might be yelling at the screen right now telling me to just use the cmd-tab to switch back and paste the text. Don’t yell at me. What if I had quickly jumped to Safari to check a link, or looked for a contact or previous mail message? So much for the super quick cmd-tab application switcher.

Well, there’s an easy way to do this with Keyboard Maestro and it involves a bit of variable magic. So why not learn a little something about my favorite macro application?

This solution is two separate macros. The first macro grabs the text and the name of the application. The second macro takes the edited text and returns to the original app for insertion.

Macro One

Set the variable “currentApp” to the currently running application name. Next, simulate cmd-A and cmd-C to get the text. The macro then switches to MultiMarkdown Composer and simulates cmd-N and cmd-V to create a new document and insert the text.

KM Macro 1

Macro Two

Now we’re done editing and looking up links and taking a break and playing AlphaBaby with our three year old. We want to send the text back to whatever application we were originally working in. Luckily, Keyboard Maestro variables persist across restarts and shutdowns, which is more than I can say about my memory.

The second macro performs a cmd-A and cmd-C to grab all of our polished text.[1] The trick is that bit of AppleScript in the middle.

KM Macro 2

tell application “Keyboard Maestro Engine”
set kmVarApp to (process tokens “%Variable%currentApp%”) as text
end tell
tell application kmVarApp  
activate
end tell

This script accesses the Keyboard Maestro variable using the “process tokens” function provided by the Keyboard Maestro Engine. That allows access to any variable or token available in KM. The script then launches the application by name.

Finally, the macro does the cmd-A and cmd-V to insert the new text. Boom.

We’re done here.


  1. This works from the preview window as well.


18
Nov 11

Omnifocus to Text [Link]

A nice little script by Wolf Rentzsch for extracting actions from Omnifocus to plain text. Applescript may be showing its age, but it sure is readable. That script almost looks like instructions you would provide to a person to perform the same action.


8
Nov 11

Resize Images in AppleScript

I really like Dr. Drang’s method of using sips for manipulating images. I set out to modify my FTP macro to include an image resize step. After a short bit of playing around I discovered that it’s very easy to manipulate images right in AppleScript. In fact, Apple provides services to add the necessary code to a script just by selecting the variable that points to an image.

Here’s the script:

tell application “Finder”

set this_item to get selection

set myPath to POSIX path of (this_item as text)

end tell

tell application “Image Events”

set this_image to open myPath

scale this_image to size 550

save this_image in myPath

close this_image

end tell


Here’s how easy it is. The first couple of lines just get the finder selection and places the path in a variable. Select that variable and right click.

 

 

Select the “Resize” script as shown. A window will pop-up asking for the desired size. That’s about it. Apple has made this very easy.


27
Sep 11

Scratch File – Add to Top

I modified my scratch file script. The new version appends the clipboard to the top of the file rather than the bottom. That way the scratch file is in chronological order.

WARNING: This script overwrites the contents of a file.

do shell script "pbpaste > '/tmp/qqq_Scratch.txt'
echo >> '/tmp/qqq_Scratch.txt'
cat '/Volumes/Macintosh HD 2/Dropbox/Notes/qqq_Scratch.txt' >> '/tmp/qqq_Scratch.txt'
cat '/tmp/qqq_Scratch.txt' > '/Volumes/Macintosh HD 2/Dropbox/Notes/qqq_Scratch.txt'"

Just as a Unix reminder, the double angle bracket “>>” will append text to the end of another file. The single angle bracket “>” will create a new file or overwrite the existing content.

This new version of the script takes advantage of the hidden tmp directory on OSX to first store the contents of the clipboard. It then adds a new line char with the echo and finally writes the previous contents of the scratch file into the temporary file. It then overwrites the scratch file in my notes directory with the contents of the temporary file.


26
Sep 11

Scratch File

I keep a scratch file in my NVAlt library. I use it to keep random bits of information that I want to out live the clipboard. It’s not meant to be permanent just a stop-over to some other destination. My clipboard is pretty volatile since I have a number of macros and scripts that temporarily hold bits of information on the clipboard. If it’s something I might need later, then I better get it into something a bit more permanent. A scratch file is perfect for this.

The file is titled “qqq_Scratch.txt” after Merlin’s trick. I don’t have many files that start with “qqq” but a scratch file needs to be available as soon as I open my notes. I also pin the file to the top of my Simplenote list. So, yeah, I use it a lot.

I was pasting a bunch of info back and forth to it the other day and suddenly realized I could quickly make a macro to do the job. It’s really just a shell script:

 

do shell script "echo >>  '/Volumes/Macintosh HD 2/Dropbox/Notes/qqq_Scratch.txt'
pbpaste >> '/Volumes/Macintosh HD 2/Dropbox/Notes/qqq_Scratch.txt'"

The first echo command adds a newline to the end of the file. The second pbpaste command pipes the current clipboard entry to the end of the text file.

The first thing I did was make a new Keyboard Maestro macro out of this. It works perfectly. I also decided to make a LaunchBar action out of the command.

To create the LaunchBar action, I saved the above AppleScript to a folder I keep on Dropbox for LaunchBar scripts. It’s particularly easy to create AppleScripts for LaunchBar if you don’t need to pass parameters. I’ve created a custom list in the LaunchBar index where I manually add the scripts I create.

Screen Shot 20110926 171420

So to use this script from LaunchBar, I copy some text to the clipboard and then CMD-SPACE to access LaunchBar. Start typing the name of the script (Clipboard to Scratch) and hit return. Within a second, the clipboard contents (as long as it’s text) is appended to the end of the scratch file.


23
Sep 11

Upload File Selection Via Transmit

 

In the never-ending pursuit of hard-won laziness, I often develop scripts to do simple tasks. Sometimes the joy is in the problem solving and sometimes it’s in the final product. In this case it was in both.

Yesterday I was working on an as yet to be published post that has a large number of images. My typical workflow is to make an annotation in the text of the image I want to insert. I then transfer the html to MarsEdit and begin the image insertion process. I quickly decided that there had to be a better way to upload a bunch of images and grab their url at that same time.

Here’s what I came up with. It’s an AppleScript that uses Transmit to FTP the current Finder selections to my WordPress content directory for the current year and month and give back the exact url’s to the files. It’s not that pretty or efficient. What I like about it is how it shows just how flexible and powerful AppleScript can be. In one script, there is AppleScript doing most of the integration and basic logic, with a shell script to do some date conversion and finally python to perform the url encoding of the file name.

The following script could be triggered by FastScripts, Keyboard Maestro, LaunchBar or Alfred. That’s the real beauty of scripting on Mac OS.

There are a couple of assumptions for this script to work. First, you must have Transmit from Panic Software. If you need any kind of FTP access, quit messing around and go buy it.

Second, you need to save your ftp location as a favorite in Transmit. Using favorites in Transmit is nice, because you can have all of your login credentials securely handled by Transmit and omit them from an scripts you may publish to some silly blog.

(* This is my WordPress upload root *)
set urlPath to "http://www.macdrifter.com/wp-content/uploads/"

(* This will set the upload path to year/month/ *)
set myMonth to do shell script "date +\"%m\""
set myYear to 1 * (year of (current date))
set clipContents to {}

tell application "Finder"
    set these_items to the selection
    set myFolder to (POSIX path of (target of the front window as alias))
end tell
tell application "Transmit"

    (* Find the favorite for the FTP Site *)
    set myFav to item 1 of (favorites whose name is "Macdrifter_WP")
    tell current tab of (make new document at end)

        (* Connect to the favorite *)
        connect to myFav
        change location of remote browser to path "/wp-content/uploads/" & myYear & "/" & myMonth & "/"
        change location of local browser to path myFolder

        (* Process all of the finder selections *)
        repeat with i from 1 to the count of these_items
            set this_item to (item i of these_items) as alias
            set this_info to info for this_item
            set myPath to (POSIX path of this_item)
            set myFileName to name of this_info as text

            (* If we want to use the files in a blog post we need the URL's. But we need the URL's encoded because we may have spaces in the file names *)
            set myURLFileName to do shell script "/usr/bin/python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' " & quoted form of myFileName
            set myURLFileName to urlPath & myYear & "/" & myMonth & "/" & myURLFileName
            set end of clipContents to "
"
& myURLFileName

            (* Upload the files. Duplicates will require user interaction. That's safer *)
            tell remote browser
                upload item at path myPath to "/wp-content/uploads/" & myYear & "/" & myMonth & "/"
            end tell

            (* Enable if we want the window to close when the deed is done *)
            (* close remote browser *)

        end repeat
    end tell
end tell
(* Convert our list to a single block of text *)
set AppleScript's text item delimiters to "
"

set clipContents to clipContents as string

return clipContents

 


14
Sep 11

Moom Update

No sooner do I post my Moom review and an update is released. New features:

  1. AppleScript triggers. You can now trigger your saved window layouts from AppleScripts in other applications.
  2. Trigger saved window positions when connecting or removing a display.

Those are some nice additions to already great application. At this moment I think Moom is the best window management application available.


11
Sep 11

Keyboard Maestro Macro: Alphabetize a List

Here’s another quick macro that comes in handy. I often will create a list of items and later I will want the list to be in alphabetical or numerical order. I do it enough that I created a Keyboard Maestro macro for the function.

Given a list like this:

  • Item 3
  • Item 1
  • Something borrowed
  • Something blue
  • Something Blue
  • Alphabetical would be better

I can select the items, trigger the macro, and get back this list:

  • Alphabetical would be better
  • Item 1
  • Item 3
  • Something Blue
  • Something blue
  • Something borrowed

The real meat of the macro is an AppleScript that uses a single line of Shell Script to do the alphabetization. This also works great for ordered lists in Markdown as well.

Alphabetize Macro

 

tell application "Keyboard Maestro Engine"
    set the_list to process tokens ("%Variable%myList%")
    set old_delims to AppleScript's text item delimiters
    set AppleScript's text item delimiters to {ASCII character 10} -- always a linefeed
    set list_string to (the_list as string)
    set new_string to do shell script "echo " & quoted form of list_string & " | sort -f"
    set new_list to (paragraphs of new_string)
    set new_list to new_list as text
    set AppleScript's text item delimiters to old_delims
end tell
return new_list


11
Sep 11

Markdown References with Keyboard Maestro

I have been recently shifting a large chunk of my TextExpander snippets to Keyboard Maestro. I still plan to use TextExpander for basic snippet expansion but I find the depth of Keyboard Maestro allows me to build custom tailored tools that fit their intended uses much better.

For example, here a juiced up version of a snippet for inserting Markdown references from Safari. First, here’s what my TextExpander snippet did:

1. Copy URL from Safari

2. Switch to NVAlt

3. Bracket the link phrase

4. Type “mdr” to trigger the snippet

5. TextExpander inserts a double bracket then simulates the CMD-Down Arrow (bottom of document) and a return key. TextExpander then inserts “[%I]: %clipboard”

That’s pretty nice. It’s much better than manually creating link references. There’s still some tedium though. I have to copy the link in Safari. I have to add the link reference text and I don’t have a title for the link. Basically, there’s still some repetitive typing that doesn’t need to exist. I know I could fix a lot of this in TextExpander now that it supports AppleScript and Shell Scripts, but there are still some rough edges. Trust me, I’ve tried.

The Keyboard Maestro Version

The Keyboard Maestro version simplifies the entire process. I browse in Safari to the page I want to reference. I jump back to whatever application I am working in (usually NVAlt). After I bracket the link phrase, I simply type “mdr” and Keyboard Maestro presents a pop-up window asking for the link tag.

Keyboard Maestro Dialog

The link tag is inserted with brackets and a reference is immediately added at the bottom of the document for whatever page is currently at front in Safari. It even grabs the page title for the link reference.

The result of the macro

Believe it or not, this is a pretty simple macro. There’s a bit of AppleScript to get the URL and title (both scripts could be combined but I reuse these a lot in other macros) but overall, it’s basic Keyboard Maestro functionality. I have built a small arsenal of these little macros. While I would be completely lost working on someone else’s Mac, I take comfort in the ease at which I can work now.

Keyboard Maestro Macro

Click Here for Larger Version

You can download the macro file here.

 

I will be posting more of my macros as I clean up TextExpander and get my Keyboard Maestro macros in order.