Issues with using script libraries

Hi all,

I am ready to start creating collections of handlers that I can reuse. As such, I am interested in the concept of script libraries.

So, I put all of my generic string handlers in a compiled script file called “String Handlers.scpt”.

In a new main script (“test.scpt” saved as a compiled script), I included:

set stringHandlers to (load script file "String Handlers.scpt")
tell stringHandlers
   ...
   set newS to convertCase(s)
   ...
end tell

This works perfectly when executed within Script Editor. All of my calls to “String Handlers.scpt”'s handlers (e.g., “convertCase”) executed fine.

However, when the “test.scpt” script is called from the iTunes script menu (and thus executed within the iTunes application context), although the “load script” executes fine, the first call to a handler (e.g., “convertCase”) causes a fatal error (“Can’t continue with convertCase”).

Can anyone tell me a more generic way to have reusable code that will also work when called from within an application script menu (e.g., iTunes)?

Due to this and other quirks, I am assuming that applications like iTunes do not yet necessarily support all scripting logic properly.

Regards,

Steve

Mac OS X 10.5.5
AppleScript 2.0.1
iTunes 8.0.1

The problem is likely to be one of paths.

In the line:

set stringHandlers to (load script file "String Handlers.scpt")

there’s nothing to tell the app where to find the file. It may well be that Script Editor uses one model of finding the file (maybe in the same location as the script), while another application uses some other model (based on document path or application path, for example).

So my first suggestion is to be specific about where the library is located.

Depending on your installation you could make it an absolute path:

set stringHandlers to (load script file "HD:Users:username:Library:Scripts:String Handlers.scpt")

or make it relative to the user’s Library (makes it portable across users):

set stringHandlers to (load script file (path to library folder from user domain as text & "String Handlers.scpt"))

Or maybe in the system’s Library:

set stringHandlers to (load script file (path to library folder as text & "String Handlers.scpt"))

or any number of other ways of being more specific.

Hi Camelot,

Thanks for the response.

I apologize but I was trying to simplify things:

  1. My actual line read:
set stringHandlers to (load script ("/Users/username/Scripts/String Handlers.scpt" as POSIX file))
  1. My script library worked fine with this logic when executed under Script Editor

  2. Also, I had a similar theory to you, so I had tested if it was reading the script correctly under iTunes: I changed the path to be an incorrect path/filename. In this case, it errored under both environments on the “load script” statement with “file not found”. This told me that even under iTunes it was previously loading in the script, yet somehow it just had an issue with the handler reference(s) afterward.

So, any guidance on scripting library usage from application script menus?

Regards,

Steve

Hm,

I’ve tested the scripts below running directly from Script Debugger, Script Editor and from the iTunes script menu.
All cases work fine. Both scripts are saved as simple compiled scripts

set stringHandlers to load script file ((path to desktop as text) & "String Handlers.scpt")
tell stringHandlers
	set x to getHello()
	saySomething(x)
end tell

and String Handlers.scpt

on getHello()
	return "Hello"
end getHello

on saySomething(s)
	say s
end saySomething 

Hi Stefan,

You are 3 for 3 with either solving my problem or pointing me in the right direction! Thanks!

This was another case of your simple scripts starting with what works, then building on it to see what breaks it; instead of starting with the full implementation.

So, after your simple scripts worked for me also, I wondered what was different in my main scripts. It turns out that I was trying to use a global “tell” for both “String Handlers.scpt” and application “iTunes”:

tell stringHandlers
  tell application "iTunes"
    ...
    set newS to changeCase(s)
    ...
  end tell
end tell

What I did not understand about AppleScript “tell” blocks was that the lowest level block applicable defines the context. To use handlers outside of this context, one needs to use “my” (for the current script’s handlers), “it’s” (for the target script’s handlers if applicable), or “xxxxx’s” for a loaded script’s handlers.

I knew about the “my”, but I thought that when AppleScript realized that “changeCase()” was not applicable to “iTunes”, it would resort to the next higher level (like the JavaScript “with” statement, etc.). When in reality, it passed “changeCase()” to iTunes and just stopped there (“Can’t continue with changeCase”). Thus, it was not that it was not finding it under “stringHandlers”, rather it was not designed to even look there.

So, I first just added the “stringHandlers’s” prefix and it worked. Then, I realized that nested “tell” blocks only make sense when the inner block is only for a section inside the outer block, rather than covering all the same logic like the outer block. So, in my case, I left the application “iTunes” “tell” block, since it applied to the most code, and then I just used the “stringHandlers’s” prefix when needed instead of another big “tell” block.

Now I am set up for reusable code even when called from application script menus :slight_smile:

Thanks again,

Steve

I’d like to repeat that it’s strongly recommended to use tell blocks only for the specified lines.