有一个活动字符*
(可以是任何字符,星号仅用于演示目的)。
如果后面的字符*
是空格,则写入\marginpar{foo}
,否则写入\marginpar{bar}
。这样就成功了。
活动字符可以有一个可选参数。可选参数必须紧跟在活动字符后面,否则它不会被视为宏参数,例如*[wut] bla
or *[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
并测试其扩展中的前两个标记。