假设我定义一个自定义命令\exercise
如下。
\newcounter{exercise}
\newcommand\exercise{%
\refstepcounter{exercise}%
\section*{Exercise \theexercise}%
}
现在,在下面的例子中,我想\nameref
从hyperref
包中使用。
\exercise\label{ex:first}
foo
\exercise\label{ex:second}
see \nameref{ex:first}
\exercise\label{ex:third}
bar
这样会生成“参见练习 2”而不是“参见练习 1”。似乎使用了“未展开”文本,将其展开为当前计数器值。我如何确保\nameref{ex:first}
生成“练习 1”?
(当然,我也可以直接使用Exercise~\ref{ex:first}
,但是这样更容易出错。而且,将来,我可能想用“问题”替换“练习”,而不必在文档中查找并替换所有出现的单词。)
完整示例:
\documentclass{article}
\usepackage{hyperref}
\newcounter{exercise}
\newcommand\exercise{%
\refstepcounter{exercise}%
\section*{Exercise \theexercise}%
}
\begin{document}
\exercise\label{ex:first}
foo
\exercise\label{ex:second}
see \nameref{ex:first}
\exercise\label{ex:third}
bar
\end{document}
答案1
确实,您需要传递的扩展\theexercise
,因为hyperref
不会对标题执行此操作。
\documentclass{article}
\usepackage{hyperref}
\newcounter{exercise}
\newcommand\exercise{%
\par % just in case
\refstepcounter{exercise}%
\begingroup\edef\x{\endgroup
\noexpand\section*{\unexpanded{Exercise} \theexercise}%
}\x
}
\begin{document}
\exercise\label{ex:first}
foo
\exercise\label{ex:second}
see \nameref{ex:first}
\exercise\label{ex:third}
bar
\end{document}
这是该文件的(删节版)内容.aux
:
\newlabel{ex:first}{{1}{1}{Exercise 1}{section*.1}{}}
\newlabel{ex:second}{{2}{1}{Exercise 2}{section*.2}{}}
\newlabel{ex:third}{{3}{1}{Exercise 3}{section*.3}{}}
它是
\newlabel{ex:first}{{1}{1}{Exercise \theexercise }{section*.1}{}}
\newlabel{ex:second}{{2}{1}{Exercise \theexercise }{section*.2}{}}
\newlabel{ex:third}{{3}{1}{Exercise \theexercise }{section*.3}{}}
用你的代码。
笔记。为什么\unexpanded{Exercise}
?在特殊情况下显然没有必要,但对于德语“Übung”来说却是必要的。
您也可以改用cleveref
。
\documentclass{article}
\usepackage{hyperref}
\usepackage[nameinlink]{cleveref}
\newcounter{exercise}
\newcommand\exercise{%
\par % just in case
\refstepcounter{exercise}%
\section*{Exercise \theexercise}
}
\crefname{exercise}{Exercise}{Exercises}
\begin{document}
\exercise\label{ex:first}
foo
\exercise\label{ex:second}
see \cref{ex:first}
\exercise\label{ex:third}
bar
\end{document}
两种情况下的输出是相同的。
我们能避免这个\edef\x{\endgroup
诡计吗?当然可以。
\documentclass{article}
%\usepackage{xparse} % not needed for LaTeX 2020-10-01 or later
\usepackage{hyperref}
\usepackage[nameinlink]{cleveref}
\ExplSyntaxOn
\NewDocumentCommand{\exercise}{}
{
\gooz_exercise:ne { \exercisename } { \theexercise }
}
\cs_new_protected:Nn \gooz_exercise:nn
{
\par % just in case
\refstepcounter{exercise}
\section*{#1~#2}
}
\cs_generate_variant:Nn \gooz_exercise:nn { ne }
\ExplSyntaxOff
\newcommand{\exercisename}{Exercise}
\newcounter{exercise}
\crefname{exercise}{\exercisename}{\exercisename s}
\begin{document}
\exercise\label{ex:first}
foo
\exercise\label{ex:second}
see \cref{ex:first} or \nameref{ex:first}
\exercise\label{ex:third}
bar
\end{document}
请注意,这cleveref
不是必需的,如果您愿意,只需删除相关调用即可\nameref
。