Skripte


Das LaTeX-Leben automatisieren
Ekkart Kleinod  • 

Graphisches Inhaltsverzeichnis

Ein awk-Skript, das von de.comp.text.tex inspiriert wurde, das aus dem Inhaltsverzeichnis (toc-Datei) eine dot-Datei erstellt, die mit dot (aus dem graphviz-Paket) in ein Bild umgewandelt werden kann.

Theorie

Nutzung: das Skript kopieren und in eine Datei speichern oder den Download-Link benutzen. Der Name der Datei ist egal, der Aufruf muss dann entsprechend angepasst werden. Im Folgenden heißt die Datei toc2dot.awk. Dann das Script aufrufen. Als Parameter den Scriptnamen, den Dateinamen der toc-Datei sowie den Dateinamen der dot-Datei angeben.

$> awk --file=<scriptname> <toc> > <dot>

Beim Aufruf können folgende Optionen angegeben werden:

  • title für die Angabe eines Titels, der Text wird für den obersten Knoten verwendet, default: "Top"
  • style zur Auswahl des Graphstils, möglich sind graph und tree, default: "graph" (die erzeugten Graphen irgendwie gleich aus, weiß nicht genau, was der Parameter macht)
$> awk --file=<scriptname> --assign=title="<titel>" --assign=style="tree" <toc> > <dot>

Praxis

Als Beispiel verwenden wir das Inhaltsverzeichnis des changes-Pakets. Das Inhaltsverzeichnis liegt für eigene Versuche zum Download vor: Download Inhaltsverzeichnis. Der Dateiname ist toc2dot_example.toc.

Das Inhaltsverzeichnis sieht in LaTeX gesetzt wie folgt aus:

Screenshot des LaTeX-Inhaltsverzeichnis.

Der Aufruf ohne Optionen:

$> awk --file=toc2dot.awk toc2dot_example.toc > toc2dot_example_simple.dot
$> dot -Tpng -o toc2dot_example_simple.png toc2dot_example_simple.dot

ergibt:

Ergebnis der Generierung ohne Optionen als Bild.

Es ist zu sehen, dass noch nicht alles rund läuft: Markup innerhalb der Überschriften wird gelöscht inklusive des Texts.

Der Aufruf mit der Option "title":

$> awk --file=toc2dot.awk --assign=title="Das changes-Paket." toc2dot_example.toc > toc2dot_example_title.dot
$> dot -Tpng -o toc2dot_example_title.png toc2dot_example_title.dot

ergibt:

Ergebnis der Generierung mit Option "title" als Bild.

Der Titel wird in den obersten Knoten eingetragen.

Der Aufruf mit der Option "style":

$> awk --file=toc2dot.awk --assign=style=tree toc2dot_example.toc > toc2dot_example_style.dot
$> dot -Tpng -o toc2dot_example_style.png toc2dot_example_style.dot

ergibt:

Ergebnis der Generierung mit Option "style" als Bild.

Irgendwie ändert sich das Aussehen nicht.

Code

Download: Download toc2dot.

# converts latex toc file to dot input file
# with help from de.comp.text.tex
# usage:
#  awk --file=toc2dot.awk <tocfile> > <dotfile>
# assign options with --assign or -v:
#  title: awk --file=toc2dot.awk --assign=title="<title>" <tocfile> > <dotfile>
#   default = "Top"
#  style: awk --file=toc2dot.awk --assign=style="[graph|tree]" <tocfile> > <dotfile>
#   default = "tree"

# at begin of processing start graph
BEGIN {
    # define patterns
    pattern_color = ", color=%s, style=filled"
    pattern_entry = "\t\"%s\" [label=\"%s%s\", shape=%s%s];\n"
    pattern_link = "\t\"%s\" -> \"%s\";\n"
    pattern_page = "\\nSeite %d"

    # start graph
    print "digraph G {"
    print "\t\tgraph [ordering=out]"

    # draw tree or graph
    isGraph = (style == "graph")

    # print title (top of tree/graph)
    title_ref = "main"
    title_txt = (title == "") ? "Top" : title
    print_ref(title_ref, title_txt, "", -1, "egg", "lightblue")
}

# convert and split contentsline
function split_contentsline(cl_index) {
    # convert special chars (better solution?)
    gsub(/\\IeC \{\\"a\}/, "ä", $0)
    gsub(/\\IeC \{\\"A\}/, "Ä", $0)
    gsub(/\\IeC \{\\"o\}/, "ö", $0)
    gsub(/\\IeC \{\\"O\}/, "Ö", $0)
    gsub(/\\IeC \{\\"u\}/, "ü", $0)
    gsub(/\\IeC \{\\"U\}/, "Ü", $0)
    gsub(/"`/, "\\\"", $0)
    gsub(/"'/, "\\\"", $0)

    split(substr($0, 1, length($0) - 1), arr_content, "}{")
    return arr_content[cl_index]
}

# get unique reference from contentsline
function contentsline_ref() {
    return (isGraph) ? contentsline_txt() : split_contentsline(4)
}

# get node text from contentsline
function contentsline_txt() {
    # text may contain \numberline{...}, delete this
    txt = split_contentsline(2)
    sub(/\\numberline \{.*\}/, "", txt)
    return txt
}

# get page from contentsline
function contentsline_page() {
    return split_contentsline(3)
}

# print node definition and pattern_link pattern_entry
function print_ref(ref, txt, parent, page, shape, color) {
    page_txt = (page <= 0) ?  "" : sprintf(pattern_page, page);
    color_txt = (color == "") ? "" : sprintf(pattern_color, color);

    printf pattern_entry, ref, txt, page_txt, shape, color_txt
    if (parent != "")
        printf pattern_link, parent, ref
    else
        if (ref != title_ref)
            printf pattern_link, title_ref, ref
}

# matching the different content
/\\contentsline \{part\}/ {
    part_ref = contentsline_ref()
    print_ref(part_ref, contentsline_txt(), "", contentsline_page(), "box")
}

/\\contentsline \{chapter\}/ {
    chapter_ref = contentsline_ref()
    print_ref(chapter_ref, contentsline_txt(), part_ref, contentsline_page(), "box")
}

/\\contentsline \{section\}/ {
    section_ref = contentsline_ref()
    print_ref(section_ref, contentsline_txt(), chapter_ref, contentsline_page(), "box", "lightsalmon")
}

/\\contentsline \{subsection\}/ {
    subsection_ref = contentsline_ref()
    print_ref(subsection_ref, contentsline_txt(), section_ref, contentsline_page(), "box", "lightseagreen")
}

/\\contentsline \{subsubsection\}/ {
    subsubsection_ref = contentsline_ref()
    print_ref(subsubsection_ref, contentsline_txt(), subsection_ref, contentsline_page(), "box", "lightcyan")
}

/\\contentsline \{paragraph\}/ {
    paragraph_ref = contentsline_ref()
    print_ref(paragraph_ref, contentsline_txt(), subsubsection_ref, contentsline_page(), "ellipse")
}

# at end of processing close graph
END {
    print "}"
}

# EOF