MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


Unix Gems for Mac OS X

by Kevin O'Malley
07/06/2004

I'll bet that just about everyone reading this article has heard of Eric Clapton, The Who, and Bonnie Raitt. I would also guess that many of you know who BB King and Muddy Waters are. But, I would wager that not many have heard of Charlie Patton, Mississippi John Hurt, Reverend Gary Davis, or Blind Blake.

If you've never heard of these blues players, stop now, go to the Apple Music Store and listen to some of their preview tracks. If you like blues, I'm sure you'll enjoy these musicians and will be able to detect how their style has influenced modern players.

What does this have to do with your Mac? Well, it's not just my way of imposing musical tastes on others, or exposing these great players to as many people as possible -- well, sort of. But more importantly, it's this: in any domain, there are hidden gems that never reach our radar screens. In music we have examples such as Don Carlo Gesualdo and Jean-Joseph Cassanéa de Mondonville. In computing, there are many as well.

In this article I'll expose you to some truly useful programs that you may not know about. Then I'll show you how to incorporate them into your daily work.

So put on some of Mississippi John Hurt's music and let's get started!

GNU Screen -- Screen Manager with VT100/ANSI Terminal Emulation

Installation: Comes with Mac OS X

Imagine you use a laptop with little screen real estate. Wouldn't it be nice if you could overlay several shells within a single Terminal window, and access each individually? Or maybe you're running a process on your machine at work and would like to log in from home and check its progress. What about developing code at work, or maybe writing some papers, and being able to get back to the exact place you left off from any other computer -- all with one command?

If any of these things appeal to you, then GNU Screen is for you.

GNU Screen is an application, or window manager, that enables you to interact with many processes through a single terminal window. Basically, you create a new virtual terminal for each process, or session you wish to run. Each of these virtual terminals is layered in a single window so you only see one at a time. You use various screen commands to switch between windows. Screen handles the details of multiplexing the physical terminals between processes.

What does this give you? You now have a single terminal window that holds as many virtual sessions as you like. Screen enables you to easily switch between sessions without opening up lots of shells and cluttering your desktop.

If this is all you used screen for, you'd be missing its real power. The real strength of screen is you can setup virtual sessions on one machine and access them from any other machine. This enables you to work on one machine and continue working from anywhere else, without the hassle of reconstructing each session.

Sound interesting? Let's take a look at screen's basic commands and some examples.

Using Screen

Screen comes standard with your Mac OS X installation so you won't need to install anything new to use it.

To get a flavor for how screen works, let's use a simple example. Imagine each morning when you get to work, you run the same programs -- say emacs for coding, pine for mail, lynx for text-based web surfing, and slrn for news reading. You set this up using screen. (Note: you can install these programs using Fink if necessary.)

First, open a new shell from the Terminal application and type "screen" at the prompt.

% screen

When screen starts, it reads its default initialization information from the file $HOME/.screenrc. This file can contain options, key binding functions, as well as other commands that you use to customize screen to your tastes. Later in the article, I'll discuss some possible customizations you can add to .screenrc. For now, let's just stay with the defaults.

When you run screen, it displays an informational screen. Simply press Space or Return and you are returned to a the prompt. (You can also turn this off by adding the command startup_message off to your .screenrc file.) At this point, you may think that screen did not run -- not so. Screen is lurking in the background available to you at any point.

Now, let's create a new virtual window for each program. To accomplish this, type Ctrl-a c (hold down the control key and press 'a', release the control key and press the 'c' key). You'll see a new, clean window with a new prompt. At the prompt, type the program you wish to run. Repeat this for each program.


  Window 1. Emacs: type Ctrl-a c, at the prompt type emacs 
  Window 2. pine: type Ctrl-a c, at the prompt type pine 
  Window 3. lynx: type Ctrl-a c, at the prompt type lynx 
  Window 4. slrn: type Ctrl-a c, at the prompt type slrn

You should have five screen windows -- the original window and four more running different processes.

Now that your processes are running, you need some way to switch between windows. There are a few ways to accomplish this. To toggle between the current window and the one you were previously using, type Ctrl-a Ctrl-a. To switch to the next window type Ctrl-a n, or Ctrl-a p for the pervious window.

You can also switch windows using screen's window list. When you type Ctrl-a, screen displays a list of active windows. To switch to a window, use the arrow keys (or vi-style, with j and k), to select the window and press Return.

As you can see, screen assigns each virtual window a unique ID number. The first window is tagged with ID 0, indicating it's the first window. As you create new window, screen tags then with ascending IDs.

If you add the following commands to your .cshrc file, your prompt will be prefixed with its screen window ID.


	unset prompt
	if ($TERM == screen) then
	  set prompt = "(%{#$WINDOW%}) % "
	else
	  set prompt = "% "
	endif

Window IDs are OK, but it's easier to navigate if you use window names instead. To name a window, type Ctrl-a A, backspace over the old title, and enter the new name at the prompt. Now when you list the windows (Ctrl-a), you can refer to them by name rather than ID.

Another way to navigate windows is by typing Ctrl-a followed by the window ID. Finally, adding the command:


  caption always "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<"

to your .screenrc file displays all windows at the bottom of the screen.

Using just this knowledge, I'm sure you can imagine all sorts of useful things to do with screen. For example, what if you log into several remotes machines daily. Using screen, you can set things up once and leave them open indefinitely, all in one Terminal window.

At this point, you might be saying to yourself all this sounds fine, but it still requires lots of typing if I exit screen. This is where your .screenrc file comes in. As you read earlier, this file contains settings that you use to customize screen.

A common technique is to create different screenrc files and have screen read the one you want at startup using the -c command-line option. The -c option tells screen to override the default configuration file $HOME/.screenrc with the specified file.

You can use the following screenrc file to simplify the previous example.


# ---- Example screenrc file for creating windows and processes.
# Create a window and use tcsh.
screen tcsh
# Turn off the startup message.
startup_message off
# Set the caption to the active windows. 
caption always "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<"

# New screens for various processes.
screen -t emacs 1 emacs
screen -t pine 2 pine
screen -t lynx 3 lynx
screen -t news 4 slrn                                        

Now that you understand the basics, let's look at a powerful feature of screen -- detaching and reattaching from/to a screen session. Staying with the pervious example, you should have a screen session running emacs, pine, lynx, and slrn.

Switch to any of these windows and type Ctrl-a d. This command detaches screen from this terminal and returns you to your original shell prompt. When detaching, screen prints a message to your shell indicating that the session was detached.

Now, go to a different machine, open a shell, ssh to the machine running screen (the one you just detached from), and type:

% screen -r

The -r option instructs screen to reattach to the session. Just like magic, your session is back up and running, just like you never left it. Try switching between windows to convince yourself that things are working.

To exit screen simply exit each program and the window you created. At any point, you can type Ctrl-a ? for a list of the available screen commands and their bindings.

The following table lists some of the more useful screen commands. For a complete list, see the screen man page.

Commands
Create a new window Ctrl-a c
Toggle between windows Ctrl-a Ctrl-a
Switch to the next window Ctrl-a n
Switch to the previous window Ctrl-a p
Switch to the window id Ctrl-a k (k = window id)
List all windows Ctrl-a "
Name a window Ctrl-a A
Help Ctrl-a ?
Detach from a session Ctrl-a d
Reattach to a session screen -r

Take a look at the screen man page as well as the articles listed in the Resource section. They cover many of screen's other features, including copying and pasting between windows, setting up key bindings, and sharing a screen session between different users.

Remind -- A Sophisticated Reminder Service

Installation: http://www.roaringpenguin.com/remind

Palm devices are everywhere. They're used to track contacts and schedules, enter information into databases, access email and the web, and play games. For scheduling and dealing with your calendar and contact list, Mac OS X come with software you can use to handle these things at no cost.

There are a few calendaring programs that you can use under Mac OS X. The simplest cal. The cal program displays a text-based calendar of the current month, or any other month or year that you specify.

The cal program generates read-only calendars. They're great for viewing, but not for scheduling your own events.

Another useful program is the Unix calendar utility. This utility enables you to keep a list of dated activities in a file and print out today's events using the calendar program.

The cal and calendar work great for general calendaring, but if you want more control and features, you will want to use Remind.

Remind is a reminder service with lots of options and features. Here's how it works. First, you list your reminders in a file in your home directory called .reminders. Each entry represents a calendar event or reminder. Once you add entries to the file, you run the Remind command to process the file and produce a formatted calendar.

Depending on the options, Remind will output events from a reminder list to a text or Postscript-formatted calendar.

Let's take a look at how to add events to your reminders file, as well as generating reminders. You add an entry in the reminders file for each event you would like to add to your calendar.

The following figure shows examples of the different types of events you can place in your .reminders file. Some of these are original and some I've collected from various web sites and articles.


# Example .reminders file.

# Single message.
REM 31 October 2002 MSG 4:00 Message.

# Last Monday of a month.
REM Mon 1 --7 MSG Last Monday of a month.

# The OMIT line tells Remind that 1 July is a holiday, and 
# it also prints a nice message on that date..
OMIT 1 July MSG Canada Day.

# The SKIP token in the REM line tells Remind to skip the 
# reminder if it falls on a holiday.
REM Thursday SKIP MSG Meeting.

# The AT keyword introduces an "AT clause." The 17:00 means 
# that the trigger time is 5:00 PM. The +15 means Remind 
# starts carping at you fifteen minutes ahead of time, and 
# the *3 means it annoys you every three minutes.
REM Mon Tue Wed Thu Fri AT 17:00 +15 *3 MSG Go home!

# Print message every week.
REM 13 March 2001 *7 MSG 4:00-5:00 AI seminar

# Every January 1, and for the five preceding days, 
# it will print the phrase 'My Birthday'. This is not 
# quite what you want, though: December 26, 27, 28, 29, 
# etc., are not your birthday.
# REM 1 Jan +5 My Birthday

# This will add 'in 5 days', 'in 4 days', 'tomorrow', 
# 'today' to the end of the phrase. However, if you 
# also use Remind to print a calendar, that day's entry 
# will have the phrase 'My Birthday today'.
REM 1 Jan +5 My Birthday %b

# This will still, when you simply ask for your day's reminders, 
# print 'My Birthday in 5 days', etc, but on the calendar 
# it will simply print 'My Birthday' on the correct day.
REM 1 Jan +5 %"My Birthday%" %b

# This will print, on the first Monday on or after the 
# 15th, the phrase 'Writer's Guild 6:30 PM'. 
# The third Monday can be no earlier than the 15th, 
# because the 1st Monday can be no earlier than the 1st, 
# making the 2nd Monday the 8th and the third the 15th. 
# By specifying a date of 'Monday 15', Remind knows to 
# look for the first Monday on or after the 15th of the month.
REM Monday 15 Writer's Guild 6:30 PM

# Similar to the above, but we've specified a more specific 
# date: the first Sunday in April.
REM Sunday 1 April MSG Spring Forward

# On November 27, 2001, and every two days after, you'll see 
# the phrase 'Feed the Fish'.
REM November 27 2001 *2 MSG Feed the Fish

# This will do the same as the above, until December 25 2001, 
# after which it 'expires'. It will no longer print.
REM November 27 2001 *2 UNTIL December 25 2001 MSG Feed the Fish

# However, you don't want to print 'Vacation' on Saturday 
# and Sunday, because that's silly.
REM July 22 2001 *1 UNTIL July 29 2001 MSG Vacation

There are many ways to output reminders. The simplest is to run the rem command. You can also add the command to your .cshrc file (if you are using tcsh) so each time you open a new shell, you are notified of todays events.

The Remind program has a few options for producing text-based and Postscript calendars. The first is the -c[n] option, which causes Remind to produce a text-based calendar, which it writes to stdout.

If you specify a number (n), Remind generates a calendar with that many months, beginning with the current month. If you do not specify n, Remind generates a calendar for the current month only.

The -p[n] option cause Remind to generate a Postscript calendar. Like the -c syntax, adding a n will cause Remind to generate a calendar with that many months.

In addition to these options, you can also use other programs to generate different calendar formats. For example, you can use Remind in conjunction with the rem2html.pl script to generate an HTML calendar.

Now that you understand the basics, let's look at an example of using Remind and cal. The script pim.pl is a simple example of how you can combine these tools to create a useful program. The PIM script enables you to keep a contact list, your calendar, a word list, notebook, and a quote database using freely available programs.

To run the program, download the script, cd to the directory that holds the script, edit the constants at the top of the file, and type:

% perl pim.pl

If you run this within screen, you can keep your calendar on one machine and access it from any host connected to the Internet.

Finally, the text-based pim script is useful as is, but is easily extendable to other implementations. For example, I have re-implemented it as a CGI and use it as an online pim.

GNUPlot -- An Interactive Plotting Program

Installation: http://fink.sourceforge.net/

So far, we've looked at two pretty useful applications. The final program I will present has been around for since the mid-1980s. GNUPlot is a program you can use to generate plots and charts. Unlike many plotting programs, GNUPlot is a "command driven" program.

For example, in a program like Excel, you create your data, select it, and tell Excel to plot the data, in some format. GNUPlot, on the other hand, is command driven. This means you tell GNUPlot what data to plot and how to plot it by issuing commands.

The power of this approach is that you can issue commands in several ways. You can enter commands interactivity within the GNUPlot program, you can store plot commands and data in files and have GNUPlot process the files from the command line, or you can access GNUPlot programmatically from scripting languages such as Perl and Python, as well as other languages.

Another plus is that you can create a batch of plots and save them to files. This is really useful when controlling GNUPlot programmatically. Finally, you can even control GNUPlot from AppleScript.

Let's begin by creating some interactive plots. Open a Terminal window and type gnuplot at the prompt.

You'll see some program information and be left at a prompt. You use this prompt to enter commands that drive the plotting process. Also, notice above the prompt the line "Terminal type set to 'aqua'." This tells you that plots will be generated for display using the AquaTerm.

You can tell GNUPlot to generate plots in different formats. For example, plots do not have to be displayed on the screen in a window. Instead, you can save them as Postscript or JPEG files. This is great for batching processing plot data.

Let's start by creating a simple plot of the sin function. To do this first open a Terminal window and type gnuplot at the prompt. next, type the following command:

gnuplot> plot sin(x) 

Since the terminal is set to aqua, the plot is displayed in a window. Let's change the output format to Postscript and generate the same plot.


gnuplot> set term postscript 
gnuplot> plot sin(x)

Instead of the plot coming up in a window, it's generated in Postscript. To get a list of the available terms, type help terminal at the GNUPlot prompt. See the documentation for information on adding more terminal types.

To change the format of the plot, you can use any one of GNUPlot's formatting commands. Here are some examples. (Switch your terminal back to aqua, set term aqua, before running these commands).

gnuplot> set title 'Test Plot'
gnuplot> set style function linespoints
gnuplot> plot sin(x)

These example show how to create plots interactivity within GNUPlot. All of this requires a lot of typing. Another way to use GNUPlot is to save all your data and commands in files and tell GNUPlot to process the files to produce the plot. This is a very powerful technique since you can write code to generate these files on the fly and feed them to GNUPlot automatically.

Let's take a look at how this works. Imagine you are developing a program and would like to plot its CPU usage. To accomplish this, we need a script that captures the process' CPU usage and another script that takes this data and plots it using GNUPlot.

For this example, we'll use 3 programs. The first is called fibonacci, a C program that generates the fibonacci series. The other two programs are scripts that acquire CPU information and plot the data. One is called logger.py, which collects CPU usage while the fibonacci program runs and writes it to a file. The other script is called plotCPU.py. It writes a plot format file and calls GNUPlot to display the plot of CPU usage.

To use these scripts, you need to open two shells. In the first shell, compile the fibonacci program (gcc -o fibonacci fibonacci.c). Next, run the fibonacci program by typing fibonacci at the prompt. While fibonacci is running, type the command python logger.py fibonacci 1 > fibonacci.dat in the second shell.

Once the fibonacci program exits, Ctrl-C out of the logging script. Finally, run plotCPU.py to generate the plot (python plotCPU.py).

There are lots of other things you can do with GNUPlot like generating 3D and multi-plot. If you ever need to visualize data, definitely check out GNUPlot. It's very powerful when combined with scripting languages like Perl and Python and is a natural addition to the development process.

Miscellaneous Programs

Before concluding, I'd like to mention two other programs I really like. The first is called bc, an arbitrary precision calculator language. If you are at the command line and need to perform some quick calculation, or possibly need more power than the calculator that comes with Mac OS X, take a look at bc.

The bc program supports arbitrary precision numbers and is great for complex, as well as simple calculations. In addition to being an interactive calculator, its also a language with a similar syntax to "C."

Here are some simple examples of bc in action:


% bc
12+54
66
x=2
y=3.123
z = x*y
z
6.246
scale=100
12/9
1.333333333333333333333333333333333333333333333333333333333333333333\
3333333333333333333333333333333333
scale=10
12/9
1.3333333333
z = 12/9
"z = "; z
quit
%

To exit bc, type quit or Ctrl-d. Take a look at the bc man page and the resource section of this article for more information.

A useful feature of Apple's TextEdit program is you can set it up to check spelling as you type. This way, if you misspell a word, you are notified immediately and can make the corrections right a way.

If you use Emacs for your writing, you can get the same functionally by using Flyspell. Flyspell is an Emacs minor mode that enables Emacs to perform spell checking and correction as you type.

Flyspell has lots of features. You can select your own dictionary, it works great with LaTeX, and can be set up to only check certain types of files. This way, it only checks your spelling for text and LaTeX files for example, and not source code; very useful.

Flyspell is very easy to set up so check its documentation for more information on installation and use.

Final Thoughts

There you have it, a look at some very useful Unix-based programs that you can use under Mac OS X. In this article, I only covered a few of my personal favorites. As you can imagine, there are lots of others waiting to be discovered. Check out the Resources section for information on where you can discover more.

Resources

GNU Screen

Remind

GNUPlot

bc

Flyspell

Other Resources

Copyright © 2009 O'Reilly Media, Inc.