# mhl

> NOTE: for users of the online version of this book: This chapter has a lot of examples followed by long explanations. To avoid jumping between the example and its explanation, it's a good idea to open a new browser window to show an example. (Check your browser's menu for a command like New Web Browser or Open in New Window.) Then, use the original browser to read the explanation while you view the example in the second browser window.

Let's start with the mhl message-formatting command. The Section Using mhl explains how to use it when you read messages. (Later in this chapter, you'll see how to use it with repl and forw.) If you use nmh version 0.21 or above, you're probably already using mhl because it's the default showproc. (If you aren't sure, run `mhparam` `showproc` and see if the answer is mhl.) If you're not already using mhl when you read your non-MIME messages, add an entry to your MH profile that sets mhl as the default:

        showproc: mhl

(If you want to, you can delete that entry after you're done with this section.) Now, when you use show, next, and prev, they will format non-MIME messages with mhl.

In the following examples, I'll show how to format a test message that has lots of fields in the header and some long, messy lines in the body. The test message is shown in the Example below. The text comes from the file /usr/dict/words. If your UNIX system has the file, it's a handy place to get text for testing. I used the UNIX head command to get the first 800 words from the file. The long (250-character) lines in the message body came from the UNIX fmt command. Mail the text with mhmail. The whole command is:

        head -800 /usr/dict/words | fmt -250 | mhmail "to-addresses" -cc "cc-addresses" -subject "A wordy message"

For normal-length lines of words, I would have left off the `-250`. Note that there are several versions of fmt (including one that formats disks!); one version wants to see `-l 250` and another version needs `-w 250`. Check your local version to be sure.

Before running show for the next Example, use repl -annotate and forw -annotate on the test message to add `Replied:` and `Forwarded:` header fields. The example uses show -noshowproc, which displays the message as is, without mhl -- so that you can see it exactly. The `head -26` shows the first 26 lines (if your UNIX doesn't have head, you can use the command `sed 26q` instead).

Example: Unformatted message with long lines in its body

        % show -noshowproc | head -26
        (Message test:21)
        Forwarded: Fri, 13 Jan 1995 03:41:35 -0500
        Forwarded: alex
        Forwarded: sullivan
        Replied: Wed, 11 Jan 1995 10:25:45 -0500
        Replied: Joe Doe <joe@foobar.ph.com>
        Return-Path: <al@phl.ph.com>
        Date: Mon, 09 Jan 1995 09:49:08 -0500
        Received: by asun.phl.ph.com (5.54/PHL)
                id AA27070; Mon, 09 Jan 1995 10:10:27 EST
        Received: by quack.phl.ph.com id AA26696
                Mon, 09 Jan 1995 09:49:08 EST
        Message-Id: <199501091349.AA26696@quack.phl.ph.com>
        From:  Al Bok <al@phl.ph.com>
        Reply-to: Joe Doe <joe@foobar.ph.com>
        To:   ehuser@asun.phl.ph.com,
                bob@phl.ph.com
        cc: liz@phl.ph.com
        Subject:  A wordy message

        Here's a message with some useless words and long
        lines for your tests.

        10th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th a Aaron ABA Ababa a
        back abalone abandon abase abash abate abbas abbe abbey abbo
        t Abbott abbreviate abc abdicate abdomen abdominal abduct Ab
        e abed Abel Abelian Abelson Aberdeen Abernathy aberrant aber

The Example above doesn't show all of the body. The body has some very long lines of words, as if the person who sent it forgot to press RETURN where he should have. The long lines were folded on my terminal screen, so I've shown them that way here, but they might have just "run off the right-hand edge" of your screen.

mhl reads a format file that tells how your messages should look. In these examples, you'll be making your own format files and storing them in your MH directory. First, here's a quick summary. Refer to it as you work through the examples.

An mhl format file has four types of entries (lines) in it:

        ;comment
        :cleartext
        variable(s)
        field:zero-or-more-variables

- An entry beginning with a semicolon (`;`) is a comment.
- An entry beginning with a colon (`:`) is clear text, and is output exactly as is. To output a blank line, use a colon with no text.
- An entry can set global variables that affect the formatting of the whole message.
- An entry beginning with a header field name, `field:`, tells mhl to display that field. You can override the global settings for a particular field by giving variables after the field name.

## Formatting the Message Header

Now that you've told show to use mhl, you're ready to make your own simple format file named mhl.test1. Change to your MH directory and use an editor (like vi) that doesn't rearrange or wrap your lines into paragraphs:

        % cd Mail
        % vi mhl.test1

Put these three entries into the file. Start each entry in column 1 (the left-hand edge of your screen):

        : -- test mhl format file #1 --
        To:
        Subject:

(You can also get this little file from the book's online archive. It's in examples/mh/Mail/mhl.test1.) When you use mhl and this format file to show a message, the entry that starts with a colon (`:`) will be displayed as is -- here it prints a reminder that you're using an mhl format file. The other two entries will display any fields that match.

Tell mhl to use your own format file with the show -form switch. For instance, here's how to show the message in the Example Unformatted message with long lines in its body with the format file called mhl.test1:

        % show -form mhl.test1
         -- test mhl format file #1 --
        To:    ehuser@asun.phl.ph.com,
                bob@phl.ph.com
        Subject:   A wordy message

You didn't ask to see the body of the message, so mhl didn't show it (we'll fix that). mhl did show the comment entry and the two fields you asked for.

Here's the next generation. Put this in a file named mhl.test2; you can get it from the book's online archive, as examples/mh/Mail/mhl.test2:

        : -- test mhl format file #2 --
        leftadjust,compwidth=4
        To:
        Cc:
        compwidth=10
        ignores=message-id,received,forwarded,return-path
        Extras:nocomponent

> NOTE: Be sure that there aren't any spaces (blanks) in the entries which have `compwidth=`, `ignores=`, or `Extras:`. These entries, which set mhl variables, are sensitive about extra spaces.

Format file 2 uses mhl variables. As you use the example and read the explanation below, refer to the Table mhl Variables. Here's how that same message from the previous Example Unformatted message with long lines in its body looks with this new format file:

        % show -form mhl.test2
         -- test mhl format file #2 --
        To: ehuser@asun.phl.ph.com,
            bob@phl.ph.com
        cc: liz@phl.ph.com
        Replied:  Wed, 11 Jan 1995 10:25:45 -0500
        Replied:  Joe Doe <joe@foobar.ph.com>
        Date:     Mon, 09 Jan 1995 09:49:08 -0500
        From:     Al Bok <al@phl.ph.com>
        Reply-to: Joe Doe <joe@foobar.ph.com>
        Subject:  A wordy message

Here's an explanation of mhl.test2:

- The entry `leftadjust,compwidth=4` sets two mhl variables. Variables affect the way that a message is displayed. You'll see that leftadjust removes blanks and tabs at the left-hand side of each word -- compare the `To:` fields displayed with this format file to the fields from format file 1, and you'll see how leftadjust tidies up the message.

  The leftadjust variable is on an entry which doesn't start with a field name. That makes leftadjust a global variable, which affects all the entries below it in the format file.

  The `compwidth=4` sets another variable (which is global, for the same reason leftadjust is). A compwidth setting of 4 means that the field text should be indented by four spaces -- in other words, it should start in the fifth output column. The `To:` and `cc:` fields are formatted that way and they line up neatly under each other.

- After the `To:` and `cc:` entries in the format file, the compwidth variable is reset to 10. From there on, the text of each field is indented by 10 (starts in column 11) -- the rest of the header fields start in column 11.
- In the last two entries, the global ignores variable and the `Extras:` "field" work together. The ignores variable holds a list of fields from the message that you don't want displayed. The usual fields you want to ignore are `Message-Id:` and `Received:`, though I've added two more to the list. You can type the ignores list in lowercase letters; it matches any combination of uppercase and lowercase in the message header. If there are too many fields for one entry, you can split the lists onto more than one ignores entries.

  The `Extras:` looks like a header field name, but it's a special entry. It means "output any field here if it hasn't been mentioned before." This format file has mentioned the fields `To:`, `cc:`, `Message-Id:`, `Received:`, `Forwarded:`, and `Return-Path:` -- any field in the message header which isn't in that list will be output by the `Extras:` entry.

  I don't want to see the literal string `Extras:` displayed on the screen when I show the message. Therefore, I've used the `nocomponent` variable on the same entry. Putting the variable on the same entry makes the variable local -- it only affects this one field.

  The `Extras:` entry is a special case, remember. Here, nocomponent means "don't print the string `Extras:.`" As you can see, the "extra" field names are still printed.

  If you don't use `Extras:`, only the fields you name (`To:`, `cc:`, etc.) will be displayed.

Before we start working with the message body, here's one more. Format file 3 uses the offset global variable and the component local variable. (You can also get this file from the book's online archive. It's in examples/mh/Mail/mhl.test3.)

        : -- test mhl format file #3 --
        compress,leftadjust
        Date:
        From:
        offset=2
        To:
        Cc:
        offset=0
        Subject:component="Subj"

This is how the message from the Example Unformatted message with long lines in its body looks with format file 3:

         -- test mhl format file #3 --
        Date: Mon, 31 Jul 89 09:49:08 EDT
        From: Al Bok <al@phl.ph.com>
          To: ehuser@asun.phl.ph.com,
              bob@phl.ph.com
          cc: liz@phl.ph.com
        Subj: A wordy message

See how neatly the fields are lined up? Look at the `Subject:` too, and compare it to the format file. To get some experience with the mhl summary in the Section Summary of mhl, please browse through it and use it to find out how format file 3 works. If you want more information, check your online mhl(1) manual page.

MH systems with MIME support have an mhl format file that formats MIME message headers. It's named mhl.headers. If you'd like to experiment with that file, copy it from the MH library directory and display a MIME message.

## Formatting the Message Body

As demonstrated in the previous section, mhl won't show the message body unless you ask for it. The mhl command treats the body a lot like a header field. To show the message body, put `Body:` in your format file. Format file 4 is simple, more for demonstration than to be useful. (But, to be complete, you can also get it from the book's online archive. Go to examples/mh/Mail/mhl.test4.)

        : -- test mhl format file #4 --
        To:
        Subject:
        Body:

Here's the first ten lines of the result:

        % show -form mhl.test4 | head
         -- test mhl format file #4 --
        To:    ehuser@asun.phl.ph.com,
                bob@phl.ph.com
        Subject:   A wordy message
        BodyHere's a message with some useless words and long lines
         for your tests.
        Body10th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th a Aaron ABA Ab
        aba aback abalone abandon abase abash abate abbas abbe abbe
        y abbot Abbott abbreviate abc abdicate abdomen abdominal ab

Notice that the message body starts just below the `Subject:` field, without a blank line to separate them. Also, because I didn't use the nocomponent variable, mhl has printed the word `Body` at the start of each line of the body. (The lines of the actual message body were longer than the screen. The mhl command adds the "field name" `Body` before it folds the long lines.)

The mhl command has automatically folded the body lines. That makes sure that I'll see all of each line, even if my terminal hadn't wrapped the long lines.

Let's clean up the body. Here's format file 5. (NOTE: Be careful when typing in three plus signs (`+++`) if you're using a modem; that's the escape sequence for many modems. You might type the first `+`, then press the space bar and BACKSPACE, and then the last `++`. Other ideas are typing two plus signs (`++`) or trying other characters (MH uses `***`). Or just get the file from the online archive -- at examples/mh/Mail/mhl.test5.)

        Messagename:nocomponent
        : -- test mhl format file #5 --
        To:
        Subject:
        :
        body:nocomponent,overflowtext="+++",overflowoffset=2

And here are the first 13 lines of the show output -- on the previous Example Unformatted message with long lines in its body again:

        % show -form mhl.test5 | head -13
        (Message test:21)
         -- test mhl format file #5 --
        To:    ehuser@asun.phl.ph.com,
                bob@phl.ph.com
        Subject:   A wordy message

        Here's a message with some useless words and long lines for
          +++ your tests.

        10th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th a Aaron ABA Ababa
          +++aback abalone abandon abase abash abate abbas abbe abb
          +++ey abbot Abbott abbreviate abc abdicate abdomen abdomi
          +++nal abduct Abe abed Abel Abelian Abelson Aberdeen Aber

In the format file, the colon (`:`) makes the blank line before the body. The local variables after `body:` tell it not to print the "field" name, what characters to mark the folded text with (`+++`), and how many spaces to put before the folded parts of the lines (two). The `Messagename:` entry prints a string with the folder name and message number -- again, you need the nocomponent variable to stop the field name from being printed.

Of course, most messages don't have lines that are too long. A message with normal-length lines wouldn't have all those plus signs (`++`) in it. If you never want long lines flagged, you can leave out the overflowtext and overflowoffset variables so that mhl will fold long lines without telling you about it.

The last format file in this section, mhl.body, is simple:

        width=10000
        body:nocomponent,overflowoffset=0

(You can also get this short file from the book's online archive. It's in examples/mh/Mail/mhl.body.) The `width=10000` is a dirty kludge that keeps mhl from breaking long body lines -- assuming that no line has more than 10,000 characters, that is. (RFC 822 requires lines less than 1,000 characters. Some messages may not follow RFC 822 specs. Still, 10,000 is probably a safe limit.)

This file might look useless, but it can be really handy. The Sections Copying a Message to a File and ReplyInsertFilter show two examples.

## Default mhl Format File for show

mhl reads a format file that tells how your messages should look. The default format file for show is called mhl.format. The default format file for forw is called mhl.forward. The repl command will also use an mhl format file with the repl -filter switch, but there's no default filename. You can copy the system mhl.format and mhl.forward files from the MH library directory into your MH directory and customize them. If files with those names exist in your MH directory, mhl and forw will use them instead of the system default files.

Let's take a quick look at the default mhl.format file shown in the Example below. (You can also get it from the book's online archive. It's in examples/mh/Mail/mhl.format.default.) Then we'll explore how you can customize yours.

> NOTE: In later versions of nmh, the default file is slightly different. See the explanation at the end of this section.

Example: Default mhl.format file and message formatted with it

        % cat mhl.format
        : -- using template mhl.format --
        overflowtext="***",overflowoffset=5
        leftadjust,compwidth=9
        ignores=msgid,message-id,received
        Date:formatfield="%<(nodate{text})%{text}%|%(pretty{text})%>"
        To:
        cc:
        :
        From:
        Subject:
        :
        extras:nocomponent
        :
        body:nocomponent,overflowtext=,overflowoffset=0,noleftadjust
        % show -showproc mhl
         -- using template mhl.format --
        Date:    Mon, 31 Jul 89 09:49:08 EDT
        To:      ehuser@asun.phl.ph.com, bob@phl.ph.com
        cc:      liz@phl.ph.com

        From:    Al Bok <al@phl.ph.com>
        Subject: A wordy message

        Forwarded: Sun, 04 Feb 90 03:41:35 -0500
        Forwarded: alex
        Forwarded: sullivan
        Replied: Sat, 16 Dec 89 10:25:45 -0500
        Replied: Joe Doe <joe@foobar.ph.com>
        Return-Path: <al@phl.ph.com>
        Reply-to: Joe Doe <joe@foobar.ph.com>

        Here's a message with some useless words and long lines for
        your tests.

        10th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th a Aaron ABA Ababa
        aback abalone abandon abase abash abate abbas abbe abbey ab
        bot Abbott abbreviate abc abdicate abdomen abdominal abduct
         Abe abed Abel Abelian Abelson Aberdeen Aberdeen Abernathy
                ...

We haven't looked at the formatfield variable in the `Date:` entry. It uses MH format strings to give you more control of the way a field is displayed. Briefly, the format string in the Example above says that if MH doesn't recognize the format of the date in the `Date:` field, the field should be output as is; otherwise, it should be reformatted into an easy-to-read date style. There's another example and more information in the mhl.forward file; see the Section forw Filter Files.

I'd do six things to change that default format file:

1. Change the first entry to show that it's not the system default mhl.format file.
2. Add more fields to the `ignores=` entry (or add another; you can use more than one `ignores=` entry). For example, I'm never interested in seeing the `Return-Path:` or `Reply-to:` fields (because repl will use them when I need them).
3. Show the `From:` field before the `To:` field.
4. If a message doesn't have a `To:` field, the sendmail MTA will add a `Apparently-to:` field with the envelope address. I want to see that, too, so I've added an `Apparently-to:` entry.
5. I don't like all the blank lines that the mhl.format file adds, especially when there are no `extras:`. I'd get rid of a couple of colons.
6. Some versions of MH leave a blank line after the `Date:` field. So I've added compress to the `Date:` entry. That removes any stray newline character and gets rid of the blank line.

My mhl.format and the previous message formatted with it are in the next Example. If you don't like the default mhl.format, maybe this (and the test format files from previous sections) will help you fix yours. This revised file is in the book's online archive at examples/mh/Mail/mhl.format.revised.

Example: Revised mhl.format file and same message reformatted

        % cat mhl.format
        : -- using Nutshell mhl.format template --
        overflowtext="***",overflowoffset=5
        leftadjust,compwidth=9
        ignores=msgid,message-id,received,return-path,reply-to,forwarded
        Date:compress,formatfield="%<(nodate{text})%{text}%|%(pretty{text})%>"
        From:
        To:
        Apparently-to:
        cc:
        Subject:
        extras:nocomponent
        :
        body:nocomponent,overflowtext=,overflowoffset=0,noleftadjust
        % show -showproc mhl
         -- using Nutshell mhl.format template --
        Date:    Mon, 31 Jul 89 09:49:08 EDT
        From:    Al Bok <al@phl.ph.com>
        To:      ehuser@asun.phl.ph.com, bob@phl.ph.com
        cc:      liz@phl.ph.com
        Subject: A wordy message
        Replied: Sat, 16 Dec 89 10:25:45 -0500
        Replied: Joe Doe <joe@foobar.ph.com>
        Here's a message with some useless words and long lines for
        your tests.

        10th 1st 2nd 3rd 4th 5th 6th 7th 8th 9th a Aaron ABA Ababa
        aback abalone abandon abase abash abate abbas abbe abbey ab
        bot Abbott abbreviate abc abdicate abdomen abdominal abduct
         Abe abed Abel Abelian Abelson Aberdeen Aberdeen Abernathy
                ...

Why not try it? Make your own mhl.format format file for show now. Use the information in the early parts of this chapter to display your messages the way you'd like to.

Recent versions of nmh have some changes to the mhl.format file:

1. The title line "using template mhl.format" is just a blank line.
2. The `ignores=` line lists some MIME header fields.
3. There's no blank line after `cc:`.
4. Most important, the `From:` and `Subject:` header fields have the decode variable. This decodes any RFC 2047 encoding in those fields. For example, this changes a `Subject:` field encoded as `Un =?iso-8859-1?Q?d=EDa_dif=EDcil?=` into `Un día difícil`.

   mhl only decodes these fields if your terminal can natively display the character set used in the encoding. You should set the MM_CHARSET environment variable to your native character set if it is not US-ASCII.

## forw Filter Files

The Section Formatting Forwarded Messages explains how you can use mhl to filter messages you send with the forw command. The default forw filter file is named mhl.forward. Filter files for forwarded messages are almost the same as format files for displaying messages. This section looks at the default filter file and shows another filter file used for a special application.

> NOTE: At first, it's easy to get confused about what formats the header of the forwarded message itself, and what formats the messages you're forwarding. It might help you to think of a paper envelope with some paper messages inside. The format of the envelope (the forwarded message header) is set by the template draft file (like forwcomps). The format of the messages inside the envelope is controlled by a filter file (like mhl.forward).

> (To add to the confusion, forw -digest uses an mhl format file named digestcomps. It creates the message header and the first part of the body.

Let's start with mhl.forward, as shown in the Example below. (You can also get this file from the book's online archive. It's in examples/mh/Mail/mhl.forward.) Messages you forward with this filter file will have the `Date:`, `From:`, `To:`, `cc:`, and `Subject:` fields from the original message. Other fields will be skipped. Each forwarded message will be broken into lines less than 80 characters wide.

Example: mhl.forward: Default forw filter file

        width=80,overflowtext=,overflowoffset=10
        leftadjust,compress,compwidth=9
        Date:formatfield="%<(nodate{text})%{text}%|%(tws{text})%>"
        From:
        To:
        cc:
        Subject:
        :
        body:nocomponent,overflowoffset=0,noleftadjust,nocompress

The formatfield variable uses an MH format string. The format string in the Example above says that if MH doesn't recognize the format of the date in `Date:` field, the field should be output as is; otherwise, it should be reformatted into an official RFC 822 date style. The contents of the date string, without the `Date:` label, are available in the `%{text}` component escape. You can change the appearance of the `Date:` field by changing the format string.

If you haven't used a forw filter file yet, this is a good time to experiment with mhl.forward.

The second Example below shows a filter file for a company that tracks its product bug reports with MH mail. A series of messages about a particular bug are forwarded together with this special formatting. You probably won't want to format your forwarded messages this way, but this is a simple example of the sort of customizing you can do. For example, the messages about the company's VMX2244 product might be forwarded as the next Example shows.

Example: Four messages forwarded with mhl.prodsumry

        % scan +vmx2244
           1+ 06/20 Ed Bledsoe         Kimzit broken in VMX2244<<Our
           3  06/21 To:Field Service   bug fix: VMX2244 Kimzit<<Ed B
           4  06/27 Ed Bledsoe         Kimzit fix for VMX2244<<Jane
        % forw all -filter mhl.prodsumry
        To: bugboss@bigcorp.com
        cc: imah, edb
        Subject: Bug Summary: VMX2244 Kimzit
        --------

        ------- Forwarded Messages

        Date:    Monday 6/20/94 13:35 MDT
        Msgid:   <FCC5C552B13F201F9E@mysun.bigcorp.com>
        From:    Ed Bledsoe <edb@bigcorp.com>
        To:      bugtrack@bigcorp.com
        Subject: Kimzit broken in VMX2244

        Our customer Jane Bluenose in Snow Flow, Alaska reported the
                ...

        ------- Message 2

        Date:    Tuesday 6/21/94 10:45 MDT
        Msgid:   <900620100423@avax.bigcorp.com>
        From:    Ima Hacker <imah>
        To:      Field Service <fse@bigcorp.com>
        Subject: ******** bug fix: VMX2244 Kimzit ********

        Ed Bledsoe wrote in <FCC5C552B13F201F9E@mysun.bigcorp.com>:
                ...

The forwarded messages have some special formatting:

- The `Date:` fields are in a new format.
- The `Message-Id:` fields are included and labeled `Msgid:`.
- The `cc:` fields, if there was one, isn't included.
- The `Subject:` field in the second message has asterisks around it.

That's all done by the mhl.prodsumry filter file in the Example below. Line numbers to the left of each line (like `12>`) are not part of the file; they are for reference only. (You can also get this file, without line numbers, from the book's online archive. It's in examples/mh/Mail/mhl.prodsumry.)

Example: mhl.prodsumry: forw filter file

         1> width=80,overflowtext=,overflowoffset=10
         2> leftadjust,compress,compwidth=9
         3> ; Reformat date into company standard:
         4> Date:formatfield="%<(nodate{text})%{text}%|\
         5>     %(weekday{text})\
         6>     %(mon{text})/%(mday{text})/%(void(year{text}))%02(modulo 100)\
         7>     %(hour{text}):%02(min{text}) %(tzone{text})%>"
         8> Message-Id:component=Msgid
         9> From:
        10> To:
        11> ; If subject contains "bug fix", put stars around it:
        12> Subject:formatfield="%(void{text})\
        13>     %<(match bug fix)******** %{text} ********%|%{text}%>"
        14> :
        15> body:nocomponent,overflowoffset=0,noleftadjust,nocompress

Let's look at the filter file:

- Lines 1-2 came from mhl.forward. They set global variables that control the overall formatting.
- Because line 3 starts with a semicolon (`;`), it's a comment. Lines 4-7 format the `Date:` field. MH format strings like the one in this formatfield variable are explained in the Section MH Format Strings. As you read this description, you might compare lines 4-7 of the Example above, mhl.prodsumry: forw filter file, to the `Date:` fields shown in the previous Example, Four messages forwarded with mhl.prodsumry.

  The formatfield variable uses MH format strings to control the format of a particular field. The text from that field is available in the {text} escape -- look for `{text}` in the format string.

  There's an overall if-then-else test starting on line 4 that checks the format of the message `Date:` field. If MH can't parse the date, it's output as is by the end of line 4. If MH can parse the date, the format on lines 5-7 is used. This format outputs the day name; the month, date, and year separated by slashes (`/`); the hour and minute; and the time zone name. The last part of line 6 outputs a two-digit year in the latest versions of MH, which use four-digit years by default. The `02` before the (min) function formats the minutes to have two digits with a leading zero if needed. MH date parsing is a powerful feature; the Section The scan.dateparse Format File explains it.

  To continue a format entry, end the line with a backslash (`\`).

- Line 8 outputs the original `Message-Id:` field with a different name.
- Lines 12-13 use another formatfield variable. This one tests the message `Subject:` field. It stores the subject string in an internal register, then tests its contents with `(match bug fix)`. If the string contains the phrase `bug fix`, it's output with asterisks around it. Otherwise, the subject is output as is.

That's a quick example of what you can do with forw filter files. Remember that you won't always need MH format strings. When you do, read the Section MH Format Strings.

## Screen Size and moreproc

The mhl command tries to find the width and length of your screen.

Unless you tell it differently, mhl will fold lines just before the end of the screen. For instance, if your screen is 80 columns wide (most are), mhl will make message lines 79 characters wide. On these screens, any line with more than 79 characters will be folded.

As long as your UNIX system "knows" about your screen (through the termcap or terminfo entries, for example), then mhl should be able to find your screen size.

The `-width nn` switch and the `width=nn` global variable both tell mhl to ignore the screen width information it gets from UNIX. For example, `-width 40` on the command line or `width=40` in a format file set the screen width to 40 -- and mhl will make lines no more than 39 characters wide.

By default, the screen length (number of lines top to bottom) doesn't matter to mhl. That's because mhl uses a moreproc program to show your messages -- and the moreproc decides your screen size by itself, with no help from mhl. The default moreproc is the UNIX more program. This is the same program that show uses to display your messages, page by page, when it's not using mhl.

If you put the following entry in your MH profile, then mhl won't use the moreproc program:

        mhl: -nomoreproc

Instead, mhl will do its own paging. Then the screen length will matter -- and you can change the defaults, along with other mhl paging parameters. More on that in a minute.

First, though, here's a list that shows what MH does when you display a message in several different ways. This should help to clear up any mhl/moreproc confusion.

- The command show, without any mhl formatting, will give the message directly to the moreproc command. On Berkeley-type UNIX systems, the moreproc is usually the more program. If you're reading message 21 in inbox, the command executed is:

            more inbox/21

- The command show -showproc mhl or an entry like one of these in your MH profile:

            showproc: mhl
            show: -showproc mhl

  will give the message directly to mhl. Then mhl output is piped to the moreproc. The resulting command looks like:

            mhl inbox/21 | more

  (Actually, the show program has its own built-in version of mhl. The real command executed is simply `more`, with more's standard input coming from the show program. But I think the effect is easier to understand when shown as `mhl | more`. You can actually run this yourself with the real mhl program without running show at all.)
- If show is using mhl, but your MH profile has the entry:

            mhl: -nomoreproc

  then the command executed will be:

            mhl inbox/21

  and mhl will use its own internal paging routines.

If you want to experiment with mhl's internal pager, you'll need these two entries in your MH profile:

        showproc: mhl
        mhl: -nomoreproc

mhl has several command-line switches and global variables for its format files that control its built-in pager:

- The -clear switch and the clearscreen global variable both clear the screen before showing each page of a message. The -noclear switch and the noclearscreen global variable tell mhl not to clear the screen. The default is -noclear.

  If the output is not a tty (UNIX terminal) -- for instance, if you've redirected the output to a file -- the -clear switch outputs a formfeed CTRL-L character after each message.

- The -bell switch and the bell global variable both ring the terminal bell after showing each page of a message. The -nobell switch and the nobell global variable don't ring the bell. The default is -bell.
- The `-length nn` switch and the `length=nn` global variable both tell mhl to ignore the UNIX screen length information. For example, `-length 10` on the command line or `length=10` in a format file sets the screen length to 10 -- and mhl will stop after every ten lines.

When you're using mhl's built-in pager and the display pauses, press the RETURN key to see the next screenful. Other keys do other things -- see the mhl summary.

## Summary of mhl

Previous sections of this chapter introduced mhl by example. This section is a summary. (This section was adapted from the mhl(1) manual page.) This section has a Table, mhl Variables, that lists mhl variables and has cross-references to examples.

mhl is a formatted message listing program. It can be used as a replacement for more(1) (the default showproc). As with more, each of the messages specified as arguments (or the standard input) will be output.

Handling Multiple Files

If more than one message file is specified, the user will be prompted prior to each one. To begin output, press RETURN, which also clears the screen if appropriate -- or press the EOT key (usually, CTRL-D) which doesn't clear the screen. Your Interrupt key (usually, CTRL-C) will abort the current message and prompt for the next message (if any); the Quit key (usually, CTRL-\) will terminate mhl (without creating a core file).

Options, Switches

The -bell switch tells mhl to ring the terminal's bell at the end of each page. The -clear switch tells mhl to clear the screen at the end of each page (or output a formfeed after each message). The following list contains several things you should know about these options.

- Both of these switches (and their inverse counterparts -nobell and -noclear) take effect only if the MH profile entry `moreproc:` is defined but empty, and mhl is outputting to a terminal.
- If the moreproc entry is defined and non-empty, and mhl is outputting to a terminal, then mhl will cause the moreproc to be placed between the terminal and mhl (see the Section Screen Size and moreproc); the switches will be ignored.
- If the -clear switch is used and mhl's output is directed to a terminal, then mhl will find out how to clear by checking the TERM and TERMCAP environment variables.
- If the -clear switch is used and mhl's output is not directed to a terminal (e.g., a pipe or a file), then mhl will send a formfeed after each message.

To override the default moreproc and the profile entry, use the -moreproc program switch. Note that mhl will never start a moreproc if invoked on a hardcopy terminal.

The -length `length` and -width `width` switches set the screen length and width, respectively. These default to the values indicated by TERMCAP, if appropriate; otherwise they default to 40 and 80, respectively.

The default format file used by mhl is called mhl.format. mhl looks for that file first in the user's MH directory and next in the MH library directory. You can choose a different format file with the -form `formatfile` option.

Finally, the -folder `+folder` option sets the MH folder name, which is used for the `messagename:` entry described below. The environment variable mhfolder is consulted for the default value, which show, next, and prev initialize appropriately.

Overall Operation

mhl operates in two phases:

1. Read and parse the format file.
2. Process each message (file).

During phase 1, an internal description of the format is produced as a structured list. In phase 2, this list is walked for each message, outputting message information under the format constraints from the format file.

An mhl format file contains information controlling screen clearing, screen size, wrap-around control, transparent text, field ordering, and field formatting. Also, a list of fields to ignore may be specified, and a couple of "special" fields are defined to provide added functionality. Message output will be in the order specified by the order in the format file.

Each entry of an mhl format file has one of the formats:

`;comment`
`:cleartext`
`variable`[`,variable`...]
`field:`[`variable`,...]

An entry beginning with a `;` is a comment, and is ignored. An entry beginning with a `:` is clear text, and is output exactly as is. An entry containing only a `:` produces a blank line in the output. An entry beginning with `field:` defines the format for the specified header field, and finally, remaining entries define the global environment.

For example, the entry:

        width=80,length=40,clearscreen,overflowtext="***",overflowoffset=5

defines the screen size to be 80 columns by 40 rows, specifies that the screen should be cleared prior to each page, that the overflow indentation is 5, and that overflow text should be flagged with `***`.

The Table below lists all mhl variables and their arguments. Notes:

- If a variable (and its argument, if any) follows a field name, it applies only to that field. Otherwise, it applies to all fields.
- The whole format file is parsed before any output processing. So, if a variable is used in a global context (the variables with type "flag/G" below, such as clearscreen), the last global switch setting for a variable applies to the whole message.
- To specify the value of integer-valued and string-valued variables, follow their name with `=` (equal) and the value. Integer-valued variables are given decimal values, while string-valued variables are given arbitrary text bracketed by pairs of double quotes (`"`).
- If a value in the Type column is suffixed by "/G" or "/L", then its value is useful in a global-only or local-only context (respectively).

Table: mhl Variables

Variable (Type)
  Description
width (integer)
  Screen width or field width
length (integer)
  Screen length or field length
offset (integer)
  Amount (number of character positions or columns) to indent `field``:`
overflowtext (string)
  Text to use at the beginning of an overflow line
overflowoffset (integer)
  Amount to indent overflow lines
compwidth (integer)
  Amount to indent field text after the first line is output
uppercase (flag)
  Output text of this field in all upper case
nouppercase (flag)
  Don't uppercase
clearscreen (flag/G)
  Clear the screen prior to each page
noclearscreen (flag/G)
  Don't clear screen
bell (flag/G)
  Ring the bell at the end of each page
nobell (flag/G)
  Don't ring bell
component (string/L)
  Name to use instead of `field` for this field
nocomponent (flag)
  Don't output `field:` for this field
center (flag)
  Center field on line (works for one-line fields only)
nocenter (flag)
  Don't center
leftadjust (flag)
  Strip off leading whitespace on each line of text
noleftadjust (flag)
  Don't leftadjust
compress (flag)
  Change newlines in text to spaces
nocompress (flag)
  Don't compress
split (flag)
  Don't combine multiple fields into a single field
nosplit (flag)
  Combine multiple fields into a single field
newline (flag)
  Print newline at end of fields (default)
nonewline (flag)
  Don't print newline at end of fields
formatfield (string)
  Format string for this field (see below)
decode (flag)
  Decode text as RFC-2047 encoded header field (nmh only)
addrfield (flag)
  Field contains addresses
datefield (flag)
  Field contains dates

Other Format File Features

An entry of the following form specifies a list of fields that are never output:

        ignores=field,...

The entry `MessageName:` (case-insensitive) outputs the actual message name (file name) preceded by the folder name (if one is specified or found in the environment). The format is identical to that produced by the -header option to show.

The entry `Extras:` outputs all message header fields which weren't matched by explicit entries or included in the `ignores=` list. If a format file doesn't have an `Extras:` entry, it doesn't need an `ignores=` list because all non-specified fields will be ignored.

If the nocomponent variable is not specified, the field name will be output as it appears in the format file.

The variable formatfield specifies an MH format string (see the Section MH Format Strings and the mh-format(5) manual page). The flag variables addrfield and datefield, which are mutually exclusive, tell mhl to interpret the escapes in the format string as either addresses or dates, respectively.

By default, mhl does not apply any formatting string to fields containing address or dates (see mh-mail(5) for a list of these fields). Note that this results in faster operation since mhl must parse both addresses and dates in order to apply a format string to them. If desired, mhl can be given a default format string for either address or date fields (but not both). To do this, on a global entry specify: either the flag addrfield or datefield, along with the apropriate formatfield variable string.