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 which specifies how scan should generate the scan listing for each message; repl() uses a format file which 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 multi-letter 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 \ 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 non-zero (for integer-valued escapes), or non-empty (for string-valued escapes), then 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 non-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 non-empty |
| msg | integer | message number | |
| cur | integer | message is current | |
| size | integer | size of message | |
| strlen | string | integer | length of str |
| me | string | the 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 | the personal name of the address |
| mbox | string | string | the local part of the address |
| host | string | string | the domain part of the address |
| path | string | string | the route part of the address |
| type | string | integer | the 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 | the 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 | the 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. And 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.