完全展开 toks 并保存以供日后使用(附录包含正文中表格的精确副本)

完全展开 toks 并保存以供日后使用(附录包含正文中表格的精确副本)

我有一个包含一些复杂表格的文档,这些表格由一个带有\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\labelrule

我还通过删除所有\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 页:

第 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}

在此处输入图片描述

相关内容