考虑以下样式文件goat.sty
:
\NeedsTeXFormat{LaTeX2e}[2014/05/01]
\ProvidesPackage{goat}[2014/10/16 goat]
\DeclareOption{mammalbirdfish}{
\makeatletter
\begingroup
\catcode`\_=\active
\protected\gdef_{\@ifnextchar|\subtextup\sb}
\endgroup
\def\subtextup|#1|{\sb{\textup{#1}}}
\AtBeginDocument{\catcode`\_=12 \mathcode`\_=32768}
\makeatother}
\ExecuteOptions{mammalbirdfish}
\ProcessOptions
当我尝试在 LaTeX 文档中加载该包并执行时\usepackage{goat}
,出现以下错误:
! Missing control sequence inserted.
<inserted text>
\inaccessible
l.13 \ExecuteOptions{mammalbirdfish}
如何将上面的代码块放入我的样式文件中?
PS:我之前从来没有写过样式文件,所以如果我的问题答案很简单,请原谅我。
更新
我也不能把
\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
进入我的风格文件
\NeedsTeXFormat{LaTeX2e}[2014/05/01]
\ProvidesPackage{goat}[2014/10/16 goat]
\RequirePackage{expl3}
\DeclareOption{macros}{
\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
}
\ExecuteOptions{macros}
\ProcessOptions
当我编写文档时
\documentclass{article}
\usepackage{goat}
\begin{document}
test
\end{document}
它给出了错误
! Undefined control sequence.
\ds@makroer ...scriptfalse \par \ExplSyntaxOn \cs
_new_eq:NN \calc \fp _eval...
我该如何解决?
(如果我应该把更新问题作为一个新问题提出,请告诉我;它被放在这里是因为我思考这可能是一个类似的问题。
答案1
让我们看看会发生什么
\DeclareOption{mammalbirdfish}{
\makeatletter
\begingroup
\catcode`\_=\active
\protected\gdef_{\@ifnextchar|\subtextup\sb}
\endgroup
\def\subtextup|#1|{\sb{\textup{#1}}}
\AtBeginDocument{\catcode`\_=12 \mathcode`\_=32768}
\makeatother}
\ExecuteOptions{mammalbirdfish}
\ProcessOptions
\makeatletter
从到 的代码\makeatother
是作为 的参数给出的\DeclareOption
,因此它已经被标记化,特别是,_
之后的\gdef
类别代码为 8,因此\gdef
当代码为执行(存储它不是问题,因为 TeX 此时不会解释命令)。
在类或包文件中,几乎不需要发出\makeatletter
and ,因为它们是在末尾隐式使用and读取的。更准确地说,类或包文件中的这些命令通常是错误的,除非它们作为宏定义的一部分出现。在这种情况下,它们是\makeatother
\makeatletter
\makeatother
错误的,因为当\ProcessOptions
扩展选项的代码时mammalbirdfish
,\makeatother
将破坏对类或包中代码的所有后续读取。
请注意,将该代码设置为无论如何都会执行的选项是无稽之谈:这样的选项永远不应该传递给\ExecuteOptions
。
然而,最重要的问题是的类别代码_
。我将展示一种不同于设置条件并在\ProcessOptions
条件为真后执行代码的策略。
\begingroup\lccode`\~=`\_
\lowercase{\endgroup
\DeclareOption{mammalbirdfish}{%
\protected\gdef~{\@ifnextchar|\subtextup\sb}%
\def\subtextup|#1|{\sb{\textup{#1}}}%
\AtBeginDocument{\catcode`\_=12 \mathcode`\_=\string"8000 }%
}%
}
之所以有效,是因为代码中没有大写字符标记,因此只有~
(已经处于活动状态) 才会转换为 (活动) _
。
类似的问题还有
\DeclareOption{macros}{
\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
}
应该是
\ExplSyntaxOn
\DeclareOption{macros}{
\cs_new_eq:NN \calc \fp_eval:n
}
\ExplSyntaxOff
否则字符:
和_
将被标记为“其他字符”。
答案2
我不确定我的评论是否比泥巴还不清楚,但对于评论来说代码太多了——抱歉。如果可以的话,我很乐意稍后删除它。
\NeedsTeXFormat{LaTeX2e}[2014/05/01]
\ProvidesPackage{goat}[2014/10/16 goat]
\newif\ifmammalbirdfish
\mammalbirdfishfalse
\DeclareOption{mammalbirdfish}{%
\mammalbirdfishtrue}
\ExecuteOptions{mammalbirdfish}
\ProcessOptions
\ifmammalbirdfish
\begingroup
\catcode`\_=\active
\protected\gdef_{\@ifnextchar|\subtextup\sb}%
\endgroup
\def\subtextup|#1|{\sb{\textup{#1}}}%
\AtBeginDocument{%
\catcode`\_=12 \mathcode`\_=32768}%
\fi