groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[groff] 17/18: [docs]: Revise "Writing Macros" material.


From: G. Branden Robinson
Subject: [groff] 17/18: [docs]: Revise "Writing Macros" material.
Date: Fri, 20 Aug 2021 06:25:25 -0400 (EDT)

gbranden pushed a commit to branch master
in repository groff.

commit 07edefd1bb3cfd4b5a80832b42e7c8f1d612408d
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Fri Aug 20 18:32:58 2021 +1000

    [docs]: Revise "Writing Macros" material.
    
    * doc/groff.texi (Writing Macros): Revise.
      - Tighten wording.
      - Present `de` request thoroughly before moving on to its groff
        extension variants.
      - Revise, but comment out, an example of unsuccessful definition of
        `.` as an end macro, partly because it doesn't fit well in the PDF
        version of the Texinfo manual, but also because the topic can be
        discussed in a footnote and an example of something that _doesn't_
        work might be of questionable value.
      - Revise nested macro example to use only AT&T-compatible syntax.
        Drop use of font escapes since they don't illustrate anything
        relevant.
      - Push as much discussion of copy mode as possible into the node "Copy
        Mode".
      - Update example to correctly identify output to the standard error
        stream.
      - Shorten \$*/\$@/\$^ example to not cover \$1 and \$2 as well.
      - Fix error: diversions are not read in copy mode.  Problem introduced
        by me in 2a63d94e, 15 November 2020.
      - Expand discussion of copy mode in an effort to demystify it.
    
    * man/groff.7.man: Sync with our Texinfo manual, adding new section
      "Writing macros", adding subsection "Parameters", and demoting
      existing "Copy mode" section to subsection, paralleling Texinfo
      structure.
---
 doc/groff.texi  | 548 +++++++++++++++++++++++++++++++-------------------------
 man/groff.7.man | 248 +++++++++++++++++++++----
 2 files changed, 520 insertions(+), 276 deletions(-)

diff --git a/doc/groff.texi b/doc/groff.texi
index a84b189..6429533 100644
--- a/doc/groff.texi
+++ b/doc/groff.texi
@@ -12034,42 +12034,43 @@ restarting the next iteration.
 @cindex writing macros
 @cindex macros, writing
 
-A @dfn{macro} is a collection of text and embedded commands that can be
-invoked multiple times.  Use macros to define common operations.
+A @dfn{macro} is a stored collection of text and control lines that can
+be used multiple times.  Use macros to define common operations.
 @xref{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.
+While requests exist for the purpose of creating macros, simply
+interpolating an undefined macro will cause it to be defined as empty.
 @xref{Identifiers}.
 
-@DefreqList {de, name [@Var{end}]}
-@DefreqItemx {de1, name [@Var{end}]}
-@DefreqItemx {dei, name [@Var{end}]}
-@DefreqListEndx {dei1, name [@Var{end}]}
-Define a new macro named @var{name}.  GNU @code{troff} copies subsequent
-lines (starting with the next one) into an internal buffer until it
-encounters the line @samp{..} (two dots).  If the optional second
-argument to @code{de} is present it is used as the macro closure
-request instead of @samp{..}.
+@Defreq {de, name [@Var{end}]}
+Define a macro @var{name}, replacing the definition of any existing
+request, macro, string, or diversion called @var{name}.  GNU
+@code{troff} stores subsequent lines to an internal buffer in ``copy
+mode'' (see below).  If the optional second argument is not specified,
+the macro definition ends with the control line @samp{..} (two dots).
+Alternatively, @var{end} names a macro which, upon being subsequently
+called, ends the definition of @var{name}.
 
-There can be spaces or tabs after the first dot in the line containing
+Spaces or tabs are permitted after the first dot in the line containing
 the ending token (either @samp{.} or macro @samp{@var{end}}).  Don't
-insert a tab character immediately after the @samp{..}, otherwise it
-isn't recognized as the end-of-macro symbol.@footnote{While it is
-possible to define and call a macro @samp{.} with
-
-@Example
-.de .
-.  tm foo
-..
-.
-..    \" This calls macro '.'!
-@endExample
-
-@noindent
-you can't use this as the end-of-macro macro: during a macro definition,
-@samp{..} is never handled as a call to @samp{.}, even if you say
-@samp{.de foo .} explicitly.}
+insert a tab character immediately after the @samp{..}, or it will fail
+to be recognized as ending the macro definition.@footnote{While it is
+possible to define and call a macro @samp{.}, you can't use it as the
+end-of-macro macro: during a macro definition, @samp{..} is never
+handled as calling @samp{.}, even if you say @samp{.de @var{name} .}
+explicitly.}
+@c
+@c @Example
+@c .de .
+@c (dot macro)
+@c ..
+@c .
+@c ..    \" This calls macro '.'!
+@c .de m1 .
+@c (m1 macro)
+@c ..    \" This does not.
+@c .m1
+@c     @result{} (dot macro) (m1 macro)
+@c @endExample
 
 Here is a small example macro called @samp{P} that causes a break and
 inserts some vertical space.  It could be used to separate paragraphs.
@@ -12081,59 +12082,67 @@ inserts some vertical space.  It could be used to 
separate paragraphs.
 ..
 @endExample
 
-The following example defines a macro within another.  Remember that
-expansion must be protected twice; once for reading the macro and once
-for executing.
+We can define one macro within another.  Attempting to nest @samp{..}
+na�vely will end the outer definition because the inner definition
+isn't interpreted as such until the outer macro is later interpolated.
+We can use an end macro instead.  Each level of nesting should use a
+unique end macro.
 
 @Example
-\# a dummy macro to avoid a warning
-.de end
+.de en \" a do-nothing macro
 ..
-.
-.de foo
-.  de bar end
-.    nop \f[B]Hello \\\\$1!\f[]
-.  end
+.de mo
+.  de mi en
+Hello, Joe.
+What do you know?
+.  en
 ..
-.
-.foo
-.bar Joe
-    @result{} @b{Hello Joe!}
+.mo
+.mi
+    @result{} Hello, Joe.  What do you know?
 @endExample
 
 @noindent
-Since @code{\f} has no expansion, it isn't necessary to protect its
-backslash.  Had we defined another macro within @code{bar} that takes a
-parameter, eight backslashes would be necessary before @samp{$1}.
+A nested macro definition @emph{can} be terminated with @samp{..},
+and nested macros @emph{can} reuse end macros, but these control lines
+must be escaped twice for each level of nesting.  The necessity of this
+escaping and the utility of nested macro definitions will become clearer
+when we employ macro parameters and consider the behavior of copy mode
+in detail.
+@endDefreq
 
-The @code{de1} request turns off compatibility mode while executing the
-macro.  On entry, the current compatibility mode is saved and restored
-at exit.
+@Defreq {de1, name [@Var{end}]}
+The @code{de1} request defines a macro that executes with compatibility
+mode disabled (@pxref{Implementation Differences}).  On entry, the state
+of compatibility mode enablement is saved, and on exit it is restored.
+Observe the extra backlash before the interpolation of register
+@samp{xxx}; we'll explore this subject in @ref{Copy Mode}.
 
 @Example
 .nr xxx 12345
-.
 .de aa
 The value of xxx is \\n[xxx].
+.  br
 ..
 .de1 bb
 The value of xxx is \\n[xxx].
 ..
-.
 .cp 1
-.
 .aa
     @error{} warning: register '[' not defined
     @result{} The value of xxx is 0xxx].
 .bb
     @result{} The value of xxx is 12345.
 @endExample
+@endDefreq
 
-The @code{dei} request defines a macro indirectly.  That is, it expands
-strings whose names are @var{name} or @var{end} before performing the
-append.
+@DefreqList {dei, name [@Var{end}]}
+@DefreqListEndx {dei1, name [@Var{end}]}
+The @code{dei} request defines a macro indirectly.  That is, it
+interpolates strings named @var{name} and @var{end} before performing
+the definition.
 
-This:
+The following examples are equivalent.
 
 @Example
 .ds xx aa
@@ -12141,32 +12150,23 @@ This:
 .dei xx yy
 @endExample
 
-@noindent
-is equivalent to:
-
 @Example
 .de aa bb
 @endExample
 
-The @code{dei1} request is similar to @code{dei} but with compatibility
+The @code{dei1} request is similar to @code{dei}, but with compatibility
 mode switched off during execution of the defined macro.
 
-If compatibility mode is on, @code{de} (and @code{dei}) behave similar
-to @code{de1} (and @code{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.  @xref{Gtroff
-Internals}, for more information on switching compatibility mode on and
-off in a single document.
-
-@pindex trace.tmac
-Using @file{trace.tmac}, you can trace calls to @code{de} and
-@code{de1}.
+If compatibility mode is on, @code{de} and @code{dei} behave similarly
+to @code{de1} and @code{dei1}, respectively:@: a ``compatibility save''
+token is inserted at the beginning, and a ``compatibility restore''
+token at the end, with compatibility mode switched on during execution.
+@endDefreq
 
-Macro identifiers share their name space with those for strings and
+Macro identifiers share their name space with requests, strings, and
 diversions; @ref{Identifiers}.  @xref{als,,the description of the
 @code{als} request}, for possible pitfalls if redefining a macro that
 has been aliased.
-@endDefreq
 
 @DefreqList {am, name [@Var{end}]}
 @DefreqItemx {am1, name [@Var{end}]}
@@ -12174,10 +12174,11 @@ has been aliased.
 @DefreqListEndx {ami1, name [@Var{end}]}
 @cindex appending to a macro (@code{am})
 @cindex macro, appending to (@code{am})
-Works similarly to @code{de} except it appends onto the macro named
-@var{name}.  So, to make the previously defined @samp{P} macro set
-indented instead of block paragraphs, add the necessary code to the
-existing macro.
+@code{am} appends subsequent input lines to macro @var{name}, extending
+its definition, and otherwise working as @code{de} does.
+
+To make the previously defined @samp{P} macro set indented instead of
+block paragraphs, add the necessary code to the existing macro.
 
 @Example
 .am P
@@ -12185,25 +12186,25 @@ existing macro.
 ..
 @endExample
 
-The @code{am1} request turns off compatibility mode while executing the
-appended macro piece.  To be more precise, a @dfn{compatibility save}
-input token is inserted at the beginning of the appended code, and a
-@dfn{compatibility restore} input token at the end.
-
-The @code{ami} request appends indirectly, meaning that GNU @code{troff}
-expands strings whose names are @var{name} or @var{end} before
-performing the append.
-
-The @code{ami1} request is similar to @code{ami} but compatibility mode
-is switched off during execution of the defined macro.
+The other requests are analogous to their @samp{de} counterparts.  The
+@code{am1} request turns off compatibility mode while executing the
+appendment:@: a @dfn{compatibility save} input token is inserted before
+the appended input lines, and a @dfn{compatibility restore} input token
+after the end.  The @code{ami} request appends indirectly, meaning that
+strings @var{name} and @var{end} are interpolated with the resulting
+names used before appending.  The @code{ami1} request is similar to
+@code{ami}, disabling compatibility mode during interpretation of the
+appended lines.
+@endDefreq
 
 @pindex trace.tmac
-Using @file{trace.tmac}, you can trace calls to @code{am} and
-@code{am1}.
-@endDefreq
+Using @file{trace.tmac}, you can trace calls to @code{de},
+@code{de1}, @code{am}, and @code{am1}.  You can also use the
+@code{backtrace} request at any point desired to troubleshoot tricky
+spots (@pxref{Debugging}).
 
-@xref{Strings}, for the @code{als} and @code{rn} requests to create an
-alias and rename a macro, respectively.
+@xref{Strings}, for the @code{als}, @code{rm}, and @code{rn} requests to
+create an alias of, remove, and rename a macro, respectively.
 
 @cindex object creation
 The @code{am}, @code{as}, @code{da}, @code{de}, @code{di}, and @code{ds}
@@ -12213,10 +12214,9 @@ is defined as a request; normally, they modify the 
value of an existing
 object.
 
 @Defreq {return, [@Var{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
+Exit a macro, immediately returning to the caller.  If called with an
+argument @var{anything}, exit twice---the current macro and the macro
+one level higher.  This is used to define a wrapper macro for
 @code{return} in @file{trace.tmac}.
 @endDefreq
 
@@ -12231,90 +12231,96 @@ macro one level higher.  This is used to define a 
wrapper macro for
 @subsection Parameters
 @cindex parameters
 
-The arguments to a macro or string can be examined using a variety of
-escapes.
+Macro calls and string interpolations optionally accept a list of
+arguments; recall @ref{Request and Macro Arguments}.  At the time such
+an interpolation takes place, these @dfn{parameters} can be examined
+using a register and a variety of escape sequences starting with
+@code{\$}.
 
 @Defreg {.$}
-@cindex number of arguments register (@code{.$})
-The number of arguments passed to a macro or string.  This is a
-read-only register.
-
-The @code{shift} request can change its value.
+@cindex parameter count register (@code{.$})
+The count of parameters available to a macro or string is kept in this
+read-only register.  The @code{shift} request can change its value.
 @endDefreg
 
-Any individual argument can be retrieved with one of the following
-escapes:
+Any individual parameter can be accessed by its position in the list of
+arguments to the macro call, numbered from left to right starting at 1,
+with one of the following escapes.
 
 @DefescList {\\$, , n, }
 @DefescItem {\\$, (, nn, }
 @DefescListEnd {\\$, [, nnn, ]}
-@cindex copy mode, and macro arguments
-@cindex mode, copy, and macro arguments
-@cindex macro, arguments (@code{\$})
-@cindex arguments, macro (@code{\$})
-Retrieve the @var{n}@dmn{th}, @var{nn}@dmn{th} or @var{nnn}@dmn{th}
-argument.  As usual, the first form only accepts a single number (larger
-than zero), the second a two-digit number (larger than or equal
-to@tie{}10), and the third any positive integer value (larger than
-zero).  Macros and strings can have an unlimited number of arguments.
-Because string and macro definitions are read in copy mode, use two
-backslashes on these in practice to prevent their interpolation until
-the macro is actually invoked.
+Interpolate the @var{n}@dmn{th}, @var{nn}@dmn{th}, or @var{nnn}@dmn{th}
+parameter.  The first form only accepts a single digit
+(1@leq{}@var{n}@leq{}9)), the second two digits
+(01@leq{}@var{nn}@leq{}99)), and the third any positive integer
+@var{nnn}.  Macros and strings can accept an unlimited number of
+parameters.
 @endDefesc
 
 @Defreq {shift, [@Var{n}]}
-Shift the arguments 1@tie{}position, or as many positions as specified
-by its argument.  After executing this request, argument@tie{}@var{i}
-becomes argument @math{@var{i}-@var{n}}; arguments 1 to@tie{}@var{n} are
-no longer available.  Shifting by negative amounts is currently
-undefined.
-
-The register @code{.$} is adjusted accordingly.
+Shift the parameters @var{n} places (1@tie{}by default).  This is a
+``left shift'': what was parameter@tie{}@var{i} becomes parameter
+@math{@var{i}-@var{n}} and so on.  The parameters formerly in positions
+1 to@tie{}@var{n} are no longer available.  Shifting by a nonpositive
+amount performs no operation.  The register @code{.$} is adjusted
+accordingly.
 @endDefreq
 
-@DefescList {\\$*, , , }
-@DefescListEndx {\\$@@, , , }
-In some cases it is convenient to use all of the arguments at once (for
-example, to pass the arguments along to another macro).  The @code{\$*}
-escape concatenates all the arguments separated by spaces.  A similar
-escape is @code{\$@@}, which concatenates all the arguments with each
-surrounded by double quotes, and separated by spaces.  If not in
-compatibility mode, the interpolation depth of double quotes is
-preserved (@pxref{Request and Macro Arguments}).
-@endDefesc
+@cindex copy mode, and macro parameters
+@cindex mode, copy, and macro parameters
+@cindex macro, parameters (@code{\$})
+@cindex parameters, macro (@code{\$})
+In practice, parameter interpolations are usually seen prefixed with an
+extra escape character.  This is because the @code{\$} family of escape
+sequences is interpreted even in copy mode.@footnote{If they were not,
+parameter interpolations would be similar to command-line
+parameters---fixed for the entire duration of a @code{roff} program's
+run.  The advantage of interpolating @code{\$} escape sequences even in
+copy mode is that they can change from one interpolation to the next,
+like parameters to a function call.  The additional escape character is
+the price of this power.}
 
-@Defesc {\\$^, , , }
-Handle the parameters of a macro as if they were an argument to the
-@code{ds} or similar requests.
+@DefescList {\\$*, , , }
+@DefescItemx {\\$@@, , , }
+@DefescListEndx {\\$^, , , }
+In some cases it is convenient to interpolate all of the parameters at
+once (to pass them to a request, for instance).  The @code{\$*} escape
+concatenates the parameters, separating them with spaces.  @code{\$@@}
+is similar, concatenating the parameters, surrounding each by double
+quotes and separating them with spaces.  If not in compatibility mode,
+the interpolation depth of double quotes is preserved (@pxref{Request
+and Macro Arguments}).  @code{\$^} interpolates all parameters as if
+they were arguments to the @code{ds} request.
 
 @Example
 .de foo
-.  tm $1='\\$1'
-.  tm $2='\\$2'
 .  tm $*='\\$*'
 .  tm $@@='\\$@@'
 .  tm $^='\\$^'
 ..
 .foo " This is a "test"
-    @result{} $1=' This is a '
-    @result{} $2='test"'
-    @result{} $*=' This is a  test"'
-    @result{} $@@='" This is a " "test""'
-    @result{} $^='" This is a "test"'
-@endExample
-
-This escape is useful mainly for macro packages like @file{trace.tmac},
+    @error{} $*=' This is a  test"'
+    @error{} $@@='" This is a " "test""'
+    @error{} $^='" This is a "test"'
+@endExample
+
+@code{\$*} is useful when writing a macro that doesn't need to
+distinguish its arguments, or even to not interpret them; examples
+include macros that produce diagnostic messages by wrapping the
+@code{tm} or @code{ab} requests.  Use @code{\$@@} when writing a macro
+that may need to shift its parameters and/or wrap a macro or request
+that finds the count significant.  If in doubt, prefer @code{\$@@} to
+@code{\$*}.  An application of @code{\$^} is seen in @file{trace.tmac},
 which redefines some requests and macros for debugging purposes.
 @endDefesc
 
 @Defesc {\\$0, , , }
 @cindex macro name register (@code{\$0})
 @cindex @code{als} request, and @code{\$0}
-The name used to invoke the current macro.  The @code{als} request can
-make a macro have more than one name.
-
-If a macro is called as a string (within another macro), the value of
-@code{\$0} isn't changed.
+Interpolate the name by which the executing macro was called.  The
+@code{als} request can cause a macro to have more than one name.
+Applying string interpolation to a macro does not change this name.
 
 @Example
 .de foo
@@ -12350,8 +12356,6 @@ If a macro is called as a string (within another 
macro), the value of
 @endExample
 @endDefesc
 
-@xref{Request and Macro Arguments}.
-
 @c ---------------------------------------------------------------------
 
 @node Copy Mode, , Parameters, Writing Macros
@@ -12364,25 +12368,32 @@ If a macro is called as a string (within another 
macro), the value of
 @cindex @code{\n}, when reading text for a macro
 @cindex @code{\$}, when reading text for a macro
 @cindex @code{\*}, when reading text for a macro
-@cindex @code{\\}, when reading text for a macro
 @cindex \@key{RET}, when reading text for a macro
 When GNU @code{troff} processes certain requests, most importantly those
-which define or append to a macro, string, or diversion, it does so in
-@dfn{copy mode}: it copies the characters of the definition into a
-dedicated storage region, interpolating the escape sequences @code{\n},
-@code{\g}, @code{\$}, @code{\*}, and @code{\V} normally; interpreting
-@code{\.} and @code{\@key{RET}} immediately; discarding comments
-@code{\"} and @code{\#}; interpolating the current leader, escape, or
-tab character with @code{\a}, @code{\e} or @code{\E}, and @code{\t},
-respectively; and storing all other escape sequences in an encoded form.
-@xref{Character Translations} for more on the use of @code{\e} and
-@code{\E}, and the distinction between them.
-
-Since the escape character escapes itself, you can control whether any
-escape sequence is interpreted at macro definition time or when it is
-later interpolated by preceding it with an additional instance of the
-escape character.@footnote{Compare this to the @code{\def} and
-@code{\edef} commands in @TeX{}.}
+which define or append to a macro or string, it does so in @dfn{copy
+mode}: it copies the characters of the definition into a dedicated
+storage region, interpolating the escape sequences @code{\n}, @code{\g},
+@code{\$}, @code{\*}, and @code{\V} normally; interpreting
+@code{\@key{RET}} immediately; discarding comments @code{\"} and
+@code{\#}; interpolating the current leader, escape, or tab character
+with @code{\a}, @code{\e}, and @code{\t}, respectively; and storing all
+other escape sequences in an encoded form.
+
+@cindex interpretation mode
+@cindex mode, interpretation
+The complement of copy mode---a @code{roff} formatter's behavior when
+not defining or appending to a macro, string, or diversion---where all
+macros are interpolated, requests invoked, and valid escape sequences
+processed immediately upon recognition, can be termed
+@dfn{interpretation mode}.
+
+@Defesc {\\\\, , , }
+The escape character, @code{\} by default, escapes itself.  Thus you can
+control whether a given @code{\n}, @code{\g}, @code{\$}, @code{\*}, or
+@code{\V} escape sequence is interpreted at the time the macro
+containing it is defined, or later when the macro is
+called.@footnote{Compare this to the @code{\def} and @code{\edef}
+commands in @TeX{}.}
 
 @Example
 .nr x 20
@@ -12395,98 +12406,151 @@ escape character.@footnote{Compare this to the 
@code{\def} and
     @result{} 20 10
 @endExample
 
-@cindex interpretation mode
-@cindex mode, interpretation
-The complement of copy mode---a @code{roff} formatter's behavior when
-not defining or appending to a macro, string, or diversion---where all
-macros are interpolated, requests invoked, and valid escape sequences
-processed immediately upon recognition, can be termed
-@dfn{interpretation mode}.
-
-@DefescList {\\\\, , , }
-@DefescListEndx {\\E, , , }
-@code{\\} is a `delayed' backslash; more precisely, it is the default
-escape character followed by a backslash, which no longer has special
-meaning due to the leading escape character.  It is @emph{not} an escape
-sequence in the usual sense!  In any unknown escape sequence
-@code{\@var{X}} the escape character is ignored and @var{X} is printed.
-But if @var{X} is equal to the current escape character, no warning is
-emitted.
-
-@cindex @code{\E}, and copy mode
-@cindex copy mode, and @code{\E}
-@cindex mode, copy, and @code{\E}
-As a consequence, only at the top level or in a diversion is a backslash
-glyph printed; in copy mode, it expands to a single backslash, which
-then combines with the following character to form an escape sequence.
+You can think of @code{\\} as a ``delayed'' backslash; it is the escape
+character followed by a backslash from which the escape character has
+removed its special meaning.  Consequently, @samp{\\} is not an escape
+sequence in the usual sense.  In any escape sequence @samp{\@var{X}}
+that GNU @code{troff} does not recognize, the escape character is
+ignored and @var{X} is output, with two exceptions---@samp{\\} is the
+first.
+@endDefesc
 
-The @code{\E} escape differs from @code{\e} by printing an escape
-character that is not interpreted in copy mode.  Use this to define
-strings with escapes that work when used in copy mode (for example, as a
-macro argument).  The following example defines strings to begin and end
-a superscript:
+@cindex @code{\\}, when reading text for a macro
+@Defesc {\\., , , }
+@code{\.} escapes the control character.  It is similar to @code{\\} in
+that it isn't a true escape sequence.  It is used to permit nested macro
+definitions to end without a named macro call to conclude them.  Without
+a syntax for escaping the control character, this would not be possible.
 
 @Example
-.ds @{ \v'-.3m'\s'\En[.s]*60/100'
-.ds @} \s0\v'.3m'
+.de m1
+foo
+.
+.  de m2
+bar
+\\..
+.
+..
+.foo
+.bar
+    @result{} foo bar
 @endExample
 
-Another example to demonstrate the differences between the various
-escape sequences, using a strange escape character, @samp{-}.
+@noindent
+The first backslash is consumed while the macro is read, and the second
+is interpreted while executing macro @code{foo}.
+@endDefesc
+
+@code{roff} documents should not use the @code{\\} or @code{\.}
+tokens outside of copy mode; they serve only to obfuscate the input.
+Use @code{\e} to obtain the escape character, @code{\[rs]} to obtain a
+backslash glyph, and @code{\&} before @code{.} and @code{'} where GNU
+@code{troff} expects them as control characters if you mean to use them
+literally (recall @ref{Requests and Macros}).
+
+Macro definitions can be nested to arbitrary depth.  The mechanics of
+parsing the escape character have significant consequences for this
+practice.
 
 @Example
-.ec -
-.de xxx
---A'foo'
+.de M1
+\\$1
+.  de M2
+\\\\$1
+.    de M3
+\\\\\\\\$1
+\\\\..
+.    M3 hand.
+\\..
+.  M2 of
 ..
-.xxx
-    @result{} -A'foo'
+This is getting
+.M1 out
+    @result{} This is getting out of hand.
+@endExample
+
+Each escape character is interpreted twice---once in copy mode, when the
+macro is defined, and once in interpretation mode, when it is executed.
+As seen above, this fact leads to exponential growth in the number of
+escape characters required to delay interpolation of @code{\n},
+@code{\g}, @code{\$}, @code{\*}, and @code{\V} at each nesting level,
+which can be daunting.  GNU @code{troff} offers a solution.
+
+@Defesc {\\E, , , }
+@code{\E} represents an escape character that is not interpreted in copy
+mode.  You can use it to ease the writing of nested macro definitions.
+
+@Example
+.de M1
+.  nop \E$1
+.  de M2
+.    nop \E$1
+.    de M3
+.      nop \E$1
+\\\\..
+.    M3 better.
+\\..
+.  M2 bit
+..
+This vehicle handles
+.M1 a
+    @result{} This vehicle handles a bit better.
 @endExample
 
-@noindent
-The result is surprising for most users, expecting @samp{1} since
-@samp{foo} is a valid identifier.  What has happened?  As mentioned
-above, the leading escape character makes the following character
-ordinary.  Written with the default escape character the sequence
-@samp{--} becomes @samp{\-}---this is the minus sign.
+Observe that because @code{\.} is not a true escape sequence, we can't
+use @code{\E} to keep @samp{..} from ending a macro definition
+prematurely.  If the multiplicity of backslashes complicates
+maintenance, use end macros.
 
-If the escape character followed by itself is a valid escape sequence,
-only @code{\E} yields the expected result:
+@code{\E} is also convenient to define strings that contain escape
+sequences that need to work when used in copy mode (for example, as
+macro arguments) We might define strings to begin and end superscripting
+as follows.@footnote{These are lightly adapted from the @code{groff}
+implmentation of the @file{ms} macros.}
 
 @Example
-.ec -
-.de xxx
--EA'foo'
-..
-.xxx
-    @result{} 1
+.ds @{ \v'-.9m\s'\En[.s]*7u/10u'+.7m'
+.ds @} \v'-.7m\s0+.9m'
 @endExample
-@endDefesc
 
-@Defesc {\\., , , }
-Similar to @code{\\}, the sequence @code{\.} isn't a real escape
-sequence.  As before, a warning message is suppressed if the escape
-character is followed by a dot, and the dot itself is printed.
+When the @code{ec} request is used to redefine the escape character,
+@code{\E} also makes it easier to distinguish the semantics of an escape
+character from the other meaning(s) its character might have.  Consider
+the use of an unusual escape character, @samp{-}.
 
 @Example
-.de foo
-.  nop foo
-.
-.  de bar
-.    nop bar
-\\..
-.
+.nr a 1
+.ec -
+.de xx
+--na
 ..
-.foo
-.bar
-    @result{} foo bar
+.xx
+    @result{} -na
 @endExample
 
 @noindent
-The first backslash is consumed while the macro is read, and the second
-is swallowed while executing macro @code{foo}.
+This result may surprise you; some people expect @samp{1} to be output
+since register @samp{a} has clearly been defined with that value.  What
+has happened?  The robotic replacement of @samp{\} with @samp{-} has led
+us astray.  As mentioned above, the leading escape character makes
+the following character ordinary.  Written with the default escape
+character, the sequence @samp{--} becomes @samp{\-}, which you may
+recognize as the special character escape sequence for the minus sign
+glyph.  Since the escape character followed by itself is a valid escape
+sequence, only @code{\E} yields the expected result.
+
+@Example
+.nr a 1
+.ec -
+.de xx
+-Ena
+..
+.xx
+    @result{} 1
+@endExample
 @endDefesc
 
+
 @c =====================================================================
 
 @node Page Motions, Drawing Requests, Writing Macros, gtroff Reference
diff --git a/man/groff.7.man b/man/groff.7.man
index 65114ff..927f38a 100644
--- a/man/groff.7.man
+++ b/man/groff.7.man
@@ -5299,64 +5299,132 @@ such as formatting the calendar date.
 .
 .
 .\" ====================================================================
-.SH "Copy mode"
+.SH "Writing macros"
+.\" ====================================================================
+.
+The
+.B .de
+request defines a macro replacing the definition of any existing
+request,
+macro,
+string,
+or diversion of the same name.
+.
+.I \%@g@troff
+stores subsequent lines to an internal buffer in \[lq]copy mode\[rq]
+(see below).
+.
+If the optional second argument is not specified,
+the macro definition ends with the control line
+.RB \[lq] .. \[rq]\&
+(two dots).
+.
+Alternatively,
+a second argument names a macro which,
+upon being subsequently called,
+ends the macro definition in progress.
+.
+Spaces or tabs are permitted after the first dot in the line containing
+the ending token.
+.
+Macro definitions can be nested;
+this requires use of unique end macros for each nested definition or
+escaping of the line with the ending token.
+.
+.
+.P
+Variants of
+.B .de
+that disable compatibility mode and/or indirect the names of the macros
+being defined or ending the definition through a string are available as
+.BR .de1 ,
+.BR .dei ,
+and
+.BR .dei1 .
+.
+Existing macro definitions can be appended to with
+.BR .am ,
+.BR .am1 ,
+.BR .ami ,
+and
+.BR .ami1 .
+.
+The
+.BR .als ,
+.BR .rm ,
+and
+.B .rn
+requests create an alias of,
+remove,
+and rename a macro,
+respectively.
+.
+.B .return
+stops the execution of a macro immediately,
+returning to the enclosing context.
+.
+.
+.\" ====================================================================
+.SS Parameters
+.\" ====================================================================
+.
+Macro calls and string parameters can be accessed using the
+.B \[rs]$
+escapes.
+.
+The
+.B \[rs]n[.$]
+read-only register stores the count of parameters available to a macro
+or string;
+its value can be changed by the
+.B .shift
+request,
+which dequeues parameters from the current list.
+.
+The
+.B \[rs]$0
+escape sequence interpolates the name by which a macro was called.
+.
+Applying string interpolation to a macro does not change this name.
+.
+.
+.\" ====================================================================
+.SS "Copy mode"
 .\" ====================================================================
 .
 When
 .I \%@g@troff
 processes certain requests,
-most importantly those which define or append to a macro,
-string,
-or diversion,
+most importantly those which define or append to a macro or string,
 it does so in
 .IR "copy mode" :
 it copies the characters of the definition into a dedicated storage
 region,
 interpolating the escape sequences
-.esc n ,
-.esc g ,
-.esc $ ,
-.esc * ,
+.BR \[rs] n ,
+.BR \[rs] g ,
+.BR \[rs] $ ,
+.BR \[rs] * ,
 and
-.esc V
+.B \[rs] V
 normally;
 interpreting
-.esc .\&
-and
 .BI \[rs] newline
 immediately;
 discarding comments
-.esc "
+.BR \[rs] "
 and
-.esc # ;
+.BR \[rs] # ;
 interpolating the current leader,
 escape,
 or tab character with
-.esc a ,
-.esc e
-or
-.esc E ,
+.BR \[rs] a ,
+.BR \[rs] e ,
 and
-.esc t ,
+.BR \[rs] t ,
 respectively;
 and storing all other escape sequences in an encoded form.
 .
-See section \[lq]Character Translations\[rq] of the
-.I groff
-Texinfo manual
-for more on the use of
-.esc e
-and
-.esc E ,
-and the distinction between them.
-.
-.
-.P
-Since the escape character escapes itself,
-you can control whether any escape sequence is interpreted at macro
-definition time or when it is later interpolated by preceding it with an
-additional instance of the escape character.
-.
 The complement of copy mode\[em]a
 .I roff
 formatter's behavior when not defining or appending to a macro,
@@ -5368,6 +5436,118 @@ can be termed
 .IR "interpretation mode" .
 .
 .
+.P
+The escape character,
+.B \[rs]
+by default,
+escapes itself.
+.
+Thus you can control whether a given
+.BR \[rs] n ,
+.BR \[rs] g ,
+.BR \[rs] $ ,
+.BR \[rs] * ,
+or
+.B \[rs] V
+escape sequence is interpreted at the time the macro containing it is
+defined,
+or later when the macro is called.
+.
+.
+.P
+You can think of
+.B \[rs]\[rs]
+as a \[lq]delayed\[rq] backslash;
+it is the escape character followed by a backslash from which the escape
+character has removed its special meaning.
+.
+Consequently,
+.B \[rs]\[rs]
+is not an escape sequence in the usual sense.
+.
+In any escape sequence
+.BI \[rs] X
+that
+.I \%@g@troff
+does not recognize,
+the escape character is ignored and
+.IR X \~is
+output,
+with two exceptions,
+.B \[rs]\[rs]
+being one.
+.
+The other is
+.BR \[rs]. ,
+which escapes the control character.
+.
+It is used to permit nested macro definitions to end without a named
+macro call to conclude them.
+.
+Without a syntax for escaping the control character,
+this would not be possible.
+.
+.I roff
+documents should not use the
+.B \[rs]\[rs]
+or
+.B \[rs].\&
+tokens outside of copy mode;
+they serve only to obfuscate the input.
+.
+Use
+.B \[rs]e
+to obtain the escape character,
+.B \[rs][rs]
+to obtain a backslash glyph,
+and
+.B \[rs]&
+before
+.RB \[lq] . \[rq]
+and
+.RB \[lq] \[aq] \[rq]
+where
+.I \%@g@troff
+expects them as control characters if you mean to use them literally.
+.
+.
+.P
+Macro definitions can be nested to arbitrary depth.
+.
+Each escape character is interpreted twice\[em]once in copy mode,
+when the macro is defined,
+and once in interpretation mode,
+when it is executed.
+.
+This fact leads to exponential growth in the number of escape characters
+required to delay interpolation of
+.BR \[rs] n ,
+.BR \[rs] g ,
+.BR \[rs] $ ,
+.BR \[rs] * ,
+and
+.B \[rs] V
+at each nesting level.
+.
+An alternative is to use
+.BR \[rs]E ,
+which represents an escape character that is not interpreted in copy
+mode.
+.
+Because
+.B \[rs].\&
+is not a true escape sequence,
+we can't use
+.B \[rs]E
+to keep
+.RB \[lq] ..\& \[rq]
+from ending a macro definition prematurely.
+.
+If the multiplicity of backslashes complicates
+maintenance,
+use end macros.
+.
+.
 .\" ====================================================================
 .SH Traps
 .\" ====================================================================



reply via email to

[Prev in Thread] Current Thread [Next in Thread]