这个 MWE 被简化得太多,以至于代码失去了实用性。然而,代码仍然表现出我遇到的问题。
\documentclass{article}
\usepackage{pgffor}
\usepackage{etoolbox}
\makeatletter
\newcommand\aetest[1]{%%
\foreach \myl in {#1}
{%%
\expandafter\ae@parse@line\myl
}%%
}
%% read the next character and
%% branch off if its "*"
\def\ae@parse@line{%%
\@ifnextchar*
{\s@ae@parse@line}
{\@ae@parse@line[]}}
%% what to do if there is no "*"
\def\@ae@parse@line[#1]#2#3{%%
\fbox{Case #2}\hspace*{0.5em}%%
\def\ae@tmp{#3}%%
\typeout{==[base case][#2]==>\expandonce\ae@tmp}%%
\@ae@parse@content#3\@nil
}
%% If there's "*" the command now
%% expects three arguments with the argument
%% #3 dressed up like an optional argument.
%% After processing, pass arguments back to
%% "\@ae@parse@line"
\def\s@ae@parse@line*#1#2[#3]{%%
\def\ae@tmp{#2}%%
\typeout{==[star case]___==>\expandonce\ae@tmp}%%
\@ae@parse@line[#3]{#1}{#2}}
%% the "content" argument
%% may start with "[" which
%% signals that the "content"
%% should go in a `minipage`.
\def\@ae@parse@content{%%
\@ifnextchar[%%]
{\@ae@parse@mp}
{\@@ae@parse@content}}
%% formatting for "non-minipage" case
\def\@@ae@parse@content#1\@nil{%%
\textbf{#1}\par}
%% formatting for "minipage" case
\def\@ae@parse@mp[#1]#2\@nil{%%
\fbox{\begin{minipage}[t]{#1}
#2
\end{minipage}}\par}
\makeatother
\begin{document}
\aetest{
{A}{formatted correctly},
*{B} {formatted correctly}[],
*{C} {[4in] spurious space, and is \textbf{not} correct formatted}[],
*{D}{[4in] no spurious space and correctly formatted}[],
{E} {[2in] spurious space but still correctly formatted},
{F}{[3in] no spurious space, formatted correctly},
{G} {done as expected}}
\end{document}
生产
我感到好奇的是为什么 caseC
格式不正确,而 caseE
却正确。在我看来,如果它们都存在相同的虚假空格,那么我希望它们得到类似的处理。
查看log
文件发现,在caseB
和中空格被解析为参数的一部分,因此括号不会丢失。但是为什么在case和C
中括号会消失呢?E
G
这是日志文件的相关部分。==>
指向传递的参数的内容并显示虚假空格和括号。
==[base case][A]==>formatted correctly
==[star case]___==> {formatted correctly}
==[base case][B]==> {formatted correctly}
==[star case]___==> {[4in] spurious space, and is \textbf {not} correct formatted}
==[base case][C]==> {[4in] spurious space, and is \textbf {not} correct formatted}
==[star case]___==>[4in] no spurious space and correctly formatted
==[base case][D]==>[4in] no spurious space and correctly formatted
==[base case][E]==>[2in] spurious space but still correctly formatted
==[base case][F]==>[3in] no spurious space, formatted correctly
==[base case][G]==>done as expected
答案1
#2
中的参数\s@ae@parse@line
被分隔(用 分隔[
),因此 TeX 在查找它时不会跳过空格。并且,在 C 的情况下,初始空格会阻止括号剥离。
使用两个步骤:
%% If there's "*" the command now
%% expects three arguments with the argument
%% #3 dressed up like an optional argument.
%% After processing, pass arguments back to
%% "\@ae@parse@line"
\def\s@ae@parse@line*#1#2{%
\s@ae@parse@line@aux{#1}{#2}%
}
\def\s@ae@parse@line@aux#1#2[#3]{%
\def\ae@tmp{#2}%%
\typeout{==[star case]___==>\expandonce\ae@tmp}%%
\@ae@parse@line[#3]{#1}{#2}}
以这种方式论证#2
将正确地丢失括号,并且不会出现空格问题,因为 TeX 在寻找时会忽略它们未限定參數。
我没有改变任何其他东西,所以图像并不能反映真实情况。;-)
无论如何,如果你在尾随可选参数之前留一个空格,你就会得到相同的结果,就像
*{C} {[4in] spurious space, and is \textbf{not} correct formatted} []% <-- a space!
答案2
按照@egreg的建议,我想出了以下方法来处理有害的、虚假的空白:
\def\s@ae@parse@line*#1#2{%%
\def\ae@tmp@a{#1}%%
\def\ae@tmp@b{#2}%%
\s@ae@parse@line@aux}
\def\s@ae@parse@line@aux{%%
\@ifnextchar[%]
{\@s@ae@parse@line@aux}
{\@s@ae@parse@line@aux[]}}
\def\@s@ae@parse@line@aux[#1]{%%
\def\ae@tmp@c{#1}%%
\edef\ae@tmp{[\expandonce\ae@tmp@c]{\expandonce\ae@tmp@a}{\expandonce\ae@tmp@b}}%%
\expandafter\@ae@parse@line\ae@tmp}
作为egreg
建议,我处理选修的通过定义一个论点辅助的宏。但正如指出的那样,如果空格出现在 之前,它仍然会干扰预期解析[
。因此,我通过将前两个参数保存到宏来处理这个问题,然后我使用两个辅助宏。第一个测试是否有后续[
(非常方便地为我吞噬空格)。然后这个第三个参数也被保存到宏中。然后我使用扩展技巧\@ifnextchar
构建参数。\@ae@parse@line