TOC |
latest revision: 12-08-03 14:13:30
14 June 2003 |
The size of this manual is getting ridiculous. Working on it (the doc macros need chapter mode).
Zoem: <Dutch> The sound made by electrical devices and flying bugs.
Zoem is an interpretive macro language with substantial facilities for programming. It supports a two-stage process, consisting of macro interpretation (featuring inside-out evaluation if needed), followed by a simple and powerful application of stream character filtering. Its syntax is reminiscent of TeX's, it has dictionary stacks like PostScript, and various resemblances to m4 and info. It has interfaces to modules making life easy - counters, references, arithmetic, multi-dimensional data storage, input/output operations, and regular expressions.
Zoem is used for creating extendible dummy mark-up languages and mapping those to real mark-up languages. The dummy languages have all the power of the zoem primitives available to them. A prime application is the creation of little mark-up languages that allow easy preparation of documents for use with different devices. Two examples are the zoem faq language and the zoem man language. Both provide a concise and easily extendible format with which FAQs and manual pages can be written in a single source file for output in either HTML or troff. The two languages are compact and easy to type. This document itself was generated using the zoem doc language. And yes, I was tempted to call zoem TUAT instead, The Umpteenth Authoring Tool.
This manual covers the whole zoem language. A large part of it is only interesting for someone writing a reusable macro package. A smaller part is still interesting for someone who is just using such a package, but might want to add some utilities and shortcuts of his own. The part where file inclusion, macro definitions, and macro expansions are explained is required reading for anyone considering or planning to use zoem. The manual also covers an example manual page written using the zoem manual macros, and the results after conversion to html and (PostScript generated from) troff (Section 10, see the table of contents below).
* | ||
* | ||
* | ||
* |
Small examples are littered throughout this manual. If you want to see examples of what can be achieved using zoem, visit Section 10.
Clicking on the number to the left of a section title (e.g. the 1.1 to the left of the title About this document of this section) will get you to the corresponding section of the table of contents.
Zoem input and zoem output are both generally shown in a typeface font, like this.
Links that point to locations within this document are shown in blueish colors. Links that point to documents originating from the same package (project) or perhaps the same site are shown in in greenish colors. Links that point to other stations on the internet or perhaps other packages on the same site are shown in in reddish colors.
The zoem doc macros provide arbitrarily deeply nesting sections. This silly section is a level 3 section.
TOP | ||||||||||||||||||||||||||||||||||||||
1 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
2 . | ||||||||||||||||||||||||||||||||||||||
3 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
4 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
5 . | ||||||||||||||||||||||||||||||||||||||
6 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
7 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
8 . | ||||||||||||||||||||||||||||||||||||||
9 . | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
10 . | ||||||||||||||||||||||||||||||||||||||
11 . |
Zoem was first used for generating manual pages in both HTML and troff from the same source. A table of contents is automatically added if desired and cross-references show up as links in HTML. This functionality is not directly supported by Zoem; it is obtained by assembling Zoem primitives into higher-level units. These particular units are one possible set of Zoem man macros. Normally, not a single zoem primitive is encountered in a zoem manual page - it should consist of high-level macros only. The largest part of this manual is concerned with the zoem primitives and how to assemble them into macro packages that facilitate mapping input to different devices. However,
A simple hello world example shows the basic idea behind zoem. For an example manual page view (in this document) the zoem source, the rendered html resulting from that source, and (external document) the rendered PostScript compiled from the troff source compiled from the zoem source. An annotated list of the manual macros is given in the man_zmm manual page.
Zoem supports several programming constructs, immediate and postponed expansions, stream character filtering, easy I/O facilities, integer arithmetic, and a whole lot more. Its four main aims are:
* |
Providing the building blocks for a structural and programmable approach.
Section 3.3
contains an overview of the zoem primitives and their use.
|
|
* |
Accepting a pleasant syntax that does not require much thinking,
favouring simplicity and rigor over looseness.
|
|
* |
Creation from the keyboard while minimizing on key-strokes.
|
|
* |
Few meta characters. Zoem achieves this by having a single first-level
meta character.
|
|
* |
Adding filtering capabilities so that multiple devices can be
addressed.
|
Zoem's biggest advantage: you can accomplish almost anything you want. One price you pay is that the source document must obey zoem syntax. One price that you don't pay is that zoem is not a mark-up language in itself. Zoem knows nothing whatsoever about paragraphs, lay-out, font weights, slant, sections, and headers. There are two sides to this.
On the one hand, every aspect of authoring has to be encoded somewhere, e.g. lists, verbatim environments, et cetera. Making this work for multiple devices can be quite challenging. You have to teach zoem, or perhaps somebody else has already taught it before, or perhaps someone has already done something similar that only needs a little adjusting. Zoem distinctly enables and promotes reuse and the creation of macro packages. All the same, making a zoem paragraph macro or a zoem boldface macro and mapping those to both html and troff is quite easy; making a general purpose zoem list macro and mapping that is a lot more difficult.
On the other hand, this difficulty is exactly what makes most authoring solutions for multiple devices fail somewhere. By keeping authoring issues out of the core zoem language, and focussing on small and powerful building blocks, zoem makes the playing field very large. If two devices support the same kind of authoring construct, then you really should be able to unify them in zoem.
One can (and should) isolate device specific instructions from authoring specific instructions, and those should again be encapsulated in macro packages. Reuse is essential: I use the same set of zoem man macros for all the manual pages that I write. The macro definitions themself are not too pretty (nor horrid) to look at, but the zoem source for the manual pages themself (importing the macros) looks a lot like TeX and may even be somewhat easier on the eye.
In general, low-end macros have to be defined and mapped onto each output device. Device-specific macros must be written by someone whose knowledge about output devices matches the desired level of typesetting sophistication. This is a pain on the one hand, on the other hand, this will ensure that you succeed in what you are aiming at. Moreover, high-end macros generally do not need device-specific instructions, so these need only be defined once.
If the output device has no macro facilities (HTML) or has interesting syntax and whitespace restrictions (troff), zoem may be a gain even if you need only one device. It is very easy to (conditionally) include device-specific material in the running zoem text itself.
Zoem was created because several of the author's itches were scratched by other approaches. I disliked existing ways of generating manual pages in both troff and html. These are always about converting from one mark-up language to one or more others, and they are invariably broken. More often than not it is a hugely unwieldy Perl script. Zoem was designed with the explicit goal of device forking, and zoem is not a mark-up language. It's a way of creating dummy mark-up languages with a TeX-like syntax. The notion of mapping the dummy language to a real mark-up language is built into the very DNA of zoem. Since manual pages do not need a large set of mark-up features, this is a feasible approach.
I was inspired by the leaden-footed approach of the SGML/XML/DocBook setup, which makes me nearly crave for a GUI because the typing is so cumbersome, with tags all over the place and no good macro facilities. That does something to a vim/tex/mutt/nn user, wondering whether he should use a GUI for flushing his writings. It's more like pulling a leg than scratching an itch. I need to type my documents and I need to have powerful macro facilities - as I need semantic mark-up that will do multiple things at the same time. So I disagree somewhat with what demigod James Clark (of groff, expat, SP, and XML fame) has to say about this:
One lesson I drew from TeX and groff is that you want a real programming language, not a macro processing language. When you look at the thousands of lines of TeX macros or troff macros that people produce, it's a monument to the human intellect, but it's not really the right way to solve the problem.
For my everyday document, I don't think I need something that has all the generality, power, and inconvenience of attribute grammars and feature structures mixed with relational databases, i.e. the kind of thing that people usually write a thesis about, not with. Of course, using zoem to output XML is a very viable option - for my everyday document again, I do understand that publishers and the likes have different needs.
I was inspired in a positive way by the TeX syntax and design. TeX really enables the rapid creation of documents over which the creator is able to maintain powerful control by creating his own semantic mark-up - I am not even mentioning TeX's superb typesetting capabilities here. Zoem syntax was copied in a modified form from TeX (please note that zoem is absolutely infinitesimal in aim and scope [then perhaps note that zoem's macro facilities go a lot further]).
Then there is troff. I would love to love it, but the more I get to know it, the more I marvel at the insanity of its syntax, which goes much deeper than just being terse. It is beyond me that anyone would enter of their free will a document in plain troff. Still, troff has a very special place in my heart, and I am quite happy to produce (by all means simple) troff by mapping zoem macros to troff input.
Finally, info was a big itch on its own. If ever I saw an attitude problem matched only by the absence of achievement (that's a gripe about info, not texinfo, mind you). Admittedly, RMS is a giant and me just a dwarf squashed beneath his feet, which may explain why I cannot look any further. Count me in with all the other dwarfs squeaking they don't like info one bit.
The zoem man macros for the two devices HTML and roff were written by Stijn van Dongen and use a straightforward subset of HTML and the troff man macros plus a little additional plain troff (thanks go to Jan van der Steen for teaching me the first insights). Zoem input written in these macros yields cross-referenced html including a table of contents if desired, while at the same time a classic-style manual page can be produced. The good thing of zoem is that you can easily modify, improve, and replace these macros to suit your own needs. The page you are currently reading was created using macros which were morphed from the man macros. See the zzello world and The zoem manual macros sections.
Below you find some features of the zoem primitives. Note that there are in practice two kinds of zoem files. The first is a zoem macro file, which should contain macros defined in terms of lower-level macros, with zoem primitives at the lowest level. The second is a zoem document file, which should import such a macro file and only use the high-level macros defined in that macro file. Additionally, a document file can define some high-level macros of its own, in terms of low-level macros, zoem primitives, or a mixture of both.
* |
Macros with arguments, overloading of key names allowed (i.e. different
keys with the same name are distinguished by the number of arguments they
take). (\def#2, \set#2, and \setx#2).
Zoem primitives look like regular macros, but
usually they expand their arguments before use. User macros
can be equipped with this behaviour by wrapping them in \apply#2.
|
|
* |
Support for variable number of arguments - see the
vararg section.
|
|
* |
Easy file, stdin, stdout, and stderr input/output,
nested file inclusion (\dofile#2, \write#3, \finsert#1,
and \zinsert#1).
|
|
* | ||
* |
A separate namespace for references. References can have
up to five members: caption, number, level, type, and misc.
They are set using \refload#6, and got using \ref#2
(or one of the non-primitives \refcaption#2, \refnumber#2 etc).
|
|
* |
Operators returning booleans (\defined#2, \cmp#3, \eqt#3),
control operators acting on those (\while#2, \if#3).
|
|
* | ||
* |
Match and substitution capabilities using POSIX regexes (\inspect#4).
|
|
* |
The switch primitive \switch#2,
employing the vararg construct.
Yes, zoem has a switch statement, and it takes arbitrary expressions too!
|
|
* | ||
* |
A user dictionary stack that can be manipulated using \push#1 and
\pop#1. An environment environment for doing \begin{stuff} ..
\end{stuff} stuff (see \env#3). This enviroment creates name
scopes by pushing and popping to/from the dollar
dictionary stack. Environments may take arguments,
one particular useful application is that local variables (e.g. local
to an itemize environment) can thus be specified by the user.
|
|
* |
Storage of data by multiple string indexing - arbitrary data can be stored
in a tree by indexing nodes with (arbitrary) strings.
Refer to the
Tree data
section.
|
|
* |
The ability to nicely format macros (see \formatted#1).
|
|
* |
Syntactic sugar
for writing SGML-style mark-up and having it checked.
|
|
* |
Executing system commands, possibly sending data to STDIN and
receiving data from STDOUT - \system#3.
|
|
* |
And more.
|
If you want to do arbitrarily complex stuff, it will be difficult to map it onto multiple devices. That is true for any system however, and zoem can still be very useful for example when you like the TeX way of creating documents whereas you need HTML output.
Tables are notoriously difficult to maintain along multiple devices. With zoem one should be able to aim for a least common denominator. I have not yet attempted to create such a forked table enviroment (which would likely benefit from the \table#5 and \apply#2 primitives), mostly because tables are neither common nor easily implemented in manual pages that are meant to be read in terminals. The usual approach towards tables in manual pages is to use a verbatim environment like so:
.-------.-------.-------. | | | | | 8 | 1 | 6 | | | | | .-------.-------.-------. | | | | | 3 | 5 | 7 | | | | | .-------.-------.-------. | | | | | 4 | 9 | 2 | | | | | .-------.-------.-------.
The zoem manual pages provides a verbatim environment and a verbatix environment for this. The former will not be split over two pages by troff (if it fits on a single page).
The zoem manual pages posed interesting difficulties when I looked further than html under Netscape and troff under groff. Making things work for both Netscape and Internet Explorer (with respect to spacing in lists) and for both GNU troff (groff) and other (older and proprietary) troff versions (with respect to the verbatim environment) was interesting, to say the least. Some issues sprang from my own mistakes, and I learned a couple of things along the road. Notably the existence of \e and \& in troff, and the power of the <div> and <span> elements in HTML. The list issue seems unsolvable using orthodox methods, as the list environments are broken in different ways and degrees in the various browsers (e.g. mangling the margin attributes). The solution currently in use is that all zoem itemize variants are mapped onto html tables.
One unfortunate matter is the following. I have become quite attached to using italics in manual pages, as groff does a good job (in terminals) of rendering italic text as underlined - when groff produces PostScript it will simply render italics of course. Other and older versions of troff seem to render italics by switching to reverse video, which gives a horrendous effect. Beware of this, and avoid italics if you want to optimize the worst case user experience. Another thing is that older troffs don't seem to justify paragraphs as groff does.
The usefulness of zoem depends on the premise that mark-up languages like troff, html, and TeX possess certain orthogonality properties. One such property is that environments like lists can be nested freely. Luckily this is what everyone expects from a sane mark-up language, and most mark-up languages try to be sane. If a language fails to meet this requirement, you will have to work within the restricted area of the language that does meet the requirement.
Zoem's behaviour right now is pretty straightforward. It distinguishes two kinds of parse scopes, plain scope and device scope. When plain scope is output, any character that is special to the output device is translated to the corresponding 'magic sequence' for that device. Zoem has efficient provisions for different levels of magicality and the ability to switch between them. When device scope is output, nothing is mapped, and some additional primitives for regulating the output of white space are available. Parse scope is subject to macro expansion; device scope is not.
For example, the zoem manual macros map every period '.' encountered by zoem in plain scope onto the sequence '\&.' [sic], if the output device is troff. They map every ampsersand '&' onto the sequence '&' if the output device is html. However, the first example is slightly overdoing it. In troff, a dot only has magic powers if it is the first character on a line. Zoem currently provides no way of recognizing this kind of subtlety. The natural generalization of the present scope model would be to equip zoem's output behaviour with a finite state automaton. I hope that this will never be necesary though, as the simplicity of the present model is gratifying and promotes robustness when constructing high-level macros.
If zoem is not what you are looking for, you might be interested in one of the following. The links are to Google searches, as I am lazy and the items are in varying states of being supported.
aft |
almost free text
|
|
chakotay |
chakotay/chpp
|
|
EmPy |
embedded python [in text]
|
|
gellmu |
generalized extensible LaTeX-like markup
|
|
gema |
gema, the general purpose macro preprocessor
|
|
htlatex |
hypertext LaTeX
|
|
info |
GNU info, from the folks that abhor man pages and love topic splatter
|
|
jamal |
Jamal, Just Another Macro Language
|
|
latex2html |
latex to html, on my system a 17032 line Perl-script
|
|
latex2man |
latex to man
|
|
latte |
latte
|
|
m4 |
a Unix macro processor
|
|
man2html |
man to html
|
|
manServer |
convert manual pages to HTML
|
|
mtex |
manual TeX [by Mike Sofka]
|
|
mtex |
manual TeX [by Compaq]
|
|
pod |
plain old documentation (Perl's documentation format)
|
|
PolyglotMan |
parses and maps troff source to other devices
|
|
PYM |
PYM (A Macro Preprocessor based on Python)
|
|
reStructuredText |
reStructuredText, not unlike aft and pod
|
|
smartHTML |
smart HTML
|
|
tei |
text encoding initiative
|
|
tex4ht |
TeX for hypertext?
|
|
tth |
TeX to HTML translator
|
|
txt2tags |
txt2tags, not unlike reStructuredText, aft, and pod
|
|
wlatex |
web LaTeX?
|
|
WML |
Website Meta Language
|
|
yodl |
yet oneOther Documentation Language
|
Really, the number of inhabitants is stupifyingly mindboggling. Even when restricting attention to proposed solutions for the manual/troff/html problem, there are many applications. A few Net searches turn up plenty (more).
Christopher Browne has a section on macro languages: http://www.cbbrowne.com/info/macros.html
A not entirely trivial hello world example, featuring the concepts of plain scope and device scope. The latter should only be seen in macro packages. The distinction between these parse scopes is essential to zoem, and is thoroughly explained in the Scope dichotomy and Device scope sections. The sequence \@{..} encloses device scope, the sequence \: introduces a comment until the end of line. \switch#2, \def#2, and \special#1 are zoem primitives. \__device__ is a normal macro conventionally used to divide and rule over different devices. The mappings defined by \special#1 live in device scope.
Say this macro file is named simple.zmm.
\: ----------------------------------------------------------------- \: Stuff such as this belongs in a (reusable) macro file. \: \bf#1 and \par need device specific sequences. \: \special#1 maps characters with meta meaning in plain scope. \: \@{..} encloses device scope: nothing is mapped therein. \: ----------------------------------------------------------------- \switch{\__device__}{ {html}{ \def{bf#1}{\@{<b>}\1\@{</b>}} \def{par}{\@{<p>\N}} \special{ \: how to map characters in plain scope. {38} {&} \: 38 is ascii character '&' {60} {<} \: 60 -> '<' {62} {>} \: 62 -> '>' } } {roff}{ \def{bf#1}{\@{\\fB}\1\@{\\fP}} \def{par}{\@{\P}} \special{ \: how to map characters in plain scope. {46} {\\&.} \: a dot. {96} {\\&`} \: backquote. {39} {\\&'} \: quote {92} {\\e} \: backslash (default troff escape character). \: escaping by backslash may fail in \: diversions [for old roffs]. } } }
\import{simple.zmm} \def{greet}{\bf{greetings}} \def{greet#1}{\bf{hello \1!}} \def{greet#2}{\bf{\1 \2!}} \: Use the keys just defined. Some kind of overloading there. \: the '&' will be automatically mapped and so will '<' and '>'. \par The other day I said \greet{Venus & Serena}, and they said cheerfully \greet{<morning>}{Truman}, give Laura our best \greet please.
This is the html output:
<p> The other day I said <b>hello Venus & Serena!</b>, and they said cheerfully <b><morning> Truman!</b>, give Laura our best <b>greetings</b> please.
which renders of course as
The other day I said hello Venus & Serena!, and they said cheerfully <morning> Truman!, give Laura our best greetings please.
The troff output is not shown here. You can look at several comprehensive and much more sophisticated examples in the The zoem manual macros section. The output formats shown in that section are html, PostScript, troff, and plain t(e)xt.
You use zoem by invoking it from the command line. The normal mode of operation is that you specify a file for zoem to chew up and spit out. This is called the entry file, and its name usually has the extension .azm. The other thing you normally specify is the device, which will just assign a value to the \__device__ key. A common invocation thus looks as follows:
zoem -i mcl.azm -d html
The -i flag specifies the entry file and the -d flag sets the \__device__ key. It is not necessary to write the .azm extension, zoem will append it for you. The preceding could also have been entered as
zoem -i mcl -d html
In either case, zoem will set the session key \__fnbase__ to the base name of the entry file, i.e. the name stripped of its .azm suffix. In this example, the key \__fnbase__ will get the value mcl. If you have an input file without the .azm extension, you need to use the -I option.
Zoem writes its output to a default output file which is named according to three rules. The rules are:
* |
If the -o flag was given the value say somestr,
zoem will write to the file named somestr.
|
|
* |
If -o was not supplied but the -d flag was used with argument say
zyx, zoem will write to the file named \__fnbase__.zyx.
|
|
* |
If neither -d nor -o was given, zoem will write to the
file named \__fnbase__.ozm.
|
It is possible to change the default output file from within the document; this is achieved with the \writeto#1 primitive. Zoem can mingle default output with output to other files, use the \write#3 primitive for that.
Both the -i and -o flag accept a hyphen as argument, meaning respectively that zoem will read from stdin and write to stdout.
Specifying just zoem and entering a return will cause zoem to enter interactive mode, in which it reads from stdin and writes to stdout. Interactive mode currently should catch any errors occurring, so it is a good way of experimenting and testing. By default, interactive mode reads chunks that are ended by a single dot on a line by itself. This behaviour can be changed by setting the session variable \__parmode__ using the -s option. Using zoem -l parmode shows the bits that can be set in this variable. It is for example possible to make zoem read paragraphs (ended by two or more consecutive newlines).
NOTE
There is a difference between specifying no output stream
(i.e. not using the -o option}) and explicitly specifying -o -.
In the latter case, zoem will never enter interactive mode. Should
you need to insert zoem into some pipe sequence, then you need to
use -o -.
TRACING ERRORS
If your documents contains erroneous input (e.g. using a macro
that was never defined), zoem will by default print the approximate
corresponding line number of the current input file and the last key it saw,
and then exit. If that does not suffice in tracking down the error, you have
a choice of options. One possibility is to use one of the various tracing
modes described below and in the zoem interpreter manual. Another possibility
is to specify the -x option which says to enter interactive mode should an
error occur. This enables you to inspect the values of keys defined or used in
the problematic area.
A selection of other options is given below. For the full story, consult the manual page of the zoem interpreter.
-h | ||
lists all flags accepted by zoem with a short description for each.
|
||
-s <foo>=<bar> | ||
Sets key \foo to bar.
|
||
-e <any> | ||
Zoem will evaluate <any>, writing any result text to stdout,
and then exit.
|
||
-E <any> | ||
Zoem will evaluate <any>, writing any result text to stdout,
and then proceed.
|
||
-x | ||
If an error occurs, zoem stops processing and enters interactive mode.
|
||
-l <str> | ||
lists all entities specified by <str>. It can be any of
all,
filter,
legend,
macro,
session,
trace, or
zoem.
Repeated use is allowed. In fact, zoem will only check whether
the target is present as a substring, so
zoem -l legendzoem will print the legend and the list of zoem primitives. |
||
--trace | ||
This traces (prints) all keys encountered, and prints
possibly truncated arguments.
Zoem has several other tracing flags, use the -h flag
or refer to the zoem manual page for more information.
Tracing can be set from within the document using the \trace#1 primitive. Part or whole of the data tree can be output from within the document using the \%%% primitive (refer to the Tree data section). |
||
--stats | ||
When zoem is done, it prints statistics about the primitive name
table and about the user name table.
|
Zoem parses text which may contain zoem escape sequences, these are sequences that have special meaning and cause zoem to do special processsing. Each and every escape sequences starts with a backslash, no exceptions. There are three kinds of sequences that are macros, which may or may not take arguments. These are zoem primitives, user keys, and dollar keys. There are currently roughly forty zoem primitives, these are listed in the The zoem language section. User keys and dollar keys are discussed in the Macro expansion section. Arguments are shipped by delimiting them with curly braces, as in
\thiskey{takes}{\bf{two}\it{arguments}}.
No characters are allowed inbetween (the delimiting curlies of) two arguments (but take note of the handy \formatted#1 primitive). See the Macro expansion section for more information. Zoem is very strict in the syntax it accepts, but it garantuees to accept a text in which each backslash \ is escaped as \\ (i.e. a text in which all consecutive runs of backslashes have even length).
An active backslash is any backslash that is not made inactive by an active backslash immediately preceding it. The first backslash seen by zoem (proceeding sequentially through the text) is active. This is one incomprehensible way of stating the obvious, and I bet you know what I mean anyway. An active backslash must always have a meaning known to zoem. If zoem does not get it, it will complain and exit. The meaning (i.e. class) of the escape sequence introduced by an active backslash is determined by the character immediately following it. A list is given below.
Within arguments, curlies not functioning as argument delimiters must also be escaped if they are not balanced. It is best practice to escape all non-argument-delimiting curlies, but I never do so myself unless they are not balanced. An escaped curly is a curly preceded by an active backslash. An active curly is a curly that is not escaped. A pair of balanced curlies consists of an active left curly that matches an active right curly, where inbetween all escaped curlies are disregarded. A block is anything delimited by balanced curlies. The word scope is most often used to distinguish between device scope and plain scope, these are the two kinds of parse scopes. An environment scope refers to the stuff enclosed by instances of the \begin#1 and \end#1 primitives. So called name scopes are entered and exited by \push#1 and \pop#1.
This is a list of escape sequence classes recognized by zoem, indexed by the (set of) character(s) triggering the class(es) - this assumes that the character in question is preceded by an active backslash.
$[_a-zA-Z]* | ||
[dollar key]
A sequence starting with a dollar sign possibly continued with
underscores and alphanumeric characters. Introduces a dollar key. No
dollar signs are allowed in the remainder, and the first non-alphanumeric
non-underscore character terminates the sequence. Any key that is set by
zoem itself (and which is not simply an alias) takes the form of a dollar
key. The primary use of dollar keys is that they are set by \begin#1
and \end#1. Dollar keys live in the dollar dictionary stack, which is
pushed and popped by \begin#1 and \end#1. Nested begin/end
scopes can thus safely associate different values with the same key name.
Refer also to the Macro expansion section, the The zoem language section, and
the Dictionary stacks section.
Note: \$#2 is a zoem primitive. |
||
[_a-zA-Z][_a-zA-Z0-9]* | ||
[user key/zoem primitive]
A sequence starting with an underscore or an alphabetic character, with
only underscores and alphanumeric characters in the remainder. Introduces a
user key or a zoem primitive. The first non-alphanumeric non-underscore
character terminates the sequence. These keys live in the user
dictionary stack, which the user can control with the \push#1 and
\pop#1 primitives. Refer also to the Macro expansion, The zoem language,
and Dictionary stacks sections.
A sequence consisting of a single underscore (i.e. not followed by an alphanumeric character) introduces an anonymous key. |
||
" | ||
[user key]
Starts a user key, which is only different from the user keys mentioned
above in that it looks different. The sequence is terminated by
a closing ". Inbetween, anything is allowed except
a backslash or curly. This is used for creating mnemonic names such as
\"man::author" \"man::section" \"man::version" \"html::title" \"html::charset"These keys live in the user dictionary stack. See the Macro expansion section and the Dictionary stacks section. |
||
% | ||
[grape key]
A sequence starting with a percent sign. The percent sign is
followed by a number of scopes. This is used to access multi-dimensional
data storage. Such data is stored using the \def#2 primitive or one
of its siblings.
|
||
[1-9] | ||
[positional parameter]
A single (character encoding a) positive digit. The sequence
backslash followed by digit is called a positional parameter.
It is only interpreted in the second argument of \set#2, \setx#2,
\def#2, and \defx#2, and in the definition part of an
anonymous key (which can be an argument to \apply#2
and \inspect#4). In all these instances, the sequence denotes a
positional parameter into which the corresponding argument will be
interpolated when a key with arguments is used. It is allowed in other
places though, as it is possible in zoem to create key definitions
dynamically (see e.g. the \setx#2 primitive).
NOTE during interpolation, positional parameters that are enclosed by
the delay scope \!{..} will not be interpolated (see \!#1).
The status of this feature is not entirely clear.
|
||
: | ||
[comment sequence] It starts a comment that is
terminated by a newline and stripped during file read (cf the
File read section). During file read, zoem
only checks whether the leading backslash preceding the colon is active.
It does not check whether the sequence is contained in some block (e.g.
nested in the argument to some key) - that is in fact explicitly allowed
and useful in commenting large macro sequences contained in the
\formatted#2 primitive.
|
||
| | ||
[zoem glyph]
Comprises a special two-character sequence that can be given a
device-specific meaning. It is customarily used to encode a line break. To
zoem, this sequence is more or less the same as a 'normal' character. See
the \special#1 primitive.
|
||
~ | ||
[zoem glyph]
It is customarily used to encode a non-breaking space. See the entry above.
|
||
- | ||
[zoem glyph]
It is customarily used to encode a long dash. See two entries back.
|
||
\ | ||
[backslash] Denotes a literal backslash.
|
||
{ | ||
[left curly] Denotes a literal left curly.
|
||
} | ||
[right curly] Denotes a literal right curly.
|
||
* | ||
[glyph sequence] Starts a glyph sequence or constant sequence (that is
terminated by another *). Refer to the Device scope section and to
the \constant#1 primitive.
|
||
< | ||
> | ||
[syntactic sugar]
This introduces syntactic sugar for directly writing SGML-style mark-up,
such as HTML and XML (e.g. DocBook).
Refer to the anchor section for that topic.
|
||
@ | ||
[at scope] Typically seen in macro package files only.
Starts a special instance of device scope called at scope. The
sequence \@ must immediately be followed by a pair of balanced
curlies, so at scope always appears as \@{..}. Refer to the
Scope dichotomy and Device scope sections for more information.
|
||
& | ||
[and scope] Typically seen in macro package files only.
May only be used within device scope, and implements a limited
form of macro expansion within that scope.
The sequence \& must immediately be followed by a pair of balanced
curlies. so at scope always appears as \&{..}. Refer to the
Scope dichotomy and Device scope sections for more information.
|
||
` | ||
[back quote - formatting escape]
Typically seen in macro package files only.
Starts a formatting sequence (that is terminated by another `).
This is only recognized within the \formatted#1 primitive.
This primitive removes all literal whitespace it encounters in its
argument; the formatting sequences are transformed to the
whitespace character encoded by them.
|
||
, | ||
[comma - atomic separator] Typically seen in macro package files only.
This is interpreted during filter time, and is
always mapped to nothing. Use it for glueing things as in \foo\,1,
which will result in theresultoffoo1.
|
||
! | ||
[delay sequence] Typically seen in macro package files only.
Introduces a zoem meta sequence. Such a sequence consists of a maximal run
of consecutive backslashes, possibly followed by a single block. It can be
used to delay interpretation during any number of interpretation stages, and
is useful to delay interpretation, perhaps even in a nested fashion, for
arguments in keys such as \apply#2 that expand one or more of their
arguments before use. The run of exclamation marks (or 'bangs' as they are
internally called) actually comprises an argument to the underlying
primitive, so the two primitives (one taking a single block argument)
internally have respective signatures !#1 and !#2. Externally
though, they are just refered to as \! and \!#1.
|
||
= | ||
[inline files] Rarely used feature.
Starts either a sequence of the form \=fname=, which begins a so called
inline file named fname, or a sequence of the form \==, which
ends such an inline file. Refer to the File read section.
|
This leaves 0'()[]?^#/.; for future use, hopefully very few of these will ever acquire meaning. If the sequence \# acquires meaning, it will probably be for encoding Unicode scalar values.
Parsing is separated into three stages, conceptually. Zoem knows two different parse scopes, plain scope and device scope. These are mentioned below, and explained in the Scope dichotomy section. The three stages are:
* |
File read
|
|
* |
Macro expansion / file inclusion - only plain scope is seen.
|
|
* |
Filtering - both plain scope and device scope are filtered.
Device directives that lay hidden in device scope
are interpreted during output.
|
In reality, as soon as a piece of text is no longer subject to the second stage, it is immediately filtered and output.
Macro expansion is done recursively. Whenever a macro is encountered, it is replaced by its expansion, and the result is again fed to the parser. Evaluatation is not necessarily lazy, that is, during macro expansion the expander may expand arguments before they are interpolated and substituted in the macro definition. This inside-out evaluation can recurse if necessary. Many zoem primitives evaluate one or more of their arguments before use. The default behaviour for user macros is lazy evaluation. This can be changed however by wrapping both the macro and its arguments in \apply#2. Expansion can be delayed using \! and \!#1, so different arguments can be treated differently.
Important is that the result from the second stage is still valid zoem input. If you re-feed it to zoem, file read and macro expansion are usually no-ops (unless some interpretation delay-magic was used), and the syntax is garantueed to be acceptable to zoem. This is because device scope is not touched during the first two stages, and device specific text (which is most likely not conforming to zoem syntax) lies always hidden in that scope. There are three kinds of escape sequences introducing device scope; these are described in the Device scope section.
This is used for example when creating a table of contents; you can write expanded but unfiltered content to a file and read it in during the following run. It is important that such content is fully expanded, because you want things like index numbers and references as they are at the time of macro invocation. It is equally important that what you read back in is still valid zoem input; this is simply achieved by witholding filtering. When the table of contents is read in, it can be subjected to filtering, and this is the right way to do toc stuff in Zoem.
File read - stripping comments, reading inline files.
Zoem searches for files included via \dofile#2 or one of its aliases in a number of places if it cannot find the file in the current directory. The precise way of searching is documented in section File search path .
\: |
introduces comment until end of line.
|
|
\=fname= | ||
starts inline file named fname at the next line,
removes remainder of line after the \=fname= sequence.
When using the \dofile#2 primitive or one of its
four aliases, an inline file takes precedence over regular files
in the file system, whether it is present (as a regular file)
or not. See below. This feature can be used to ship zoem
input in one piece while putting the macro parts at the end.
The future will probably bring a zoem option that creates such a self-contained file automatically from the zoem entry file. |
||
\== |
ends inline file, removes remainder of line.
|
The above applies to any file read at any stage. Inline files may occur in any file included at any time, but they do not nest.
The zoem entry file is the single file that is specified on the command line. This is the main file, from which other files can be included if desired.
Zoem entry files must have the extension .azm, which is memnonic for A ZoeM file. It is not uncommon to generate sibling files with .roff, .html, .zmt (zoem table of contents), and .zmr (zoem references) extensions - however, this is all configurable in user space and not part of zoem itself. There are no restrictions on names of files that are included from the entry file. Inclusion is done recursively.
The future will probably bring a second extension that is allowed, namely .ezm for Expanded ZoeM file, which is a self-contained file in which every included file is present as an inline file.
If zoem cannot find a file in the current directory, it attempts to find the file in one of three different ways. These are, in the order in which they are attempted:
* |
The environment variable $ZOEMSEARCHPATH is checked. It may
contain a listing of paths separated by whitespace or colons.
|
|
* |
The zoem variable \__searchpath__ is checked. It must contain a listing
of paths stored as a vararg, i.e. a sequence of paths where each path is
delimited by curly brackets. DO NOT overwrite this variable, but
rather append or prepend to it. Most likely zoem was configured and compiled
locally on your system, in which case \__searchpath__ contains the path
necessary to find the macro packages man.zmm, faq.zmm, and
doc.zmm.
|
|
* |
The path of the file currently being parsed is used.
Assume that file foo contains \import{/a/b/c/bar}.
If file bar wants to include file zut, which is in
the same /a/b/c/ directory, it need not prepend a path
but can just issue \import{zut}. Should the
previous search mechanisms fail to find zut, then zoem will
as a last resort deduce the path from /a/b/c/bar.
This feature is probably rarely needed, if ever at all.
|
Macro expansion consists of recursive file inclusion and macro expansion. All zoem primitives and user keys are recursively expanded until none remains. Zoem primitives and user keys take one of the following forms:
\abc_0123_ | ||
A key with alphanumerics and underscores only. Ends with
any other character. All zoem primitives but one have this form.
Note: \_ denotes an anonymous key, see the Anonymous keys section. These keys live in the user dictionary stack. Initially, there is only one dictionary. The stack can be manipulated using the \push#1 and \pop#1 primitives. |
||
\"abc::def-ghi.jkl,mno+qrs" | ||
A quoted key. Almost anything inbetween quotes is allowed. Always
ends with a quote. No zoem primitive has this form.
These keys live in the same user dictionary stack
as the keys above.
|
||
\$abc_0123_ | ||
A key introduced with a dollar sign, alphanumerics and underscores in
the remainder only. Ends with any non-alphanumeric character. These
keys live in the dollar dictionary stack.
A dictionary is pushed with every occurrence of
\begin#1, and that dictionary is popped with the corresponding
occurrence of \end#1.
\$0, \$1, .. \$9 is a set of keys of which a subset is set with every occurrence of \begin#1. Further note: \$#2 is a zoem primitive. |
All three types of keys may take arguments, and overloading is allowed:
\foo \: signature foo \foo{bar} \: signature foo#1 \foo{bar}{bop} \: signature foo#2 \$foo{bar}{baz} \: signature $foo#2 \"foo::oof"{zut}{zit}{zot} \: signature "foo::oof"#3
is an ensemble of valid and unique keys, which can be defined for example by
\def{foo}{FOO} \def{foo#1}{The FOO of \1} \def{foo#2}{The FOO of \1 and \2} \def{$foo#2}{The $FOO of \1 and \2} \def{"foo::oof"#3}{\foo{\1}{\2}\foo{\2}{\3}}
Additionally, zoem allows the definition of constant keys that map directly into device space and are ignored during macro expansion. Usage of such keys looks like \*'e* or \*(c)* and is detailed later on.
A sequence \k where k is in 1-9 is allowed within anonymous keys (as used for example in \apply#2 and \inspect#4) and in the definition argument of the \def#2 primitive and its siblings \defx#2, \set#2, and \setx#2. It indicates the position(s) where arguments should be interpolated. NOTE during interpolation, positional parameters that are enclosed by the delay scope \!{..} will not be interpolated (see \!#1). The status of this feature is not entirely clear.
A feature that should only rarely be needed is that zoem allows name scopes. Refer to the Dictionary stacks section.
There is one zoem primitive which has four different uses. For each of those uses, an alias exists.
\dofile#2 use alias meaning \dofile{expr}{!+} \input{expr} require file, interpret and output \dofile{expr}{!-} \import{expr} require file, interpret only \dofile{expr}{?+} \read{expr} permit absence, interpret and output \dofile{expr}{?-} \load{expr} permit absence, interpret only
The \dofile#2 primitive and its four aliases are perhaps a little funny interface-wise - better ideas are welcome. The expr argument is digested, that is, expanded until no macro's remain. It is thus possible to specify \__fnbase__.zmt and include a table of contents file that has been written to in a previous run. \dofile#2 and its aliases have the property that zoem really descends into the files, and on error will emit a message containing the approximate line number where it occurred.
Additionally, the contents of a file can be placed inline using \finsert#1 and \zinsert#1.
Note: wherever key is written, it means that something of the form \foo, \$foo, or \"foo" has to be provided, so you would use \setx#2 e.g. as \setx{foo}{\finsert{\__fnbase__.zyx}}.
The \dofile#2 primitive requires that the files to be included satisfy zoem syntax. It will descend into the files and proceed parsing them.
The \finsert#1 and \zinsert#1 primitives do not descend, but rather act as if the contents of the file specified were pasted into the place of macro invocation.
\finsert#1 will protect the contents of the inserted file, that is, all backslashes and curlies are escaped by preprending them with a backslash. \zinsert#1 will include the file unchanged, assuming that its contents satisfy zoem syntax.
The \system#3 primitive is able to pipe data to a system command's STDIN stream and retrieve data from the command's STDOUT stream. This primitive will unprotect the data it sends, and it will protect the data it receives.
Data can be explicitly protected using the \protect#1 primitive.
Protected data can (currently) never result in it being expanded again. This is because escaped backslashes are only interpreted at filter time, and never during expansion. If you only need temporary delay of expansion, use the \! primitive or the \!#1 primitive.
Zoem knows two parse scopes: plain scope and device scope. The latter is also called 'at scope' because \@{..} is one (but not the only) way of entering device scope. In plain scope, every character represents itself as a glyph, i.e. as something that should show that way in print/on screen (after the zoem output/device input is fed to the device interpreter).
For example, if you write the less than sign < in plain scope, it should show up as a readable less than glyph, like in this very sentence. In order to make this happen, zoem provides the \special#1 primitive, so that the less than sign can be automatically mapped to the html entity sequence <.
In device scope, nothing is mapped except for a double backslash should it occur. If you enter this particular sequence of mixed scope: \@{<b>}<hello world>\@{</b>} as zoem input, the zoem output/device input is (provided the \special#1 primitive was correctly used for the html device): <b><hello world></b> and what you finally see on screen is: <hello world>. In device scope, every character (except for the escape sequences available in that scope) represents itself as the ASCII character that should be present in the zoem output/device input. Device scope should normally only be seen in macros and not in running zoem input.
In plain space you type characters just as you want to see them eventually - when you read the document after the zoem output was run through a device interpreter (such as a browser or printer, or postscript previewer). The only exceptions are the backslash and the two curlies, these should be entered as \}, \{, and \}, respectively. Those escape sequences are interpreted as the characters or glyphs \, {, and }. For all characters, including these three, it is checked whether they should be further mapped according to the \special#1 primitive. If a mapping is found, it is retrieved and interpreted by the device scope filter. Read on.
There are three kind of strings which are interpreted by the generic device filter, and which are said to live in device scope:
* |
The strings embedded in \@{..} sequences. |
|
* |
The strings mapped to by the \special#1 primitive, including
mappings of the zoem glyphs \~, \|, and \-.
|
|
* |
The strings mapped to by the \constant#1 primitive.
|
In a macro package that is meant to work for multiple devices, every use of any of these constructs will typically be embedded in something that tests the value of the active device. This can be done using either \cmp#3 with \if#3, \switch#1, or \$#2, in conjuction with the pre-defined zoem key \__device__, containing the name of the active device (which can be specified on the command-line). The following are equivalent:
\if{\cmp{eq}{\__device__}{html}}{ \@{<!-- (c) foo bar -->} }{} \: is equivalent with \${html}{ \@{<!-- (c) foo bar -->} }
The \$#2 primitive is used if something needs to be done for one device only, and it may occasionally appear in documents. For example, the zoem man macros enable the creation of a table of contents (for both html and troff). My own convention is to have a table of contents only in html, and I specify this using the sequence
\${html}{\"man::maketoc"}
When zoem enters device scope, it outputs all characters literally, except that the backslash still has special meaning. It is used for encoding the backlash itself (as \\), and for encoding the two curlies { and } (as \{ and \}). This is the same as in plain scope (except that in plain scope the resulting character may again be mapped onto something else, for example, in troff the backslash also needs encoding as \\).
In device scope the sequence \" maps to a double quote. This is an additional feature to allow zoem input to be more susceptible to some editors moving features. It is not necessary though; simply using the double quote without escaping it is sufficient.
Additionally, the backslash can be followed by a single letter from a prescribed set listed below. Such a backslash+letter combination is called a device directive. By default, zoem will never print consecutive newlines, and it will never print consecutive spaces or spaces at the beginning of a line. The device directives allow this to be altered.
N |
garantuee a newline
|
|
P |
garantuee a paragraph skip (two consecutive newlines)
|
|
S |
garantuee a space (except if next char is newline)
|
|
I |
increase indent by one (indent is printed after each newline)
|
|
J |
decrease indent by one
|
|
C |
set indent to zero
|
|
n |
print newline
|
|
s |
print space
|
|
t |
print tab
|
|
w |
stop managing white space (squashing spaces and newlines)
|
|
W |
start managing white space (use after w)
|
|
& |
start and scope (see further below)
|
|
+ |
set the special level (see further below)
|
Note that the directives mainly affect the lay-out of the device text (which is zoem output), not the look of the interpreted device text. The 'N' directive is rather important when constructing troff macros, as many special troff commands are encoded by a dot as the first character on a line, i.e. a newline followed by a dot. Since troff attaches special meaning to two consecutive newlines as well (interpreting it as a paragraph break), zoem needs to be able to specify print a newline only if the previous character was not a newline. This is exactly what the N directive means. The 'W' and 'w' directives are required for enabling the construction of a verbatim environment.
The sequence \&{<almost any>} can be used to avoid overly cumbersome constructions. It is for example illegal to write
\@{<table width="\width">}
In the early days of zoem, you had to write
\@{<table width="}\width\@{">}
- ugly by most standards. Today you write
\@{<table width="\&{\width}">}
Which is not any shorter, but more pleasant to read. What happens is that the contents of and scope \&{..} is first fully expanded in plain scope, after which the result is passed back to device scope. You have to be careful though. The content of \&{..} should never expand to something containing the at sequence \@{..}, because device scope is not allowed to nest. It should also not expand to something containing the and sequence \&{..} either, as this sequence is illegal in plain scope.
The first kind of zoem escape introducing device scope is \@{..}. The second kind comprises the \special#1 mappings, including the three zoem glyphs \~, \|, and \-. Conventionally, these are used to encode a non-breaking space ( in html), a line break (<br> in html), and a long dash (emdash, not present in html). You would for example put
\if{\cmp{eq}{\__device__}{html}}{ \special{ {38} {&} \: 38 is ascii character '&' {60} {<} \: 60 -> '<' {62} {>} \: 62 -> '>' {256} { } \: the zoem escape \~ {257} {<br>\N} \: the zoem escape \| {258} {-} \: the zoem escape \- } }{ }
All \special#1 definitions are interpreted in device scope. For every character encountered in plain scope, it is checked whether a \special#1 definition exists, if so, the corresponding string is retrieved and this is filtered through the device scope filter. Note that the three zoem glyphs described here may not be used in device scope, they can only be used in plain scope. In device scope you will have to write the explicit, device-specific sequence such as <br> (in html).
The \special#1 primitive allows different levels of mappings to be defined simultaneously. Several definitions of the same character are allowed; these are placed on a stack particular to that character (cf. the \special#1 entry). When zoem encounters a character for which one or more mappings exist, it retrieves a mapping using the special level. This is an integer that has by default the value 1. Each open output stream has a unique special level associated with it. [Output streams exist for the default output file (see e.g. \writeto#1) and for each file openend by \write#3]. A mapping is retrieved using this rule: The deepest element is fetched for which the depth does not exceed the level. The most visible element (which is the element first occurring in the \special#1 invocation) has depth 1.
The presence of different levels comes in handy e.g. when the troff device is used. In some contexts, the double quote is a special character in troff (and a printable quote is then mysteriously represented by two consecutive double quotes), in most contexts it is not. This is combatted by including these two specifications in the \special#1 call preparing for troff output (note that 34 is the ASCII value representing the double quote):
\special{ ... {34}{"} {34}{""} {92}{\e} ... }
The first pair shown simply maps the double quote onto itself, and the second pair maps it onto a double double quote. As long as the special level is 1, the second definition is not used. The backslash (with ASCII value 92) needs only one definition as it is escaped in the same way in all troff contexts.
The special level can be set using the \+ directive, which must be followed immediately by a digit in the range 0-9 enclosed by curly brackets, e.g. \@{\+{2}} will set the special level to 2. The special level can be set to 0 (zero) and this means that no character will be mapped.
Example
Whenever a troff context is entered where the quotes needs escaping,
the controlling zoem macro issues a sequence
\@{\+{2}"} ... funny quote context ... \@{"\+{1}}
Such a macro is typically defined in a package and its definition should never be visibile to the user of the package. Note that the double quotes embedded in at scope in the example above are not susceptible to special mapping -- mapping is only applied in plain scope.
The third kind of device scope strings are those mapped to by the \constant#1 primitive. An example of (toy) usage is this:
\constant{ {'e} {é} \: Use e.g. as \*'e*l\*`e*ve (élève) {(c)} {©} \: Use e.g. as \*(c)* DEEDEE (© DEEDEE) {+-} {±} \: Use e.g. as \*+-* a few (± a few) }
This is largely convenient syntactic sugar. These constants could also have been defined as
\def{"'e"}{\@{é}} \def{"(c)"}{\@{©}} \def{"+-"}{\@{±}}
The idea is that the \*..* namespace is used for glyph-like device-specific bindings, whereas the \".." namespace is used for semantic purposes that are device-independent, but nothing prohibits you from fiddling with this.
Zoem provides a shorthand for entering SGML-style tags. It is checked by zoem for well-formedness of the resulting SGML code, and it can be freely mixed with other modes of entering tags. Normally you would have to enter SGML-style tags in device scope, or write a macro for doing that. For example, a macro x#2 that expands \x{b}{be bold} to \@{<b>}be bold\@{</b>} is a likely candidate. However, this would be inelegant for constructions that span a long distance, and it does not provide for letting zoem expressions expand within an xml tag.
Zoem provides the \< and \> tokens. The \< token can be used in three ways:
\<foo> \: foo can be an expression. Some <content> \: of course, expressions may occur here as well. over here. \<bar>{zut} \: bar can be an expression too; \: this syntax will close itself. Some <content> \: again, expressions may occur here as well. over there. \<> \: this is a closing tag for the first foo.
Suppose that foo, bar, and zut expand to strings FOO, BAR, and ZUT respectively (FOO and BAR might be of the form tag a="b" c="d"). Provided that the characters <, >, and & are automatically mapped in plain scope (as a result of correct \special#1 usage), the above will result in
<FOO> Some <content> over here. <BAR> ZUT </BAR> Some <content> over there. </FOO>
The foo part inside the \<foo> syntax should never expand to something containing a >. This is entirely the responsibility of the user.
Both kinds of syntax, \<foo> and \<bar>{zut}, are kept as they are during the expansion stage, and they can be subjected to multiple levels of expansion (which may be the case if such syntax is used inside e.g. \setx#2 or \apply#2). It is only at the output stage that the syntax is transformed to actual SGML code and that well-formedness is checked. So, the two examples just seen will first transform to \<FOO> and \<BAR>{ZUT} (please note that foo, bar, and zut all denote expressions here). If they are at that point no longer subject to expansion they enter the output stage where they are converted to <FOO> and <BAR>ZUT</BAR> (plus some additional formatting/indenting) respectively.
Zoem pushes on a stack of opening tags whenever it encounters \<foo> syntax during the output stage. It naturally knows that a tag can be followed by attributes. It also knows that a tag such as <tag a=b/> closes itself (XML syntax). It does not know about other ways of entering tags, so \@{<body>} would not affect the stack just mentioned. \<> automatically closes the top level opening tag from the stack. Again, syntax such as \@{</body>} does not interact with the stack. This is actually useful; I mainly use the \<foo> syntax for more complicated stuff such as nested material in tables (e.g. the table of contents in this document).
It is possible to explicitly close a tag by simply using \</foo> syntax. Zoem will check whether the closing tag matches the top level opening tag. As seen before, \<> does the same thing, but rather than doing a check, zoem will use the top level opening tag to construct the corresponding closing tag. Finally, \> does the same as \<>.
Zoem prints each opening or closing tag on a line by itself, and it indents nested tags (using two spaces as the indent unit). This cannot be changed.
Several keys take another key as argument, e.g. they store a value in a second key or check whether the second key exists. The full list of these meta keys is \def#2, \defx#2, \set#2, \setx#2, \undef#1, \defined#2, \apply#2, and \inspect#4. In all cases, the argument key is passed as the first argument, by means of the key signature.
For a key \key taking k (k>0) arguments its signature is key#k. The signature of a key \key taking no arguments is simply key. The rule is: Key usage always includes a single leading backslash (this activates the key). When a key is subject of inspection, it is always referred to by its signature.
Throughout this text, a key with signature key#k is mentioned by means of its key mention \key#k, that is, for extra clarity the backslash is prepended to the signature.
A single underscore introduces an anonymous key. It is optionally followed by a #k tag (for k in 0..9), denoting the number of arguments the anonymous key takes. An occurrence of the latter is called a tagged anonymous key. The first argument to the key should be a key definition, the other arguments are the arguments for that key definition. If a tag is present, it is used for verifying that the anonymous key is used properly.
\_{\1 the \2}{row}{boat} \_#2{\1 the \2}{row}{boat}
results in
row the boat row the boat
Anonymous keys may occur in the first argument of \apply#2, within the first argument of \inspect#4, and they may occur freely in running text. The presence of a tag is required when an anonymous key is used within either of \apply#2 and \inspect#4. An example of usage in \apply#2:
\apply{_#2{\1 kisses \2\|}}{{bill}{max}{max}{bill}} bill kisses max max kisses bill
or even
\set{%foo}{{{\1 hugs \2\|}}} \apply{_#2\%{foo}}{{bill}{max}{max}{bill}} bill hugs max max hugs bill
Note that in order to store a block with \set#2, an extra pair of curlies has to be used, as blocks can only be passed as a sub-argument of a single-element vararg. Also note that in a vararg it is allowed to put white space inbetween the constituting elements.
Data can be organized in a global tree with a specialized use of \set#2 and its siblings, as shown further below. The data is retrieved from the tree using so called grape keys. Such a key is started using a percent sign, immediately followed by zero, one, or more blocks, e.g. \%, \%{..}, and \%{...}{...}{...} would all be allowable invocations. If more than one block follows the percent sign, there must be no interleaving white space.
The underlying primitive has signature %#1, as the trailing scopes are congegrated into a single argument before they are further processed. The two sibling primitives %%#1 and %%%#1 serve for freeing and dumping parts or whole of the tree, as described further below.
When applied to grape keys, \set#2 and its siblings set one or more values in a global multi-dimensional associative array that we shall refer to here as ROOT. Please note that ROOT is for explanatory purposes only. This associative array is best viewed as a tree, in which every node can have branches to higher nodes. A node may or may not contain a value. Let us denote the value contained by a node some-node as *(some-node). The fact that beta is a node one branch higher than alpha, which is in turn one branch higher than ROOT, is denoted as ROOT->"alpha"->"beta". In this path notation, strings indexing nodes in the trees are written inbetween quotes. This has the advantage that the empty string, which is a valid index string, has the representation "". Combining these conventions, we write the value associated with beta as *(ROOT->"alpha"->"beta"). Consider these examples.
\set{%{foo}{bar}{zut}}{lez} \: now *(ROOT->"foo"->"bar"->"zut") is "lez" \set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \: now *(ROOT->"foo"->"bar"->"zut"->"a") is "b" \: and *(ROOT->"foo"->"bar"->"zut"->"x") is "y" \: and *(ROOT->"foo"->"bar"->"zut") still is "lez" \: some special cases \set{%{foo}{bar}{zut}}{{{c}}} \: now *(ROOT->"foo"->"bar"->"zut") is "{c}" \set{%{foo}{bar}{zut}}{{c}} \: now *(ROOT->"foo"->"bar"->"zut") is "c" \set{%{foo}{bar}{zut}}{c} \: now *(ROOT->"foo"->"bar"->"zut") is "c" \set{{foo}{bar}{zut}}{{c}{d}{e}} \: This does nothing, because the second argument \: must either be an *even* vararg, a 1-element vararg, \: or a simple argument. \set{%{{tiger}}}{in the woods} \: now *(ROOT->"{tiger}") is "in the woods" \set{%{tiger}}{in the woods} \: now *(ROOT->"tiger") is "in the woods" \set{%tiger}{on the loose} \: now *(ROOT->"tiger") is "on the loose" \: stripping curlies from a vararg with one argument \: does not make a difference with the exception of \: the case shown below. \set{%{}}{empty} \: now *(ROOT->"") is "empty". \set{%}{root} \: now *(ROOT) is "root".
Take note of the rule governing the second argument. If the first non-white space character is a left curly, \set#2 expects a vararg. The vararg must either be even or it must contain exactly one argument. An even vararg is interpreted as a sequence of key-value pairs. Each key induces a new branch from the node specified in the first argument, and each value is associated with the node at the end of that branch. If the vararg contains exactly one argument, that argument is simply used as a value. This is the only way to specify a block as the value. If the first non-white space character is not a curly, \set#2 will simply interpret the second argument as a value to append to the node specified in the first argument.
If you want the data to be stored to be expanded before it is bound, use \setx#2 or \defx#2.
Data is retrieved simply by prefixing the path with the \% token. Example:
\set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \%{foo}{bar}{zut}{a} \%{foo}{bar}{zut}{x}will print b and y. If the path is not an existing path in the current tree it will simply be ignored, allthough an error message will be emitted.
Whole or part of the data tree can be freed using the \%% primitive. Again, simply append the access sequence in which you are interested. For freeing the entire tree, use \%% without trailing scopes. The \%% primitive largely exists for testing purposes to ensure that zoem gets its internal data manipulation right.
Whole or part of the data tree can be output for debugging purposes using the \%%% primitive. Simply append the access sequence in which you are interested. For printing the entire tree, use \%%% without trailing scopes. This can be used for debugging if your data manipulation does not work out as expected. There is no result text as far as usual processing is concerned. The underlying primitive dumps its findings to STDOUT in a line-based textual representation of the data-tree.
The future might bring support for using localized data trees, e.g. by means of \push{grape} and \pop{grape}. It should also become possible to specify the behaviour if a grape key access sequence does not exist.
A block is a string beginning with a left curly and ending with a right curly, the curlies being balanced. This is a convenient naming convention. Blocks can be used in constructing anonymous keys; refer to the Anonymous keys section.
Some keys take a vararg argument, which is a single argument (enclosed by curlies as are all arguments), which can contain any number of sub-arguments, that is, a list consisting of blocks. Inbetween the blocks white space may occur. The \special#1 and \constant#1 keys both take a single vararg argument, and the \apply#2 and \switch#2 keys each take a vararg as their second argument. For \apply#2 the first argument is a key that is applied to subsequent batches of arguments from that vararg. The \table#5 primitive takes a vararg as its last argument. For examples, see the A zoem tour section and the \apply#2 entry.
An even vararg is a vararg with an even number of elements, An odd vararg is a vararg with an odd number of elements.
\__device__ \: the session's output device \__fnbase__ \: the base name of the entry file \__fnentry__ \: the name of the entry file \__fnin__ \: the name of the current input file \__fnout__ \: the current default output file \__lc__ \: expands to a left curly (only for magic) \__line__ \: the line number in the file currently parsed \__parmode__ \: slurp setting for interactive mode \__rc__ \: expands to a right curly (only for magic)\__searchpath__ \: search path for included files \__split__ \: user space chapter mode indicator
This manual is littered with examples of the usage of \__device__. The \__fnbase__ key is useful for creating sibling files of the entry file, i.e. a table of contents file or a file containing reference information. I have the habit of naming those \__fnbase__.zmt and \__fnbase__.zmr, respectively. The \__fnin__ key is useful for emitting log, warning, or error messages particular to the file currently being parsed.
The \__parmode__ macro affects the way in which zoem reads chunks in interactive mode (refer to Section Invoking zoem from the command line ).
The \__searchpath__ macro is one of the ways in which zoem can be instructed to search for files in a set of locations, when confronted with \dofile#2 or one of its aliases. Refer to Section File search path .
This is the result from doing zoem -l macro:
Built-in aliases and macro's \def{input#1}{\dofile{\1}{!+}} \def{import#1}{\dofile{\1}{!-}} \def{read#1}{\dofile{\1}{?+}} \def{load#1}{\dofile{\1}{?-}} \def{refcaption#1}{\ref{\1}{c}} \def{refnumber#1}{\ref{\1}{n}} \def{reflevel#1}{\ref{\1}{l}} \def{refmisc#1}{\ref{\1}{m}} \def{reftype#1}{\ref{\1}{t}} \def{ctrinc#1}{\ctradd{\1}{1}} \def{ctrdec#1}{\ctradd{\1}{-1}} \def{and#1}{\fv{and}{\1}} \def{or#1}{\fv{or}{\1}} \def{and#2}{\f{and}{\1}{\2}} \def{or#2}{\f{or}{\1}{\2}} \def{not#1}{\if{\1}{0}{1}} \def{ignore#1}{} \def{group#1}{\1} \def{system#2}{\system{\1}{\2}{}} \def{system#1}{\system{\1}{}{}} \def{div#2}{\f{div}{\1}{\2}} \def{mod#2}{\f{mod}{\1}{\2}} \def{PI}{3.1415926536} \def{E}{2.71828182846} \def{"+"#2}{\f{+}{\1}{\2}} \def{"*"#2}{\f{*}{\1}{\2}} \def{"%"#2}{\f{%}{\1}{\2}} \def{"-"#2}{\f{-}{\1}{\2}} \def{"/"#2}{\f{/}{\1}{\2}} \def{""}{}
Cf \dofile#2, \ref#2, \ctradd#2, \f#2, \f#3, \fv#2, and \system#3.
By default, when using \def#2 and \set#2, keys and their values are put in a global user dictionary. It could be useful to shadow keys by entering a new name scope. Zoem facilitates this by providing the \push#1 and \pop#1 keys. These push and pop a new dictionary onto the user dictionary stack.
A second dictionary stack is the dollar dictionary stack, which contains all keys that start with a dollar sign. The user has no control over this stack. The \begin#1 primitive pushes a dollar dictionary each time it is invoked, and that dictionary is popped by the corresponding \end#1 invocation. This is typically useful for creating nested environments that need access to the same type of information - by storing such information in dollar keys, it can be shadowed and recovered. Refer to the \begin#1 entry.
When a key is used its definition is searched in all dictionaries, starting from the top-level dictionary. The key \undef#1 has only access to the top-level dictionary, and will never delete a key in any other dictionary.
What follows is an informal tour through zoem's offerings. The next section contains a comprehensive overview of the zoem primitives.
Let us start with how filtering in plain space is configured. An example was given above for a single device (namely html). A more realistic approach, used in the zoem man macros, is this.
\switch{\__device__}{ {html}{ \special{ {38} {&} {60} {<} {62} {>} {256} { } \: the zoem escape \~ {257} {<br>\N} \: the zoem escape \| {258} {-} \: the zoem escape \- } } {roff}{ \special{ {46} {\\.} {96} {\\`} {92} {\\\\} \: a single backslash {256} {\\ } \: the zoem escape \~ {257} {\N.br\N} \: the zoem escape \| {258} {\\-} \: the zoem escape \- } } {\write{stderr}{txt}{No such device: \__device__\|} \write{\__fnbase__.err}{txt}{No such device: \__device__\|} \exit } }
Take note of the number of backslashes. In order to print a backslash in troff, the troff input must contain two consecutive backslashes. In order to specify a backslash in zoem, we must also provide two, thus we need four backslashes in all (in order to create this example I needed eight backslashes in the zoem input).
Also note the use of the \switch#2 primitive, which takes an expression in the first argument and an arbitrary number of pairs plus an optional clause in the second argument. The optional clause was in this case used as a failure test.
\special#1 is an example of a zoem key taking an argument that may contain arbitrarily many sub-arguments (i.e. a vararg). In this particular case the sub-arguments must be paired, each pair defining how certain ascii characters that are special to the device must be represented. There is a very limited number of additional tokens that can be mapped in this way:
The \write#3 and \exit need little comment, they work as expected. Zoem opens output files as needed, and closes them when it is done. stdout and stderr work as you should expect, and - is equivalent to either stdout or stdin, depending on the context.
\exit is considered a failure (and will cause zoem to stop and complain), but \quit is not. \quit will merely quit parsing the current stack, so if you specify it at top level in a file - not nested in a key that does its own parsing such as \setx#2, zoem will stop parsing the current file and transfer control back to the file from which it was included.
The previous example introduces the keys \__device__ and \__fnbase__. They are so called session variables described in section Session keys.
A sibling primitive to \special#1 is \constant#1. The following is an example of use.
\constant{ {'e} {é} \: Use e.g. as \*'e*l\*`e*ve (élève) {(c)} {©} \: Use e.g. as \*(c)* DEEDEE (© DEEDEE) {+-} {±} \: Use e.g. as \*+-* a few (± a few) }
The main thing to note here is that the target string (e.g. é) is always interpreted in device space. Inbetween the asterisks almost anything is allowed, except a backslash or a curly, and it is obviously not allowed to use an asterisk in one of the definition parts of \constant#1.
There are three zoem tokens representing the characters that have meaning to zoem syntax, the backslash and the two curlies. Those zoem tokens are just like any other plain characters: they can be mapped in plain space, and they are printed literally in device space.
\\ \: A backslash; possibly mapped in plain space. \{ \: A curly; possibly mapped in plain space. \} \: A curly; possibly mapped in plain space. \, \: The atomic separator (vanishes).
These tokens are mapped only during the (final) filter stage. The atomic separator can be useful when you want to glue together items some of which will be the result of macro expansion.
\def{foo}{bar} \foo\,1 \: \foo1 would be the key \foo1
This will result in bar1. The tokens \\, \{, and \} are really the corresponding ordinary ASCII characters. They can be mapped in plain space via \special#1 using their ASCII values 92, 123, and 125 as was seen above for the backslash. In device space, they will result in \, {, and }.
Let us now continue with device scope by implementing a \bf#1 key. Below you find two possible definitions:
\def{bf}{1}{\@{<b>} \1 \@{</b>}} \: Ok \def{bf}{1}{\@{<b> \1 </b>}} \: Wrong! Wrong!
The second is wrong because the contents of \1 end up in device space. If the expansion of \1 still contains keys they will not be expanded (and cause a fatal syntax error when device space is filtered), and additionally any special characters in \1 will not be mapped.
This is an overlapping categorization in topics.
Using and inspecting keys | ||
\apply#2
\constant#1
\def#2
\defx#2
\defined#2
\inspect#4
\pop#1
\push#1
\set#2
\setx#2
\table#5
\undef#1
These primitives affect or use either user keys that are stored in the user dictionary, dollar keys that are stored in the dollar dictionary, or anonymous keys. Dictionaries are discussed in Section 7.7. |
||
Control, booleans, testing and comparison | ||
Expansion and meta-zoem | ||
Input/output | ||
Filtering | ||
Environment scopes | ||
Name scopes | ||
Data storage | ||
\%, \%%, and \%%% are primitives described elsewhere
- refer to the
Tree data
section.
|
||
String conversions | ||
Arithmetic | ||
Counters | ||
References | ||
Glyphs | ||
Execution | ||
Syntactic sugar | ||
Zoem primitives may expand (which is the same as evaluate) one, several, or all of their arguments before using them. Such arguments are enclosed by double angle brackets in the listing below. The inside-out type evaluation is done recursively and works for arbitrary levels of nesting. An argument which is first expanded and is then interpreted as a label is thus written <<label>> in the primary entry. In the definition text accompanying the entry, the expanded argument is simply refered to as <label>, so the extra pair of brackets is dropped.
Each primitive below has a little paragraph with the caption Result text. It gives a summary of 'what comes out'. Note that the result of macro expansion is always passed to the parser again, so the result text is again subject to expansion.
\<>#1 | ||||||||||||||||||||||||||||||||||||||||||||
\<>#2 | ||||||||||||||||||||||||||||||||||||||||||||
These are special. Refer to section SGML/HTML/XML syntactic sugar cubes.
The angle brackets are part of the syntax, do not confuse them
with the angle brackets used below to enclose arguments.
These primitives are respectively used as \<*any*> and
\<*any*>{*any*},
so the positioning of arguments is different from all other
zoem primitives.
|
||||||||||||||||||||||||||||||||||||||||||||
\! | ||||||||||||||||||||||||||||||||||||||||||||
This primitive is triggered by an active backslash followed by a consecutive
run of exclamation marks, which is not followed by an opening curly.
The sequence is called a delay sequence, and its arity is the
count of backslashes. A single exclamation mark is stripped (i.e. the arity
is decremented) and the sequence is no longer subject to the current
expansion stage. It is used to construct valid zoem input, which is usually
redirected to file with the copy filter, stored using \setx#2, or used
in nested occurrences of \apply#2, \inspect#4, and other primitives.
Other uses are possible, the main thing is that one should keep a clear view
of the meta-programming implied by \!.
Refer also to the \eval#1 primitive.
Example
\set{foo}{zut} \eval{\!foo} \foo\ whereas \!foo would pass the sequence \foo to the filtering stage, where it will yield a (non-fatal) error message. Similarly, \eval{\eval{\!!foo}} is equivalent to the above.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\!#1: \!{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
This primitive is triggered by an active backslash followed by a consecutive
run of exclamation marks, which is in turn followed by a block. The block
is called a delay scope. The arity of the delay scope is the count of
backslashes found in the run. A single exclamation mark is stripped (i.e.
the arity is decremented); if no further exclamation marks remain (i.e. the
arity becomes zero) then the introducing backslash and the delimiting
curlies are stripped as well. The result (including the contents of the
block) is passed on and is no longer subject to the current expansion stage.
The same observations hold as those made for the previous entry.
Refer also to the \eval#1 primitive.
Additionally, blocks that are protected by the delay primitive will be skipped during parameter interpolation.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\$#2: \${<str>}{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
This is a shortcut for activating output for a particular device.
If \__device__ expands to <str>, <any>
is passed on for expansion, otherwise it is ignored.
The following two are equivalent:
\${html}{Seen only in the html device} \if{\cmp{eq}{\__device__}{html}}{Seen only in the html device}{}
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\alpha#1: \alpha{<<int>>} | ||||||||||||||||||||||||||||||||||||||||||||
Puts the corresponding letter in place, e.g. \alpha{3} results in c.
Use \ucase#1 to obtain capitals.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\apply#2: \apply{<<key-sig|anon-key>>}{<<vararg>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded before use.
It should expand either to the signature of a user key taking
arguments, or to a tagged anonymous key.
Examples of the first are foo#k and "bar::baz"#k, the latter
takes the form _#k{..}.
If you use an anonymous key containing macro sequences, be sure to
escape whole or part of the anonymous key, depending on your needs.
The expansion of _#2\!{{<any>}} for example, will result
in _#2{<any>}.
The second argument should result in a vararg. \apply#2 extracts k elements at a time from <vararg>, and applies the key resulting from the first argument to each vector of k elements successively. Any elements remaining in <vararg> are ignored. apply#2 has really turned out to be an all-round workhorse. For an interesting application see Example II in the \begin#1 entry below.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\begin#1: \begin{<label[<<vararg>>]>} | ||||||||||||||||||||||||||||||||||||||||||||
Expands the begin expression associated with <label> via \env#3. The
label can optionally be followed by a <vararg> with any number of
arguments inbetween 1 and 9. These arguments are accessible to the begin
expression (as defined by \env#3) as the keys \$1 .. \$9. The idea
is that the environment can allow a user to specify arguments if he wants to,
whereas it will provide default values for the undefined slots. The
<label> part is not expanded. The <vararg>, if present, is
expanded before use.
The number of arguments that is present is stored in the key \$0 (note that it is not stored as a counter). \begin#1 pushes a new dictionary onto the dollar dictionary stack and the keys just mentioned live in this dictionary (which is popped by the matching \close#1). This means that nested \begin#1 statements will work. It also means that the begin definition must use \defined{lkey}{...} rather than \defined{key}{...} when it wants to check the definedness of its arguments - but the \$0 keys is always defined. Finally, it means that by associating dollar keys with an environment, these keys can be given different meanings in nested environments - the previous meaning will be restored once an environment is closed. The advantages are that the environment does not have to exercise \push#1 and \pop#1 itself, that the user dictionary stack is not unnecessarily extended (saving look-up time), and that the 'dollar' look of a key such as \$item signals that it will automagically work in nested enviroments. Of course, the latter is still the responsibility of the author of the environment.
Result text
Example I
\begin{faqsec{misc}{Miscellaneous questions}} ... \end{faqsec} The first additional argument is a label (which is allowed to be empty but must be present), the second argument is the title of the section.
Example II
\begin{itemize{ {contiguous}{1} {compact}{1} {mark}{\*bullet*} {align}{right} } } ... \end{itemize} Internally, the itemize environment maps these options to dollar keys. Because a unique dollar dictionary is associated with each environment, this makes it possible for nested itemize instances to have separate namespaces. Several more options than those given here are supported by the itemize environment. All listings in the present text were created with it. This is approximately how the itemize environment does initialization: \env{itemize}{ \apply{def#2}{ {$contiguous}{0} {$compact}{0} {$w1}{30} {$w2}{10} {$mark}{\*bullet*} {$margintop}{1} {$align}{left} {$debug}{0} } \if{\defined{lkey}{$1}}{ \apply{_#2\!{{\set{$\1}{\2}}}}{\$1} }{ } .. }{ .. } This is clearly programming close to the metal, but it works very well.
Warning
|
||||||||||||||||||||||||||||||||||||||||||||
\cmp#3: \cmp{<str>}{<<any>>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
The last two arguments are expanded. Their results are compared as
strings. The first argument must be one of the labels
lt|lq|eq|gq|gt|ne|cp. In case it equals one of the six labels
lt|lq|eq|gq|gt|ne, this primitive puts in place
the associated boolean as
a string (i.e. either 0 or 1). In case the label equals cp,
it puts in place the result of the string compare (as a string),
namely one of -1, 0, or 1.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\constant#1: \constant{<vararg>} | ||||||||||||||||||||||||||||||||||||||||||||
<vararg> must have an even number of arguments. These are
interpreted as pairs. The first of each pair must enclose a string
that does not contain any of the characters *, \, {, or },
say string <keystr>. The second encloses a string that will be
interpreted in device space, say string <valstr>. When a sequence
\*<keystr>* is encountered, it is interpreted as
\@{<valstr>}. This is done at filter time only, the sequence
is skipped during macro expansion. It is not allowed to use a sequence
\*<keystr>* in device scope, e.g.
\@{\*<keystr>*} is illegal.
For furtherh information see section Device scope.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\ctradd#2: \ctradd{<<label>>}{<<amount>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded, yielding some string <label>.
This string is used as a counter and <amount> is added to
this counter. If the counter does not exist, it is first autovivified with
a value of zero.
The expansion of the first argument is useful, because it allows counters that otherwise count the same thing to be attached to different scopes, simply by appending a string representing the level to the counter.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\ctrset#2: \ctrset{<<label>>}{<<quantity>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded, yielding some string <label>.
This string is used as a counter which is set to the value
<quantity>. The counter may or may not exist beforehand.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\ctrput#1: \ctrput{<<label>>} | ||||||||||||||||||||||||||||||||||||||||||||
Puts in place the counter associated with <label> as a string.
If counter does not exist, the value zero is assumed.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\def#2: \def{<key-sig|grape-seq>}{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
Bind second argument to the key or access sequence
in the first argument. This primitive will
complain if a binding exists already, but it will overwrite the
previous binding and continue anyway. Use \set#2 if you do no want to be
warned for overwriting. Examples of usage:
\def{foo}{FOO} \def{foo#1}{The FOO of \1} \def{foo#2}{The FOO of \1 and \2} \def{$foo#2}{The $FOO of \1 and \2} \def{"foo::oof"#3}{\foo{\1}{\2}\foo{\2}{\3}} These examples are all of type key-sig. See the Tree data section for examples of type grape-seq (this pertains to multi-dimensional data storage). See the Macro expansion section for the forms that keys may take. A key signature is the name of a key with appended to it the number of argument that the key takes, if any. If the key takes no arguments, than the key signature is identical to the key name. If you want the value to be bound to be expanded before binding it, use either \defx#2 or \setx#2. This works the same for grape keys.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\defx#2: \defx{<key-sig>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
The second argument is expanded and stored in the key <key-name>. This
primitive will complain if a binding for that key exists already, but it will
overwrite the previous value anyway.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\defined#2: \defined{<type>}{<<access>>} | ||||||||||||||||||||||||||||||||||||||||||||
<type> is one string of key, lkey, or data. The
second argument is expanded before use. For the type key, the result is
looked up as a key signature in either the user dictionary stack or the
dollar dictionary stack. For the type lkey, it is looked up only in the
top level dictionary. For the type data, the result is interpreted as a
data access sequence. This primitive pushes the string 1 if the result
is indeed a valid reference, it pushes the string 0 otherwise.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\dofile#2: \dofile{<<file name>>}{<char[!?]><char[+-]>} | ||||||||||||||||||||||||||||||||||||||||||||
Open a file and process its contents while keeping track of line numbers.
Depending on the second argument, absence of the file is either allowed or
not, and its interpreted contents are output or not. The fact
that <file name> is first expanded allows you to specify
file names such as \__fnbase__.zyx.
Zoem may search for a file in several locations until it is found. The process of locating a file is described in section File search path . When found, the file is opened according to the specification in the second argument. This argument must contain exactly two characters, the first one of [!?], the second one of [+-]. The first character indicates whether the file is allowed to be absent. A ´!' implies that absence is fatal, a '?' permits absence. The latter is useful e.g. when creating a Table Of Contents file. The second character indicates whether the interpreted file should be filtered and output or not ('+' for yes and '-' for no). Macro packages typically need interpretation only, whereas concatenation of document parts (c.q. chapters) stored in different files requires that the interpreted content is also filtered and output. The following aliases are available: \input{fname} \dofile{fname}{!+} \import{fname} \dofile{fname}{!-} \read{fname} \dofile{fname}{?+} \load{fname} \dofile{fname}{?-} The contents of <file name> cannot be captured. If you need to capture the contents of a file, use \finsert#1 or \zinsert#1.
Result text
\setx{foo}{\dofile{bar}{!+}} will result in the file <bar> being processed and output via the standard output mechanisms, while the key \foo will have the empty string as value. |
||||||||||||||||||||||||||||||||||||||||||||
\end#1: \end{<label>} | ||||||||||||||||||||||||||||||||||||||||||||
\env#3: \env{<label>}{<any1>}{<any2>} | ||||||||||||||||||||||||||||||||||||||||||||
\eqt#3: \eqt{<str>}{<<num1>>}{<<num2>>} | ||||||||||||||||||||||||||||||||||||||||||||
The last two arguments are expanded. Their results are compared as
numbers. The first argument must be one of the labels
lt|lq|eq|gq|gt|ne|cp. In case it equals one of the six labels
lt|lq|eq|gq|gt|ne, this primitive pushes the associated boolean as a
string (i.e. either 0 or 1). In case the label equals cp,
this primitive pushes the result of the integer compare,
namely one of -1 (if the result of <any1> is
smaller than the result of <any2>),
0 (equal to), or 1 (greater than).
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\eval#1: \eval{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
Expands <any> and passes it on for further evaluation.
This can come in handy when complicated requirements demand
zoem acrobatics. This primitive used to be implemented as a macro;
it is fully equivalent to
\set{eval#1}{\apply{_#1{\!1}}{\1}} The above macro works as follows. First, \apply#2 expands both of its arguments. The second argument is the data it received from \eval, i.e. the latter's single argument. At this stage, the data is thus expanded for the first time. \apply#2 also expands its first argument. The sequence \!1 is contracted to the sequence \1. The \1 needed by \apply#2 needs to be protected by the interpolation that occurs when eval#1's argument is interpolated. Expansion of \apply#2's first argument thus yields the anonymous key _#1{\1} - a key that simply copies it argument and passes it on for further expansion.
Example
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\exit | ||||||||||||||||||||||||||||||||||||||||||||
goodbye world. This is a disgraceful exit for use when some error test
presumably yields true.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\f#2: \f{<fun>}{<<num1>>} | ||||||||||||||||||||||||||||||||||||||||||||
Expand the last argument, interprets the result as a number,
applies the operand specified by <fun>, and puts the
result in place.
<fun> can be one of
floor, ceil, round, abs, sign, inc, dec, not, and that's about it. For a wider range of mathematical functions, refer to the \let#1 primitive.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\f#3: \f{<fun>}{<<num1>>}{<<num2>>} | ||||||||||||||||||||||||||||||||||||||||||||
Expands the last two arguments, interprets the results as
numbers, applies the operand specified by <fun>, and puts the
result in place.
Most arithmetic is done using floating point arithmetic (with the C double type). Integers are preserved if possible. Since nearly everything is treated as a string in zoem, this simply means that no decimal fraction is printed when the number is output. A number is considered integer if the difference with the integer nearest by is less than the precision (1e-8) and if it can be represented as an integer using the C long type. Otherwise it is output in decimal representation of the underlying floating point representation. <fun> can be one of
For a wider range of mathematical functions, refer to the \let#1 primitive.
NOTE
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\fv#2: \fv{<fun>}{<<vararg>>} | ||||||||||||||||||||||||||||||||||||||||||||
Expands the second argument and interprets it as vararg,
and applies the operator specified by <fun> to the elements of vararg.
<fun> can be one of
NOTE
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\finsert#1: \finsert{<file name>} | ||||||||||||||||||||||||||||||||||||||||||||
The argument is expanded and interpreted as file name. The file is read,
and every \, {, and } is escaped (resulting in one of
\\, \{, and \}) The altered contents are then put in
place. See also \zinsert#1.
If file can not be opened, the empty string results.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\formatted#1: \formatted{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
This removes and adds white space from its arguments
via the following rules:
This is useful for writing legible macro files while exercising full control over whitespace (modulo Zoem's white space munging rules).
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\if#3: \if{<<condition>>}{<any1>}{<any2>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded and interpreted as an integer.
If it is nonzero, <any1> is pushed on the interpretation stack
and <any2> is ignored, vice versa if it is zero.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\inspect#4: \inspect{<mods{<<reg>>}{<<any|anon key>>}>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
All arguments except mods are expanded before use. The expansion of
<reg> is
followed by an unprotect and should result in a POSIX regular expression. The
unprotect action unescapes escaped backslashes and curlies, so that those can
be passed to the regex engine (although it interprets backslashes, so you need
to quadruple those if you don't want them interpreted).
The expansion of <any|anon key> can either result in plain data or in an
anonymous key. The third expansion results in data to which the regex
<reg> is successively applied.
If the second expansion results in something recognizable as an anonymous key,
then the subpatterns from the matched pattern are interpolated by the key, and
the entire matched pattern is substituted by the interpolation.
Else, the matched pattern is simply replaced by the expansion.
mods must contain the keyword posix, it may further contain a subset of the keywords count dotall grep grepc icase lines look skip snip vararg. This primitive has not yet been blessed by exhaustive stress-testing, so perhaps not all of these work flawlessly. skip prohibits non-matching part from being output. icase induces case insensitive matching. dotall makes the dot . match any character, including the newline. lines causes matching to be applied to lines shifted from the data (i.e. data is split on newlines). vararg causes matching to be applied to blocks shifted from the data (which should obviously be a vararg). count replaces the data by the count of matches, and works in conjunction with both lines and vararg. snip removes any lines or blocks which are empty after inspect is done with it. grep outputs only matching elements (only in conjunction with lines or vararg). grepc outputs only non-matching elements (only in conjunction with lines or vararg). look does not substitute, works in conjunction with grep -- matching elements are kept intact.
Example
\formatted{ \setx{buzzz}{ \inspect {posix, dotall, skip} {DOCTYPE(.*)PUBLIC} {_#1{\1}} {\finsert{buzzz.html}} } } \<div class=indent> \apply{_#1{\@{\w\1\W}}}{{\buzzz}} \</div> Note the use of \apply#2 in order to get the contents of a macro into device scope, and note that in device scope white space munging is turned off using \w (and resumed using \W). This is done so that verbatim environments are preserved in the included text.
Bugs
There are many possible combinations of modifiers, and not all of them work together. It is mainly a bug in this documentation that forbidden combinations are not yet listed here. It is possible that certain combinations should work together but fail to do so. However, no such cases are known at the moment. A search pattern consisting of a single word boundary or the start-of-string token (^) will match at each position, because after a succesful match \inspect#4 simply resumes searching for a new match by skipping to the end of the previous match (and adding a single position if the match had width zero and offset zero). Similar but not yet noticed bugs may exist. Nevertheless, this can be a very useful primitive for the occasional odd job, and it should always work except for the cases just mentioned. If you have a complicated instance of \inspect#4, test it first in isolation. Consider sending a bug report in case you find one (a bug, or a bug report).
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\let#1: \let | ||||||||||||||||||||||||||||||||||||||||||||
The \let#1 primitive puts zoem in arithmetic mode and the contents are
parsed accordingly. All of C's operators are supported including the
logical, bitwise, and comparison operators as well as the ternary operator.
The operators ** and // are added, which respectively denote
exponentiation and integer division.
Operations or functions resulting in integers are tracked, and
the result will be stored in the integer type used (typically
long) if possible. Thus one may find that
\let{2**42} \let{2**22} respectively result in 4398046511104.0 and 2097152. The precedence rules used by Zoem are simpler than C's. The respective groups of logical, bitwise, and comparison operators all have identical precedence internally, and associate from left to right. Most of the ANSI C math functions are supported, with in addition max and min. The functions round, sign, and abs behave slightly different from their C counterparts, as they result in integer results if no overflow occurs. At any place where an atomic type is expected one is allowed to insert a zoem macro invocation. It will be evaluated and the result will be interpreted as a number. Evaluation will take place in the order as dictated by the precedence rules governing the expression. The logical operators shortcircuit and the ternary operator evaluates only one of its branches. This can be used to create side effects, such as in \let{\bar && \group{\set{foo}{zut}1}} This sets foo only if bar evaluates to a non-zero number. The trailing 1 in the group macro is good practice because \let#1 expects a number to be the result of any macro it encounters. It could have been any other number, or a macro or sequence of macros evaluating to a number. The group macro is a predefined macro that does nothing except passing its arguments. It is necessary in this concocted example because any occurrence of a macro within \let#1 is interpreted as a number by itself. The sequence \bar \bar would for example be syntactically identical to 1 1, which is incorrect.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\pop#1: \pop | ||||||||||||||||||||||||||||||||||||||||||||
Pops a dictionary from the user dictionary stack if <label>
is the character u.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\protect#1: \protect | ||||||||||||||||||||||||||||||||||||||||||||
The argument is expanded. Subsequently, all backslashes and curlies
are escaped. The resulting text is put in place.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\push#1: \push | ||||||||||||||||||||||||||||||||||||||||||||
Pushes a new dictionary onto the user dictionary stack if <label> is
the character u. Note that \defined#2 with the lkey label
checks only the top-level dictionary, whereas \defined#2 with the
key label checks the whole stack of dictionaries. Also, \undef#1
only removes a key from the top-level dictionary. There is currently not a
way to remove a key from all dictionaries.
Result text
Example of usage: \def{num}{1} \push{u} \def{num}{2} \push{u} \def{num}{3} \push{u} \def{num}{4} \pop num is \num \pop num is \num \pop num is \num results in num is 3 num is 2 num is 1 |
||||||||||||||||||||||||||||||||||||||||||||
\quit | ||||||||||||||||||||||||||||||||||||||||||||
Quit parsing current stack. If encountered in a file at top level,
i.e. not nested in a key that does its own parsing such as \setx#2,
it simply terminates file interpretation at that point. And these are
equivalent:
\setx{foo}{\bar begat \baz\quit bla boo dee} \setx{foo}{\bar begat \baz}
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\ref#2: \ref{<str>}{<char[ltncm]>} | ||||||||||||||||||||||||||||||||||||||||||||
Put one of the fields associated with the label <str>
in place. The second argument is a single character identifying
the field to retrieve. Use l for the level field, t for the
type field, n for the number field, c for the caption field,
and m for the misc field.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\refload#6: \refload{<a>}{<l>}{<t>}{<n>}{<c>}{<m>} | ||||||||||||||||||||||||||||||||||||||||||||
Associates several fields with an anchor for later retrieval using \ref#2.
Here <a>, <l>, <t>, <n>, <c>, and <m> stand
for anchor, level, type, number, caption, and misc respectively. For a
section, the fields other than the anchor field could for example be 3,
Section, 6.2.1, How to peel potatoes, this field not used.
This primitive is clearly meant to support index and table of content
macros.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\roman#1: \roman{<<int>>} | ||||||||||||||||||||||||||||||||||||||||||||
Puts the corresponding letter in place, e.g. \roman{1999} results in
mcmxcix. Used in the itemize environment defined in the
generic package.
Use \ucase#1 to obtain capitals.
|
||||||||||||||||||||||||||||||||||||||||||||
\set#2: \set{<key-sig>}{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
\setx#2: \setx{<key-sig>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
The second argument is expanded and stored in the key <key-name>.
Besides simply storing the expansion of an expression, it can
also be used to do trickier things as
\def{bar}{klaas} \setx{foo#2}{\bar says \1 and \2} \foo{x}{y} klaas says x and y If you need lambda-like capabilities, take note that you can use \!k or \!{\k} to construct a positional parameter \k, if you want to interpolate arguments into a key that will later take other arguments. Like this: \: is there any use for this wacky stuff? \def{lambda#2}{\setx{\1#1}{\2 says \!1}} \lambda{foo}{bar} \foo{moo} bar says moo Take care: the \dofile#2 key outputs to the default output file. If you need to include the contents of a file within a \setx#2 call, you need to use \finsert#1 or \zinsert#1 in conjunction with \setx#2.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\special#1: \special{<vararg>} | ||||||||||||||||||||||||||||||||||||||||||||
<vararg> must have an even number of arguments. These are
interpreted as pairs. The first of each pair must enclose an integer in
the range 0-258. The first 256 integers in this range are interpreted as
character indices according to the ASCII (American Standard Code for
Information Interchange) standard. The characters indexed 256, 257, and
258 correspond with the zoem glyphs \~, \|, and \-
respectively. The second element in each pair defines the string to
which the character specified by the first element must be mapped. This
string is interpreted in device scope. See the
zzello world and Device scope sections for simple uses.
A key may occur multiple times. The corresponding definitions are stacked away and will be accessed according to the current special level (cf. the section on mapped characters in device scope). Repeated use of \special#1 does not cause the removal of previous definitions, with one exception: If \special#1 is invoked with no arguments at all then all definitions are removed.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\switch#2: \switch{<<pivot>>}{<vararg>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded. Subsequently, two arguments are successively
taken from <vararg>. The first is expanded and string compared with
<pivot>. If they match, the second argument is expanded and everything
else is ignored. If they do not match, the procedure is repeated. If no
(odd) argument matches, and the <vararg> has an odd number of
arguments, the last argument is put in place. It can be considered a
failure clause. This primitive does not have fall-through behaviour; at
most one branch will be handed to the parser.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\system#3: \system{<cmd>}{<<args>>}{<<data>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is the name of a system command. The environment variable
PATH is used in tracing the location of the command. If <data> is
non-empty, it is first unprotected, that is, escaped backslashes and
curlies are unescaped. The resulting text is then fed to command <cmd>
with arguments <args>. The latter, if non-empty, must be
specified as a vararg, even if only a single argument is present.
Should execution of the command (be it with or
without data) result in output then the latter is captured, backslashes and
curlies are escaped (i.e. the output is protected), and the result is put in
place.
A simple exit status is written in the variable \__sysval__: it is zero (0) on success, and one (1) on failure. Built-in macros \system#2 and system#1 exist. The former drops the <data> argument, the latter also drops the <args> argument.
Example
\system{sort}{{-n}}{\finsert{foo}} \system{ls}{{-l}{-a}} \system{date}
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\table#5: \table{<<row length>>}{<any1>}{<any2>}{<any3>}{<<vararg>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded and interpreted as an integer, say k.
Successively, vectors of k elements are shifted from
<vararg>. Each vector is bordered on the left with
<any1>, bordered on the right with <any3>, and
all elements in the vector are separated with <any2>.
This primitive is perhaps not really needed as its functionality is largely covered by \apply#2.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\tr#4: \tr{<[cds]*>}{<<list1>>}{<<list2>>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
If no modifiers (one or more of [cds]) are specified, map characters
from <any> which are in <list1> to the corresponding character in
<list2>. <list1> and <list2> may contain ranges of
characters such as a-z and 0-9, but syntactically the two lists
must be identical, i.e. the combination {1a-z}{A-Z0} is illegal. There is
one exception, namely <list1> is allowed to be longer than
<list2>. The characters for which no mapping is specified will be
deleted.
An example of legal use would be {A-Z #@$%}{a-z_} which maps uppercase
to lowercase, space to underscore, and removes some ugly characters.
Characters can be specified using octal notation, e.g. \012 encodes the newline. Use \173 for the opening curly, \175 for the closing curly, and \134 for the backslash. DON'T use \\, \{, or \} in this case! The s modifier squashes translated sequences consisting of the same character repeated into one occurrence of that character. The d modifier simply deletes all entries in <list1> found in <any>. The c modifier only works in conjunction with one of the other two modifiers. It means that the complement is taken of <list1>. When using this in conjunction with s, <list2> must have at least one character and only the first character is considered.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\trace#1: \trace{<<int>>} | ||||||||||||||||||||||||||||||||||||||||||||
The argument is expanded and interpreted as an integer. This integer
encodes an ensemble of flags controlling the trace output. The different
modes are exactly the same as those that can be set from the command line.
Refer to the corresponding section for more information.
Special values are 0 (switch off all tracing),
-1 (switch on all tracing modes in short mode),
-2 (switch on all tracing modes in long mode),
-3 (switch to the previous tracing value),
and -4 emit a listing of tracing bits.
The third can be useful to switch tracing on for a short while and then off
again if you need to debug your document.
Additionally and redundantly, \trace#1 puts the previous tracing
value in place.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\ucase#1: \ucase{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
Translates a-z to A-Z in (the expansion of) <any>.
This is a special case of \tr#4
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\undef#1: \undef{<key-sig>} | ||||||||||||||||||||||||||||||||||||||||||||
Deletes the key with signature <key-sig> from the
top level dictionary. Complains (but does not fail) if the key
does not exist in that dictionary.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\while#2: \while{<condition>}{<any>} | ||||||||||||||||||||||||||||||||||||||||||||
While <condition> exands to something that is nonzero when interpreted
as an integer, <any> is expanded and concatenated to the result text.
The following piece of zoem asks the user for an integer and writes all
Fibonacci numbers smaller than that integer plus one extra to stdout.
\def{fib#1}{ \ctrset{a}{1} \ctrset{b}{1} \ctrset{c}{0} \while{\eqt{lq}{\ctrput{c}}{\1}}{ \ctrset{c}{\ctrput{a}} \ctrset{a}{\"+"{\ctrput{a}}{\ctrput{b}}} \write{-}{txt}{\ctrput{c}\|} \ctrset{b}{\ctrset{c}} } } \write{-}{txt}{Enter a number please, } \write{-}{txt}{then press <cr> and <ctl-d>\|} \setx{num}{\finsert{-}} \: this reads from stdin. \fib{\num}
Note
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\write#3: \write{<<file name>>}{<str>}{<<any>>} | ||||||||||||||||||||||||||||||||||||||||||||
The first argument is expanded and used as a file name. It is a fatal error
if the file has either not been opened by a previous \write#3 call or
cannot be opened for writing. Two special file names or 'streams' are
recognized, namely - and stderr. They map to stdout
and stderr.
The third argument is expanded, filtered, and written to file. The second
argument indicates the filter to be used. It must be one of the (literal)
strings copy, device, or txt.
The copy filter does not filter anything at all (neither plain scope nor device scope) and does not touch any of the zoem escape sequences remaining after expansion. The device filter does a full-fledged filtering of both parse scopes. It respects the settings according to the \special#1 primitive. The write primitive associates unique metadata with each file it opens, so at directives such as \N, \W, and \+ for different output files do not interfere with one another. Refer to the Device scope section for more information on at directives. The txt filter maps \\ to \ (i.e. a single backslash), \~ to a single space, \- to a single hyphen, \, (the atomic separator) to nil, \| to a newline, \{ to {, and \} to }. It copies everything else verbatim.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\writeto#1: \writeto{<<file name>>} | ||||||||||||||||||||||||||||||||||||||||||||
Closes the current default output stream, and changes it to point to file
<file name>. Useful when splitting a document into chapters, or god
forbid, nodes.
Result text
|
||||||||||||||||||||||||||||||||||||||||||||
\zinsert#1: \zinsert{<<file name>>} | ||||||||||||||||||||||||||||||||||||||||||||
The contents of file <file name> are put in place unaltered
enclosed by the \!#1 delay primitive. The contents must necessarily
satisfy zoem syntax. If the file can not be opened, the empty
string results.
See also \finsert#1.
Example
\setx{foo}{\zinsert{mydata}} \setx{foo}{\eval{\zinsert{mydata}}} In the first case, \foo will contain the exact contents of file mydata. Those contents are first enclosed within the \!#1 primitive by \zinsert#1. The resulting text is evaluated by \setx#2 - the only thing this does is strip the enclosing \!{} scope. In the second case, \foo will contain the evaluated contents of file mydata, as \eval#1 adds an additional layer of evaluation.
Result text
|
This section contains a manual page for the fictitious buzzz utility. Several things are shown, including references to options and sections that show up as hyperlinks in html, while resulting in normal text in troff. This requires some authoring discipline, as one has to write the text such that it makes sense in the absence of hyperlinks. This section contains the following subsections:
The last section has several links to the full-fledged mcl manual page and the mcl FAQ.
The buzzz manual page is shipped with the zoem source, as are the manual macros. They are in the files respectively named buzzz.azm and man.zmm.
\def{"man::synstyle"}{long} \def{"man::defstyle"}{long} \import{man.zmm} \: customized command for the synopsis section. \def{fileopt#2}{\bf{\1} (\it{\2})} \set{"man::year"}{2002} \set{"man::month"}{Feb} \set{"man::day"}{4} \set{"man::name"}{buzzz} \set{"man::html-title"}{What's the buzzz} \set{"man::author"}{Stijn van Dongen} \set{"man::section"}{1} \set{"man::tag"}{1.00} \"man::preamble" \${html}{\"man::maketoc"} \def{buzzz}{\bf{buzzz}} \sec{name}{NAME} \par buzzz \- go buzzz. \sec{synopsis}{SYNOPSIS} \par \buzzz \synreqopt{-l}{i}{loudness} \synreqopt{-d}{f}{duration} \synoptopt{-f}{f}{frequency} \synoptopt{--dragonfly}{dragon style} \synoptopt{--bumblebee}{bumble style} \synoptopt{--disk}{computer style} \synoptopt{-style}{some style} \synoptopt{--scan}{scan mode} \synoptopt{-sd}{i}{scan duration} \fileopt{<file.bzz|dir>}{tune source} \sec{description}{DESCRIPTION} \par \buzzz buzzes. It can do so in different styles, at different base frequencies, and at different volumes. See the \secref{options} section for a description of all options. \par The \optref{-l}{\genopt{-l}{loudness}} and \optref{-d}{\genopt{-d}{duration}} options are both mandatory. The last argument given must be a file containing the tune to buzz, or a directory containing such tune files. The tune must be contained in an interval of at most five tones. Non-conforming tunes may damage your soundcard. \sec{options}{OPTIONS} \begin{itemize} \item{\defopt{-f}{f}{frequency}} Frequency in Hertz, can be specified as a positive real number. \item{\defopt{-l}{i}{loudness}} Loudness, which is specified as an integer inbetween 0 and 100. \item{\defopt{-d}{f}{duration}} Duration in hours, can be specified as a positive real. \intermezzo{ The following options are discussed as a group: } \items{ {\defopt{--dragonfly}{dragon style}} {\defopt{--bumblebee}{bumble style}} {\defopt{--disk}{computer style}} {\defopt{--mosquito}{sting style}} } These are unary options specifying the style in which to buzz. \item{\defopt{-style}{str}{buzz style}} \genarg{str} should be one of \v{bumblebee}, \v{dragonfly}, \v{mosquito}, or \v{disk}. \item{\defopt{--scan}{scan mode}} This will buzz 10 seconds for each tune specified. Refer also to the \optref{-sd}{\genopt{-sd} option}. \item{\defopt{-sd}{i}{scan duration}} Sets the scan time in (an integer number of) seconds. This affects the \optref{--scan}{\genopt{--scan} option}. \end{itemize} \sec{files}{FILES} \par /etc/zoem/foriamzoem.bzz contains the zoem jingle.\| /etc/zoem/zoem.ascii-art contains zoem related ascii art. An excerpt is shown below. \verbatim{ .-----------------------------. | | | _ " _ | | (\\"/) (_\\|/_) | | (/|\\) (_/|\\_) | | | | | | () | | | -----% | | () | | ejm| .-----------------------------. } \sec{environment}{ENVIRONMENT} \par Currently, no environmental issues with \buzzz. \sec{diagnostics}{DIAGNOSTICS} \par If the tune spans an interval larger than 5 tones, buzzz will emit little beeps. If the interval exceeds an octave, buzzz will fork and exec \bf{bell}. \sec{bugs}{BUGS} \par Some do. \sec{author}{AUTHOR} \par Bugs Bunny. \sec{history}{HISTORY} \par repeats itself, especially from a buzzing point of view. Refer to \publref{foobar} for an in-depth analysis. A different point of view is presented in \publref{barfoo}. \sec{seealso}{SEE ALSO} \par The \sibref{bell}{bell(1) manual}. \${html}{This reference is not going anywhere; it just demonstrates a way of implementing references to other utilities. Troff can not link anyway, so this warning is strictly html.} \${html}{\par On the www it is difficult to show a manual page as compiled for rendering in a terminal, but one can view a manual page as compiled for rendering by a postscript interpreter. Lo and behold \httpref{buzzz.ps}.} \par \httpref{http://www.google.com/search?hl=en&q=zoem+macro} . \par \publanch{foobar} Bugs Bunny. Foo Bar. A history of making, maintenance, repair, and disposal. \par \publanch{barfoo} Donald Duck. The futile mistake, and how it changes my life every day. \"man::postamble"
4 Feb 2002 buzzz 1.00
1. | ||
2. | ||
3. | ||
4. | ||
5. | ||
6. | ||
7. | ||
8. | ||
9. | ||
10. | ||
11. |
buzzz -l i (loudness) -d f (duration) [-f f (frequency)] [--dragonfly (dragon style)] [--bumblebee (bumble style)] [--disk (computer style)] [-style (some style)] [--scan (scan mode)] [-sd i (scan duration)] <file.bzz|dir> (tune source)
buzzz buzzes. It can do so in different styles, at different base frequencies, and at different volumes. See the OPTIONS section for a description of all options.
The -l loudness and -d duration options are both mandatory. The last argument given must be a file containing the tune to buzz, or a directory containing such tune files. The tune must be contained in an interval of at most five tones. Non-conforming tunes may damage your soundcard.
-f f (frequency) | ||
Frequency in Hertz, can be specified as a positive real number.
|
||
-l i (loudness) | ||
Loudness, which is specified as an integer inbetween 0 and 100.
|
||
-d f (duration) | ||
Duration in hours, can be specified as a positive real.
|
||
The following options are discussed as a group: | ||
--dragonfly (dragon style) | ||
--bumblebee (bumble style) | ||
--disk (computer style) | ||
--mosquito (sting style) | ||
These are unary options specifying the style in which to buzz.
|
||
-style str (buzz style) | ||
str should be one of bumblebee, dragonfly,
mosquito, or disk.
|
||
--scan (scan mode) | ||
This will buzz 10 seconds for each tune specified.
Refer also to the -sd option.
|
||
-sd i (scan duration) | ||
Sets the scan time in (an integer number of) seconds. This affects the
--scan option.
|
/etc/zoem/foriamzoem.bzz contains the zoem jingle.
/etc/zoem/zoem.ascii-art contains zoem related ascii art.
An excerpt is shown below.
.-----------------------------. | | | _ " _ | | (\"/) (_\|/_) | | (/|\) (_/|\_) | | | | | | () | | | -----% | | () | | ejm| .-----------------------------.
Currently, no environmental issues with buzzz.
If the tune spans an interval larger than 5 tones, buzzz will emit little beeps. If the interval exceeds an octave, buzzz will fork and exec bell.
repeats itself, especially from a buzzing point of view. Refer to [1] for an in-depth analysis. A different point of view is presented in [2].
The bell(1) manual. This reference is not going anywhere; it just demonstrates a way of implementing references to other utilities. Troff can not link anyway, so this warning is strictly html.
On the www it is difficult to show a manual page as compiled for rendering in a terminal, but one can view a manual page as compiled for rendering by a postscript interpreter. Lo and behold buzzz.ps.
http://www.google.com/search?hl=en&q=zoem+macro .
[1] Bugs Bunny. Foo Bar. A history of making, maintenance, repair, and disposal.
[2] Donald Duck. The futile mistake, and how it changes my life every day.
A link to the PostScript version of the manual page was provided in the buzzz document itself and here is another one. Note that this PostScript was compiled by groff from the troff output that was compiled by zoem from the zoem input.
mcl.azm |
The source for the manual.
|
|
mcx.zmm |
A resource file used by mcl and its sibling applications.
|
|
mcl.html |
The html generated from the source by zoem.
|
|
mcl.1 |
The troff generated from the source by zoem.
|
|
mcl.ps |
The PostScript generated from mcl.1 by groff.
|
|
mcl.txt |
The text version generated from mcl.1 by groff.
|
|
mclfaq.azm |
The source for the mcl FAQ.
|
|
mclfaq.html |
The html generated by zoem.
|
|
mclfaq.ps |
The PostScript generated by groff from the zoem troff output.
|
For user keys, dollar keys, and dictionary stacks, refer to the Dictionary stacks section and the Macro expansion section. For grape keys, refer to the Tree data section.
For key signatures and key mention, refer to the Key signatures section. For anonymous keys: the Anonymous keys section.
Session variables are described in the Session keys section.
For varargs, arguments in which a variable number of sub-arguments can be stored, and for blocks: the Of blocks and varargs section.
For plain scope, device scope, at scope, and glyph sequences: The Scope dichotomy and Device scope sections.
For file read and inline files: the File read section.
Sometimes zoem protects or unprotects data. Refer to the Protection section.