prependEnvironment
handler:to prependEnvironment onto scriptString
"export SEE_LATEX_COMPILER='latexmk -pdf -quiet \"$FILE\"'; export SEE_LATEX_PRODUCT_TYPE=pdf; export SEE_LATEX_VIEWER='/Applications/Skim.app/Contents/SharedSupport/displayline \"$LINE\" \"$PRODUCT\" \"$FILE\"';" & scriptString
end prependEnvironment
"export SEE_LATEX_COMPILER='latexmk -pdf -quiet \"$FILE\"'; export SEE_LATEX_PRODUCT_TYPE=pdf; export SEE_LATEX_VIEWER='/Applications/Skim.app/Contents/SharedSupport/displayline \"$LINE\" \"$PRODUCT\" \"$FILE\"';" & scriptString
end prependEnvironment
The handler abstracts away the details of how the environment is constructed from the rest of the AppleScript. We can thus just focus on the internals of the handler, without worrying about how the rest of the AppleScript will be affected. Put another way, we'll replace the string defining the environment by a function call that returns the string.
The approach I'll take will be to store the environment settings in a property list file, read them into lists representing variables and values, and format the list contents appropriately. This is pretty easy, thanks to the property list suite in System Events. I'll encapsulate reading the environment into a handler of its own:
to readEnvironment out of plist
readListPair out of plist
environmentString from result
end readEnvironment
readListPair out of plist
environmentString from result
end readEnvironment
The
plist
parameter is the path to the property list file containing our environment. With
readEnvironment
, the prependEnvironment
handler is pretty straightforward. We just define the path to the environment file and let readEnvironment
do the work. All that remains is to decide where to store the environment settings. The Preferences folder seems like a natural choice, so let's use a file called de.codingmonkeys.SubEthaEdit.LaTeX_environment.plist
, which is similar to how the LaTeX mode settings are treated in TextMate. The handler becomes:to prependEnvironment onto scriptString
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit.LaTeX_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit.LaTeX_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
To be clear, it is not necessary to have the plist file present at all, since we defined our shell script to use default values when no environment variables are set. We'll handle the case of an absent environment file below.
We now need to provide
readListPair
and environmentString
handlers. The former draws on the property list suite of System Events, returning two lists of equal length. The first list contains the environment variable names, while the second contains the corresponding values. The handler is complicated a bit by checking whether the plist exists, but has a single get
at its core:to readListPair out of plist
tell application "System Events"
if exists file plist then
tell property list file plist
get {name, value} of every property list item
end tell
else
{{}, {}}
end if
end tell
end readPlist
tell application "System Events"
if exists file plist then
tell property list file plist
get {name, value} of every property list item
end tell
else
{{}, {}}
end if
end tell
end readPlist
To format the list contents into an appropriate string, we define the
environmentString
handler:on environmentString from keyValueListPair
set {plistKeys, plistValues} to keyValueListPair
set accumulator to {}
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to ""
repeat with i from 1 to number of items in plistKeys
set tokens to {"export ", item i of plistKeys, "=", item i of plistValues, ";"}
copy (tokens as string) to the end of the accumulator
end repeat
set AppleScript's text item delimiters to space
set envString to accumulator as string
set AppleScript's text item delimiters to oldTIDs
envString
end environmentString
set {plistKeys, plistValues} to keyValueListPair
set accumulator to {}
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to ""
repeat with i from 1 to number of items in plistKeys
set tokens to {"export ", item i of plistKeys, "=", item i of plistValues, ";"}
copy (tokens as string) to the end of the accumulator
end repeat
set AppleScript's text item delimiters to space
set envString to accumulator as string
set AppleScript's text item delimiters to oldTIDs
envString
end environmentString
This is a straightforward, ugly function that just iterates through the lists, formatting the contents. Each variable-value pair is turned into a shell-style export statement and accumulated in a list. The accumulated export statements are then joined together into one big string that defines the environment.
To test all of this out, it is easier to just call the base
prependEnvironment
handler, instead of working through a SEE mode. I used prependEnvironment onto "buildScript"
, and ran it with the environment plist both present and absent. It works as expected, so could be simply dropped into the LaTeX mode bundle. However, I prefer to make another, relatively minor change that requires an extra parameter for the prependEnvironment
handler. Specifically, I will pass in the active mode from SubEthaEdit:to prependEnvironment for seeMode onto scriptString
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit." & (name of seeMode) & "_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit." & (name of seeMode) & "_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
Later extensions could make use of more properties of the mode, so I passed in the entire mode, instead of just the name. The advantage of passing the mode as a parameter is that all of the stuff I've shown in this post can be used without change for other scripts and for other modes. It will only be necessary to change the line defining the string holding the shell script and to make appropriate redefinitions of the
seescriptsettings
handler.Next time, I'll take a look at how to easily access and make changes to the environment.
For completeness, here's the entire AppleScript:
tell application "SubEthaEdit"
if exists path of front document then
if modified of front document then
try
save front document
end try
end if
set filePath to path of front document
set lineNumber to startLineNumber of selection of front document
set activeMode to mode of front document
set modeResources to resource path of activeMode
else
error "You have to save the document first"
end if
end tell
set buildScript to prependEnvironment for activeMode onto (join of {quotedForm for (modeResources & "/Scripts/shell/buildlatex.sh"), quotedForm for filePath, lineNumber} by space)
do shell script buildScript
on seescriptsettings()
return {displayName:"Typeset and View PDF", shortDisplayName:"Typeset", keyboardShortcut:"@b", toolbarIcon:"ToolbarIconBuildAndRun", inDefaultToolbar:"yes", toolbarTooltip:"Typeset and view the current document", inContextMenu:"no"}
end seescriptsettings
on join of tokenList by delimiter
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to delimiter
set joinedString to tokenList as string
set text item delimiters of AppleScript to oldTIDs
return joinedString
end join
on quotedForm for baseString
quote & baseString & quote
end quotedForm
to prependEnvironment for seeMode onto scriptString
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit." & (name of seeMode) & "_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
to readEnvironment out of plist
readListPair out of plist
environmentString from result
end readEnvironment
to readListPair out of plist
tell application "System Events"
if exists file plist then
tell property list file plist
get {name, value} of every property list item
end tell
else
{{}, {}}
end if
end tell
end readPlist
on environmentString from keyValueListPair
set {plistKeys, plistValues} to keyValueListPair
set accumulator to {}
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to ""
repeat with i from 1 to number of items in plistKeys
set tokens to {"export ", item i of plistKeys, "=", item i of plistValues, ";"}
copy (tokens as string) to the end of the accumulator
end repeat
set AppleScript's text item delimiters to space
set envString to accumulator as string
set AppleScript's text item delimiters to oldTIDs
envString
end environmentString
if exists path of front document then
if modified of front document then
try
save front document
end try
end if
set filePath to path of front document
set lineNumber to startLineNumber of selection of front document
set activeMode to mode of front document
set modeResources to resource path of activeMode
else
error "You have to save the document first"
end if
end tell
set buildScript to prependEnvironment for activeMode onto (join of {quotedForm for (modeResources & "/Scripts/shell/buildlatex.sh"), quotedForm for filePath, lineNumber} by space)
do shell script buildScript
on seescriptsettings()
return {displayName:"Typeset and View PDF", shortDisplayName:"Typeset", keyboardShortcut:"@b", toolbarIcon:"ToolbarIconBuildAndRun", inDefaultToolbar:"yes", toolbarTooltip:"Typeset and view the current document", inContextMenu:"no"}
end seescriptsettings
on join of tokenList by delimiter
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to delimiter
set joinedString to tokenList as string
set text item delimiters of AppleScript to oldTIDs
return joinedString
end join
on quotedForm for baseString
quote & baseString & quote
end quotedForm
to prependEnvironment for seeMode onto scriptString
set envFilePath to (path to preferences from user domain as string) & "de.codingmonkeys.SubEthaEdit." & (name of seeMode) & "_environment.plist"
(readEnvironment out of envFilePath) & scriptString
end prependEnvironment
to readEnvironment out of plist
readListPair out of plist
environmentString from result
end readEnvironment
to readListPair out of plist
tell application "System Events"
if exists file plist then
tell property list file plist
get {name, value} of every property list item
end tell
else
{{}, {}}
end if
end tell
end readPlist
on environmentString from keyValueListPair
set {plistKeys, plistValues} to keyValueListPair
set accumulator to {}
set oldTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to ""
repeat with i from 1 to number of items in plistKeys
set tokens to {"export ", item i of plistKeys, "=", item i of plistValues, ";"}
copy (tokens as string) to the end of the accumulator
end repeat
set AppleScript's text item delimiters to space
set envString to accumulator as string
set AppleScript's text item delimiters to oldTIDs
envString
end environmentString
No comments:
Post a Comment