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