Monday, May 29, 2017

#26 2012-09-27 10:17:19 am

Adam Bell
Administrator
From: Nova Scotia, Canada
Registered: 2005-10-04
Posts: 4658

Re: Coerce GUI scripting information into string?

In the latest version of Lion (10.7.5) and Script Debugger 5.0.4 the line (which is fine in AppleScript Editor):

Applescript:


if (elementCount is 1) then set specifier to text 1 thru text item j of thisLine

fails because specifier is a key word in SD's dictionary. Changing specifier to _specifier everywhere solves that problem for SD users.

Further of course, users of this script must have a copy of Nigel's Insertion Sort script or the line loading it will fail. Here's my copy:

Applescript:

(* Insertion sort
Algorithm: unknown author.
AppleScript implementation: Arthur J. Knapp and Nigel Garvey, 2003.

Parameters: (list, range index 1, range index 2)
*)


on insertionSort(theList, l, r)
   script o
       property lst : theList
   end script
   
   -- Process the input parmeters.
   set listLen to (count theList)
   if (listLen > 1) then
       -- Negative and/or transposed range indices.
       if (l < 0) then set l to listLen + l + 1
       if (r < 0) then set r to listLen + r + 1
       if (l > r) then set {l, r} to {r, l}
       
       -- Do the sort.
       set u to item l of o's lst -- The highest value sorted so far!
       repeat with j from (l + 1) to r
           -- Get the next unsorted value.
           set v to item j of o's lst
           if (v < u) then
               -- If it's less than highest sorted value, initialise the insertion location to the beginning of the range. This will usually be changed below when a more suitable slot's found.
               set here to l
               -- Work back through the already sorted items, moving up those with greater values than this one, until a lesser or equal value or the beginning of the range is reached.
               set item j of o's lst to u
               repeat with i from (j - 2) to l by -1
                   tell item i of o's lst
                       if (it > v) then
                           -- Greater value. Move it up one position.
                           set item (i + 1) of o's lst to it
                       else
                           -- Lesser or equal value. Set the vacated slot after it as the insertion location.
                           set here to i + 1
                           exit repeat
                       end if
                   end tell
               end repeat
               -- Insert the value for insertion at the appropriate location.
               set item here of o's lst to v
           else
               -- The value's greater than or equal to the highest sorted so far. It's now the highest itself.
               set u to v
           end if
       end repeat
   end if
   
   return -- nothing.
end insertionSort

property sort : insertionSort

(* Demo:
set l to {}
repeat 1000 times
   set end of my l to (random number 1000)
end repeat

sort(l, 1, -1)
l
*)


iMac running OS X 10.11.6

Offline

 

#27 2012-09-27 11:08:55 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 4286

Re: Coerce GUI scripting information into string?

Thanks, Adam. I'd regard the 'specifier' thing as a fault in Script Debugger. Its own keywords shouldn't get in the way of the scripts it's running or editing. But I've changed 'specifier' to '_specifier' in the posted code.

The sort is just a cosmetic nicety from my own copy of the script and I've now cut it from the posted version.

Last edited by Nigel Garvey (2012-09-28 02:41:16 am)


NG

Offline

 

#28 2012-09-27 05:39:06 pm

Adam Bell
Administrator
From: Nova Scotia, Canada
Registered: 2005-10-04
Posts: 4658

Re: Coerce GUI scripting information into string?

What's interesting about "specifier" is that it works in OS X 10.8, but not in  10.7 or 10.6. What happens is that the word specifier is changed to the word reference by the compiler. For some reason the AppleScript Editor deals with that, but Script Debugger does not. The author of SD is looking into it.


iMac running OS X 10.11.6

Offline

 

#29 2012-09-27 08:17:41 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 5002

Re: Coerce GUI scripting information into string?

Nigel Garvey wrote:

Its own keywords should get in the way of the scripts it's running or editing

I assume you meant to include a "not" in there, but what you're asking for is probably impossible given the way AS works. Here's a counter example:

Applescript:

set language to 5

That compiles fine in Script Debugger 5, with language as a variable, but it won't compile in ASE because language is one of its keywords. I don't think there's anyway around that sort of thing, other than having a minimal dictionary and using multi-word terms as much as possible. (Earlier versions of Script Debugger used to offer the option of turning the dictionary off to avoid the problem, but I don't know that that is practical with Cocoa scripting.)

The problem with specifier stems in part from the decision at some stage to change the terminology used in AS dictionaries.  Where once, for example, the move command would specify a direct parameter of type reference, it now specifies type specifier. But the specifier type isn't actually defined anywhere, so it's a type that's a bit in no-man's land.

Script Debugger has actually defined the specifier type in its dictionary, and I suspect that's a sensible thing to do. Making it a synonym for reference was required to avoid the term reference compiling as specifier because they both point to the same thing (Cocoa's NSScriptObjectSpecifier).

Probably more than anyone wanted to know...


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#30 2012-09-28 02:47:51 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 4286

Re: Coerce GUI scripting information into string?

Shane Stanley wrote:

Nigel Garvey wrote:

Its own keywords should get in the way of the scripts it's running or editing

I assume you meant to include a "not" in there

Oops. Yes. I was concentrating so hard on trying to get "its" and "it's" right, I missed that. Now corrected.

Thanks for the background. I hadn't noticed the 'language' thing before.


NG

Offline

 

#31 2012-09-28 09:56:06 am

Adam Bell
Administrator
From: Nova Scotia, Canada
Registered: 2005-10-04
Posts: 4658

Re: Coerce GUI scripting information into string?

Shane Stanley wrote:

Nigel Garvey wrote:

Its own keywords should get in the way of the scripts it's running or editing

I assume you meant to include a "not" in there, but what you're asking for is probably impossible given the way AS works. Here's a counter example:

Applescript:

set language to 5

That compiles fine in Script Debugger 5, with language as a variable, but it won't compile in ASE because language is one of its keywords. I don't think there's anyway around that sort of thing, other than having a minimal dictionary and using multi-word terms as much as possible. (Earlier versions of Script Debugger used to offer the option of turning the dictionary off to avoid the problem, but I don't know that that is practical with Cocoa scripting.)

The problem with specifier stems in part from the decision at some stage to change the terminology used in AS dictionaries.  Where once, for example, the move command would specify a direct parameter of type reference, it now specifies type specifier. But the specifier type isn't actually defined anywhere, so it's a type that's a bit in no-man's land.

Script Debugger has actually defined the specifier type in its dictionary, and I suspect that's a sensible thing to do. Making it a synonym for reference was required to avoid the term reference compiling as specifier because they both point to the same thing (Cocoa's NSScriptObjectSpecifier).

Probably more than anyone wanted to know...

In sd-talk today, Matt Neuburg  points out that on p. 331 of his "AppleScript: The Definitive Guide" (which I have) in the chapter on Dictionaries and wildcards, he points out:

Reference
A less wild wildcard type (' Obj '), indicating that the value is some object belonging to the application. Might appear as "specifier". [Emphasis mine]


iMac running OS X 10.11.6

Offline

 

#32 2012-09-30 09:18:01 am

Nigel Garvey
Moderator
From: Warwickshire, England
Registered: 2002-11-19
Posts: 4286

Re: Coerce GUI scripting information into string?

Just for interest, I've had a go a "sed" alternative to the vanilla AppleScript formatting code in my script. It's not appreciably faster and is noted separately in Edit 4 at the bottom of post #17.


NG

Offline

 

#33 2013-11-21 01:19:36 pm

Krioni
Member
From: New York, NY
Registered: 2002-11-19
Posts: 244
Website

Re: Coerce GUI scripting information into string?

I added memory - when this script is saved and runs as an applet, it remembers and re-selects from the list (if that is still running) the app you previously chose.

Applescript:

property ScriptTitle : "UI Properties"

property appName : ""

-- By squaline (alias partron22?), emendelson, and Nigel Garvey.
-- http://macscripter.net/viewtopic.php?id=37674
on main()
   try
       tell application "System Events"
           set appNames to name of application processes whose visible is true
           set curApp to name of first application process whose frontmost is true
       end tell
       tell application curApp
           if length of appName is not 0 and appNames contains appName then
               set appChoice to (choose from list appNames with prompt "Which running application?" with title "Choose an application" default items {appName})
           else
               set appChoice to (choose from list appNames with prompt "Which running application?" with title "Choose an application")
           end if
           
           if (appChoice is false) then error number -128
           try
               set outputType to button returned of (display dialog "Choose output" with title ScriptTitle buttons {"Cancel", "Menu", "Window"} default button 2 cancel button 1 with icon 1)
           on error
               error number -128
           end try
           
       end tell
       set appName to item 1 of appChoice
       
       tell application "System Events"
           tell application process appName
               set frontmost to true
               set {windowExists, menuExists} to {front window exists, menu bar 1 exists}
               
               set {winstuff, menustuff} to {"(No window open)", "(No menu!)"}
               if outputType is "Window" then
                   if (windowExists) then
                       set winstuff to my listToText(entire contents of front window)
                   else
                       error number 3000
                   end if
               else
                   if (menuExists) then
                       set menustuff to my listToText(entire contents of menu bar 1)
                   else
                       error number 3001
                   end if
               end if
           end tell
       end tell
   on error e number n
       tell application "System Events" to set frontmost of application process curApp to true
       tell application curApp to activate
       if n = 3000 then
           tell application curApp to display alert "No windows to gather data from!"
           
       else if n = 3001 then
           tell application curApp to display alert "No menu to gather data from!"
       end if
       error number -128
   end try
   
   tell application "TextEdit"
       activate
       make new document at the front
       if outputType is "Window" then
           set the text of the front document to winstuff
       else
           set the text of the front document to menustuff
       end if
       set WrapToWindow to text 2 thru -1 of (localized string "&Wrap to Window")
   end tell
   
   tell application "System Events"
       tell application process "TextEdit"
           tell menu item WrapToWindow of menu 1 of menu bar item 5 of menu bar 1
               if ((it exists) and (it is enabled)) then perform action "AXPress"
           end tell
       end tell
   end tell
   tell application curApp to activate
   do shell script "open -b \"com.apple.textedit\""
   
end main

on listToText(entireContents) -- (Handler specialised for lists of System Events references.)
   try
       || of entireContents -- Deliberate error.
   on error stuff -- Get the error message
   end try
   
   -- Parse the message.
   set astid to AppleScript's text item delimiters
   set AppleScript's text item delimiters to {"{", "}"} -- Snow Leopard or later.
   set stuff to text from text item 2 to text item -2 of stuff
   
   -- If the list text isn't in decompiled form, create a script containing the list in its source code, store it in the Temporary Items folder, and run "osadecompile" on it.
   if (stuff does not contain "application process \"") then
       try
           set scpt to (run script "script
   tell app \"System Events\"
   {"
& stuff & "}
   end
   end"
)
       on error errMsg
           set AppleScript's text item delimiters to astid
           tell application (path to frontmost application as text) to display dialog errMsg buttons {"OK"} default button 1 with icon caution
           return errMsg
       end try
       set tmpPath to (path to temporary items as text) & "Entire contents.scpt"
       store script scpt in file tmpPath replacing yes
       set stuff to (do shell script "osadecompile " & quoted form of POSIX path of tmpPath)
       set stuff to text from text item 2 to text item -2 of stuff
   end if
   
   -- Break up the text, using "\"System Events\", " as a delimiter.
   set AppleScript's text item delimiters to "\"System Events\", "
   set stuff to stuff's text items
   -- Insert a textual "reference" to the root object at the beginning of the resulting list.
   set AppleScript's text item delimiters to " of "
   set beginning of stuff to (text from text item 2 to -1 of item 1 of stuff) & "\"System Events\""
   -- Reduce the remaining "reference" fragments to object specifiers, tabbed according to the number of elements in the references.
   set tabs to tab & tab & tab & tab & tab & tab & tab & tab
   set tabs to tabs & tabs
   set tabs to tabs & tabs -- 32 tabs should be enough!
   repeat with i from 2 to (count stuff)
       set thisLine to item i of stuff
       set lineBits to thisLine's text items
       -- Make sure any " of "s in element names aren't mistaken for those of the reference!
       set elementCount to 0
       set nameContinuation to false
       repeat with j from 1 to (count lineBits)
           set thisBit to item j of lineBits
           if ((not ((nameContinuation) or (thisBit contains "\""))) or ((thisBit ends with "\"") and (thisBit does not end with "\\\"")) or (thisBit ends with "\\\\\"")) then
               -- thisBit is either a complete nameless-element specifier or it ends the right way to be either a complete named one or the completion of a name.
               set nameContinuation to false
               set elementCount to elementCount + 1
               if (elementCount is 1) then set spec to text 1 thru text item j of thisLine
           else
               -- The next "bit" will be the continuation of a name containing " of ".
               set nameContinuation to true
           end if
       end repeat
       set item i of stuff to (text 1 thru (elementCount - 3) of tabs) & spec
   end repeat
   -- Coerce back to a single text, inserting line feeds between the items.
   set AppleScript's text item delimiters to linefeed
   set stuff to stuff as text
   set AppleScript's text item delimiters to astid
   
   return stuff
end listToText

main()

Offline

 

#34 2013-11-23 11:49:35 am

partron22
Member
Registered: 2011-03-18
Posts: 86

Re: Coerce GUI scripting information into string?

Nigel Garvey wrote:

I've made a few improvements to the script in post #17. Details at the bottom of the post.

Cool, I'm surprised at how robust this script has proven. Ten plus years, and only minor tweaking needed in a GUI script? That's practically heresy.

Small correction: I'm Squalene over at Mac OS X Hints, not 'Squaline'.

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.079 seconds, 10 queries executed ]

RSS (new topics) RSS (active topics)