For a service script, I am trying to fetch some “origin” information from any frontmost application.
For instance, for Browsers, I want to fetch the current URL, from apps with document windows I try to get the doc or window name.
Now it happens sometimes, e.g. when I run it on Safari while it’s entered a search string that has not been turned into a URL yet, that the script aborts with the error: The variable res is not defined. But hte variable is defined, I clearly always use “set res …” before I access it, right?
Can someone tell me what I’m doing wrong?
Also, maybe “null” is not the best way to indicate that there’s no value returned. What’s better? Would it work better if I replaced all “null” occurances with “missing value”?
Bonus question: The script refers to “Google Chrome”. Now, if a user does not have Chrome installed, the script won’t run, right? Is there a way to make the script compilable regardless?
on infoForAppWithID(appID)
if appID is "com.apple.Finder" then
-- No need to get either file or URL from the Finder as we already should have them in the clipping.
return null
end if
set res to getURLFromAppWithID(appID)
if res is not null then
return res
end if
set res to itemForCurrentSelectionInAppWithID(appID)
return res
end infoForAppWithID
on getURLFromAppWithID(appID)
if appID = "com.apple.Safari" then
try
tell front window of application "Safari"
return URL of current tab
end tell
end try
else if appID = "com.google.Chrome" then
try
tell front window of application "Google Chrome"
return URL of active tab
end tell
end try
end if
return null
end getURLFromAppWithID
on itemForCurrentSelectionInAppWithID(appIdentifier)
try
tell application id appIdentifier
try
set d to first document
on error
try
set d to first document of first window
end try
end try
set x to path of d
return x as POSIX file
end tell
end try
return null
end itemForCurrentSelectionInAppWithID
If I understand well, your code calls the handler infoForAppWithID(appID)
then it calls the handler getURLFromAppWithID(appID).
Assuming that I am right, you define a variable named res in the handler infoForAppWithID(appID)
but there is no reason for the calling code to see this variable.
I do not access “res” anywhere outside of infoForAppWithID(), so your explanation does not fit, I think.
The issue has to do with the fact that Safari does not give an URL. It rather gives an error, which is caught by the try clause, and then the function should exit with “return null”. That should then lead to itemForCurrentSelectionInAppWithID being call, which should also fail and return null, It’d expect.
The calling code looks like this:
set appInfo to infoForAppWithID(appID)
if appInfo is not null then
tell current clipping
if class of appInfo is «class furl» then
-- It's a file -> Set the clip's file reference
set file reference of first clip item to appInfo
else if name is "" then
-- Set the name of the clipping
set name to appInfo as rich text
else
-- Set the "info" property. That'll appear in the preview window.
set info to (appInfo as rich text) & return & info
end if
end tell
end if
I added several log instructionsto trace the script
set appID to "com.apple.Safari"
set appInfo to infoForAppWithID(appID)
(*
# Disabled because current clipping doesn't compile here !
if appInfo is not null then
tell current clipping
if class of appInfo is «class furl» then
-- It's a file -> Set the clip's file reference
set file reference of first clip item to appInfo
else if name is "" then
-- Set the name of the clipping
set name to appInfo as rich text
else
-- Set the "info" property. That'll appear in the preview window.
set info to (appInfo as rich text) & return & info
end if
end tell
end if
*)
on infoForAppWithID(appID)
log "infoForAppWithID(appID)"
log appID
if appID is "com.apple.Finder" then
-- No need to get either file or URL from the Finder as we already should have them in the clipping.
return null
end if
log "here I am"
set res to getURLFromAppWithID(appID)
log res
if res is not null then
return res
end if
log res
set res to itemForCurrentSelectionInAppWithID(appID)
return res
end infoForAppWithID
on getURLFromAppWithID(appID)
log "getURLFromAppWithID(appID)"
log appID
if appID = "com.apple.Safari" then
try
tell front window of application "Safari"
set theURL to URL of current tab
log theURL
return theURL
end tell
end try
else if appID = "com.google.Chrome" then
try
using terms from application "Google Chrome"
tell front window of application id appID
-- return URL of active tab
return «class URL » of «class acTa» # the reserved words are replaced by their raw code (the chevrons one)
end tell
end using terms from
end try
end if
return null
end getURLFromAppWithID
on itemForCurrentSelectionInAppWithID(appIdentifier)
log " itemForCurrentSelectionInAppWithID(appIdentifier)"
log appidetifier
try
tell application id appIdentifier
try
set d to first document
on error
try
set d to first document of first window
end try
end try
set x to path of d
return x as POSIX file
end tell
end try
return null
end itemForCurrentSelectionInAppWithID
Solely based on your statement I quoted: It seems that one of the commands sets an undefined variable. This should be considered a bug and should be reported to the developers. Some commands always returns an undefined variables but properties should always contain a value and commands either always return an undefined value or never.
The most easiest way to check if an variable is undefined is using an exception:
set res to beep 0
try
res
on error msg
-- oops something went wrong
display alert "Undefined variable" message msg
return
end try
Ah, so you mean that it’s not the Applescript engine but the app that I asked to get a value from. That would make more sense.
So, I just learned that there is another state that I’ve not seen before, it seems: <> (or what AS called “undefined”).
So far I only knew of “missing value”. But if I do this for a Safari window with no open URL:
tell application id "com.apple.Safari" -- Safari.app
URL of tab 1 of window 1
end tell
Then the result is non-existing. Script Debugger shows <> for it. I guess that’s what is then triggering the error, as it seems that Applescript does not let me compare an empty value to something else.
Using try seems to be the only way to even test that state. Not even the “exists” command works.
Anyway - thanks, you answer helped me fix my code, and now it runs without a hitch.