[Tutorial] Scripting Libraries

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.

Hi a quick question.

If I use use script “Applescript Utilities”

And in my Applescript outside or inside any tell blocks

 set posixFile to POSIX file "/Users/UserName/Library/SomeFooPath"

I get an error “Expected end of line, etc. but found class name.”

from the file part of the command.

I do not have any single word file verbs in my script libraries.
the closes is <command name=“existence of file path” code=“MOSXEOFP” description=“Check the existence of a file or folder path”

Does any one know why I am getting this.

if I use a Applescript Utilities tell block around all the other code where needed instead of the global use clause all is ok. But that defeats the point of having a global use clause.

*SLIGHT UPDATE;

Another example:

I can use:

use finder : application "Finder"
set thisPath to item 1 of (get selection of finder) as alias

with none of my custom script libraries loaded.

Works fine. But if I add the:

 set g to POSIX file "/Users/UserName/Library/SomeFooPath"

any where else in the script.
like so:

use finder : application "Finder"
set thisPath to item 1 of (get selection of finder) as alias
 set g to POSIX file "/Users/UserName/Library/SomeFooPath"

I still get the error.

POSIX File is part of the standard scripting addition. When you use the “use script” statement you should use the line “use scripting additions” as well if you want to make use of scripting additions. When you use the “use script” statement, scripting additions are by default not included into your script. It’s something that I should have mentioned in my tutorial I guess.

Thanks.

Annoyingly that was the first thing I tried. But clearly did not have enough coffee this morning because I now realise I must have used

use script “scripting additions” which obviously did nor work.
Doh…

Hello.

I am currently writing some sdef files, and I have a couple of questions:

I have some handlers that takes a list of lists of integers as a parameter (a matrix), how do I specify that?

Am I right in that it is better to not specify the return type, than do so for a command?

I also wonder how you specify an AppleScript Object as a parameter.

Thanks.

A list of any. That’s the best you can do.

If you know the type, by all means specify it.

Usually as any.

In script libraries, types are purely informative – they don’t actually do anything, unlike in apps and scripting additions. So just use common sense, and add explanations where you think they will help.

Hello.

Thanks a whole lot Shane. I was really wondering about this. My qualms with return types, is of course when the return types varies, which isn’t good practice, but which choose from list for instance uses anyway. :slight_smile:

Hello.

I am at a loss,wondering about how I make scripting terminology for a handler that takes no parameters, if that is possible.

It doesn’t just work by leaving out the direct parameter definition, and any other parameter description. I hope I have overlooked something.

Most simplest form of a command is like:

<command name="command name" code="suitcomm" />

where the implementation is like:

on command name
   return true
end command name

which should be used like

use script "name of library"

set x to command name 

p.s. Tested and worked in Mavericks

Hello.

I can’t compile anything like that, maybe I am doing something wrong, (I get the message: Expected «given», «into», «with», «without» or other parametername, but found end of line) I am on Mavericks too.

use AppleScript version "2.3"
use scripting additions
use framework "Foundation"
use framework "AppKit"

(* ========== debug suite ========== *)
on milli secs
 # from start
	tell current application to set this_time to (its NSDate's timeIntervalSinceReferenceDate()) * 1000
	return this_time
(*
	if start = 0 then
		return this_time
	else
		return (this_time - start)
	end if
*)
	# NSDate's alloc()'s init() to return ((its timeIntervalSince1970()) * 1000)
end milli secs

from the Cocoa Scripting documentation

Cocoa scripting will generate default keys for property and element attributes and for commands, if you do not specify them. For a property, it capitalizes each word of the property’s name except the first word, then removes any spaces. For an element, it specifies the plural of the element type. For a command, the default is NSScriptCommand

apart from that, the handler parentheses are missing

on milliSecs()

Hello Stefan.

Thanks for the input, I had a question earlier in this thread regarding parenthesis, and by the answer I got from Shane, I figured I couldn’t use parenthesis with a command that is supported with terminology.

Edit

I asked the question in post #9, and Shane answered it in post #11, (page 1 :smiley: ).

The motivation, is of course to have the terminology load with the use script clause, so I won’t have to use a script object in order to utilize the commands, but can use them like I can with a scripting additions command.

For the record, the script bundle is named corelibrary, the sdef file is named corelibrary.sdef, the name in the bundle tab is corelibrary, and the id is net.mcusr.corelibrary. ASOBJC is enabled, and the sdef document a valid sdef/xml utf-8 document.

your sdef should have an empty command tag if it is really empty, I guess it uses libxml to parse the file because in libxml there is a difference between and . So you sdef should look like:

Not when you use your own scripting definition, parentheses are not needed then.

sorry, I was wrong, forget the other post

Hello.

Thanks for answering DJ Bazzie Wazzie, I have tried that as well. :slight_smile:

At least it works on my machine only when you write an empty tag as otherwise it won’t work.

What I did was

  1. create new applescript in script editor
  2. save script as script bundle
  3. a bundle inspector (drawer) appears, open it
  4. create sdef file with plain text editor (sublime text)
  5. drag & drop the sdef file inside the bundle
  6. fill in the name (without extension) in the sdef field name in the drawer
  7. save the file again
  8. write the handler as below

on milli secs
return 0
end milli secs

  1. compile (the handler should compile properly)