Ich möchte eine Datenbank erstellen, die aus nummerierten TeX-Codeblöcken besteht. Insbesondere möchte ich so etwas tun \mycommand{counterName}{Some text}
und irgendwo einen neuen Eintrag speichern, um ihn Some Text
später an anderer Stelle im Dokument zu verwenden. Es CounterName
gibt einen Zähler, auf den ich zurückgreifen kann, um den in das Dokument eingefügten Text abzurufen:
\newcounter{a}
\mycommand{a}{The first line}
\stepcounter{a}
\mycommand{a}{The second line}
.........
print{2}
Und TeX wird „Die zweite Zeile“ produzieren.
Ich suche nach etwas wie glossaries
einem Paket, aber mit der Möglichkeit, nicht die ganze Liste auf einmal zu erstellen, sondern nur einen bestimmten Eintrag, sodass es aussieht, als \print{n}
würde der Befehl einfach durch den Text im Befehl ersetzt \mycommand{n}{TEXT}
.
Beim Durchsuchen von TeX.SX habe ich einige Antworten zu datatool
Paketen und Lua
Codes gefunden, aber keine Lösung, die ich anwenden kann.
datatool
Ich wäre Ihnen für eine kurze Erklärung zur Verwendung glossaries
oder etwas Ähnlichem zu diesem Thema sehr dankbar.
Antwort1
Da Sie datatool
und erwähnt haben glossaries
, hier einige Alternativen.
Bei datatool
besteht die einfachste Methode darin, alle Einträge in inkrementeller Reihenfolge (ohne Verwendung eines Zählers) zu definieren. Die Indizierung erfolgt über die Zeilennummer.
\documentclass{article}
\usepackage{datatool}
\DTLnewdb{data}
\newcommand{\addline}[1]{%
\DTLnewrow{data}%
\DTLnewdbentry{data}{Text}{#1}%
}
\newcommand{\print}[1]{%
\DTLgetvalue{\thisval}{data}{#1}{1}%
\thisval
}
\addline{The first line}
\addline{The second line}
\begin{document}
Line 2: \print{2}.
All lines:
\DTLforeach*{data}{\Text=Text}{\DTLcurrentindex. \Text.\par}
\end{document}
Das Ergebnis:
Zeile 2: Die zweite Zeile.
Alle Zeilen:
1. Die erste Zeile.
2. Die zweite Zeile.
Wenn Sie Ihre Einträge ungeordnet über einen Zähler definieren möchten, ist dies mit einer zusätzlichen Spalte möglich:
\documentclass{article}
\usepackage{datatool}
\DTLnewdb{data}
\newcommand{\addline}[2]{%
\DTLnewrow{data}%
\dtlexpandnewvalue
\DTLnewdbentry{data}{Index}{\the\value{#1}}%
\dtlnoexpandnewvalue
\DTLnewdbentry{data}{Text}{#2}%
}
\newcommand{\print}[1]{%
\dtlgetrowindex{\thisrowidx}{data}{1}{#1}%
\ifx\thisrowidx\dtlnovalue
Not found!%
\else
\DTLgetvalue{\thisval}{data}{\thisrowidx}{2}%
\thisval
\fi
}
\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}
\setcounter{a}{1}
\addline{a}{The first line}
\begin{document}
Line 2: \print{2}.
All lines:
\DTLforeach*{data}{\theIndex=Index,\Text=Text}{\theIndex. \Text.\par}
\end{document}
Das Ergebnis:
Zeile 2: Die zweite Zeile.
Alle Zeilen:
2. Die zweite Zeile.
1. Die erste Zeile.
Die Liste ist nun nicht mehr numerisch geordnet, sondern entspricht der Reihenfolge, in der die Blöcke definiert wurden. Sie können sie sortieren, bevor Sie die Liste anzeigen:
\DTLsort{Index}{data}
\DTLforeach*{data}{\theIndex=Index,\Text=Text}{\theIndex. \Text.\par}
Zeile 2: Die zweite Zeile.
Alle Zeilen:
1. Die erste Zeile.
2. Die zweite Zeile.
Hier ist ein glossaries
Ansatz:
\documentclass{article}
\usepackage{glossaries-extra}
\glssetexpandfield{name}
\newcommand{\addline}[2]{%
\edef\thisidx{\the\value{#1}}%
\newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}
\newcommand{\print}[1]{%
\glsentrydesc{#1}%
}
\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}
\setcounter{a}{1}
\addline{a}{The first line}
\begin{document}
Line 2: \print{2}.
All lines:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printunsrtglossary[style=index]
\end{document}
Das Ergebnis:
Auch hier erfolgt die Liste in der Reihenfolge der Definition. Wenn Sie die Liste sortiert haben möchten, können Sie stattdessen Folgendes verwenden:
\documentclass{article}
\usepackage[automake,nopostdot]{glossaries}
\makeglossaries
\glssetexpandfield{name}
\newcommand{\addline}[2]{%
\edef\thisidx{\the\value{#1}}%
\newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}
\newcommand{\print}[1]{%
\glsentrydesc{#1}\glsadd{#1}%
}
\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}
\setcounter{a}{1}
\addline{a}{The first line}
\begin{document}
Line 2: \print{2}.
All lines:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printglossary[style=index,nonumberlist]
\end{document}
Das Ergebnis:
Zeile 2: Die zweite Zeile.
Alle Zeilen:
2 Die zweite Zeile
Dies listet nur den Eintrag auf, der (mit ) indiziert wurde \glsadd
. Wenn Sie möchten, dass alle Einträge aufgelistet werden, verwenden Sie \glsaddall
(nachdem alle Einträge definiert wurden).
\documentclass{article}
\usepackage[automake,nopostdot]{glossaries}
\makeglossaries
\glssetexpandfield{name}
\newcommand{\addline}[2]{%
\edef\thisidx{\the\value{#1}}%
\newglossaryentry{\thisidx}{name={\thisidx},description={#2}}%
}
\newcommand{\print}[1]{%
\glsentrydesc{#1}%
}
\newcounter{a}
\setcounter{a}{2}
\addline{a}{The second line}
\setcounter{a}{1}
\addline{a}{The first line}
\glsaddall
\begin{document}
Line 2: \print{2}.
All lines:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glossarysection}[2][]{}
\printglossary[style=index,nonumberlist]
\end{document}
Das Ergebnis:
Zeile 2: Die zweite Zeile.
Alle Zeilen:
1 Die erste Zeile
2 Die zweite Zeile
Erweiterung
Es ist wichtig, dass der Indexierungswert \the\value{#1}
vor dem Speichern vollständig erweitert wird, da er sich sonst ständig ändert, wenn sich der Wert des Zählers ändert. Sowohl als datatool
auch glossaries
gibt es eine Möglichkeit, die Erweiterung beim Hinzufügen/Definieren eines neuen Eintrags ein- oder auszuschalten.
Bei datatool
wird die Erweiterung mit eingeschaltet \dtlexpandnewvalue
. Bei glossaries
wird die Erweiterung für ein bestimmtes Feld mit eingeschaltet.\glssetexpandfield{
Feldbezeichnung}
.
Der Code, den Sie (im letzten Argument von \addline
) hinzufügen möchten, enthält möglicherweise instabile Befehle. In diesem Fall ist es wichtig, den Wert nicht zu erweitern. Mit datatool
wird die Erweiterung mit wieder ausgeschaltet \dtlnoexpandnewvalue
. Mit glossaries
wird der Wert im description
Schlüssel gespeichert und die Erweiterung ist für dieses Feld standardmäßig deaktiviert.
Antwort2
Das Folgende basiert auf der Annahme, \printlistitem
dassnach \addlistitem
:
\documentclass{article}
\usepackage{xparse}
\newcounter{listitem}
\NewDocumentCommand{\addlistitem}{o m}{%
\IfValueTF{#1}
{\expandafter\def\csname #1-list\endcsname{#2}}
{\stepcounter{listitem}%
\begingroup\edef\x{\endgroup\noexpand\expandafter
\def\noexpand\csname \thelistitem-list\noexpand\endcsname}%
\x{#2}}%
}
\newcommand{\printlistitem}[1]{%
\ifcsname #1-list\endcsname
\csname #1-list\endcsname
\else
Item~#1 does not exist.
\fi
}
\begin{document}
\addlistitem{The first line}% 1
\addlistitem[B]{The second line}% C
\addlistitem{The third line}% 2
\printlistitem{2}
\printlistitem{1}
\printlistitem{3}
\printlistitem{B}
\end{document}
Es können weitere Modifikationen hinzugefügt werden, darunter Fehlerprüfung/-behandlung und Modifikationen für die Handhabung von Rückwärtsreferenzierungen (mithilfe eines \label
-Setups \ref
).
Möglicherweise möchten Sie ein hinzufügen, \printallitems
um alle Elemente aufzulisten, die Sie in Form eines Inhaltsverzeichnisses hinzugefügt haben. Das folgende Beispiel ahmt dies nach, indem jedes \addlistitem
als festgelegt wird \section
. Sie können die Präsentation nach Bedarf verfeinern:
\documentclass{article}
\usepackage{xparse,tocloft}
\newcounter{listitem}
\NewDocumentCommand{\addlistitem}{o m}{%
\IfValueTF{#1}
{\expandafter\def\csname #1-list\endcsname{#2}%
\addcontentsline{los}{listitem}{\protect\numberline{#1} #2}}
{\stepcounter{listitem}%
\begingroup\edef\x{\endgroup\noexpand\expandafter
\def\noexpand\csname \thelistitem-list\noexpand\endcsname}%
\x{#2}%
\addcontentsline{los}{listitem}{\protect\numberline{\thelistitem} #2}}%
}
\newcommand{\printlistitem}[1]{%
\ifcsname #1-list\endcsname
\csname #1-list\endcsname
\else
Item~#1 does not exist.
\fi
}
\makeatletter
\let\l@listitem\l@section
\newcommand{\printallitems}{{%
\renewcommand{\cftsecfont}{\mdseries}% Add more ToC-related tuning here
\@starttoc{los}}}
\makeatother
\begin{document}
\printallitems
\bigskip
\addlistitem{The first line}% 1
\addlistitem[B]{The second line}% C
\addlistitem{The third line}% 2
\printlistitem{2}
\printlistitem{1}
\printlistitem{3}
\printlistitem{B}
\end{document}