doctools::toc(n)

πŸ“¦
version 2.0 Β· 2 versions
, in fedora 43, fedora 44, nixos 26.05, nixpkgs unstable

πŸ’– doctools::toc β€” the manual page, but make it a group chat πŸ’–

okay bestie, gather round, because today we're learning about doctools::toc β€” that's the manual page from Documentation tools and it is literally the whole vibe of holding tables of contents. πŸŽ€


✨ NAME ✨

doctools::toc β€” holding tables of contents. that's it. that's the job. holding them. 🫢


🌸 SYNOPSIS 🌸

here's the whole tea, verbatim, no notes:

package require doctools::toc ?2?

package require Tcl 8.5 9

package require doctools::toc::structure

package require struct::tree

package require snit

::doctools::toc objectName

objectName method ?arg arg ...?

objectName destroy

objectName + reference id label docid desc

objectName + division id label ?docid?

objectName remove id

objectName up id

objectName next id

objectName prev id

objectName child id label ?...?

objectName element ?...?

objectName children id

objectName type id

objectName full-label id

objectName elabel id ?newlabel?

objectName description id ?newdesc?

objectName document id ?newdocid?

objectName title

objectName title text

objectName label

objectName label text

objectName importer

objectName importer object

objectName exporter

objectName exporter object

objectName deserialize = data ?format?

objectName deserialize += data ?format?

objectName serialize ?format?

look at all those methods, she's serving range πŸ’…


πŸ‘‘ DESCRIPTION πŸ‘‘

so this package? it gives you a class that can contain tables of contents and programmatically manipulate them. yes, programmatically. you get to poke at them with code. iconic.

this class is one of the three public pillars that the management of tables of contents rests on, and the other two pillars are:

  1. Exporting tables of contents, and
  2. Importing tables of contents

for the lore about the Concepts of tables of contents β€” like, what are their parts, what's the anatomy β€” go read the section literally called that (it's right below, i gotchu). for the tea on the data structure used to encode tables of contents as values, that's the ToC serialization format section. and here's the key thing, bestie: that format is the only one this class directly knows about. any conversion from or to any other format? that's not her job. that's handled by export and import manager objects. you can attach those to a container, but you absolutely don't have to β€” it's purely a convenience situation. no pressure. πŸ¦‹


🧚 CONCEPTS 🧚

okay so here are the ground rules, numbered, because we're organized:

  1. a table of contents consists of a (possibly empty) list of elements.
  2. each element in that list is identified by its label.
  3. each element is either a reference, or a division.
  4. each reference has an associated document β€” identified by a symbolic id β€” plus a textual description.
  5. each division may have an associated document, identified by a symbolic id. (may. it's optional. she's flexible.)
  6. each division consists of a (possibly empty) list of elements, with each element following the rules as specified in item 2 and above. recursion said hi πŸ™ˆ

a few notes

  1. the above rules span up a tree of elements β€” with references as the leaf nodes, divisions as the inner nodes, and each element representing an entry in the whole table of contents.
  2. the identifying labels of any element E are unique within their division (or toc), and the full label of any element E is the list of labels for all nodes on the unique path from the root of the tree to E, including E. so yes, it's the whole ancestry line, no skipping. 😌

ngl this page is long, so this is only part 1 β€” more parts are coming, don't go anywhere, bestie πŸ’–

✨ API ✨

okay bestie, this is where we stop vibing about concepts and start actually doing stuff πŸ’… every single thing below is real, so read carefully and don't skip, i promise it's giving useful.


πŸŽ€ PACKAGE COMMANDS πŸŽ€

  • ::doctools::toc objectName β€” this one builds you a brand new container object, and it comes with its own Tcl command whose name is literally objectName. the whole personality of that object command is explained down in Object command and Object methods. also important: if objectName is not fully qualified, the object command gets created under the current namespace; if it is fully qualified, it lands in whatever namespace you specified. no cap 🫢

πŸ¦‹ OBJECT COMMAND πŸ¦‹

every object that ::doctools::toc makes follows this exact general shape:

objectName method ?arg arg ...?

so like, the method you call plus its arguments are what decide the actual behavior of the command. the full tea on each one lives in Object methods below, don't worry, we get there 🌸


πŸ‘‘ OBJECT METHODS πŸ‘‘

okay so this is the big list. every method is invoked as objectName method ?arg arg ...?. let's go one by one, no skipping, periodt πŸ’–

  • objectName destroy β€” this method destroys the object it was invoked on. bye bestie, you're gone πŸ’€
  • objectName + reference id label docid desc β€” this drops a brand new reference element into the table of contents, right under the element you point to with its handle id. that parent element has to be a division element, or the root β€” anything else and it throws an error, sorry, rules are rules.

the new element gets externally identified by its label, which has to be unique within the parent element. not unique? error. also error if you get it wrong. that's just how it is 😭

as a reference element it refers to a document identified by the symbolic docid. this reference must not be the empty string β€” if it is, an error is thrown, fr fr. beyond the label, the element also carries a longer descriptive string, handed to it via desc.

the result of the method is the handle (id) of the new element. you get your shiny new id back, slay ✨

  • objectName + division id label ?docid? β€” this adds a new division element to the table of contents, under the element you point at with its handle id. that parent element has to be a division element, or the root. otherwise? error, obviously πŸ™ˆ

the new element is externally identified by its label, which has to be unique within the parent element. if it's not unique, an error is thrown.

as a division element it can refer to a document identified by the symbolic docid, but it's fully allowed to choose not to.

the result of the method is the handle (id) of the new element. iconic πŸ‘‘

  • objectName remove id β€” removes the element identified by the handle id from the table of contents. and if that element is a division, all of its children get removed too β€” the whole squad goes down together 🫢
🚨 but the root element/division of the table of contents cannot be removed. nope. you can only remove its children. don't try it.

the result of the method is the empty string.

  • objectName up id β€” gives you the handle of the parent of the element identified by its handle id. or, if id referred to the root element, you get the empty string back.
  • objectName next id β€” gives you the handle of the right sibling of the element identified by its handle id. if that element has no right sibling, you get the handle of the parent instead. and if id referred to the root element, you get the empty string. that's the whole vibe check 🌈
  • objectName prev id β€” gives you the handle of the left sibling of the element identified by its handle id. if there's no left sibling, you get the handle of the parent. and if id referred to the root element β€” empty string, as always πŸ’œ
  • objectName child id label ?...? β€” gives you the handle of a child of the element identified by its handle id. the child itself is identified by a series of labels. so yeah, walk it down, step by step 🧚
  • objectName element ?...? β€” gives you the handle of the element identified by a series of labels, starting all the way from the root of the table of contents. and plot twist: the series of labels is allowed to be empty, in which case you just get the handle of the root element back. convenient ✨
  • objectName children id β€” gives you a list with the handles of all the children of the element identified by the handle id, from first to last, in that order. ordered, respectful, no chaos πŸ’…
  • objectName type id β€” tells you the type of the element, and it's either reference or division. that's it. that's the answer.
  • objectName full-label id β€” this one is the literal complement of the element method. it takes the handle id of an element and converts it into a list of labels that fully identifies that element within the whole table of contents. reverse uno card πŸ”₯
  • objectName elabel id ?newlabel? β€” queries and/or changes the label of the element identified by the handle id. if the newlabel argument is there, the label gets changed to that value. either way, doesn't matter, the result of the method is always the current value of the label.

if you do change it, the new label has to be unique within the containing division, or an error gets thrown. no duplicates allowed, bestie 🚫

and here's a fun one: if id refers to the root element of the table of contents, then using this method is equivalent to using the label method β€” i.e. you're accessing the global label for the whole table. iykyk 🌟

  • objectName description id ?newdesc? β€” queries and/or changes the description of the element identified by the handle id. if newdesc is present, the description gets changed to that value. and regardless, the result of the method is the current value of the description.
⚠️ the element this method operates on has to be a reference element β€” otherwise an error will be thrown. so check before you poke πŸ™ˆ
  • objectName document id ?newdocid? β€” queries and/or changes the document reference of the element identified by the handle id. if newdocid is present, the reference gets changed to that value. and regardless of that, the result of the method is the current value of the document reference.

setting the reference to the empty string means unsetting it, and that's allowed only for division elements. flip side: if the result you get back is the empty string, then the element has no document reference at all β€” and that can only happen for division elements. so no, a reference element can never be empty-stringed here 😀

  • objectName title β€” returns the title of the table of contents that's currently defined. that's the whole method, short and sweet πŸ“
  • objectName title text β€” sets the title of the table of contents to text, and then returns it as the result of the command. set and served in one move πŸ’–
  • objectName label β€” returns the label of the table of contents that's currently defined.
  • objectName label text β€” sets the label of the table of contents to text, and returns it as the result of the command.
  • objectName importer β€” returns the import manager object that's currently attached to the container, if there is one. if there isn't, well, nothing to return πŸ‘€
  • objectName importer object β€” attaches object as the import manager to the container, and returns it as the result of the command.
🚨 note: the object is not put into ownership of the container. meaning: destroying the container will not destroy the object. you own it, bestie, don't forget that.

it's expected that object provides a method named import text which takes a text and a format name, and returns the canonical serialization of the table of contents contained in that text, assuming the given format. that's the deal 🌸

  • objectName exporter β€” returns the export manager object currently attached to the container, if any.
  • objectName exporter object β€” attaches object as the export manager to the container, and returns it as the result of the command.
🚨 same warning as before: the object is not put into ownership of the container. destroying the container will not destroy the object. periodt.

it's expected that object provides a method named export object which takes the container and a format name, and returns a text encoding the table of contents stored in the container, in the given format. it's further expected that the object will use the container's method serialize to obtain the serialization of the table of contents from which it's going to generate that text. teamwork makes the dream work 🫢

  • objectName deserialize = data ?format? β€” this method replaces the contents of the table object with the table contained in data. if no format was specified, it's assumed to be the regular serialization of a table of contents.

otherwise, the object will use the attached import manager to convert the data from the specified format into a serialization it can actually handle. and in that case, an error gets thrown if the container has no import manager attached to it. so like, attach one first πŸ’…

the result of the method is the empty string.

  • objectName deserialize += data ?format? β€” this behaves like deserialize = in its essentials, except that it merges the table of contents in data into its contents instead of replacing it. cute, additive, respectful πŸŽ€

the method will throw an error if merging is not possible, i.e. if it would produce an invalid table. and in that case, the existing content is left unchanged β€” nothing gets half-eaten, promise.

the result of the method is the empty string.

  • objectName serialize ?format? β€” this method returns the table of contents contained in the object. if no format is specified, the returned result is the canonical serialization of its contents.

otherwise, the object will use the attached export manager to convert the data to the specified format. and in that case, an error gets thrown if the container has no export manager attached to it. same energy as the importer situation, just the other direction 🌈

✨ TOC SERIALIZATION FORMAT ✨

okay so here we specify the format used by doctools v2 packages to serialize tables of contents as immutable values for transport, comparison, etc. πŸ’…

We distinguish between regular and canonical serializations. While a table of contents may have more than one regular serialization, only exactly one of them will be canonical. no cap, periodt. ✨


πŸ’– regular serialization πŸ’–

  1. The serialization of any table of contents is a nested Tcl dictionary. πŸͺ†
  2. This dictionary holds a single key, doctools::toc, and its value. This value holds the contents of the table of contents. πŸ‘‘
  3. The contents of the table of contents are a Tcl dictionary holding the title of the table of contents, a label, and its elements. The relevant keys and their values are:
    • title β€” The value is a string containing the title of the table of contents. ✨
    • label β€” The value is a string containing a label for the table of contents. 🏷️
    • items β€” The value is a Tcl list holding the elements of the table, in the order they are to be shown. πŸ‘€

Each element is a Tcl list holding the type of the item, and its description, in this order. An alternative description would be that it is a Tcl dictionary holding a single key, the item type, mapped to the item description. 🧠

The two legal item types and their descriptions are:

  • reference β€” This item describes a single entry in the table of contents, referencing a single document. To this end its value is a Tcl dictionary containing an id for the referenced document, a label, and a longer textual description which can be associated with the entry. The relevant keys and their values are:
    • id β€” The value is a string containing the id of the document associated with the entry. πŸ†”
    • label β€” The value is a string containing a label for this entry. This string also identifies the entry, and no two entries (references and divisions) in the containing list are allowed to have the same label. 🚫
    • desc β€” The value is a string containing a longer description for this entry. πŸ“
  • division β€” This item describes a group of entries in the table of contents, inducing a hierarchy of entries. To this end its value is a Tcl dictionary containing a label for the group, an optional id to a document for the whole group, and the list of entries in the group. The relevant keys and their values are:
    • id β€” The value is a string containing the id of the document associated with the whole group. This key is optional. πŸ†”
    • label β€” The value is a string containing a label for the group. This string also identifies the entry, and no two entries (references and divisions) in the containing list are allowed to have the same label. 🚫
    • items β€” The value is a Tcl list holding the elements of the group, in the order they are to be shown. This list has the same structure as the value for the keyword items used to describe the whole table of contents, see above. This closes the recusrive definition of the structure, with divisions holding the same type of elements as the whole table of contents, including other divisions. πŸŒ€

🌈 canonical serialization 🌈

The canonical serialization of a table of contents has the format as specified in the previous item, and then additionally satisfies the constraints below, which make it unique among all the possible serializations of this table of contents. fr fr. ✨

  1. The keys found in all the nested Tcl dictionaries are sorted in ascending dictionary order, as generated by Tcl's builtin command lsort -increasing -dict. πŸ”€

😭 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. πŸ“Ž


πŸ”‘ KEYWORDS πŸ”‘

HTML, TMML, conversion, doctoc markup, documentation, formatting, generation, json, latex, markup, nroff, parsing, plugin, reference, table, table of contents, tcler's wiki, text, wiki


πŸ“š CATEGORY πŸ“š

Documentation tools


Copyright (c) 2009 Andreas Kupries <andreas_kupries@users.sourceforge.net>


okay bestie that's the whole page! from tcllib, section 2, titled doctools::toc(n). the footer didn't hand me a date, so that's the whole vibe. mwah πŸ’‹πŸ’–

πŸ“¦ where this page comes from