Mercurial > hg > Applications > mh
diff doc/mh-format.me @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/mh-format.me Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,531 @@ +.\" This file is automatically generated. Do not edit! +.\" @(#)$Id$ +.SC MH-FORMAT 5 +.NA +mh-format \- format file for MH message system +.SY +some \fIMH\fR commands +.DE +Several \fIMH\fR commands utilize either a \fIformat\fR string or a +\fIformat\fR file during their execution. +For example, +\fIscan\fR\0(1) uses a format string which directs it how to generate the +scan listing for each message; +\fIrepl\fR\0(1) uses a format file which directs it how to generate the +reply to a message, and so on. + +Format strings are designed to be efficiently parsed by \fIMH\fR which +means they are not necessarily simple to write and understand. +This means that novice, casual, or even advanced users of \fIMH\fR should +not have to deal with them. +Some canned scan listing formats are in +/usr/local/mh/lib/scan.time, /usr/local/mh/lib/scan.size, and /usr/local/mh/lib/scan.timely. +Look in /usr/local/mh/lib for other \fIscan\fR and \fIrepl\fR format files +which may have been written at your site. + +It suffices to have your local \fIMH\fR expert actually write new format +commands or modify existing ones. +This manual section explains how to do that. +Note: familiarity with the C \fIprintf\fR routine is assumed. + +A format string consists of ordinary text, and special +multi-character \fIescape\fR sequences which begin with `%'. +When specifying a format 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. +To put a literal `%' or `\\' in a format string, use two of them: +`%%' and `\\\\'. +.\" talk about syntax first, then semantics +There are three types of \fIescape\fR sequences: +header \fIcomponents\fR, built-in \fIfunctions\fR, and flow \fIcontrol\fR. + +A \fIcomponent\fR escape is specified as `%{\fIcomponent\fR\^}', +and exists for each header found in the message being processed. +For example `%{date}' refers to the \*(lqDate:\*(rq field of the appropriate +message. +All component escapes have a string value. +Normally, component values are compressed by +converting any control characters (tab and newline included) to spaces, +then eliding any leading or multiple spaces. +However, +commands may give different interpretations to some component escapes; +be sure to refer to each command's manual entry for complete details. + +A \fIfunction\fR escape is specified as `%(\fIfunction\fR\^)'. +All functions are built-in, and most have a string or numeric value. + +.ne 12 +.Uh "Control-flow escapes" +A \fIcontrol\fR escape is one of: `%<', `%?', `%|', or `%>'. +.\" `%[', or `%]'. +These are combined into the conditional execution construct: +.sp +.nf + %<condition + \fIformat text 1\fP + %?condition2 + \fIformat text 2\fP + %?condition3 + \fIformat text 3\fP + \.\.\. + %| + \fIformat text N\fP + %> +.fi +.sp +Extra white space is shown here only for clarity. +These constructs may be nested without ambiguity. +They form a general \fBif\-elseif\-else\-endif\fP block where +only one of the \fIformat text\fP segments is interpreted. + +The `%<' and `%?' control escapes causes a condition to be evaluated. +This condition +may be either a \fIcomponent\fP or a \fIfunction\fP. +The four constructs have the following syntax: +.sp 1 +.nf + %<{component} + %<(function) + %?{component} + %?(function) +.fi +.sp +These control escapes test whether +the function or component value is non-zero (for integer-valued escapes), +or non-empty (for string-valued escapes). + +If this test evaulates true, +then the format text +up to the next corresponding control escape +(one of `%|', `%?', or `%>') +is interpreted normally. +Next, +all format text (if any) up to the corresponding `%>' control +escape is skipped. +The `%>' control escape is not interpreted; +normal +interpretation resumes after the `%>' escape. + +If the test evaluates false, however, +then the format text +up to the next corresponding control escape +(again, one of `%|', `%?', or `%>') +is skipped, instead of being interpreted. +If the control escape encountered was `%?', +then the condition associated with that control escape is +evaluated, and interpretation +proceeds after that test +as described in the previous paragraph. +If the control escape encountered was `%|', +then the format text +up to the corresponding `%>' escape +is interpreted normally. +As above, +the `%>' escape is not interpreted and normal +interpretation resumes after the `%>' escape. + +The `%?' control escape and its following format text +is optional, and may be included zero or more times. +The `%|' control escape and its following format text +is also optional, and may be included zero or one times. + +.\" The '%[' and '%]' escapes form a loop construct. +.\" For format strings which are executed repeatedly +.\" (as with \fIscan\fP), these escapes delimit the main +.\" body of execution. Format text which occurs +.\" before the '%[' escape is executed once only, prior +.\" to processing the first message; format text occuring +.\" after the '%]' escape is ignored. +.\" (These escapes may not be nested). +.\" +.Uh "Function escapes" +.ne 10 +Most functions expect an argument of a particular type: +.sp 1 +.nf +.ta +\w'Argument 'u +\w'An optional component, 'u +\fIArgument\fR \fIDescription\fR \fIExample Syntax\fR +literal A literal number, %(\fIfunc\fR 1234) + or string %(\fIfunc\fR text string) +comp Any header component %(\fIfunc\fR\^{\fIin-reply-to\fR\^}) +date A date component %(\fIfunc\fR\^{\fIdate\fR\^}) +addr An address component %(\fIfunc\fR\^{\fIfrom\fR\^}) +expr An optional component, %(\fIfunc\fR\^(\fIfunc2\fR\^)) + function or control, %(\fIfunc\fR %<{\fIreply-to\fR\^}%|%{\fIfrom\fR\^}%>) + perhaps nested %(\fIfunc\fR\^(\fIfunc2\fR\^{\fIcomp\fR\^})) +.re +.fi + +The types \fIdate\fR and \fIaddr\fR have the same syntax +as \fIcomp\fR, but require that the header +component be a date string, or address string, respectively. + +All arguments except those of type \fIexpr\fR are required. +For the \fIexpr\fR argument type, +the leading `%' must be omitted for component and function escape arguments, +and must be present (with a leading space) for control escape arguments. + +The evaluation of format strings +is based on a simple machine with an +integer register \fInum\fR, and a text string register \fIstr\fR. +When a function escape is processed, +if it accepts an optional \fIexpr\fR argument which is not present, +it reads the current value of either \fInum\fR or \fIstr\fR as appropriate. + +.\" return values +.Uh "Return values" +Component escapes write the value of their message header in \fIstr\fR. +Function escapes write their return value in +\fInum\fR for functions returning \fIinteger\fR or \fIboolean\fR values, +and in \fIstr\fR for functions returning string values. +(The \fIboolean\fR type is a subset of integers with usual +values 0=false and 1=true.) +Control escapes return a \fIboolean\fP value, and set \fInum\fP. + +All component escapes, and those +function escapes which return an \fIinteger\fR or \fIstring\fR value, +pass this value back to their caller +in addition to setting \fIstr\fR or \fInum\fR. +These escapes will print out this value +unless called as part of an argument to another escape sequence. +Escapes which return a \fIboolean\fR value do pass this value +back to their caller in \fInum\fP, but will never print out the value. + +.nf +.ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u +\fIFunction\fR \fIArgument\fR \fIReturn\fR \fIDescription\fR +msg integer message number +cur integer message is current +.\" unseen integer message is unseen +size integer size of message +strlen integer length of \fIstr\fR +width integer output buffer size in bytes +charleft integer bytes left in output buffer +timenow integer seconds since the UNIX epoch +me string the user's mailbox +eq literal boolean \fInum\fR == \fIarg\fR +ne literal boolean \fInum\fR != \fIarg\fR +gt literal boolean \fInum\fR > \fIarg\fR +match literal boolean \fIstr\fR contains \fIarg\fR +amatch literal boolean \fIstr\fR starts with \fIarg\fR +plus literal integer \fIarg\fR plus \fInum\fR +minus literal integer \fIarg\fR minus \fInum\fR +divide literal integer \fInum\fR divided by \fIarg\fR +modulo literal integer \fInum\fR modulo \fIarg\fR +num literal integer Set \fInum\fR to \fIarg\fR +lit literal string Set \fIstr\fR to \fIarg\fR +getenv literal string Set \fIstr\fR to environment value of \fIarg\fR +profile literal string Set \fIstr\fR to profile component \fIarg\fR value +.\" dat literal int return value of dat[arg] +nonzero expr boolean \fInum\fR is non-zero +zero expr boolean \fInum\fR is zero +null expr boolean \fIstr\fR is empty +nonnull expr boolean \fIstr\fR is non-empty +void expr Set \fIstr\fR or \fInum\fR +comp comp string Set \fIstr\fR to component text +compval comp integer \fInum\fR set to \*(lq\fBatoi\fR(\fIcomp\fR\^)\*(rq +.\" compflag comp integer Set \fInum\fR to component flags bits (internal) +trim expr trim trailing white-space from \fIstr\fR +putstr expr print \fIstr\fR +putstrf expr print \fIstr\fR in a fixed width +putnum expr print \fInum\fR +putnumf expr print \fInum\fR in a fixed width +.\" addtoseq literal add msg to sequence (LBL option) +.re +.fi + +These functions require a date component as an argument: +.sp 1 +.nf +.ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u +\fIFunction\fR \fIArgument\fR \fIReturn\fR \fIDescription\fR +sec date integer seconds of the minute +min date integer minutes of the hour +hour date integer hours of the day (0-23) +wday date integer day of the week (Sun=0) +day date string day of the week (abbrev.) +weekday date string day of the week +sday date integer day of the week known? + (0=implicit,\-1=unknown) +mday date integer day of the month +yday date integer day of the year +mon date integer month of the year +month date string month of the year (abbrev.) +lmonth date string month of the year +year date integer year (may be > 100) +zone date integer timezone in hours +tzone date string timezone string +szone date integer timezone explicit? + (0=implicit,\-1=unknown) +date2local date coerce date to local timezone +date2gmt date coerce date to GMT +dst date integer daylight savings in effect? +clock date integer seconds since the UNIX epoch +rclock date integer seconds prior to current time +tws date string official 822 rendering +pretty date string user-friendly rendering +nodate date integer \fIstr\fR not a date string +.re +.fi + +.ne 12 +These functions require an address component as an argument. +The return value of functions noted with `*' pertain only to +the first address present in the header component. +.sp 1 +.nf +.ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u +\fIFunction\fR \fIArgument\fR \fIReturn\fR \fIDescription\fR +proper addr string official 822 rendering +friendly addr string user-friendly rendering +addr addr string mbox@host or host!mbox rendering* +pers addr string the personal name* +note addr string commentary text* +mbox addr string the local mailbox* +mymbox addr integer the user's addresses? (0=no,1=yes) +host addr string the host domain* +nohost addr integer no host was present* +type addr integer host type* (0=local,1=network, + \-1=uucp,2=unknown) +path addr string any leading host route* +ingrp addr integer address was inside a group* +gname addr string name of group* +formataddr expr append \fIarg\fR to \fIstr\fR as a + (comma separated) address list +putaddr literal print \fIstr\fR address list with + \fIarg\fR as optional label; + get line width from \fInum\fR +.re +.fi + +When escapes are nested, evaluation is done from inner-most to outer-most. +The outer-most escape must begin with `%'; the inner escapes must not. +For example, + +.ti +.5i +%<(mymbox{from}) To: %{to}%> + +writes the value of the header component \*(lqFrom:\*(rq to \fIstr\fR\^; +then (\fImymbox\fR\^) reads \fIstr\fR +and writes its result to \fInum\fR; +then the control escape evaluates \fInum\fR. If \fInum\fR is +non-zero, the string \*(lqTo: \*(rq is printed followed by +the value of the header component \*(lqTo:\*(rq. + +A minor explanation of (\fImymbox\fR\^{\fIcomp\fR\^}) is in order. +In general, it checks each of the addresses in the header component +\*(lq\fIcomp\fR\*(rq +against the user's mailbox name and any \fIAlternate-Mailboxes\fR. +It returns true if any address matches, however, it +also returns true if the \*(lq\fIcomp\fR\*(rq header is not present +in the message. If needed, the (\fInull\fR\^) function can be +used to explicitly test for this condition. + +When a function or component escape is interpreted and the result +will be immediately printed, +an optional field width can be +specified to print the field in exactly a given number of characters. +For example, a numeric escape like %4(\fIsize\fR\^) will print at most 4 +digits of the message size; overflow will be indicated by a `?' in the +first position (like `?234'). +A string escape like %4(\fIme\fR\^) will print the first 4 characters and +truncate at the end. +Short fields are padded at the right with the fill character (normally, +a blank). If the field width argument begins with a leading zero, +then the fill character is set to a zero. + +As above, +the functions (\fIputnumf\fR\^) and (\fIputstrf\fR\^) print their result in +exactly the number of characters specified by their leading field width +argument. +For example, +%06(\fIputnumf\fR\^(\fIsize\fR\^)) will print the message size +in a field six characters wide filled with leading zeros; +%14(\fIputstrf\^\fR{\fIfrom\^\fR}) will print +the \*(lqFrom:\*(rq header component in fourteen characters with +trailing spaces added as needed. +For \fIputstrf\fR, +using a negative value for the field width causes right-justification +of the string within the field, +with padding on the left up to the field width. +The functions (\fIputnum\fR\^) and (\fIputstr\fR\^) print their result in +the minimum number of characters required, and ignore any leading +field width argument. + +The available output width is kept in an internal register; any output past +this width will be truncated. + +Comments may be inserted in most places where a function argument +is not expected. A comment begins with `%;' and ends with +a (non-escaped) newline. + +With all this in mind, +here's the default format string for \fIscan\fR. +It's been divided into several pieces for readability. +The first part is: + +.ti +.5i +%4(msg)%<(cur)+%| %>%<{replied}\-%?{encrypted}E%| %> + +which says that the message number should be printed in four digits, +if the message is the current message then a `+' else a space should be +printed, +and if a \*(lqReplied:\*(rq field is present then a `\-' else +if an \*(lqEncrypted:\*(rq field is present then an `E' otherwise +a space should be printed. +Next: + +.ti +.5i +%02(mon{date})/%02(mday{date}) + +the month and date are printed in two digits (zero filled) separated by +a slash. +Next, + +.ti +.5i +%<{date} %|*> + +If a \*(lqDate:\*(rq field was present, +then a space is printed, otherwise a `*'. +Next, + +.ti +.5i +%<(mymbox{from})%<{to}To:%14(friendly{to})%>%> + +if the message is from me, +and there is a \*(lqTo:\*(rq header, +print `To:' followed by a \*(lquser-friendly\*(rq rendering of the +first address in the \*(lqTo:\*(rq field. +Continuing, + +.ti +.5i +%<(zero)%17(friendly{from})%> + +if either of the above two tests failed, +then the \*(lqFrom:\*(rq address is printed +in a \*(lquser-friendly\*(rq format. +And finally, + +.ti +.5i +%{subject}%<{body}<<%{body}%> + +the subject and initial body (if any) are printed. + +For a more complicated example, next consider +the default \fIreplcomps\fR format file. + +.ti +.5i +%(lit)%(formataddr %<{reply-to} + +This clears \fIstr\fR and formats the \*(lqReply-To:\*(rq header +if present. If not present, the else-if clause is executed. + +.ti +.5i +%?{from}%?{sender}%?{return-path}%>)\\ + +This formats the +\*(lqFrom:\*(rq, \*(lqSender:\*(rq and \*(lqReturn-Path:\*(rq +headers, stopping as soon as one of them is present. Next: + +.ti +.5i +%<(nonnull)%(void(width))%(putaddr To: )\\n%>\\ + +If the \fIformataddr\fR result is non-null, it is printed as +an address (with line folding if needed) in a field \fIwidth\fR +wide with a leading label of \*(lqTo: \*(rq. + +.ti +.5i +%(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\\ + +\fIstr\fR is cleared, and the +\*(lqTo:\*(rq and \*(lqCc:\*(rq headers, along with the user's +address +(depending on what was specified with +the \*(lq\-cc\*(rq switch to \fIrepl\fR\^) are formatted. + +.ti +.5i +%<(nonnull)%(void(width))%(putaddr cc: )\\n%>\\ + +If the result is non-null, it is printed as above with a +leading label of \*(lqcc: \*(rq. + +.ti +.5i +%<{fcc}Fcc: %{fcc}\\n%>\\ + +If a \*(lq\-fcc\ folder\*(rq switch was given to \fIrepl\fR +(see \fIrepl\fR\0(1) for more details about %{\fIfcc\fR\^}), +an \*(lqFcc:\*(rq header is output. + +.ti +.5i +%<{subject}Subject: Re: %{subject}\\n%>\\ + +If a subject component was present, +a suitable reply subject is output. + +.nf +.ti +.5i +%<{date}In-reply-to: Your message of "\\ +.ti +.5i +%<(nodate{date})%{date}%|%(pretty{date})%>."%<{message-id} +.ti +.5i + %{message-id}%>\\n%>\\ +.ti +.5i +\-\-\-\-\-\-\-\- +.fi + +If a date component was present, +an \*(lqIn-Reply-To:\*(rq header is output with the preface +\*(lqYour message of \*(rq. If the date was parseable, it is +output in a user-friendly format, otherwise it is output as-is. +The message-id is included if present. +As with all plain-text, +the row of dashes are output as-is. + +This last part is a good example for a little more elaboration. +Here's that part again in pseudo-code: +.sp 1 +.nf +.in +.5i +.ta .5i 1i 1.5i 2i +if (comp_exists(date)) then + print (\*(lqIn-reply-to: Your message of \\\*(lq\*(rq) + if (not_date_string(date.value) then + print (date.value) + else + print (pretty(date.value)) + endif + print (\*(lq\\\*(rq\*(rq) + if (comp_exists(message-id)) then + print (\*(lq\\n\\t\*(rq) + print (message-id.value) + endif + print (\*(lq\\n\*(rq) +endif +.re +.in -.5i +.fi +.sp 1 +Although this seems complicated, +in point of fact, +this method is flexible enough to extract individual fields and print them in +any format the user desires. +.Fi +None +.Pr +None +.Sa +scan(1), repl(1), ap(8), dp(8) +.De +None +.Co +None +.Hi +This software was contributed for MH 6.3. Prior to this, output +format specifications were much easier to write, but considerably +less flexible. +.Bu +On hosts where \fIMH\fR was configured with the BERK option, +address parsing is not enabled. +.En