3. Figures

For best results, figures, tables and code blocks should get captions and they should be referenced with and :xref: for figures/tables/code-blocks (:sref: for sections). :xref: and :sref: are defined as :numref:, when appropriate, otherwise as :ref:. Do not use the image directive to keep figures in place.

Label prefixes allow using the same caption for different entities, e.g., listing and figure (see section 3.1.1, Directive figure).

Emacs support functions for generating labels and their shortcuts are shown in table 3.1.

table 3.1 Emacs support functions for generating labels
shortcut command
C-c r l s M-x sdx-make-section-label
C-c r l f M-x sdx-make-figure-label
C-c r l t M-x sdx-make-table-label
C-c r l l M-x sdx-make-listing-label
C-c r l c M-x sdx-make-caption-label
C-c r l r M-x sdx-make-figctr-label

3.1. Figures with numbers

Sphinx allows certain entities to be referenced by number (see fig:Numeric references example).

This requires the option numfig to be set to True in conf.py as shown in listing 3.1.

listing 3.1 option numfig in conf.py
1
2
3
4
5
6
7
numfig = True
numfig_format = {
    'section': 'section {number}, {name}',
    'figure': 'figure %s',
    'table': 'table %s',
    'code-block': 'listing %s',
}

The supported entities are:

3.1.1. Directive figure

As documented in reStructuredText Directives, figure. See listing 3.2) and figure 3.1).

  • always use fig: prefix for label
listing 3.2 Figure example Magritte’s Pipe
1
2
3
4
.. _`fig:Figure example Magrittes Pipe`:
.. figure:: _static/MagrittePipe.jpg

   Figure example Magritte's Pipe
_images/MagrittePipe.jpg

figure 3.1 Figure example Magritte’s Pipe

3.1.2. Directive table

The body must contain a table, however, a single table cell (rectangle) is sufficient (see listing 3.3 and table 3.2).

  • always use tab: prefix for label
listing 3.3 table directive with single table cell (rectangle)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.. _`tab:single table cell rectangle`:
.. table:: single table cell (rectangle)

   +-----------------------+
   | .. code-block:: text  |
   |                       |
   |    code-block without |
   |    caption inside a   |
   |    single table cell  |
   +-----------------------+
table 3.2 single table cell (rectangle)
code-block without
caption inside a
single table cell

3.1.3. Directive code-block

code-block directives with a :caption: option can be referenced by number, e.g., “See :xref:`lst:Definition of a general code-block listing`”: renders as “See listing 3.4”.

  • always use lst: prefix for label
  • always specify language
  • always use option :linenos:
listing 3.4 Definition of a general code-block listing
1
2
3
4
5
6
.. _`lst:<LABEL>`:
.. code-block:: <LANGUAGE>
   :caption: <TITLE>
   :linenos:

   <BODY>

An example is shown in listing 3.5.

listing 3.5 Example with Elisp code
1
2
3
4
5
6
7
8
.. _`lst:Some Emacs Lisp code`:
.. code-block:: elisp
   :caption: Some Emacs Lisp code
   :linenos:

   (if (not nil)
      (let (x) (princ x))
     (let(y) princ y))

The rendered example is shown in listing 3.6.

listing 3.6 Some Emacs Lisp code
1
2
3
(if (not nil)
   (let (x) (princ x))
  (let(y) princ y))

3.1.4. Directive uml

The uml directive for plantuml(1) diagrams also works as figure, as shown in listing 3.7 and figure 3.2.

  • always use fig: prefix for label
listing 3.7 uml directive for plantuml(1) diagrams
1
2
3
4
5
6
7
8
.. _`fig:UML test`:
.. uml::
   :caption: UML test

   @startuml
   A --> B : send
   A <-- B : receive
   @enduml

@startuml
A --> B : send
A <-- B : receive
@enduml

figure 3.2 UML test

3.1.5. Directives graphviz, dot

Obviously, the graphviz directive for dot(1) diagrams also works as figure, as shown in listing 3.8 and figure 3.3.

  • always use fig: prefix for label
listing 3.8 graphviz directive for dot(1) graph diagrams
1
2
3
4
5
6
7
.. _`fig:dot test`:
.. graphviz::
   :caption: dot test

   digraph xx {
   A -> B;
   }

digraph xx { A -> B; }

figure 3.3 dot test

3.1.6. Directive figctr

Since single cell tables end up in the table namespace, the extension ws_figure_container provides the figctr directive, which works like a container in the figure namespace (see listing 3.9 and fig:Fig Ctr Caption).

listing 3.9 figctr directive
.. _`fig:Fig Ctr Caption`:
.. figctr:: Fig Ctr Caption

   Arbitrary things like this:

   .. code-block:: sh

      if test -r "file"
      then
          cat "file"
      fi

3.3. Check README for figure requirements

Before a README is done, it is useful to check, if every figure has a caption, directive and a reference.

figure-regexp:

   ^ *\([.][.]  *\(\(table\|figure\|uml\|graphviz\|graph\|digraph\)::\|_`\(tab\|fig\):\)\|:caption:\)\|:xref:

figure-grep-cmd::

  /bin/grep --color -nH README-fillme.txt -e '{figure-regexp}'

Search with

- :kbd:`M-x occur RET {figure-regexp} RET`
- :kbd:`M-x grep RET {figure-grep-cmd} RET`

- For creating figure labels, use emacs commands

  - :kbd:`C-c r l c`, :kbd:`M-x sdx-make-caption-label`
  - :kbd:`C-c r l f`, :kbd:`M-x sdx-make-figure-label`
  - :kbd:`C-c r l t`, :kbd:`M-x sdx-make-table-label`

See :xref:`fig:complete figure requirements`

.. _`fig:complete figure requirements`:
.. uml::
   :caption: complete figure requirements

    @startuml
    package "complete figure requirements" {
      start
      floating note right
      figure requirements:
      * caption
      * directive
      * reference
      end note
      :grep for uml/table (figure-regexp);
      while (for each matched directive line) is (do)
        while (caption, label or reference is missing?)
          if (caption is missing?) then (yes)
          :* add caption
          * correct label, if present
          * correct reference, if present;
          elseif (label is missing?) then (yes)
          :* move before figure
          * add label with `C-c r l [cft]`
          * correct reference, if present;
          else (reference\nis missing)
          :add reference;
          endif
        end while
      end while
      stop
    }
    @enduml

3.4. Templating with automatic labels (NO!)

|:q:| |:da:| f5 Sections (3, 4, 5) yank a new section title, why not also a .. sec:fillme: above it?
|:a:| because:
  • Do not inflate the use of section labels! if a section is not referenced, it should not have a label.

  • Why would want write the section title three times?

    The correct template would be:

    :xref:`sec:::fillme::`
    .. _`sec:::fillme::`:
    
    ================
    :sec: ::fillme::
    ================
    

    Filling in the section title must be done anyway:

    • change tag delimiter to “::” (C-c C-x)
    • move to beginning of fillme (M-left)
    • delete fillme (M-k)

    Alternative 1: Copy title and replace label fillme

    • mark beginning of title (C-SPC)
    • enter title
    • copy title (M-w)
    • go to label fillme (M-left)
    • delete fillme (M-k)
    • insert title (C-y)
    • Clean up label (remove all non-ascii characters) 0 - aleph_0 keystrokes
    • If the title ws not clean, copy the label title (many keystrokes)
    • go to :xref: sec:::fillme:: (M-left)
    • delete fillme (M-k)
    • insert title (C-y)

    Minimum keystrokes: 8, Maximum keystrokes: aleph_0

    Alternative 2: Write title and generate label with emacs function (C-c r l s)

    • enter title
    • go before :sec: line (up)
    • generate xref + label (C-c r l s)

    Minimum keystrokes: 5, Maximum keystrokes: 5