mh-format(5mh)
Name
mh-format − format file for MH message system
Description
Several MH commands utilize either a format string or a format file during their execution. For example, scan() uses a format string that specifies how scan should generate the scan listing for each message; repl() uses a format file that directs it how to generate the reply to a message, and so on.
This reference page describes how to write new format commands or modify existing ones. You should not attempt this unless you are an experienced MH user.
A format string is similar to a printf() string, but uses multiletter escapes. When specifying a string, the usual C backslash characters are honored: \b, \f, \n, \r, and \t. Continuation lines in format files end with a backslach (\) followed by the newline character.
The interpretation model is based on a simple machine with two registers, num and str. The former contains an integer value, the latter a string value. When an escape is processed, if it requires an argument, it reads the current value of either num or str; and, if it returns a value, it writes either num or str.
Escapes are of three types: components, functions, and control. A component escape is specified as %{name}, and is created for each header found in the message being processed. For example, %{date} refers to the Date: field of the appropriate message. A component escape is always string valued.
A control escape is one of: %<escape, %|, and %>. These correspond to if-then-else constructs: if escape is not zero (for integer-valued escapes), or not empty (for string-valued escapes), everything up to %| or %> (whichever comes first) is interpreted; else, then skip to %| or %> (whichever comes first) and start interpreting again. A function escape is specified as %(name), and is statically defined. The following table lists the function escapes.
| Escape | Argument | Returns | Interpretation |
| nonzero | integer | integer | num is not zero |
| zero | integer | integer | num is zero |
| eq | integer | integer | num == width |
| ne | integer | integer | num != width |
| gt | integer | integer | width > num |
| null | string | integer | str is empty |
| nonnull | string | integer | str is not empty |
| msg | integer | Message number | |
| cur | integer | Message is current | |
| size | integer | Size of message | |
| strlen | string | integer | Length of str |
| me | string | User’s mailbox | |
| plus | integer | Add width to num | |
| minus | integer | Subtract num from width | |
| charleft | integer | Space left in output buffer | |
| timenow | integer | Seconds since the epoch |
When str is a date, these escapes are defined:
| Escape | Argument | Returns | Interpretation |
| sec | string | integer | Seconds of the minute |
| min | string | integer | Minutes of the day |
| hour | string | integer | Hours of the day (24 hour clock) |
| mday | string | integer | Day of the month |
| mon | string | integer | Month of the year |
| wday | string | integer | Day of the week (Sunday=0) |
| year | string | integer | Year of the century |
| yday | string | integer | Day of the year |
| dst | string | integer | Daylight savings in effect |
| zone | string | integer | Timezone |
| sday | string | integer | Day of the week known |
| 1 for explicit in date | |||
| 0 for implicit | |||
| −1 for unknown | |||
| clock | string | integer | Seconds since the epoch |
| rclock | string | integer | Seconds prior to current time |
| month | string | string | Month of the year |
| lmonth | string | string | Month of the year (long form) |
| tzone | string | string | Timezone |
| day | string | string | Day of the week |
| weekday | string | string | Day of the week (long) |
| tws | string | string | Official RFC 822 rendering of the date |
| pretty | string | string | A more user-friendly rendering |
| nodate | string | Date was not parseable |
When str is an address, these escapes are defined:
| Escape | Argument | Returns | Interpretation |
| pers | string | string | Personal name of the address |
| mbox | string | string | Local part of the address |
| host | string | string | Domain part of the address |
| path | string | string | Route part of the address |
| type | string | integer | Type of host |
| −1 for uucp | |||
| 0 for local | |||
| 1 for network | |||
| 2 for unknown | |||
| nohost | string | integer | No host was present in the address |
| ingrp | string | integer | Address appeared inside a group |
| gname | string | string | Name of the group (present for first |
| address only) | |||
| note | string | string | Commentary text |
| proper | string | string | Official RFC 822 rendering of the address |
| friendly | string | string | A more user-friendly rendering |
| mymbox | string | Address refers to the user’s mailbox | |
| formataddr | string | Print str in an address list |
The default format string for scan follows. This has been divided into several pieces for readability. The first part is:
%4(msg)%<(cur)+%| %>%<{replied}-%| %>
This means that the message number should be printed in four digits; if the message is the current message then a + is printed. If the message is not the current message, then a space is printed. If a Replied: field is present, a − is printed. If no Replied: field is present, then a space is printed. Next:
%02(mon{date})/%02(mday{date})
The hours and minutes are printed in two digits (zero filled). Next:
%<{date} %|*>
If no PN Date: field is present, then a * is printed; otherwise, a space. Next:
%<(mymbox{from})To:%14(friendly{to})
If the message is from me, print To: followed by a user-friendly rendering of the first address in the To: field.
%|%17(friendly{from})%>
If the message is not from me, then the From: address is printed. Finally:
%{subject}%<{body}<<%{body}%>
The subject and initial body are printed preceded by the string <<.
Although this seems complicated, this method is flexible enough to extract individual fields and print them in any format the user desires.
If the −form formatfile switch is given, scan will treat each line in the named file as a format string and act accordingly. This lets the user develop template scan listing formats. See /usr/new/lib/mh/scan.time, /usr/new/lib/mh/scan.size, and /usr/new/lib/mh/scan.timely for more details.