宏在表格环境中使用时失败

宏在表格环境中使用时失败

我正在尝试使用宏以更清晰的方式重新格式化内容。特别是,我希望转换如下字符串

foo; bar; baz;

进入

foo;
bar;
baz;

这是我目前拥有的宏及其在文档中的使用,工作正常:

\documentclass{article}
\usepackage{xstring}

\newcommand{\splitStatementsAndTextttize}[1]{%
  \StrCut{#1}{; }\leftPart\rightPart%
  \ifx\rightPart\empty
    \leftPart\\%
  \else
    \leftPart;\\ \splitStatementsAndTextttize{\rightPart}%
  \fi
}%

\begin{document}
\noindent \splitStatementsAndTextttize{foo; bar; baz;}
\end{document}

给出以下内容,并带有预期的排版:

foo;
bar;
baz;

现在,这个确切的内容实际上应该位于表格的单个单元格中。以下表格中某些单元格包含多行,这可以通过将内容放入表格来实现。

更新后的示例如下(相同的宏,不同的用途):

\documentclass{article}
\usepackage{xstring}

\newcommand{\splitStatementsAndTextttize}[1]{%
  \StrCut{#1}{; }\leftPart\rightPart%
  \ifx\rightPart\empty
    \leftPart\\%
  \else
    \leftPart;\\ \splitStatementsAndTextttize{\rightPart}%
  \fi
}%

\begin{document}
\begin{tabular}[x]{@{}l@{}}
  \splitStatementsAndTextttize{foo; bar; baz;}
\end{tabular}
\end{document}

由于某些我无法理解的原因而失败了......

! Undefined control sequence.
<argument> \rightPart 
                      
l.15 ...plitStatementsAndTextttize{foo; bar; baz;}

答案1

问题在于表格单元格组成一个组,因此两个单元格之间的任何本地分配都会丢失。例如:

\def\cmd{?}
\begin{tabular}{cc}
  \def\cmd{foo} \cmd & \cmd \\
\end{tabular}

将导致

在此处输入图片描述

因为当你切换到第二列时,分配就被恢复了。

您的示例中也发生了同样的情况:在第一行中分配了\leftPart\rightPart,然后您执行了\leftPart \\ something with \rightPart,但是当您尝试使用时\rightPart,分配已被还原(因为您结束了表行)并且\rightPart不再存在。

您有办法摆脱这种情况:首先是在表格行结束之前使用一些\expandafter来扩展:\rightPart

\newcommand{\splitStatementsAndTextttize}[1]{%
  \StrCut{#1}{; }\leftPart\rightPart%
  \ifx\rightPart\empty
    \leftPart\\%
  \else
    \leftPart;%
    \expandafter\\%
      \expandafter\splitStatementsAndTextttize
        \expandafter{\rightPart}%
  \fi
}%

第二种是根本不使用赋值(下面的代码使用分隔宏来抓取分隔的内容;并逐个排版;这不使用xstring):

\newcommand{\splitStatementsAndTextttize}[1]{%
  \splitthingyaux#1;\splitthingyaux;}
\def\splitthingyaux#1;{%
  \if\relax\detokenize{#1}\relax\else % if non-empty
    \ifx\splitthingyaux#1\else % if not reached the end
      \texttt{\ignorespaces#1;}\\% use item
      \expandafter\expandafter
      \expandafter\splitthingyaux
    \fi
  \fi}

还要注意是\begin{tabular}[x]错误的(它的行为与完全相同\begin{tabular}[c],但它只是一个实现细节)。

完整代码:

\documentclass{article}
\usepackage{xstring}

\newcommand{\splitStatementsAndTextttize}[1]{%
  \splitthingyaux#1;\splitthingyaux;}
\def\splitthingyaux#1;{%
  \if\relax\detokenize{#1}\relax\else % if non-empty
    \ifx\splitthingyaux#1\else % if not reached the end
      \texttt{\ignorespaces#1;}\\% use item
      \expandafter\expandafter
      \expandafter\splitthingyaux
    \fi
  \fi}

% \newcommand{\splitStatementsAndTextttize}[1]{%
%   \StrCut{#1}{; }\leftPart\rightPart%
%   \ifx\rightPart\empty
%     \leftPart\\%
%   \else
%     \leftPart;%
%     \expandafter\\%
%       \expandafter\splitStatementsAndTextttize
%         \expandafter{\rightPart}%
%   \fi
% }%

\begin{document}
\begin{tabular}[c]{@{}l@{}}
  \splitStatementsAndTextttize{foo; bar; baz;}
\end{tabular}
\end{document}

答案2

我必须更多地了解您想要使用它的方式,但一个简单的堆栈可以将水平输入转换为垂直输出。

\documentclass{article}
\usepackage{stackengine}

\newcommand{\splitStatementsAndTextttize}[1]{\Longunderstack[l]{#1}}

\begin{document}
\begin{tabular}[x]{@{}l@{}}
  \splitStatementsAndTextttize{foo; bar; baz;}
\end{tabular}
\end{document}

在此处输入图片描述

答案3

这是 的工作expl3。该设施将一次性\seq_map_function:NN交付整个令牌列表,因此只有在构建了整个令牌列表后,才会“看到” 。foo \\ bar \\ baz \\\\

您的代码的问题在于,您设置的循环从一个单元格开始tabular,而在另一个单元格结束,这是不可能的。

\documentclass{article}
\usepackage{xstring}

\ExplSyntaxOn

\NewDocumentCommand{\splitStatementsAndTextttize}{m}
 {
  % split the input at semicolons
  \seq_set_split:Nnn \l_tmpa_seq { ; } { #1 }
  % remove the last item
  \seq_pop_right:NN \l_tmpa_seq \l_tmpa_tl
  % if the last item is not empty, reinsert it back
  \tl_if_empty:NF \l_tmpa_tl { \seq_put_right:NV \l_tmpa_seq \l_tmpa_tl }
  % map the sequence adding \\ after each item
  \seq_map_function:NN \l_tmpa_seq \pamplemousse_add_endline:n
 }
\cs_new_protected:Nn \pamplemousse_add_endline:n
 {
  #1 \\
 }

\ExplSyntaxOff

\begin{document}

\begin{tabular}{@{}l@{}}
\hline
  \splitStatementsAndTextttize{foo; bar; baz;}
\hline
\end{tabular}
\qquad
\begin{tabular}{@{}l@{}}
\hline
  \splitStatementsAndTextttize{foo; bar; baz}
\hline
\end{tabular}

\end{document}

我添加\hline只是为了表明无论是否有尾随分号,输出都是相同的。

在此处输入图片描述

相关内容