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