groff: Strings

 
 5.22 Strings
 ============
 
 GNU 'troff' supports strings primarily for user convenience.
 Conventionally, if one would define a macro only to interpolate a small
 amount of text, without invoking requests or calling any other macros,
 one defines a string instead.  Only one string is predefined by the
 language.
 
  -- String: \*[.T]
      Contains the name of the output device (for example, 'utf8' or
      'pdf').
 
    The 'ds' request creates a string with a specified name and contents
 and the '\*' escape sequence dereferences its name, interpolating its
 contents.  If the string named by the '\*' escape sequence does not
 exist, it is defined as empty, nothing is interpolated, and a warning in
 category 'mac' is emitted.  ⇒Warnings, for information about the
 enablement and suppression of warnings.
 
  -- Request: .ds name [contents]
  -- Request: .ds1 name [contents]
  -- Escape sequence: \*n
  -- Escape sequence: \*(nm
  -- Escape sequence: \*[name [arg1 arg2 ...]]
      Define a string called NAME with contents CONTENTS.  If NAME
      already exists as an alias, the target of the alias is redefined;
      see 'als' and 'rm' below.  If 'ds' is called with only one
      argument, NAME is defined as an empty string.  Otherwise, GNU
      Strings-Footnote-1::)
 
      The '\*' escape sequence interpolates a previously defined string
      variable NAME (one-character name N, two-character name NM).  The
      bracketed interpolation form accepts arguments that are handled as
      macro arguments are; recall ⇒Calling Macros.  In contrast to
      macro calls, however, if a closing bracket ']' occurs in a string
      argument, that argument must be enclosed in double quotes.  '\*' is
      interpreted even in copy mode.  When defining strings, argument
      interpolations must be escaped if they are to reference parameters
      from the calling context; ⇒Parameters.
 
           .ds cite (\\$1, \\$2)
           Gray codes are explored in \*[cite Morgan 1998].
               => Gray codes are explored in (Morgan, 1998).
 
      *Caution:* Unlike other requests, the second argument to the 'ds'
      request consumes the remainder of the input line, including
      trailing spaces.  This means that comments on a line with such a
      request can introduce unwanted space into a string when they are
      set off from the material they annotate, as is conventional.
 
           .ds H2O H\v'+.3m'\s'-2'2\v'-.3m'\s0O \" water
 
      Instead, place the comment on another line or put the comment
      escape sequence immediately adjacent to the last character of the
      string.
 
           .ds H2O H\v'+.3m'\s'-2'2\v'-.3m'\s0O\" water
 
      Ending string definitions (and appendments) with a comment, even an
      empty one, prevents unwanted space from creeping into them during
      source document maintenance.
 
           .ds author Alice Pleasance Liddell\"
           .ds empty \" might be appended to later with .as
 
      An initial neutral double quote '"' in CONTENTS is stripped to
      allow embedding of leading spaces.  Any other '"' is interpreted
      literally, but it is wise to use the special character escape
      sequence '\[dq]' instead if the string might be interpolated as
      part of a macro argument; see ⇒Calling Macros.
 
           .ds salutation "         Yours in a white wine sauce,\"
           .ds c-var-defn "  char mydate[]=\[dq]2020-07-29\[dq];\"
 
      Strings are not limited to a single input line of text.  '\<RET>'
      works just as it does elsewhere.  The resulting string is stored
      _without_ the newlines.  Care is therefore required when
      interpolating strings while filling is disabled.
 
           .ds foo This string contains \
           text on multiple lines \
           of input.
 
      It is not possible to embed a newline in a string that will be
      interpreted as such when the string is interpolated.  To achieve
      that effect, use '\*' to interpolate a macro instead; see ⇒
      Punning Names.
 
      Because strings are similar to macros, they too can be defined so
      as to suppress AT&T 'troff' compatibility mode when used; see ⇒
      Writing Macros and ⇒Compatibility Mode.  The 'ds1' request
      defines a string such that compatibility mode is off when the
      string is later interpolated.  To be more precise, a "compatibility
      save" input token is inserted at the beginning of the string, and a
      "compatibility restore" input token at the end.
 
           .nr xxx 12345
           .ds aa The value of xxx is \\n[xxx].
           .ds1 bb The value of xxx is \\n[xxx].
           .
           .cp 1
           .
           \*(aa
               error-> warning: register '[' not defined
               => The value of xxx is 0xxx].
           \*(bb
               => The value of xxx is 12345.
 
  -- Request: .as name [contents]
  -- Request: .as1 name [contents]
      The 'as' request is similar to 'ds' but appends CONTENTS to the
      string stored as NAME instead of redefining it.  If NAME doesn't
      exist yet, it is created.  If 'as' is called with only one
      argument, no operation is performed (beyond dereferencing the
      string).
 
           .as salutation " with shallots, onions and garlic,\"
 
      The 'as1' request is similar to 'as', but compatibility mode is
      switched off when the appended portion of the string is later
      interpolated.  To be more precise, a "compatibility save" input
      token is inserted at the beginning of the appended string, and a
      "compatibility restore" input token at the end.
 
    Several requests exist to perform rudimentary string operations.
 Strings can be queried ('length') and modified ('chop', 'substring',
 'stringup', 'stringdown'), and their names can be manipulated through
 renaming, removal, and aliasing ('rn', 'rm', 'als').
 
  -- Request: .length reg anything
      Compute the number of characters of ANYTHING and store the count in
      the register REG.  If REG doesn't exist, it is created.  ANYTHING
      is read in copy mode.
 
           .ds xxx abcd\h'3i'efgh
           .length yyy \*[xxx]
           \n[yyy]
               => 14
 
  -- Request: .chop object
      Remove the last character from the macro, string, or diversion
      named OBJECT.  This is useful for removing the newline from the end
      of a diversion that is to be interpolated as a string.  This
      request can be used repeatedly on the same OBJECT; see ⇒Gtroff
      Internals, for details on nodes inserted additionally by GNU
      'troff'.
 
  -- Request: .substring str start [end]
      Replace the string named STR with its substring bounded by the
      indices START and END, inclusively.  The first character in the
      string has index 0.  If END is omitted, it is implicitly set to the
      largest valid value (the string length minus one).  Negative
      indices count backward from the end of the string: the last
      character has index -1, the character before the last has index -2,
      and so on.
 
           .ds xxx abcdefgh
           .substring xxx 1 -4
           \*[xxx]
               => bcde
           .substring xxx 2
           \*[xxx]
               => de
 
  -- Request: .stringdown str
  -- Request: .stringup str
      Alter the string named STR by replacing each of its bytes with its
      lowercase ('stringdown') or uppercase ('stringup') version (if one
      exists).  Special characters in the string will often transform in
      the expected way due to the regular naming convention for accented
      characters.  When they do not, use substrings and/or catenation.
 
           .ds resume R\['e]sum\['e]
           \*[resume]
           .stringdown resume
           \*[resume]
           .stringup resume
           \*[resume]
               => Résumé résumé RÉSUMÉ
 
    (In practice, we would end the 'ds' request with a comment escape
 '\"' to prevent space from creeping into the definition during source
 document maintenance.)
 
  -- Request: .rn old new
      Rename the request, macro, diversion, or string OLD to NEW.
 
  -- Request: .rm name
      Remove the request, macro, diversion, or string NAME.  GNU 'troff'
      treats subsequent invocations as if the name had never been
      defined.
 
  -- Request: .als new old
      Create an alias NEW for the existing request, string, macro, or
      diversion object named OLD, causing the names to refer to the same
      stored object.  If OLD is undefined, a warning in category 'mac' is
      produced, and the request is ignored.  ⇒Warnings, for
      information about the enablement and suppression of warnings.
 
      To understand how the 'als' request works, consider two different
      storage pools: one for objects (macros, strings, etc.), and another
      for names.  As soon as an object is defined, GNU 'troff' adds it to
      the object pool, adds its name to the name pool, and creates a link
      between them.  When 'als' creates an alias, it adds a new name to
      the name pool that gets linked to the same object as the old name.
 
      Now consider this example.
 
           .de foo
           ..
           .
           .als bar foo
           .
           .de bar
           .  foo
           ..
           .
           .bar
               error-> input stack limit exceeded (probable infinite
               error-> loop)
 
      In the above, 'bar' remains an _alias_--another name for--the
      object referred to by 'foo', which the second 'de' request
      replaces.  Alternatively, imagine that the 'de' request
      _dereferences_ its argument before replacing it.  Either way, the
      result of calling 'bar' is a recursive loop that finally leads to
      an error.  ⇒Writing Macros.
 
      To remove an alias, call 'rm' on its name.  The object itself is
      not destroyed until it has no more names.
 
      When a request, macro, string, or diversion is aliased,
      redefinitions and appendments "write through" alias names.  To
      replace an alias with a separately defined object, you must use the
      'rm' request on its name first.