.aux 文件中定义宏的宏不起作用

.aux 文件中定义宏的宏不起作用

以下是我尝试定义的一些宏(基于这个问题):

  • \odef{foo}{bar}foo将定义一个具有名称和值的“对象” bar
  • \objRef{foo}将插入“对象”的值foo

这些宏应该允许我引用定义的变量任何地方在我的文档中。例如,执行以下操作:

Lorem ipsum dolor \objRef{sentence-Ends/lipsum}.

% INSERT OTHER PARTS OF MY DOCUMENT HERE (CHAPTERS, SECTIONS, FIGURES, TABLES, ETC.)

Defining variables now... \odef{sentence-Ends/lipsum}{sit amet} Done!

应该产生

Lorem ipsum 痛苦???。

现在定义变量...完成!

在第一次运行 LaTeX 之后

Lorem ipsum dolor sit amet。

现在定义变量...完成!

第二次运行后。

我在 objectref.sty 中编写了此代码,但它并未按预期工作——???我的日志文件中总是出现页面和未定义警告。

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{objectref}[Create and reference custom variables in LaTeX documents]

\def\odef#1#2{\immediate\write\@auxout{\expandafter\def \csname obj:#1\endcsname {#2}}}
\def\objRef#1{\ifcsname obj:#1\endcsname \csname obj:#1\endcsname \else ??? \PackageWarning{objectref}{Object #1 undefined on input line \the\inputlineno.}\fi}

除其他外,我编译文档时生成的.aux 文件包含:

\def \obj:sentence-Ends/lipsum {sit amet}

哪个应该意味着一切都会正常工作(但事实并非如此)。

我的代码有什么问题?我该如何修复它?

答案1

主要问题是您应该使用\gdef而不是\def,因为.aux文件是在组内读取的。

第二个问题:使用你的代码你会得到

\def \obj:sentence-Ends/lipsum {...}

.aux文件中,但是这定义了\obj

第三个问题:如果你这样做

\odef{test}{\'amet}

.aux文件将包含垃圾(尝试一下)。

第四个问题:如果您打算\odef在段落中间说话,那么您在输出中就会得到虚假的空格。

建议的解决方案。

不要在文件中写入\defnor并使替换文本不扩展。也可以使用and 。\gdef.aux\@bsphack\@esphack

\documentclass{article}

\makeatletter

\newcommand{\odef}[2]{%
  \@bsphack
  \immediate\write\@auxout{\string\objectref@def{#1}{\unexpanded{#2}}}%
  \@esphack
}
\newcommand{\objectref@def}[2]{\global\@namedef{obj:#1}{#2}}

\newcommand{\objRef}[1]{%
  \ifcsname obj:#1\endcsname
    \csname obj:#1\endcsname
  \else
    ???%
    \PackageWarning{objectref}{Object #1 undefined on input line \the\inputlineno.}%
  \fi
}

\makeatother

\begin{document}

Lorem ipsum dolor \objRef{sentence-Ends/lipsum}

Defining variables now... \odef{sentence-Ends/lipsum}{sit \'amet} Done!

Defining variables now... Done!% added line to check spaces

\end{document}

.aux文件将

\relax 
\objectref@def{sentence-Ends/lipsum}{sit \'amet}
\gdef \@abspage@last{1}

输出为

在此处输入图片描述

如果我注释掉\@bsphack并且\@esphack,我得到

在此处输入图片描述

错误的间距很明显。

不同版本中第二个参数\odef在文件中安全扩展.aux;安全意味着重音和其他危险命令不需要受到保护。

这是通过 的更强大的功能实现的expl3,特别\text_expand:n是它精确地完成了我们需要的工作。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\odef}{mm}
 {
  \use:c { @bsphack }
  \iow_now:cx { @auxout } { \token_to_str:N \objectrefdef { #1 } { \text_expand:n { #2 } } }
  \use:c { @esphack }
 }

\NewDocumentCommand{\objectrefdef}{mm}
 {
  \prop_gput:Nnn \g_benz_objectref_prop { #1 } { #2 }
 }

\prop_new:N \g_benz_objectref_prop

\NewExpandableDocumentCommand{\objRef}{m}
 {
  \prop_if_in:NnTF \g_benz_objectref_prop { #1 }
   {
    \prop_item:Nn \g_benz_objectref_prop { #1 }
   }
   {
    ???
    \PackageWarning{objectref}{Object~#1~undefined}
   }
 }

\ExplSyntaxOff

\newcounter{Counter}

\begin{document}

Lorem ipsum dolor \objRef{sentence-Ends/lipsum}

Defining variables now... \odef{sentence-Ends/lipsum}{sit \'amet} Done!

Defining variables now... Done!% added line to check spaces

\stepcounter{Counter}

\odef{Name with space}{The counter value hêr\'e is \theCounter}

\stepcounter{Counter} % now 2

\objRef{Name with space}

\end{document}

请注意,第一个参数中的空格被尊重,并且使用时间的当前\odef值。Counter\odef

在此处输入图片描述

答案2

你没有给出最小的例子,所以我的回答只是理论上的,没有经过检验。定义\sdef宏的用法:

\sdef{text}{body}

将其定义\csname text\endcsname为主体。并在文件中使用它.aux。因此:

\def\sdef#1{\expandafter\gdef\csname#1\endcsname}
\def\odef#1#2{\immediate\write\@auxout{\string\sdef{obj:#1}{#2}}}
\def\objRef#1{\ifcsname obj:#1\endcsname \csname obj:#1\endcsname \else ??? \PackageWarning{objectref}{Object #1 undefined on input line \the\inputlineno.}\fi}

相关内容