定义一个宏来对以 \\ 分隔的文本应用操作

定义一个宏来对以 \\ 分隔的文本应用操作

我希望定义这样一个命令(比如说\test)来将操作(比如说\action)应用于以 分隔的文本\\,例如\test{A\\B\\C}将变成

\action{A}\\\action{B}\\\action{C}

这类似于这个问题,但我无法调整那里的答案来实现我在这里想要的。我该如何定义这样的宏?

答案1

\DeclareListParserfrometoolbox就是为此而制作的,它允许您使用自定义列表分隔符定义列表解析器。(编辑:修复了一个缺点,感谢 cgnieder!)

\documentclass{article}
\usepackage{etoolbox}
\DeclareListParser{\mydocsvlist}{\\}
\newif\ifFirstItem
\newcommand{\action}[1]{\textbf{#1}}
\newcommand{\test}[1]{\begingroup
\FirstItemtrue
\renewcommand*{\do}[1]{\ifFirstItem\FirstItemfalse\else\\\fi\action{##1}}%
\mydocsvlist{#1}%
\endgroup}
\parindent0pt
\begin{document}
\test{A\\B\\C} 

\renewcommand{\action}[1]{\emph{#1}!}%
\test{A\\B\\C} 
\end{document}

在此处输入图片描述

答案2

有一种基于 TeX 基元的经典方法(也可能是最简单的方法):

\def\test#1{\testA#1\\\end\\}
\def\testA#1\\{\ifx\end#1\empty\else\action{#1}\expandafter\testA\fi}
\def\action#1{parameter is: #1\par}

\test{A\\B\\C}

例如,如果我们需要在动作之间插入一些内容\actionbetween,那么宏会稍微复杂一些,但它也是完全可扩展的:

\def\test#1{\testA#1\\\end\\\\}
\def\testA#1\\#2\\{\ifx\end#1\empty 
   \else\action{#1}\ifx\end#2\empty \else \actionbetween \fi
   \afterfi{\testA#2\\}\fi}
\def\afterfi#1#2\fi{\fi#1}

\def\action#1{parameter is #1\par}
\def\actionbetween{\string\\}

\test{A\\B\\C}

答案3

\documentclass{arlticle}
\usepackage{listofitems}
\newcommand\action[1]{%
  \setsepchar{\\}%
  \readlist\myparse{#1}%
  \foreachitem\z\in\myparse[]{%
    \expandafter\theaction\expandafter{\z}\myparsesep[\zcnt]%
  }%
}
\newcommand\theaction{\textit}
\begin{document}
\action{A\\B\\C plus more}

\renewcommand\theaction{\textsc}
\action{A\\B\\C plus more}
\end{document}

在此处输入图片描述

为了使其更加通用,您还可以将其设置为指定分隔符。请注意,在第二个示例中,分隔符标记不受小写字母的影响行动

\documentclass{arlticle}
\usepackage{listofitems}
\newcommand\action[1]{%
  \readlist\myparse{#1}%
  \foreachitem\z\in\myparse[]{%
    \expandafter\theaction\expandafter{\z}\myparsesep[\zcnt]%
  }%
}
\setsepchar{\\}
\newcommand\theaction{\textit}
\begin{document}
\action{A\\B\\C plus more}

\renewcommand\theaction{\textsc}
\setsepchar{(Hi Mom)\\}
\action{A (Hi Mom)\\B (Hi Mom)\\C plus more}
\end{document}

在此处输入图片描述

答案4

这是一个基于的相当通用的方法来满足您的需求expl3

输入在指定的分隔符处拆分(并修剪项目周围的空格);每个项目都按照模板指定的方式进行“装饰”,其中当前项目用 表示#1;最后,“装饰后的项目”以它们之间的指定分隔符(任何有效代码)输出。

##1请注意,如果\actonlist在另一个命令的定义中使用,则模板参数应该具有。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\actonlist}{ m m +m m}
 {% #1 = input separator
  % #2 = template
  % #3 = output separator
  % #4 = list
  \jinwen_actonlist:nnnn { #1 } { #2 } { #3 } { #4 }
 }

\seq_new:N \l__jinwen_actonlist_in_seq
\seq_new:N \l__jinwen_actonlist_out_seq

\cs_new_protected:Nn \jinwen_actonlist:nnnn
 {
  \seq_set_split:Nnn \l__jinwen_actonlist_in_seq { #1 } { #4 }
  \seq_set_map:NNn \l__jinwen_actonlist_out_seq \l__jinwen_actonlist_in_seq { #2 }
  \seq_use:Nn \l__jinwen_actonlist_out_seq { #3 }
 }

\ExplSyntaxOff

\begin{document}

\actonlist{\\}{\emph{#1}}{ (here a par)\par}{A\\B\\C}

\newcommand{\test}[1]{%
  \actonlist
    {\\}
    {\emph{##1}}
    { (here a par)\par}
    {#1}%
}

\test{A\\B\\C}

\newcommand{\testcomma}[1]{%
  \actonlist
    {,}
    {\textbf{##1}}
    { (here a par)\par}
    {#1}%
}

\testcomma{A, B, C}

\end{document}

从“here a par”可以看出,输出分隔符仅用于项之间。如果您还需要在末尾使用它,只需在 的定义中添加它\test,例如

\newcommand{\test}[1]{%
  \actonlist
    {\\}
    {\emph{##1}}
    { (here a par)\par}
    {#1} (here a par)\par
}

在此处输入图片描述

相关内容