在此链接的答案中,如何在写入 aux 文件时在变量名中拥有一个变量:https://tex.stackexchange.com/a/416272/192717
例如,来自上面的链接:
\edef\mysuffix{helloworld}
% define variable with variable suffix \mysuffix
\definevalue{tester\mysuffix}{42}
% and use it elsewhere
\usevalue{tester\mysuffix}
目前,我收到了这个可以理解的错误:
! Undefined control sequence.
<argument> usevalue@tester\mysuffix
l.37 ... \global \@namedef {tester\mysuffix }...
据我所知,如果我们能够扩展并在 aux 文件中写入变量名,问题就会得到解决,如下所示:
\global \@namedef {testerhelloworld }...
答案1
不要使用\unexpanded
。
\documentclass{article}
\makeatletter
\newcommand{\usevalue}[1]{%
\ifcsname usevalue@#1\endcsname
\csname usevalue@#1\endcsname
\else
??%
\fi
}
\newcommand{\definevalue}[2]{%
\begingroup\edef\x{\endgroup
\write\@auxout{%
\global\string\@namedef{usevalue@#1}{#2}%
}%
}\x
}
\makeatother
\def\mysuffix{helloworld}
\begin{document}
\usevalue{tester\mysuffix}
\definevalue{tester\mysuffix}{42}
\end{document}
这将打印“42”。
该文件的内容.aux
是
\relax
\global \@namedef{usevalue@testerhelloworld}{42}
但是,只要你定义\mysuffix
前 \begin{document}
正如它应该。
\documentclass{article}
\makeatletter
\newcommand{\usevalue}[1]{%
\ifcsname usevalue@#1\endcsname
\csname usevalue@#1\endcsname
\else
??%
\fi
}
\newcommand{\definevalue}[2]{%
\write\@auxout{%
\unexpanded{\global\@namedef{usevalue@#1}{#2}}%
}
}
\makeatother
\newcommand{\mysuffix}{helloworld}
\begin{document}
Something with \usevalue{tester\mysuffix}.
Something else.
Now we can define \texttt{tester} and use again it: \usevalue{tester\mysuffix}.
\definevalue{tester\mysuffix}{42}
\end{document}
答案2
您可以实现类似于现有的LaTeX 2ε 内核机制的\label
定义和检索值的基础结构。\ref
下面的示例提供了以下用户宏:
\valueundefinederror{⟨name of value⟩}
如果值未定义,则触发错误消息,否则不执行任何操作。
对应于\refused
Heiko Oberdiek 的 refcount 包。\usevalue[{⟨tokens in case value is undefined⟩}]{⟨name of value⟩}
如果没有提供可选参数,则 在值未定义的情况下传递。如果没有提供可选参数, 则对应于LaTeX 2ε-kernel。
\valueundefinederror{⟨name of value⟩}\nfss@text{\reset@font\bfseries??}
\ref
\usevalueexpandable{⟨name of value⟩}{⟨tokens in case value is undefined⟩}
对应于 Heiko Oberdiek 的 refcount 包的 \getrefnumber。
\immediatedefinevalue{⟨name of value⟩}{⟨tokens to deliver when using the value⟩}
几乎与LaTeX 2ε 内核的
\def\@currentlabel{...}
...相对应。 与 不同,立即完成 .aux 文件。)\label{...}
\label
\write
\definevalue{⟨name of value⟩}{⟨tokens to deliver when using the value⟩}
对应于 LaTeX 2ε 内核的
\def\@currentlabel{...}
...。 与 一样,到 .aux 文件的操作也延迟完成。\label{...}
\label
\write
既有和的扩展,也
\immediatedefinevalue
有形成标记的扩展\definevalue
⟨tokens to deliver when using the value⟩
⟨name of value⟩
不是在将数据写入 .aux 文件时被阻止。
下面的示例提供了一些与 LaTeX 2ε 内核基础架构的挂钩,用于在值发生变化/未定义/多次定义时传递警告消息/错误消息。
\documentclass[landscape]{article}
\makeatletter
%%=====================================================================================
%% Layout of example document
%%=====================================================================================
\@ifundefined{pagewidth}{}{\pagewidth=\paperwidth}
\@ifundefined{pdfpagewidth}{}{\pdfpagewidth=\paperwidth}
\@ifundefined{pageheight}{}{\pageheight=\paperheight}
\@ifundefined{pdfpageheight}{}{\pdfpageheight=\paperheight}
\textwidth=\paperwidth
\oddsidemargin=2.5cm
\advance\textwidth-2\oddsidemargin
\advance\oddsidemargin-1in
\evensidemargin=\oddsidemargin
\marginparwidth=1.5cm
\marginparsep=.5cm
\parindent=0ex
\parskip=\bigskipamount
\pagestyle{empty}%
%%=====================================================================================
\makeatother
\makeatletter
%%=====================================================================================
%% Switches and helper-macros for triggering error-messages/
%% warnings in case of undefined/multiply defined/changed values
%%=====================================================================================
\newif\if@valueschanged\global\@valueschangedfalse
\newcommand*\@valuesmultiplydefined{}%
\newcommand*\@valuesundefined{}%
\newcommand*\G@valueundefinedtrue{%
\gdef\@valuesundefined{\@latex@warning@no@line{There were undefined values}}%
}%
%%=====================================================================================
%% \valueundefinederror{<name of value>}
%% Trigger error-message if value is undefined, else do nothing.
%% (Corresponds to \refused of Heiko Oberdiek's refcount-package.)
%%=====================================================================================
\newcommand\valueundefinederror[1]{%
\@bsphack
\begingroup
\@ifundefined{usevalue@#1}{%
\protect\G@valueundefinedtrue
\@latex@warning{Value `#1' on page \thepage \space undefined}%
}{}%
\endgroup
\@esphack
}%
%%=====================================================================================
%% \usevalue[{<tokens in case value is undefined>}]{<name of value>}
%%
%% If no optional argument is provided,
%% \valueundefinederror{<name of value>}\nfss@text{\reset@font\bfseries??}%
%% is delivered.
%% (Corresponds to \ref of the LaTeX2e-kernel if no optional argument is provided.)
%%=====================================================================================
\@ifdefinable\usevalue{%
\DeclareRobustCommand\usevalue{\kernel@ifnextchar[{\@usevalue}{\@@usevalue}}%
}%
\@ifdefinable\@@usevalue{%
\long\def\@@usevalue#1{\usevalueexpandable{#1}{\valueundefinederror{#1}\nfss@text{\reset@font\bfseries??}}}%
}%
\@ifdefinable\@usevalue{\long\def\@usevalue[#1]#2{\usevalueexpandable{#2}{#1}}}%
%%=====================================================================================
%% \usevalueexpandable{<name of value>}{<tokens in case value is undefined>}
%% (Corresponds to \getrefnumber of Heiko Oberdiek's refcount package.)
%%=====================================================================================
\newcommand{\usevalueexpandable}[2]{%
\@ifundefined{usevalue@#1}{#2}{\csname usevalue@#1\endcsname}%
}%
%%=====================================================================================
%% \immediatedefinevalue{<name of value>}{<tokens to deliver when using the value>}
%% (Almost corresponds to \def\@currentlabel{...}...\label{...} of the LaTeX2e-kernel.
%% Unlike with \label, the \write is done immediately.)
%%=====================================================================================
\@ifdefinable\immediatedefinevalue{%
\DeclareRobustCommand{\immediatedefinevalue}{%
\@definevalue{\immediate\write\@auxout}%
}%
}%
%%=====================================================================================
%% \definevalue{<name of value>}{<tokens to deliver when using the value>}
%% (Corresponds to \def\@currentlabel{...}...\label{...} of the LaTeX2e-kernel.
%% Like with \label, the \write is done delayed.)
%=====================================================================================
\@ifdefinable\definevalue{%
\DeclareRobustCommand{\definevalue}{%
\@definevalue{\let\thepage\relax\@@definevalue\@auxout}%
}%
}%
\newcommand\@definevalue[3]{%
\@bsphack
\begingroup
\let\protect\noexpand
#1{\string\@valuedef{#2}{#3}}%
\endgroup
\if@nobreak\ifvmode\nobreak\fi\fi
\@esphack
}%
\newcommand\@@definevalue[2]{\write#1{\unexpanded\expandafter{\expanded{#2}}}}%
%%%=====================================================================================
%% \@valuedef{<name of value>}
%% (Corresponds to \newlabel of the LaTeX2e-kernel.)
%%%=====================================================================================
\newcommand\@valuedef[1]{\@@valuedef{#1}{usevalue}}%
%%=====================================================================================
%% \@@valuedef{<name of value>}{<prefix for internal macros>}{<tokens to deliver when using the value>}
%% (Corresponds to \@newl@bel / \@testdef of the LaTeX2e-kernel.)
%%=====================================================================================
\newcommand\@@valuedef[3]{%
\begingroup
% Hashes were doubled while writing to \@auxout. Let's use a macro for halving them.
\def\@tempa{#1}%
\ifx\@newl@bel\@testdef\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
{%
\@ifundefined{#2@\@tempa}\relax{%
\gdef\@valuesmultiplydefined{%
\@latex@warning@no@line{There were multiply-defined values}%
}%
\@latex@warning@no@line{Value `\@tempa' multiply defined}%
}%
\global\@namedef{#2@\@tempa}{#3}%
}{%
\def\reserved@a{#3}%
\expandafter\ifx\csname#2@\@tempa\endcsname\reserved@a
\else
\global\@valueschangedtrue
\fi
}%
\endgroup
}%
%%=====================================================================================
%% This hooks into \@refundefined (which is executed by \enddocument)
%% for delivering messages in case of undefined/multiply defined/changed values:
%%=====================================================================================
\AtEndDocument{%
\@ifundefined{@refundefined}\gdef\g@addto@macro\@refundefined{\valueschangedmessage}%
}%
\newcommand\valueschangedmessage{%
\@valuesundefined
\if@filesw
\ifx\@valuesmultiplydefined\@empty
\if@valueschanged
\@latex@warning@no@line{Value(s) may have changed. Rerun to get value(s) right}%
\fi
\else
\@valuesmultiplydefined
\fi
\fi
}%
%%=====================================================================================
\makeatother
\begin{document}
\fbox{\parbox{\dimexpr\textwidth-2\fboxsep-2\fboxrule\relax}{Let's see the meaning
of the underlying macro:}}
\makeatletter
\verb|\meaning\usevalue@testerhelloworld|: \texttt{\meaning\usevalue@testerhelloworld}
\makeatother
\fbox{\parbox{\dimexpr\textwidth-2\fboxsep-2\fboxrule\relax}{Now let's use the
unexpandable variant with the optional argument which by default does trigger
(unexpandable) error-messages in case of the value not being defined/available:}}
\underline{Here \texttt{\string\mysuffix} is not yet defined:}
\verb|\usevalue{testerhelloworld}|: \usevalue{testerhelloworld}
\underline{Here \texttt{\string\mysuffix} is defined:}
\def\mysuffix{helloworld}%
\verb|\def\mysuffix{helloworld}| $\to$ \texttt{\string\mysuffix:\ \meaning\mysuffix}
\verb|\usevalue{tester\mysuffix}|: \usevalue{tester\mysuffix}
\fbox{\parbox{\dimexpr\textwidth-2\fboxsep-2\fboxrule\relax}{Now let's use the
expandable variant which does not trigger (unexpandable) error-messages
in case of the value not being defined/available:}}
Trigger the error-message about the value being undefined ``by hand'' if necessary:
\verb|\valueundefinederror{tester\mysuffix}|
\valueundefinederror{tester\mysuffix}
Perform something within an expansion-context where non-expandable things would disturb:
\verb|Value \texttt{tester\mysuffix} is \ifnum\usevalueexpandable{tester\mysuffix}{-1}=-1 un\fi defined.|:\\
Value {\tt tester\string\mysuffix} is \ifnum\usevalueexpandable{tester\mysuffix}{-1}=-1 un\fi defined.
\fbox{\parbox{\dimexpr\textwidth-2\fboxsep-2\fboxrule\relax}{Here the value \texttt{testerhelloworld} is
defined in terms of \texttt{\string\mysuffix}:}}
\verb|\immediatedefinevalue{tester\mysuffix}{42}|%
\immediatedefinevalue{tester\mysuffix}{42}%
\end{document}