[Tutorial] Scripting Libraries

Having read this excellent description rather carefully, though I haven’t thoroughly tested it yet, I have decided to include it with our other tutorials in unScripted. Well done.

McUsrII’s comment that this tutorial must be tested in the Script Editor rather than in Script Debugger arises from the the differences in way SE handles dictionaries compared to SD. I have no doubt that a fix for SD will make this right eventually.

Hello.

I want to add that ScriptLibraries included by the new “use” keyword, that are without an sdef file, works flawlessly with my ScriptDebugger 4.5.7 that I bought originally for Snow Leopard. -Now, that is value for money! Thank you Late Night Software!

Hi,
I had watch the Developers video on script libraries and have written a library. Similar to this one actually. Seems everyone wants to replace text. :slight_smile:

In my search for an answer to one problem I have, I came across you well constructed Tutorial. But I do not think you cover what i am trying to solve.

The same as you I have some options. My options are ‘using any match’ or ‘using exact match’

But what I want is to be able to write the command with or with out the ‘using…’ options. Similar to where you can use: ‘replacing’ or not in the save command.

My sdef does contain the optional=yes in the parameter.


But this does not seem to make it optional and I still get the error.

I already employ error controls in the script libraries handler to catch invalid classes being used as arguments. But they are inside the handler. I cannot find a way to catch an error in the parameters though.

Do you or any one have any ideas

Many thanks

You can’t designate parameters as optional – AppleScript has never supported optional parameters in its handlers, and terminology is just repackaging handlers.

Ah I think I see,. Although not sure how would go about it.

A a test I added

to my sdef inside the command.

This allowed the replacing to be placed on the end or not.

But is the code working?

AppleScript has always allowed this sort of thing:

on addUp(x, y, z)
	return x + y + z
end addUp
addUp(5, 6, 7, 8)
--> 18

where it just ignores the extra argument, but it won’t handle this type of thing:

on addUp(x, y, z)
	return x + y + z
end addUp
addUp(5, 6)
--> {5, 6} doesn't match the parameters {x, y, z} for addUp.

When you add terminology, all you are doing is effectively wrapping a new interface around ordinary AppleScript handlers; you’re not changing the underlying rules.

That’s not to say it couldn’t be made to work, though, so feel free to log a request for it.

Hello.

I have been wondering if it is possible to write an sdef that would make handlers take parenthesis.
Is that possible, -to write and sdef file for a handler like addUp(x,y,z)?

Thanks. (A “no” will suffice.)

Which I think is what it is doing.
Thanks

No. (Or commas.)

While writing this tutorial I’ve tested the optional parameter and found out that you can add this attribute to the parameter element but it’s value is ignored. As for applications and scripting additions the binding process is completely different and therefore optional values can be used. The most important reason is script libraries, using it’s own terminology or not, is an instantiated script object and not an C library that’s dynamically loaded directly into the AppleScript Interpreter. That means, like Shane also said, it’s limited to the rules of AppleScript objects and handlers.

Because script libraries are instantiated AppleScript objects the optional parameters should be made in the AppleScript language. I like the idea of optional parameters but how would that work since AppleScript handlers supports both labeled parameters and positional parameters? If you have an handler for uppercasing you would have something like:

on makeUpper(theString, mode:1) --optional without own terminology
end makeUpper

on makeUpper theString case style:sentence case --option with terminology using enumeration
end makeUpper

@Mark Hunte:

While that’s true, there’s an important exception: if you are using the same term as Apple, you should use the same code. Mark’s example uses the code standard additions uses for the replacing parameter (in store script).

I thought so to until I watched video 416 of the wwdc (Introducing AppleScript Libraries). There it say “The use of codes, comprised of all lower case letter, is reserved by Apple.” and as “Sal Soghoian” says that you need to use at least 1 upper case character in your code, not saying anything about re-using codes by Apple. Am I missing something here, please tell me then I can change that in my tutorial above as well.

Thanks for the prompt reply Shane.

With regards to the codes reserved by Apple, the same exception as Shane stated above pertains to those. Just writing this for completion. There is a long list of the codes for the return types in: Cocoa Scripting Guide table 1-1.

I can’t hurt to also read: TN 2106 Scripting Interface Guidelines.

I found the second link now, while looking for the first one, but it looks like a good read up. :slight_smile:

Edit

There is “of course” also a new AppleScript Language Guide that ships with this fine Operating System!

Not as sexy, but it’s possible to have pseudo-optional parameters in AppleScript by passing them in a list or a record. You still have to pass something (ie. the list or the record), but it doesn’t have to be fully populated:

on addUp(aList)
	set |sum| to 0
	repeat with thisValue in aList
		set |sum| to |sum| + thisValue
	end repeat
	
	return |sum|
end addUp

addUp({5, 6, 7})
--> 18

addUp({})
--> 0
on addUp(aRecord)
	set defaults to {x:0, y:0, z:0}
	set aRecord to aRecord & defaults
	
	tell aRecord to return (its x) + (its y) + (its z)
end addUp

addUp({x:5, y:6})
--> 11

addUp({})
--> 0

Thanks.I Know about the code thing and my own codes comply. As Shane say I used apple code here. But only because I was doing a test. Not to be used in my real code.

@Nigel Garvey

Thanks for the idea.

I don’t know if you want to use this in the Tutorial. But I was looking to dynamically choose which CharacterSet to use from NSCharacterSet.

So for example if I ran my script to remove characters and set the CharacterSet with a string:

 set thisSet to "alphanumericCharacterSet"
set changedText to remove characters in "<%p>%s: object_: %@ name:- %@  899userInfo:.,) %@" not in thisSet adding characters " @-_.)" replacing with "-"

I would need to coerce the string into a class method name.

What I came up with was inside the Script Libraries handler I use the NSSelectorFromString function.
Then have NSMutableCharacterSet class perform the selector.

set s to current application's NSSelectorFromString(current application's NSString's stringWithString:thisSet)
	set characterSet to (current application's NSMutableCharacterSet's performSelector:s)
	set charString to current application's NSString's stringWithString:charText
characterSet's addCharactersInString:charString

This returns which ever NSCharacterSet I need. And saves me having to use a load of if statements of a repeat loop to work out what NSCharacterSet is needed.

Note: I am using a NSMutableCharacterSet instead of NSCharacterSet because I will be adding characters to the set later on.

I think Sal was trying to simplify what is actually a fairly tricky business. The commands themselves should be unique both in the term used and the code. But for parameters, and enumerations, the rules are different. For example, if you are going to have an enumeration with yes/no/ask enumerators, using an exact copy of the one used in standard additions is perfectly fine, and makes sense in terms of the pool of available codes – just don’t mess with it. Importantly, it pretty much guarantees that you will not conflict with another definition – and avoiding conflicts is what the guidelines are all about. The same goes for parameters, although it is not compulsory that they be the same.

Apple still have some defined suites, and although they haven’t been updated for a long time, the whole idea behind them was that developers would use consistent terms and codes.

From tech note TN2106:

The quote was aimed at app developers under the pre-use regime. With the use command, the terminology is being pooled, so you can’t just rely on your terms trumping scripting addition terms.

Three things:

The use command, and especially the ability to avoid scripting additions, gives us control over how conflicts are handled, so we possibly don’t have to be so rigid about it all. The fact that conflicts are called out at compile time is a good thing. But it doesn’t hurt to try to avoid them in the first place, to avoid the extra work of including extra tell or using terms from blocks.

The best way to limit conflict with the command part is to try to use multi-word terms. Scripting additions with very large dictionaries can be a serious cause of conflict. (If third-party scripting additions disappeared, this would all be a lot simpler.)

Finally, the all-lowercase rule of thumb is pretty rough. There are quite a few case where Apple has used other characters. (Most of the parameters to the say command, for instance, are all-uppercase.)

(And in case you are wondering: if you write your dictionary using ASObjC Explorer, the red colouring that comes up when you enter a code that conflicts is based on my building a list from trawling through Apple’s headers, so it should be reasonably accurate. But it just means you should not use it for a command, or unless you also use the same name.)

Save yourself some effort – just pass the string and let the bridge convert it for you:

set s to current application's NSSelectorFromString(thisSet)

Thanks Shane for the thorough answer.

I was expecting the use of parameters as you said and I had it written down in as you replied in my first edition of this tutorial. I was aware what the documentations says about code usage while making scripting additions and applications scriptable. But after watching the video I wasn’t sure, so I chose for a better-safe-than-sorry way. The sdef is extending the terminology like scripting additions but it’s still just an AppleScript object. And besides that I couldn’t really find anything that says explicitly that it needs to follow the guidelines for scriptability in applications or scripting additions.

Done,:rolleyes:

Ta.