Showing and Printing Messages

By default, the show command puts all of your message, including "boring" header fields like Received:, onto your screen.

You can change the way that your message is shown by deleting these header fields, folding lines that are too long for your terminal, and so on. You can print your messages with neat margins and a header line at the top of the page. Here's how MH displays non-MIME messages. This is good background for the Section Reading MIME Messages, which explains how MIME messages are displayed.

The Current Message

When you show a message with show, it becomes the current message. When you show a message with next or prev, MH actually runs the commands show next and show prev, respectively -- which also reset the current message. If you show a group of messages by typing, for example:

    % show 1 3 5
        ...
    
the last message (5) becomes the current message.

Messages You Haven't Read

MH can track which messages you haven't read yet. When you incorporate new mail, the message numbers are added to a sequence automatically. rcvstore, which puts new mail into folders automatically, also adds messages to this sequence. As you read the messages (with show, next, and prev), the message numbers are taken out of the sequence. See the Section More About Sequences.

To set this up, pick a name for the unseen sequence (I call mine unseen).

(Note that MH will keep more than one unseen sequence, if you need that. Add other sequence names to the Unseen-Sequence: entry, separated with spaces. All the unseen sequences will have the same message lists in them. You can use the mark program to modify one or more of them, though.)

Put an entry in your MH profile:

    Unseen-Sequence: unseen
    
Remember that in MH, you can use a sequence name any place you can use message numbers. For example, to get a list of the messages you haven't read, you can use:
    % scan unseen
    
If you have MH 6.7.2 or later, you can tack on a range specification like :first or :last. For instance, to read the first unseen message, remove it, then read the rest of the unseen messages one-by-one:

% show unseen:first
    ...
% rmm
% show unseen:next
    ...
% rmm
% !s     C shell history: repeats previous show command
    ...

If you've already read some of the messages -- that is, there are "gaps" in the unseen messages, show unseen:next will step through the unseen messages. When you've seen all the messages, you'll get "show: no unseen:next message."

Would you like an automatic list of your unread messages as you log in? Use lines like those in the Example below to your .login or .profile file. If there are messages in your unseen sequence, you'll get a scan listing.

Examples: Automatic scan of unread messages
C shell

    mhpath unseen +inbox >& /dev/null
    if ($status == 0) then
        echo "Unseen mail in inbox:"
        scan +inbox unseen
    endif
    
Bourne and Korn shells:
    if mhpath unseen +inbox >/dev/null 2>&1
    then
        echo "Unseen mail in inbox:"
        scan +inbox unseen
    fi
    
The flist command will list all folders that have messages in the unseen sequence.

Each folder keeps its own unseen sequence, but it's mostly useful in folders that get new mail. As of this writing, no version of xmh supports the unseen sequence.

Weeding Out Before You Read

Do you get a group of messages you don't want -- system status reports that usually aren't worth reading, test messages to yourself, and so on? You might want to remove all of them with a .maildelivery file, as explained in the Chapter Processing New Mail Automatically. The Example below shows how you can decide, though, before removing some or all of the batch. (The same trick works for refiling, printing, and so on -- not just for removing.)

Our system manager and I get status reports from uucp. I ignore them unless he's out of the office. This Example shows how I delete them quickly:

Example: Finding and handling a group of messages quickly

    % inc
    Incorporating new mail into inbox...
     155+ 01/09 uucp               uu-status<<LCK..cuZ2: 23283 LCK..cuZ3
        ...
     189  01/09 Tim O'Reilly       New edition of MH & xmh<<How are the
    % pick -from uucp -seq temp cur-last
    12 hits
    % scan temp
     155+ 01/09 uucp               uu-status<<LCK..cuZ2: 23283 LCK..cuZ3
        ... more messages from uucp...
    % rmm temp
    
First I find the messages with pick and store them in the temp sequence. (I use pick cur-last because that'll be all the messages inc brought in. As the Section Messages You Haven't Read explains, pick unseen would check the same messages -- though it might also include older messages I hadn't read yet.) A quick review with scan (and maybe show on a few) makes sure there's nothing I need to see. So, I remove the messages. There's more about this in the Sections Find and Specify with scan, pick, Ranges, Sequences and Storing Message Numbers in MH Sequences.

What if I decide not to remove one of the messages in that temp sequence? I can use mark -delete to take the message out of the sequence before I run rmm.

Where's the Next Message?

In the previous Example, I removed a group of messages without paying much attention to the message numbers. How could I read the first message that I didn't delete?

Here's the trick:
    % show cur:1
    
In MH, cur has the current message number, even if it's been deleted. The :1 is a range with one message in it -- your online mh-sequence(5) manual page has details. Of course, ranges usually have more than one message -- such as first:10, the first ten message numbers in the folder. But there's nothing wrong with cur:1 -- it means "up to one message in the range beginning with the current message." If the current message doesn't exist, MH automatically finds the next message number in the folder.

If that command is too cryptic to remember, you might want to stick it in a shell alias or function named something like nx. Then you can use nx to read the current or next message, whichever.

Changing Showproc for Viewing, Printing, and Editing

By default, MH show uses a pager (a screen-by-screen file viewer, like more(1)) to display the message on your terminal. In version 0.21 and above of nmh, the default is mhl, which formats the message and then (by default) uses a pager. To use a different viewer, like the program called less (which comes in the MH distribution), use the -showproc switch (or put it in your MH profile):

    % show -showproc less
    
If you like the less viewer or any other file viewer, you can make that viewer the default for all messages you read. If you aren't using mhl as your showproc, you can choose the viewer with an entry like this in your MH profile:
    showproc: less
    
If you are using mhl as your showproc, though, you should choose your pager by setting the moreproc.

Before show starts the showproc, it prints a header line with the folder name and message number:

    (Message inbox:24)
    
Usually, that's convenient. Sometimes it isn't. For example, when you're printing a message that fits onto a page exactly, the extra header line can make the page too long. The UNIX pr(1) program does that kind of message formatting. It formats a file for printing, with a header and page number, one message per page. By default, pr output goes to the terminal, not the printer. But you can use a standard UNIX pipe to send output to your printer program (often called lp or lpr). For example, here's how to print the last three messages, formatted with pr, on the lpr printer:
    % show -noheader -showproc pr last:3 | lpr
    
The -noheader switch tells show not to output (Message folder:Number). Of course, that command line is pretty long. A shell alias or function can shorten it to something like:
    % msgpr last:3
    
The Section Custom Printing: showpr shows a shell program that does even more.

If you need to edit a message you've received from someone else, the show command can do that too! Just set your showproc to be...a text editor. The mhedit command version makes this convenient.

Setting the showproc doesn't work the same way for multipart MIME messages. The showproc may be run several times, once for each part, on temporary copies of the parts. (There are details in the Section Showing MIME Messages.) Even a single-part MIME message may still need to be decoded before you can print it. There are two fairly simple ways to print MIME messages:

CAUTION: Some graphic file formats may contain commands that can be dangerous security holes. For instance, PostScript files can hold commands that can change printer settings -- or even delete other files! If you get a PostScript or other interpreted file from someone you don't trust, be careful.

Using mhl

A very useful showproc for viewing on the terminal is called mhl. It's an MH program that's designed for formatting mail messages. Section mhl explains how to customize mhl output, but a lot of people just use the default mhl settings.

mhl is the default showproc in nmh version 0.21 and above. If you aren't using it, try it yourself -- compare plain show in the first example below to show -showproc mhl in the example after it. (If you are using mhl, you can disable it temporarily with a command like show -showproc more, which uses the pager more to display the message.)

Example: Showing a message without mhl

    % show
    (Message inbox:14)
    Received: by mysun.xyz.edu (5.54/ACS)
            id AA22457; Mon, 09 Jan 1995 10:32:37 EST
    Received: from cliff.xyz.edu by asun.xyz.edu (4.1/CNS)
            id AA00488; Mon, 09 Jan 1995 10:24:44 EST
    Message-Id: <9501091524.AA00488@asun.xyz.edu>
    Received: by cliff.xyz.edu (4.1/SMI-4.0)
            id AA00220; Mon, 09 Jan 1995 10:24:42 EST
    To: jdpeek@mysun.xyz.edu, nancyp@hersun.xyz.edu
    To: ed@hissun.xyz.edu
    Subject: X Terminal Presentation/Demonstration next week; be there, please
    Date: Mon, 09 Jan 1995 10:24:39 -0500
    From: "Wilbur, Orville" <owilbur@asun.xyz.edu>

    Vince Molino from NAC Corp. will give a short presentation
        ...
    
Example: Showing a message with default mhl formatting
    % show -showproc mhl
    (Message inbox:14)
     -- using template mhl.format --
    Date:    Mon, 09 Jan 1995 10:24:39 EST
    To:      jdpeek@mysun.xyz.edu, nancyp@hersun.xyz.edu,
             ed@hissun.xyz.edu

    From:    "Wilbur, Orville" <owilbur@asun.xyz.edu>
    Subject: X Terminal Presentation/Demonstration next week; be
         ***there, please
        ...
    
Unless your system has a different default or you customize it, mhl does what you saw in the second Example: nmh has made some changes to the default mhl formatting. Some changes are subtle -- like decoding any encoded international (non-ASCII) characters in the From: and Subject: fields. The obvious changes are that you'll get a blank line instead of the line "using template mhl.format", and there isn't a blank line before the From: field.
NOTE: When mhn and mhshow show MIME messages with mhl, they split the message into header and body parts; the parts are shown separately. The techniques in this section don't apply directly to MIME mail. There's more information in the Section Showing MIME Messages.

To use mhl on a single message, give it as the showproc on a command line:

    % show -showproc mhl
    
mhl is the default showproc in nmh-0.21 and above. If you use MH or earlier versions of nmh and you like mhl, you can use it to show all messages by putting this entry in your MH profile:
    showproc: mhl
    
Or you can add separate entries for individual mail-showing programs:
    show: -showproc mhl
    next: -showproc mhl
    prev: -showproc mhl
    
If mhl is your default showproc, you can override that default temporarily by typing the name of a different showproc on the command line:
    % show -showproc more
    % show -showproc pr 3-7 | lpr
    
mhl uses your moreproc to page through a message that's longer than the screen (see the manual page for all the conditions; it's pretty complex). The moreproc is typically more or less. You can choose a different pager than the system default by adding an entry to your MH profile:
    moreproc: mypager
    
mhl reads a format file that sets the appearance of your messages. The default format file is called mhl.format and is in the system MH library directory or nmh etcetera directory. You can copy the system mhl.format file into your MH directory and customize it. For example, to copy it and edit it with vi in MH:
    % cd Mail
    % cp /usr/local/lib/mh/mhl.format .
      (...or, in nmh, cp `mhparam etcdir`/mhl.format .)
    % vi mhl.format
    
The next example shows the message above with my customized mhl.format file and showproc: mhl in my MH profile:

Example: Showing a message with customized mhl formatting

    % show
    (Message inbox:14)
     -- using Jerry's mhl.format template --
    Date:    Mon, 09 Jan 1995 10:24:39 EST
    From:    "Wilbur, Orville" <owilbur@asun.xyz.edu>
    To:      jdpeek@mysun.xyz.edu, nancyp@hersun.xyz.edu,
             ed@hissun.xyz.edu
    Subject: X Terminal Presentation/Demonstration next week; be
          ***there, please

    Vince Molino from NAC Corp. will be giving a short presentation
        ...
    
To make your own mhl.format file, see the Section Default mhl Format File for show.

Without a showproc

To display a message exactly as it was received, with no formatting or pagination, use the -noshowproc switch. MH will display the message with cat(1). This is one way to see encoded MIME messages: if you use -noshowproc, show won't run mhn or mhshow. (In nmh, you can also use the -nocheckmime switch to prevent MIME processing, but get other normal processing.)

Of course, you can pipe the output of show -noshowproc to another program -- for instance, a separate pager like less(1), or a program like od -c or (on some systems) cat -v that displays "unprintable" characters. (The C shell alias showv sends output to a pager.) You can also use the shell's > and >> operators to redirect show output into a file.

Multiple MH Sessions

By default, MH information like the current folder, sequences in each folder, and default options (from the MH profile) are shared between all your MH sessions. If you're logged into the same host more than once, or if you're logged into several hosts that share the same home directory, changes in one MH session will affect the others. For instance, if you type folder +foo in one window, the current folder and message in all the other windows will change. If you show a message in one window, you can forward it from another window by simply typing forw because the current folder and message will be the same in the other window. If you log out and log in later, the current folder and message are preserved.

That may not always be what you want! And it's a real surprise to people who have used monolithic user agents. If you don't want information to be shared between MH sessions, or kept after you log out, you can make separate context, sequence or MH profile files. The MH sessions that use separate copies of some or all of those files will be independent. Then you can do things like browsing through the messages in one folder while you remove messages from another folder; you don't need to constantly type folder-changing commands. This is also a way to stop accidental interactions between a standard MH session and a session with an MH front-end like xmh; otherwise, changing the current folder or message from MH without telling the front-end about the change can cause some real problems.

The Figure Important parts of a UNIX filesystem shows the parts of a UNIX filesystem that MH uses. Three files control the MH session:

Setting up a separate MH session is usually as simple as making a temporary context file. The next Example shows how to open a second window and work in a second folder with the C shell:

Example: Separate MH sessions with different current folders

    projects/beta folder        summaries folder

    % scan +projects/beta       % setenv MHCONTEXT /tmp/myctx$$
      ...scan listing...        % folder +summaries
    % show 27                     summaries+ has 1540 messages (  1-1826)
    (Message projects/beta:27)  % show last
      ...message appears...     (Message summaries:1826)
    %   ...                     ...message appears...
                                     ...
                                % unsetenv MHCONTEXT
                                % rm /tmp/myctx$$
    
The context filename can be any absolute pathname. I picked a temporary file, in /tmp, with a unique name that includes the shell's process ID number (from the $$ shell variable). That name will be different in every shell running on a system. If you want to keep the same context, session-to-session, you should choose a filename somewhere else -- in your MH directory, for instance. If several people share the same account, you could make context files named context.carol, context.jake, and so on.

Changing the context file doesn't affect public sequences in a folder. If two people are working in the same folder, or you have two windows open on a folder, changing the current message in one session may cause grief in the other session. So, if the account isn't already set up to use private sequences, you can make one or both sessions use them. To do this, make an empty mh-sequences: entry (with no filename after it) in the MH profile. If you want one session to use public sequences, and another to use private sequences, make a copy of the MH profile and put an empty mh-sequences: entry in the copy. The next example shows that for the Bourne shell (and Korn shell, bash, etc.):

Example: A second session with different current folder and sequences

    $ cd
    $ cp .mh_profile /tmp/profile$$
    $ MH=/tmp/profile$$ MHCONTEXT=/tmp/context$$
    $ export MH MHCONTEXT
    $ emacs $MH
        ...edit temporary profile, add empty mh-sequences: entry
    $ show some-message +some-folder
    
In the Example above, the new context file won't have any sequences defined when you start. (Remember, the empty mh-sequences: entry means that sequences are stored in the context file.) If you have public sequences defined that you'd like to copy to the second session, you can copy the .mh_sequences file from the folder into your new context file. But the two file formats are different. A sequence in the .mh_sequences (public sequences) file looks like this:
    urgent: 2 4 9 16-19
    
A private sequence in the context file contains the folder pathname. Here's an example of the urgent sequence for the project folder:
    atr-urgent-/home/andy/Mail/project: 2 4 9 16-19
    
As you copy the sequences, you need to change the label at the beginning of each entry. Be careful not to break or truncate long entries. Worse, the format of public and private sequence files isn't documented (as far as I can tell), so it could change. If you do this often, you'll want a little Perl script to do the conversion automatically. And, when you're done in the private session, do you want to copy the sequences back to the folder's public sequence file? Maybe you should have defined a different public sequence filename in the temporary MH profile:
    mh-sequences: sequences.temp
    
As you can see, there are lots of possibilities. We're getting beyond the scope of this chapter. By understanding the principles in this section, though, you can do almost anything you need to do in multiple MH sessions.

Custom Printing: showpr

You can print your mail messages like this (assuming your printer program is named lpr), but all the messages will be run together:

    % show 23 24 29 | lpr
    
Or, as the Section Changing Showproc for Viewing, Printing, and Editing shows, you can use pr(1) to make simple headers (with the folder and message number), to make page numbers, and to start each message on a new page:
    % show -showproc pr 23 24 29 | lpr
    
The showpr program, in this book's online archive, lets you do more. It can use mhl to clean up each message before printing. You can customize the page heading -- to include the message subject, for instance. And you can pass options to pr to tell it how to format your message. You can store default showpr options in your MH profile.

You can use mh-format strings on the showpr command line -- like the ones you'd give to the scan command.

Here are some examples. Some of these might look pretty complicated to type just for printing a message. But remember that you can store any set of options as defaults in your MH profile:

Finally, a note about mhl. You can make an mhl format file named mhl.showpr and put it in your MH directory (like /yourMHdir/mhl.showpr). If you do, and if you use the -mhl option, then showpr will format your messages with mhl -form mhl.showpr. Otherwise, the -mhl option uses the standard mhl.format file.

Here's how to set up showpr.

Showing Multiple Messages

When you give show more than one message number, things work a little differently:

    % show 1-5
        ...
    
By default -- except with MIME messages -- show hands each message separately to your pager program. When your showproc is a pager like more or less, your pager's "next file" command (like :n) will skip to the next message, Of course, you can also quit in the middle of the messages with your pager's "quit" command -- like q in more and less.

When you show more than one message at a time with mhl as your showproc, the messages will be shown in a stream:

    % show 1825 1826
    >>> inbox:1825

     -- using template mhl.format --
    Date:    Tue, 10 Jan 1995 15:24:39 EST
        ...
    >>> inbox:1826

     -- using template mhl.format --
    Date:    Wed, 11 Jan 1995 02:29:03 PST
        ...
    
This surprises people who've just started using mhl because the "next file" command in their pager program (like :n in more and less) doesn't skip to the next message anymore. You can work around the problem by using your pager's search command to find the message-number marker at the top of the next message. Searching for >>> may be enough. If messages contain that string, though, you can be more exact. For instance, if you're reading mail from the inbox folder -- as in the example above -- use the search command:
    /^>>> inbox:
    
and repeat it, using the pager's n command, to go to each following message.