检测活动字符后的空格不会处理尾随格式宏

检测活动字符后的空格不会处理尾随格式宏

有一个活动字符*(可以是任何字符,星号仅用于演示目的)。

如果后面的字符*是空格,则写入\marginpar{foo},否则写入\marginpar{bar}。这样就成功了。

活动字符可以有一个可选参数。可选参数必须紧跟在活动字符后面,否则它不会被视为宏参数,例如*[wut] blaor *[but]yum,但* [noo]where[noo]不会被解释为宏参数,因为它被空格分隔。这也有效。

我认为这是一个简单的任务,但是当活动字符后面的标记是格式化宏时,就会不断出现错误,例如*[flut]\textbf{...}

我偷借了一些 LaTeX2e 宏来满足我的需求,经过几个小时的反复试验,我能想到的最好的办法是:

\documentclass{book}
\usepackage{lipsum}

\makeatletter
% Do not skip space in contrast to \@ifnextchar.
\long\def\@ifonlynextchar#1#2#3{%
  \let\reserved@d=#1%
  \def\reserved@a{#2}%
  \def\reserved@b{#3}%
  \futurelet\@let@token\@ifonch}
\def\@ifonch{%
  \ifx\@let@token\reserved@d
    \let\reserved@c\reserved@a
  \else
    \let\reserved@c\reserved@b
  \fi
  \reserved@c}
% Check for trailing space
\long\def\@ifspace#1#2{%
  \def\reserved@a{#1}%
  \def\reserved@b{#2}%
  \futurelet\@let@token\@ifspc}
\def\@ifspc{%
  \if\@let@token\@sptoken
    \let\reserved@c\reserved@a
  \else
    \let\reserved@c\reserved@b
  \fi
  \reserved@c}

\def\foobar{%
  \@ifonlynextchar[{\foobar@opt}%
  {\foobar@{}}%
}
\def\foobar@opt[#1]{\foobar@{#1}}
\def\foobar@#1{%
  {\scriptsize #1}%
  \@ifspace{\foo}{\bar}%
}

\def\foo{\marginpar{foo}}
\def\bar{\marginpar{bar}}

\catcode`\*=13
\let*\foobar

\makeatother

\begin{document}

\lipsum[2][2] There is a trailing space* here should write \emph{foo} in margin.

There is a trailing space*[xy] should write \emph{foo} in margin and \emph{xy} before space. \lipsum[3][4]
There is a space between asterisk and bracket,* [za] should write \emph{foo} in margin and [za] as a literal (shall not be part of the macro argument).

\lipsum[1][3] There is no trailing space *should write \emph{bar}. Then, there is no trailing space but an optional argument so should *[bc]write \emph{bar} in margin and \emph{bc} before ``write.''

Macro after active char *\textbf{shall} detect no space and write \emph{bar} in margin. Then, with an optional argument *[de]\textbf{shall} write \emph{bar} in margin and emit \emph{de} before ``shall.''

\end{document}

预期成绩:

  • 最后一段中第一次出现的情况打印酒吧在边缘并且不会发出错误。
  • 最后一段中第二次出现打印, 和酒吧在边缘处不会发出错误。

实际结果:

  • 第一次发生时出错
! Undefined control sequence.
\reserved@c ->\@nil 
                    
l.60 Macro after active char *\textbf
                                     {shall} emit no space and write \emph{b...
  • 第二次发生时出错
! Undefined control sequence.
\reserved@c ->\@nil 
                    
l.60 ...en, with an optional argument *[de]\textbf
                                                  {shall} write \emph{bar} i...

我被困在这里了。作为一种解决方法,我可以发出 TeX 原语来消除错误,例如,bla bla *\relax\textbf{even more bla}但这违背了使用活动字符的意图。

活动角色应该足够智能,无需人工干预即可检测出任何非空格的标记。有人发现上述最小工作示例中的错误吗?有人能提出一个可行的解决方案吗?我将不胜感激。

答案1

你有一个简单的打字错误

\if\@let@token\@sptoken

应该

\ifx\@let@token\@sptoken

您正在扩展\@let@token并测试其扩展中的前两个标记。

相关内容