Documentation blocks in Tcl

The Doxygen doesn't support Tcl anymore. The last release with Tcl support is 1.8.18 link .

Doxygen documentation can be included in normal Tcl comments.

To start a new documentation block start a line with ## (two hashes). All following comment lines and continuation lines will be added to this block. The block ends with a line not starting with a # (hash sign).

A brief documentation can be added with ;#< (semicolon, hash and lower then sign). The brief documentation also ends at a line not starting with a # (hash sign).

Inside doxygen comment blocks all normal doxygen markings are supported. The ony difference are described in the following two paragraphs.

If a doxygen comment block ends with a line containing only #\code or #@code all code until a line only containing #\endcode or #@endcode is added to the generated documentation as code block.

If a doxygen comment block ends with a line containing only #\verbatim or #@verbatim all code until a line only containing #\endverbatim or #@endverbatim is added verbatim to the generated documentation.

To detect namespaces, classes, functions and variables the following Tcl commands are recognized. Documentation blocks can be put on the lines before the command.

  • namespace eval .. Namespace
  • proc .. Function
  • variable .. Variable
  • common .. Common variable
  • itcl::class .. Class
  • itcl::body .. Class method body definition. Will be appended to method documentation.
  • oo::class create .. Class
  • oo::define .. OO Class definition
  • method .. Class method definitions
  • constructor .. Class constructor
  • destructor .. Class destructor
  • public .. Set protection level
  • protected .. Set protection level
  • private .. Set protection level
  • inherit .. superclass .. Set class relations.

To use your own keywords you an map these keyword to the recognized commands using the "TCL_SUBST" entry in the config file. The entry contain a list of word-keyword mappings. To use the itcl::* commands without the leading namespace use p.e.:

'TCL_SUBST = class=itcl:class body=itcl:body'

Following is a example using doxygen style comments:

## \file tclexample.tcl
# File documentation.

# Startup code:\
exec tclsh "$0" "$@"
## Documented namespace \c ns .
# The code is inserted here:
namespace eval ns {
  ## Documented proc \c ns_proc .
  # param[in] arg some argument
  proc ns_proc {arg} {}
  ## Documented var \c ns_var .
  # Some documentation.
  variable ns_var
  ## Documented itcl class \c itcl_class .
  itcl::class itcl_class {
    ## Create object.
    constructor {args} {eval $args}
    ## Destroy object.
    destructor {exit}
    ## Documented itcl method \c itcl_method_x .
    # param[in] arg Argument
    private method itcl_method_x {arg}
    ## Documented itcl method \c itcl_method_y .
    # param[in] arg Argument
    protected method itcl_method_y {arg} {}
    ## Documented itcl method \c itcl_method_z .
    # param[in] arg Argument
    public method itcl_method_z {arg} {}
    ## Documented common itcl var \c itcl_Var .
    common itcl_Var
    ## \protectedsection
    variable itcl_var1;#< Documented itcl var \c itcl_var1 .
    variable itcl_var2;#< Documented itcl var \c itcl_var2 .
  ## Documented oo class \c oo_class .
  oo::class create oo_class {
    ## Create object.
    # Configure with args
    constructor {args} {eval $args}
    ## Destroy object.
    # Exit.
    destructor {exit}
    ## Documented oo var \c oo_var .
    # Defined inside class
    variable oo_var
    ## \private Documented oo method \c oo_method_x .
    # param[in] arg Argument
    method oo_method_x {arg} {}
    ## \protected Documented oo method \c oo_method_y .
    # param[in] arg Argument
    method oo_method_y {arg} {}
    ## \public Documented oo method \c oo_method_z .
    # param[in] arg Argument
    method oo_method_z {arg} {}

itcl::body ::ns::itcl_class::itcl_method_x {argx} {
  puts "$argx OK"

oo::define ns::oo_class {
  ## \public Outside defined variable \c oo_var_out .
  # Inside oo_class
  variable oo_var_out

## Documented global proc \c glob_proc .
# param[in] arg Argument
proc glob_proc {arg} {puts $arg}

variable glob_var;#< Documented global var \c glob_var\
  with newline
#< and continued line

# end of file


  • Version 1.7.5: Tcl is supported under doxygen
  • Version 'TCL_SUBST' keyword and command linking in documantation added
  • Version tcl related bugs 662286 and 662289 solved
  • Version 1.8.0: tcl related bug 669758 solved
  • Version 1.8.18: last version with Tcl support


Wish list

RobertHeller - 2010-09-09 11:18:36

I've written a Tcl-coded filter that 'generates' a pseudo C++ header. It handles SNIT objects (snit::type, snit::widget, snit::widgetadaptor, and snit::macro).

It is available at the URL

Feel free to download it and have a look. It is pretty simple and does what *I* need it to do.

RZ I will have look on it.

arjen - 2010-09-15 03:15:13

AM I just happened to get involved in something similar for MATLAB code. But we use the filter functionality of doxygen to mold the code into something digestible to doxygen. doxygen offers the possibility to run Perl scripts, but I you put my Tcl code in a starpack and that is happily accepted. The output has C++ syntax and comment style.

RZ Yes, you can use the doxygen filters. But you are loosing references (line number) to the original code.

WTS - 2010-09-15 19:50:00

There is tcl-dox .

It is no longer maintained so I started a new one tcl2doxy . I tried a parser only approach first, but quickly gave up. Now it has a simple parser which is recursively called for script arguments.

RZ Is it a filter to oxygen?

WTS - 2010-010-03 18:15:00 Yes, both are filters. And yes, there is the problem with line numbers. I tried to preserve the original formatting as far as possible. However, code that resides outside of any procedure may lead to unwanted results. I usually include the filtered code into the documentation. This way, the links to line numbers point correctly. The filtered code is readable enough.

Googie - 2010-11-17 - I downloaded Linux binary from kbskit download area (the link at the top of this page). I guess that's the binary with patch included. Correcty?

RZ yes

If yes, then I cannot make it to get work done. I configured it so it scans tcl files (I see it on stdout), but the output documents are empty, even I have some procedures defined in tcl files. Any tips?

RZ Check your settings in Doxyfile. To check the binary try the following:

 Run: doxygen -g
 Set in Doxyfile: INPUT = test.tcl
 Create test.tcl with:
 ## Brief comment
 # additional comment
 # @param[in] input some input
 proc myproc {input} {
 # end of file
 Run: doxygen

Googie - 2010-11-17 - It doesn't work, so I guess the binary isn't patched. I'll try to compile it myself then.

RZ Found it offline. Currently the namespace :: is not shown. It seems the doc generator ignore it. This need some investigation. You can workaround by commenting your file with:

 ## @file test.tcl

The proc in :: will then be shown in the file documentation.

Googie - 2010-11-18 - I used workeround to see results. It works, but I noticed other problem: I created procedure with 4 arguments, where the last one is optional (has default value). It handles default value correctly in detailed description, but on that "Functions" list, the optional argument is not separated by whitespace. It looks like this:

 myproc in1 in2 in3{input true}

RZ The output in the function description is ok. So it seems a problem in the formatting code inside doxygen. I will remember this but I do not think I will have time to fix it soon.

And one more thing - I'd like to be able to use

 @fn myproc {input}

but now I'm not. When I use it the doxygen prints warning on stdout:

 Member myproc {input} (function) of file test.tcl is not documented.

and function is not documented in files section anymore (just listed, with no details).

RZ Could you post your code? Also remember that all documentation in commments is parsed by doxygen directly. So the normal doxygen rules apply. There will be a difference in the next version. Everything between the two lines #@code and #@endcode or #@verbatim and #@endverbatim will be included in the current documentation part.

Googie The code is:

 ## @file test.tcl

 # @fn myproc {input}
 # @param input some input
 proc myproc {input} {

 # end of file

RZ I will try to fix this. In the meantime you can work without the @fn. It is also recommended in the doxygen documentation. I also fixed some issues with continuation lines (\ at end of line) and protection levels. I hope to post the new version on the weekend.

Googie I updated code above. I also let myself to put this dialog into "discussion" block, as it's a trend lately. I hope that's ok.

Googie - Great news about the TCL_SUBST implemented! One thing to clarify: if I define TCL_SUBST, then do I overwrite default list of substituted commands (like proc, etc)?

RZ This depends on your setting. Overwriting commands is possible. Some examples to clarify.

 # Use 'class' inside your code and create documentation for 'oo::class'
 TCL_SUBST = class oo::class
 # Use 'proc' inside your code and create documentation for 'itcl::class'.
 TCL_SUBST = proc itcl::class
 # Use 'variable' inside your code and do not generate documentation.
 TCL_SUBST = variable dummy

jdc - 2011-02-03 04:48:46

Anything can be done to display proc arguments in Tcl style iso using C style in the generated HTML?

RZ I have found the place. Not so easy because of C++ and using the same functions in different things. But how should I format? Currently I use ?varname? for parameter with default values and left args untouched. Is this ok? jdc Ok for me. Thanks.

Googie - 2011-02-07 Any comments on recent changes?

RZ I changed the function declarations to a more tcl'ish style.

Googie - 2011-06-17 I downloaded version from february and tried to regenerate my documentation (I haven't done it for long time) and I ran into a problem that documentation contains list of classes, also class description, class details contains list of methods and variables, but description of these methods and variables is completly ignored :(

I write code like:

# @class Class1
# Class description.
class Class1 {
    public {
        # @var var1
        # This is variable description.
        variable var1 ""

        # @fn doSomething {arg1}
        # @param arg1 Argument description.
        # Method description.
        # @return Return value description.
        method doSomething {arg1}

body Class1::doSomething {arg1} {
    # ...

I'm using itcl with imported itcl namespace. I declared:

 TCL_SUBST = class itcl::class body itcl::body

in doxygen config.

What do I do wrong?

RZ If you put your documentation directly before the definition you do not need the '@class', '@var' and '@fn' parts. Remove these lines and it should work. It is even less work. Nonetheless it is something I will have in mind for a next version.

I have some code that looks like the following:

# Class description.
class Class1 {

    # Some proc
    proc some_proc { } { }

    # Some method
    public method some_method { } { }

When I used the patched doxygen, documentation is generated for some_method but not for some_proc. Any workaround for this?

RZ If I put your code in a file I get the documentation under Class List -> Class1. May be an error in your Doxyfile? I have the following line in it:

  TCL_SUBST              = class itcl::class

Mamu I too get documentation under Class List -> Class1. But there is nothing generated for 'some_proc'. My Doxyfile has: 'TCL_SUBST = class itcl::class body itcl::body'

RZ You can find the docu for 'some_proc' under Namespace list -> Class1. Methods are documented under classes and normal proc's under namespaces.

Googie - 2011-07-18 It's great to hear it's now official! Is the TCL_SUBST planned to be included as well in next releases or do the Doxygen developers have objections about it?

RZ Currently the developer has #ifdef'd the code. I will try to get it official. He suggests to use the class=itcl::class styple. But this should be no problem. I also have some changes to create links to command names (first word of command or first word in brackets).

WTS - 2011-09-07 Works great! Thank you! I cannot find how to include call/caller graphs. Are they expected to work?

RZ I'm currently working on it.

tombert - 2011-10-20 07:05:54

Thx for this converter - really waited for it.

Unfort. I have problems with the "Related Page" - it only shows a single item per class: Also the classes show up as namespaces but with empty pages:

RZ - 2011-11-04 Try the new tclscanner.l file. It is attached to bug 662190.

marmstro - 2013-02-25

I do not get documentation for class procs, similar to the comment above. I did look under namespace list and I do not see any namespace corresponding to the class. My code looks like this:

# \brief my class
class MyClass {
    # \brief my method
    method mymethod {} {}
    # \brief my proc
    proc myproc {} {}

I am using doxygen 1.8.2

RZ You need to define the object system. Either itcl or oo. I asume you are using itcl. So you have two options. Either use itcl::class or put the following line in your Doxyfile:

 TCL_SUBST = proc itcl::class

marmstro I assume you meant TCL_SUBST = class=itcl::class following the current documentation. I did try both ways and still don't see the class in the namespace list. I see in the 662268 bug discussion that the documentation page for the namespace corresponding to a class was removed. Is this the case even when procs are present in the class definition or only when the documentation page would otherwise be empty as in the case of no procs?

RZ copy&paste error, sorry. TCL_SUBST = class=itcl::class is right. It works for me with the following version:

 ./doxygen --version

Could you try to put a file documentation block in your file. The following should be enough:

 # \file myfile.tcl

marmstro After inserting the \file card the procs show up under the corresponding file entry under the Files tab. The Namespace tab is still absent.

marmstro Setting EXTRACT_ALL = YES fixes this issue. Even better, using member groups or modules works, which I was planning to do anyway.

marmstro - 2013-02-27

There are some other issues with the scanner, evident in the example given in the Doxygen documentation at this link: [L1 ] which gives the output at this link: [L2 ]

  1. Class variables are listed as static attributes, whereas they are not static. Only common class variables should be listed as static. In the linked example you can see the class variables under the static heading.
  2. The protection level is not automatically extracted. In the linked example, the private, protected and public methods are all listed under public member functions.
  3. Another issue: The scanner does not like constructors with the optional initialization statement (this adds another argument).