Script Debugger 5 is scriptable. Moreover, you can script Script Debugger from within Script Debugger itself, either from a script window or from a script in the Scripts menu. Such a script need not include a tell block targeting Script Debugger; Script Debugger will implicitly be the tell target.
However, for development and debugging purposes it is better to supply an explicit tell block (tell application "Script Debugger"
), because if you don’t, the returned values in the result could be less helpful.
Script Debugger will appear among the applications listed under File > Open Dictionary, in the dictionaries inspector, and in the dictionary window, so you can easily open its dictionary.
The dictionary is fairly self-explanatory, so a detailed discussion of scripting Script Debugger should be unnecessary. But here are a few points that deserve attention.
Some kinds of Script Debugger window can be opened. Here are some examples:
To create a new empty script window, say make new document
.
To open a script from disk, say open alias "vol:folder:file.scpt"
. The result is a reference to the document.
To open an application’s dictionary, open the application itself. The simplest approach is to take advantage of path to application
; so, for example, open (path to application "BBedit")
.
Alternatively, say make new dictionary window
. This creates an empty dictionary window, not displaying any application’s dictionary.
Once you have a dictionary window, you can change what application’s dictionary it displays by setting its file spec
property. For example, set file spec of dictionary window 1 to (path to application "BBEdit")
.
To open a script window’s event log window, tell the document to make new event log window
. The event log window and the document have pointers to one another.
To open a script window’s result explorer window, tell the document to open last result
.
All open windows are elements of the application object. You can get a complete list by asking for every window
, or you can get a list of windows in a particular category by asking for e.g. every dictionary window
or every script window
.
Every script window
is associated with exactly one document
(it has a document
property). The two classes are not interchangeable, but a script window and its document have the same id. This is fairly standard Cocoa Scripting stuff.
Documents are numbered front to back, so the numbering is volatile. In other words, document 1
is the document of whatever script window is frontmost at that moment.
To close a window, use the close
command.
However, when your script running within Script Debugger wants to close a script window (or document), you must provide the full form and you must not use the saving ask
option, or Script Debugger will throw an error. So, for example, you can say close document 2 without saving
, and you can say close document 2 saving yes
if the file has been previously saved, but you cannot say simply close document 2
, nor can you say close document 2 saving ask
.
By the same token, if document 2 has never been saved, you cannot say simply save document 2
. You must supply the full form, with an in
parameter specifying where to save.
The reason is that when Script Debugger is scripting itself, we cannot pause the script while the user interacts with the “Do you want to save changes?” dialog or the Save File dialog. So you must avert such interaction by stating explicitly what you want done with the document.
As you would expect, most interaction with objects occurs by way of their properties. Look, for example, at the properties of a document or a dictionary window or an event log window to see all the manipulations you can perform. For example, to switch a script to debug mode, set the document’s debugger enabled
to true
.
There are two ways to manipulate the contents of a script. First, you can get or set a script’s entire contents as text, through the document’s script source
property; you can also get and set a script’s entire contents as a script object, through the document’s script
property.
You can also manipulate a script’s selection. If you get selection
you are handed mere text, but if you ask for selection as point
or character range of selection
, what you get is a list of two integers, the character offset after the insertion point or the start of the selection (the first character offset is 1) and the count of characters in the selection. Similarly, you can set selection
to alter the selected text, but if what you set the selection to is a list of two integers, or if you set character range of selection
to such a list, you reposition the selection.
So, for example, here’s a crude but effective utility for selecting a given line of a given script:
on selectLine(num, docnum)
tell application "Script Debugger"
tell document docnum
set L to every paragraph of (get script source)
set offs to 1
repeat with i from 1 to (num - 1)
set aLine to item i of L
set offs to offs + (length of aLine) + 1
end repeat
set selection to {offs, length of item num of L}
end tell
end tell
end selectLine
selectLine(3, 2) -- or whatever
Script Debugger provides a repertory of specialized commands for making a script (a document
) do such things as compile
, execute
, step into
, and so on. Execution causes compilation, obviously. After calling any command that causes compilation, you can check whether compilation succeeded by examining the document’s compiled
property.
Some of these commands come with a caveat: execute
, pause
, step into
, step out
, and step over
all share the feature that they can return before the script has stopped or paused (and start recording
can return before the script has started recording). This is a consequence of Script Debugger’s multi-threaded architecture.
The correct approach, therefore, if you wish to proceed after the script has done what you asked it to do, is to poll the document’s execution state
property. So, for example, here’s a script that provides a utility for waiting until the document is paused or stopped, and shows how to use it in connection with execute
.
on waitUntilReady(d)
repeat while execution state of d is not in {stopped, paused}
delay 0.2
end repeat
end waitUntilReady
-- and here's how to use it
tell application "Script Debugger"
set d to document "convertFigures"
tell d
execute
my waitUntilReady(d)
if not compiled then return last error message -- compilation failed, get error
if last error message is not missing value then -- execution failed, get error
return last error message
end if
return last result -- execution succeeded, get result
end tell
end tell
We’d like to provide fuller scriptability, but this takes work, so we would prefer to go in directions that our users will actually use. If Script Debugger’s scriptability lacks a feature you need, do let us know.