mh-format man page on Cygwin

Man page or keyword search:  
man Server   22533 pages
apropos Keyword Search (all sections)
Output format
Cygwin logo
[printable version]

MH-FORMAT(5)							  MH-FORMAT(5)

NAME
       mh-format - format file for nmh message system

DESCRIPTION
       Several	nmh  commands  utilize either a format string or a format file
       during their execution.	For example, scan uses a format	 string	 which
       directs it how to 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.

       There   are   a	 few  alternate	 scan  listing	formats	 available  in
       nmh/etc/scan.time, nmh/etc/scan.size, and nmh/etc/scan.timely.  Look in
       nmh/etc	for other scan and repl format files which may have been writ‐
       ten at your site.

       It suffices to have your local nmh expert  actually  write  new	format
       commands	 or modify existing ones.  This manual section explains how to
       do that.	 Note: familiarity with the C printf routine is assumed.

       A format string consists of ordinary text, and special  multi-character
       escape  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 `\' fol‐
       lowed by the newline character.

   SYNTAX
       Format strings are built around	escape	sequences.   There  are	 three
       types  of  escape sequences: header components, built-in functions, and
       flow control.  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.

       A component escape is specified as `%{component}', and exists for  each
       header  found  in  the  message being processed.	 For example `%{date}'
       refers to the “Date:” 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 spa‐
       ces,  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.  Some
       commands (such as ap and mhl) use  a  special  component	 `%{text}'  to
       refer  to  the text being processed; see their respective man pages for
       details and examples.

       A function escape is specified as  `%(function)'.   All	functions  are
       built-in,  and  most have a string or numeric value.  A function escape
       may have an argument.  The argument follows the function escape:	 sepa‐
       rating whitespace is discarded: `%(function argument)'.

       In  addition  to literal numbers or strings, the argument to a function
       escape can be another function, a component, or a control escape.  When
       the  argument  is  a function or a component, they are listed without a
       leading `%'.  When control escapes are used as function arguments, they
       written as normally, with a leading `%';

   Control escapes
       A  control escape is one of: `%<', `%?', `%|', or `%>'.	These are com‐
       bined into the conditional execution construct:

	    %< condition format-text
	    %? condition format-text
		...
	    %| format-text
	    %>

       Extra white space is shown here only for clarity.  These constructs may
       be  nested without ambiguity.  They form a general if-elseif-else-endif
       block where only one of the  format-texts  is  interpreted.   In	 other
       words,  `%<'  is like the "if", `%?' is like the "elseif", `%|' is like
       "else", and `%>' is like "endif".

       A `%<' or `%?' control escape causes its	 condition  to	be  evaluated.
       This  condition	is  a component or function.  For integer valued func‐
       tions or components, the condition is true if the  function  return  or
       component  value	 is  non-zero,	and  false if zero.  For string valued
       functions or components, the condition is true if the  function	return
       or  component  value  is	 a  non-empty  string,	and false for an empty
       string.

       The `%?' control escape is optional, and may there may be more than one
       `%?' control escape in a conditional block.  The `%|' control escape is
       also optional, but may be included at most once.

   Function escapes
       Functions expecting an argument generally require an argument of a par‐
       ticular	type.	In  addition  to  the  number  and string types, these
       include:

	    Argument Description	    Example Syntax
	    literal  A literal number	    %(func 1234)
		     or string		    %(func text string)
	    comp     Any component	    %(func{in-reply-to})
	    date     A date component	    %(func{date})
	    addr     An address component   %(func{from})
	    expr     Nothing		    %(func)
		     or a subexpression	    %(func(func2))
		     or control escape	    %(func %<{reply-to}%|%{from}%>)

       The types date and addr have the same syntax as comp, but require  that
       the header component be a date string, or address string, respectively.

       Most  arguments not of type expr are required.  When escapes are nested
       (via expr arguments), evaluation is done from inner-most to outer-most.
       As  noted  above,  for the expr argument type, functions and components
       are written without a leading `%'.  Control escape arguments must use a
       leading `%', preceded by a space.

       For example,

	    %<(mymbox{from}) To: %{to}%>

       writes  the  value of the header component “From:” to the internal reg‐
       ister named str; then (mymbox) reads str and writes its result  to  the
       internal register named num; then the control escape evaluates num.  If
       num is non-zero, the string “To:” is printed  followed  by  the	 value
       of  the header component “To:”.

   Evaluation
       The  evaluation	of  format  strings  is	 performed  by a small virtual
       machine.	 The machine is capable of evaluating  nested  expressions  as
       described  above,  and  in  addition has an integer register num, and a
       text string register str.  When	a  function  escape  that  accepts  an
       optional	 argument  is  processed, and the argument is not present, the
       current value of either num or str is used as the argument: which  reg‐
       ister is used depends on the function, as listed below.

       Component  escapes  write  the  value  of  their message header in str.
       Function escapes write their return value in num for functions  return‐
       ing  integer  or	 boolean  values,  and	in str for functions returning
       string values.  (The boolean type is a subset of	 integers  with	 usual
       values  0=false	and  1=true.)  Control escapes return a boolean value,
       setting num to 1 if the last explicit condition evaluated by a `%<'  or
       `%?' control succeeded, and 0 otherwise.

       All component escapes, and those function escapes which return an inte‐
       ger or string value, evaluate to their value as well as setting str  or
       num.   Outermost	 escape	 expressions  in  these forms will print their
       value, but outermost escapes which return a boolean value do not result
       in printed output.

   Functions
       The function escapes may be roughly grouped into a few categories.

	    Function	Argument   Result Description
	    msg			 integer  message number
	    cur			 integer  message is current (0 or 1)
	    unseen		 integer  message is unseen (0 or 1)
	    size		 integer  size of message
	    strlen		 integer  length of str
	    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 (username)
	    myhost		 string	  the user's local hostname
	    myname		 string	  the user's name
	    localmbox		 string	  the complete local mailbox
	    eq		literal	 boolean  num == arg
	    ne		literal	 boolean  num != arg
	    gt		literal	 boolean  num > arg
	    match	literal	 boolean  str contains arg
	    amatch	literal	 boolean  str starts with arg
	    plus	literal	 integer  arg plus num
	    minus	literal	 integer  arg minus num
	    divide	literal	 integer  num divided by arg
	    modulo	literal	 integer  num modulo arg
	    num		literal	 integer  Set num to arg.
	    num			 integer  Set num to zero.
	    lit		literal	 string	  Set str to arg.
	    lit			 string	  Clear str.
	    getenv	literal	 string	  Set str to environment value of arg
	    profile	literal	 string	  Set str to profile component arg
					  value
	    nonzero	expr	 boolean  num is non-zero
	    zero	expr	 boolean  num is zero
	    null	expr	 boolean  str is empty
	    nonnull	expr	 boolean  str is non-empty
	    void	expr		  Set str or num
	    comp	comp	 string	  Set str to component text
	    compval	comp	 integer  Set num to “atoi(comp)”
	    decode	expr	 string	  decode str as RFC-2047 (MIME-encoded)
					  component
	    unquote	expr	 string	  remove RFC-2822 quotes from str
	    trim	expr		  trim trailing white-space from str
	    putstr	expr		  print str
	    putstrf	expr		  print str in a fixed width
	    putnum	expr		  print num
	    putnumf	expr		  print num in a fixed width
	    putlit	expr		  print str without space compression
	    nodate	string	 integer  Argument not a date string (0 or 1)
	    formataddr	expr		  append arg to str as a
					  (comma separated) address list
	    concataddr	expr		  append arg to str as a
					  (comma separated) address list,
					  including duplicates,
					  see Special Handling
	    putaddr	literal		  print str address list with
					  arg as optional label;
					  get line width from num

       The  (me)  function  returns  the  username  of	the current user.  The
       (myhost) function returns the localname entry in mts.conf, or the local
       hostname	 if  localname	is not configured.  The (myname) function will
       return the value of the SIGNATURE environment variable if  set,	other‐
       wise  will  return the passwd GECOS field (truncated at the first comma
       if it contains one) for the current  user.   The	 (localmbox)  function
       will return the complete form of the local mailbox, suitable for use in
       a “From” header.	 It will return the “Local-Mailbox” profile  entry  if
       it is set; if it is not, it will be equivalent to:

	    %(myname) <%(me)@%(myhost)>

       The following functions require a date component as an argument:

	    Function	Argument Return	  Description
	    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?
					  (1=explicit,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?
					  (1=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? (0 or 1)
	    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

       These  functions	 require  an  address  component  as an argument.  The
       return value of functions noted with `*' is  computed  from  the	 first
       address present in the header component.

	    Function	Argument Return	  Description
	    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  List has the user's address? (0 or 1)
	    host	addr	 string	  the host domain*
	    nohost	addr	 integer  no host was present (0 or 1)*
	    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 (0 or 1)*
	    gname	addr	 string	  name of group*

       (A  clarification  on (mymbox{comp}) is in order.  This function checks
       each of the addresses in the header component “comp” against the user's
       mailbox	name  and  any	“Alternate-Mailboxes”.	It returns true if any
       address matches, however, it also returns true if the “comp” header  is
       not present in the message.  If needed, the (null) function can be used
       to explicitly test for this case.)

   Formatting
       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(size) will print at most 4 digits of the mes‐
       sage size; overflow will be indicated by a `?' in  the  first  position
       (like  `?234').	 A  string  escape  like %4(me) 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.

       The functions (putnumf) and (putstrf) print their result in exactly the
       number of characters specified by their leading field  width  argument.
       For  example, %06(putnumf(size)) will print the message size in a field
       six characters wide filled with leading zeros; %14(putstrf{from})  will
       print the “From:” header component in fourteen characters with trailing
       spaces added as needed.	For putstrf, 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 (putnum)
       and (putstr) are somewhat special: they print their result in the mini‐
       mum number of characters required, and ignore any leading  field	 width
       argument.  The (putlit) function outputs the exact contents of str reg‐
       ister without any changes such as duplicate space  removal  or  control
       character conversion.

       The  available output width is kept in an internal register; any output
       past this width will be truncated.

   Special Handling
       A few functions have different behavior depending on what command  they
       are being invoked from.

       In  repl	 the  (formataddr) function stores all email addresses encoun‐
       tered into an internal cache and will use this cache to suppress dupli‐
       cate  addresses.	  If  you need to create an address list that includes
       previously-seen addresses you may use the (concataddr) function,	 which
       is  identical  to  (formataddr) in all other respects.  Note that (con‐
       cataddr) will NOT add addresses to the duplicate-suppression cache.

   Other Hints and Tips
       Sometimes to format function writers it is confusing as to  why	output
       is  duplicated.	 The general rule to remember is simple: If a function
       or component escape is used where it starts with a %, then it will gen‐
       erate text in the output file.  Otherwise, it will not.

       A  good	example	 is a simple attempt to generate a To: header based on
       the From: and Reply-To: headers:

	    %(formataddr %<{reply-to}%|%{from})%(putaddr To: )

       Unfortuantely if the Reply-to: header is NOT present, the  output  line
       that is generated will be something like:

	    My From User <from@example.com>To: My From User <from@example.com>

       What  went wrong?  When performing the test for the if clause (%<), the
       component is not output because it is considered an argument to the  if
       statement (hence the rule about the lack of % applies).	But the compo‐
       nent escape in our else statement (everything after the `%|') is NOT an
       argument	 to  anything;	the syntax is that it is written with a %, and
       thus the value of that component is output.  This  also	has  the  side
       effect  of  setting  the	 str register, which is later picked up by the
       (formataddr) function and then output by (putaddr).  This format string
       has  another bug as well; there should always be a valid width value in
       the num register when (putaddr) is called, otherwise bad formatting can
       take place.

       The solution is to use the (void) function; this will prevent the func‐
       tion or component from outputting any text.  With this  in  place  (and
       using (width) to set the num register for the width, a better implemen‐
       tation would look like:

	  %(formataddr %<{reply-to}%|%(void{from})%(void(width))%(putaddr To: )

       It should be noted here that the side-effects of functions  and	compo‐
       nent escapes still are in force: as a result each component test in the
       if-elseif-else-endif clause sets the str register.

       As an additional note, the (formataddr) and (concataddr) functions have
       some behavior when it comes to the str register.	 The starting point of
       the register is saved and is used to build up entries  in  the  address
       list.

       You  will  find	the  ap	 and fmtdump utilities invaluable in debugging
       problems with format strings.

   Examples
       With all this in mind, here's the default format string for scan.  It's
       been divided into several pieces for readability.  The first part is:

	      %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;	 if  a	“Replied:”  field  is  present	then  a `-' else if an
       “Encrypted:” field is present then an `E' otherwise a space  should  be
       printed.	 Next:

	      %02(mon{date})/%02(mday{date})

       the month and date are printed in two digits (zero filled) separated by
       a slash. Next,

	    %<{date} %|*%>

       If a “Date:” field was present, then a space is	printed,  otherwise  a
       `*'.  Next,

	    %<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>

       if  the	message	 is  from me, and there is a “To:” header, print “To:”
       followed by a “user-friendly” rendering of the  first  address  in  the
       “To:”  field;  any  MIME-encoded characters are decoded into the actual
       characters.  Continuing,

	    %<(zero)%17(decode(friendly{from}))%>

       if either of the above two tests failed, then the  “From:”  address  is
       printed in a mime-decoded, “user-friendly” format.  And finally,

	    %(decode{subject})%<{body}<<%{body}>>%>

       the mime-decoded subject and initial body (if any) are printed.

       For a more complicated example, next consider a possible replcomps for‐
       mat file.

	    %(lit)%(formataddr %<{reply-to}

       This clears str and formats the “Reply-To:” header if present.  If  not
       present, the else-if clause is executed.

	    %?{from}%?{sender}%?{return-path}%>)\

       This  formats  the “From:”, “Sender:” and “Return-Path:” headers, stop‐
       ping as soon as one of them is present.	Next:

	    %<(nonnull)%(void(width))%(putaddr To: )\n%>\

       If the formataddr result is non-null, it is printed as an address (with
       line  folding  if needed) in a field width wide with a leading label of
       “To:”.

	    %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\

       str is cleared, and the “To:” and “Cc:” headers, along with the	user's
       address (depending on what was specified with the “-cc” switch to repl)
       are formatted.

	    %<(nonnull)%(void(width))%(putaddr cc: )\n%>\

       If the result is non-null, it is printed as above with a leading	 label
       of “cc:”.

	    %<{fcc}Fcc: %{fcc}\n%>\

       If a -fcc folder switch was given to repl (see repl(1) for more details
       about %{fcc}), an “Fcc:” header is output.

	    %<{subject}Subject: Re: %{subject}\n%>\

       If a subject component was present, a suitable reply subject is output.

	    %<{message-id}In-Reply-To: %{message-id}\n%>\
	    %<{message-id}References: %<{references} %{references}%>\
	    %{message-id}\n%>
	    --------

       If a message-id component was present, an “In-Reply-To:” header is out‐
       put  including  the message-id, followed by a “References:” header with
       references, if present, and the message-id.  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:

	    if (comp_exists(message-id))  then
		 print (“In-reply-to: ”)
		 print (message-id.value)
		 print (“\n”)
	    endif
	    if (comp_exists(message-id)) then
		 print (“References: ”)
		 if (comp_exists(references)) then
		       print(references.value);
		 endif
		 print (message-id.value)
		 print (“\n”)
	    endif

       One more example: Currently, nmh supports very large  message  numbers,
       and  it	is  not uncommon for a folder to have far more than 10000 mes‐
       sages.  Nontheless (as noted above) the various scan format strings are
       inherited  from	older  MH  versions, and are generally hard-coded to 4
       digits of message number before formatting  problems  start  to	occur.
       The  nmh	 format	 strings  can be modified to behave more sensibly with
       larger message numbers:

	      %(void(msg))%<(gt 9999)%(msg)%|%4(msg)%>

       The current message number is placed in num.  (Note that	 (msg)	is  an
       int  function,  not a component.)  The (gt) conditional is used to test
       whether the message number has 5 or more digits.	 If so, it is  printed
       at full width, otherwise at 4 digits.

SEE ALSO
       scan(1), repl(1), ap(8), dp(8)

CONTEXT
       None

nmh-1.5-2			March 24, 2012			  MH-FORMAT(5)
[top]

List of man pages available for Cygwin

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net