Creating a User Script Choose the Edit User Scripts command from the script menu — that ’ s the menu that looks like a scroll.. FIGURE 23 - 10 The Edit User Scripts window is almost id
Trang 1JavaArchive
Legacy
Library
Native
Resources
ShellScript
Sources
Tool Refer to other templates, or fi rst create a target of the desired type and add your desired phases to
it, to ensure that the target can accept a particular build phase type You should not include a build
phase in a target type that does not normally accept that build phase type
Name your target template fi le and place it where you want it to reside inside the Target
Templates folder Relaunch Xcode to use the new template
USER SCRIPTS
User scripts are custom actions that appear in the Xcode menu Each script is an executable text
fi le that can optionally interact with the content of your active editor pane, essentially allowing you
to extend the editor with your own commands You can write your scripts using a shell language,
perl , python , ruby , awk , or any other interpreter you want
Although the script is in the form of an executable fi le, you cannot substitute a binary executable The fi le must be a text fi le encoded using UTF-8 However, there is nothing stopping a script from launching another binary executable
or script For example, a custom script could start an AppleScript using the
osascript tool.
Xcode preprocesses script fi les before they are executed Scripts contain additional properties and
commands that enable them to communicate with the Xcode application — in a fashion Because of
the subtle differences between regular executable scripts and custom Xcode scripts, the following
sections use the term “ custom script ” to indicate an executable script that employs special Xcode
syntax
The StartupScript
When Xcode starts, it looks for the custom script /Developer/Library/Xcode/StartupScript
and executes it This script is a custom script that can employ any of the special custom script
extensions explained later — at least those that make sense in the absence of an editor context You
can modify this script to automatically perform any action you want every time Xcode starts
➤
➤
➤
➤
➤
➤
➤
➤
Trang 2The StartupScript is worth mentioning, from an historical perspective, because this is where you used to install custom scripts in the Xcode menus That ability has been formalized, as you ’ ll see in the next section, so the StartupScript is no longer the appropriate place for customizing Xcode ’ s interface If your StartupScript creates menu items or keyboard shortcuts, now would be a good time to remove those and add them back using the Edit User Scripts interface
Creating a User Script
Choose the Edit User Scripts command from the script menu — that ’ s the menu that looks like a scroll This command opens the Edit User Scripts window, shown in Figure 23 - 10
FIGURE 23 - 10
The Edit User Scripts window is almost identical to the actions window used to defi ne custom organizer actions The only signifi cant differences are that the Add menu includes a New Submenu command and user scripts have different options than action scripts This is where you create, add, name, arrange, and assign keyboard shortcuts to user scripts See Chapter 22 if any of this seems unfamiliar The user scripts window maintains a hierarchy of submenus, which you can edit and reorganize
User Script Options
User scripts can be invoked while editing and are intended to augment the capabilities of the Xcode editors User scripts can do anything, but they typically process the fi le or text selection by digesting the text in the editor pane and replacing it with its output The user script ’ s options determine how the script interacts with the document Some of these options duplicate menu script variables, described later
Trang 3A user script has four options:
Input Directory Output Errors The Input option determines what information will be piped to the script on its stdin The choices
are None, Selection, and Entire File Unlike the organizer, Selection in this case means exactly what
it says: the span of text currently selected in the editor Use this when you want your script to fi lter
or process the current selection The Entire File choice pipes the entire contents of the current editor
pane to the script, and of the current editor pane, and None doesn ’ t supply anything at all
The Directory option sets the working directory to one of three locations: Selection, Home
Directory, or File System Root These choices will set the working directory to the one that contains
the fi le in the editor pane (.), your user ’ s home directory (~), or the fi le system ’ s root directory (/),
respectively This is usually only useful for scripts that need to process other fi les, and the setting
isn ’ t normally signifi cant
The Output and Errors settings determine what happens to any text output by the script The
following table lists the Output settings and what will happen with the text the script sends to
stdout :
Discard The output of the script is discarded This is the default
Replace Selection The output of the script replaces the current selection in the
editor pane
Replace Document Contents The output of the script replaces the contents of the entire
editor pane
Insert After Selection The output of the script is inserted into the active fi le
immediately following the current selection or insertion point
Insert After Document Contents Appends the output of the script to the end of the editor pane
Open in New Window Opens a new editor window and writes the output of the text
to it The original source fi le is not aff ected
Open as HTML Same as Open in New Window, but the output is interpreted
and displayed as a web page
Place on Clipboard Transfers the output of the script to the clipboard The original
source fi le is not aff ected
Display in Alert Displays the output of the script in an alert dialog
➤
➤
➤
➤
Trang 4Similarly, the Errors setting determines the disposition of text output to stderr The choices are Ignore Errors, Display in Alert, Place on Clipboard, and Merge with Script Output
Anatomy of a User Script
A custom script is, above all else, an executable script fi le The fi rst line of the fi le must be a
“ shebang ” line that informs the system of the application that will be used to interpret the script
The fi rst line of a bash script would be as follows:
#! /bin/bash
The fi le must be encoded using UTF - 8 or an encoding that is compatible with UTF - 8 UTF - 8
is a superset of the plain ASCII encoding, so any interpreter that requires ASCII source will be compatible
A custom menu script can contain special tokens that enable it to interact, in a fashion, with the Xcode application These consist of menu script defi nitions and custom script variables Custom script tokens are surrounded by the character sequences %%%{ and }%%% An example is the expression %%%{PBXFilePath]%%% This user script variable will be replaced with the path of the fi le being edited when the script is preprocessed You can think of user script variables as shell macros, except that they are substituted prior to the script ’ s execution From the script ’ s perspective, they appear as a literal value
Prior to the introduction of the Edit User Scripts interface, user scripts were added to the menu by the StartupScript using special user script declarations that defi ned the script’s name in the menu, its keyboard shortcut, its input and output options, and so on If you’re incorporating an older user script, remove declarations like PBXName=, PBXKeyEquivalent=, PBXInput=, and
when confi guring the script in the Edit User Scripts window.
Scripts can also call a number of utilities provided by the Xcode tools framework These are executable programs and scripts that can be called by your custom script See the “ Script Helpers ” section for the script utilities you can use
User Script Variables
User script variables are replaced by the value obtained from the currently active editor pane
Again, this substitution happens prior to the beginning of script execution, so treat these variables
as constants in your script Here ’ s an example that uses the PBXSelectionLength variable that contains the number of characters in the user ’ s current text selection when the script is executed:
if [ %%%{PBXSelectionLength}%%% == 0 ]; then echo "No Selection"; exit; fi
If the value of PBXSelectionLength is 8, the actual line of text in the script that is executed by the interpreter will be:
if [ 8 == 0 ]; then echo "No Selection"; exit; fi
Trang 5PBXFilePath
The PBXFilePath variables expand to the complete pathname of the fi le in the editor pane You
can use this instead of, or in addition to, piping the contents of the document to the script ’ s input
It ’ s also useful for writing scripts that perform some action on the fi le itself — like a source control
script — instead of the contents of the editor pane
This variable works reliably when used in an editor pane displaying an existing
fi le In other situations — like a text selection in the build transcript or a text
fi le window that’s never been saved — its behavior is erratic It may evaluate to nothing, a path that isn’t a fi le, or a path to a temporary fi le Code defensively when using this value.
PBXSelectedText and PBXAllText
The PBXSelectedText and PBXAllText variables expand to the contents of the current text
selection or the contents of the entire editor pane, respectively You can use these variables instead
of, or in addition to, the Input option of the script
These can be rather dangerous to use in a script They are replaced, verbatim, with the contents
of the selection or editor pane There is no protection from special characters that might be
inappropriate at that location in your script In other words, the substitution may result in portions
of the editor text being interpreted as part of the script For example, the following shell statement
appears harmless, but it will cause the script to fail with a syntax error if the currently selected text
contains a double quote character:
SELECTION="%%%{PBXSelectedText}%%%"
One way to avoid this kind of problem in the shell is to use a so - called “ here document, ”
like this:
cat < < END_OF_SELECTION
%%%{PBXSelectedText}%%%
END_OF_SELECTION
Most shells and interpreters like perl support some kind of “ here document ” syntax It ’ s more
robust than trying to quote the value, but still isn ’ t foolproof Consider an editor pane where the
text “ END_OF_SELECTION ” is the current selection
PBXTextLength, PBXSelectionStart, PBXSelectionEnd,
and PBXSelectionLength
These four variables, described in the following table, report the number of characters in the fi le
or current text selection and the index into the current document where the text selection begins
and ends
Trang 6VARIABLE DESCRIPTION
PBXTextLength The number of characters in the active editor pane
PBXSelectionLength The number of characters in the current text selection This will be
0 if the text selection is an insertion point
PBXSelectionStart The position within the editor pane where the current text selection
or insertion point begins
PBXSelectionEnd The position within the editor pane where the current text selection
ends
Using these variables, your user script can treat the contents of the editor pane as a whole
A common scenario is to set the script ’ s Input option to Entire Document and its Output option
to Replace Document Contents The script reads the entire document into a variable and then uses these four user script values to identify the selected text The script has the entire contents of the document, knows the location of the current selection, and can change anything within the document
These variables are typically more useful when used with interpreters, like perl and ruby , that provide more sophisticated string and character functions
PBXSelection
The PBXSelection variable is replaced by a special marker — some obscure sequence of characters known only to Xcode The Xcode editor looks for this special marker, or markers, in the text output
by the user script If it fi nds these markers in the text, it uses them to set the text selection in the editor pane This only applies when the output of the script is being used to replace or insert text in the editor pane
Including one PBXSelection marker in your script ’ s output causes the insertion point to be placed
at that position Including two PBXSelection markers causes everything between the two to be selected This listing shows a custom script that inserts a HeaderDoc comment and leaves the class name selected:
#! /bin/bash cat < < END_OF_HEADERDOC /*!
@class %%%{PBXSelection}%%%Class%%%{PBXSelection}%%%
@abstract @discussion */
END_OF_HEADERDOC
Trang 7Script Helpers
Xcode — or more precisely the Xcode developer tools framework — provide a number of utility
programs that can be called by a custom script to programmatically interact with Xcode and
the user
These tools are in a framework bundle added by the Xcode Developer Tools installer Use
the path supplied in the PBXUtilityScriptsPath custom script variable to locate the tools
The following script demonstrates using the PBXUtilityScriptsPath variable to execute the
AskUserForExistingFileDialog tool:
TOOLSPATH='%%%{PBXUtilityScriptsPath}%%%'
"${TOOLSPATH}"/AskUserForExistingFileDialog "Choose a text file"
Prompt for a String
The AskUserForStringDialog tool prompts users for some text, which they can enter interactively
via a dialog box The single, optional, argument specifi es the default text value that will appear in
the dialog box when it is opened The text entered by the user is returned via stdout The following
example bash script prompts for a username, supplying the current account ’ s short name as a
default, and captures the results in the variable NEWNAME :
NEWNAME="$('%%%{PBXUtilityScriptsPath}%%%/AskUserForStringDialog' ${USER})"
Ask for an Existing File or Folder
AskUserForExistingFileDialog and AskUserForExistingFolderDialog prompt the user to
select an existing fi le or folder, respectively Each takes a single, optional, prompt argument that
will be visible in the dialog box The path to the selected fi le or folder is returned via stdout If the
FIGURE 23 - 11
The two selection markers in the output text are caught by Xcode and used to establish a new text
selection in the editor pane, as shown in Figure 23 - 11
Trang 8user clicks the Cancel button in the dialog, the return value is empty You have no control over the type of fi le the user can select The dialog displays, and allows the user to choose, invisible
fi les and folders
Prompt for a New File
The AskUserForNewFileDialog tool prompts the user to choose a fi lename and location for a new
fi le The path to the new fi le is returned via stdout The tool takes two, optional, arguments The
fi rst is a prompt string that will be visible in the dialog box The second is a default fi lename for the new fi le To specify a default fi lename but no prompt, pass an empty prompt like this:
'%%%{PBXUtilityScriptsPath}%%%/AskUserForNewFileDialog' "" "New.txt"
Ask for an Application
AskUserForApplicationDialog presents the user with an application picker dialog This dialog, shown in Figure 23 - 12, enables the user to choose an application known to launch services,
or browse the fi le system in search of an unknown one The tool returns the full path to the application ’ s program fi le or bundle folder, as appropriate
FIGURE 23 - 12
The command takes two, optional, arguments The fi rst is the title used for the dialog, normally “ Choose Application ” The second argument is a prompt string, normally “ Select an application ”
APPLESCRIPT
In addition to the many ways in which Xcode can run automated scripts, the Xcode application itself can be driven programmatically using AppleScript Open the AppleScript dictionary for Xcode, shown
in Figure 23 - 13, and you will fi nd a rich and complex set of objects and command to work with
Trang 9Closely related to AppleScript are Automator actions The Xcode Developer Tools includes several
Automator actions, shown in Figure 23 - 14, that allow Xcode processes to be integrated into
Automator workfl ows
FIGURE 23-13
Trang 10Although you can build a project using the xcodebuild tool, that ’ s about all you can do with it.
AppleScript provides the ability to automate Xcode by accessing the data and structures within projects and the Xcode application itself For example, your company may have a set of target settings that need to be uniform across multiple projects You can write an AppleScript program to quickly check, and possibly correct, those properties in dozens of projects containing potentially hundreds of individual settings Or maybe you just like your windows stacked up in certain way
The possibilities are almost endless
Remember too that AppleScripts are supported directly by the organizer (see Chapter 22) Once you write and save your AppleScript, you can attach it to a project in the organizer as an action
AppleScript programming is beyond the scope of this book, but here are a few tips for using AppleScript with Xcode:
A shell script can start an AppleScript using the osascript tool This enables you to utilize AppleScript in build phases and custom commands You can also use AppleScript to inte-grate applications that couldn ’ t normally be controlled by a build script, such as an audio or image conversion program
The AppleScript Standard Additions allow an AppleScript program to run a shell script, meaning you can freely mix AppleScript and shell scripting technologies
Although Xcode lets you create AppleScript Studio applications, debugging an AppleScript application that is trying to interact with Xcode at the same time can be problematic If you can ’ t debug your script because the script is trying to use Xcode at the same time, switch
to another AppleScript editor or debugger like the AppleScript Editor application included with Mac OS X
RESETTING YOUR XCODE CUSTOMIZATIONS
If you ever want to wipe all of your customizations and put Xcode back the way it came when you fi rst installed it, then close the Xcode application, open up a Terminal window, and issue the following two commands:
defaults delete com.apple.Xcode
rm -rf ~/Library/Application\ Support/Xcode This will reset all per - user customizations and restore Xcode to its factory defaults for the logged - in user
SUMMARY
In earlier chapters, you learned to customize your project and how it is built In this chapter, you learned to customize your Xcode environment beyond the many options already exposed in the Xcode Preferences window You can set invisible features, add your own processing scripts to any
➤
➤
➤