是否可以在 \DeclareDocumentCommand 中使用 \index{\command}?

是否可以在 \DeclareDocumentCommand 中使用 \index{\command}?

所以我一直在写一本书,我曾经用它来xparse创建一些命令和环境。现在,当事情快要完成时,我意识到有一个索引会很棒!我创建的一个环境接受一个参数,并给出一个带有参数的小框作为标题。所有这些框都使用表单作为foo: bar标题,我想索引bar

我意识到xstring可以帮助我,并测试了\index{\StrBehind{foo: bar}{:}}哪些工作没有麻烦(见MWE),但是当我声明命令

\DeclareDocumentCommand \cutindex {m}{\index{\StrBehind{#1}{:}}}

我得到了错误

! Argument of \reserved@a has an extra }.
---Mumbo which is better to read from MWE---
! Paragraph ended before \reserved@a was complete.

我也尝试过使用临时命令来保存字符串,但这也不起作用。

\newcommand{\tempor}{}
\DeclareDocumentCommand \cutindex {m}{
\renewcommand{\tempor}{\StrBehind{#1}{:}}
\index{\tempor}
}

我得出的结论是,\index{\command}在普通文本中确实有效,但在\DeclareDOcumentCommand(或\newcommand) 中无效。是否有可能以某种方式绕过此限制?

梅威瑟:

\documentclass{article}
\usepackage{xstring}
\usepackage{makeidx}
\usepackage{xparse}

\DeclareDocumentCommand \cutindex {m}{\index{\StrBehind{#1}{:}}}

\makeindex

\begin{document}
This works! \index{\StrBehind{Foo: Bar}{:}}

This does not work! \cutindex{Bar: Foo}

\printindex
\end{document}

答案1

Joseph Wright 的诊断是正确的:您无法执行诸如\StrBehind\index条目中的命令。

这是一个不同的解决方案,使用l3regex

\documentclass{article}
\usepackage{xparse,l3regex}
\usepackage{imakeidx}

\makeindex

\ExplSyntaxOn
\NewDocumentCommand{\cutindex}{m}
 {
  \robert_cutindex:n { #1 }
 }

\tl_new:N \l__robert_entry_tl

\cs_new_protected:Npn \robert_cutindex:n #1
 {
  \tl_set:Nn \l__robert_entry_tl { #1 }
  \regex_replace_once:nnN { .*? \: \s* } { } \l__robert_entry_tl
  \index{ \l__robert_entry_tl }
 }
\ExplSyntaxOff

\begin{document}

Here's a standard entry: \index{Foo}

This works! \cutindex{Bar: Foo}

And this also! \cutindex{Bar:Foo}

\printindex

\end{document}

请注意,冒号后的空格会被忽略,因此可以使用也可以不使用。搜索正则表达式会查找到第一个冒号(后跟零个或多个空格)之前的所有字符;替换操作就是将它们丢弃。

答案2

您可能需要查看.idx文件以查看这里的“工作”是否与您期望的完全一致:您会看到

\indexentry{\StrBehind{Foo: Bar}{:}}{1}
\indexentry{\let \reserved@d =*\def \par }{1}

原因是它\index逐字读取它的参数。当它不在另一个命令中时,这很好,但如果你已经获取了该参数,它就会失败。如果你已经标记化输入,也就是你使用

\DeclareDocumentCommand \cutindex {m}{\index{\StrBehind{#1}{:}}}

就像\StrBehind一个命令,而不是一个字符串。

还有一个问题是\StrBehind无法扩展,这意味着即使没有业务,\index您也不能简单地将其粘贴到您想要文本的地方。但是,您可以使用可选参数将结果存储在宏中,然后在正确的位置扩展它(它是一个字符串,所以这是安全的)。

\DeclareDocumentCommand \cutindex {m}{%
  \StrBehind{#1}{:}[\tempa]%
  \index{\tempa}%
}

(您会注意到我没有费心去扩展,\tempa因为我知道\index在写入.idx文件时会这样做。)

相关内容