发生了什么
假设\CurrentOption
文档中已经存在值为未知英文字符串的宏,我想创建另一个名称为大写值的宏\CurrentOption
。
例如,如果\CurrentOption
包含字符串word
,我想定义一个名为的宏Word
。
然而,错误
! Missing \endcsname inserted.
<to be read again>
\def
l.8 \expandafter\def\csname\temp
YesOrNo\endcsname{1}
在使用以下 MWE 编译时生成pdfLaTeX
:
\documentclass{article}
\usepackage{mfirstuc} % For \xmakefirstuc, to capitalize the first letter.
\begin{document}
\def\CurrentOption{word}
\edef\temp{\xmakefirstuc{\CurrentOption}}
\expandafter\xdef\csname\temp\endcsname{1} % <--- The error is here
\end{document}
我应该如何更改上述代码(不删除语句)\def\CurrentOption{word}
以便定义一个Word
以该值命名的宏?1
代码的通用目的
我正在编写一个包,其中应该处理不区分大小写的选项。例如,如果包接收选项word
,我希望包使用xdef
名称为的宏Word
。类似地,如果包接收选项wOrD
,我希望包使用xdef
相同的宏Word
。
我的计划是使用包中的以下代码来实现这一点:
\ProvidesPackage{courseMacros}[6/13/2022 v2.0, Miriam Briskman]
\RequirePackage{mfirstuc}
\DeclareOption*{
\edef\temp{\xmakefirstuc{\CurrentOption}}
\expandafter\xdef\csname\temp\endcsname{1}
}
\ProcessOptions\relax
% .... the rest of the package ...
注意\CurrentOption
以上是定义的宏扩展到当前选项的值。
! Missing \endcsname inserted.
尽管如此,在文件中使用上述包时仍会产生同样的错误TeX
。
控制台输出
编译第一个 MWE 时控制台的完整输出是
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (MiKTeX 22.3) (preloaded format=pdflatex.fmt)
restricted \write18 enabled.
entering extended mode
(example.tex
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-02-24>
(C:\Users\Miriam Briskman\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\arti
cle.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(C:\Users\Miriam Briskman\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\size
10.clo))
(C:\Users\Miriam Briskman\AppData\Local\Programs\MiKTeX 2.9\tex/latex/mfirstuc\
mfirstuc.sty
(C:\Users\Miriam Briskman\AppData\Local\Programs\MiKTeX 2.9\tex/latex/etoolbox\
etoolbox.sty))
(C:\Users\Miriam Briskman\AppData\Local\Programs\MiKTeX 2.9\tex/latex/l3backend
\l3backend-pdftex.def) (C:\temp\example.aux)
! Missing \endcsname inserted.
<to be read again>
\def
l.8 \expandafter\xdef\csname\temp
\endcsname{1}
?
迄今为止的研究
- 约瑟夫·赖特在他们的回答中https://tex.stackexchange.com/a/519/256551令人印象深刻地解释了 中的扩展工作原理
TeX
。但是,没有一个示例在 中使用宏\csname ... \endcsname
。 - 坎帕在他们的回答中https://tex.stackexchange.com/a/515203/256551成功地演示了如何在另一个宏的名称中使用一些宏
\a
和,但是和被定义为简单的字符串,和,而我的 MWE 中的宏本身正在调用一个宏。\b
\a
\b
\def\a{A}
\def\b{B}
\temp
- 当我将 MWE 更改为
\documentclass{article}
\usepackage{mfirstuc}
\begin{document}
\def\CurrentOption{word}
\edef\temp{\CurrentOption} % <--- \xmakefirstuc{\CurrentOption} changed to \CurrentOption
\expandafter\xdef\csname\temp\endcsname{1}
\end{document}
或者
\documentclass{article}
\usepackage{mfirstuc}
\begin{document}
\def\CurrentOption{word}
\expandafter\xdef\csname\CurrentOption\endcsname{1}
\end{document}
代码执行无错误。但是,这些更改会阻止使用 macro 将宏的名称大写\xmakefirstuc
。
软件规格
pdflatex --version
在我的 Windows 10 的 CMD 输出中执行
MiKTeX-pdfTeX 4.10 (MiKTeX 22.3)
© 1982 D. E. Knuth, © 1996-2021 Hàn Thế Thành
TeX is a trademark of the American Mathematical Society.
using bzip2 version 1.0.8, 13-Jul-2019
compiled with curl version 7.72.0; using libcurl/7.72.0 Schannel
compiled with expat version 2.2.10; using expat_2.2.10
compiled with jpeg version 9.4
compiled with liblzma version 50020052; using 50020052
compiled with libpng version 1.6.37; using 1.6.37
compiled with libressl version LibreSSL 3.1.4; using LibreSSL 3.1.4
compiled with MiKTeX Application Framework version 4.4; using 4.4
compiled with MiKTeX Core version 4.12; using 4.12
compiled with MiKTeX Archive Extractor version 4.0; using 4.0
compiled with MiKTeX Package Manager version 4.7; using 4.7
compiled with uriparser version 0.9.4
compiled with xpdf version 4.02
compiled with zlib version 1.2.11; using 1.2.11
应如何更正第一个 MWE 中的代码以消除错误,而不删除的定义\CurrentOption
,并且仍然能够将新创建的宏大写?
答案1
\documentclass{article}
\begin{document}
\def\CurrentOption{word}
\ExplSyntaxOn
\cs_generate_variant:Nn\text_titlecase:n{V}
\cs_new:cpn {\text_titlecase:V\CurrentOption}{1}
\ExplSyntaxOff
\Word
\end{document}
答案2
您无需任何工具即可解决您的任务\ExplSyntaxOn
,只需使用 TeX 原语即可:
\def\defoptionmacro#1#2\relax#3{%
\uppercase{\expandafter\xdef\csname #1}#2\endcsname{#3}%
}
% usage:
\def\CurrentOption{worD}
\lowercase\expandafter{\expandafter\defoptionmacro\CurrentOption}\relax{1}
% test:
\meaning\Word % it is macro:->1
首先,\lowercase
被处理并被\defoptionmacro word\relax{1}
调用。其次,\uppercase
将 应用于第一个标记,然后\csname...\endcsname
完成。
但恕我直言,您要求将第一个字符大写是因为您想避免重新定义现有宏或其他控制序列。这可以通过不同的方式实现:使用通常不存在于控制序列中的字符。例如:
\def\defoptionmacro#1\relax#2{\expandafter\xdef\csname option?#1\endcsname{#2}}
这样宏\option?word
就定义了。当然,你必须使用相同的前缀option?
using来使用选项定义的宏\csname...\endcsname
。