MH & nmh: Email for Users & Programmers

May, 2006

Versions of scan

Format files and message ranges make the scan command really flexible, and the next two examples should get you started on custom versions that do just what you want. Beginning with MH 6.7, scan lets you scan files such as your system mailbox. This section shows you how to scan your new (unincorporated) mail.

Scanning Message Ranges: cur, c10, l5, etc.

I have some folders with a lot of mail in them. Two of the commands I use the most are scan cur:-10 cur:10 (scan the current message, the previous nine and the next nine -- handy when I'm looking through new mail) and scan -reverse last:5 (scan the last five messages in reverse order -- great for finding my newest mail and Fcc:'s of messages I just sent). These are perfect for versions of scan -- they have short names because I use them so much.

For example, to scan the current message (and change folder to project):

    % cur +project
      24+ SENT: 19Jan  CHARS: 1068
        FROM: Raymond LaPlante <ray@phobos.spacey.com>
          TO: Al Bok <al@phl.ph.com>, zot!ant@uunet.uu.net
        SUBJ: Update on my research
    
To make c10, cur, l5, or whatever you choose as versions of cur, see the Section Making a New Command Version. To make aliases or functions, see the Section Writing Command Versions as Aliases or Functions.

Then, add entries like the following to your MH profile -- or add the arguments to your alias or function. Of course, you don't have to use the same names or switches shown here:

    c10: cur:+10
    cur: cur -form scan.more -width 235
    l5: -reverse last:5
    n20: cur:-10 cur:10
    
For cur:, I used the scan.more file.

Scan and Show Size of Message: sscan

One of the standard scan format files is scan.size. Here's a version of scan called sscan that uses the format file every time. (You can do the same kind of thing with other format files.) For example:

    % sscan 2 3
       2  11/23 15326 Al Bok             Query about "repl -query"<<I ha
       3 -02/09   739 "Wilbur, Orville"  X Terminal Presentation/Demonst
    
To make sscan as a version of scan, see the Section Making a New Command Version. To make an alias or function, see the Section Writing Command Versions as Aliases or Functions.

Add the following entry to your MH profile, or add the arguments to your alias or function:

    sscan: -form scan.size
    
The Section MH Format Strings shows how to make custom scan formats. These format files are perfect to use in a new scan version.

Scan Messages Waiting: msgscan

msgscan is like msgchk, but it does more than tell you that you have mail waiting. It scans the new mail so you can decide whether to run inc now or wait. msgscan can use the scan.time format file (explained in the Section scan Format Files) to show you what time of day each message was sent. Or, you can use a scan.msgscan file, shown below, to get more of the From: (or Sender: or Apparently-From:) field, as well as the Subject:.

NOTE: msgscan only works with the scan -file switch in MH 6.7 and later. Earlier versions of scan don't have it.

Here's an example -- with a couple of msgchk commands:

    % msgchk
    You have new mail waiting; last read on Mon, 09 Jan 1995 20:49:54 EST
    % msgscan
       1  01/10 21:54EST To:al@phlabs.ph.co New MH feature<<Al, scan is
       2  01/10 21:13CST Al Bok             Re: New MH feature<<I scann
    % msgchk
    You have old mail waiting; last read on Tue, 10 Jan 1995 09:00:05 EST
    
The first msgchk shows that there's mail to read. Running msgscan tells that there are two messages waiting; one is a message you sent last night, the other is a reply. Another msgchk calls your mail "old" and says that you've "read" the mail. That's because msgscan reads your system mailbox directly. But the mail is still there, like before; msgscan just changes the mailbox file's last-access time when it reads for new mail.

With the scan.msgscan file, the output looks like this:

    % msgscan
    From: "Emma H. User" <ehuser@phlabs
    Subject: New MH feature
    -------------------
    From: Al Bok <al@phlabs.ph.com>
    Subject: Re: New MH feature
    -------------------
    
My scan.msgscan file cuts off the first line at 35 characters. Your version doesn't have to.

The steps to make your own msgscan are:

  1. Make msgscan as a version of scan (see the Section Making a New Command Version) or as an alias or function (see the Section Writing Command Versions as Aliases or Functions).

    Add an entry like one of the two below to your MH profile -- or add the arguments to your alias or function. Be sure to replace username with your own username and fix the pathname for your system mailbox:

          msgscan: -file /usr/spool/mail/username -form scan.time
          msgscan: -file /usr/spool/username -form scan.msgscan -width 120
          
  2. If you're using the msgscan that uses the scan.msgscan format file, put the file below into your MH directory. You can also get it from the book's online archive. It's in examples/mh/Mail/scan.msgscan.)
          %<{from}From: %35{from}%|%<{sender}Sender: %35{sender}%|\
          Apparently-From: %35{apparently-from}%>%>\n\
          %<{subject}Subject: %{subject}\n%>\
          -------------------
          

Get Message Number List: msgnums

There are times when you want a list of the message numbers from a folder: when you're using a shell loop, for example. A loop like the one below won't work because the shell doesn't understand MH message number ranges and sequences. You want to print each message, one at a time:

    $ for num in 2-22 unseen:5                 ...not what you want
    > do show $num | printer -h "Message $num"
    > done
    
What you want is a command that will expand the MH ranges and sequences into individual message numbers. The loop needs to look like this:
    $ for num in 2 3 6 15 20 22 44 45 46 47 48 ...the effect you want
    > do show $num | printer -h "Message $num"
    > done
    
But you don't want to type in those message numbers -- or to have to figure out which message numbers in a range are valid. (As you can see, a range like 2-22 can have gaps in the message numbering.) The msgnums version of scan does what you want. It expands ranges and sequences into message numbers:
    $ for num in `msgnums 2-22 unseen:5`       ...the answer
    > do show $num | printer -h "Message $num"
    > done
    
The Section Working in an MH Directory has another example.

A lot of people use pick to make lists of message numbers. But, in my experience, msgnums runs faster than pick.

To make msgnums as a version of scan, see the Section Making a New Command Version. To make an alias or function, see the Section Writing Command Versions as Aliases or Functions.

Add the following entry to your MH profile, or add the arguments to your alias or function:

    msgnums: -format %(msg)
    
In a shell alias or function, you'll have to put quotes around %(msg). Remember that scan options like -reverse in the MH profile will affect an alias or function.

This uses the MH format string %(msg), which gives the number of the current message.