groff: Writing Macros

 
 5.21 Writing Macros
 ===================
 
 A "macro" is a collection of text and embedded commands that can be
 invoked multiple times.  Use macros to define common operations.  See
 Strings, for a (limited) alternative syntax to call macros.
 
    Although the following requests can be used to create macros, simply
 using an undefined macro will cause it to be defined as empty.  See
 Identifiers.
 
  -- Request: .de name [end]
  -- Request: .de1 name [end]
  -- Request: .dei name [end]
  -- Request: .dei1 name [end]
      Define a new macro named NAME.  'gtroff' copies subsequent lines
      (starting with the next one) into an internal buffer until it
      encounters the line '..' (two dots).  If the optional second
      argument to 'de' is present it is used as the macro closure request
      instead of '..'.
 
      There can be whitespace after the first dot in the line containing
      the ending token (either '.' or macro 'END').  Don't insert a tab
      character immediately after the '..', otherwise it isn't recognized
      as the end-of-macro symbol.(1)  (SeeWriting Macros-Footnote-1)
 
      Here a small example macro called 'P' that causes a break and
      inserts some vertical space.  It could be used to separate
      paragraphs.
 
           .de P
           .  br
           .  sp .8v
           ..
 
      The following example defines a macro within another.  Remember
      that expansion must be protected twice; once for reading the macro
      and once for executing.
 
           \# a dummy macro to avoid a warning
           .de end
           ..
           .
           .de foo
           .  de bar end
           .    nop \f[B]Hallo \\\\$1!\f[]
           .  end
           ..
           .
           .foo
           .bar Joe
               => Hallo Joe!
 
      Since '\f' has no expansion, it isn't necessary to protect its
      backslash.  Had we defined another macro within 'bar' that takes a
      parameter, eight backslashes would be necessary before '$1'.
 
      The 'de1' request turns off compatibility mode while executing the
      macro.  On entry, the current compatibility mode is saved and
      restored at exit.
 
           .nr xxx 12345
           .
           .de aa
           The value of xxx is \\n[xxx].
           ..
           .de1 bb
           The value of xxx ix \\n[xxx].
           ..
           .
           .cp 1
           .
           .aa
               => warning: number register `[' not defined
               => The value of xxx is 0xxx].
           .bb
               => The value of xxx ix 12345.
 
      The 'dei' request defines a macro indirectly.  That is, it expands
      strings whose names are NAME or END before performing the append.
 
      This:
 
           .ds xx aa
           .ds yy bb
           .dei xx yy
 
      is equivalent to:
 
           .de aa bb
 
      The 'dei1' request is similar to 'dei' but with compatibility mode
      switched off during execution of the defined macro.
 
      If compatibility mode is on, 'de' (and 'dei') behave similar to
      'de1' (and 'dei1'): A 'compatibility save' token is inserted at the
      beginning, and a 'compatibility restore' token at the end, with
      compatibility mode switched on during execution.  SeeGtroff
      Internals, for more information on switching compatibility mode
      on and off in a single document.
 
      Using 'trace.tmac', you can trace calls to 'de' and 'de1'.
 
      Note that macro identifiers are shared with identifiers for strings
      and diversions.
 
      Seethe description of the 'als' request als, for possible
      pitfalls if redefining a macro that has been aliased.
 
  -- Request: .am name [end]
  -- Request: .am1 name [end]
  -- Request: .ami name [end]
  -- Request: .ami1 name [end]
      Works similarly to 'de' except it appends onto the macro named
      NAME.  So, to make the previously defined 'P' macro actually do
      indented instead of block paragraphs, add the necessary code to the
      existing macro like this:
 
           .am P
           .ti +5n
           ..
 
      The 'am1' request turns off compatibility mode while executing the
      appended macro piece.  To be more precise, a "compatibility save"
      input token is inserted at the beginning of the appended code, and
      a "compatibility restore" input token at the end.
 
      The 'ami' request appends indirectly, meaning that 'gtroff' expands
      strings whose names are NAME or END before performing the append.
 
      The 'ami1' request is similar to 'ami' but compatibility mode is
      switched off during execution of the defined macro.
 
      Using 'trace.tmac', you can trace calls to 'am' and 'am1'.
 
    SeeStrings, for the 'als' and 'rn' request to create an alias
 and rename a macro, respectively.
 
    The 'de', 'am', 'di', 'da', 'ds', and 'as' requests (together with
 its variants) only create a new object if the name of the macro,
 diversion or string diversion is currently undefined or if it is defined
 to be a request; normally they modify the value of an existing object.
 
  -- Request: .return [anything]
      Exit a macro, immediately returning to the caller.
 
      If called with an argument, exit twice, namely the current macro
      and the macro one level higher.  This is used to define a wrapper
      macro for 'return' in 'trace.tmac'.
 

Menu