Ruff! (v3.0.4)

::ruffTop, Main, Index

UsageTop, Main, Index

Usage from a scriptTop, Main, Index

To document a package or packages, first load them into a Tcl interpreter. Then load ruff and invoke the document command to document classes and commands within one or more namespaces. Alternatively, invoke the coverage command to identify missing components in the documentation.

For example, the following command will document the NS namespace using the built-in HTML formatter.

package require ruff
::ruff::document ::NS

The output will be written to NS.html. The document command takes a number of options which control what is documented, output formats, layouts etc.

For example, the following will document the namespace NS, NS2 and their children, splitting the output across multiple pages.

::ruff::document {::NS ::NS2} -outdir /path/to/docdir -recurse true -pagesplit namespace

To identify components with missing documentation,

::ruff::coverage {::NS ::NS2}

Usage from the command lineTop, Main, Index

The command line interface has changed in 3.0.

Documentation can also be generated from the command line by invoking the ruff.tcl script. The help command or --help option will display usage information.

Usage: tclsh.exe ruff.tcl command [OPTION...] NAMESPACE ...
Copyright (c) 2009-2026, Ashok P. Nadkarni
All rights reserved.
See the file LICENSE in the source root directory for license.

Argument "command" must be one of "document", "coverage" or "help".

Mandatory arguments to long options are mandatory for short options too.
      --compact                Generate compact form of documentation if
                               supported by formatter. For the coverage command
                               this will only emit program elements that have
                               missing documentation.
      --copyright=TEXT         Include TEXT as the copyright. Not all formatters
                               may support this option.
      --diagrammer=ARGS        Arguments to pass to the diagram processor if
                               none specified in the diagram block header.
                               Defaults to "kroci ditaa"
      --exclude-classes=REGEX  Exclude any classes with names matching
                               regular expression REGEX. This option may be
                               specified multiple times.
      --exclude-procs=REGEX    Exclude any procedures with names matching
                               regular expression REGEX. This option may be
                               specified multiple times.
  -f, --format=FORMAT          Generate documentation in the format given by
                               FORMAT. Defaults to only html.
      --hide-namespace=NS      Omit namespace qualifiers in class and
                               procedure names in namespace NS.
      --include=TYPES          Type of program elements to include in the
                               documentation. TYPES must be a list containing
                               one or both of "classes" and "procs". Only
                               program elements of the included types will
                               be output and in that order. Defaults to
                               "procs classes".
      --link-assets            Link CSS and Javascript assets instead of
                               embedding even when generating single-page
                               output.
  -s, --split=SPLIT            Generate single-page (SPLIT="none") or
                               multi-page output (SPLIT="namespace").
      --locale=LOCALE          Sets the locale for pre-defined texts.
      --noindex                Do not generate an index page.
      --html-navigation=NAV    Controls behavior of the navigation pane for
                               the HTML formatter. NAV may be "sticky" or
                               "scrolled".
      --only-exports           Only document procedures that are exported
                               from the namespace.
  -d, --directory=PATH         Write output files to directory PATH.
  -o, --output=FILENAME        Specifies the name of the output file. If the
                               output is to multiple files, this is the name
                               of the documentation main page. Other files
                               will named accordingly by appending the
                               namespace. Defaults to a name constructed from
                               the first namespace specified. FILENAME must
                               not include a path.
  -e, --preeval=SCRIPT         Evaluate SCRIPT before generating
                               documentation. Generally used to load packages
                               being documented. May be specified multiple
                               times. If SCRIPT has the form "@PATH", the
                               script is read from the file PATH.
  -p, --preamble=TEXT          Any text that should be appear as a preamble
                               outside of any namespace documentation, for
                               example an introduction or overview of a
                               package. This shows up as the Start page
                               content when used with the --split namespace
                               option. If TEXT has the form "@PATH", the
                               preamble is read from the file PATH.
      --product=PRODUCT        The short name of the product. Defaults to the
                               first namespace passed. This should be a short
                               name and is used by formatters to identify the
                               documentation set as a whole when documenting
                               multiple namespaces.
      --punctuate              Capitalize and add periods as necessary.
  -r, --recurse                Recurse passed namespaces.
      --nroff-section=SECTION  The manpage section to be used by the Nroff
                               formatter. Defaults to 3tcl.
      --sort-namespaces        Sort the namespaces in the navigation. By
                               default, they are shown in the order they
                               appear in the argument list.
  -t, --title=TITLE            This text is shown in a formatter-specific
                               area on every generated page. The `nroff`
                               formatter for manpages has only a limited
                               space to display this so `TITLE` should be
                               limited to roughly 50 characters if that
                               formatter is to be used. If unspecified, it is
                               constructed from the --product option.
  -v, --version=VER            The version of the package being documented.
      --with-private-methods   Include private methods in generated
                               documentation.
      --with-source            Include procedure and method source code in
                               generated documentation.
      --help                   display this help and exit

The following invocation is equivalent to the earlier example (assuming the mypac package implements the NS and NS2 namespaces).

tclsh /path/to/ruff.tcl document -r -e "package require mypac" -d /path/to/docdir -s namespace ::NS ::NS2

Similarly, to list all program elements and identify missing documentation,

tclsh /path/to/ruff.tcl coverage -r -e "package require mypac" ::NS ::NS2

To only list program elements with missing documentation,

tclsh /path/to/ruff.tcl coverage --compact -r -e "package require mypac" ::NS ::NS2

Documenting proceduresTop, Main, Index

Ruff! generates documentation using Tcl's runtime system to gather proc and class definitions. Comments in procedure and method bodies are further parsed to extract the documentation.

The structure Ruff! expects is described below. In practice, the structure is simple and intuitive though the description may be a bit long winded. You can simply look at the documentation of the sample namespace instead, and click on the Show source links for each procedure or method there to see the formatting.

An example procedure may look as follows:

proc ruff::sample::character_at {text {pos 0}} {
    # Get the character from a string.
    #  text - Text string.
    #  pos  - Character position. 
    # The command will treat negative values of $pos as offset from
    # the end of the string.
    #
    # Returns the character at index $pos in string $text.
    set n [string length $text]
    if {[tcl::mathfunc::abs $pos] >= [string length $text]} {
        #ruff
        # An error exception is raised if $pos is not within bounds.
        error "Index $pos out of bounds."
    }
    if {$pos < 0} {
        return [string index $text end$pos]
    } else {
        return [string index $text $pos]
    }
}

You can see the generated documentation for the above at sample::character_at.

The first block of comments within a procedure before the first line of code are always processed by Ruff!. Note preceding blank lines are OK. We will refer to this block as the lead comment block. It is terminated by either a line of code or a blank line.

Any comments appearing after the first line of code are not processed by Ruff! unless immediately preceded by a line beginning with #ruff which indicates the start of another Ruff! comment block.

The lead comment block begins with a summary that will be used anywhere the document output inserts a procedure summary, for example, a tooltip. The summary is terminated with a blank comment or by the parameter block.

The parameter block is a definition list (see below) and follows its syntactic structure. It only differs from definition lists in that it must directly follow the summary line and receives special treatment in that the default value, if any for the argument, is automatically inserted by Ruff!. Options and switches may also be documented here. The parameter block is terminated in the same fashion as definition blocks.

Any blocks following the parameter block, whether part of the lead block or appearing in a subsequent comment block marked with a leading #ruff, are processed as follows.

TablesTop, Main, Index

Ruff supports basic Markdown-formatted tables with a header and configurable horizontal alignment. Each row of the table must be appear on a single line. All rows should have the same number of cells. The following is an example of a table with each column aligned differently.

|Left Aligned|Center Aligned|Right Aligned|Unaligned|
|:-|:-:|-:|--|
|Cell 0,0|Cell 0,1|Cell 0,2|Cell 0,3
|Cell 1,0|Cell 1,1|Cell 1,2|Cell 1,3

This is displayed as

Left AlignedCenter AlignedRight AlignedUnaligned
Cell 0,0Cell 0,1Cell 0,2Cell 0,3
Cell 1,0Cell 1,1Cell 1,2Cell 1,3

The header and separator may be omitted. For example,

|Cell 0,0|Cell 0,1|Cell 0,2|
|Cell 1,0|Cell 1,1|Cell 1,2|

is displayed as

Cell 0,0Cell 0,1Cell 0,2
Cell 1,0Cell 1,1Cell 1,2

Note however, that if the Markdown formatter is used and its output is passed to another Markdown processor, the latter may not support tables without headers.

In the case of the nroff output, the tbl program needs to be used to format the table. On many systems, man and nroff will automatically invoke it if necessary.

Not all formatters support alignment of columns.

Differences from MarkdownTop, Main, Index

Note that the block level parsing is similar but not identical to Markdown. Amongst other differences, Ruff! has

Ruff! adds

As a general rule, inline formatting should be kept basic and avoid complexities like nested constructs as formatters vary in their capabilities. Embedded HTML is also strongly discouraged as most formatters will not process it.

Documenting classesTop, Main, Index

Class documentation includes methods, classmethods, properties, superclasses and mixins for all selected classes. Classes created from user-defined metaclasses are also included.

The format for method documentation is as described above for procedures. If a property has specialized setter and getter methods, their documentation is extracted in the same fashion except that only paragraph text is considered and other elements like definition lists or diagrams are ignored.

Information about superclasses and mixins is automatically collected and need not be explicitly provided.

Note that unlike for procedures and methods, Tcl does not provide a means to retrieve the body of the class so that comments can be extracted from them. Thus to document information about the class as a whole, you can either include it in the comments for the constructor, which is often a reasonable place for such information, or define a classmethod called _ruffClassHook. The method should return a dictionary with the following keys, all optional.

optionsThis will be placed right after the class method summary section.
preambleThis will be placed right after the class name heading.
propertydescriptionsThe content is added to the description of properties defined for the class.

The value for options and preamble is a docstring as described in Documenting namespaces and may contain any elements there except for headings. See the sample::Base class for an example.

The value for propertydescriptions should be a nested dictionary keyed by the property name and the inner value being a docstring. Inlike markup is permitted but not block constructs like tables and multiple paragraphs will be coalesced. The content will be shown in the second column of the property description table. See the sample::ConfigurableClass class for an example.

The _ruffClassHook method must be a class method and is therefore only available with Tcl 9.

Documenting namespacesTop, Main, Index

In addition to procedures and classes within a namespace, there may be a need to document general information such as the sections you are currently reading. For this purpose, Ruff! looks for a variable _ruff_preamble within each namespace. The indentation of the first line of section content is stripped off from all subsequent lines before processing (This impacts what constitutes a preformatted line). The result is then processed in the same manner as procedure or method bodies except for the following differences:

The documentation generated from the _ruff_preamble content is placed before the documentation of the commands in classes for that namespace.

Note: Older versions supported the _ruffdoc variable. Though this will still work, it is deprecated.

Content that should lie outside of any namespace can be passed through the -preamble option to document. When generating single page output, this is included at the top of the documentation. When generating multipage output this forms the content of the main documentation page.

Per-namespace optionsTop, Main, Index

A namespace can override certain global options passed to the document command by storing a dictionary defining one or more options in a variable _ruff_ns_opts in the namespace. For example,

namespace eval ns {
    variable _ruff_ns_opts {
        -onlyexports true
        -excludeprocs private.*
        -heading {Heading to be used for the namespace}
    }
}

will override the -onlyexports and -excludeprocs passed to the document command.

The options that can be overridden by a namespace are -excludeclasses, -excludeprocs, -includeimports, -includeprivate and -onlyexports. See document for their semantics.

Additionally, the option -heading can be specified to override the heading used for the namespace, which defaults to its name.

Inline formattingTop, Main, Index

Once documentation blocks are parsed as above, their content is subject to inline formatting rules using Markdown syntax with some minor extensions. Markdown compatibility is only for inline elements noted below.

`Text surrounded by backquotes is formatted as inline code.
*Text surrounded by single asterisks is emphasized.
**Text surrounded by double asterisks is bolded.
***Text surrounded by triple asterisks is bold emphasized.
[]Text surrounded by square brackets is treated as a link (more below).
<>Text in angle brackets are treated as HTML tags and auto-links as in Markdown.
$Words beginning with $ are treated as variable names and shown as inline code similar to backquotes (non-standard Markdown).

The default HTML formatter supports other Markdown inline elements but other formatters might not.

Text enclosed in [] is checked whether it references a section heading or a program element name (namespaces, classes, methods, procedures). If so, it is replaced by a link to the section or documentation of that element. If the text is not a fully qualified name, it is treated relative to the namespace or class within whose documentation the link appears. If it is fully qualified, it is displayed relative to the namespace of the link location. For example,

Alternatively, text different from the section heading or symbol can be shown by putting it in another [] pair immediately bfore the symbol or heading reference. For example, [here][document] will show as here and link to document as before. Note: unlike Markdown, there must be no whitespace between the two pairs of [] else it will be treated as two separate symbol references. This is intentional.

If the text does not match a section heading or program element name, it is treated as a normal Markdown reference but a warning is emitted.

Fenced blocksTop, Main, Index

A line containing 3 or more consecutive backquote (`) characters with only leading whitespace starts a fenced block. The block is terminated by the same sequence of backquotes. By default, formatters will pass all intervening lines through verbatim to the output.

However, the leading line of a fenced block can contain additional options for specialized processing. The general form of a fenced block is

```?language? ?option value...? ?transform arg...?
some text
lines
```

The language token is optional and specifies the programming language for the preformatted lines. If present, it must immediately follow the backquote without intervening whitespace. Some formatters make use of the language to colorize the output.

The supported options are

-align ALIGNMENTAligns the output as per ALIGNMENT which may be specified as left, right or center.
-caption CAPTIONAdds a caption below the output.

In addition, a transform can be specified which transforms the input lines into some other form as opposed to outputting them without modification. The only transform currently implemented is diagram and is described in Embedding diagrams.

Formatters that do not support the language, options or the transforms will silently ignore them and do the default processing on the block.

The fenced block below illustrates use of the options.

``` -align center -caption "An example"
This is a
center-aligned
fenced block
with a caption
```

This produces

This is a
center-aligned
fenced block
with a caption
Figure 1. An example

The -caption option is optional. If specified, it is shown below the output and can be linked to using the value of the option. For example [An example] will link as Figure 1. An example.

Embedding diagramsTop, Main, Index

Diagrams can be embedded in multiple textual description formats by specifying the diagram transform on fenced blocks. The following marks the content as a ditaa textual description.

``` diagram
+------------+   Ruff!   +---------------+
| Tcl script |---------->| HTML document |
+------------+           +---------------+
```

The above will produce

The general format of the diagram transform is

?fence options? diagram ?GENERATOR ARG ...?

where GENERATOR is the diagram generator to use and is followed by generator-specific arguments. Currently Ruff! supports kroki and ditaa generators.

If GENERATOR is not specified, as above, it defaults to kroki ditaa. This default can be changed with the -diagrammer option to the document command.

Formatter supportTop, Main, Index

Not all output formats support embedded diagrams. In such cases the fenced block is output as standard preformatted text. For this reason, it is best to use an ascii diagram format like ditaa so flowcharts etc. are still readable when displayed in their original text format. You can use tools like asciiflow for construction of ascii format diagrams.

Diagrams with krokiTop, Main, Index

The kroki generator is based on the online diagram converter at https://kroki.io which can convert multiple input formats. For example, the block below in graphviz format

``` diagram kroki graphviz
digraph {
    "Tcl package" -> "HTML document" [label=" Ruff!"]
}
```

will produce

The single argument following diagram kroki specifies the input format for the block and may be any format supported by kroki.

Use of kroki requires a network connection and any one of the following

Ruff! will try each of the above in turn and use the first that is available.

Diagrams with ditaaTop, Main, Index

The ditaa generator produces images from ASCII text diagrams. Although the kroki generator also supports this format (using ditaa on the server side), the ditaa generator has the advantage of not requiring network access and allowing for more control over image generation. Conversely, it needs the ditaa Java application to be locally installed.

Ruff! expects that the generator can be invoked by exec'ing ditaa. On most Linux programs this can be installed through the system package manager. On Windows ditaa needs to be downloaded from its repository as a jar file to a directory included in the PATH environment variable. Then create a batch file containing the following in that same directory.

@echo off
java -jar %~dp0\ditaa-0.11.0-standalone.jar %*

You will need Java also installed and available through PATH.

Similarly, on Unix and MacOS, a shell script needs to be placed in the path with equivalent content.

A ditaa block is similar to kroki block except it does not need a generator argument as input format is always the same. Additional arguments specified are passed to the ditaa executable. For example,

``` diagram ditaa --round-corners --scale 0.8 --no-shadows
+------------+   Ruff!   +---------------+
| Tcl script |---------->| HTML document |
+------------+           +---------------+
```

The above will produce

Notice the options to control the generated image, something Ruff! cannot do with kroki.

Only the following options or their short form equivalent should be used with ditaa : --no-antialias, --no-separation, --round-corners, --scale, and --fixed-slope. The --background and --transparent options may be specified but may not play well with all Ruff! themes. See the ditaa documentation for the meaning of these options.

Diagram optionsTop, Main, Index

The options allowed for fenced blocks may be used with diagram.

Below is a captioned and centered version of the previous example.

``` -align center -caption "Centered diagram with caption" diagram ditaa --scale 0.8
+------------+   Ruff!   +---------------+
| Tcl script |---------->| HTML document |
+------------+           +---------------+
```

The result is shown in Figure 2. Centered diagram with caption.

Figure 2. Centered diagram with caption

Note that not all formatters support these options. Those not understood by the formatter will be silently ignored.

Ruff! directivesTop, Main, Index

Ruff! directives allow finer control of how content is processed. Directives have the prefix #ruff. There are currently two directives defined -- #ruff and #ruffopt.

The #ruff directiveTop, Main, Index

The #ruff directive may only be used in procedure and method bodies and not in documentation strings processed through namespace _ruff_preamble variables. It is used to mark comments within a procedure or method body that should be processed as Ruff! content even though they do not appear in the initial comment section at the top of the body. The rest of the line after the #ruff directive and subsequent contiguous comment lines are considered documentation lines. Note that this means that #ruff on a line by itself (possibly with trailing whitespace) is a blank line and terminates the previous documentation block with succeeding lines comprising a new block. On the other hand, if #ruff is followed by additional text on the same line, it will continue the previous documentation block as there will be no blank line separator.

The #ruff directive is useful for documenting options and features adjacent to their implementation as opposed to at the top of the procedure body.

The #ruffopt directiveTop, Main, Index

The #ruffopt directive may be used within procedure bodies as well as _ruff_preamble documentation strings. It is used to for settings that control certain aspects of content processing and has the general form

#ruffopt ?SETTING ?VALUE?...?

The only setting currently supported are includedformats and excludedformats. Their use is described in Conditional inclusion.

Conditional inclusionTop, Main, Index

Ruff! lets you conditionally include or exclude content based on the formatter in use. This is accomplished through the includedformats and excludedformats settings passed to the #ruffopt content directive using the following syntax.

#ruffopt includedformats LISTOFFORMATS
#ruffopt excludedformats LISTOFFORMATS

For example, to only enable content for HTML

#ruffopt includedformats html

Or, to exclude HTML and Markdown

#ruffopt excludedformats {html markdown}

Directives are effective until the end of the documentation string or procedure body. To only have conditional inclusion to have effect for a fragment, you need to reset to default formatters by excluding none as in the following example.

#ruffopt includedformats html
<div style="ruff_bd"> <table class="ruff_deflist"> <tbody>
<tr><th>Column1</th><th>Column2</th><th>Column3</th><th>Column4</th><th>Column5</th></tr>
<tr><td>1</td><td>element1</td><td>element2</td><td>element3</td><td>element4</td></tr>
<tr><td>2</td><td>element5</td><td>element6</td><td>element7</td><td>element8</td></tr>
</tbody> </table> </div>
#ruffopt excludedformats {}

Column1Column2Column3Column4Column5
1element1element2element3element4
2element5element6element7element8

The generated content for the fragment above will only show in the HTML output. However, succeeding content will be included for all formatters.

For an example of using in documenting procedures as opposed to documentation strings as above, see sample::proc_with_conditional_content in the sample code.

OutputTop, Main, Index

Ruff! is designed to support multiple output formats through pluggable formatters. The command formatters returns a list of supported formatters.

In addition, the output may be produced in single or multipage format.

Multipage outputTop, Main, Index

The generated documentation may be either in a single output file or spread across multiple files. This is controlled by the -pagesplit option to the document command. Some formatters may not support this feature.

When generating multipage output, the toplevel generated page contains links to the other pages which contain per-namespace documentation. The preamble (passed as the -preamble option to the document command) is also placed in this page.

HTML formatterTop, Main, Index

The internal HTML formatter offers

It is also the simplest to use as no other external tools are required.

The following is a simple example of generating the documentation for Ruff! itself in a single page format.

ruff::document ::ruff -title "Ruff! reference"

To generate documentation, including private namespaces, in multipage format:

ruff::document ::ruff -recurse true -pagesplit namespace -outdir ./docs -title "Ruff! internal reference"

Markdown formatterTop, Main, Index

The Markdown formatter generates output in generic Github-flavored Markdown syntax and expects support for tables in that format. It includes cross-linking but does not include a table of contents, tooltips or source code display. On the other hand, it allows conversion to other formats using external tools.

The following generates Ruff! documentation in Markdown format and then uses pandoc to convert it to HTML.

ruff::document ::ruff -format markdown -outfile ruff.md -title "Ruff! reference"

Then from the shell or Windows command line,

pandoc -s -o ruff.html -c ../ruff-md.css --metadata pagetitle="My package" ruff.md

When generating HTML from Markdown, it is generally desirable to specify a CSS style file. The ruff-md.css file provides some minimal CSS for this purpose.

Nroff formatterTop, Main, Index

The Nroff formatter generates documentation in the format required for Unix manpages. It generates documentation as a single manpage or as a page per namespace with the -pagesplit namespace option. It does not support inline HTML, navigation links or table of contents.

The Nroff formatter does not support images and links. Table support requires presence of the tbl program.

Sphinx formatterTop, Main, Index

The Sphinx formatter generates documentation in reStructuredText format in the form expected by the Sphinx documentation system. Note it is not directly usable by Python's doctools.

The Sphinx formatter does not support inline HTML.

The primary benefit of Sphinx is the ability to integrate Tcl documentation with Sphinx documentation for Python, C or other languages and produce output in additional formats like Latex.

The Sphinx formatter produces the file index.rst along with secondary files in the Ruff! output directory. To generate HTML from this file,

sphinx-build /PATH/TO/RUFF/OUTPUTDIR /PATH/TO/HTMLOUTPUT

OSVVM is an example of Ruff! generated documentation integrated within a larger Sphinx documentation set.

Asciidoctor formatterTop, Main, Index

The Asciidoctor formatter generates documentation in the Asciidoc format as processed by the Asciidoctor text processor.

Asciidoctor does not have native support for producing multipage output so use of the -pagesplit namespace option to Ruff! will require additional post-processing.

The Asciidoctor formatter produces the file index.adoc along with secondary files in the output directory. To generate HTML from this file,

asciidoctor index.adoc

Asciidoctor also supports other output formats. For example, Ruff! PDF documentation is generated by

asciidoctor-pdf -o ruff.pdf index.adoc

CommandsTop, Main, Index

coverage [::ruff]Top, Main, Index

Generates documentation coverage information.

coverage namespaces ?args?
Details
Parameters
namespacesList of namespaces for which documentation is to be generated.
argsOptions described below. Unknown options are ignored.
-compact BOOLEANIf true, only components with missing information are included.
-excludeclasses REGEXPIf specified, any classes whose names match REGEXPR will not be included in the documentation.
-excludeprocs REGEXPIf specified, any procedures whose names match REGEXPR will not be included in the documentation.
-format FORMATThe output format. FORMAT defaults to html. Relevant because some documentation may be excluded depending on format.
-include LISTSpecifies which program elements are to be examined. LIST must be a list from one or both amongst classes or procs. Defaults to procs classes.
-includeprivate BOOLEANIf true private methods are also inspected. Default is false.
-onlyexports BOOLEANIf true, only procs exported from namespaces are included.
-outdir DIRPATHSpecifies the output directory path. Defaults to the current directory.
-outfile FILENAMESpecifies the name of the output file.
-recurse BOOLEANIf true, child namespaces are recursively documented.
-sortnamespaces BOOLEANIf true (default) the namespaces are sorted in the output.
Description

The command generates documentation coverage information for one or more namespaces and writes it out to stdout or file per the options shown above. Each line of the output is indicative of missing documentation. The first two words of the each line is identify the program element type and its name with rest of the line providing additional details.

When the first word is proc, class or method, with obvious semantics, the name field is followed by a list of tags, shown in the table below, that identify the missing documentation.

summaryThe procedure or method has no summary line.
descriptionThe procedure or method has no description. Since missing subscription default to the summary line for short procedures, this also means the summary line is also absent.
paramsOne or more parameters, whose names follow the params word, do not have descriptions.
preambleIndicates the class has neither a descriptive preamble nor a constructor which may include general description of the class.

The first word may also be native or alias. The following name identifies a command in the namespace that is not documented by Ruff! as it is not a procedure.

proc ::ruff::coverage {namespaces args} {

    # Generates documentation coverage information.
    # namespaces - list of namespaces for which documentation is to be generated.
    # args - Options described below. Unknown options are ignored.
    # -compact BOOLEAN - If `true`, only components with missing information
    #  are included.
    # -excludeclasses REGEXP - If specified, any classes whose names
    #  match `REGEXPR` will not be included in the documentation.
    # -excludeprocs REGEXP - If specified, any procedures whose names
    #  match `REGEXPR` will not be included in the documentation.
    # -format FORMAT - The output format. `FORMAT` defaults to `html`.
    #  Relevant because some documentation may be excluded depending on format.
    # -include LIST - Specifies which program elements are to be examined.
    #  `LIST` must be a list from one or both amongst `classes` or `procs`.
    #  Defaults to `procs classes`.
    # -includeprivate BOOLEAN - if true private methods are also inspected.
    #  Default is false.
    # -onlyexports BOOLEAN - if true, only procs exported from namespaces
    #  are included.
    # -outdir DIRPATH - Specifies the output directory path. Defaults to the
    #  current directory.
    # -outfile FILENAME - Specifies the name of the output file.
    # -recurse BOOLEAN - if true, child namespaces are recursively
    #  documented.
    # -sortnamespaces BOOLEAN - If `true` (default) the namespaces are
    #  sorted in the output.
    #
    # The command generates documentation coverage information for one or more
    # namespaces and writes it out to stdout or file per the options shown above.
    # Each line of the output is indicative of missing documentation. The first
    # two words of the each line is identify the program element type and its name
    # with rest of the line providing additional details.
    #
    # When the first word is `proc`, `class` or `method`, with obvious semantics,
    # the name field is followed by a list of tags, shown in the table below, that
    # identify the missing documentation.
    #
    # `summary` - The procedure or method has no summary line.
    # `description` - The procedure or method has no description. Since missing
    # subscription default to the summary line for short procedures, this also
    # means the summary line is also absent.
    # `params` - One or more parameters, whose names follow the `params` word,
    # do not have descriptions.
    # `preamble` - Indicates the class has neither a descriptive preamble nor a
    # constructor which may include general description of the class.
    #
    # The first word may also be `native` or `alias`. The following name identifies
    # a command in the namespace that is not documented by Ruff! as it is not a
    # procedure.

    namespace upvar private ProgramOptions ProgramOptions
    variable gFormatter

    array set opts {
        -compact 0
        -excludeprocs {}
        -excludeclasses {}
        -format html
        -include {procs classes}
        -includeprivate false
        -onlyexports false
        -recurse false
        -sortnamespaces true
    }

    array set opts $args

    if {[info exists opts(-output)]} {
        error "Option -output is obsolete. Use -outdir and/or -outfile instead."
    }

    # Fully qualify namespaces
    set namespaces [lmap ns $namespaces {
        if {![string match ::* $ns]} {
            set ns "[string trimright [uplevel 1 {namespace current}] ::]::$ns"
        }
        if {![namespace exists $ns]} {
            error "Namespace $ns does not exist."
        }
        set ns
    }]
    if {[llength $namespaces] == 0} {
        error "At least one namespace needs to be specified."
    }


    if {$opts(-recurse)} {
        set namespaces [namespace_tree $namespaces]
    }

    # Coverage needs formatter because some docs may be excluded based
    # on formatter.
    set formatter [[load_formatter $opts(-format)] new]
    set gFormatter $formatter
    set ProgramOptions(-format) $opts(-format)

    set classprocinfodict [extract_namespaces $namespaces  -excludeprocs $opts(-excludeprocs)  -excludeclasses $opts(-excludeclasses)  -onlyexports $opts(-onlyexports)  -include $opts(-include)  -includeprivate $opts(-includeprivate)]

    set coverage ""

    dict for {ns ns_info} $classprocinfodict {
        set min_name_width [string len $ns]
        incr min_name_width 32
        set fmt "%-${min_name_width}s"
        dict for {proc_name proc_info} [dict get $ns_info procs] {
            set tags [check_proc_doc $proc_info]
            if {[llength $tags] || !$opts(-compact)} {
                append coverage [string cat "proc   "  [format $fmt $proc_name]  " " $tags \n]
            }
        }
        dict for {class_name class_info} [dict get $ns_info classes] {
            set constructor_exists 0
            foreach method_info [dict get $class_info methods] {
                set method_name [dict get $method_info name]
                if {$method_name eq "constructor"} {
                    set constructor_exists 1
                }
                set tags [check_proc_doc $method_info]
                if {[llength $tags] || !$opts(-compact)} {
                    append coverage [string cat "method " [format $fmt $class_name.[dict get $method_info name]]  " " $tags \n]
                }
            }
            # preamble should exists unless constructor is documented
            if {![dict exists $class_info preamble] && !$constructor_exists} {
                append coverage [string cat "class  "  [format $fmt $class_name] " " preamble] \n
            } elseif {!$opts(-compact)} {
                append coverage [string cat "class  " [format $fmt $class_name]] \n
            }
        }
        # List all commands that are not procs and therefore not documented
        if {[Tcl9]} {
            foreach cmd [info commands ${ns}::*] {
                if {[is_builtin $cmd]} {
                    continue
                }
                set cmd_type [info cmdtype $cmd]
                if {$cmd_type in "native alias"} {
                    append coverage "$cmd_type " $cmd \n
                }
            }
        }
    }

    if {![info exists opts(-outdir)] && ![info exists opts(-outfile)]} {
        # To stdout
        puts $coverage
    } else {
        if {![info exists opts(-outdir)]} {
            set opts(-outdir) [pwd]
        }

        if {![info exists opts(-outfile)]} {
            # Special cases  - :: -> "", ::foo::bar:: -> ::foo::bar
            set ns [string trimright [lindex $namespaces 0] :]
            if {$ns eq ""} {
                set opts(-outfile) "global-doc-coverage.txt"
            } else {
                set opts(-outfile) [namespace tail $ns]-doc-coverage.txt
            }
        } elseif {[file tail $opts(-outfile)] ne $opts(-outfile)} {
            error "Option -outfile must not include a path."
        }
        set fd [open [file join $opts(-outdir) $opts(-outfile)] w]
        try {
            puts $fd $coverage
        } finally {
            close $fd
        }
    }
    return
}

document [::ruff]Top, Main, Index

Generates documentation for commands and classes.

document namespaces ?args?
Details
Parameters
namespacesList of namespaces for which documentation is to be generated.
argsOptions described below.
-autopunctuate BOOLEANIf true, the first letter of definition descriptions (including parameter descriptions) is capitalized and a period added at the end if necessary.
-compact BOOLEANIf true, documentation is generated in a more compact form if supported by the formatter. For the built-in HTML formatter this results in procedure and method details being placed in collapsed sections that can be expanded on demand.
-diagrammer DIAGRAMARGSArguments to pass to diagram processor if none are specified in the diagram block header. Defaults to kroci ditaa
-excludeclasses REGEXPIf specified, any classes whose names match REGEXPR will not be included in the documentation.
-excludeprocs REGEXPIf specified, any procedures whose names match REGEXPR will not be included in the documentation.
-format FORMATThe output format. FORMAT defaults to html.
-hidenamespace NAMESPACEBy default, documentation generated by Ruff! includes namespace qualifiers in all class and proc names. It is possible to have the generated output leave out the namespace qualifers by adding the -hidenamespace NAMESPACE qualifier to the document generation commands. This will omit NAMESPACE in displayed program element names and provides a more visually pleasing output with less noise. However, it may result in ambiguities in case of names being present in more than one namespace. In particular, some formatters may not cross-link correctly in such cases.
-include LISTSpecifies which program elements are to be documented. LIST must be a list from one or both amongst classes or procs. Defaults to procs classes. This also controls the order in which they appear in the output documentation.
-includeprivate BOOLEANIf true private methods are also included in the generated documentation. Default is false.
-includesource BOOLEANIf true, the source code of the procedure is also included. Default value is false.
-linkassetsIf true, CSS and Javascript assets are linked. If false, they are embedded inline. If unspecified, defaults to false if the -pagesplit option is none and true otherwise. Only supported by the HTML formatter.
-locale STRINGSets the locale of the pre-defined texts in the generated outputs such as Description or Return value (Default en). To add a locale for a language, create a message catalog file in the msgs directory using the provided de.msg as a template. Only supported by the HTML formatter.
-makeindex BOOLEANIf true, an index page is generated for classes and methods. Default value is true. Not supported by all formatters.
-navigation OPTControls navigation box behaviour when scrolling. If scrolled, the navigation box will scroll vertically along with the page. Thus it may not visible at all times. If sticky, the navigation box remains visible at all times. However, this requires the number of links in the box to fit on the page as they are never scrolled. Note that older browsers do not support stickiness and will resort to scrolling behaviour. box (see below). Only supported by the html formatter. (Default scrolled)
-onlyexports BOOLEANIf true, only procs exported from namespaces are included.
-outdir DIRPATHSpecifies the output directory path. Defaults to the current directory.
-outfile FILENAMESpecifies the name of the output file. If the output is to multiple files, this is the name of the documentation main page. Other files will named accordingly by appending the namespace. Defaults to a name constructed from the first namespace specified.
-pagesplit SPLITIf none, a single documentation file is produced. If namespace, a separate file is output for every namespace.
-preamble TEXTAny text that should be appear at the beginning outside of any namespace documentation, for example an introduction or overview of a package. This shows up as the Start page content when used with the -pagesplit namespace option. TEXT is assumed to be in Ruff! syntax.
-product PRODUCTNAMEThe short name of the product. If unspecified, this defaults to the first element in $namespaces. This should be a short name and is used by formatters to identify the documentation set as a whole when documenting multiple namespaces.
-recurse BOOLEANIf true, child namespaces are recursively documented.
-section SECTIONThe section of the documentation where the pages should be located. Currently only used by the nroff formatter and defaults to 3tcl.
-sortnamespaces BOOLEANIf true (default) the namespaces are sorted in the navigation otherwise they are in the order passed in.
-title TITLEThis text is shown in a formatter-specific area on every generated page. The nroff formatter for manpages has only a limited space to display this so TITLE should be limited to roughly 50 characters if that formatter is to be used. If unspecified, it is constructed from the -product.
-version VERSIONThe version of product being documented.
Description

The command generates documentation for one or more namespaces and writes it out to file(s) as per the options shown above. See Documenting procedures, Documenting classes and Documenting namespaces for details of the expected source formats and the generation process.

proc ::ruff::document {namespaces args} {

    # Generates documentation for commands and classes.
    # namespaces - list of namespaces for which documentation is to be generated.
    # args - Options described below.
    # -autopunctuate BOOLEAN - If `true`, the first letter of definition
    #  descriptions (including parameter descriptions) is capitalized
    #  and a period added at the end if necessary.
    # -compact BOOLEAN - If `true`, documentation is generated in a more
    #  compact form if supported by the formatter. For the built-in HTML formatter
    #  this results in procedure and method details being placed in collapsed
    #  sections that can be expanded on demand.
    # -diagrammer DIAGRAMARGS - arguments to pass to `diagram` processor
    #  if none are specified in the diagram block header. Defaults to
    #  `kroci ditaa`
    # -excludeclasses REGEXP - If specified, any classes whose names
    #  match `REGEXPR` will not be included in the documentation.
    # -excludeprocs REGEXP - If specified, any procedures whose names
    #  match `REGEXPR` will not be included in the documentation.
    # -format FORMAT - The output format. `FORMAT` defaults to `html`.
    # -hidenamespace NAMESPACE - By default, documentation generated by Ruff!
    #  includes namespace qualifiers in all class and proc names. It is possible
    #  to have the generated output leave out the namespace qualifers by adding
    #  the `-hidenamespace NAMESPACE` qualifier to the document generation
    #  commands. This will omit `NAMESPACE` in displayed program element names
    #  and provides a more visually pleasing output with less noise. However,
    #  it may result in ambiguities in case of names being present in more than
    #  one namespace. In particular, some formatters may not cross-link correctly
    #  in such cases.
    # -include LIST - Specifies which program elements are to be documented.
    #  `LIST` must be a list from one or both amongst `classes` or `procs`.
    #  Defaults to `procs classes`. This also controls the order in which
    #  they appear in the output documentation.
    # -includeprivate BOOLEAN - if true private methods are also included
    #  in the generated documentation. Default is false.
    # -includesource BOOLEAN - if true, the source code of the
    #  procedure is also included. Default value is false.
    # -linkassets - if true, CSS and Javascript assets are linked. If false,
    #  they are embedded inline. If unspecified, defaults to `false` if the
    #  `-pagesplit` option is `none` and `true` otherwise. Only supported by the
    #  HTML formatter.
    # -locale STRING - sets the locale of the pre-defined texts in the generated
    #  outputs such as **Description** or **Return value** (Default `en`). To add a
    #  locale for a language, create a message catalog file in the `msgs`
    #  directory using the provided `de.msg` as a template. Only supported by the
    #  HTML formatter.
    # -makeindex BOOLEAN - if true, an index page is generated for classes
    #  and methods. Default value is true. Not supported by all formatters.
    # -navigation OPT - Controls navigation box behaviour when
    #  scrolling. If `scrolled`, the navigation box will scroll vertically
    #  along with the page. Thus it may not visible at all times. If
    #  `sticky`, the navigation box remains visible at all times.
    #  However, this requires the number of links in the box to fit on
    #  the page as they are never scrolled. Note that older browsers
    #  do not support stickiness and will resort to scrolling behaviour.
    #  box (see below). Only supported by the `html` formatter.
    #  (Default `scrolled`)
    # -onlyexports BOOLEAN - if true, only procs exported from namespaces
    #  are included.
    # -outdir DIRPATH - Specifies the output directory path. Defaults to the
    #  current directory.
    # -outfile FILENAME - Specifies the name of the output file.
    #  If the output is to multiple files, this is the name of the
    #  documentation main page. Other files will named accordingly by
    #  appending the namespace. Defaults to a name constructed from the first
    #  namespace specified.
    # -pagesplit SPLIT - if `none`, a single documentation file is produced.
    #  If `namespace`, a separate file is output for every namespace.
    # -preamble TEXT - Any text that should be appear at the beginning
    #  outside of any namespace documentation, for example an introduction
    #  or overview of a package. This shows up as the Start page content
    #  when used with the `-pagesplit namespace` option.
    #  `TEXT` is assumed to be in Ruff! syntax.
    # -product PRODUCTNAME - the short name of the product. If unspecified, this
    #  defaults to the first element in $namespaces. This should be a short name
    #  and is used by formatters to identify the documentation set as a whole
    #  when documenting multiple namespaces.
    # -recurse BOOLEAN - if true, child namespaces are recursively
    #  documented.
    # -section SECTION - the section of the documentation where the pages should
    #  be located. Currently only used by the `nroff` formatter and defaults to
    #  `3tcl`.
    # -sortnamespaces BOOLEAN - If `true` (default) the namespaces are
    #  sorted in the navigation otherwise they are in the order passed in.
    # -title TITLE - This text is shown in a formatter-specific area on every
    #  generated page. The `nroff` formatter for manpages has only a limited
    #  space to display this so `TITLE` should be limited to roughly 50 characters
    #  if that formatter is to be used. If unspecified, it is constructed from
    #  the `-product`.
    # -version VERSION - The version of product being documented.
    #
    # The command generates documentation for one or more namespaces
    # and writes it out to file(s) as per the options shown above.
    # See [Documenting procedures], [Documenting classes] and
    # [Documenting namespaces] for details of the expected source
    # formats and the generation process.
    #

    variable gFormatter

    array set opts {
        -compact 0
        -excludeprocs {}
        -excludeclasses {}
        -format html
        -hidesourcecomments false
        -include {procs classes}
        -includeprivate false
        -includesource false
        -onlyexports false
        -preamble ""
        -recurse false
        -pagesplit none
        -sortnamespaces true
        -locale en
        -section 3tcl
        -diagrammer "kroki ditaa"
    }

    array set opts $args

    if {[info exists opts(-output)]} {
        error "Option -output is obsolete. Use -outdir and/or -outfile instead."
    }

    if {![info exists opts(-makeindex)]} {
        set opts(-makeindex) [expr {$opts(-pagesplit) ne "none"}]
    }
    if {$opts(-pagesplit) eq "none" && $opts(-makeindex)} {
        app::log_error "Option -makeindex ignored when -pagesplit is specified as none."
        set opts(-makeindex) false
    }
    if {![info exists opts(-linkassets)]} {
        set opts(-linkassets) [expr {$opts(-pagesplit) ne "none"}]
    }
    lappend args -linkassets $opts(-linkassets)

    if {![info exists opts(-product)]} {
        set opts(-product) [string trim [lindex $namespaces 0] :]
        lappend args -product $opts(-product)
    }

    if {![info exists opts(-title)]} {
        set opts(-title) [string totitle $opts(-product)]
        lappend args -title $opts(-title)
    }

    ::msgcat::mclocale $opts(-locale)

    namespace upvar private ProgramOptions ProgramOptions
    set ProgramOptions(-hidesourcecomments) $opts(-hidesourcecomments)
    if {$opts(-pagesplit) ni {none namespace}} {
        error "Option -pagesplit must be \"none\" or \"namespace\" "
    }
    set ProgramOptions(-pagesplit) $opts(-pagesplit)
    set ProgramOptions(-makeindex) $opts(-makeindex)
    set ProgramOptions(-diagrammer) $opts(-diagrammer)
    set ProgramOptions(-product) $opts(-product)

    # Fully qualify namespaces
    set namespaces [lmap ns $namespaces {
        if {![string match ::* $ns]} {
            set ns "[string trimright [uplevel 1 {namespace current}] ::]::$ns"
        }
        if {![namespace exists $ns]} {
            error "Namespace $ns does not exist."
        }
        set ns
    }]
    if {[llength $namespaces] == 0} {
        error "At least one namespace needs to be specified."
    }

    set formatter [[load_formatter $opts(-format)] new]
    set gFormatter $formatter
    set ProgramOptions(-format) $opts(-format)

    # Determine output file paths
    array unset private::ns_file_base_cache
    if {![info exists opts(-outdir)]} {
        set opts(-outdir) [pwd]
    } else {
        set opts(-outdir) [file normalize $opts(-outdir)]
    }
    set ProgramOptions(-outdir) $opts(-outdir)

    if {![info exists opts(-outfile)]} {
        # Special cases  - :: -> "", ::foo::bar:: -> ::foo::bar
        set ns [string trimright [lindex $namespaces 0] :]
        if {$ns eq ""} {
            error "Option -outfile must be specified for namespace ::."
        }
        set opts(-outfile) [namespace tail $ns]
    }
    if {[file tail $opts(-outfile)] ne $opts(-outfile)} {
        error "Option -outfile must not include a path."
    }
    set private::output_file_base [file root $opts(-outfile)]
    set private::output_file_ext [file extension $opts(-outfile)]
    if {$private::output_file_ext in {{} .}} {
        set private::output_file_ext .[$formatter extension]
    }

    if {$opts(-recurse)} {
        set namespaces [namespace_tree $namespaces]
    }

    if {$opts(-preamble) ne ""} {
        # TBD - format of -preamble argument passed to formatters
        # is different so override what was passed in.
        lappend args -preamble [extract_docstring $opts(-preamble) ::]
    } else {
        if {$ProgramOptions(-pagesplit) eq "namespace"} {
            app::log_error "Warning: no main preamble specified for multipage output. Some formatters may complain."
        }
    }
    reset_symbol_occurrence_counts
    set classprocinfodict [extract_namespaces $namespaces  -excludeprocs $opts(-excludeprocs)  -excludeclasses $opts(-excludeclasses)  -onlyexports $opts(-onlyexports)  -include $opts(-include)  -includeprivate $opts(-includeprivate)]

    set docs [$formatter generate_document  $classprocinfodict  -include $opts(-include)  {*}$args]
    if {$opts(-makeindex)} {
        set docindex [$formatter generate_document_index]
        if {$docindex ne ""} {
            lappend docs -docindex $docindex
        }
    }

    $formatter copy_assets $ProgramOptions(-outdir)

    file mkdir $opts(-outdir)
    set output_files [list ]
    foreach {ns doc} $docs {
        set fn [private::ns_file_base $ns]
        set path [file join $opts(-outdir) $fn]
        lappend output_files $path
        set fd [open $path w]
        fconfigure $fd -encoding utf-8
        if {$opts(-format) eq "nroff"} {
            # On Unix, nroff, or at least tbl, does not recognize directives
            # with CRLF line endings. So always force LF for nroff.
            fconfigure $fd -translation lf
        }
        if {[catch {
            puts $fd $doc
        } msg]} {
            close $fd
            error $msg
        }
        close $fd
    }

    $formatter finalize $opts(-outdir) $output_files
    $formatter destroy

    return
}

formatters [::ruff]Top, Main, Index

Gets the available output formatters.

formatters
Details
Description

The returned values can be passed to document to generate documentation in that format.

Return value

Returns a list of available formatters.

proc ::ruff::formatters {} {

    # Gets the available output formatters.
    #
    # The returned values can be passed to [document] to generate
    # documentation in that format.
    #
    # Returns a list of available formatters.
    return {asciidoctor html markdown nroff sphinx}
}

version [::ruff]Top, Main, Index

Returns the Ruff! version.

version
Details
Return value

Returns the Ruff! version.

proc ::ruff::version {} {

    # Returns the Ruff! version.
    variable version
    return $version
}