我继续我的传奇故事,使用 LaTeX 来扩展东西etoolbox
。
这次我有下面一段代码。
\documentclass[8pt]{book}
\usepackage{etoolbox}
\usepackage{hyperref}
\newcount\infoCounter
\newcommand{\addInfoRef}[1]{
\unexpanded{\nameref{\csuse{info#1Label}}}
\cseappto{info#1Ref}{Mentioned in %
\unexpanded{\unexpanded{\nameref}}{\csuse{info\currentname Label}}%
\unexpanded{\unexpanded{\\}}
}
}
\newcommand{\newInfon}[3][]{
\listxadd\listInfo{#2}
\edef\currentname{#2}
\csedef{info#2Label}{infoKey\the\infoCounter}
\advance\infoCounter by 1
\ifstrempty{#1}{}{\csedef{info#2Img}{#1}}
\csedef{info#2Cnt}{#3}
\nullfont#3\normalfont
}
\newcommand{\printInfo}[1]{%
\edef\currentName{#1}
\section{#1}\label{\expandafter\csuse{info#1Label}}%
\csuse{info#1Cnt}
\ifcsname info#1Ref\endcsname
\\\begin{tabular}{p{9cm}}
\csuse{info#1Ref}
\end{tabular}
\fi}
\begin{document}
\chapter{Tests Result}
\newInfon{Test Case 1}{%
The result was inconclusive.}
\newInfon{Test Case 2}{%
The result was more conclusive than in \addInfoRef{Test Case 1}, but was still inconclusive.}
\newInfon{Test Case 3}{%
The result less conclusive than in \addInfoRef{Test Case 2}, but was still more conclusive than in \addInfoRef{Test Case 1}.}
\printInfo{Test Case 1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}
\end{document}
期望的输出是......嗯,几乎是生成的内容:
顶部的两个红点表示在时间之前引用了某件事。如果您尝试重新排序\printInfo{Test Case X}
,您会注意到“提及”不再正确打印。例如,如果我重新排序:
\printInfo{Test Case 3}
\printInfo{Test Case 2}
\printInfo{Test Case 1}
我明白了
也就是说,一些“提及”条目是重复的!我考虑做类似的事情
\ifcsname info\currentname#2Switch\endcsname{\relax}{%
\cseappto{info#2Ref}{Mentioned in...}
}
\csedef{info\currentname#2Switch}{1}
,\addInfoRef
但是那没有用而且我不知道为什么。
任何帮助都非常感谢!提前致谢!
答案1
expl3
以下是使用(via xparse
)的实现。\newInfon
如果第一个强制参数包含非 ASCII 字符,则该命令有一个可选参数可供使用(我做了一个示例):可选参数只是一个键,可在引用案例时使用。
诀窍是做两件不同的事情,并在框内执行\addInfoRef
时执行,因此输出最终被丢弃。\newInfon
\documentclass{book}
\usepackage[utf8]{inputenc}
\usepackage[greek,english]{babel}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage[unicode]{hyperref}
\pdfstringdefDisableCommands{\let\textgreek\relax}
\ExplSyntaxOn
\prop_new:N \g_benedict_info_items_prop
\bool_new:N \l_benedict_info_add_bool
\NewDocumentCommand{\newInfon}{O{#2}mm}
{
\prop_gput:Nnn \g_benedict_info_items_prop
{ #1 key } % key
{ #2 }
\prop_gput:Nnx \g_benedict_info_items_prop
{ #1 text } % text
{ \tl_trim_spaces:n { #3 } }
\tl_set:Nn \l__benedict_info_temp_tl { #1 }
\hbox_set:Nn \l_tmpa_box
{
\bool_set_true:N \l_benedict_info_add_bool #3
}
}
\NewDocumentCommand{\addInfoRef}{m}
{
\bool_if:NTF \l_benedict_info_add_bool
{
\seq_if_exist:cF { g_benedict_info_#1_seq }
{
\seq_new:c { g_benedict_info_#1_seq }
}
\seq_gput_right:cx { g_benedict_info_#1_seq }
{
Mentioned ~ in ~ \exp_not:N \nameref{\l__benedict_info_temp_tl label}
}
}
{
\prop_item:Nn \g_benedict_info_items_prop { #1 key }
}
}
\NewDocumentCommand{\printInfo}{m}
{
\exp_args:Nx \section {\prop_item:Nn \g_benedict_info_items_prop { #1 key }}\label{#1label}
\prop_item:Nn \g_benedict_info_items_prop { #1 text }
\seq_if_exist:cT { g_benedict_info_#1_seq }
{
\\*[\medskipamount]
\begin{tabular}{@{} p{9cm} @{}}
\seq_use:cn { g_benedict_info_#1_seq } { \\ }
\end{tabular}
\par\addvspace{\medskipamount}
}
}
\ExplSyntaxOff
\begin{document}
\chapter{Tests Result}
\newInfon[TC1]{Test Case (\textgreek{δοκιμή}) 1}{
The result was inconclusive.
}
\newInfon{Test Case 2}{
The result was more conclusive than in \addInfoRef{TC1},
but was still inconclusive.
}
\newInfon{Test Case 3}{
The result less conclusive than in \addInfoRef{Test Case 2},
but was still more conclusive than in \addInfoRef{TC1}.
}
\printInfo{TC1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}
\end{document}
答案2
我通过大量的反复试验回答了自己的问题。基本上,我创建了一个printingInfo
变量,将其设置为 0,并且只在 printInfo 期间将其设置为 1。然后,如果该 printingInfo=0,addInfoRef 函数才会执行 cseappto。
这是可行的解决方案:
\documentclass[8pt]{book}
\usepackage{etoolbox}
\usepackage{hyperref}
\newcount\infoCounter
\edef\printingInfo{0}%
\newcommand{\addInfoRef}[1]{%
\ifstrequal{\printingInfo}{0}{\unexpanded{\nameref{\csuse{info#1Label}}}}{%
\cseappto{info#1Ref}{Mentioned in %
\unexpanded{\unexpanded{\nameref}}{\csuse{info\currentname Label}}%
\unexpanded{\unexpanded{\\}}}%
}%
}
\newcommand{\newInfon}[3][]{
\edef\printingInfo{0}%
\edef\currentname{#2}
\csedef{info#2Label}{infoKey\the\infoCounter}
\advance\infoCounter by 1
\ifstrempty{#1}{}{\csedef{info#2Img}{#1}}
\csedef{info#2Cnt}{#3}
\nullfont#3\normalfont
}
\newcommand{\printInfo}[1]{%
\edef\printingInfo{1}%
\edef\currentname{#1}
\section{#1}\label{\expandafter\csuse{info#1Label}}%
\csuse{info#1Cnt}
\ifcsname info#1Ref\endcsname
\\\begin{tabular}{p{9cm}}
\csuse{info#1Ref}
\end{tabular}
\fi}
\begin{document}
\chapter{Tests Result}
\newInfon{Test Case 1}{%
The result was inconclusive.}
\newInfon{Test Case 2}{%
The result was more conclusive than in \addInfoRef{Test Case 1}, but was still inconclusive.}
\newInfon{Test Case 3}{%
The result less conclusive than in \addInfoRef{Test Case 2}, but was still more conclusive than in \addInfoRef{Test Case 1}.}
\printInfo{Test Case 1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}
\end{document}
现在唯一剩下的问题是“第 1 章”与各章节之间剩余的间距。