Appscript and Spotlight comments

In yesterday’s post, I rewrote an AppleScript in Python using the appscript library. It simplified the script by taking advantage of Python’s superior text and list handling facilities. I found an even greater simplification when rewriting an AppleScript that inserted Spotlight comments into photo files.

The idea behind that script was to take a plain text file in which each line has the format

filename.jpg|caption text

and use it to create Spotlight comments for the listed files. The text file with the captions is called “captions.txt,” and is placed in the same folder as the photos themselves.

The AppleScript looked like this:

 1:  tell application "Finder"
 2:    set photoFolder to target of front Finder window as alias
 3:    set cFiles to files of photoFolder whose name is "captions.txt"
 4:    if (count of cFiles) = 0 then
 5:      return -- stop if there's no captions file
 6:    end if
 7:    
 8:    display dialog "Do you want to append or replace existing comments?" buttons ["Append", "Replace"] default button 2
 9:    set dialogResult to result
10:    set cFile to item 1 of cFiles as alias
11:    set capLines to read cFile as text using delimiter "
12:  "
13:    set savedTextItemDelimiters to AppleScript's text item delimiters
14:    set AppleScript's text item delimiters to {"|"}
15:    repeat with theLine in capLines
16:      set fileName to text item 1 of theLine
17:      set fileComment to text item 2 of theLine
18:      if button returned of dialogResult is "Append" then
19:        set oldComment to comment of file fileName in folder photoFolder
20:        set comment of file fileName in folder photoFolder to (oldComment & return & fileComment)
21:      else
22:        set comment of file fileName in folder photoFolder to fileComment
23:      end if
24:    end repeat
25:    set AppleScript's text item delimiters to savedTextItemDelimiters
26:    
27:  end tell  

This is a mess, partly because AppleScript is always verbose, but mainly because it has a clumsy way of splitting text if you need to split it into anything other than words. Lines 11, 13, 14, and 25 are all devoted to working around AppleScript’s limitations in this area.

Here’s the rewritten Python version:

 1:  #!/usr/bin/env python
 2:  
 3:  from appscript import *
 4:  import os
 5:  import sys
 6:  
 7:  # Move to the directory of the top Finder window.
 8:  curDir = app('Finder').Finder_windows[1].target
 9:  os.chdir(curDir.get(resulttype=k.alias).path)
10:  
11:  # Quit if there's no captions file.
12:  if 'captions.txt' not in os.listdir('.'):
13:    sys.exit()
14:  
15:  # Go through the captions file, setting the comments.
16:  cap = open('captions.txt')
17:  for line in cap:
18:    (name, desc) = line.split('|')
19:    curDir.files[name].comment.set(desc)
20:  
21:  cap.close()

To be sure, some of the shortening is the result of my removal of an unnecessary “feature”. The original script let you choose whether the captions are going to append or replace any existing Spotlight comments. I decided that I’m very unlikely to ever use the “append” feature, so I removed it. This version runs without stopping to ask me a question that I will always answer the same way.

But even accounting for the missing logic, this is a much cleaner program. The lines are shorter and fewer, even with more whitespace and the introduction of comments. The trickiest parts were lines 8 and 9, which involve getting the top window in the Finder and its standard Unix pathname. I don’t see this as being more complicated than doing it in AppleScript: it’s never been clear to me when I need to use an alias and when I don’t. For both languages, I’m reduced to trial and error.

The best part is line 18 of the Python version. Instead of fiddling with AppleScript's text item delimiters and then writing

set fileName to text item 1 of theLine
set fileComment to text item 2 of theLine

it’s just

(name, desc) = line.split('|')

Beautiful.

Tags: