我正在编写一份文档,该文档以枚举列表的形式列出操作和预期结果。有些操作值得注意,有些结果也值得注意。我希望列出值得注意的操作和结果的标签,其中值得注意的程度由定义操作和结果时使用的带星号的操作/结果宏来确定,以避免手动排版。当前 MWE:
\documentclass{article}
\usepackage{enumitem}
\newlist{actions}{enumerate}{1}
\setlist[actions, 1]{label=A\arabic*}
\newlist{checks}{enumerate}{1}
\setlist[checks, 1]{label=R\arabic*}
\usepackage{xparse}
\NewDocumentCommand{\action}{s m}{\IfBooleanTF #1 {\item\emph{#2}}{\item #2}}
\NewDocumentCommand{\result}{s m}{\IfBooleanTF #1 {\item\emph{#2}}{\item #2}}
\begin{document}
\subsection{First of many}
\noindent
Special actions: \textbf{A2}.\\
Special results: \textbf{A1R2, A3R2}.
\begin{actions}
\action{Make list references to `special' items automatically.}
\begin{checks}
\result{First attempt fails}
\result*{All other attempts fail}
\end{checks}
\action*{Turn to google\ldots}
\begin{checks}
\result{Still fails, can't find the right search terms}
\end{checks}
\action{Post a MWE to \TeX{} SE.}
\begin{checks}
\result{Someone produces automagic? There's a package for that\ldots}
\result*{Re-write the original document. Again.}
\result{Job done}
\end{checks}
\end{actions}
\end{document}
这里最好的方法是什么?我目前的失败包括生成标签并生成标签列表、使用 imakeidx 以及将 enumi/enumii 列表维护为文本。
一个复杂的问题是,该文件将包含许多这样的部分(约 50 个),每个小节应该只列出它自己值得注意的项目。
答案1
这是一个原型。其想法是将特殊操作和结果保存到 LaTeX3 序列中\g_actions_seq
,并且\g_results_seq
每次开始一个子部分时,这些操作和结果都会aux
以以下形式的条目形式保存到文件中
\SetActionResult{actions}{0.1}{{{A2}}}
\SetActionResult{results}{0.1}{{{A1}}{{R2}},{{A3}}{{R2}}}
aux
读入文件时,\SetActionResult
命令会将数据存储到两个属性列表中,\g_special_actions_prop
用于\g_special_results_prop
操作和结果。在每个小节的开头,如果属性列表包含当前小节的键,则会自动打印此信息。有了这个,您的 MWE 会生成:
我将特殊操作和结果的硬编码列表保留在文件中以供比较。
以下是代码:
\documentclass{article}
\usepackage{enumitem}
\newlist{actions}{enumerate}{1}
\setlist[actions, 1]{label=A\arabic*}
\newlist{checks}{enumerate}{1}
\setlist[checks, 1]{label=R\arabic*}
\usepackage{xparse}
\usepackage{expl3}
\ExplSyntaxOn
\prop_new:N \g_special_actions_prop
\prop_new:N \g_special_results_prop
\seq_new:N \g_actions_seq
\seq_new:N \g_results_seq
\NewDocumentCommand\action{ sm }
{
\item
\IfBooleanTF{#1}
{ \emph{#2}\seq_gput_right:Nx \g_actions_seq {\theactionsi} }
{ #2 }
}
\NewDocumentCommand\result{ sm }
{
\item
\IfBooleanTF{#1}
{ \emph{#2}
\seq_gput_right:Nx \g_results_seq {\theactionsi\thechecksi} }
{ #2 }
}
\NewDocumentCommand\SetActionResult{mmm}
{
\prop_gput:cnn {g_special_#1_prop} {#2} {#3}
}
\NewDocumentCommand\SaveActionsResults{}{
% save special actions and results to the aux file
\seq_if_empty:NF \g_actions_seq
{
\iow_now:cx { @auxout }
{
\token_to_str:N\SetActionResult {actions}
{ \thesubsection }{\seq_use:Nn \g_actions_seq {,~}}
}
\seq_gclear:N \g_actions_seq
}
\seq_if_empty:NF \g_results_seq
{
\iow_now:cx { @auxout }
{
\token_to_str:N\SetActionResult {results}
{ \thesubsection }{\seq_use:Nn \g_results_seq {,~}}
}
\seq_gclear:N \g_results_seq
}
}
\NewDocumentCommand\Subsection{ m }
{
\SaveActionsResults
\subsection{ #1 }
% print all known special results and actions
\prop_if_in:NxT \g_special_actions_prop {\thesubsection} {
\prop_get:NxN \g_special_actions_prop {\thesubsection} \l_tmpa_tl
\noindent Special~actions:~\tl_use:N \l_tmpa_tl.
\newline
}
\prop_if_in:NxT \g_special_results_prop {\thesubsection} {
\prop_get:NxN \g_special_results_prop {\thesubsection} \l_tmpa_tl
\noindent Special~results:~\tl_use:N \l_tmpa_tl.
\newline
}
}
\cs_generate_variant:Nn \prop_if_in:NnT {NxT}
\cs_generate_variant:Nn \prop_get:NnN {NxN}
\ExplSyntaxOff
\begin{document}
\Subsection{First of many}
\noindent
Special actions: \textbf{A2}.\\
Special results: \textbf{A1R2, A3R2}.
\begin{actions}
\action{Make list references to `special' items automatically.}
\begin{checks}
\result{First attempt fails}
\result*{All other attempts fail}
\end{checks}
\action*{Turn to google\ldots}
\begin{checks}
\result{Still fails, can't find the right search terms}
\end{checks}
\action{Post a MWE to \TeX{} SE.}
\begin{checks}
\result{Someone produces automagic? There's a package for that\ldots}
\result*{Re-write the original document. Again.}
\result{Job done}
\end{checks}
\end{actions}
% save the data from the last subsection
\SaveActionsResults
\end{document}
尽管存在混淆的风险,但代码可以稍微合理化,因为操作和结果的处理方式几乎完全相同。例如,该\SetActionResult
命令显示了如何将操作和结果代码分支合并到一个函数中。
LaTeX3 需要一点时间来适应,但一段时间后你就会喜欢上它,因为它非常强大。我发现了解它的最佳方式是输入texdoc interface3
。
答案2
您可以使用数据工具-用于维护包含您的特殊事物的数据库的包。
然后,您可以使用 datatool-macros 来迭代数据库并“过滤”条目以“吐出”所需的列表。
在下面的例子中实际上使用了两个数据库。
写入一个数据库。LaTeX 运行结束时,该数据库将保存到外部文件中。该数据库名为specialthingsinterim
。
另一个数据库源自上一次 LaTeX 运行/来自上一次 LaTeX 运行中保存的外部文件,用于迭代和打印列表等。该数据库名为specialthings
。
这样,您既可以写入数据库,又可以同时使用数据库。
但您至少需要编译该文档两次。
\documentclass{article}
\usepackage{hyperref}
\usepackage{datatool}
\usepackage{atveryend}
\makeatletter
\newcommand\DATABASEFILECreateIfNotExistent[1]{%
\DTLifdbexists{#1}{}{%
\IfFileExists{\jobname.#1}{%
\DTLloaddb{#1}{\jobname.#1}%
}{%
\DTLnewdb{#1}%
}%
}%
\DTLifdbexists{#1interim}{}{%
\DTLnewdb{#1interim}%
\AtEndDocument{%
% This will save the interim-database to file with
% the last \shipout. The last \shipout is triggered
% by \end{document}/\enddocument.
\DTLsavedb{#1interim}{\jobname.#1}%
}%
\AfterLastShipout{%
% Check if content of database-token-register stemming from
% database-file of previous LaTeX-run differs from content of
% database-token-register stemming from database-file of
% the current LaTeX-run.
% If so, something changed and you need to re-run LaTeX.
% Probably this should be omitted with large databases.
\begingroup
\DTLgdeletedb{#1interim}%
\DTLloaddb{#1interim}{\jobname.#1}%
\edef\tempa{\the\csname dtldb@#1\endcsname}%
\edef\tempb{\the\csname dtldb@#1interim\endcsname}%
\ifx\tempa\tempb
\endgroup
\else
\endgroup
\@latex@warning@no@line{%
Database `#1' may have changed.
Rerun to get listings of entries etc right%
}%
\fi
}%
}%
}%
%-------------------------------------------------------------------------
\newcommand\SpecialThingsCount{0}%
\newcommand\AddSpecialThingToDatabase{%
\@bsphack
\xdef\SpecialThingsCount{\number\numexpr\SpecialThingsCount+1\relax}%
\DATABASEFILECreateIfNotExistent{specialthings}%
\DTLnewrow{specialthingsinterim}%
{%
\dtlexpandnewvalue
\DTLnewdbentry{specialthingsinterim}{PrimaryKey}{\SpecialThingsCount}%
\DTLnewdbentry{specialthingsinterim}{Subsection}{\thesubsection}%
\DTLnewdbentry{specialthingsinterim}{HSubsection}{\theHsubsection}%
\DTLnewdbentry{specialthingsinterim}{Environment}{\@currenvir}%
\DTLnewdbentry{specialthingsinterim}{Itemnumber}{\@currentlabel}%
\DTLnewdbentry{specialthingsinterim}{Superordinateitemnumber}{\previouscurrentlabel}%
\DTLnewdbentry{specialthingsinterim}{Destinationname}{\@currentHref}%
}%
\@esphack
}%
\newcommand\exchange[2]{#2#1}%
\newcommand\previouscurrentlabel{}%
\newcommand\ListOfSpecialThingsSeparator{}%
\newcommand\ListOfSpecialThings[2]{%
\xdef\ListOfSpecialThingsSeparator{}%
\DATABASEFILECreateIfNotExistent{specialthings}%
\DTLforeach{specialthings}{%
\PrimaryKeyField=PrimaryKey,
\SubsectionField=Subsection,
\HSubsectionField=HSubsection,
\EnvironmentField=Environment,
\ItemnumberField=Itemnumber,
\SuperordinateitemnumberField=Superordinateitemnumber,
\Destinationnamefield=Destinationname%
}{%
\begingroup
\edef\@tempa{\HSubsectionField}%
\edef\@tempb{#2}%
\ifx\@tempa\@tempb\expandafter\@firstofone\else\expandafter\@secondoftwo\fi
{%
\edef\@tempa{\EnvironmentField}%
\def\@tempb{#1}%
\ifx\@tempa\@tempb\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{%
\def\@tempa{checks}%
\ifx\@tempa\@tempb\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\exchange{\hyperlink{\Destinationnamefield}{\textbf{\SuperordinateitemnumberField\ItemnumberField}}}}%
{\exchange{\hyperlink{\Destinationnamefield}{\textbf{\ItemnumberField}}}}%
{%
\endgroup
\ListOfSpecialThingsSeparator
}%
\xdef\ListOfSpecialThingsSeparator{, }%
}%
}%
{\endgroup}%
}%
}%
\newcommand\ListOfSpecialActions{\ListOfSpecialThings{actions}{\theHsubsection}}%
\newcommand\ListOfSpecialChecks{\ListOfSpecialThings{checks}{\theHsubsection}}%
\usepackage{enumitem}
\newlist{actions}{enumerate}{1}
\setlist[actions, 1]{label=A\arabic*, before*={\def\previouscurrentlabel{}}}
\newlist{checks}{enumerate}{1}
\setlist[checks, 1]{label=R\arabic*, before*={\let\previouscurrentlabel=\@currentlabel}}
\newcommand*{\SpecialThingItem}{\item\@ifstar{\AddSpecialThingToDatabase\emph}{}}
\newcommand*{\action}{\SpecialThingItem}
\newcommand*{\result}{\SpecialThingItem}
\makeatother
\begin{document}
\subsection{First of many}
\noindent
Special actions: \ListOfSpecialActions.\\
Special results: \ListOfSpecialChecks.
\begin{actions}
\action{Make list references to `special' items automatically.}
\begin{checks}
\result{First attempt fails}
\result*{All other attempts fail}
\end{checks}
\action*{Turn to google\ldots}
\begin{checks}
\result{Still fails, can't find the right search terms}
\end{checks}
\action{Post a MWE to \TeX{} SE.}
\begin{checks}
\result{Someone produces automagic? There's a package for that\ldots}
\result*{Re-write the original document. Again.}
\result{Job done}
\end{checks}
\end{actions}
\subsection{Second of many}
\noindent
Special actions: \ListOfSpecialActions.\\
Special results: \ListOfSpecialChecks.
\begin{actions}
\action*{Make list references to `special' items automatically.}
\begin{checks}
\result{First attempt fails}
\result{Second attempt fails}
\result{Third attempt fails}
\result*{All other attempts fail}
\end{checks}
\action{Turn to google\ldots}
\begin{checks}
\result*{Still fails, can't find the right search terms}
\end{checks}
\action*{Post a MWE to \TeX{} SE.}
\begin{checks}
\result{Someone produces automagic? There's a package for that\ldots}
\result{Re-write the original document. Again.}
\result*{Job done}
\end{checks}
\end{actions}
\end{document}