User Scripts

User scripts are shell scripts you can define in your workspace and that you can execute by choosing them from the User Scripts menu or using a keyboard shortcut. With these scripts you can invoke command-line tools and perform operations on the selected text. For example, you can sort the selected lines in the text editor.

Xcode provides a number of mechanisms for working with user scripts. These features include:

This chapter describes how to manage and use Xcode user scripts.

Managing User Scripts

Xcode provides predefined user scripts that let you open files, perform searches, add comments to your code, sort text, and even add HeaderDoc templates that can help you document your header files. And you can use these files as examples to help write custom scripts.

The User Scripts menu (Figure 8-1) shows the predefined user scripts and the user scripts you add. This menu reflects the user-script hierarchy defined in the Edit User Scripts window, shown in Figure 8-2.

Figure 8-1  User Scripts menu
Figure 8-2  The Edit User Scripts window

You use the user-scripts editor to add, modify, and delete user scripts. You can also add user-script groups (menu groups) and separators.

Adding a user script adds a corresponding menu item to the User Scripts menu. You can define the script in the text editor pane of the user-scrips editor, or you can specify the location of an existing shell script in your file system.

A user script has four attributes, whose values you specify in the Edit User Scripts window:

To add a user script:

  1. Select the user-script group into which you want to add the user script.

  2. Choose User Scripts > Edit User Scripts to open the Edit User Scripts window.

  3. Click the Add Script button (+) and choose one of the following items from the menu:

    • New Shell Script. Creates a user-script menu item and a blank shell script, which you edit in the editor pane.

    • Add Script File. Creates a user-script menu item and prompts you for the location of an existing shell script file.

    • Add Automator Workflow. Creates a user-script menu item and prompts you for the location of an existing Automator workflow.

  4. Enter the name and keyboard shortcut (if desired) for the user script in the user-script list, as shown in Figure 8-3.

    Figure 8-3  Adding a shell script
  5. Choose values from the Input, Directory, Output, and Errors menus.

To remove a user script, user-script group, or separator, select it and click the Remove Script button.

To edit a file-based user script, select the script in the user-scripts list and click the Edit Script button (this button is available only for file-based user scripts).

Duplicating User Scripts

Sometimes it may be more convenient to create a user script based on an existing one instead of writing one from scratch. To create a custom user script based on a predefined user script:

  1. Choose User Scripts > Edit User Scripts to open the Edit User Scripts window.

  2. Select the user script to duplicate.

  3. Click the Add Script button and choose Duplicate Script from the menu.

  4. Customize the script and its attributes as appropriate.

Advanced User Scripts

The following sections describe advanced features of shell-based user scripts. The topics covered include variables you can use in menu script definitions, variables expanded prior to script execution, and special user output script markers.

Script Input Variables

Shell-based user scripts can also contain a variety of special variables that are expanded by Xcode each time the script is executed. The following sections describe the supported variables.

Getting Text from the Active Window

These variables are replaced by text in the active window:

  • %%%{PBXSelectedText}%%% is replaced by the selected text in the active text object.

  • %%%{PBXAllText}%%% is replaced by the entire text in the active text object.

The text is expanded verbatim with no quotation marks. In most shells this would be a dangerous practice because the selection might include single or double quotation marks or any number of other special shell characters. One safe way to use this in a Bourne shell script, for example, is to have it expand within “here-doc” style input redirection like so:

cat << EOFEOFEOF
%%%{PBXSelectedText}%%%
EOFEOFEOF

The script above would simply print the selected text to the standard output.

Getting Information on the Contents of the Active Window

These variables are replaced by information on the text in the active window:

  • %%%{PBXTextLength}%%% is replaced by the number of characters in the active text object.

  • %%%{PBXSelectionStart}%%% is replaced by the index of the first character in the selection in the active text object.

  • %%%{PBXSelectionEnd}%%% is replaced by the index of the first character after the selection in the active text object.

  • %%%{PBXSelectionLength}%%% is replaced by the number of characters in the current selection in the active text object.

Getting the Pathname for the File in the Active Window

This variable Is replaced by the path to the file for the active text object if it can be determined:

%%%{PBXFilePath}%%%

This result may not be accurate. Xcode tries to find the file path first by walking up the responder chain looking for a window controller that has a document. If it finds one it uses the document’s filename. If it does not find one, it uses name of the window’s represented file. For more information, see NSWindowController and NSDocument.

Sometimes this variable expands to nothing and sometimes it may expand to a filename that is not really a text file containing the text of the active text object. In the Xcode text editor this works correctly. In other text areas in Xcode (like the build log or any text field) it does not do anything reasonable.

Getting the Pathname for the Utility Scripts

This variable is replaced by the path to the folder that contains a number of built-in utility scripts and commands:

%%%{PBXUtilityScriptsPath}%%%

These scripts and commands can be used from user scripts to provide functionality such as presenting a dialog to ask the user for a string or to ask the user to choose a folder or file, or to add to the menu bar of the host application. See Built-in Utility Scripts for descriptions of the available utility scripts.

Script Output Markers

When a user script is done executing, Xcode scans the output for certain special markers. Only one output marker is supported. This variable specifies an exact selection within the output:

%%%{PBXSelection}%%%

By default, Xcode sets the selection to be an insertion point after the newly inserted output text. But if the output contains one or two instances of this special marker, it uses them to determine the selection. If there is one such marker, it identifies an insertion point selection. If there are two, all the text between them is selected. Xcode then removes the markers from the output.

Using Utility Scripts

Xcode provides several useful built-in utility scripts, which you can use in the user scripts you create.

To use one of these scripts, preface it with the expansion variable %%%{PBXUtilityScriptsPath}%%%, which specifies the location of the script. For example, the following statement displays a dialog to get input from the user and places the result in the variable STRING. The original text displayed in the dialog is “DefaultString”.

STRING = `%%%{PBXUtilityScriptsPath}%%%/AskUserForStringDialog "DefaultString" "DefaultWindowName"`

In addition to the AskUserForStringDialog script, Xcode provides built-in scripts to:

  • Choosing a new file

  • Choose an existing file or folder

  • Choose an application

For details, see Built-in Utility Scripts.

Built-in Utility Scripts

Xcode provides several useful utility scripts that are built in to Xcode itself. These scripts can be used in menu definition file scripts or in MPW-style worksheet content. To use one of these scripts, use the %%%{PBXUtilityScriptsPath}%%% expansion variables. For an example, see Using Utility Scripts.

Specifying a String

AskUserForStringDialog [default-string]

Displays a dialog in the active application and returns the string that the user enters. If supplied, default-string is the initial content of the text field.

Choosing an Existing File or Folder

AskUserForExistingFileDialog [prompt-string]

AskUserForExistingFolderDialog [prompt-string]

Displays a standard open dialog and returns the path of the file or folder that the user chooses. If supplied, prompt-string is the prompt in the dialog. Otherwise a default prompt is used.

Choosing a New File

AskUserForNewFileDialog [prompt-string [default-name]]

Displays a standard save dialog and returns the path of the new file. If supplied, prompt-string is the prompt in the dialog. Otherwise, a default prompt is used. If supplied, default-name is the default name for the new file.

Choosing an Application

AskUserForApplicationDialog [title-string [prompt-string]]

Displays an application picker dialog and returns the path of the application the user chose. If supplied, title-string is the title for the dialog. Otherwise, a default title is used. If supplied, prompt-string is the prompt in the dialog. Otherwise, a default prompt is used.

Adding a Menu Item from Any Script File

SetMenu add script script menu-title key-equiv input-treatment output-treatment index [menu-path ...]

Adds a menu item to an existing menu in Xcode. The menu item has the name menu-title, and the keyboard shortcut key-equiv. (Use "" for no keyboard shortcut.) When the user chooses this command, it invokes the script script, getting its input from input-treatment and placing its output in output-treatment. The new item is inserted at index in the menu identified by menu-path. If you don’t specify menu-path the item appears in the menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

index is a zero-based index starting at the end of all the original items in the menu. For example, the index 0 in the File menu would generally be the first item after Print (usually the last item in the File menu of an application). Index 2 would be after the second custom item in a menu. Use negative indices to count from the end of a menu. Index -1 means “at the end,” and Index -2 means “right before the last item.”

The key-equiv, input-treatment, and output-treatment arguments use the same syntax as the values of the menu definition file directives PBXKeyEquivalent, PBXInput, and PBXOutput respectively. For example, if input-treatment is Selection, the selected text is the input for the new menu item's script.

This is the most complicated form of the SetMenu command. Usually it is better to use the form described inAdding a Menu Item from a Menu Definition Script in conjunction with menu script definition files.

Adding a Menu Item from a Menu Definition Script

SetMenu add scriptfile script-pathindex [menu-path ...]

Adds menu items to an existing menu in Xcode. The items are read from script-path. See Adding a Menu Item from Any Script File for details on the file format. Details such as the menu items keyboard shortcuts, and input and output treatment are defined within the file. The new items are inserted at the given index in the menu specified by menu-path. If you don’t specify menu-path, the item appears in the main menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

index is a zero-based index starting at the end of all the original items in the menu. For example, the index 0 in the File menu would generally be the first item after the Print command (usually the last item in the File menu of an application). Index 2 would be after the second custom item in a menu. Use negative indices to count from the end of a menu. Index -1 means “at the end,” and Index -2 means “right before the last item.”

Adding a Submenu

SetMenu add submenu submenu-nameindex [menu-path ...]

Adds a submenu to an existing menu in Xcode. The submenu's title is submenu-name. Initially, it has no items. The new submenu is inserted at index in the menu specified by menu-path. If you don’t specify menu-path, the item appears in the main menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

index is a zero-based index starting at the end of all the original items in the menu. For example, the index 0 in the File menu would generally be the first item after the Print command (usually the last item in the File menu of an application). Index 2 would be after the second custom item in a menu. Use negative indices to count from the end of a menu. Index -1 means “at the end,” and Index -2 means “right before the last item.”

Adding a Menu Separator

SetMenu add separator index [menu-path ...]

Adds a separator to an existing menu in Xcode. The new separator is inserted at index in the menu specified by menu-path. If you don’t specify menu-path, the item appears in the main menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

index is a zero-based index starting at the end of all the original items in the menu. For example, the index 0 in the File menu would generally be the first item after the Print command (usually the last item in the File menu of an application). Index 2 would be after the second custom item in a menu. Use negative indices to count from the end of a menu. Index -1 means “at the end,” and Index -2 means “right before the last item.”

Removing a Custom Menu Item

SetMenu remove item index [menu-path ...]

Removes a custom item from an existing menu in Xcode. The custom item at index in the menu specified by menu-path. If you don’t specify menu-path, the item is removed from the main menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

index is a zero-based index starting at the end of all the original items in the menu. For example, the index 0 in the File menu would generally be the first item after the Print command (usually the last item in the File menu of an application). Index 2 would be after the second custom item in a menu. Use negative indices to count from the end of a menu. Index -1 means “at the end,” and Index -2 means “right before the last item.”

Only items and submenus added by a SetMenu command can be removed by the SetMenu remove item command. You cannot remove the standard Xcode menu items.

Removing All Custom Menu Items from a Menu

SetMenu remove all [menu-path ...]

Removes all custom items from an existing menu in Xcode. All custom items in the menu identified by menu-path are removed. If you don’t specify menu-path, the item is removed from the main menu bar. menu-path contains the titles of menus and submenus that lead to the desired menu.

This command applies to items and custom submenus but does not recurse into original submenus. For example, if you add an item to the File menu and you add a menu called My Scripts to the main menu bar, SetMenu remove all removes the My Scripts menu but does not remove the custom item in the File menu. SetMenu remove all File removes the custom item from the File menu.

Only items and submenus added by a SetMenu command can be removed by the SetMenu remove all command. You cannot remove the standard Xcode menu items.