我需要在大型政策手册的每个部分的底部添加一个程序手册的参考表,如下所示:
\begin{table}[H]
\begin{tabular}{ |c|c| }
\hline
\multicolumn{2}{|c|}{Procedures} \\
\hline
%fyi PM = Procedures Manual
PM \ref{PM-tyinglaces} & \nameref{PM-tyinglaces} \\
PM \ref{PM-polishshoes & \nameref{PM-polishshoes} \\
PM \ref{PM-ironshirt} & \nameref{PM-ironshirt} \\
\hline
\end{tabular}
\end{table}
当然,由于每个表的格式都相同,我真的很想要一个具有类似语法的宏:
%\procedurelist{firstlabel}{nextlabel}...{nthlabel}
%
\procedurelist{PM-tyinglaces}{PM-polishshoes}{PM-ironshirt}
单个逗号分隔的参数也可以。我的尝试如下。我就是无法让它关闭表格,不知何故,当我包含结束 \hline 时它会中断。
\makeatletter
\newcommand{\procedurelist}[1]{%
\begin{table}[H]
\begin{tabular}{ |c|c| }
\hline
\multicolumn{2}{|c|}{Procedures} \\
\hline
PM \ref{#1} & \nameref{#1} \\%
\checknextarg
}
\newcommand{\checknextarg}{%
\@ifnextchar\bgroup{%
\consumenextarg
}{%
\hline %causes error?
\end{tabular}
\end{table}
}
}
\newcommand{\consumenextarg}[1]{%
PM \ref{#1} & \nameref{#1} \\%
\@ifnextchar\bgroup{%
\consumenextarg
}{%
\hline %causes error?
\end{tabular}
\end{table}
}
}
\makeatother
我如何实现我的目标?
我的宏中做错了什么?
答案1
我不建议使用如下语法
\procedurelist{a}{b}{c}...{z}
更喜欢类似的东西
\procedurelist{a,b,c,...,z}
其实按照你想象的那样去做并不难,诀窍在于提前搭建好桌体。
\documentclass{article}
\usepackage{hyperref}
\makeatletter
\newcommand{\procedurelist}{%
\proclist@body={}%
\proclist@start
}
\newtoks\proclist@body
\newcommand{\proclist@start}{%
\@ifnextchar\bgroup\proclist@absorb\proclist@finish
}
\newcommand{\proclist@absorb}[1]{%
\proclist@body=\expandafter{%
\the\proclist@body
PM~\ref{#1} & \nameref{#1} \\%
}%
\proclist@start
}
\newcommand{\proclist@finish}{%
\begin{tabular}{|c|c|}
\hline
\the\proclist@body
\hline
\end{tabular}%
}
\makeatother
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{PM-tyinglaces}{PM-polishshoes}{PM-ironshirt}
\end{document}
使用逗号分隔列表的另一种方法更容易expl3
,因为它已经具有处理逗号分隔列表和循环它们的功能。
\documentclass{article}
\usepackage{xparse}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\procedurelist}{m}
{
\seq_clear:N \l__kjc_procedurelist_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nn \l__kjc_procedurelist_seq
{
PM~\ref{##1} & \nameref{##1}
}
}
\begin{tabular}{|c|c|}
\hline
\seq_use:Nn \l__kjc_procedurelist_seq { \\ } \\
\hline
\end{tabular}
}
\seq_new:N \l__kjc_procedurelist_seq
\ExplSyntaxOff
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{PM-tyinglaces,PM-polishshoes,PM-ironshirt}
\end{document}
更好的表格:
\documentclass{article}
\usepackage{xparse,booktabs}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\procedurelist}{m}
{
\seq_clear:N \l__kjc_procedurelist_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nn \l__kjc_procedurelist_seq
{
\ref{##1} & \nameref{##1}
}
}
\begin{tabular}{cl}
\toprule
\multicolumn{1}{c}{\textbf{PM}} & \textbf{Name} \\
\midrule
\seq_use:Nn \l__kjc_procedurelist_seq { \\ } \\
\bottomrule
\end{tabular}
}
\seq_new:N \l__kjc_procedurelist_seq
\ExplSyntaxOff
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{PM-tyinglaces,PM-polishshoes,PM-ironshirt}
\end{document}
一旦掌握了窍门,就可以更简单地实现它:
\documentclass{article}
\usepackage{xparse,booktabs}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\procedurelist}{m}
{
\cs_set:Nn \__kjc_procedurelist_row:n { \ref{##1} & \nameref{##1} \\ }
\begin{tabular}{cl}
\toprule
\multicolumn{1}{c}{\textbf{PM}} & \textbf{Name} \\
\midrule
\clist_map_function:nN { #1 } \__kjc_procedurelist_row:n
\bottomrule
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{PM-tyinglaces,PM-polishshoes,PM-ironshirt}
\end{document}
通过这种方法,\__kjc_procedurelist_row:n
可以在主命令之外定义函数。但是,也可以通过允许动态更改默认值来改进这一点:
\documentclass{article}
\usepackage{xparse,booktabs}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\procedurelist}{om}
{
\IfValueT{#1}
{
\cs_set:Nn \__kjc_procedurelist_row:n { #1 }
}
\begin{tabular}{cl}
\toprule
\multicolumn{1}{c}{\textbf{PM}} & \textbf{Name} \\
\midrule
\clist_map_function:nN { #2 } \__kjc_procedurelist_row:n
\bottomrule
\end{tabular}
}
\cs_new:Nn \__kjc_procedurelist_row:n { \ref{#1} & \nameref{#1} \\ }
\ExplSyntaxOff
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{
PM-tyinglaces,
PM-polishshoes,
PM-ironshirt
}
\procedurelist[\ref{#1} & \textit{\nameref{#1}} \\]{
PM-tyinglaces,
PM-polishshoes,
PM-ironshirt
}
\end{document}
答案2
诀窍是首先获取所有这些参数并将它们存储在某个地方(此处\procedurelist@content
)。获取所有参数后,您就可以输出格式化的表格。这样,表格内部就不会有任何无法扩展的测试阻止任何\noalign
s。
示例代码(我删除了\nameref
s 和周围的内容,因为如果唯一允许的位置是并且您不使用标题,table
那么这没有意义):H
\documentclass[]{article}
\makeatletter
\newcommand*\procedurelist@content{}
\newcommand*\procedurelist@checknext
{%
\@ifnextchar\bgroup
{\procedurelist@eatnext}
{\procedurelist@shipout}%
}
\newcommand\procedurelist[1]
{%
\begingroup
\def\procedurelist@content{PM \ref{#1} & #1 \\}%
\procedurelist@checknext
}
\newcommand\procedurelist@eatnext[1]
{%
\edef\procedurelist@content
{\unexpanded\expandafter{\procedurelist@content PM \ref{#1} & #1 \\}}%
\procedurelist@checknext
}
\newcommand*\procedurelist@shipout
{%
\begin{tabular}{|c|c|}
\hline
\multicolumn{2}{|c|}{Procedures} \\
\hline
\procedurelist@content
\hline
\end{tabular}%
\endgroup
}
\makeatother
\begin{document}
\procedurelist{arg1}{arg2}{arg3}{arg4}
\end{document}
答案3
使用\xintFor
(这不是可扩展循环,但仍然可以在表格中工作......)
\documentclass{article}
\usepackage{booktabs}
\usepackage{hyperref}
\usepackage{xinttools}
\newcommand{\procedurelist}[1]{%
\begin{tabular}{cl}
\toprule
\multicolumn{1}{c}{\textbf{PM}} & \textbf{Name} \\
\midrule
\xintFor ##1 in {#1}\do {\ref{##1} & \nameref{##1} \\ }
\bottomrule
\end{tabular}
}
\begin{document}
\section{Tie laces}\label{PM-tyinglaces}
\section{Polish shoes}\label{PM-polishshoes}
\section{Iron shirt}\label{PM-ironshirt}
\section{End}
\procedurelist{PM-tyinglaces,PM-polishshoes,PM-ironshirt}
\end{document}