doctools_lang_intro(3tcl)
β¨ doctools_lang_intro β¨ β the manual page doctools_lang_intro(3tcl)
okay bestie, sit down, hydrate, because this is the informal intro to version 1 of the doctools markup language, and it's taught entirely through a lot of examples π. Read this and you'll be ready to vibe with the two parts of the formal spec: the doctools language syntax specification and the doctools language command reference. no cap. π«Ά
DESCRIPTION
This doc is an informal intro to version 1 of the doctools markup language, and it's built on a whole bunch of examples. After you read it, a writer should be ready to understand the two parts of the formal spec, i.e. the doctools language syntax specification and the doctools language command reference. β¨
FUNDAMENTALS
Broadest terms possible: the doctools markup language is LaTeX-like, not like SGML and friends. A document written in this language is primarily text, with markup commands embedded into it. that's the whole vibe. π
Each markup command is a Tcl command wrapped in a matching pair of [ and ]. Inside those delimiters the usual rules for a Tcl command apply β word quotation, nested commands, continuation lines, etc. like so:
... [list_begin enumerated] ...
... [call [cmd foo] \
[arg bar]] ...
... [term {complex concept}] ...
... [opt "[arg key] [arg value]"] ...
BASIC STRUCTURE
The most simple document you can write in doctools is:
[manpage_begin NAME SECTION VERSION]
[see_also doctools_intro]
[see_also doctools_lang_cmdref]
[see_also doctools_lang_faq]
[see_also doctools_lang_syntax]
[keywords {doctools commands}]
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
[description]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
and this also shows us that all doctools documents split into two parts: the header and the body. Everything before [description] belongs to the header, everything after belongs to the body, and the whole document is bracketed by the two manpage_* commands. Before and after those opening and closing commands we have only whitespace. π
For the rest of this section we're only talking about the contents of the header β the body's structure gets its own section, Text structure.
The header section can be empty. Otherwise it may contain only an arbitrary sequence of the four so-called header commands, plus whitespace. Those commands are:
titledescmoddescrequirecopyright
They give extra info about the document through their arguments β its title, the title of the larger group the document belongs to (if applicable), the requirements of the documented packages (if applicable), and copyright assignments. All of them can occur multiple times, including zero times, and they can be used in any order. BUT π β for titledesc and moddesc only the last occurrence is taken. For the other two, the specified information is accumulated, in the given order. Regular text is not allowed within the header. periodt.
Given all that, a less minimal example of a document is:
[manpage_begin NAME SECTION VERSION]
[copyright {YEAR AUTHOR}]
[titledesc TITLE]
[moddesc MODULE_TITLE]
[require PACKAGE VERSION]
[require PACKAGE]
[description]
[manpage_end]
Remember that whitespace is optional. This document:
[manpage_begin NAME SECTION VERSION]
[copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
[require PACKAGE VERSION][require PACKAGE][description]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
has the exact same meaning as the example before it. slay. π
On the other hand, if whitespace is present it consists not only of any sequence of characters containing the space character, horizontal and vertical tabs, carriage return, and newline β it may contain comment markup as well, in the form of the comment command. π¦
[comment { ... }]
[manpage_begin NAME SECTION VERSION]
[copyright {YEAR AUTHOR}]
[titledesc TITLE]
[moddesc MODULE_TITLE][comment { ... }]
[require PACKAGE VERSION]
[require PACKAGE]
[description]
[manpage_end]
[comment { ... }]
ADVANCED STRUCTURE
In the simple examples of the last section we fudged a bit about the markup actually allowed before the manpage_begin command that opens the document. π
Instead of only whitespace, the two templating commands include and vset are also allowed β so the writer can either set and/or import configuration settings relevant to the document. I.e. it is possible to write:
[include FILE]
[vset VAR VALUE]
[manpage_begin NAME SECTION VERSION]
[description]
[manpage_end]
Even more important: these two commands are allowed anywhere a markup command is allowed, without regard for any other structure. I.e. in the header as well, for example:
[manpage_begin NAME SECTION VERSION]
[include FILE]
[vset VAR VALUE]
[description]
[manpage_end]
The only restriction include has to obey is that the contents of the included file must be valid at the place of the inclusion. I.e. a file included before manpage_begin may contain only the templating commands vset and include; a file included in the header may contain only header commands, etc. π§
TEXT STRUCTURE
The body of the document is mainly text, possibly split into sections, subsections, and paragraphs, with parts marked up to highlight various semantic categories of text, plus additional structure through the use of examples and (nested) lists.
This section explains the high-level structural commands; everything else gets deferred to the following sections. πΈ
The simplest way to structure the body is by introducing paragraphs. The command for that is para. Each occurrence of this command closes the previous paragraph and automatically opens the next. The first paragraph is automatically opened at the beginning of the body, by description. Same deal at the end: the last paragraph automatically ends at manpage_end. β¨
[manpage_begin NAME SECTION VERSION]
[description]
...
[para]
...
[para]
...
[manpage_end]
Empty paragraphs are ignored.
A structure coarser than paragraphs are sections, which let the writer split a document into larger, labeled pieces. The command for that is section. Each occurrence of this command closes the previous section and automatically opens the next, including its first paragraph. The first section is automatically opened at the beginning of the body, by description (this section is labeled "DESCRIPTION"). Same deal: the last section automatically ends at manpage_end.
Empty sections are not ignored. And we're free to (not) use paragraphs within sections. π
[manpage_begin NAME SECTION VERSION]
[description]
...
[section {Section A}]
...
[para]
...
[section {Section B}]
...
[manpage_end]
Between sections and paragraphs we have subsections, to split sections. The command for that is subsection. Each occurrence of this command closes the previous subsection and automatically opens the next, including its first paragraph. A subsection is automatically opened at the beginning of the body, by description, and at the beginning of each section. Same deal again: the last subsection automatically ends at manpage_end.
Empty subsections are not ignored. And we're free to (not) use paragraphs within subsections. π«Ά
[manpage_begin NAME SECTION VERSION]
[description]
...
[section {Section A}]
...
[subsection {Sub 1}]
...
[para]
...
[subsection {Sub 2}]
...
[section {Section B}]
...
[manpage_end]
TEXT MARKUP
Now that we've handled the overall structure a writer can impose on the document, let's take a closer look at the text in a paragraph. π
Most often it's just the unadorned content of the document, but sometimes we want to highlight parts of it as some type of thing or other β command arguments, command names, concepts, uris, etc.
For this we have a series of markup commands that take the text to highlight as their single argument. Note: while their predominant use is highlighting parts of a paragraph, they can also be used to mark up the arguments of list item commands, and of other markup commands. nesting rights, we love to see it. π
The commands available to us are:
argβ Its argument is a the name of a command argument.classβ Its argument is a class name.cmdβ Its argument is a command name (Tcl command).constβ Its argument is a constant.emphβ General, non-semantic emphasis.fileβ Its argument is a filename / path.funβ Its argument is a function name.methodβ Its argument is a method namenamespaceβ Its argument is namespace name.optβ Its argument is some optional syntax element.optionβ Its argument is a command line switch / widget option.packageβ Its argument is a package name.sectrefβ Its argument is the title of a section or subsection, i.e. a section reference.syscmdβ Its argument is a command name (external, system command).termβ Its argument is a concept, or general terminology.typeβ Its argument is a type name.uriβ Its argument is a uniform resource identifier, i.e an external reference. A second argument can be used to specify an explicit label for the reference in question.usageβ The arguments describe the syntax of a Tcl command.varβ Its argument is a variable.widgetβ Its argument is a widget name.
The example demonstrating the use of text markup is an excerpt from the doctools language command reference, with some highlighting added. It shows their use within a block of text, as the arguments of a list item command (call), and our ability to nest them. π₯
...
[call [cmd arg_def] [arg type] [arg name] [opt [arg mode]]]
part 1 done, bestie β but we're not done-done, there's more coming π
- Text structure. List element. Argument list. Automatically closes the previous list element. Specifies the data-
[arg type]of the described argument of a command, its[arg name]and its i/o-[arg mode]. The latter is optional.
β¨ ESCAPES β¨
Okay bestie, so we already showed you the 20 commands for simple markup in the previous section. There are two more that are technically simple markup too π
. But their whole thing isn't marking up phrases as specific types of things β it's inserting characters, specifically [ and ].
These commands, lb and rb respectively, are literally required because our use of [ and ] to bracket markup commands makes it impossible to directly use [ and ] within the text. π¦
Our example of their use is the sources of the last sentence in the previous paragraph, with some highlighting added.
...
These commands, [cmd lb] and [cmd lb] respectively, are required
because our use of [lb] and [rb] to bracket markup commands makes it
impossible to directly use [lb] and [rb] within the text.
...
Not me noticing the source writes [cmd lb] twice up there π β that's exactly how it's written, so we're keeping it exactly as-is, no touchy.
πΈ CROSS-REFERENCES πΈ
The last two commands we have to discuss are for the declaration of cross-references between documents β explicit and implicit. They are keywords and see_also. π
Both take an arbitrary number of arguments, and all of those arguments have to be plain unmarked text. I.e. it is not allowed to use markup on them. Both commands can be used multiple times in a document. If that is done, all arguments of all occurrences of one of them are put together into a single set. (Yes, they merge into one set. Slay.)
keywordsβ the arguments of this command are interpreted as keywords describing the document. A processor can use this information to create an index indirectly linking the containing document to all documents with the same keywords. πsee_alsoβ the arguments of this command are interpreted as references to other documents. A processor can format them as direct links to these documents. π
All the cross-reference commands can occur anywhere in the document between manpage_begin and manpage_end. So the writer gets to choose: does she want them at the beginning of the body, or at its end, maybe near the place a keyword is actually defined by the main content, or does she consider them meta data which should be in the header, etc. Authorial freedom, we love to see it. β¨
Our example shows the sources for the cross-references of this document, with some highlighting added. Incidentally they are found at the end of the body.
...
[see_also doctools_intro]
[see_also doctools_lang_syntax]
[see_also doctools_lang_cmdref]
[keywords markup {semantic markup}]
[keywords {doctools markup} {doctools language}]
[keywords {doctools syntax} {doctools commands}]
[manpage_end]
π EXAMPLES π
Where ever we can write plain text we can write examples too. Iconic. For simple examples we have the command example, which takes a single argument β the text of the argument. The example text must not contain markup.
If we wish to have markup within an example, we have to use the 2-command combination example_begin / example_end instead. π«Ά
The first opens an example block, the other closes it, and in between we can write plain text and use all the regular text markup commands. Note that text structure commands are not allowed. This also means that it is not possible to embed examples and lists within an example. π On the other hand, we can use templating commands within example blocks to read their contents from a file (remember section Advanced structure). π§
The source for the very first example in this document (see section Fundamentals), with some highlighting added, is
[example {
... [list_begin enumerated] ...
}]
Using example_begin / example_end this would look like
[example_begin]
... [list_begin enumerated] ...
[example_end]
π LISTS π
Where ever we can write plain text we can write lists too. The main commands are list_begin to start a list, and list_end to close one. The opening command takes an argument specifying the type of list started, and this in turn determines which of the eight existing list item commands are allowed within the list to start list items. Eight!! π₯
After the opening command only whitespace is allowed, until the first list item command opens the first item of the list. Each item is a regular series of paragraphs and is closed by either the next list item command, or the end of the list. If closed by a list item command, this command automatically opens the next list item. A consequence of a list item being a series of paragraphs is that all regular text markup can be used within a list item, including examples and other lists. π
The list types recognized by list_begin and their associated list item commands are:
argumentsβ (arg_def) This opens an argument (declaration) list. It is a specialized form of a term definition list where the term is an argument name, with its type and i/o-mode.commandsβ (cmd_def) This opens a command (declaration) list. It is a specialized form of a term definition list where the term is a command name.definitionsβ (defandcall) This opens a general term definition list. The terms defined by the list items are specified through the argument(s) of the list item commands, either general terms, possibly with markup (def), or Tcl commands with their syntax (call).enumeratedβ (enum) This opens a general enumerated list.itemizedβ (item) This opens a general itemized list.optionsβ (opt_def) This opens an option (declaration) list. It is a specialized form of a term definition list where the term is an option name, possibly with the option's arguments.tkoptionsβ (tkoption_def) This opens a widget option (declaration) list. It is a specialized form of a term definition list where the term is the name of a configuration option for a widget, with its name and class in the option database.
Our example is the source of the definition list in the previous paragraph, with most of the content in the middle removed.
...
[list_begin definitions]
[def [const arg]]
([cmd arg_def]) This opens an argument (declaration) list. It is a
specialized form of a definition list where the term is an argument
name, with its type and i/o-mode.
[def [const itemized]]
([cmd item])
This opens a general itemized list.
...
[def [const tkoption]]
([cmd tkoption_def]) This opens a widget option (declaration) list. It
is a specialized form of a definition list where the term is the name
of a configuration option for a widget, with its name and class in the
option database.
[list_end]
...
Note that a list cannot begin in one (sub)section and end in another. Differently said, (sub)section breaks are not allowed within lists and list items. π
An example of this illegal construct is
...
[list_begin itemized]
[item]
...
[section {ILLEGAL WITHIN THE LIST}]
...
[list_end]
...
π FURTHER READING π
Now that this document has been digested, the reader β assumed to be a writer of documentation β should be fortified enough to be able to understand the formal doctools language syntax specification as well. π«Ά
From here on out the doctools language command reference will also serve as the detailed specification and cheat sheet for all available commands and their syntax. (Cheat sheet era. We're obsessed.) π
To be able to validate a document while writing it, it is also recommended to familiarize oneself with one of the applications for the processing and conversion of doctools documents, i.e. either Tcllib's easy and simple dtplite, or Tclapps' ultra-configurable dtp. β¨
π BUGS, IDEAS, FEEDBACK π
This document, and the package it describes, will undoubtedly contain bugs and other problems. Please report such in the category doctools of the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please also report any ideas for enhancements you may have for either package and/or documentation. π
When proposing code changes, please provide unified diffs, i.e the output of diff -u.
Note further that attachments are strongly preferred over inlined patches. Attachments can be made by going to the Edit form of the ticket immediately after its creation, and then using the left-most button in the secondary navigation bar. π
π SEE ALSO π
doctools_intro, doctools_lang_cmdref, doctools_lang_faq, doctools_lang_syntax
β KEYWORDS β
doctools commands, doctools language, doctools markup, doctools syntax, markup, semantic markup
π CATEGORY π
Documentation tools
π COPYRIGHT π
Copyright (c) 2007 Andreas Kupries <andreas_kupries@users.sourceforge.net>
And that's a wrap bestie!! π This whole page lives in tcllib, version 1.0, under the name doctools_lang_intro(3tcl), and it's dated right there in that footer line at the bottom of the original. Go forth and mark up your docs, you main character. π
πΈ
π¦ where this page comes from
- debian bookworm: tcllib 1.21+dfsg-1 Β· BSD
- debian trixie: tcllib 2.0+dfsg-4 Β· Tcl
- ubuntu jammy: tcllib 1.20+dfsg-1 Β· BSD
- ubuntu noble: tcllib 1.21+dfsg-1 Β· BSD
- ubuntu questing: tcllib 2.0+dfsg-4
- ubuntu resolute: tcllib 2.0+dfsg-5 Β· Tcl
- ubuntu stonking: tcllib 2.0+dfsg-6 Β· Tcl
- Copyright (c) 2007 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms