Archives

Saturday May 27, 2006

Multiple sets of Terminal windows in Mac OS X

Having three screens up 24/7, it's easy to accumulate windows. I typically have several dozen available on my Mac, spread across a few dozen apps. In general, this is quite convenient. When I'm not using an app, I hide it (via cmd-H) and all of its windows disappear. If I only want to get a few windows out of the way, I WindowShade them or send them to the Dock.

Unfortunately, these approaches don't work very well for applications that have lots of windows. Terminal programs, for example, may have dozens of windows, each presenting a different shell and/or application context. Mac OS X doesn't let me hide some of an app's windows, so that's out. The Dock and WindowShade are awkward ways to manage dozens of windows; simply dismissing and retrieving a set of several windows becomes quite a hassle.

Fortunately, it turns out that there is a (relatively) simple workaround. By using multiple copies of an app (e.g., Terminal), I can hide and display each copy's windows separately. I currently have four copies of Terminal available. One is used for generic tasks, two are used for specific projects, and one is idle.

The arrangement is working well. Any new Terminal window I create (via cmd-N) becomes part of the current copy's set. I even found a way to let a script know which Terminal it's running under. Finally, although it might be nice to be able to migrate windows between sets, this has not been a serious deficiency in practice.

HOWTO

Here's a basic walkthrough of the procedure. Feel free to season to taste; it's your machine, after all! However, if you're a bit paranoid, you may want to quit the relevant copies of Terminal before performing these steps.

  • Copy the preference file and the Terminal app.

    Using the Finder, go to ~/Library/Preferences and copy com.apple.Terminal.plist to com.apple.Terminal_2.plist. Then, go to /Applications/Utilities and copy Terminal.app to Terminal_2.app.

  • Link up the app to the preference file.

    Control-click on Terminal_2.app and select "Show Package Contents". In the Contents folder, double-click on the Info.plist file. In the resulting Property List Editor, change CFBundleIdentifier from com.apple.Terminal to com.apple.Terminal_2. Save and Quit to make the changes permanent.

  • Trim the foreign language support files (optional).

    In the Resources folder, remove any superfluous *.lproj files. This can reduce the copy's disk storage by more than 60%.

You can now start up and play with the copied app. Some customization is also a reasonable idea at this point. The following sections explain how to change the windows' titles, the app's name in the Menu Bar, and the value of the TERM_PROGRAM environment variable. The techniques get increasingly scary as we go along; feel free to bail out at any time...

Window Titles

It's easy to change the "Title" information that gets used on each window. Pull down Terminal > Window Setting from the Menu Bar, then select the "Window" category. Change the "Title" fill-in to "TS2" (Terminal Set 2). Note that each copy of the app has its own preferences, window settings, etc. So, if you want to make a global change, you'll have to adjust each copy.

Menu Bar

If you have Xcode installed, you can change the Menu Bar to say "Terminal_2" (or whatever). Navigate to the Contents/Resources/English.lproj folder and double-click on Terminal.nib. After Interface Builder has started up, double-click on the "Terminal" string in "Terminal.nib (English) - MainMenu" and fill in the desired value (e.g., Terminal_2). Save and Quit.

Now, double-click on InfoPlist.strings. When a text editor window appears, change the value of CFBundleName to the same text string. Save and Quit. When you next start up Terminal_2, the Menu Bar will read correctly.

Shell Support

It's handy for shell scripts to be able to find out which terminal set they are in. This can be used, for example, in dynamically setting window titles or command-line prompts. My current solution, which is a bit scary, is to edit the executable binary for the application. If you're comfortable with this idea, read on...

Note: The following hack does not work on Mac OS X 10.5 (Leopard). See this entry for a safer and less brittle approach...

This hack is based on the fact that Terminal sets up a pair of environment variables for its sessions. One of these, TERM_PROGRAM, is normally set to Apple_Terminal. By editing Terminal's executable, we can change this value to a different text string.

Navigate to the Contents/MacOS folder. Using a binary-capable text editor (e.g., BBEdit), open the original executable. Search for the text string Apple_Terminal. In my executable, it is preceded by TERM_PROGRAM and followed by the string TERM_PROGRAM_VERSION, but Your Mileage May Vary.

Select the part of the string you wish to change and replace it with an equal number of characters. (I use Apple_Term_TS2 for Terminal_2.) Save and Quit. When you next start up the app, this string will be available in TERM_PROGRAM.

Final Comments

Although this exercise used Terminal as its target app, the same sorts of changes could be made to any app. By (a) breaking apps up into phalanxes of files and (b) giving us the tools to edit these files, Apple has given its users quite a bit of freedom. Not as much as an Open Source application would provide, to be sure, but still very handy on occasion.

Although he bears no blame for any of my ideas or mistakes, David Hill was splendidly helpful in my effort to change the app's title in the Menu Bar. Having worked closely with David in co-authoring the Mac OS X Technology Guide to Spotlight for SpiderWorks, I expected no less. Nonetheless, it's nice to have one's positive expectations confirmed.

Multiple sets of Terminal windows in Mac OS X in Computers , Technology - posted at Sat, 27 May, 19:09 Pacific | «e» | TrackBack

Comments

I've been using this hack for a week or so. It seems to be wearing well, providing the desired flexibility while not adding confusion. I have four terminal sets configured:

  • TS1 - administrivia and miscellanea
  • TS2 - my "work" project
  • TS3 - my "hobby" project
  • TS4 - unassigned, as yet