Initial revision
[mmh] / man / mh-format.man
1 .\"
2 .\" %nmhwarning%
3 .\" $Id$
4 .\"
5 .\" include the -mh macro file
6 .so %etcdir%/tmac.h
7 .\"
8 .TH MH-FORMAT %manext5% MH.6.8 [%nmhversion%]
9 .SH NAME
10 mh-format \- format file for nmh message system
11 .SH SYNOPSIS
12 .in +.5i
13 .ti -.5i
14 some \fInmh\fR commands
15 .in -.5i
16 .SH DESCRIPTION
17 Several \fInmh\fR commands utilize either a \fIformat\fR string or a
18 \fIformat\fR file during their execution.  For example, \fIscan\fR\0(1)
19 uses a format string which directs it how to generate the scan listing
20 for each message; \fIrepl\fR\0(1) uses a format file which directs it
21 how to generate the reply to a message, and so on.
22
23 Format strings are designed to be efficiently parsed by \fInmh\fR
24 which means they are not necessarily simple to write and understand.
25 This means that novice, casual, or even advanced users of \fInmh\fR
26 should not have to deal with them.
27
28 There are a few alternate scan listing formats available
29 in %etcdir%/scan.time, %etcdir%/scan.size, and %etcdir%/scan.timely.
30 Look in %etcdir% for other \fIscan\fR and \fIrepl\fR format files which
31 may have been written at your site.
32
33 It suffices to have your local \fInmh\fR expert actually write new format
34 commands or modify existing ones.  This manual section explains how to
35 do that.  Note: familiarity with the C \fIprintf\fR routine is assumed.
36
37 A format string consists of ordinary text, and special multi-character
38 \fIescape\fR sequences which begin with `%'.  When specifying a format
39 string, the usual C backslash characters are honored: `\\b', `\\f',
40 `\\n', `\\r', and `\\t'.  Continuation lines in format files end with
41 `\\' followed by the newline character.
42
43 .\" TALK ABOUT SYNTAX FIRST, THEN SEMANTICS
44 There are three types of \fIescape\fR sequences: header
45 \fIcomponents\fR, built-in \fIfunctions\fR, and flow \fIcontrol\fR.
46
47 A \fIcomponent\fR escape is specified as `%{\fIcomponent\fR\^}', and
48 exists for each header found in the message being processed.  For example
49 `%{date}' refers to the \*(lqDate:\*(rq field of the appropriate message.
50 All component escapes have a string value.  Normally, component values are
51 compressed by converting any control characters (tab and newline included)
52 to spaces, then eliding any leading or multiple spaces.  However, commands
53 may give different interpretations to some component escapes; be sure
54 to refer to each command's manual entry for complete details.
55
56 A \fIfunction\fR escape is specified as `%(\fIfunction\fR\^)'.
57 All functions are built-in, and most have a string or numeric value.
58
59 .ne 12
60 .Uh "Control-flow escapes"
61 A \fIcontrol\fR escape is one of: `%<', `%?', `%|', or `%>'. 
62 These are combined into the conditional execution construct:
63 .sp
64 .nf
65         %<condition
66                 \fIformat text 1\fP
67         %?condition2
68                 \fIformat text 2\fP
69         %?condition3
70                 \fIformat text 3\fP
71         \.\.\.
72         %|
73                 \fIformat text N\fP
74         %>
75 .fi
76 .sp
77 Extra white space is shown here only for clarity.  These
78 constructs may be nested without ambiguity.  They form a general
79 \fBif\-elseif\-else\-endif\fP block where only one of the \fIformat
80 text\fP segments is interpreted.
81
82 The `%<' and `%?' control escapes causes a condition to be evaluated.  
83 This condition
84 may be either a \fIcomponent\fP or a \fIfunction\fP.
85 The four constructs have the following syntax:
86 .sp 1
87 .nf
88         %<{component}
89         %<(function)
90         %?{component}
91         %?(function)
92 .fi
93 .sp
94 These control escapes test whether the function or component value is
95 non-zero (for integer-valued escapes), or non-empty (for string-valued
96 escapes).
97
98 If this test evaulates true, then the format text up to the next
99 corresponding control escape (one of `%|', `%?', or `%>') is interpreted
100 normally.  Next, all format text (if any) up to the corresponding `%>'
101 control escape is skipped.  The `%>' control escape is not interpreted;
102 normal interpretation resumes after the `%>' escape.
103
104 If the test evaluates false, however, then the format text up to
105 the next corresponding control escape (again, one of `%|', `%?', or
106 `%>') is skipped, instead of being interpreted.  If the control escape
107 encountered was `%?', then the condition associated with that control
108 escape is evaluated, and interpretation proceeds after that test as
109 described in the previous paragraph.  If the control escape encountered
110 was `%|', then the format text up to the corresponding `%>' escape is
111 interpreted normally.  As above, the `%>' escape is not interpreted and
112 normal interpretation resumes after the `%>' escape.
113
114 The `%?' control escape and its following format text is optional, and may
115 be included zero or more times.  The `%|' control escape and its following
116 format text is also optional, and may be included zero or one times.
117
118 .Uh "Function escapes"
119 .ne 10
120 Most functions expect an argument of a particular type:
121 .sp 1
122 .nf
123 .ta +\w'Argument 'u +\w'An optional component, 'u
124 \fIArgument\fR  \fIDescription\fR       \fIExample Syntax\fR
125 literal A literal number,       %(\fIfunc\fR 1234)
126         or string       %(\fIfunc\fR text string)
127 comp    Any header component    %(\fIfunc\fR\^{\fIin-reply-to\fR\^})
128 date    A date component        %(\fIfunc\fR\^{\fIdate\fR\^})
129 addr    An address component    %(\fIfunc\fR\^{\fIfrom\fR\^})
130 expr    An optional component,  %(\fIfunc\fR\^(\fIfunc2\fR\^))
131         function or control,    %(\fIfunc\fR %<{\fIreply-to\fR\^}%|%{\fIfrom\fR\^}%>)
132         perhaps nested  %(\fIfunc\fR\^(\fIfunc2\fR\^{\fIcomp\fR\^}))
133 .re
134 .fi
135
136 The types \fIdate\fR and \fIaddr\fR have the same syntax as \fIcomp\fR,
137 but require that the header component be a date string, or address
138 string, respectively.
139
140 All arguments except those of type \fIexpr\fR are required.  For the
141 \fIexpr\fR argument type, the leading `%' must be omitted for component
142 and function escape arguments, and must be present (with a leading space)
143 for control escape arguments.
144
145 The evaluation of format strings is based on a simple virtual machine
146 with an integer register \fInum\fR, and a text string register \fIstr\fR.
147 When a function escape is processed, if it accepts an optional \fIexpr\fR
148 argument which is not present, it reads the current value of either
149 \fInum\fR or \fIstr\fR as appropriate.
150
151 .Uh "Return values"
152 Component escapes write the value of their message header in \fIstr\fR.
153 Function escapes write their return value in \fInum\fR for functions
154 returning \fIinteger\fR or \fIboolean\fR values, and in \fIstr\fR for
155 functions returning string values.  (The \fIboolean\fR type is a subset
156 of integers with usual values 0=false and 1=true.)  Control escapes
157 return a \fIboolean\fP value, and set \fInum\fP.
158
159 All component escapes, and those function escapes which return an
160 \fIinteger\fR or \fIstring\fR value, pass this value back to their caller
161 in addition to setting \fIstr\fR or \fInum\fR.  These escapes will print
162 out this value unless called as part of an argument to another escape
163 sequence.  Escapes which return a \fIboolean\fR value do pass this value
164 back to their caller in \fInum\fP, but will never print out the value.
165
166 .nf
167 .ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u
168 \fIFunction\fR  \fIArgument\fR  \fIReturn\fR    \fIDescription\fR
169 msg             integer message number
170 cur             integer message is current
171 unseen          integer message is unseen
172 size            integer size of message
173 strlen          integer length of \fIstr\fR
174 width           integer output buffer size in bytes
175 charleft                integer bytes left in output buffer
176 timenow         integer seconds since the UNIX epoch
177 me              string  the user's mailbox
178 eq      literal boolean \fInum\fR == \fIarg\fR
179 ne      literal boolean \fInum\fR != \fIarg\fR
180 gt      literal boolean \fInum\fR > \fIarg\fR
181 match   literal boolean \fIstr\fR contains \fIarg\fR
182 amatch  literal boolean \fIstr\fR starts with \fIarg\fR
183 plus    literal integer \fIarg\fR plus \fInum\fR
184 minus   literal integer \fIarg\fR minus \fInum\fR
185 divide  literal integer \fInum\fR divided by \fIarg\fR
186 modulo  literal integer \fInum\fR modulo \fIarg\fR
187 num     literal integer Set \fInum\fR to \fIarg\fR
188 lit     literal string  Set \fIstr\fR to \fIarg\fR
189 getenv  literal string  Set \fIstr\fR to environment value of \fIarg\fR
190 profile literal string  Set \fIstr\fR to profile component \fIarg\fR value
191 .\" dat literal int     return value of dat[arg]
192 nonzero expr    boolean \fInum\fR is non-zero
193 zero    expr    boolean \fInum\fR is zero
194 null    expr    boolean \fIstr\fR is empty
195 nonnull expr    boolean \fIstr\fR is non-empty
196 void    expr            Set \fIstr\fR or \fInum\fR
197 comp    comp    string  Set \fIstr\fR to component text
198 compval comp    integer Set \fInum\fR to \*(lq\fBatoi\fR(\fIcomp\fR\^)\*(rq
199 .\" compflag    comp    integer Set \fInum\fR to component flags bits (internal)
200 .\" decodecomp  comp    string  Set \fIstr\fR to RFC-2047 decoded component text
201 decode  expr    string  decode \fIstr\fR as RFC-2047 component
202 trim    expr            trim trailing white-space from \fIstr\fR
203 putstr  expr            print \fIstr\fR
204 putstrf expr            print \fIstr\fR in a fixed width
205 putnum  expr            print \fInum\fR
206 putnumf expr            print \fInum\fR in a fixed width
207 .\" addtoseq literal    add msg to sequence (LBL option)
208 .re     
209 .fi
210
211 These functions require a date component as an argument:
212 .sp 1
213 .nf
214 .ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u
215 \fIFunction\fR  \fIArgument\fR  \fIReturn\fR    \fIDescription\fR
216 sec     date    integer seconds of the minute
217 min     date    integer minutes of the hour
218 hour    date    integer hours of the day (0-23)
219 wday    date    integer day of the week (Sun=0)
220 day     date    string  day of the week (abbrev.)
221 weekday date    string  day of the week
222 sday    date    integer day of the week known?
223                         (0=implicit,\-1=unknown)
224 mday    date    integer day of the month
225 yday    date    integer day of the year
226 mon     date    integer month of the year
227 month   date    string  month of the year (abbrev.)
228 lmonth  date    string  month of the year
229 year    date    integer year (may be > 100)
230 zone    date    integer timezone in hours
231 tzone   date    string  timezone string
232 szone   date    integer timezone explicit?
233                         (0=implicit,\-1=unknown)
234 date2local      date            coerce date to local timezone
235 date2gmt        date            coerce date to GMT
236 dst     date    integer daylight savings in effect?
237 clock   date    integer seconds since the UNIX epoch
238 rclock  date    integer seconds prior to current time
239 tws     date    string  official 822 rendering
240 pretty  date    string  user-friendly rendering
241 nodate  date    integer \fIstr\fR not a date string
242 .re     
243 .fi
244
245 .ne 12
246 These functions require an address component as an argument.  
247 The return value of functions noted with `*' pertain only to
248 the first address present in the header component.
249 .sp 1
250 .nf
251 .ta \w'Formataddr 'u +\w'Argument 'u +\w'Rboolean 'u
252 \fIFunction\fR  \fIArgument\fR  \fIReturn\fR    \fIDescription\fR
253 proper  addr    string  official 822 rendering
254 friendly        addr    string  user-friendly rendering
255 addr    addr    string  mbox@host or host!mbox rendering*
256 pers    addr    string  the personal name*
257 note    addr    string  commentary text*
258 mbox    addr    string  the local mailbox*
259 mymbox  addr    integer the user's addresses? (0=no,1=yes)
260 host    addr    string  the host domain*
261 nohost  addr    integer no host was present*
262 type    addr    integer host type* (0=local,1=network,
263                         \-1=uucp,2=unknown)
264 path    addr    string  any leading host route*
265 ingrp   addr    integer address was inside a group*
266 gname   addr    string  name of group*
267 formataddr      expr            append \fIarg\fR to \fIstr\fR as a
268                         (comma separated) address list
269 putaddr literal         print \fIstr\fR address list with
270                         \fIarg\fR as optional label;
271                         get line width from \fInum\fR
272 .re     
273 .fi
274
275 When escapes are nested, evaluation is done from inner-most to outer-most.
276 The outer-most escape must begin with `%'; the inner escapes must not.
277 For example,
278
279 .ti +.5i
280 %<(mymbox{from}) To: %{to}%>
281
282 writes the value of the header component \*(lqFrom:\*(rq to \fIstr\fR\^;
283 then (\fImymbox\fR\^) reads \fIstr\fR and writes its result to \fInum\fR;
284 then the control escape evaluates \fInum\fR.  If \fInum\fR is non-zero,
285 the string \*(lqTo: \*(rq is printed followed by the value of the header
286 component \*(lqTo:\*(rq.
287
288 A minor explanation of (\fImymbox\fR\^{\fIcomp\fR\^}) is in order.
289 In general, it checks each of the addresses in the header component
290 \*(lq\fIcomp\fR\*(rq against the user's mailbox name and any
291 \fIAlternate-Mailboxes\fR.  It returns true if any address matches,
292 however, it also returns true if the \*(lq\fIcomp\fR\*(rq header is not
293 present in the message.  If needed, the (\fInull\fR\^) function can be
294 used to explicitly test for this condition.
295
296 When a function or component escape is interpreted and the result will
297 be immediately printed, an optional field width can be specified to
298 print the field in exactly a given number of characters.  For example, a
299 numeric escape like %4(\fIsize\fR\^) will print at most 4 digits of the
300 message size; overflow will be indicated by a `?' in the first position
301 (like `?234').  A string escape like %4(\fIme\fR\^) will print the first 4
302 characters and truncate at the end.  Short fields are padded at the right
303 with the fill character (normally, a blank).  If the field width argument
304 begins with a leading zero, then the fill character is set to a zero.
305
306 As above, the functions (\fIputnumf\fR\^) and (\fIputstrf\fR\^)
307 print their result in exactly the number of characters
308 specified by their leading field width argument.  For example,
309 %06(\fIputnumf\fR\^(\fIsize\fR\^)) will print the message
310 size in a field six characters wide filled with leading zeros;
311 %14(\fIputstrf\^\fR{\fIfrom\^\fR}) will print the \*(lqFrom:\*(rq header
312 component in fourteen characters with trailing spaces added as needed.
313 For \fIputstrf\fR, using a negative value for the field width causes
314 right-justification of the string within the field, with padding on
315 the left up to the field width.  The functions (\fIputnum\fR\^) and
316 (\fIputstr\fR\^) print their result in the minimum number of characters
317 required, and ignore any leading field width argument.
318
319 The available output width is kept in an internal register; any output
320 past this width will be truncated.
321
322 Comments may be inserted in most places where a function argument is
323 not expected.  A comment begins with `%;' and ends with a (non-escaped)
324 newline.
325
326 With all this in mind,
327 here's the default format string for \fIscan\fR.
328 It's been divided into several pieces for readability.
329 The first part is:
330
331 .ti +.5i
332 %4(msg)%<(cur)+%| %>%<{replied}\-%?{encrypted}E%| %>
333
334 which says that the message number should be printed in four digits,
335 if the message is the current message then a `+' else a space should
336 be printed, and if a \*(lqReplied:\*(rq field is present then a `\-'
337 else if an \*(lqEncrypted:\*(rq field is present then an `E' otherwise
338 a space should be printed.  Next:
339
340 .ti +.5i
341 %02(mon{date})/%02(mday{date})
342
343 the month and date are printed in two digits (zero filled) separated by
344 a slash.
345 Next,
346
347 .ti +.5i
348 %<{date} %|*>
349
350 If a \*(lqDate:\*(rq field was present,
351 then a space is printed, otherwise a `*'.
352 Next,
353
354 .ti +.5i
355 %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>
356
357 if the message is from me,
358 and there is a \*(lqTo:\*(rq header,
359 print `To:' followed by a \*(lquser-friendly\*(rq rendering of the 
360 first address in the \*(lqTo:\*(rq field.
361 Continuing,
362
363 .ti +.5i
364 %<(zero)%17(friendly{from})%>
365
366 if either of the above two tests failed,
367 then the \*(lqFrom:\*(rq address is printed
368 in a \*(lquser-friendly\*(rq format.
369 And finally,
370
371 .ti +.5i
372 %{subject}%<{body}<<%{body}%>
373
374 the subject and initial body (if any) are printed.
375
376 For a more complicated example, next consider
377 the default \fIreplcomps\fR format file.
378
379 .ti +.5i
380 %(lit)%(formataddr %<{reply-to}
381
382 This clears \fIstr\fR and formats the \*(lqReply-To:\*(rq header 
383 if present.  If not present, the else-if clause is executed.
384
385 .ti +.5i
386 %?{from}%?{sender}%?{return-path}%>)\\
387
388 This formats the 
389 \*(lqFrom:\*(rq, \*(lqSender:\*(rq and \*(lqReturn-Path:\*(rq
390 headers, stopping as soon as one of them is present.  Next:
391
392 .ti +.5i
393 %<(nonnull)%(void(width))%(putaddr To: )\\n%>\\
394
395 If the \fIformataddr\fR result is non-null, it is printed as
396 an address (with line folding if needed) in a field \fIwidth\fR
397 wide with a leading label of \*(lqTo: \*(rq.
398
399 .ti +.5i
400 %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\\
401
402 \fIstr\fR is cleared, and the 
403 \*(lqTo:\*(rq and \*(lqCc:\*(rq headers, along with the user's
404 address 
405 (depending on what was specified with
406 the \*(lq\-cc\*(rq switch to \fIrepl\fR\^) are formatted.
407
408 .ti +.5i
409 %<(nonnull)%(void(width))%(putaddr cc: )\\n%>\\
410
411 If the result is non-null, it is printed as above with a
412 leading label of \*(lqcc: \*(rq.
413
414 .ti +.5i
415 %<{fcc}Fcc: %{fcc}\\n%>\\
416
417 If a \*(lq\-fcc\ folder\*(rq switch was given to \fIrepl\fR
418 (see \fIrepl\fR\0(1) for more details about %{\fIfcc\fR\^}),
419 an \*(lqFcc:\*(rq header is output.
420
421 .ti +.5i
422 %<{subject}Subject: Re: %{subject}\\n%>\\
423
424 If a subject component was present,
425 a suitable reply subject is output.
426
427 .nf
428 .ti +.5i
429 %<{date}In-reply-to: Your message of "\\
430 .ti +.5i
431 %<(nodate{date})%{date}%|%(pretty{date})%>."%<{message-id}
432 .ti +.5i
433              %{message-id}%>\\n%>\\
434 .ti +.5i
435 \-\-\-\-\-\-\-\-
436 .fi
437
438 If a date component was present, an \*(lqIn-Reply-To:\*(rq header is
439 output with the preface \*(lqYour message of \*(rq.  If the date was
440 parseable, it is output in a user-friendly format, otherwise it is
441 output as-is.  The message-id is included if present.  As with all
442 plain-text, the row of dashes are output as-is.
443
444 This last part is a good example for a little more elaboration.
445 Here's that part again in pseudo-code:
446 .sp 1
447 .nf
448 .in +.5i
449 .ta .5i 1i 1.5i 2i
450 if (comp_exists(date))  then
451         print (\*(lqIn-reply-to: Your message of \\\*(lq\*(rq)
452         if (not_date_string(date.value) then
453                 print (date.value)
454         else
455                 print (pretty(date.value))
456         endif
457         print (\*(lq\\\*(rq\*(rq)
458         if (comp_exists(message-id)) then
459                 print (\*(lq\\n\\t\*(rq)
460                 print (message-id.value)
461         endif
462         print (\*(lq\\n\*(rq)
463 endif
464 .re
465 .in -.5i
466 .fi
467 .sp 1
468 Although this seems complicated,
469 in point of fact,
470 this method is flexible enough to extract individual fields and print them in
471 any format the user desires.
472 .Fi
473 None
474 .Pr
475 None
476 .Sa
477 scan(1), repl(1), ap(8), dp(8)
478 .De
479 None
480 .Co
481 None
482 .En