Opening a Finder's window from Impromptu (alas how to use the applescript bridge..)

Imagine you've got a bunch of audio samples you want to load up while livecoding with Impromptu but you can't remember exactly their names - it'd be handy to be able to open up the corresponding Finder window directly from scheme, without too much clicking around. Do-able or not?

I spent some time trying to figure this out, and the answer is yes! Quite a nice learning experience... although it came with a surprise at the end.

Originally I thought, let's do it via impromptu's ObjC bridge. I don't know much about ObjC but after a bit of googling it seemed evident that the quickest way to accomplish this is by writing ObjC code that, in turns, runs a simple applescript command that opens a window:

[NSString]( \*s \= \[[NSString]( stringWithFormat:  
     @"tell application "Terminal" to do script "cd %@"", folderPath];  

[NSAppleScript]( \*as \= \[\[[NSAppleScript]( alloc\] initWithSource: s\];  
[as executeAndReturnError:nil];

So I translated the bottom part of the code above into impromptu/scheme:

(define run_applescript  
   (lambda (script)  
      (objc:call (objc:call (objc:call "NSAppleScript" "alloc")  
                 "executeAndReturnError:" )))

That is a generic script-running function, that is, you can pass any script and it'll run it, eg:

(define script0 "  
   tell application "Finder" to open folder "Macintosh HD:Users"  
   tell application "Finder" to activate")  

(define script1 "  
   tell application "Terminal" to do script "cd ~; open ."")  

(define script2 "  
                tell application "System Events"n  
                tell dock preferencesn  
                set properties to {autohide:false}n  
                end telln  
                end tell")  

;; finally, let's choose randomly one of the scripts above and run it  
(run_applescript (random '(script0 script1 script2)))

Now, back to the original problem: in order to open a Finder's window at a specified location we need to pass the location variable to our function run_applescript; also, we want to be able to pass unix path expressions (eg '/Users/mike/music/'), so we've got to transform that path syntax into the semicolon-delimited macintosh syntax ("Macintosh HD:Users:mike:music") needed by the applescript function we're using. That's easily done with string-replace, so here we go:

(define open_finder_at  
   (lambda (location)  
      (let* ((llocation (string-replace location "/" ":"))  
              (script (string-append "tell application "Finder" to activate open folder "Macintosh HD" llocation """)))  
         (objc:call (objc:call (objc:call "NSAppleScript" "alloc")  
                    "executeAndReturnError:" ))))  

(open_finder_at "/Users/me/")

That's pretty much it really... now we can easily open OsX Finder's windows from within Impromptu.

But as I said above, there's a surprise: after getting this far I thought I'd search impromptu's mailing list for more examples of obj:call .... and guess what, there's already a system function that runs applescripts, it's called sys:run-applescript !

Too bad, it's been a rewarding learning experience anyways...

Cite this blog post:

Michele Pasin. Opening a Finder's window from Impromptu (alas how to use the applescript bridge..). Blog post on Published on Jan. 29, 2011.

Comments via Github:

See also:


paper  Fitting Personal Interpretation with the Semantic Web: lessons learned from Pliny

Digital Humanities Quarterly, Jan 2017. Volume 11 Number 1


paper  How do philosophers think their own discipline? Reports from a knowledge elicitation experiment

European Philosophy and Computing conference, ECAP10, Munich, Germany, Oct 2010.

paper  Data integration perspectives from the London Theatres Bibliography project

Annual Conference of the Canadian Society for Digital Humanities / Société pour l'étude des médias interactifs (SDH-SEMI 2010), Montreal, Canada, Jun 2010.