我正在尝试做我认为相当简单的事情 - 在 CS 中使用 xargs 定义的宏。MWE:
\documentclass{article}
\usepackage{xargs}
\usepackage{etoolbox}
\makeatletter
\def\abx@foo@baz@bar{test}
\def\abx@field@original@default@test{baz}
\newcommandx*{\blx@imc@thefield}[3][1=original,2=default]{\csuse{abx@field@#1@#2@#3}}
\def\blx@getformat#1#2{%
\ifcsundef{abx@#1@\blx@imc@thefield{test}@#2}
{no}
{yes}}
\begin{document}
\blx@getformat{foo}{bar}
\makeatother
\end{document}
对我来说,这总是给出:
! Missing \endcsname inserted.
<to be read again>
\begingroup
l.17 \blx@getformat{foo}{bar}
我无论如何也想不出为什么。通过跟踪运行它,它会在内部 xargs 宏中死掉。这个\abx@field@original@default@test
宏本身工作得很好,只是不喜欢在测试中。如果我用普通的(当然没有可选参数)\ifcsundef
替换 xargs ,它就可以工作了。我试过保护 newcommandx 调用,试过将带有默认值的可选参数传递给宏等,但总是得到相同的错误。任何想法都非常感谢。\newcommandx
\def
答案1
这行不通,至少在使用 时行不通xargs
。在构造内部\csname
,所有内容都必须完全可扩展,或者由 TeX 允许在名称中使用的标记组成(字母、数字、空格、$
...)。但是,检测可选参数不是这样工作的:涉及到\futurelet
,但这里也有一个\begingroup
。
可以以可扩展的方式获取可选参数,但要受到一些限制。xparse
包为此提供了一个包装器
\documentclass{article}
\usepackage{xparse}
\usepackage{etoolbox}
\makeatletter
\def\abx@foo@baz@bar{test}
\def\abx@field@original@default@test{baz}
\DeclareExpandableDocumentCommand{\blx@imc@thefield}
{O{original}O{default}m}
{\csuse{abx@field@#1@#2@#3}}
\def\blx@getformat#1#2{%
\ifcsundef{abx@#1@\blx@imc@thefield{test}@#2}
{no}
{yes}}
\begin{document}
\blx@getformat{foo}{bar}
\makeatother
\end{document}
(虽然这不是一个文档命令!),而etextools
也提供了类似的概念。但是,我不确定我是否想以这种方式处理内部宏:我更喜欢只带有强制参数的东西。