修改现有的迭代代码

修改现有的迭代代码

我最近在网上发现了这段代码,它完全可以帮助我解决我遇到的一个问题。代码如下:

\documentclass{article}
\usepackage{catoptions}
\makeatletter
\robust@def*\inputcommandnames{\cpt@testopt\@inputcommandnames{general}}
\newletcs\inputcommandname\inputcommandnames
% #1=stack name, #2=input name(s)
\robust@def*\@inputcommandnames[#1]#2{%
  \ifblankFT{#1}{%
    \@latex@info{No stack name given: using 'general' instead}%
  }{%
    % It is possible to iterate over stack names, but leave this for now:
    % the use case isn't yet apparent.
    \ifinsetTF,{#1}{%
      \@latexerr{List '#1' not allowed}\@ehd
    }{}%
  }%
  \ifcsndefTF{name@stack@#1}{}{\csn@def{name@stack@#1}{}}%
  \ifcsndefTF{name@stackcount@#1}{}{\csn@def{name@stackcount@#1}{0}}%
  \cptdocommalist{#2}{%
    \csn@edef{name@stackcount@#1}%
      {\the\numexpr\usename{name@stackcount@#1}+1}%
    \csn@edef{name@stack@#1}{%
      \expandcsnonce{name@stack@#1}\noexpand
      \do{\usename{name@stackcount@#1}}{\unexpanded{##1}}%
    }%
  }%
}
\robust@def*\outputinnormalorder{\@outputcommandnames{normal}}
\newletcs\outputcommandnames\outputinnormalorder
\robust@def*\outputinreverseorder{\@outputcommandnames{reverse}}
% #1=listing/printing order, #2=stack name(s)
\robust@def*\@outputcommandnames#1#2{%
  \cptdocommalist{#2}{%
    \begingroup
    \let\reserved@a\relax
    \ifcsndefTF{name@stack@##1}{%
      % If the stack is defined but it is currently empty, ignore it
      % (but issue a warning). A 'verbose' option for triggering the
      % warning will be useful here, but it hasn't been provided:
      \ifcsnnullFT{name@stack@##1}{}{%
        \@latex@info{Stack '##1' is empty}%
        \def\reserved@a####1\endgroup{\endgroup}%
      }%
    }{%
      \@latexerr{Stack '##1' is not defined}\@ehd
    }%
    \reserved@a
    \xifstrcmpTF{#1}{normal}{%
      \let\do\curroutputformat
      \csname name@stack@##1\endcsname
    }{%
      \def\name@sentinel####1\name@stop{%
        \let\do\curroutputformat####1%
      }%
      \def\do####1####2####3\name@sentinel####4\name@stop{%
        ####3\name@sentinel\do{####1}{####2}####4\name@stop
      }%
      \usename{name@stack@##1}\name@sentinel\name@stop
    }%
    \endgroup
  }%
}
% \commandnameoutputformat<input no.><input item>
\robust@def*\commandnameoutputformat{%
  % Skip any spurious spaces before opening brace:
  \begingroup
  \toks0{##1##2}%
  \def\reserved@a{%
    \expandafter\endgroup\expandafter\def\expandafter
    \curroutputformat\the\toks\expandafter0\expandafter{\the\toks1}%
  }%
  \afterassignment\reserved@a\toks1=%
}
% If the stack isn't initialized after use, it will start building
% from the last count whenever it is called:
\robust@def*\initializecommandstacks#1{%
  \cptdocommalist{#1}{%
    \csn@def{name@stackcount@##1}{0}%
    \csn@def{name@stack@##1}{}%
  }%
}
\newletcs\initializecommandstack\initializecommandstacks

% Set empty stack 'xx' for warning later:
\csn@def{name@stack@xx}{}
\makeatother

% Examples:
\begin{document}
\inputcommandname{I wanted this whole sentence on this input, but when I use a comma it breaks the input and starts a new one}
\inputcommandname{If I don't use commas then it's ok}
\commandnameoutputformat{Input number #1 is: #2.\par}

Output:\par
\outputinnormalorder{general}
\end{document} 

它产生: 在此处输入图片描述

所以,问题就在这里:我希望代码能够完全按照它的功能运行(存储迭代命令的变量),但每次输入逗号时都不会自动创建新的输入。我一直试图改变它,但每次都失败了。你们能修改它,让它以这种方式工作吗(没有“逗号中断”)?谢谢你们的关注。

答案1

您可以使用以下方法获取灵活的代码expl3

\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs} % for the last example

\ExplSyntaxOn
% first define the user interface
\NewDocumentCommand{\addtolist}{O{general}m}
 {
  \marinho_lists_add:nn { #1 } { #2 }
 }
\NewDocumentCommand{\listoutputformat}{+m}
 {
  \marinho_lists_output_format:n { #1 }
 }
\NewDocumentCommand{\outputlist}{m}
 {
  \marinho_lists_output:n { #1 }
 }

% define the internal functions
\cs_new_protected:Nn \marinho_lists_add:nn
 {
  % create the sequence if it doesn't exist
  \seq_if_exist:cF { l_marinho_lists_#1_seq }
   {
    \seq_new:c { l_marinho_lists_#1_seq }
   }
  % add the item in the form {<number>}{<text>}
  \seq_put_right:cx { l_marinho_lists_#1_seq }
   {% compute the number based on the sequence length
    { \int_to_arabic:n { \seq_count:c { l_marinho_lists_#1_seq } + 1 } }
    { \exp_not:n { #2 } }
   }
 }

\cs_new_protected:Nn \marinho_lists_output_format:n
 {% the private function holds the format
  \cs_set:Nn \__marinho_lists_output_current:nn { #1 }
 }
\marinho_lists_output_format:n { #1~--~#2 \par } % a default

\cs_new_protected:Nn \marinho_lists_output:n
 {% map the sequence using the current format
  \seq_map_function:cN { l_marinho_lists_#1_seq } \__marinho_lists_item:n
 }
\cs_new:Nn \__marinho_lists_item:n
 {% \__marinho_lists_item:n receives an argument in the form {<number>}{<text>}
  % which we pass to \__marinho_lists_output_current:nn as two arguments
  \__marinho_lists_output_current:nn #1
 }

\ExplSyntaxOff

\setlength{\parindent}{0pt} % just for this example

\begin{document}

\section{Fill in the lists}

This section will have no other output.

\addtolist{%
  I wanted this whole sentence on this input, even with commas,
  without breaking the sentence
}
\addtolist{If I don't use commas then it's ok}

\addtolist[another]{Some text to go first}
\addtolist[another]{Some text to go second}
\addtolist[another]{Some text to go third}

\addtolist{This is in the general list}

\section{Output the \texttt{general} list}

\listoutputformat{Input number #1 is: #2\par}

\outputlist{general}

\section{Output the list named \texttt{another}}

{%
  \listoutputformat{(#1) #2\par}
  \outputlist{another}
}

\bigskip

Since the code above was in a group, the \texttt{general}
list will now be output identically as before.

\bigskip

\outputlist{general}

\section{We can do in a \texttt{tabular}}

\listoutputformat{#1 & #2 \\}% for a table

\begin{tabular}{ll}
\toprule
N & \multicolumn{1}{c}{Text} \\
\midrule
\outputlist{another}
\bottomrule
\end{tabular}

\end{document}

如果不带可选参数,\addtolist则添加到“常规”列表。您可以根据需要定义任意数量的列表。输出列表时,\listoutputformat如果默认格式不合适,请使用命令。这尊重分组,如示例所示。

最后的例子表明您可以使用\outputlist宏来构建表格,只要列表中的每个项目都形成一个表格行。

在此处输入图片描述

不同的版本允许您重新开始计数\addtolist*(仍然允许使用多个列表)。

\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs} % for the last example

\ExplSyntaxOn
% first define the user interface
\NewDocumentCommand{\addtolist}{sO{general}m}
 {
  \IfBooleanTF{#1}
   { \marinho_lists_add_restart:nn { #2 } { #3 } }
   { \marinho_lists_add_continue:nn { #2 } { #3 } }
 }
\NewDocumentCommand{\listoutputformat}{+m}
 {
  \marinho_lists_output_format:n { #1 }
 }
\NewDocumentCommand{\outputlist}{m}
 {
  \marinho_lists_output:n { #1 }
 }

% define the internal functions

\cs_new_protected:Nn \__marinho_lists_check:n
 {
  % create the sequence if it doesn't exist
  \seq_if_exist:cF { l_marinho_lists_#1_seq }
   {
    \seq_new:c { l_marinho_lists_#1_seq }
    \int_new:c { l_marinho_lists_#1_int }
    \int_incr:c { l_marinho_lists_#1_int }
   }
 }
\cs_new_protected:Nn \marinho_lists_add_restart:nn
 {
  \__marinho_lists_check:n { #1 }
  % add the item in the form {<number>}{<text>}
  \int_set:cn { l_marinho_lists_#1_int } { 1 }
  \seq_put_right:cx { l_marinho_lists_#1_seq }
   {
    { \int_eval:n { \int_use:c { l_marinho_lists_#1_int } } }
    { \exp_not:n { #2 } }
   }
  \int_incr:c { l_marinho_lists_#1_int }
 }
\cs_new_protected:Nn \marinho_lists_add_continue:nn
 {
  \__marinho_lists_check:n { #1 }
  % add the item in the form {<number>}{<text>}
  \seq_put_right:cx { l_marinho_lists_#1_seq }
   {% compute the number based on the sequence length
    { \int_eval:n { \int_use:c { l_marinho_lists_#1_int } } }
    { \exp_not:n { #2 } }
   }
  \int_incr:c { l_marinho_lists_#1_int }
 }

\cs_new_protected:Nn \marinho_lists_output_format:n
 {% the private function holds the format
  \cs_set:Nn \__marinho_lists_output_current:nn { #1 }
 }
\marinho_lists_output_format:n { #1~--~#2 \par } % a default

\cs_new_protected:Nn \marinho_lists_output:n
 {% map the sequence using the current format
  \seq_map_function:cN { l_marinho_lists_#1_seq } \__marinho_lists_item:n
 }
\cs_new:Nn \__marinho_lists_item:n
 {% \__marinho_lists_item:n receives an argument in the form {<number>}{<text>}
  % which we pass to \__marinho_lists_output_current:nn as two arguments
  \__marinho_lists_output_current:nn #1
 }

\ExplSyntaxOff

\setlength{\parindent}{0pt} % just for this example

\begin{document}

\section{Fill in the lists}

This section will have no other output.

\addtolist{%
  I wanted this whole sentence on this input, even with commas,
  without breaking the sentence
}
\addtolist{If I don't use commas then it's ok}

\addtolist{This is in the general list}

\addtolist*{This will have number 1}

\addtolist{This will have number 2}

\section{Output the \texttt{general} list}

\listoutputformat{Input number #1 is: #2\par}

\outputlist{general}

\section{We can do in a \texttt{tabular}}

\listoutputformat{#1 & #2 \\}% for a table

\begin{tabular}{lp{6cm}}
\toprule
N & \multicolumn{1}{c}{Text} \\
\midrule
\outputlist{general}
\bottomrule
\end{tabular}

\end{document}

在此处输入图片描述

答案2

您发布的几乎所有代码都是通过逗号分隔列表实现的\cptdocommalist,但我认为您的问题意味着您根本不想要这样,但也许

在此处输入图片描述

\documentclass{article}

\newcount\mycount
\newtoks\mylist

%odd name for this command? what is the "name" here?
\def\inputcommandname#1{%
\advance\mycount1
\mylist\expandafter{\the\expandafter\mylist
                    \expandafter\mydo\expandafter
                    {\the\mycount}{#1}}}
\def\commandnameoutputformat{\def\mydo##1##2}
\def\outputinnormalorder{\the\mylist}

\begin{document}
\inputcommandname{I wanted this whole sentence on this input, but when I use a comma it breaks the input and starts a new one}
\inputcommandname{If I don't use commas then it's ok}

\commandnameoutputformat{\par Input number #1 is: #2.\par}

Output:\par
\outputinnormalorder
\end{document} 

相关内容