我想创建一个由 TeX 代码编号块组成的数据库。具体来说,我想做类似的事情\mycommand{counterName}{Some text}
,将新条目保存在某处,以便Some Text
在文档的另一部分中使用。这CounterName
是一个计数器,我可以参考它来获取插入文档的文本:
\newcounter{a}
\mycommand{a}{The first line}
\stepcounter{a}
\mycommand{a}{The second line}
.........
print{2}
TeX 将生成“第二行”。
我正在寻找类似glossaries
包的东西,但能够一次生成非所有列表,而是生成特定条目,因此看起来命令\print{n}
只是由命令中的文本替换\mycommand{n}{TEXT}
。
通过搜索 TeX.SX,我找到了一些关于datatool
包和Lua
代码的答案,但还没有找到我可以应用的解决方案。
我将非常感激关于如何使用或类似内容的简单datatool
说明glossaries
。
答案1
既然您提到了datatool
和glossaries
,这里有一些替代方案。
使用datatool
,最简单的方法需要按递增顺序定义所有条目(不使用计数器)。行号提供索引。
\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}
得出的结果为:
第 2 行:第二行。
所有行:
1. 第一行。2
. 第二行。
如果您想使用计数器来定义无序条目,则可以使用附加列来完成:
\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}
得出的结果为:
第 2 行:第二行。
所有行:
2。第二行。1
。第一行。
该列表现在不按数字顺序排列,但与块定义的顺序相匹配。您可以在显示列表之前对它们进行排序:
\DTLsort{Index}{data}
\DTLforeach*{data}{\theIndex=Index,\Text=Text}{\theIndex. \Text.\par}
第 2 行:第二行。
所有行:
1. 第一行。2
. 第二行。
这里有一种glossaries
方法:
\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}
得出的结果为:
再次按定义顺序列出。如果您希望列表排序,可以使用以下命令:
\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}
得出的结果为:
第 2 行:第二行。
所有行:
2 第二行
这仅列出已编入索引的条目(\glsadd
使用 )。如果要列出所有条目,请使用\glsaddall
(在所有条目都已定义之后)。
\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}
得出的结果为:
第 2 行:第二行。
所有行:
1 第一行
2 第二行
扩张
索引值\the\value{#1}
在存储之前必须完全展开,否则它会随着计数器值的变化而不断变化。datatool
和glossaries
都有在添加/定义新条目时打开或关闭展开的方法。
在 的情况下datatool
,使用 开启扩展\dtlexpandnewvalue
。在 的情况下glossaries
,使用 开启特定字段的扩展\glssetexpandfield{
字段标签}
。
您要添加的代码(在 的最后一个参数中\addline
)可能包含脆弱的命令,在这种情况下,重要的是不要扩展值。使用datatool
,扩展将再次使用 来关闭\dtlnoexpandnewvalue
。使用glossaries
,值将存储在description
键中,并且默认情况下该字段的扩展处于关闭状态。
答案2
以下基于以下假设\printlistitem
:后 \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}
可以添加更多修改,包括错误检查/处理和修改它以处理反向引用(使用\label
-\ref
设置)。
您可能有兴趣添加一个,\printallitems
以目录的形式列出您添加的所有项目。以下示例通过将每个\addlistitem
项目设置为来模拟此\section
操作。您可以根据需要对演示文稿进行改进:
\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}