Part of Nobumi Iyanaga's website. n-iyanag@ppp.bekkoame.ne.jp. 12/16/04.

logo picture

scriptApp_buildHelper

Background

AppleScript in OS X became a scripting language much less interesting (and less powerful) than it was in Classic OS days. This is mainly because of the lack of implementation of good AppleScript commands/classes in different applications. On the other hand, OS X has many very powerful scripting languages that come with Unix -- these are for example Perl, Python, Ruby, etc., and shell script. But they generally lack any GUI capability, so that it is not very handy to use them. There are some good tools that add GUI elements to these languages, for example Platypus 2.5 (which can be used with CocoaDialog), Pashua, or DropScript. But in this regard, AppleScript can provide a good complementary tool: the user can easily make double-clickable applications or droplet applications. It has some basic GUI elements, and with the help of some utilities like 24U Appearance OSAX, it is possible to add more GUI elements. And most importantly, AppleScript is bundled with the system, so that everybody has it. On the other hand, we can generate application bundles with AppleScript, and put inside them the script(s) (Perl, Python, shell script(s), etc.) which can be called from AppleScript; this way, it is handy to distribute these "composite" scripts/applications.

Here, I tried to write a droplet script which can help building such application bundles: it is called "scriptApp_buildHelper". To use it, you need to know to write working scripts for any of Unix scripting languages of your preference, and also some basic things about AppleScript.

How to use it

You would first write your "external script" (Perl script, Python script, shell script, etc.); if it is for a droplet, it would accept (at least) one argument, which is an input file (or folder); you can make it so that it would return ("print") some string, or write a file, or anything you want. And it must begin with "#!...".

Then you would write an AppleScript script. If it is for a script application, the script can be anything, provided that it can be compiled as AppleScript script. For example, something like:


set a to "z"
can be good.

If it is for a droplet application, it can be anything, provided that it begins with "on open (droppedItems)" and ends with "end open". For example, it can be something like this:


on open (droppedItems)
    repeat with theFile in droppedItems
	    set a to "z"
    end repeat
end open

You would save this droplet script as an application bundle. Then you would drop your "external script" on the droplet "scriptApp_buildHelper". It will ask you if you want to make a droplet or a script application. You will choose one of them.

Then it will bring up a file selecting dialog, prompting you to select your droplet/script application. When you have selected the application that you have made, it will:
1. copy your "external" script in the application bundle's /Contents/Resources/ folder, and make it executable;
2. it will open a "script_template" window in Script Editor, which will contain either the "script_template" for a droplet or "script_template" for a script application.
The "script_template" for a droplet is:


property script_fname : "foo.bar" -- your "external script" name

on open (droppeditemList) set my_path to POSIX path of (path to me) set shell_scpt to quoted form of (my_path & "Contents/Resources/" & script_fname) repeat with theFile in droppeditemList --if (theFile as string) ends with ":" then --display dialog "The droplet can accept only a file or a bunch of files..." --return --end if set shell_scpt to shell_scpt & space & quoted form of POSIX path of theFile end repeat --display dialog "Enter your option" default answer "" --set theOption to " -" & text returned of the result --set shell_scpt to shell_scpt & space & quoted form of theOption --return shell_scpt -- for debugging try do shell script shell_scpt --set res to the result on error errMsg display dialog "An error occurred: " & errMsg end try --display dialog res end open

--open {"Macintosh HD:Users:me:Documents:my_test_file"} -- for debugging

The "script_template" for a script application is:


property script_fname : "foo.bar" -- your "external script" name

on run set my_path to POSIX path of (path to me) set shell_scpt to quoted form of (my_path & "Contents/Resources/" & script_fname)

--display dialog "Enter your option" default answer "" --set theOption to " -" & text returned of the result --set shell_scpt to shell_scpt & space & quoted form of theOption --return shell_scpt -- for debugging try do shell script shell_scpt --set res to the result on error errMsg display dialog "An error occurred: " & errMsg end try --display dialog res end open

--run -- for debugging

3. finally, it will open in Script Editor the script of the droplet that you have written, to let you edit it, and displays a prompt saying "Now, edit your droplet script...!".

Explanation on the "script_template"

The "script_template" shows a "model" of the AppleScript script that will be used for your droplet/script application.

Here, I will explain the "script_template" for the droplet, because it is more complicated than the one for the script application. You will understand the script for the script application if you understand the one for the droplet.

The first line "property script_fname : "foo.bar" -- your "external script" name" defines your "external script" file name.

The handler "on open... end open" is the handler used for droplets. The basic form of a droplet script is:


on open (droppeditemList)
    repeat with theFile in droppeditemList
	    ...
    end repeat
end open
When you drag-&-drop one or several items on the droplet, the "dropped items" will be set as a list in the parameter of "on open" handler; with "repeat with theFile in droppeditemList... end repeat", each item is set as an alias in the variable "theFile".

The two lines:


	set my_path to POSIX path of (path to me)
	set shell_scpt to quoted form of (my_path & "Contents/Resources/" & script_fname)
will set in the variable "shell_scpt" the POSIX path (Unix style path) of the "external script", which is placed in the droplet's bundle's "/Contents/Resources/" folder.

The "repeat with theFile in droppeditemList... end repeat" loop:


	repeat with theFile in droppeditemList
		set shell_scpt to shell_scpt & space & quoted form of POSIX path of theFile
	end repeat
will add to the variable "shell_scpt" the POSIX path of each file, separated by a space.

When all the shell script that calls the "external script" and passing to it a list of dropped files' paths is ready, in the lines:


	try
		do shell script shell_scpt
	on error errMsg
		display dialog "An error occurred: " & errMsg
	end try
we try to execute the "external script" with its argument. If there is any error, it will be trapped, and after having displayed the error message, the droplet will exit.

I added some commented out lines:
1.


		--if (theFile as string) ends with ":" then
			--display dialog "The droplet can accept only a file or a bunch of files..."
			--return
		--end if
You will un-comment these lines if your "external script" doesn't accept folders as argument.

2.


	--display dialog "Enter your option" default answer ""
	--set theOption to " -" & text returned of the result
	--set shell_scpt to shell_scpt & space & quoted form of theOption
If you un-comment these lines, you will be able to let the user enter an option (preceded by a "-") that will be added as the last argument in the arguments list to be passed to the "external script".

3. The lines:


	--return shell_scpt -- for debugging
and:

--open {"Macintosh HD:Users:me:Documents:my_test_file"} -- for debugging
are for debugging the droplet. You will have to change the pah "Macintosh HD:Users:me:Documents:my_test_file" to the path of a real file (change "me" and "my_test_file" to something existing). Now, if you un-comment these lines, and run the script in Script Editor (Command + r), the droplet will return the shell script which is to be executed, and will quit. You will find in the "Result" window the shell script that is to be executed. To test if it will work as expected, you will copy that result script, paste it in Terminal window, and press "Return"...

4. The commented out lines:


		--set res to the result
and

	--display dialog res
are for the case in which the "external script" will return some string (with the command "print" or similar command), and you want to display that returned string. Of course, if the returned string is very long, "display dialog" command is not good; you will use some other command...

Aknowledgement
I have been helped by has and Emmanuel to write the code of this droplet, as well as the "script_template". Thank you to both of them!

Another way to do...
John Delacour has posted a message to the MacScripting mailing list, proposing another method to achieve a similar goal. Using John's method, it is possible to create a generic AppleScript droplet which will store the path of an "external script" (a Perl script in this case), and execute it when other files will be dropped on it, passing to the "external script" the paths of these files. Please have a look at:
<http://listserv.dartmouth.edu/scripts/wa.exe?A2=ind0412&L=macscrpt&T=0&F=&S=&P=3918>
where you will find the code for this droplet. (added on 04.12.16)

About the "external script"

The "external script" for a droplet will receive an argument list containing the paths of all the dropped items (you may add one or more options as well...).

In Perl (the only scripting language that I know...), that would be equivalent of something like:


@ARGV = ('file1', 'file2', 'file3',...);

Normally, your code should use the construct:


for $file (@ARGV) {
	....
}
or something alike.

Notes on Pashua and Unicode input

You can make a droplet or a script application which uses Pashua GUI elements if you want. To do that, you will have to put Pashua application in your /Applications or ~/Applications folder (it must be at the top level of one of these folders). You will write an "external script" for Pashua; you can place associated module (Pashua.pm for Perl, Pashua.py for Python, etc.) either in the respective library folder, or in your droplet/script application bundle's /Contents/Resources/ folder, along with your own script.

Pashua, from its version 0.9.1 onward, is good especially because it allows the use of Unicode (UTF-8) for it's GUI elements. In this regard, it is much better than AppleScript itself, which is unable to handle Unicode text in input in dialogs.

Examples

1. A droplet application "concatenate_rtf ". This uses the same script as my "concatenate_rtf_for_v1.pl" that you will find in my page Concatenate_rtf for Nisus Writer Express v. 1.x, v. 2.0.x and TextEdit. You can use this droplet to concatenate rtf files created by Nisus Writer Express v. 1.x (do NOT use it for files created by Nisus Writer Express v. 2.x!), or by TextEdit.

2. A script application "unihanData_lookup". This script will work for a Chinese character that is in the clipboard. To use it, make sure that you have a Cocoa application handling Unicode (TextEdit, Mail, Nisus Writer Express, Jedit X, etc.): select a Chinese character in a window of that application, copy it, then launch this script application. Your web browser will open the page of Unihan database for that character.

3. A script application "Unix_grep_pashua". To use this script application, you must have Pashua in your /Applications or ~/Applications folder. When you launch this script application, a dialog will ask you to enter the grep options (we use Unix egrep; the default value is: "Hbn"); then a Pashua window, having three objects, will ask you:
a. Enter the keyword to be searched;
b. Choose a folder in which the search will be done: option 1
or
c. Choose a text file in which the search will be done: option 2
You will enter the keyword, and choose either the folder, or the file.
The search will be done, and the result will be written in a file named "grep_res.txt", "grep_res1.txt", etc. on your Desktop, and will be opened in TextEdit.


Download

Please download "dropletScript_buildHelper.dmg" from [Macro error: Can't evaluate the expression because the name "f" hasn't been defined.].


I would appreciate any feedback, bug report or suggestions.
Thank you in advance.

Have fun!


Go to Research tools Home Page
Go to NI Home Page


Mail to Nobumi Iyanaga


frontierlogo picture

This page was last built with Frontier on a Macintosh on Thu, Dec 16, 2004 at 9:33:23 AM. Thanks for checking it out! Nobumi Iyanaga