我正在写一份讨论文档,贡献者可以拥有自己的页面,我想在一般文本中提及这些页面,所以我有这个,似乎可以解决问题
% usage: create printed page space for artist and the short form reference
% \artist{Jo Blow}{JoBl}
\newcommand{\artist}[2]{
\newpage
\subsection{#1}
Lorem ipsum
\newpage
Et tu quoque! #2\label{artist:#2}
% page reserved for artwork by #1
}
% obtain page numbering for artist image page given shortform reference
% \mention{JoBl}
\newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}
但我想扩展 mention{} 以获取可变长度的参数列表
我找到了这个通过逗号分隔的参数进行迭代
这是一个我还没学会走路就跑的例子,但请忍耐一下,我只是一个愚蠢的艺术家,我试过了
%!TEX TS-program = lualatex
%!TEX encoding = UTF-8 Unicode
\documentclass{article}
\newcommand{\artist}[2]{
\newpage
\subsection{#1}
Lorem ipsum
\newpage
Et tu quoque! #2\label{artist:#2}
% page reserved for artwork by #1
}
% obtain page numbering for artist image page given short form reference
% \mention{HoBu}
\newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}
\makeatletter
\newcommand{\lmention}[2][$,$]{%
\def\nextitem{\def\nextitem{#1}}%
\@for \el:=#2\do{\nextitem\el}%
}
\makeatother
\begin{document}
\artist{Arty Blow}{Arty}
\artist{Jo Blow}{Jo}
What I want is the stylised \mention{Arty}
What would be nice would be an arg count to say p.18 or pp.18,23,24
A list of mentions is \lmention{Arty,Jo,Fred} tho we havent talked about Fred
Did I forget \lmention{Bart} who is yet to be referenced
\artist{Bart Beast}{Bart}
\artist{Fred Geest}{Fred}
\end{document}
长话短说,问题来了?我怎样才能让它逐个参数地执行 \pageref 查找
我尝试
\newcommand{\lmention}[2][$:$]{%
\def\nextitem{\def\nextitem{#1}}%
\@for \el:=#2\do{\pageref{artist:#2}\nextitem\el}%
}
但得到
A list of mentions is ??Arty??:Jo??:Fred tho we havent talked about Fred
这超出了我的理解范围
答案1
您可以\lmention
使用 TeX 原语和经典 TeX 递归循环来定义。
\def\lmention#1{\lmentionA#1,\end,}
\def\lmentionA#1,#2,{\ifx\end#2 [p.\pageref{artist:#1}]\else
[pp.\pageref{artist:#1}\afterfi{\lmentionB#2,}\fi
}
\def\lmentionB#1,#2,{,\pageref{artist:#1}%
\ifx\end#2]\else \afterfi{\lmentionB#2,}\fi
}
\def\afterfi #1#2\fi{\fi#1}
请注意,此宏与单个参数(如)一起使用\mention
,即扩展为 [p.page]。在其他情况下,它会扩展为 [pp.list-of-pages]。
答案2
您可以使用expl3
它来提供您需要的所有工具。
如您所见,只有一个\mention
命令可以区分是否提供了一个或多个引用。
\documentclass{article}
\newcommand{\artist}[2]{%
\newpage
\subsection{#1}
Lorem ipsum
\newpage
Et tu quoque! #2\label{artist:#2}
% page reserved for artwork by #1
}
\ExplSyntaxOn
\NewDocumentCommand{\mention}{m}
{
\aldobranti_mention:n { #1 }
}
\seq_new:N \l__aldobranti_mention_ref_seq
\tl_new:N \l__aldobranti_mention_first_tl
\cs_new_protected:Nn \aldobranti_mention:nn
{
% divide the item at the given delimiter
\seq_set_from_clist:Nn \l__aldobranti_mention_ref_seq { #1 }
% detach the last item
\seq_pop_right:NN \l__aldobranti_mention_ref_seq \l__aldobranti_mention_first_tl
% now process
\aldobranti_mention_format:n
{
% if the sequence is empty, there was just one item: issue 'p.'; otherwise 'pp.'
\seq_if_empty:NTF \l__aldobranti_mention_ref_seq { p. } { pp. } \nobreakspace
% now map the sequence to give 'pageref,<space>'
\seq_map_inline:Nn \l__aldobranti_mention_ref_seq { \pageref{artist:##1},~ }
% last item should not have comma and space
\pageref{artist:\l__aldobranti_mention_first_tl}
}
}
\cs_new_protected:Nn \aldobranti_mention_format:n
{% format the whole block (change as desired)
\textup{[}
\hspace*{0.1em}
\textit{#1}
\hspace*{0.1em}
\textup{]}
}
\ExplSyntaxOff
\begin{document}
\artist{Arty Blow}{Arty}
\artist{Jo Blow}{Jo}
What I want is the stylised \mention{Arty}
What would be nice would be an arg count to say p.18 or pp.18,23,24
A list of mentions is \mention{Arty,Jo,Fred} tho we haven't talked about Fred
Did I forget \mention{Bart} who is yet to be referenced
\artist{Bart Beast}{Bart}
\artist{Fred Geest}{Fred}
\end{document}
答案3
首先要意识到的是,列表的当前元素不是#2
而是\el
。参数#2
是完整列表。因此你需要\pageref{artist:\el}
。
第二件事与分隔符的位置有关。通常在构建逗号分隔列表时,您可能倾向于执行以下操作:
for each element {
print element
print separator
}
请注意,以上是伪代码,而不是实际的 LaTeX 或 TeX。
但是,这样做会得到一个列表element1,element2,element3,
,列表末尾有一个不需要的逗号。因此,另一个问题中的代码使用了一个技巧:它将分隔符前每个元素,但确保不打印第一个分隔符。这比确保不打印最后一个分隔符更容易,因为在循环中您不知道最后一个元素是什么。诀窍在于,该命令\nextitem
最初定义为不打印任何内容,而是执行定义\def\nextitem{#1}
。参数#1
是逗号,因此从第二次调用开始,\nextitem
打印逗号。因此,您需要与引用问题相同的结构,即,\do{\nextitem\el}
但不是只打印,而是\el
打印\pageref{artist:\el}
,因此完整地变成\do{\nextitem\pageref{artist:\el}}
。
要计算参数数量,您可以先循环列表并为每个元素增加一个计数器,然后测试该计数器的值。如果为 1,则打印p.
,否则打印pp.
。之后,您再次循环列表以进行实际\pageref
调用。
附带说明的是,您不需要$,$
分隔符,这仅在原始问题中需要,因为那里使用的分隔符是一个数学命令(\triangleright
),它需要带有数学模式$
。逗号是常规字符,因此不需要数学模式。
完整代码:
\documentclass{article}
\newcommand{\artist}[2]{
\newpage
\subsection{#1}
Lorem ipsum
\newpage
Et tu quoque! #2\label{artist:#2}
% page reserved for artwork by #1
}
% obtain page numbering for artist image page given short form reference
% \mention{HoBu}
\newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}
\makeatletter
\newcounter{mentionargs}
\newcommand{\lmention}[2][,]{%
\setcounter{mentionargs}{0}%
\@for \el:=#2\do{\stepcounter{mentionargs}}%
\ifnum\value{mentionargs}=1%
p.%
\else%
pp.%
\fi%
\def\nextitem{\def\nextitem{#1}}%
\@for \el:=#2\do{\nextitem\pageref{artist:\el}}%
}
\makeatother
\begin{document}
\artist{Arty Blow}{Arty}
\artist{Jo Blow}{Jo}
What I want is the stylised \mention{Arty}, \mention{Jo}, \mention{Fred}
What would be nice would be an arg count to say p.2 or pp.18,23,24
A list of mentions is \lmention{Arty,Jo,Fred} tho we havent talked about Fred
Did I forget \lmention{Bart} who is yet to be referenced
\artist{Bart Beast}{Bart}
\artist{Fred Geest}{Fred}
\end{document}
结果: