我有一个包含一些复杂表格的文档,这些表格由一个带有\Rule
命名参数的命令定义(使用keyval
包)。表格的各个行首先存储到通过定义的标记列表中,\newtoks
因为一些命名参数对应于表格的多个单元格,并且必须同时包含在条件中\ifcsname
。我想强制\Rule
存储结果表的完整展开副本(包含每个命名参数的特定值),以便我可以在附录中列出文档中任何地方出现的所有规则。但我无法强制标记列表完全展开。
我编译了xetex
并且无法改变这一点。
编辑:每个表对应一次调用\Rule
;命名参数包含信息,并且的定义提供了每种命名参数的格式(大多数是可选的)。我希望正文和附录中的表格完全相同:输出应该与我手动将所有命令从文档复制粘贴到附录中\Rule
时相同。\Rule
\documentclass{book}
\usepackage{xparse,keyval}
\newcounter{rule}
\renewcommand{\therule}[0]{G\arabic{rule}}
\makeatletter
\newtoks\@tabtoks
\newcommand\addtabtoks[1]{\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand*\resettabtoks{\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\edef\allrules{}
\edef\oldallrules{\allrules}
\newcommand*\addtoallrules[1]{\g@addto@macro{\allrules}{#1}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\define@key{myKeys}{nonnumbered}{\def\mm@nonnumbered{#1}}
\define@key{myKeys}{label}{\def\mm@label{#1}}
\define@key{myKeys}{header}{\def\mm@header{#1}}
\define@key{myKeys}{FUNKTORY}{\def\mm@FUNKTORY{#1}}
%% one \ifcsname cannot directly generate more than a single table cell (problems with & and \\ characters)
%% so instead of spitting out the rows of the table immediately,
%% the content is added to @tabtoks via the command \addtabtoks
%% and printed when all parameters are read
\DeclareDocumentCommand{\Rule}{m}{
\begingroup%
\setkeys{myKeys}{#1}%reads the key=value pairs
\medskip\noindent
\begin{table}
\addtabtoks{\begin{tabular}{|p{5cm}|l|}
\hline}
\ifcsname mm@nonnumbered\endcsname
\addtabtoks{\multicolumn{2}{|l|}{{\bf\mm@header}}\\}
\else \refstepcounter{rule}
\addtabtoks{\multicolumn{2}{|l|}{{\bf\mm@header}\hfill Rule \therule} \\}
\fi
\addtabtoks{\hline}
\ifcsname mm@FUNKTORY\endcsname \addtabtoks{\mm@FUNKTORY \\}\fi
\ifcsname mm@OBLIG\endcsname \addtabtoks{Obligatory & \mm@OBLIG \\}\fi
\addtabtoks{\hline
\end{tabular}}
\printtabtoks
% %%%%%%%% BEFORE RESETTING \@tabtoks, I'D LIKE TO STORE ITS FULLY EXPANDED VALUE
% \expandafter\long\expandafter\edef\expandafter\tmp{\expandafter\write\expandafter\the\@tabtoks}
% \show\tmp
% \expandafter\addtoallrules\expandafter{\tmp}
% \show\allrules
\resettabtoks
\ifcsname mm@label\endcsname \label{\mm@label}\fi
\end{table}
\smallskip
\endgroup%
}
\makeatother
\begin{document}
\Rule{
nonnumbered = {yes},
header = {Rules in general},
FUNKTORY = {VALUE 1 & VALUE 2},
}
\Rule{
header = {Rule 1},
FUNKTORY = {X & Y},
label = {rule:1},
}
\appendix
\allrules
\end{document}
答案1
您可能不太清楚最终的摘要是什么样子,但这可能会帮助您入门。如您所见,规则都收集在最后。
\globaltabtoks
我在这里所做的是创建与 OP 使用的寄存器并行的第二个令牌寄存器。然后,我可以按照构建摘要表的方式\@tabtoks
将规则的各个部分添加到中。\globaltabtoks
并且我不会在规则之间清除/重置寄存器!因此,例如,我没有在标题和内容之间设置一行,而是仅使用列分隔符。
关键是将键扩展为文本,然后再将它们放入令牌寄存器中。在这里,我创建了将\addglobaltabtoks{}
文字文本放在寄存器末尾\globaltabtoks
,并\xaddglobaltabtoks{}
扩展参数的第一个令牌一次,然后将它和参数的其余部分附加到\globaltabtoks
。
对于\therule
,我需要不止一次扩展才能获得所需的数字,因此我使用了新的 TeX 原\expanded
语
\xaddglobaltabtoks{\expanded{\therule}&}
但是,如果你的安装尚不支持\expanded
,你可以使用
\edef\tmp{\therule}
\xaddglobaltabtoks{\tmp&}
以下是 MWE:
\documentclass{book}
\usepackage[T1]{fontenc}
\usepackage{xparse,keyval}
\newcounter{rule}
\renewcommand{\therule}[0]{G\arabic{rule}}
\makeatletter
\newtoks\@tabtoks
\newtoks\globaltabtoks
\newcommand\addtabtoks[1]{\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand\addglobaltabtoks[1]{%
\global\globaltabtoks\expandafter{\the\globaltabtoks#1}%
}
\newcommand\xaddglobaltabtoks[1]{%
\expandafter\addglobaltabtoks\expandafter{#1}%
}
\newcommand*\resettabtoks{\@tabtoks{}}
\newcommand*\resetglobaltabtoks{\globaltabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\edef\allrules{}
\edef\oldallrules{\allrules}
\newcommand*\addtoallrules[1]{\g@addto@macro{\allrules}{#1}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\define@key{myKeys}{nonnumbered}{\def\mm@nonnumbered{#1}}
\define@key{myKeys}{label}{\def\mm@label{#1}}
\define@key{myKeys}{header}{\def\mm@header{#1}}
\define@key{myKeys}{FUNKTORY}{\def\mm@FUNKTORY{#1}}
%% one \ifcsname cannot directly generate more than a single table cell (problems with & and \\ characters)
%% so instead of spitting out the rows of the table immediately,
%% the content is added to @tabtoks via the command \addtabtoks
%% and printed when all parameters are read
\DeclareDocumentCommand{\Rule}{m}{
\begingroup%
\setkeys{myKeys}{#1}%reads the key=value pairs
\medskip\noindent
\begin{table}[ht]
\addtabtoks{\begin{tabular}{|p{5cm}|l|}
\hline}
\ifcsname mm@nonnumbered\endcsname
\addtabtoks{\multicolumn{2}{|l|}{{\bf\mm@header}}\\}
\addglobaltabtoks{&}
\else \refstepcounter{rule}
\addtabtoks{\multicolumn{2}{|l|}{{\bf\mm@header}\hfill Rule \therule} \\}
\addglobaltabtoks{Rule }\xaddglobaltabtoks{\expanded{\therule}&}
\fi
\addtabtoks{\hline}
\ifcsname mm@FUNKTORY\endcsname \addtabtoks{\mm@FUNKTORY \\}
\xaddglobaltabtoks{\mm@FUNKTORY \\}\fi
\ifcsname mm@OBLIG\endcsname \addtabtoks{Obligatory & \mm@OBLIG \\}
\addglobaltabtoks{Obligatory & }
\xaddglobaltabtoks{\mm@OBLIG \\}\fi
\addtabtoks{\hline
\end{tabular}}
\addglobaltabtoks{\hline}
\printtabtoks
\resettabtoks
\ifcsname mm@label\endcsname \label{\mm@label}\fi
\end{table}
\smallskip
\endgroup%
}
\makeatother
\begin{document}
\Rule{
nonnumbered = {yes},
header = {Rules in general},
FUNKTORY = {VALUE 1 & VALUE 2},
}
\Rule{
header = {Rule 1},
FUNKTORY = {X & Y},
label = {rule:1}
}
\Rule{
header = {Rule 2},
FUNKTORY = {P & Q},
label = {rule:2},
}
\appendix SUMMARY
\noindent
\begin{tabular}{|l|p{5cm}|l|}
\hline
\the\globaltabtoks
\end{tabular}
\end{document}
答案2
我认为您想要的是类似以下内容的内容。宏可以记录很多东西。大多数东西。逐字记录材料很棘手,但您这里没有,因此您只需将高级命令及其参数记录在 LaTeX3 序列中,然后在附录中使用它来重播所有内容(准确地说,在 中\recapallrules
)。我只需要在两个地方引入间接级别:
对于
\label
命令:必须只有一个具有给定名称的标签,因此我\mm@set@rule@label
在中使用\typesetRule
。\mm@set@rule@label
在主文本中使用时设置标签,但在从中使用时\recapallrules
(即在附录中使用时)不执行任何操作(行为很容易改变)。对于计数器增量:出于相同的原因,在主文本中使用时和从中使用时
\mm@increment@rule@ctr
都是如此(我们不希望对于相同的计数器值有两个不同的引用 - 用命令记录的位置)。\refstepcounter{rule}
\stepcounter{rule}
\recapallrules
\label
rule
我还通过删除所有\addtabtoks
类似的东西来简化您的代码,这些东西似乎根本没有必要(除非另有证明!)。
\documentclass{book}
\usepackage{keyval}
\usepackage{xparse}
\newcounter{rule}
\renewcommand{\therule}[0]{G\arabic{rule}}
\makeatletter
\define@key{myKeys}{nonnumbered}{\def\mm@nonnumbered{#1}}
\define@key{myKeys}{label}{\def\mm@label{#1}}
\define@key{myKeys}{header}{\def\mm@header{#1}}
\define@key{myKeys}{FUNKTORY}{\def\mm@FUNKTORY{#1}}
\newcommand*{\mm@normal@increment@rule@ctr}{\refstepcounter{rule}}
\newcommand*{\mm@appendix@increment@rule@ctr}{\stepcounter{rule}}
\let\mm@increment@rule@ctr=\mm@normal@increment@rule@ctr
\newcommand*{\mm@normal@rule@label@cmd}{%
\ifcsname mm@label\endcsname
\expandafter\label\expandafter{\mm@label}%
\fi
}
\newcommand*{\mm@appendix@rule@label@cmd}{}
\let\mm@set@rule@label=\mm@normal@rule@label@cmd
\NewDocumentCommand{\typesetRule}{m}{% don't forget the percent sign here!
\begingroup
\setkeys{myKeys}{#1}%reads the key=value pairs
\mm@set@rule@label
\begin{tabular}{|p{5cm}|l|}
\hline
\ifcsname mm@nonnumbered\endcsname
\multicolumn{2}{|l|}{{\bf\mm@header}}\\
\else
\multicolumn{2}{|l|}{{%
\mm@increment@rule@ctr
\bf\mm@header}\hfill Rule \therule} \\
\fi
\hline
\ifcsname mm@FUNKTORY\endcsname
\mm@FUNKTORY \\
\fi
\ifcsname mm@OBLIG\endcsname
Obligatory & \mm@OBLIG \\
\fi
\hline
\end{tabular}%
\endgroup
}
\ExplSyntaxOn % Use LaTeX3-style input syntax (see expl3.pdf)
\seq_new:N \g_mm_rules_seq
\NewDocumentCommand \Rule { m }
{
\seq_gput_right:Nn \g_mm_rules_seq { \typesetRule {#1} }
\medskip\noindent
\typesetRule {#1}
}
% Programming-level function
\cs_new_protected:Npn \mm_recap_all_rules:
{
\group_begin: % limit effect of the \cs_set_eq:NN
\setcounter {rule} {0} % reset the rule counter
% Special version of two commands for use here (we used different versions
% in the main text). Note that \cs_set_eq:NN is like \let.
\cs_set_eq:NN \mm@increment@rule@ctr \mm@appendix@increment@rule@ctr
\cs_set_eq:NN \mm@set@rule@label \mm@appendix@rule@label@cmd
% Use all elements we've recorded, separated using the provided separator
\seq_use:Nn \g_mm_rules_seq { \par \medskip \noindent } % separator
\group_end:
}
% User-level function
\NewDocumentCommand \recapallrules { }
{
\mm_recap_all_rules:
}
\ExplSyntaxOff % end of LaTeX3-style input syntax
\makeatother
\begin{document}
\Rule{
nonnumbered = {yes},
header = {Rules in general},
FUNKTORY = {VALUE 1 & VALUE 2},
}
\Rule{
header = {Rule 1},
FUNKTORY = {X & Y},
label = {rule:1},
}
\Rule{
header = {Rule 2},
FUNKTORY = {Z & T},
label = {rule:2},
}
\appendix
\chapter{All rules}
\recapallrules
\end{document}
在第 1 页:
附录:
答案3
我不会将“传统”编程与 混合使用expl3
。通过谨慎使用变体,可以轻松控制哪些可以扩展,哪些不可以扩展。
\documentclass{book}
\usepackage{xparse}
\newcounter{rule}
\renewcommand{\therule}[0]{G\arabic{rule}}
\ExplSyntaxOn
\NewDocumentCommand{\Rule}{m}
{
\group_begin:
\tl_clear:N \l__ansa_rule_body_tl
\keys_set:nn { ansa/rule } { #1 }
\__ansa_rule:
\tl_gput_right:NV \g__ansa_rule_all_tl \l__ansa_rule_body_tl
\tl_gput_right:Nn \g__ansa_rule_all_tl { \par\bigskip }
\group_end:
}
\NewDocumentCommand{\allrules}{}
{
\begin{center}
\cs_set_eq:NN \__ansa_rule_label:n \use_none:n
\tl_use:N \g__ansa_rule_all_tl
\end{center}
}
\tl_new:N \l__ansa_rule_body_tl
\tl_new:N \g__ansa_rule_all_tl
\keys_define:nn { ansa/rule }
{
nonnumbered .bool_set:N = \l__ansa_rule_nonnumbered_bool,
nonnumbered .default:n = true,
nonnumbered .initial:n = false,
label .tl_set:N = \l__ansa_rule_label_tl,
header .tl_set:N = \l__ansa_rule_header_tl,
FUNKTORY .tl_set:N = \l__ansa_rule_funktory_tl,
OBLIG .tl_set:N = \l__ansa_rule_oblig_tl,
}
\cs_new_protected:Nn \__ansa_rule:
{
\__ansa_rule_add:n { \begin{tabular}{|p{5cm}|l|}\hline }
\bool_if:NTF \l__ansa_rule_nonnumbered_bool
{
\__ansa_rule_add_multi:V \l__ansa_rule_header_tl
}
{
\refstepcounter{rule}
\tl_if_empty:NF \l__ansa_rule_label_tl { \__ansa_rule_label:n {\l__ansa_rule_label_tl} }
\__ansa_rule_add_multi_number:Vx \l__ansa_rule_header_tl { \therule }
}
\__ansa_rule_add:n { \hline }
\tl_if_empty:NF \l__ansa_rule_funktory_tl
{
\__ansa_rule_add:V \l__ansa_rule_funktory_tl
\__ansa_rule_add:n { \\ }
}
\tl_if_empty:NF \l__ansa_rule_oblig_tl
{
\__ansa_rule_add:V \l__ansa_rule_oblig_tl
\__ansa_rule_add:n { \\ }
}
\__ansa_rule_add:n { \hline\end{tabular} }
\tl_use:N \l__ansa_rule_body_tl
}
\cs_new:Nn \__ansa_rule_label:n { \label{#1} }
\cs_new_protected:Nn \__ansa_rule_add:n
{
\tl_put_right:Nn \l__ansa_rule_body_tl { #1 }
}
\cs_generate_variant:Nn \__ansa_rule_add:n { V }
\cs_new_protected:Nn \__ansa_rule_add_multi_number:nn
{
\__ansa_rule_add:n { \multicolumn{2}{|l|}{\bfseries#1\hfill Rule~#2} \\ }
}
\cs_generate_variant:Nn \__ansa_rule_add_multi_number:nn { Vx }
\cs_new_protected:Nn \__ansa_rule_add_multi:n
{
\__ansa_rule_add:n { \multicolumn{2}{|l|}{\bfseries#1} \\ }
}
\cs_generate_variant:Nn \__ansa_rule_add_multi:n { V }
\ExplSyntaxOff
\begin{document}
\Rule{
nonnumbered,
header = {Rules in general},
FUNKTORY = {VALUE 1 & VALUE 2},
}
\Rule{
header = {Rule 1},
FUNKTORY = {X & Y},
label = {rule:1},
}
\allrules
\end{document}