TweetFollow Us on Twitter

Xcode Menu Scripts

Volume Number: 23 (2007)
Issue Number: 01
Column Tag: Scripting

Xcode Menu Scripts

Creating and installing Xcode menu scripts

By Jose R.C. Cruz

Introduction

Xcode is the de facto development environment for the MacOS X platform. Its Interface Builder allows user interfaces to be easily built and linked to the appropriate code. Its use of GCC enables it to support various languages, even exotic ones such as Haskell. Also, its build phase system is much easier to understand and maintain than the more kitchen-sink approach of makefiles.

Another unique feature of Xcode is its Script menu. It allows developers to add scripts that will customize or enhance the Xcode environment. These scripts can perform specific tasks on a selected text or file, or even on the entire project. They can also enable Xcode to interact with other third-party tools.

This article will focus on what constitutes an Xcode menu script. It will demonstrate how to use Xcode to write and install a menu script. It will also provide a number of script examples that developers may find useful. Readers are assumed to have a working knowledge of writing basic shell scripts.

To complement this article, the installer package, XcodeMenu, is available for download from the MacTech website. The package contains the project and file templates that will help readers write their own menu scripts. It also contains the example scripts shown in this article, as well as the Xcode project used to create them. The package can be downloaded at the following URL: ftp://ftp.mactech.com/src/mactech/volume23_2007/23.01/sit.

The Xcode Menu Script System

The Script menu is the central launch point for all Xcode menu scripts. Each item on the menu corresponds to a script stored inside the Xcode script directory. The directory itself is located on the OS X boot volume at the following path: /Library/Application Support/Apple/Developer Tools/Scripts/10-User Scripts.

Figure 1 shows the structure of the Xcode script directory, and its default contents. Notice that the 10-User Scripts directory is further subdivided into 6 other subdirectories. Each subdirectory gathers the scripts in terms of their general function. For instance, the 20-Search subdirectory contains those scripts that perform a search function.


Figure 1. The Xcode script directory.

The numbers before the names of each subdirectory and script show their positions on the Script menu. Each subdirectory is displayed as a submenu of that menu. A menu separator is defined using an empty file whose name consists of a number followed by three dashes. For instance, an empty file with a name of 15— in the subdirectory 50-Text places a menu separator between the scripts 10-sort.sh and 20-uniq.sh.

Anatomy of a menu script

In many ways, an Xcode menu script is similar to a basic shell script. Both are text files, and both can be written in any one of the popular shell languages such as sh, bash, and Perl. However, a shell script is usually stored as an ASCII text file. It usually receives its input from stdin, and sends its output to stdout. On the other hand, an Xcode menu script is stored as a UTF-8 text file. It often receives its input from the active source file. Where it sends its output will depend on how the script is configured.

Figure 2 shows the basic structure of a typical Xcode menu script. Like the shell script, it starts with a declarative header, also known as the she-bang. This header indicates the command-line tool that will interpret and execute the script. It is also used to pass command-line options to the tool. Make sure to check that the tool is correctly installed on the MacOS X platform. Otherwise, Xcode will return an NSTask error message stating the absence of the tool. It will also terminate the execution of the rest of the script.

For example, if the declarative header reads as #!/bin/bash, the bash tool will execute the menu script. If it reads as #!/usr/bin/python -t, the python tool will execute the script. The tool will also display warning messages for any inconsistent tabs present in the script.


Figure 2. Structure of a basic menu script (sort.sh).

Right after the declarative header is the arguments list. This list defines the input source for the script as well as its output destination. Also, it is where the script is assigned with a menu name and a shortcut key.

Finally, the last part of the script is the script body. This body consists of one or more command statements that will perform the specified menu action. The commands used by these statements depend largely on the command-line tool chosen for the task. Consult your tool's user manual for more information about its commands.

Known shortcomings

A number of issues limit the capabilities of an Xcode menu script. The most notable one is that the Script menu is enabled only if a source file has been selected. Otherwise, it is disabled even in the presence of an active Xcode project. This behavior prevents a script from performing project-oriented tasks such as backups, and SCM check-ins and checkouts.

Also, a menu script can only interact with the Xcode user in a limited way. Often, it is in the form of dialogs generated using the StandardsAdditions scripting library. For a menu script to access and display any one of these dialogs, it has to use the osascript tool.

But a menu script cannot use the osascript tool as its command-line tool. If its declarative header is #!/usr/bin/osascript, the script will only generate errors when executed by Xcode. This prevents the script from being written in pure AppleScript.

The Xcode Menu Script Components

Xcode provides a number of built-in arguments that can appear in the arguments list. To prevent the command-line tool from interpreting them, these arguments are enclosed within a %%%{...}%%% delimiter. The most important argument is PBXName. Use this to assign a menu name to the script. That name is displayed on the Script menu each time it is rebuilt.

Also equally useful is the PBXKeyEquivalent argument. Use this argument to assign a keyboard shortcut to the script. The shortcut itself consists of a modifier key followed by a single alphanumeric character. Assume, for example, the following entries in the script's arguments list.

# %%%{PBXName=Test Script}%%%
# %%%{PBXKeyEquivalent=@B}%%%

This means the script will have a name of Test Script on the Script menu. It can also be invoked by pressing the <CMD> key together with the <B> key. To execute the script, either its name is selected from the Script menu, or its keyboard shortcut is typed on the keyboard.

Other supported modifier keys include <Opt> (represented by a tilde, '~'), <Ctrl> (represented by a caret, '^'), and <Shift> (represented by a dollar sign, '$'). Make sure to assign unique shortcut keys to each menu script. Otherwise, the wrong script or operation may be invoked if that shortcut is used elsewhere.

Handling input data

To supply data to the menu script, Xcode provides the built-in argument, PBXInput. This argument is the functional equivalent of the stdin file descriptor.

The source of data for the PBXInput argument comes from the active source file. This will be the file being edited in the Xcode's text editor pane. For instance, if the test.c file is being edited, data for the PBXInput argument will come from that file.

The PBXInput argument takes one of three possible values. The Selection value tells Xcode to use the currently selected text as the input data for the menu script. Conversely, the AllText value tells it to use the entire source text as the input data. Finally, the None value tells Xcode to provide no data to the script. The same also happens if the PBXInput argument is omitted from the menu script.

Another way of providing input data to the menu script is through the built-in argument, PBXArgument. This is used to pass parameters to the menu script. It performs the same function as a command-line option.

A PBXArgument can only have a single parameter. But a menu script can have more than one PBXArguments. To access the first nine PBXArguments, use the positional variables $1 to $9, with $1 corresponding to the very first one. If there are more than nine PBXArguments, make sure to enclose the positional number within a pair of braces. For instance, to retrieve the value of the 25th PBXArgument, use the variable ${25}.

Assume, for example, the following entries in the script's arguments list.

# %%%{PBXArgument=-r}%%%
# %%%{PBXArgument=-z}%%%
# %%%{PBXArgument=-e}%%%

The positional variables $1, $2, and $3 will then return their respective values of -r, -z, and -e.

Handling output results

Xcode also provides the built-in argument, PBXOutput, to handle the output results of a menu script. This argument is the functional equivalent of the stdout file descriptor. If the menu script does not have the PBXOutput argument, any output results it generates will be simply discarded.

The PBXOutput argument can have one of seven possible values. Each value determines how the output results are to be handled by Xcode. For instance, the Discard value tells Xcode to ignore any results generated by the menu script. This has the same effect as not adding a PBXOutput argument to the script.

The next three values tell Xcode how to display the output results onto the active source file. The ReplaceSelection value replaces the currently selected text with the output results. On the other hand, the InsertAfterSelection value appends the results to the selected text. Finally, the ReplaceAllText value replaces the entire source text with the results. Note that the resulting change in the source text is not permanent. Choosing Undo from the Edit menu can still restore the original text.

The SeparateWindow value, on the other hand, tells Xcode to display the output results in a separate window. At the time of this writing, however, Xcode does not display the results in a separate document window. Instead, it uses a modal dialog to display those results. Hopefully, future versions of Xcode will address this issue by providing both display options. In the meantime, see the script example shown in Listing 2 for a good workaround.

The next useful PBXOutput value is the Pasteboard value. It tells Xcode to store the output results onto the clipboard buffer. Choosing Paste from the Edit menu then places the results onto any editable text window. The results remain in the clipboard buffer until the next Cut or Copy operation replaces them. They can also be replaced by another menu script if its PBXOutput is also set to Pasteboard.

The last PBXOutput value is the AppendToAllText value. This value tells Xcode to place the output results at the very end of the active source file. However, this feature is broken in version 2.3 of Xcode. Any output results from a menu script are not displayed anywhere on the source file. The README files for both Xcode 2.4 and 2.4.1 also showed no signs of whether or not this bug is fixed.

The macro variables

Xcode provides a number of built-in macro variables that can be used in a menu script. It then replaces these variables with their actual values prior to script execution. Use these macros to simplify various aspects of a menu script. Make sure to enclose each macro variable within the %%%{...}%%% delimiters. This will prevent the command-line tool from accidentally interpreting them.

The first macro variable is the PBXTextLength macro. It returns the total number of characters contained in the active source file. The character count also includes control characters such as newlines (0x0d) and tabs (0x09). In short, this macro variable represents the size of the source file in bytes.

Three macro variables are used for processing a text selection. The PBXSelectionStart macro returns the number of characters before the start of the selection. Conversely, the PBXSelectionEnd return the number of characters from the start of the file up to the end of the selection. Finally, the PBXSelectionLength returns the number of characters contained by the selection. Its returned value is equal to the difference between PBXSelectionEnd and PBXSelectionStart.

Figure 3 shows how these three macros are interrelated with each other. This example assumes that the active source file contains only the five-word phrase shown. Note that, in this example, the selected text is highlighted in grey.


Figure 3. Macro variables on a text selection.

On a related note, the built-in macro PBXSelection sets the start and end of a selection. It is used to select a portion of the output result. For example, assume that a menu script generates the following output.

echo "Lorem ipsum "
echo "%%%{PBXSelection}%%%dolor "
echo "%%%{PBXSelection} sit amet"

If the PBXOutput argument is set to use the active source file, the word dolor will be selected on that file. However, make sure to use the PBXSelection macro in pairs. If Xcode does not find a matching PBXSelection macro for a previous one, it will not perform the text selection.

There are also two built-macros that return a file path. The first one, PBXFilePath, returns the absolute file path of the active source file. The path is returned as a string value, and is rendered as a Unix file path. Use this macro to manipulate the file, its contents, or its directory at the shell level.

The second macro is PBXUtilityScriptsPath. This macro returns the directory path for all the utility scripts bundled with Xcode. By default, it returns the path as

/System/Library/PrivateFrameworks/ ¬
DevToolsInterface.framework ¬
/Resources/UtilityScripts.

Use this macro to refer to any one of the utility scripts, which will be discussed next.

The utility scripts

In addition to built-in arguments and macros, Xcode also comes with a number of utility scripts. These scripts are primarily used to add modal dialogs to a menu script. Xcode users can then interact with the menu script through these dialogs.

The utility scripts use the osascript command-line tool to generate their modal dialogs. This tool sends AppleScript calls to the StandardAdditions library, which then displays the desired dialog. When a user interacts with the dialog, the tool returns the results to stdout as a string. If the user cancels the dialog, the tool sends an empty string to stdout and a cancellation message (error -128) to stderr.

At the time of this writing, Xcode comes bundled with five utility scripts. The first script, AskUserForApplicationDialog, displays a list of all applications present on the MacOS X volume. It requires two string parameters: the dialog title and the prompt message. For example,

REPLY=`%%%{PBXUtilityScriptsPath}%%%/AskUserForApplicationDialog ¬
"Application List" "Pick an application"`

displays a dialog with the title Application List and the message Pick an application. When a user selects an application, the script returns the absolute file path to that application as a string. In the above example, the returned string is stored in the shell variable REPLY.

The second utility script is the AskUserForStringDialog script. This script prompts the user for an input string. It takes a single string parameter, which is the default input value. For example, the following statement

REPLY=`%%%{PBXUtilityScriptsPath}%%%/AskUserForStringDialog ¬
"untitled"`

should display an input dialog with the string untitled as the default value. After the user types in a string and presses the Enter button, the script returns the string value to the menu script. However, this utility script has one notable flaw. Its prompt message is set to the default string value of Enter your name, and it cannot be changed. For a good workaround, see the script example shown in Listing 4.

The rest of the utility scripts are used for I/O interaction. The AskUserForExistingFileDialog script prompts the user to select a file from the MacOS X volume. It takes a single string parameter, which is the prompt message. For example, the statement

REPLY=`%%%{PBXUtilityScriptsPath}%%%/AskUserForExistingFileDialog ¬
"Choose a file to be edited"`

displays the dialog with the prompt Choose a file to be edited. When the user selects a file, the script returns the absolute file path to that file as a string.

The dialog displayed by this script uses ~/Documents as its default directory. It shows any files and directories that are hidden or invisible. Also, it resolves links to other directories. But it will not do the same for links to other files, treating them instead as actual files.

The next I/O utility script is the AskUserForFolderDialog script. This script prompts the user to select a directory from the MacOS X volume. It also takes a single string parameter for its prompt message. For example, the statement

REPLY=`%%%{PBXUtilityScriptsPath}%%%/AskUserForFolderDialog ¬
"Select a destination"`

displays the dialog with the prompt Select a destination. When the user selects a directory, the script returns the absolute file path to that directory as a string.

The dialog displayed by the script allows users to create a new directory, and to select it as well. It also resolves links to other directories. But, it will not display any directories that are hidden or invisible.

The third I/O utility script is the AskUserForNewFileDialog script. This script prompts the user to select the directory where a new file can be stored. It also prompts for a name to be assigned to that file. The script takes two string parameters: one for the prompt message, the other for the default filename. For example, the statement

REPLY=`%%%{PBXUtilityScriptsPath}%%%/AskUserForNewFileDialog ¬
"Save the backup as" "backup.file"`

displays the dialog with the prompt Save the backup as, and a default filename of backup.file. If a file exists with the same name, the dialog will display a warning alert. Also, once the user has selected a directory and a filename, the script returns the absolute file path to that new file. It will not, however, create the file.

Creating an Xcode Menu Script

The Xcode project template

Often, writing an Xcode menu script means using a third-party text editor. But why not use Xcode itself to write and install a menu script? The Xcode project template, Xcode Menu Script Action, is created primarily for this purpose. This template, as well as other support files, are available as part of the XcodeMenu installer package.

The template itself contains a starter script named myscript.sh. This script has the basic arguments list shown in Figure 2. Modify this list to the appropriate settings for this script.

The script also has a custom list containing two arguments. These arguments determine how the script is to be installed. The first one, USRDir, specifies the subdirectory that will contain the menu script. This subdirectory is then created inside the Xcode script directory.

The second argument is USRName. This specifies a unique filename for the menu script. It also specifies the two-digit number that determines the script's position on the Script menu. Always make sure to assign a two-digit number to the menu script. Also, make sure to add a dash between the number and the script's filename. Failure to do either one renders the script inaccessible from the Script menu.

For example, assume that a menu script has the following entries in its custom header.

# - Custom User Script Info -
# %%%{USRDir=75-CVS Control}%%%
# %%%{USRName=05-cvsbackup.sh}%%%

Xcode first checks to see if the subdirectory 75-CVS Control exists in the script directory. If it does not, Xcode creates a new subdirectory with that name. Next, Xcode copies myscript.sh into that subdirectory. It then renames the copy as 05-cvsbackup.sh.

The Xcode project can also have multiple scripts. Each script can have its USRName set to its source filename, as long as the required two-digit number and dash precedes that name. Each script can share the same USRDir subdirectory as the other scripts. Alternatively, it can have its own USRDir subdirectory.

Using the project template

To create a new Xcode menu script project, choose New Project from the File menu. Then, from the Project Assistant dialog, select Xcode Menu Script Action (Figure 4) and press the Next button. Assign a new name to the project, and select the directory to store it. Click on the Finalize button to create and save the new project.


Figure 4

To install and test the default source script, choose Build from the Build menu. If the build process generates no errors, choose Reset Menu from the Script menu. This will cause the menu to update its list of menu items. After a second or two has elapsed, click on the Script menu. There should be submenu entry named Test Scripts, and that submenu should have a single menu item named My Test Script (Figure 5).


Figure 5. A single menu script.

To add another source script to the Xcode project, choose New File from the File menu. Then, from the New File Assistant, choose Menu Script File and click on the Next Button (Figure 6). Assign a new name to the file, and the project and target to which it should belong. Click on the Finalize button to save the file, and have it added to the project.


Figure 6. Selecting the file template.

Choose Build from the Build menu to add the new menu scripts to the Script menu. Then choose Reset Menu from the Script menu to update its list. The submenu should now have two menu scripts as shown in Figure 7.


Figure 7. Two menu scripts.

Xcode Menu Script Examples

Counting the number of lines

Listing 1 shows one of the simplest menu scripts possible for the Xcode environment. This script uses the wc tool to count the number of lines in the source file. It then displays the resulting count using a modal dialog.

Listing 1. Count the number of source lines (lineCount.sh).

# - PB User Script Info -
# %%%{PBXName=Count the number of source lines}%%%
# %%%{PBXInput=None}%%%
# %%%{PBXOutput=SeparateWindow}%%%
# %%%{PBXKeyEquivalent=}%%%
# %%%{PBXArgument=}%%%
# %%%{PBXIncrementalDisplay=YES}%%%
#
# - Custom User Script Info -
# %%%{USRDir=90-Sample Menu Scripts}%%%
# %%%{USRName=01-linecount.sh}%%%
#
# count the number of lines in the source file
CNT_src="%%%{pbxfilepath}%%%"
CNT_LINES=`wc -l $CNT_SRC`
# parse out the count value
CNT_LINES=`echo $CNT_LINES | awk '{ print $1 }'`
# display the count results
CNT_MESSAGE="Number of lines: $CNT_LINES"
echo "$CNT_MESSAGE"

Search for a selected word or phrase

The script shown in Listing 2 is a little more sophisticated. It first stores the selected text into the SRCH_DAT variable using the cat tool. Notice the dash right after the tool. This tells cat to receive its input data from stdin.

The script first retrieves the file path to the active source file. It then determines the file path to the search.output file, and stores it into the SRCH_OUT variable. Next, the script passes the active source file to the nl tool to renumber the source lines. Afterward, it uses grep to parse out those lines that contain the SRCH_DAT pattern, and stores the results into the search.output file.

This script also demonstrates how to use Xcode to display the search results. It first converts the file path stored in SRCH_OUT to a form usable by AppleScript. It then sends a number of AppleScript calls to the osascript tool. The tool then uses these calls to coerce Xcode into opening the search.output file.

Listing 2. Searching for a selected text (selectSearch.sh).

# - PB User Script Info -
# %%%{PBXName=Search selected text}%%%
# %%%{PBXInput=Selection}%%%
# %%%{PBXOutput=Discard}%%%
# %%%{PBXKeyEquivalent=}%%%
# %%%{PBXArgument=}%%%
# %%%{PBXIncrementalDisplay=YES}%%%
#
# - Custom User Script Info -
# %%%{USRDir=90-Sample Menu Scripts}%%%
# %%%{USRName=02-selectSearch.sh}%%%
#
# retrieve the search parametre
SRCH_DAT=`cat -`
# renumber the search document
SRCH_INP="%%%{PBXFilePath}%%%"
#prepare the output file
SRCH_DIR=`pwd`
SRCH_OUT="$SRCH_DIR/search.output"
if [ -f $SRCH_OUT ];
then
   rm -f $SRCH_OUT
fi
#perform the search and save the output to the file
nl -b a $SRCH_INP | grep "$SRCH_DAT" 1> $SRCH_OUT
#display the results of the search
SRCH_OUT="OS X"`echo $SRCH_OUT`
SRCH_OUT=`echo ${SRCH_OUT//\//:}`
SRCH_OUT="\"$SRCH_OUT\""
osascript <<-APPLESCRIPT
   tell application "Finder"
       set fileref to get file $SRCH_OUT as string
       
       tell application "XCode"
         activate
         open file fileref
       end tell
    end tell
   APPLESCRIPT

Backing up an Xcode project

Listing 3 shows how a menu script can create a backup of the current Xcode project. It also demonstrates how the script uses a utility script to interact with the Xcode user.

First, the script navigates from the current working directory until it reaches the level where it finds the first .xcodeproj bundle. This is done in case the active source file happens to be stored inside a subdirectory within the project directory. Next, the script uses the AskUserForNewFileDialog utility script to prompt the user for a backup name and destination. It then stores the result into the PRJ_BCK variable.

Now the script uses the expr tool to check the contents of the PRJ_BCK variable. If the user cancels the dialog prompt, the variable will contain a null string, and the rest of the script is not executed. Otherwise, that variable will likely have a valid file path. The script then uses the tar tool to archive and compress the Xcode, and stores the backup archive onto the specified destination.

Listing 3. Backing up the active project (projBackup.sh).

# - PB User Script Info -
# %%%{PBXName=Backup the Xcode project}%%%
# %%%{PBXInput=None}%%%
# %%%{PBXOutput=SeparateWindow}%%%
# %%%{PBXKeyEquivalent=}%%%
# %%%{PBXArgument=}%%%
# %%%{PBXIncrementalDisplay=YES}%%%
#
# - Custom user script info
# %%%{USRDir=90-Sample Menu Scripts}%%%
# %%%{USRName=03-projBackup.sh}%%%
#
# initialise the following shell variable
PRJ_MSG="Save the backup as"
# navigate to the project directory
PRJ_CHK=`ls -d *.xcodeproj | wc -l`
while [ $PRJ_CHK -lt 1 ];
do
   cd ..
   PRJ_CHK=`ls -d *.xcodeproj | wc -l`   
done
# retrieve the current directory
PRJ_DIR=`pwd`
# generate a date/time tag
PRJ_TAG=`date "+%H%M%S"`
PRJ_NOM="Backup_$PRJ_TAG"
# select a backup filename
PRJ_BCK=`%%%{PBXUtilityScriptsPath}%%%/AskUserForNewFileDialog \
               "$PRJ_MSG" "$PRJ_NOM"`
# was it successful?
PRJ_CHK=`expr "$PRJ_BCK" : '.*'`
if [ $PRJ_CHK -gt 0 ];
then
   PRJ_BCK="$PRJ_BCK.tar.gz"
   # start the backup
   tar -czf $PRJ_BCK *.*
   # the backup is done
   echo "Backup created at: $PRJ_BCK"
fi

Exporting a CVS project archive

The script shown in Listing 4 demonstrates how to use CVS to export the latest copy of the Xcode project from the project archive. It also shows how to use the osascript tool to provide a workaround for the AskUserForStringDialog utility script.

First, the script checks to see if the project is currently being managed by CVS. It does this by looking for a CVS subdirectory within the project itself. If the subdirectory does not exist, the script displays the appropriate dialog message.

If the project is being managed by CVS, the script retrieves the path to the project archive from the Root file. It then uses the osascript tool to invoke the display dialog function with AppleScript. This dialog prompts the user for an export tag, offering a timestamp as the default tag. The results of the dialog are then stored into the CVS_TAG variable.

Next, the script uses the cvs tag command to apply the tag to the Xcode project. It then retrieves the project's archive name from the Repository file. Afterward, the script prompts the user for an export name and destination using the AskUserForNewFileDialog utility script. It stores the result of that interaction into the CVS_XPT variable.

Finally, the script uses the cvs export command to export a copy of the Xcode project from the archive and onto the desired destination. If it is successful, the script displays a dialog showing the directory path of the exported project.

Listing 4. Exporting from CVS (cvsExport.sh).

# - PB User Script Info -
# %%%{PBXName=Export CVS Xcode project}%%%
# %%%{PBXInput=None}%%%
# %%%{PBXOutput=SeparateWindow}%%%
# %%%{PBXKeyEquivalent=}%%%
# %%%{PBXArgument=}%%%
# %%%{PBXIncrementalDisplay=YES}%%%
#
# - Custom User Script Info -
# %%%{USRDir=90-Sample Menu Scripts}%%%
# %%%{USRName=04-cvsExport.sh}%%%
#
# check for the following subdirectory
CVS_DIR=`pwd`
CVS_DIR="$CVS_DIR/CVS"
if [ -d $CVS_DIR ];
then
   # retrieve the CVS repository path
   CVS_ROOT=`cat $CVS_DIR/Root`
   
   # prompt the user for an export tag
   CVS_TAG=`date "+%H%M%S"`
   CVS_TAG=`osascript <<-APPLESCRIPT
      tell application "Xcode"
         activate
         display dialog "Enter a CVS export tag:" ¬
            default answer ${CVS_TAG}
         return (text returned of result) as string
      end tell
      APPLESCRIPT
   `
   # was it successful?
   CVS_CHK=`expr "$CVS_TAG" : '.*'`
   if [ $CVS_CHK -gt 0 ];
   then
      # apply the tag to the sources
      CVS_TAG="v$CVS_TAG"
      cvs -Q tag $CVS_TAG
      
      # prompt the user for an export directory
      CVS_MSG="Export the project to:"
      CVS_NOM=`cat $CVS_DIR/Repository`
      CVS_XPT="$CVS_NOM$CVS_TAG"
      CVS_XPT=`%%%{PBXUtilityScriptsPath}%%%/AskUserForNewFileDialog "$CVS_MSG" "$CVS_XPT"`
      
      # was it successful?
      CVS_CHK=`expr "$CVS_XPT" : '.*'`
      if [ $CVS_CHK -gt 0 ];
      then
         # export the CVS project
         cvs -d $CVS_ROOT -Q export -R -r $CVS_TAG \
               -d $CVS_XPT $CVS_NOM
         
         echo "Project has been exported to: $CVS_XPT"
      fi
   fi
else
   echo "This project is currently not under SCM by CVS."
fi

Concluding Remarks

Menu scripts are a flexible and effective way to customize and enhance the Xcode environment. Their support for standard shell scripting languages makes them easy to learn and implement. They can add features that are essential to the workflow, but are not available in Xcode. They can automate certain tasks that are otherwise repetitive and prone to mistakes. They can also invoke external tasks without the need to exit the Xcode environment.

Without a doubt, menu scripts are one of the reasons why Xcode continues to be the preferred development tool for MacOS X.

Bibliography and References

Apple Computers. "Using Scripts to Customize Xcode". Xcode 2.3 User Guide. Copyright 2004, 2006. Apple Computers, Inc.

Cooper, Mendel. Advanced Bash-Scripting Guide. Revision 4.1. 2006 Oct 08. Online: www.tldp.org/LDP/abs/abs-guide.pdf.


JC is a freelance engineering consultant and writer currently residing in North Vancouver, British Columbia. He writes for various publications and teaches origami at his local district's public library. He can be reached at anarakisware@cashette.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Maintenance 2.9.9 - System maintenance u...
Maintenance is a system maintenance and cleaning utility. It allows you to run miscellaneous tasks of system maintenance: Check the the structure of the disk Repair permissions Run periodic scripts... Read more
Deeper 2.8.8 - Enable hidden features in...
Deeper is a personalization utility for macOS which allows you to enable and disable the hidden functions of the Finder, Dock, QuickTime, Safari, iTunes, login window, Spotlight, and many of Apple's... Read more
BetterTouchTool 3.9998 - Customize multi...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom)... Read more
OnyX 4.3.6 - Maintenance and optimizatio...
OnyX is a multifunction utility that you can use to verify the startup disk and the structure of its system files, to run miscellaneous maintenance and cleaning tasks, to configure parameters in the... Read more
Acorn 7.3.2 - Bitmap image editor.
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Google Chrome 109.0.5414.119 - Modern an...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
ASPPPPP 1.3.99999999999 - Create cursor...
ASPPPPP brings Aperture Science's portal technology to your desktop. Avoid carpal canal syndrome and save millions of pixels of cursor moving. When launching the app, you first set the position of... Read more
beaTunes 5.2.31 - Organize your music co...
beaTunes is a full-featured music player and organizational tool for music collections. How well organized is your music library? Are your artists always spelled the same way? Any R.E.M. vs REM?... Read more
FotoMagico 6.3.3 - Powerful slideshow cr...
FotoMagico lets you create professional slideshows from your photos and music with just a few, simple mouse clicks. It sports a very clean and intuitive yet powerful user interface. High image... Read more
RoboForm 9.4.1 - Password manager; syncs...
RoboForm is a password manager that offers one-click login, mobile syncing, easy form filling, and reliable security. Password Manager. RoboForm remembers your passwords so you don't have to! Just... Read more

Latest Forum Discussions

See All

Rec Room will be playing host to major a...
It has been a good time for gaming and music lovers lately with names like Blackpink and Man with a Mission popping up in various mobile games, and now Rec room wants to get involved in a big way, striking a deal to bring Republic Records artists... | Read more »
‘Railbound’ Massive 2.0 Update To Bring...
Railbound from Afterburn Games is set to get a massive update this week. Since its launch, Railbound has gotten a good amount of support already. Read about the most recent big update here. Afterburn Games will bring Railbound 2.0 to mobile and PC... | Read more »
TouchArcade Game of the Week: ‘Madness/E...
Sometimes a game comes along that feels so purely built for mobile, and its controls and mechanics come together so well on the touchscreen, I say that Apple should just pre-install it on every iPhone it sells. I very much feel that way about... | Read more »
SwitchArcade Round-Up: ‘ATONE’, ‘Dance o...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for January 27th, 2023. In today’s article, we mop up the remaining releases of the week. There are quite a few, thanks to some slipping out after I went home last night. There are... | Read more »
‘Prehistoric Isle 2 ACA NEOGEO’ Review –...
It’s somewhat surprising how clearly one can draw a line between SNK before NEOGEO’s launch and after. The likes of Psycho Soldier and Ikari were relegated to cameo appearances, and only a few lucky pre-NEOGEO IPs ever saw follow-ups on the multi-... | Read more »
Old School RuneScape announces landmark...
Jagex has announced some groundbreaking news for fans of its iconic MMORPG, Old School RuneScape. For the first time in the game's 15-year history, the player base has voted in favour of the implementation of a new skill to the retro masterpiece... | Read more »
Physics Puzzler ‘Squiggle Drop’ From Noo...
Noodlecake’s Squiggle Drop () featuring more than 100 puzzles is the final new Apple Arcade release of January 2023. When Apple revealed the games for the month, I was very curious to see how Squiggle Drop would turn out. It seemed like a game I’d... | Read more »
‘Of Two Minds’, a Psychoanalytical FMV G...
We are truly in the renaissance of full-motion video games since the genre first arrived in the late ’80s and early ’90s before dying an ugly death due to the poor quality of those gaming experiences as well as the poor quality of the actual video... | Read more »
SwitchArcade Round-Up: ‘Goldeneye’ Comin...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for January 26th, 2023. The big news is that Goldeneye for Nintendo Switch Online finally has a release date, and it’s soon as it could be. We have a ton of new releases to go through... | Read more »
Previously Cancelled Co-Op City Builder...
Back in August of 2021 developer Supercell formally announced Everdale to the world, a cooperative city building game that had already been in a smaller form of beta testing under a different name for at least a year prior. That announcement kicked... | Read more »

Price Scanner via MacPrices.net

Apple to release new iPad with carbon fiber k...
According to analyst Ming-Chi Kuo, a new Apple iPad will be the beneficiary of all-new technology featuring a kickstand and folding OLED screen. There will be no new iPads released in the next nine... Read more
New sale: Apple 10.9″ iPad Airs for $100 off...
Amazon has 10.9″ M1 WiFi iPad Airs on sale for $100 off Apple’s MSRP, with prices starting at $499, for a limited time. Their prices are the lowest available among the Apple retailers we track: – 10.... Read more
Apple may release high-end Reality Pro device...
Mark Gurman, in this weeks’s Power On newsletter, states that Apple may attempt to release a high-end, nearly $3000, Reality Pro device in an attempt to move the VR market forward. With potential... Read more
13″ M2 MacBook Pros available today at Apple...
Apple standard-configuration 13″ MacBook Pros with M2 CPUs in stock and available today starting at $1169, Certified Refurbished, and ranging up to $150 off original MSRP. These are the cheapest 13″... Read more
Get a 13″ M2 MacBook Air at Apple today for a...
Apple has standard-configuration 13″ M2 MacBook Airs in stock and on sale starting at only $1079, Certified Refurbished, and ranging up to $150 off MSRP. These are the cheapest M2-powered MacBooks... Read more
Apple Card special offers for January and Feb...
Apple Card is offering special offers for January & February, 2023 which include a $75 Daily Cash offer for customers who open a new Apple Card through February and a $55 Daily Cash offer for new... Read more
New low price: Clearance 14″ M1 Pro MacBook P...
B&H Photo has dropped prices on Apple’s previous-generation 14″ 8-Core M1 Pro MacBook Pros by $300 off original MSRP, now only $1699. Free 1-2 day shipping is available to most US addresses: – 14... Read more
Apple has clearance 27-inch 5K iMacs in stock...
Apple has a full line of Certified Refurbished 2020 27″ 5K iMacs available starting at only $1169 and ranging up to $810 off original MSRP. Apple’s one-year warranty is standard, shipping is free,... Read more
Price drop! Apple has M1 Mac mini in stock fo...
Apple has dropped prices on clearance M1-powered Mac minis in their Certified Refurbished section to a new low starting price of only $469. Each mini comes with Apple’s one-year warranty, and... Read more
The Latest Rumors and Potential Features of a...
The rumors are flying and speculation is running rampant around the possibility of a new Apple iMac Pro. It is expected to be a powerful computer in Apple’s lineup, and people are already asking what... Read more

Jobs Board

Wireless Device Portfolio Manager - *Apple*...
…in our Retail Wireless journey. The successful Device Portfolio Manager - Apple will work cross-functionally to develop, oversee and execute a device roadmap Read more
Bilingual Level 1 *Apple* Support Specialis...
…generous employee benefits! Our client is currently seeking a qualified Bilingual Level 1 Apple Support Specialist to join their team. This role can be hybrid / Read more
Security Officer - *Apple* Store - NANA Reg...
…security is our \#1 priority\. This is a public environment at the Apple Store and surrounding areas with the corresponding levels of traffic \(employees, visitors, Read more
Device Portfolio Manager - *Apple* - DISH (...
…in our Retail Wireless journey. The successful Device Portfolio Manager - Apple will work cross-functionally to develop, oversee and execute a device roadmap Read more
Senior STE / *Apple* / OTT / Streaming Serv...
…and perform tests to validate large-scale content operations and releases. As an Apple STE, you'll partner with the content and streaming teams to ensure smooth Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.