helper functions across operating systems

I’m curious about the pros and cons of different ways of setting up helper functions so that users can write their scripts without thinking too much about making them run on both Windows and Mac. (I’m thinking of helper functions that take care of the if-then logic of things like Command vs Control key, etc.)

One way I thought of doing this is to have a helper suite that has a separate script for each such helper function. Inside each script, there would be if-then logic that is based on a global OS variable set at the beginning of the script run. In this way, the if-then logic is abstracted away from the user trying to write a test script.

Another way I noticed in the Finale2006 demo on the Redstone downloads site involved the OS determination script doing a “start using” command and then all the helper functions are duplicated in two different scripts “HandlersOSX” and “HandlersWin”. This avoids the if-then logic being in each function, but also keeps it away from the user writing a test script.

There are probably multiple other ways of accomplishing this task that I have not thought of. Is there a recommended way to do this? Am I missing something?

I use a script called set system handlers:
SetSystemHandlers.script


if imageFound(0, "platform/winxp") then
	set the script of the target to {{
            to copy
              TypeText controlKey, c
             end copy

            to cmd_l
              TypeText controlKey, l
            end cmd_l
         }}	
else if imageFound(0, "platform/osx") then
	set the script of the target to {{
            to copy
               TypeText commandKey, c
            end copy

             to cmd_l
               TypeText commandKey, l
            end cmd_l
          }}	
end if	

What this script does is ecapsulate copy tasks and other platform dependant tasks that rely on the command key vs the control key. These commands are mapped to a SenseTalk command - e.g “copy”. This script is then placed in a CommonUI helper suite so it can be reused by other scripts with the following call:


SetSystemHandlers

// rest of script here

// perform copy command from set hander
copy


As you can see, you can then call upon the copy command and provided that your platform was determined correctly within the invocation of the SetSystemHandlers you be rest assurred that the appropriate key combination will be used without the need for an if-else.

There certainly are multiple ways to approach this! :slight_smile:

Another “recommended way” is to use a suite inserted into either the InitialSuites or the FinalSuites to provide system-specific behavior. [Note: You may also see older examples that use the OpenSuite command, but the InitialSuites and FinalSuites are more flexible replacements]

To do this you would do something like:

if imageFound(0, "platform/winxp") then 
   insert "/path/to/WinXP.suite" into the InitialSuites
else if imageFound(0, "platform/osx") then 
   insert "/path/to/OSX.suite" into the InitialSuites
end if

The idea then is that you would provide alternate versions of certain scripts in each platform-specific suite, such as a copy script as suggested by EPJoK.

By inserting a suite into the InitialSuites, its scripts will be called before those in the current suite (suites in the FinalSuites come after the current suite). By inserting a platform-specific suite in one place or the other you can choose whether a platform-specific script will override a common script by the same name in the local suite, or the other way around.

One advantage to using suites for each platform rather than scripts that you “start using” is that suites can supply images as well as scripts.

Doug–

This is new territory for me. Care to elaborate on how IntitalSuites and FinalSuites differ/are better than using OpenSuite? I’m guessing we’d still have to issue start using commands to get at handlers, correct?

OpenSuite didn’t really allow enough fine grain control of if that suite was to be checked before or after the current suite. The new initialSuites and finalSuites properties allow you to clearly control the precedence.

Yes you still need start using to reference internal handlers from outside a script.

In addition to allowing some suites to come before the current suite and some to come after it, the InitialSuites and the FinalSuites also give you complete control over the order of the suites within the two lists. Since they are lists, you can use the insert command to insert a new suite at any point in the list (for example “insert newSuite before the initialSuites” to place it before all other suites).

Also, the OpenSuite command only applies for the duration of the script or handler that executes the command. Any suites opened by OpenSuite are automatically closed when the script/handler that called OpenSuite finishes. The command was designed that way to prevent it from having unintended impacts on higher level (outer) scripts. But it turned out to be a serious limitation since people would like to call a setup script to determine the operating system etc. and open various suites as appropriate – but OpenSuite won’t work for this since the suites will be closed when the setup script finishes! The InitialSuites and the FinalSuites are global in nature so they work well in that situation.

If you write each command or function as its own script (rather than as separate handlers within a script) then you don’t need to use start using. Of course, some people prefer to pack a number of utility handlers into a single script, so then start using (inserting a script into the BackScripts) will be needed in order to make all of those handlers directly accessible.