groff
[Top][All Lists]
Advanced

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

[Groff] Re: getopt() as gtroff macro ?


From: Steve Izma
Subject: [Groff] Re: getopt() as gtroff macro ?
Date: Thu, 23 Sep 2004 13:56:42 -0500
User-agent: Mutt/1.3.28i

On Thu, Sep 23, 2004 at 08:22:50AM -0400, address@hidden wrote:
> From: Werner LEMBERG <address@hidden>
> Date: Thu, 23 Sep 2004 07:02:24 +0200 (CEST)
> To: address@hidden
> Cc: address@hidden
> Subject: Re: [Groff] Re: getopt() as gtroff macro ?
> Message: 2
> 
> > I recently heard that SoftQuad troff [...] had an undocumented
> > facility for local variables, [...]
> 
> This is on my TODO list.  It's not very complicated:
> 
>   Introduce a request `local' to tag local variables:
> 
>     .de foo
>     .  local nr bar 12345
>     ..
> 
>   The `local' prefix sets a flag within gtroff so that the `nr'
>   request saves the old value of `bar'.  After exiting the macro, the
>   value is restored.

This looks great to me. I think this is very important in
building a library of basic function macros, as in the Unix
tradition of having small, reusable tools. As a consequence we
could have small, self-contained macro files for particular
functions such as page breaking, running heads,
footnotes/endnotes, lists, floats, subheads, etc., and these
general-purpose files could be called like library functions by
a parent tmac file that sets the overall design parameters, such
as font family, point sizes, margins, trap positions, etc., and
doesn't need to worry about underlying details. Local variables
in the library files reduces our worries of stomping on variable
names used elsewhere.

> > I assume a related requirement would be to get .return to actually
> > return a value to the calling macro.
> 
> How shall this be done?  Similar to TeX, groff has no concept of
> returning a value.

I think this requires an inline macro call, I assume something
like this. Let's say we have a macro that calculates "feathering"
spacing after a subhead so that the first baseline of the text
following the subhead is at a point that's a multiple of the
default leading. I sometimes do this so that text baselines on
multiple-column pages line up with each other at the bottom of
the page.

Somewhere I recall a description of calling a macro (or perhaps a
string?) with an argument this way: \[macroname arg1], so that
you could do:

.sp \[calcspace \\n[sizeof_subhead]]u

With a getopt facility, one could set arguments and perform a
complex set of actions:

.de subhead1-start
.br
.di h1
.ev h1
' \" set or recall h1 parameters
..
.de subhead1-end
.br
.ev
.di
.setsubhead -d h1 -s 6p -e 4p
..

The usage for setsubhead would be:

-d diversion-name
-s space-before
-e space-after
-f      [flag to indicate feathering of space to even up the baselines]

or, for readability, using long options:

--divname diversion-name
--prespace space-before
--postspace space-after
--feather       [flag to indicate feathering of space to even up the baselines]

Then setsubhead would calculate the size of the diversion,
determine if it should feather the spacing before and after, then
call the diversion with the appropriate spacing.

> From: Keith MARSHALL <address@hidden>
> Date: Thu, 23 Sep 2004 09:40:27 +0100
> Subject: Re: [Groff] Re: getopt() as gtroff macro ?
> 
> The main problem I foresee is, how do you implement the call backs
> needed, to allow getopt's caller to handle the optional arguments
> as they are parsed?  This could end up being no simpler than the
> technique I suggested earlier, but it would be great if we can
> identify a viable solution.


> From: Werner LEMBERG <address@hidden>
> Date: Thu, 23 Sep 2004 13:20:47 +0200 (CEST)
> Subject: Re: [Groff] Re: getopt() as gtroff macro ?
> 
> 
> What about the following (inspired by Python's getopt module):
> 
>   .getopt <prefix> <options> <long options>
> 
> Example:
> 
>   .de foo
>   .  getopt "foox" "ac:" "--all --check="
>   .  ...
>   ..
> 
> The .getopt command would call the functions `<prefix>-<option>', passing
> the corresponding values as arguments.  `<prefix>-?' (with <option> as
> the argument) is called if <option> is invalid.  Finally, all
> non-option arguments are passed to a macro called `<prefix>'.
> 
> Calling the above function like this
> 
>   .foo -a -c bar --all --check=urgh --xxx arg1 arg2
> 
> would consequently call the functions
> 
>   .foox-a
>   .foox-c bar
>   .foox--all
>   .foox--check urgh
>   .foox-? --xxx
>   .foox arg1 arg2
> 
> It probably makes sense to provide a .gnu-getopt request also to
> reorder the arguments.
> 
> Comments, please.

Hmmm. I now realize I didn't think this through completely before
replying last time, so it's now more apparent to me what Keith
was doing.

I like python's facility for this, but one reason, I think, that
it works so well is because of how easy it is in python to step
through a list, so that you can set up a "while" loop and step
through each option and write the appropriate code for each one,
if it's present. I would prefer to avoid calling outside macros to
process the options and instead just be able to set flags and
variables.

How about having getopt set local variables based on the option
names, both the long or the short ones (one could choose between
readability and conciseness). Flags would always
be numeric (essentially boolean) and options with values would
always return a string, which if numeric would require a unit
designator (as above). If the string is used in a numeric
context, it would be converted to that first:

.de setsubhead
.getopt "d:e:fs:" "--divname --prespace --postspace --feather"
.ie \\n[feather] .nr fspace \[calcspace \\*[s]+\\*[e]+\\n[dn]u]/2u
.el .nr fspace 0
.sp \\*[prespace]+\\n[fspace]u
.nf
.\\*[divname]
.fi
.sp \\*[postspace]+\\n[fspace]u
..

I think the resulting code is a lot easier to understand than
when writing the same thing with \\$1, \\$2, etc.

        -- Steve

-- 
Steve Izma
    Computing Systems Administrator       (519) 884-0710 ext. 6125
    Wilfrid Laurier University Press      FAX: (519) 725-1399
    Waterloo, Ont., Canada N2L 3C5        address@hidden




reply via email to

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