将参数提供给 xstring 宏

将参数提供给 xstring 宏

带有自动结束句号的脚注,评论是为了提供.有条件地在脚注中添加句号的可能性,这取决于脚注是否已经有句号。我立刻想到xstring将使用以下方法解决此条件\IfEndWith并尝试以下方法:

\documentclass{article}
\usepackage{xstring}% http://ctan.org/pkg/xstring
\makeatletter%
\long\def\@makefntext#1{%
  \parindent 1em\noindent \hb@xt@ 1.8em{\hss\@makefnmark}#1\IfEndWith{#1}{.}{}{.}}
\makeatother
\begin{document} 
Here is some text\footnote{This is a footnote}.
\end{document}

此处脚注以条件结尾,\IfEndWith{#1}{.}{}{.}用于检查#1(的参数\footnote)是否以 结尾.。如果为真,则不执行任何操作,否则将打印.。当您使用 时,此操作可以顺利运行\IfEndWith{xstring.}{.}{}{.},但此处不行。TeX 会抱怨Undefined control sequence

与文件扩展名相关的问题 -如何使 nonstopmode 真正不会因缺少输入文件而停止- 已解决(或没有像上述问题那样抱怨,但在方面具有类似的设置xstring):

\documentclass{article}
\usepackage{xstring}% http://ctan.org/pkg/xstring
\let\OldInputIfFileExists\InputIfFileExists
\renewcommand{\InputIfFileExists}[2]{%
  \IfFileExists{#1}%
    {\OldInputIfFileExists{#1}{#2}}%
    {\IfEndWith{#1}{.tex}{\typeout{INPUT #1}}{\typeout{INPUT #1.tex}}}%
  }
\begin{document}
This is dummy text.
\input{missing}% missing.tex is missing
\input{missing.tex}% missing.tex is missing
\end{document}

上述 MWE 中的想法(与原帖略有修改)是检查要编辑的文件是否\input存在,并将一些信息写入文件.log,并根据需要附加扩展名。编译上述内容后,文件.tex中选定的输出应该是.log

...
INPUT missing.tex
INPUT missing.tex
...

那么,为什么传递参数#1\IfEndWith在前一个 MWE 中引起问题,而在后一个 MWE 中却不会出现问题呢?

现在,我确实知道xstring文档明确指出:

[ xstring] 提供对“标记字符串”进行操作的宏和测试...“标记字符串”是任意性质的标记列表,但括号必须匹配,并且不允许使用 catcode 6 和 14(通常为%#)标记。除此之外,允许使用列表中的任何标记,无论结果代码如何,顺序均不限。

但是为什么第二个 MWE 编译时没有问题呢?我假设对我的使用进行的更正将扩展到所有xstring宏。

答案1

正如 unbonpetit 所建议的,一个问题是\IfEndWith执行一个\edef在其论点上。然而,论点\@makefntext不是脚注文本,而是

\rule\z@\footnotesep\ignorespaces This is a footnote\@finalstrut\strutbox

所以\IfEndWith永远无法成功找到最后一个点。您必须对传递给的参数进行检查\@footnotetext

\documentclass{article}
\usepackage{xstring,etoolbox}
\makeatletter
\patchcmd{\@footnotetext}
  {#1}
  {#1\protect\IfEndWith{\detokenize{#1}}{.}{}{.}}
  {}{}
\makeatother
\begin{document}
Here is some text\footnote{This is a footnote}.
Here is some text\footnote{This is a footnote.}.
\end{document}

然而,如果脚注文本以!或结尾,此操作将会失败?

AMS 采取的方法阿姆斯特丹有所不同,值得关注:

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
%%% taken from amsthm.sty
\def\@addpunct#1{%
  \relax\ifhmode
    \ifnum\spacefactor>\@m \else#1\fi
  \fi}
\def\nopunct{\spacefactor 1007 }
\def\frenchspacing{\sfcode`\.1006\sfcode`\?1005\sfcode`\!1004%
  \sfcode`\:1003\sfcode`\;1002\sfcode`\,1001 }
%%% end of borrowed code
\patchcmd{\@footnotetext}
  {#1}
  {#1\protect\@addpunct{.}}
  {}{}
\makeatother

\begin{document}
Here is some text\footnote{This is a footnote}.
Here is some text\footnote{This is a footnote.}.
Here is some text\footnote{Is this a footnote?}.
Here is some text\footnote{This is a footnote without final period\nopunct}.
\end{document}

\nopunct在特殊情况下,当不需要最后一个句号时,可以在脚注文本末尾添加(例如,如果脚注以 结尾\dots)。

答案2

在您的第一个 MWE 中,xstring 符合要求,因为它尝试使用 进行扩展#1\edef但不能,因为#1不是“ This is a footnote”:

\documentclass{article}
\usepackage{xstring}% http://ctan.org/pkg/xstring
\makeatletter%
\long\def\@makefntext#1{%
    \def\foo{#1}\show\foo}
\makeatother
\begin{document} 
Here is some text\footnote{This is a footnote}.
\end{document}

如您所见,#1 是“ \rule \z@ \footnotesep \ignorespaces This is a footnote\@finalstrut \strutbox”。查看\@footnotetext宏以了解其工作原理。

对于你的第二个问题,我不确定 xstring 是否隐含:

\documentclass{article}
\let\OldInputIfFileExists\InputIfFileExists
\renewcommand{\InputIfFileExists}[2]{%
  \IfFileExists{#1}%
    {\OldInputIfFileExists{#1}{#2}}%
    {foobar}%
  }
\begin{document}
This is dummy text.
\input{missing}% missing.tex is missing
\input{missing.tex}% missing.tex is missing
\end{document}

行为仍然相同。抱歉,我无法找到解决方案,我得去上班了!

相关内容