.so k.tmac .so kx.tmac .so ../toc/toc.tmac .mediasize letter .fp 0 M DejaVuSansMono ttf .hw Eng-lish . .\" configure table of contents .eo .de he . bp . nr a +1 . h \X'PDFMark: Bookmark 0 \\$*'\A'\na' . br . sp -1 \$* . te .the \\\T'\na'\$*\t\n%\\T .. . .de se . nr a +1 . s \X'PDFMark: Bookmark 1 \\$*'\A'\na' . br . sp -1 \$* . if '\$1 \$2 \$3'How do I' \{\ . nr hdi +1 . if \n[hdi]>1 \{\ . shift 3 . te .the \\\T'\na'\\h'36p'"\\h'20.4p'\$*\t\n%\\T . return . \} . \} . te .the \\\T'\na'\\h'18p'\$*\t\n%\\T .. . .ec . .\" configure header and footer .eo .de @h . sp |36p . if \n%>1 .tl ''-%-'' . sp |1i .. . .de @f . sp |\n(.pu-48p . tl ''\*(#e'' .. .ec . .\" configure environments .@e l . ft M . vs +1p .@e . .\" start document .t .z Mk , a simple macro package for troff .d John Ankarström .d e . .s .ce .i "TABLE OF CONTENTS" .sp 4p .@e \X'SetLinkBorder: 0 0 0'\c .to .sp 0.5i .ns . .he Introduction .p .i Mk is a simple macro package for troff with the following features: .n 1 It is designed to be easy to understand and to customize by editing the source code. .n It makes use of the extended support for environments offered by modern troff implementations. .n It is practically easy to use. Macros consist of a single lowercase letter. .p While .i mk does provide macros for many common tasks, including footnotes, it is at the end of the day an idiosyncratic macro package, written to serve the author's personal needs. Users of .i mk are encouraged to .n 1 a ) modify the source code according to their own needs, as well as .n use built-in troff requests for some things that other packages might provide custom macros for. .p All in all, .i mk aspires to abstract as little as possible from the underlying troff requests and registers. In its author's humble opinion, it is the ideal macro package for learning troff. .p In this document, the fundamental concepts of .i mk are explained. The document itself also serves as a demonstration of .i mk . With a couple of exceptions, it uses .i mk 's default settings. The reader is encouraged to inspect the document's source code in order to see how the macro package is used in practice. .p And yes, that table of contents is automatically generated! See p. \n[&toc] for more information. . . .he Environments .te .nr &env \n% .p .i Mk makes heavy use of named environments, supported by implementations such as GNU troff, Heirloom troff and Neatroff. Environments obviate the need for many special registers that a macro package (and its user) would otherwise need to keep track of. For example, .i ms keeps track of the document's font size in the .c PS register. For the font size of headings, it has yet another register. .i mk has no such registers. If the user wishes to modify the default font size, he or she can simply switch to the relevant environment and set the font size as desired using regular troff requests: .(l .\" set heading font .h .fam H .ps +1p .)l .p Troff saves the font settings in the environment, so that the next time the environment is invoked, the desired font family and point size are automatically restored. .p The environments are initialized as soon as the first ." block-level macro is called. At the initialization of each environment, the default environment (0) is copied, meaning that all environment-relevant settings defined before the first macro call are applied to all .i mk environments. It is thus remarkably simple and intuitive to set, for example, the default font of a document: .(l .fam N .t Document title .p First paragraph. .)l .p In addition to the normal environment-relevant settings, .i mk manually associates a few special registers with the current environment: .n 1 .c sp , the amount of vertical space to add before an environment .n .c sq , the amount of vertical space to add before a different type of environment .n .c ti , the indentation of the first line in some environments (currently only .c p ) .p These can be set inside a given environment to control its behavior when invoked. The only exceptions are the margin and footnote environments .c @m , ( .c @f ), which are treated specially and do not support these registers. . . .he External macros .p .i Mk defines a number of macros. Some of them are used internally by .i mk itself; these carry an at .c @ ) ( prefix and are going to be explored later. For now, we will focus on the external macros provided by .i mk . . .se Inline macros .p There are a group of macros that provide convenient inline formatting. All take three arguments: the text to be formatted, the text to be placed immediately after and the text to be placed immediately before. The inline macros are the following: .n 1 .c \(dq , quotation (like ." this ) .n .c b , bold font .n .c c , constant-width font .n .c i , italic font .n .c z , bold italic font .p For example, the following request outputs .i mk .\(rq: \(lq .(l .i mk . .)l . .p Note that .c c uses the font family and point size set in the .c l environment (see below). .se Block-level macros .p There is a large group of macros that provide block-level formatting: .n 1 .c d , centered date or text .n .c h , heading .n .c l , literal display (for source code) .n .c p , paragraph .n .c q , indented quotation .n .c s , subheading .n .c t , centered title .p The .c t and .c d macros can be used at the beginning of a document to create a centered header: .(l .t Document title .d First author .br Second author .d i \" current date formatted as YYYY-MM-DD .)l .p In the example above, you can see that the .c d macro may be used for other things than just dates. This works because .c d displays the date only if given an argument describing the desired date format: .n 1 a ) .c i : international date, like ." 2021-06-21 .n .c e : English date, like ." "21 June 2021" .p The formatted dates are defined in strings prefixed with a hash symbol .c # ): ( .c #i and .c #e are provided by default, but more may be added by the user. . .se Other macros .p Finally, there are a few macros that belong to neither category: .n 1 .ne 2 .c ( , begin footnote .n .c ) , end footnote .n .c w , want space .p The macros .c ( and .c ) create footnotes, placing a numerical reference at the place of their invocation. Both .c ( and .c ) take an optional argument, which is output either immediately before or immediately after the inline reference. For example, the code .(l .q This is a quotation\c .( \!.ne 1 This is a footnote. .) .)l .p generates the following output: .q This is a quotation\c .( This is a footnote. .) . .p If .c ( and .c ) are called at such a position that the collected footnotes cannot fit on the current page, .i mk will print the footnotes on the next page instead. .p The .c w macro is an alternative to troff's .c ne request, which ensures that a given amount of space is available on the page \(en otherwise, a line break is issued \(en but unlike .c ne , which takes an exact amount of space as its argument, .c w takes a declarative specification describing the amount of desired space in terms of .i mk environments. For example: .(l .\" want space for... .w s p \" a subheading of one line + a paragraph of one line .w s pp \" a subheading of one line + a paragraph of two lines .w ss p \" a subheading of two lines + a paragraph of one line .)l . . .he Internal macros .p .i Mk 's internal macros are generally not meant to be used outside of .i k.tmac . Documented in this section are the exceptions to this rule. For examples of how these macros are used in practice, see the FAQ section on page \n[&faq]. . .se Page header and footer .p The .c @h , .c @f , .c @th and .c @tf macros control the page header and footer. .p At document initialization, .i mk automatically creates traps for .c @th and .c @tf . When sprung, .c @th and .c @tf call .c @h and .c @t , which control the text and spacing of the header and footer. .p .i Mk will avoid creating a trap for .c @tf if any trap has already been set before document initialization. This means that users can override the position of the .c @tf trap by setting it themselves. Likewise, users can redefine .c @h and .c @f to change the content of the header and footer. . .se Environments .p The environment-related macros .c (e , .c @e and .c @c may be used in advanced documents to define custom environments. .p At the present, .c (e is nothing more than a wrapper around troff's built-in .c ev , but it may eventually be redefined in order to offer compatibility with troff implementations without support for named environments. .p .c @e and .c @c are equivalent to troff's .c ev and .c evc , but perform some extra work to keep track of .i mk 's special environment variables (see .i Environments , p. \n[&env]). . . .he Frequently anticipated questions .te .nr &faq \n% . .se How do I customize the default appearance of a document? .p All environment settings, like point size, font family and indentation\c .( For a complete list of settings that are associated with the environment, see 5.26\~\c .i Environments in the full GNU troff manual .nh .c "info 'groff\:.info)Environments'" ). ( .hy .) , are configured with the standard troff requests. If you set the point size at the beginning of the document, before any .i mk macros have been called, it will be correctly set for the entire document. This works because .i mk 's environments initially copy all their settings from 0, the default environment. .p For example, if you wanted to write a document with the New Century Schoolbook font at 9 points and a vertical spacing of 12 points, you would start the document like this (before you call any .i mk macros): .(l .fam N .ps 9p .vs 12p .)l . .se How do I customize the default appearance of a given environment? .p To configure the layout and font settings of a specific environment, you can switch to that environment and use the relevant troff requests: .(l \!.ne 1 .q .ps +1p .)l .p If you are merely configuring the environment without printing anything in it, you can also use .c @e : .(l .@e q .ps +1p .)l . .w s ll .se How do I customize the default appearance of the margin text? .(l .(e @m \" margin environment .ps +1p .)l .p You can also set such settings in your redefinition of .c @h or .c @f . . .w s ll .se How do I customize the default appearance of footnotes? .(l .(e @f \" footnote environment .ps +1p .)l . .w s ll .se How do I redefine the page header? .(l .de @h . \" set position of header text . sp |36p . \" set header text . tl 'left'center'right' . \" set position of page text \!.ne 1 . sp |1i .. .)l . .w s ll .se How do I redefine the page footer? .p To change the position of the footer: .(l .\" set position of footer trap .\" (must be done before any macros have been called) .wh -1i @tf . .)l .p To change the contents of the footer: .(l .de @f . \" set position of footer text . \" (must be below the footer trap) . sp |\\n(.pu-48p . \" set footer text . tl 'left'center'right' .. .)l . .se How do I define my own environments? .p Environments are a feature built into troff, accessed via the .c ev request, but because .i mk extends environments with additional functionality, it provides special macros to be used instead of .c ev : .n 1 .c (e , set environment (same as .c ev ) .n .c @e , set extended environment .n .c @c , copy environment (same as .c evc ) .p The .c @e macro can be used to activate any environment that supports .i mk 's extensions (see .i Environments , p. \n[&env]). The following code configures an environment called .c n and defines a corresponding macro: .(l .@e n . @c 0 \" copy default environment . ps -1p .@e . .de n . br \" finish current environment \!.ne 1 . @e n \" activate new environment .. .)l . .se How do I prevent a section from being broken up by a page break? .p Some macro packages have a concept of ." keeps , sections that are kept together across page breaks. .i Mk does not (at least yet) define any such macros by default. The simplest solution is to use troff's .c ne request: .(l .ne 7 \" break page if seven lines won't fit on this page .\" ... some text ... .)l .p If you want to keep text of various styles together, you can use .i mk 's own .c w macro: .(l .w s qq \" break page if a subheading and two lines of a quotation won't fit .\" ... some text ... .)l .ig .p For a more general solution, you can use a diversion: .(l .di keep .\" ... some text ... .br .di .ne \n(dnu .keep .)l .. . .se How do I use alternative quotation marks? .p Redefine .c \(dq . The following code defines a Swedish quotation style: .(l .de " \\&\\$3”\\$1”\\$2 .. .)l .p Another option is to create new macros for alternative quotation styles: .(l .\" alternative swedish quotation styles .de >< \\&\\$3»\\$1«\\$2 .. .de >> \\&\\$3»\\$1»\\$2 .. .)l . .se How do I create nested inline quotations? .p Just use the backtick .c \(ga ) ( and apostrophe .c \(aq ) ( directly in the argument to .c \(dq . .p If you need to change the quotation style, for example when converting a document from US to British English, you can redefine .c " to translate backticks and apostrophes accordingly: .(l .eo .de " . char ` \(lq . char ' \(rq \&\$3\(oq\$1\(cq\$2 . char ` \(oq . char ' \(cq .. .ec .)l . .se How do I include a table of contents in my document? .te .nr &toc \n% .p Included with the .i mk distribution is a package called .i toc , which includes the following files: .n 1 .i toc.tmac , which provides the .c te and .c to macros .n .i toc , a script that invokes troff in three passes in order to allow a table of contents to be generated .p Use .c te to register a line to be inserted into the table of contents. Use .c to to insert the lines registered by .c te into the document. Note that the argument given to .c te will be interpreted as a troff input line. .p The following definitions provide a good starting point: .(l .eo .de he . h \$* . tm .the \$*\t\n% .. .de the . ta 0 \n(.luR . tc . \$* . tc . br .. .ec .)l .p Now, instead of .c h , you may use .c he to create a heading to be included in the table of contents: .(l .he A heading .)l .p Wherever you want the table of contents to be inserted, you may simply invoke .c to . .p Just remember to use .c toc to run your processing pipeline: .(l example.ps .)l .p Thanks to the multiple passes performed by .i toc , .c to can be invoked at any place in the document, including the beginning. .p The macro definition listed above is included in .i ux.tmac . . .se How do I create a reference to a later page? .p Use the macros provided by .i toc.tmac in combination with the .i toc program. Near the beginning of your document, invoke .c to . Then, at each position you want to reference, invoke .c .te like this: .(l .te .nr &refname \n% .)l .p To refer to that position, interpolate the register: .(l See page \n[&refname]. .)l .p (I prefer prefixing my references with an ampersand.) . .se How do I include source code without needing to escape it? .p The .i mk distribution includes a troff preprocessor called .i list , which filters text delimited by .c .(l and .c .)l , escaping standard troff syntax. .p To automatically add a .c .l request before each listing, set the .i -p (prefix) flag accordingly: .(l list -p.l .)l .p To transparently pass an input line to troff, prefix it with .c \\\\! . (The .i -E flag disables this behavior.)