Hello.
This is a script that will run wether the applications addressed is installed or not, if a property is not set, then it will surveil which apps among the supported that are installed. It will only attempt to call a “native” routine if the frontmost app are among the installed. Then it calls a dispatcher that calls that legitimate handler to provide “that” functionality. As long as the editing are correct I believe this to be the least cumbersome way to make scripts with support for several apps. The cornerstone of the whole is a construct I found in Matt Neubergs AppleScript The Definitive Guide it goes like this:
” page 295 Second Edition:
using terms from application "someapp"
set s to application "someapp"
tell application s
do yourStuff()
end tell
end using terms from
-- The Idea and implementation and any faults is totally mine. © McUsr 2010 and put in the Public Domain.
-- The usually guarrantees about nothing what so ever applies, use it at your own risk.
-- Read the documentation.
-- You are not allowed to post this code elsewhere, but may of course refer to the post at macscripter.net.
-- macscripter.net/viewtopic.php?pid=131424#p131424
(*
TERMS OF USE.
This applies only to posting code, as long as you don't post it, you are welcome to do
whatever you want to do with it without any further permission. Posting includes showing the code on some
web page of your own.
Except for the following: Selling the code as is, or removing copyright statmentents and the embedded link in the code (without the http:// part) from the code.
You must also state what you eventually have done with the original source. This obviously doesn't matter if you distribure AppleScript as read only. I do not require you to embed any properties helding copyright notice for the code.
Credit for having contributed to your product would in all cases be nice!
If you use this code as part of script of yours you are of course welcome to post that code with my code in it here at macscripter.net. If you then wish to post your code elsewhere after having uploaded it to MacScripter.net please email me and ask for permission.
The ideal situation is however that you then refer to your code by a link to MacScripter.net
The sole reason for this, is that it is so much better for all of us to have a centralized codebase which are updated, than having to roam the net to find any usable snippets. Which some of us probabaly originated in the first hand.
I'm picky about this. If I find you to have published parts of my code on any other site without previous permission, I'll do what I can to have the site remove the code, ban you, and sue you under the jurisdiction of AGDER LAGMANNSRETT of Norway. Those are the terms you silently agree too by using this code.
The above paragraphs are also valid if you violate any of my terms.
If you use this or have advantage of this code in a professional setting, where professional setting means that you use this code to earn money by keeping yourself more productive. Or if you as an employee share the resulting script with other coworkers, enhancing the productivity of your company, then a modest donation to MacScripter.net would be appreciated.
*)
-- This is the first test on how to centralize functionality for multiple apps into one
-- which can be altered during installation and reinstallation.
property inited : missing value
on run
if my inited is missing value then
Init()
set my inited to true
end if
set itIsOkToListChosenFile to false
set bidFrontApp to my bundleId's frontmostBundleId()
if my nativeSupport's frontmostAppAmongstInstalled(bidFrontApp) then
set itIsOkToListChosenFile to true
else if not nativeSupport's frontmostAppAmongstSupported(bidFrontApp) then
tell application "SystemUIServer"
activate
display dialog "The fronmost application is currently not supported.
Currently supported apps are Script Debugger, Applescript Editor and Smile." buttons {"Ok"} default button 1 with icon 2
end tell
end if
if itIsOkToListChosenFile is true then
set thisScript to my nativeSupport's dispatcher_0_(1, bidFrontApp)
if thisScript is not false then
tell application "LibraryLister"
launch
set myres to getPosForEntity(thisScript)
end tell
if myres is not false then
my nativeSupport's dispatcher_1_(2, bidFrontApp, myres)
end if
else
display dialog "unsaved script"
end if
end if
end run
on Init()
-- builds up our indices for the handlers first
set my nativeSupport's supportedAppBundleIds to {"com.satimage.Smile", "com.apple.ScriptEditor2", "com.latenightsw.ScriptDebugger"}
my nativeSupport's setInstalledAppsBundeleIds(my nativeSupport's findInstalledApps())
set my nativeSupport's handlerList to {"fileAliasForFrontDocument", "listCurrentFile"}
set my nativeSupport's nativeHandlers to {{my fileAliasForFrontDocument_com_satimage_Smile, my fileAliasForFrontDocument_com_apple_ScriptEditor2, my fileAliasForFrontDocument_com_latenightsw_ScriptDebugger}, {my listCurrentFile_com_satimage_Smile, my listCurrentFile_com_apple_ScriptEditor2, my listCurrentFile_com_latenightsw_ScriptDebugger}}
end Init
-- © McUsr and Put in public domain 2010. You may use it as you will but not post it elsewhere.
-- Find some other post of mine in code exchange and read what that implies.
script nativeSupport
property installedAppsBundleIds : {}
property supportedAppBundleIds : {}
property nativeHandlers : {}
property handlerList : {}
on setInstalledAppsBundeleIds(listOfUTId)
set my nativeSupport's installedAppsBundleIds to listOfUTId
end setInstalledAppsBundeleIds
on frontmostAppAmongstInstalled(thisBundleId)
-- returns true if frontmost app is among installed.
if thisBundleId is in my nativeSupport's installedAppsBundleIds then
return true
else
return false
end if
end frontmostAppAmongstInstalled
on frontmostAppAmongstSupported(thisBundleId)
-- returns true if frontmost app is among supported.
if my bundleId's frontmostBundleId() is in my nativeSupport's supportedAppBundleIds then
return true
else
return false
end if
end frontmostAppAmongstSupported
on dispatcher_0_(functIdx, uti)
-- 0 because it takes 1 parameter! every handler must return a result
global _McUsrs_nativeFuncToDispatch
local theRes, uti_index
set uti_index to my nativeSupport's IndexOfItem(uti, my nativeSupport's installedAppsBundleIds)
set _McUsrs_nativeFuncToDispatch to item uti_index of item functIdx of my nativeSupport's nativeHandlers
set theRes to _McUsrs_nativeFuncToDispatch()
return theRes
end dispatcher_0_
on dispatcher_1_(functIdx, uti, andAParameter)
-- 1 because it takes 1 parameter! every handler must return a result
global _McUsrs_nativeFuncToDispatch
local theRes, uti_index
set uti_index to my nativeSupport's IndexOfItem(uti, my nativeSupport's installedAppsBundleIds)
set _McUsrs_nativeFuncToDispatch to item uti_index of item functIdx of my nativeSupport's nativeHandlers
set theRes to _McUsrs_nativeFuncToDispatch(andAParameter)
return theRes
end dispatcher_1_
on IndexOfItem(theItem, theList) -- credit to Emmanuel Levy but I modified it with the considering case statements
considering case
set text item delimiters to return
set theList to return & theList & return
set text item delimiters to {""}
try
-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
on error
0
end try
end considering
end IndexOfItem
on findInstalledApps()
-- returns the installed apps on the users machine
script o
property l : {}
end script
repeat with aBundleId in my nativeSupport's supportedAppBundleIds
try
tell application "Finder"
set a to name of application file id aBundleId
set end of o's l to contents of aBundleId
end tell
end try
end repeat
return o's l
end findInstalledApps
end script
-- © McUsr and Put in public domain 2010. You may use it as you will but not post it elsewhere.
-- Find some other post of mine in code exchange and read what that implies.
script bundleId
on defaultAppBundleId(LSHandlerContentTypeOrTagClass) -- Made considerably shorter and faster by Nigel Garvey
-- Not LSHandlerContentTag check out defaults read com.apple.LaunchServices |more
-- Doesn't work awfully well with public.filename-extension!
try
set LSHandlerRoleAll to (do shell script "/usr/bin/defaults read com.apple.LaunchServices | /usr/bin/grep -A 2 " & LSHandlerContentTypeOrTagClass)
set {tids, text item delimiters} to {text item delimiters, "\""}
set LSHandlerRoleAll to text item -2 of LSHandlerRoleAll
set text item delimiters to tids
return LSHandlerRoleAll
on error
return "" -- The app is most probably the assumed one.
end try
end defaultAppBundleId
on frontmostBundleId()
-- returning bundleids that should be compatible down to Tiger, as the application properties
-- like id of application were made accessible with AS version 2.0 I use system profiler
-- since I currently didn't have any way to test what works under Tiger, but system profiler does!
set Major to ((system attribute "sysv") mod 4096 div 16)
if Major is 4 then -- TIGER
set ASVersion to (do shell script "/usr/sbin/system_profiler -detailLevel mini SPFrameworksDataType |/usr/bin/grep AppleScript: -A5 |/usr/bin/sed -n 's/Version:\\(.*\\)/\\1/p'")
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " "}
set ASVersion to every text item of ASVersion
set ASVersion to text item -1 of ASVersion as Unicode text
set AppleScript's text item delimiters to ""
set ASVersion to characters 1 thru 3 of ASVersion as Unicode text
set AppleScript's text item delimiters to tids
if ASVersion < "2.0" then
tell application "System Events"
set thisId to bundle identifier of every process whose frontmost is true
-- stolen from kiwilegal Thanks !
if (count thisId) is greater than 1 then
set thisId to item 1 of thisId
end if
end tell
return thisId as Unicode text
else
return id of application (path to frontmost application as Unicode text)
end if
tell application (path to frontmost application as string) to return (get name) -- from the post :
else if Major ≥ 5 then
-- this should work properly on both Leo and Snow 'pard
return id of application (path to frontmost application as Unicode text)
else
tell me
activate
display alert "getCurrentAppsBundleId: Versions of Mac Os X earlier than 10.4.0 is unsupported: your version is 10." & Major & "xx"
error number -128
end tell
end if
end frontmostBundleId
end script
on fileAliasForFrontDocument_com_satimage_Smile()
local thisScript, s
using terms from application "Smile"
set s to application id "com.satimage.Smile"
tell s
if (count its script windows) is greater than 0 then
try
set thisScript to path name of its front window as alias
return thisScript
on error
return false
end try
else
return false
end if
end tell
end using terms from
end fileAliasForFrontDocument_com_satimage_Smile
on fileAliasForFrontDocument_com_latenightsw_ScriptDebugger()
local thisScript, s
using terms from application "Script Debugger 4.5"
set s to application id "com.latenightsw.ScriptDebugger"
tell s
if (count its documents) is greater than 0 then
try
set thisScript to file spec of its document of its script window 1 as alias
return thisScript
on error
return false
end try
else
return false
end if
end tell
end using terms from
end fileAliasForFrontDocument_com_latenightsw_ScriptDebugger
on fileAliasForFrontDocument_com_apple_ScriptEditor2()
local thisScript
tell application id "com.apple.ScriptEditor2"
if (count its documents) is greater than 0 then
try
set thisScript to POSIX file (path of its front document) as alias -- as Unicode text
return thisScript
on error
return false
end try
else
return false
end if
end tell
end fileAliasForFrontDocument_com_apple_ScriptEditor2
on listCurrentFile_com_satimage_Smile(thePosition)
if thePosition is not false then
using terms from application "Smile"
set s to application id "com.satimage.Smile"
tell s
tell its window 1
activate
set its selection to {thePosition, 1}
tell application "System Events"
tell application process id "com.satimage.Smile"
tell its window 1
key code 124
key code 123
end tell
end tell
end tell
end tell
end tell
end using terms from
end if
return null
end listCurrentFile_com_satimage_Smile
on listCurrentFile_com_latenightsw_ScriptDebugger(thePosition)
local s
if thePosition is not false then
using terms from application "Script Debugger 4.5"
set s to application id "com.latenightsw.ScriptDebugger"
tell s
tell its window 1
activate
set character range of selection of (its document) to {thePosition, 1}
tell application "System Events"
tell application process id "com.latenightsw.ScriptDebugger"
tell its window 1
key code 124
end tell
end tell
end tell
end tell
end tell
end using terms from
end if
return null
end listCurrentFile_com_latenightsw_ScriptDebugger
on listCurrentFile_com_apple_ScriptEditor2(thePosition)
local s
if thePosition is not false then
tell application id "com.apple.ScriptEditor2"
tell its window 1 to activate
tell its document 1
try
set selection to insertion point thePosition
on error e number n
tell me
activate
display dialog e & " : " & n
end tell
end try
tell application "System Events"
tell window 1 of application process id "com.apple.ScriptEditor2"
tell its window 1
key code 124
end tell
end tell
end tell
end tell
end tell
end if
return null
end listCurrentFile_com_apple_ScriptEditor2