Sphinx Doc

Sphinx Doc is a collection of scripts and templates to allow for simple setup, administration and output formatting of reStructuredText documents.

The focus is on providing a simple standalone README article and a book with chapters made from single README files.

It employs snippets(1) and the python package PyJsMo.

Documentation workflow

Fig. 1 shows the definitive state diagram for the documentation workflow. Some state transitions are triggered by a list of mandatory shell commands. For alternatives, e.g.,

\[\begin{split}\left\{\begin{array}{l} \mbox{touch file}\\ \mbox{sda automodule module}\\ \mbox{sda chapter add 'Chapter title'}\\ \end{array}\right.\end{split}\]

at least one command or an equivalent must be excuted. There is no exception to this reuqirement.

' -*- plantuml -*-
' Copyright (C) 2019, Wolfgang Scherer, <Wolfgang.Scherer at gmx.de>
'
' This file is part of Documentation Standard.
'
' Permission is granted to copy, distribute and/or modify this document
' under the terms of the GNU Free Documentation License, Version 1.3
' or any later version published by the Free Software Foundation;
' with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
' A copy of the license is included in the section entitled "GNU
' Free Documentation License".

@startuml
/' |:here:| '/

scale 1080 height

hide empty description

skinparam state {
  StartColor<<break>> DarkOrange
  BackgroundColor<<stable>> lime
  BackgroundColor<<unstable>> yellow
  BackgroundColor<<break>> DarkOrange
  EndColor<<break>> yellow
}

' skinparam linetype ortho
' skinparam linetype polyline

[*] --> UPDBOOK
State "Update Book" as UPDBOOK {
State "local repo synchronized" as ULCLSYNC
State "work directory synchronized" as UWDSYNC
[*] --> ULCLSYNC : hg pull
ULCLSYNC --> UWDSYNC : hg update
ULCLSYNC --> UWDSYNC : hg merge
UWDSYNC --> [*]
}
UPDBOOK --> STABLE <<stable>>

[*] --> GETBOOK
State "Get Book" as GETBOOK {
[*] --> [*] : hg clone ""ssh:/""""/host/""""/path/book""
}
GETBOOK --> STABLE

[*] --> NEWBOOK
State "New Book" as NEWBOOK {
[*] -->  INITIALIZED : mkdir book\lcd book\lsda init 'Book title'\lhg init
INITIALIZED --> INITIALIZED : / - hg add\l\\ - hg forget
INITIALIZED --> [*] : hg commit
}
NEWBOOK --> STABLE

STABLE --> MODIFYING <<unstable>> : emacs file\lvi file
MODIFYING --> PAUSING : adhoc\nstable point\nreached
PAUSING --> MODIFYING
MODIFYING --> COMMITTING : adhoc\nstable point\nreached
MODIFYING --> DISCARDED: hg revert file

STABLE --> ADDING <<unstable>> : / - touch file\l| - sda automodule module\l\\ - sda chapter add 'Chapter title'\lhg add file
ADDING --> COMMITTING : sda chapter clean
COMMITTING --> STABLE

ADDING  --> DISCARDED  : hg forget file\l/ - rm -f file\l| - rm -f doc/module.rst\l| - sda chapter rollback\l\\    rm -f README-chapter.txt
DISCARDED -right-> STABLE

State PAUSING {
State "Doing something else" as BREAK <<break>>
State "local repo synchronized" as MLCLSYNC
State "work directory synchronized" as MWDSYNC
[*] <<break>> --> BREAK
BREAK --> MLCLSYNC : hg pull
MLCLSYNC --> MWDSYNC : hg update
MLCLSYNC --> MWDSYNC : hg merge
MWDSYNC --> [*] <<break>>
}

State COMMITTING {
State "local repo synchronized" as LCLSYNC
State "work directory synchronized" as WDSYNC
State "local repo up to date" as LCLUP
State "remote repo up to date" as RMTUP
[*] --> LCLSYNC : hg pull
LCLSYNC --> WDSYNC : hg update
LCLSYNC --> WDSYNC : hg merge
WDSYNC --> LCLUP : hg commit
LCLUP --> RMTUP : hg push
RMTUP --> [*]
}

' COMMITTING -[hidden]-> [*]
STABLE -right-> [*] : Stop\nWorking

' (progn (forward-line 1) (snip-insert-mode "puml.t.ide" t) (insert "\n"))
' :ide-menu: Emacs IDE Menu - Buffer @BUFFER@
' . M-x `eIDE-menu' ()(eIDE-menu "z")

' :ide: OCCUR-OUTLINE: Sections: `||: sec :||'
' . (x-symbol-tag-occur-outline "sec" '("||:" ":||") '("|:" ":|"))

' :ide: MENU-OUTLINE:  Sections `||: sec :||'
' . (x-eIDE-menu-outline "sec" '("||:" ":||") '("|:" ":|"))

' :ide: OCCUR-OUTLINE: Default `|||: sec :|||'
' . (x-symbol-tag-occur-outline)

' :ide: MENU-OUTLINE:  Default `|||: sec :|||'
' . (x-eIDE-menu-outline)

' :ide: +-#+
' . Buffer Outline Sections ()

' :ide: PLANTUML: HELP
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ""))) (compile (concat "plantuml -h ")))

' :ide: PLANTUML: this file's EPS
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".eps"))) (compile (concat "plantuml -teps " (buffer-file-name))))

' :ide: PLANTUML: this file's PDF
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".pdf"))) (compile (concat "plantuml -tpdf " (buffer-file-name))))

' :ide: PLANTUML: this file's PNG
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".png"))) (compile (concat "plantuml -tpng " (buffer-file-name))))

' :ide: PLANTUML: this file's SVG
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".svg"))) (compile (concat "plantuml -tsvg " (buffer-file-name))))

' :ide: PLANTUML: this file's PNG + display
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".png"))) (compile (concat "plantuml -tpng " (buffer-file-name) " && display " args)))

' :ide: PLANTUML: this file's PNG + VIEW
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".png"))) (shell-command (concat "plantuml -tpng " (buffer-file-name) " ")) (view-file-other-window args))

' :ide: PLANTUML: this file's SVG + VIEW
' . (let ((args (concat (file-name-sans-extension (buffer-file-name)) ".svg"))) (shell-command (concat "plantuml -tsvg " (buffer-file-name) " ")) (view-file-other-window args))

'
' Local Variables:
' mode: plantuml
' mode: snip-minor
' snip-show-inactive: t
' snip-mode: plantuml
' truncate-lines: t
' comment-start: "'"
' comment-end: ""
' End:
@enduml

Fig. 1 Documentation workflow

Initialize documentation

New article

  • Execute:

    sda chap new 'Chapter title'
    

This is equivalent to:

  • Execute:

    snn --mode rst --key title --value 'Chapter title' README-chapter-title.txt
    

New book

  • Make book directory

  • cd to book directory

  • Execute:

    sda init "Book Title"
    

This creates an empty README.txt and a doc subdirectory for building the full version of a documentation book with chapters.

Documentation output formats

Article format

sda readme README.txt              # => README.html
sda readme --format pdf README.txt # => README.pdf

Book format

sda make html                      # => doc/_build/html/
sda make latexpdf                  # => doc/_build/latex/

sda view html                      # xdg-open 'doc/_build/html/index.html'
sda view pdf                       # xdg-open "$(  echo doc/_build/latex/*.aux | sed 's,\.aux$,\.pdf,;1q' )"

Update documentation template structure

  • cd to doc-directory

  • Execute:

    sda update
    

This creates a new sub-directory doc-directory with a new documentation project using the title from the main README (see Fig. 2).

@startuml /' a0 '/
skinparam padding 1
partition "Update README template structure" {
start
:get **basename of working**
**directory** as update directory;
:get **title** from README.txt;
:* **create** update directory
* **change** to update directory;
:Keep original */.snippets//**;
:Initialize update directory
with */sphinx-doc-init.sh// title**;
:move_to_orig\ncompare updated files with original tree|
stop
}
@enduml

Fig. 2 SphinxDoc - update template structure

Any generated files, that are not present in the directory being updated, are moved there. Files that do not differ are deleted. (see Fig. 3).

@startuml /' a1 '/
skinparam padding 1
partition "move_to_orig - compare updated files with original tree" {
start
while (for each file in directory) is (do)
    if (file **not** in orig tree) then (yes)
        :mv "${file}" ../"${file}";
    elseif (is a directory?) then (yes)
        :move_to_orig "${file}"|
    elseif (no diff?) then (yes)
        :rm "${file}";
    endif
endwhile
:remove empty directories;
stop
}
@enduml

Fig. 3 SphinxDoc - compare updated files with original tree

Files that differ must be merged manually with M-x ediff-directories or kdiff3(1).

Document administration

Document administration is performed with sda, a shortcut link to sphinx-doc-admin.sh.

@startuml /' a0 '/
skinparam padding 1
partition "sphinx-doc-admin.sh" {
start
floating note right
sphinx-doc-admin.sh - Sphinx based documenation administration

usage: sphinx-doc-admin.sh [OPTIONS] COMMAND [COMMAND-OPTIONS] [COMMAND-ARGS]

OPTIONS
-d, --doc-dir  DOCDIR
--debug                do not execute commands
-v, --verbose

COMMANDS
init       [OPTIONS] [PROJECT-NAME]
update     [OPTIONS]
readme     [OPTIONS] [FILE]
make       [ARGS]
view       [FORMAT-OR-FILE]
automodule MODULE-OR-FILE ...
chapter    [SUB-COMMAND] [ARGS]

locate     [OPTIONS]

help

COMMAND MAKE
make       [ARGS]
Default target is //html//

COMMAND VIEW
view       [FORMAT-OR-FILE ..]
Formats are //html// and //pdf// (default: //html//).

COMMAND CHAPTER
chapter [SUB-COMMAND] [ARGS]
chapter new CHAPTER-FILENAME-OR-TOPIC
* Convert CHAPTER-TOPIC to a canonical name CANONICAL-CHAPTER-TOPIC
which is suitable as filename README-CANONICAL-CHAPTER-TOPIC.txt
* Generate README-CANONICAL-CHAPTER-TOPIC.txt, if it does not exist.

chapter add CHAPTER-FILENAME-OR-TOPIC
In addition to creating README-CANONICAL-CHAPTER-TOPIC.txt like
//chapter new//, register appropriate entries in control files:

.hgignore
${opt_doc_dir}/index-contents.snip
${opt_doc_dir}/doc_defs_standalone.inc
${opt_doc_dir}/Makefile
${opt_doc_dir}/doc_defs_combined.inc
README-chapter-topic.txt

chapter rollback [OPTIONS]

OPTIONS
-f, --force  ignore missing files

Restore documentation files from backups of last added
chapter

chapter clean
Delete documentation file backups of last added chapter

chapter remove CHAPTER-FILENAME-OR-TOPIC
Delete chapter from documentation files
end note
:configuration;
:option processing;
:Find directory with README.txt;
:determine command;
if (no command specified?) then (yes)
    :error message;
    :usage;
    end
endif
    if (command == init) then (yes)
    :call function
    command_init|
    elseif (command == update) then (yes)
    :call function
    command_update|
    elseif (command == readme) then (yes)
    :call function
    command_readme|
    elseif (command == make) then (yes)
    :call function
    command_make|
    elseif (command == view) then (yes)
    :call function
    command_view|
    elseif (command == automodule) then (yes)
    :call function
    command_automodule|
    elseif (command == chapter) then (yes)
    :call function
    command_chapter|
    elseif (command == locate) then (yes)
    :call function
    command_locate|
    elseif (command == help) then (yes)
    :call usage|
    else
    :error message;
    end
    endif
stop
} /' move before //stop//, if there are subsections '/
@enduml

Automodule files

Add automodule documentation files for python modules to the doc directory.

sda automodule MODULE-OR-FILE ...

@startuml /' a2 '/
skinparam padding 1
partition "automodule command" {
    start
    :set //--help// as default;
    :cd to //${opt_doc_dir}// directory;
    while (for each //module_or_file// argument) is (do)
        :construct module name
        - remove //.py//
        - translate ///// => //.//;
        if (automodule file exist) then (yes)
            :warning message;
        else
        :create automodule file;
        endif
    endwhile
    stop
}
@enduml

Chapters

Latest versions of the documentation have |:chapter:| symbol tags, which can be easily found with M-x symbol-tag-grep-find (usually defined as M-g).

Chapter administration entails a number of use cases:

@startuml /' u0 '/
skinparam padding 1
left to right direction
actor :User: as User
    usecase (generate new\nREADME-CTOPIC.txt from TOPIC\n[but do not integrate into book]) as CHPNEW
    usecase (generate new\nREADME-CTOPIC.txt\nfrom TOPIC\nand integrate into book) as CHPADD0
    usecase (integrate existing\nREADME-CTOPIC.txt) as CHPADD1
    usecase (a previous run\nof //sphinx-doc-admin.sh//\nwas interrupted) as CHPADDCONT
    usecase (some of the control files\nare already modified) as CTRLMOD
    usecase (run\n//chapter new 'TOPIC'//) as RCHAPNEWTOPIC
    usecase (run\n//chapter add README-CTOPIC.txt//) as RCHAPADDFILE
    usecase (update control files) as UPDCTRL
    User         --> CHPNEW
    User         --> CHPADD0
    User         --> CHPADD1
    User         --> CHPADDCONT
    User         --> CTRLMOD
    CHPNEW       --|> RCHAPNEWTOPIC
    CHPADD0 "1"  --|> RCHAPNEWTOPIC
    CHPADD0 "2"  --|> CHPADD1
    CHPADD1      --|> RCHAPADDFILE
    CHPADDCONT   --|> RCHAPADDFILE
    CTRLMOD      --|> RCHAPADDFILE
    RCHAPADDFILE --|> UPDCTRL
    usecase (rollback control files\nbefore commit with\n//chapter rollback//) as CHPROLLBACK
    User --> CHPROLLBACK
    usecase (delete control files with\n//chapter clean//) as CHPCLEAN
    User --> CHPCLEAN
    usecase (remove chapter reference\nfrom control files with\n//chapter remove FILEN-OR-TOPIC//) as CHPREMOVE
    User --> CHPREMOVE
@enduml

sda chapter SUB-COMMAND

@startuml /' a1 '/
skinparam padding 1
partition "chapter command" {
    start
    floating note right
    control files:
    * .hgignore
    * ${opt_doc_dir}/index-contents.snip
    * ${opt_doc_dir}/doc_defs_standalone.inc
    * ${opt_doc_dir}/Makefile
    * ${opt_doc_dir}/doc_defs_combined.inc
    end note
    if (no sub command specified?) then (yes)
        :error message;
        end
    endif
    if (sub command is valid?) then (yes)
        else
        :error message;
        end
        endif
    :cd to top directory with README.txt;
    if (sub command == new or sub command == add?) then (yes)
    if (//README-CANONICAL-CHAPTER-TOPIC.txt// does not exist in current directory?) then (yes)
        :snn //--mode// rst //--key// title //--value// 'Chapter topic' //README-CANONICAL-CHAPTER-TOPIC.txt//;
    endif
    endif
    if (sub command == add?) then (yes)
    while (for file in **control files**) is (do)
                if (chapter reference does\nnot exist in **file**) then (yes)
                    :write a backup
                    file **file-000**;
                    :put new file entry
                    at the right place;
                endif
    endwhile
    elseif (sub command == rollback?) then (yes)
    if (all backup files found?) then (yes)
        while (for each control file) is (do)
            :overwrite file with
            backup from file-000;
        endwhile
    else
        :error message;
        end
    endif
    elseif (sub command == clean?) then (yes)
    while (for each control file) is (do)
        :delete backup file-000;
    endwhile
    elseif (sub command == remove?) then (yes)
    if (chapter file does not esxist?) then (yes)
        end
    endif
    while (for _file in FILES) is (do)
        :remove chapter entry from _file;
        if (there was an entry?) then (yes)
            if (there is no backup file?) then (yes)
                :make backup;
            endif
            :activate new _file;
        endif
    endwhile
    endif
stop
}
@enduml

Adding a chapter

The following steps are automatically performed with:

sda chapter add topic
  • Create a new README-topic.txt:

    snn --mode rst README-topic.txt
    
  • Add a new entry to the variable CHAPTERS in doc/Makefile:

    CHAPTERS += ../README-topic.txt
    
  • Add the chapter file base topic to the toctree directive in doc/index-contents.snip:

    .. toctree::
       :maxdepth: 1
    
       topic
    

    Add a rule to .hgignore:

    ^doc/topic\.rst\.auto$
    

    Define a document reference in doc/doc_defs_standalone.inc:

    .. |chapter-topic|            replace:: document :file:`README-topic`
    

    Define a chapter reference in doc/doc_defs_combined.inc:

    .. |chapter-topic|            replace:: chapter :doc:`topic`
    

View processed documents

sda view FORMAT-OR-FILE

sda view html
sda view pdf

@startuml /' a4 '/
skinparam padding 1
partition "view command" {
    start
    :set //html// as default view format;
    while (for each _format_or_file in FORMATS-OR-FILES) is (do)
        if (_format_or_file does **not** exist) then (yes)
            if (_format_or_file matches //html//) then (yes)
                :use //${opt_doc_dir}/_build/html/index.html// as file;
            elseif (_format_or_file matches //pdf//) then (yes)
                :use //${opt_doc_dir}/_build/latex/book.pdf// as file;
            endif
        endif
        if (_format_or_file exists) then (yes)
            :call xdg-open with _format_or_file;
        else
        :error message;
        endif
    endwhile
    stop
}
@enduml

Command handlers for backends

@startuml /' a3 '/
skinparam padding 1
partition "init command" {
    start
    :exec sphinx-doc-init.sh ${1+"$@"}|
    stop
}
partition "update command" {
    start
    :exec sphinx-doc-update.sh ${1+"$@"}|
    stop
}
partition "readme command" {
    start
    :exec sphinx-readme.sh --doc-dir "${opt_doc_dir}" ${1+"$@"}|
    stop
}
partition "make command" {
    start
    :set //html// as default target;
    :cd to //${opt_doc_dir}// directory;
    :call make(1) with args|
    stop
}
partition "locate command" {
    start
    :exec sphinx-doc-locate.sh ${1+"$@"}|
    stop
}
@enduml

Structural specification

  • reStructuredText is a markup language specification in the class of wiki markup languages. (Examples for other markup languages are HTML, TeX/LaTex, NROFF). reStructuredText is the official Python documentation markup.

  • UML is used for documenting programs. It is created from textual descriptions with PlantUML. See chapter Unified Modeling Language for details.

  • Docutils is the reference library for translating reStructuredText markup into other formats like HTML/PDF/EPUB.

  • The document generator Sphinx extends Docutils and the reStructuredText specification with roles and directives. There are also various extensions to integrate other markup specifications (e.g. PlantUML, Pygments for highlighting). See chapter Sphinx Documentation Generator for further details .

    The program sphinx-build(1) generates HTML/PDF/EPUB documentation from reStructuredText documents and doc strings of python(1) modules. It is also used in the command sda readme (sphinx-readme.sh) to generate standalone HTML/PDF/EPUB from a single README file.

@startuml
' |:here:|
hide circle
hide members
skinparam padding 1

!definelong GENERATORS
  +HTML()
  +PDF()
  +EPUB()
!enddefinelong

package "Specifications" as PSPEC {  /' |:here:||:sec:| '/
  class "UML"                     as UML
  class "UML Diagram"             as UMLDIA
  class "reStructuredText"        as RST

  UML <|.. UMLDIA : <<illustrates>>
}

package "Documents" as PDOC { /' |:sec:| '/
  class "Python <i>__</i>doc__"   as PYDOC
  class "README.txt"              as README
  class "Documentation"           as DOC

  PYDOC  "*" --o DOC
  README "*" --o DOC
}

package "Generators" as PGEN { /' |:sec:| '/

  object "PlantUML"                as PUML {
    PNG()
    SVG()
  }
  show PUML members

  object "Docutils"                as DUT {
    GENERATORS
  }
  show DUT members

  object "Sphinx"                  as SPH {
    +extension[]
    GENERATORS
  }
  show SPH members

  class "Generator" as GEN {
    generates()
  }
  show GEN methods

  DUT  ..|> GEN
  SPH  ..|> GEN
  DUT  <|-- SPH : <<extends>>
  PUML <..  SPH : <<integrates>>

}

package "Output" as POUT { /' |:sec:| '/
  object "README.html"              as RHTML
  object "index.html"               as IHTML
}

' |:here:||:sec:| Relations

UMLDIA <|.. PUML : <<implements>>

RST <|.. DUT : <<implements>>
RST --o  PYDOC
RST --o  README

DOC    <|.. IHTML
README <|.. RHTML

(README, RHTML) .. GEN
(DOC, IHTML) ..    GEN

' |:here:|
@enduml

README chapters

@startuml

skinparam padding 1

' |:here:| definitions

!define dir_top <i>dir</i> = .
!define dir_doc <i>dir</i> = doc
!define parts_eq <i>parts</i> =
!define dir_top_parts dir_top, parts_eq
!define dir_doc_parts dir_doc, parts_eq

' parts definitions

!definelong R_PARTS
  dir_top_parts
  - top
  - title
  - contents
  - abstract
  - body
  - defs
  - bottom
!enddefinelong

!definelong I_PARTS
  dir_doc_parts
  - top
  - title
  - abstract
  - index-contents.snip
  - index-header.snip
  - defs
  - index-footer.snip
  - bottom
!enddefinelong

!definelong O_PARTS
  dir_doc_parts
  - top
  - overview-header.snip
  - body
  - defs
  - overview-footer.snip
  - bottom
!enddefinelong

!definelong C_PARTS
  dir_doc_parts
  - top
  - title
  - abstract
  - chapter-header.snip
  - body
  - defs
  - chapter-footer.snip
  - bottom
!enddefinelong

package "Combined output" as OUTC { /' |:here:| '/
  object "**index.html**" as ih {
    dir = doc/_build/html
  }
  object "Document.pdf" as ip {
    dir = doc/_build/latex
  }
}

package "Single chapter output" as OUTS { /' |:sec:| '/
  object "README.pdf" as RP {
    dir_top
  }
  object "**README.html**" as RH {
    dir_top
  }
  object "README-topic1.html" as RH1 {
    dir_top
  }
  object "README-topic2.html" as RH2 {
    dir_top
  }
}

package "Chapters" as IC { /' |:sec:| '/
  object "**README.txt**" as R {
    R_PARTS
  }
  object "README-topic1.txt" as RT1 {
    R_PARTS
  }
  object "README-topic2.txt" as RT2 {
    R_PARTS
  }
}

package "Index" as PI { /' |:sec:| '/
  object "**index.rst**" as i {
    I_PARTS
  }
  object "toctree" as TT {
   - overview
   - topic1
   - topic2
  }
}

package "Generated chapters" as PC { /' |:sec:| '/
  object "overview.rst" as O {
    O_PARTS
  }
  object "topic1.rst" as t1 {
    C_PARTS
  }
  object "topic2.rst" as t2 {
    C_PARTS
  }
}

' |:here:| Helper Relations

ih  -[hidden] ip
ip  -[hidden] RP
RP  -[hidden] RH
RH  -[hidden] RH1
RH1 -[hidden] RH2

' |:here:| Single Chapter Output

RH  ..|> R   : < sphinx-build\nsda readme
RP  ..|> R   : < sphinx-build\nsda readme\n--format pdf
RH1 ..|> RT1 : < sphinx-build\nsda readme
RH2 ..|> RT2 : < sphinx-build\nsda readme

' |:sec:| Combined Documentation Chapters

R   <|..  i  : snippets\nsnr --key doc_index >
R   <|..  O  : snippets\nsnr --key doc_overview >
RT1 <|..  t1 : snippets\nsnr --key doc_chapter >
RT2 <|..  t2 : snippets\nsnr --key doc_chapter >

' |:sec:| Combined Documentation Output

ih ..|> i : < sphinx-build\nmake html
ip ..|> i : < sphinx-build\nmake latexpdf

' |:sec:| toctree references

i   o-    TT
TT  .u.>  O
TT  .u.>  t1
TT  .u.>  t2

' |:here:|

@enduml

README snippets

@startuml
skinparam padding 2
hide methods

!define SNIP <b><color:blue>rem</color></b>
!define SKIP <b><color:red>skip</color></b>
!define QUOTE <b><color:black>quote</color></b>
!define REM <b><color:black>rem</color></b>
!define INDENT <b><color:black>indent</color></b>

!definelong NO_OUT_BLOCKS
!enddefinelong

!definelong OUT_BLOCKS
!enddefinelong

package "README snippet setup" as RSS {

' |:here:|

class "rst_new" as RSNP {
 -- template aliases --
 snip_quote    : alias QUOTE / REM

 .. doc_index ..
 doc_index     : block alias SNIP / SKIP
 not_doc_index : block alias SKIP / SNIP
 di_indent     : alias INDENT / REM
 not_di_indent : alias REM / INDENT

 .. minimal ..
 minimal     : block alias SNIP / SKIP
 not_minimal : block alias SKIP / SNIP
}

hide RIND circle
hide RCHP circle
hide RMIN circle

class "README.txt (doc_index)" as RIND {
  doc_index     = SNIP
  not_doc_index = SKIP
  di_indent     = INDENT
  not_di_indent = REM
  minimal       = SKIP
  not_minimal   = SNIP
  snip_quote    = QUOTE
  -- output block aliases --
  .. doc type ..
  doc_standalone
  not_doc_standalone
  doc_index
  not_doc_index
  doc_overview
  not_doc_overview
  doc_chapter
  not_doc_chapter
  .. part ..
  part_top
  part_title
  part_contents
  part_abstract
  part_body
  part_defs
  part_bottom
}

class "README.txt (chapter)" as RCHP {
  doc_index     = SKIP
  not_doc_index = SNIP
  di_indent     = REM
  not_di_indent = INDENT
  minimal       = SKIP
  not_minimal   = SNIP
  snip_quote    = QUOTE
  -- output block aliases --
  .. doc type ..
  doc_standalone
  not_doc_standalone
  doc_index
  not_doc_index
  doc_overview
  not_doc_overview
  doc_chapter
  not_doc_chapter
  .. part ..
  part_top
  part_title
  part_contents
  part_abstract
  part_body
  part_defs
  part_bottom
}

class "README.txt (minimal)" as RMIN {
  doc_index     = SKIP
  not_doc_index = SNIP
  di_indent     = REM
  not_di_indent = INDENT
  minimal       = SNIP
  not_minimal   = SKIP
  snip_quote    = REM
  -- output block aliases --
  .. doc type ..
  .. part ..
}

' |:here:|
}

RSNP <|.. RIND : snn ~--mode rst\n~--key doc_index >
RSNP <|.. RCHP : snn ~--mode rst >
RSNP <|.. RMIN : snn ~--mode rst\n~--key minmal >

' |:here:|
@enduml

How to properly move chapter files and sections

Rename chapter file in same document directory

@startuml
left to right direction

package "Document **doc**" as doc_old {
    object "**chapter-old**" as chp_old {
    }
    object "**chapter-new**" as chp_new {
    }

    chp_old --> chp_new : renamed to
}
@enduml

  • Move README-chapter-old.txt to README-chapter-new.txt.

  • Execute M-x grep-find RET chapter-old RET.
    Rename info for chapter-old to info for chapter-new.
  • Clean + compile doc-new.
    Analyze error messages and correct errors.

Move chapter file to other document directory

@startuml
left to right direction

package "Document **doc-old**" as doc_old {
    object "**chapter-old**" as chp_old {
    }
}

package "Document **doc-new**" as doc_new {
    object "**chapter-new**" as chp_new {
    }
}

chp_old --> chp_new : moved to
@enduml

  • Move README-chapter-old.txt from doc-old to README-chapter-new.txt in doc-new.

  • Execute M-x grep-find RET chapter-old RET in doc-old.
    Keep document references from doc/doc_def_standalone.inc in doc/doc_def.inc.
    Move and rename info for chapter-old from doc-old to doc-new.
  • Clean + compile doc-new.
    Analyze error messages and correct errors.
    E.g. get missing substitutions/references/images/data from doc-old.
  • Clean + compile doc-old.
    Analyze error messages and correct errors.

How to move a section from one chapter file to another chapter file

@startuml
left to right direction

package "Document **doc-old**" as doc_old {
    package "Chapter **old**" as chp_old {
        object "Section **old**" as sec_old {
        }
    }
}

package "Document **doc-new**" as doc_new {
    package "Chapter **new**" as chp_new {
        object "Section **new**" as sec_new {
        }
    }
}

sec_old --> sec_new : moved to
@enduml

  • Remove section-old section from chapter-old.
    Insert as section-new in chapter-new.
  • Clean + compile doc-new.
    Analyze error messages and correct errors.
    E.g. get missing substitutions/references/images/data from doc-old.
  • Clean + compile doc-old.
    Analyze error messages and correct errors.

Traceability of section modifications

|:todo:| incorrect, needs to be updated

Case-by-case analysis:

  1. Move sections before chapter documents:

    • Section section-old moved from chapter-old to chapter-new in doc-old
    • chapter-new moved from doc-old to chapter-new in doc-new
    • chapter-new moved to chapter-new-new in doc-new

    Consequences:

    • doc-old no longer exists. It must be looked up in the document processing logs.
    • doc-new no longer exists. It must be looked up in the document processing logs.
    • The version history of the section modification resides in the old repositories (doc-old, :doc-new).
  2. Move chapter documents before sections:

    • doc-old moved to doc-old-new
    • doc-new moved to doc-new-new
    • Section section moved from doc-old-new to doc-new-new

    Consequences:

    • The version history of the section modification resides in the new repositories (doc-old-new, :doc-new-new), which is better.