我想使用\nameref
,hyperref
但我也希望能够在没有的情况下呈现我的文档hyperref
。
因此,我想定义一个包装命令nameref
(而不是自己定义“虚拟” \nameref
),具体取决于是否\nameref
定义。
答案最好与任何定义的命令一起使用,而不仅仅是\nameref
。
从类似的问题中,我试图得出一些解决方案不工作:
\newcommand{\checkAndDef}[1]{%
\ifcsname#1\endcsname%
\newcommand{\refn}[1]{\nameref{#1}}%
\else%
\newcommand{\refn}[1]{[#1]}% no \nameref available
\fi%
}
\checkAndDef{nameref}%
请注意,\checkAndDef
看起来很丑陋,我在无法进行文字检查后添加了它\nameref
。我想我需要比现在更详细地了解 TeX 和 LaTeX 才能解决这个问题。
第一个解决方案仿照 Werner 的提议(不起作用):
\newcommand{\namerefcheck}{%
\ifcsname{}nameref\endcsname%
\newcommand{\refn}[1]{\nameref{##1}}%
\else%
\newcommand{\refn}[1]{[\detokenize{##1}]}% no \nameref available
\fi%
}
\AtBeginDocument{\namerefcheck}
该“解决方案”定义\refn
为好像未加载 hyperref,无论是否加载。
笔记:如果您{}nameref
用替换\nameref
,那么它就会起作用(在我看来)。
答案1
这里发生了几件事:
在另一命令中定义命令时,需要重复使用参数符号。因此,
#1
应该变成##1
,#2
应该变成##2
,等等。从这个意义上讲,以下定义\checkAndDef
可能就是您想要的:\newcommand{\checkAndDef}[1]{% \ifcsname#1\endcsname% \newcommand{\refn}[1]{\nameref{##1}}% \else% \newcommand{\refn}[1]{[\detokenize{##1}]}% no \nameref available \fi% }
我添加了一个
\detokenize
到“无可用”选项,因为标签默认\nameref
可以包含一些奇怪的字符(如下划线)。_
hyperref
通常应该在所有包中最后加载,因为它与许多文档元素交互,而所有这些元素都可能被其他包含的包更改。因此,\checkAndDef
可能需要后\begin{document}
在某些情况下。这是 特别需要的\nameref
。
\documentclass{article}
\usepackage{hyperref}% Comment out or not
\newcommand{\checkAndDef}[1]{%
\ifcsname#1\endcsname
\newcommand{\refn}[1]{\nameref{##1}}%
\else
\newcommand{\refn}[1]{[\detokenize{##1}]}% no \nameref available
\fi
}
\AtBeginDocument{\checkAndDef{nameref}}
\begin{document}
\section{A section}\label{sec:section}
\refn{sec:section}
\end{document}
上述代码的结果是
何时hyperref
加载,以及
什么hyperref
时候不是已加载。
答案2
我提议
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\conditionaldef}{mmO{0}omm}
{% #1 = command to define
% #2 = command to test
% #3 = number of args,
% #4 = default optional
% #5 = replacement text if #2 exists
% #6 = replacement text if #2 doesn't exist
\AtBeginDocument
{
\cs_if_exist:NTF #2
{
\IfNoValueTF{#4}
{
\newcommand{#1}[#3]{#5}
}
{
\newcommand{#1}[#3][#4]{#5}
}
}
{
\IfNoValueTF{#4}
{
\newcommand{#1}[#3]{#6}
}
{
\newcommand{#1}[#3][#4]{#6}
}
}
}
}
\ExplSyntaxOff
你称之为
\conditionaldef{\refn}{\nameref}[1]{\nameref{#1}}{[\detokenize{#1}]}
完整示例。
\documentclass{article}
\usepackage{xparse}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\conditionaldef}{mmO{0}omm}
{% #1 = command to define
% #2 = command to test
% #3 = number of args,
% #4 = default optional
% #5 = replacement text if #2 exists
% #6 = replacement text if #2 doesn't exist
\AtBeginDocument
{
\cs_if_exist:NTF #2
{
\IfNoValueTF{#4}{\newcommand{#1}[#3]{#5}}}{\newcommand{#1}[#3][#4]{#5}}
}
{
\IfNoValueTF{#4}{\newcommand{#1}[#3]{#6}}{\newcommand{#1}[#3][#4]{#6}}
}
}
}
\ExplSyntaxOff
\conditionaldef{\refn}{\nameref}[1]{\nameref{#1}}{[\detokenize{#1}]}
\begin{document}
\section{Test}\label{test}
\refn{test}
\end{document}
输出是否hyperref
已加载
hyperref
如果未加载则输出
笔记
本质上,您使用的语法与 相同,因此也允许使用带有单个可选参数的命令。调用 时\newcommand
无需重复。#
\conditionaldef
没有xparse
\documentclass{article}
%\usepackage{hyperref}
%%% syntax
%% \conditionalref{<marg>}[<oarg>][<oarg>]{<marg>}{<marg>}
\makeatletter
\newcommand{\conditionaldef}[2]{%
\@ifnextchar[{\cond@def@opt{#1}{#2}}{\cond@def@noopt{#1}{#2}}%
}
\newcommand{\cond@def@noopt}[4]{%
\AtBeginDocument{%
\ifdefined#2%
\newcommand{#1}{#3}%
\else
\newcommand{#1}{#4}%
\fi
}%
}
\def\cond@def@opt#1#2[#3]{%
\@ifnextchar[{\cond@def@twoopt{#1}{#2}{#3}}{\cond@def@oneopt{#1}{#2}{#3}}%
}
\def\cond@def@oneopt#1#2#3#4#5{%
\AtBeginDocument{%
\ifdefined#2%
\newcommand{#1}[#3]{#4}%
\else
\newcommand{#1}[#3]{#5}%
\fi
}%
}
\def\cond@def@twoopt#1#2#3[#4]#5#6{%
\AtBeginDocument{%
\ifdefined#2%
\newcommand{#1}[#3][#4]{#5}%
\else
\newcommand{#1}[#3][#4]{#6}%
\fi
}%
}
\makeatother
\conditionaldef{\refn}{\nameref}[1]{\nameref{#1}}{[\detokenize{#1}]}
\begin{document}
\section{Test}\label{test}
\refn{test}
\end{document}
更简单的版本
当然,如果你只是想定义,上面的内容就是浪费时间一命令:一个简单的
\AtBeginDocument{%
\ifdefined\nameref
\newcommand{\refn}[1]{\nameref{#1}}%
\else
\newcommand{\refn}[1]{[\detokenize{#1}]}%
\fi
}
就足够了。上面的基础设施允许定义许多命令无需代码重复。
答案3
假设令牌\BizArReUnDEFiNeD
始终未定义,您可以执行以下操作:
\documentclass{article}
\makeatletter
% \checkAndDef{<other command>}%
% {<definition-command><new command><parameter text>}%
% {<new command's definition-text in case other command is undefined>}%
% {<new command's definition-text in case other command is defined>}
%
% <parameter text> can be omitted.
%
\newcommand\checkAndDef[4]{%
\AtBeginDocument{%
\ifx\BizArReUnDEFiNeD#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#2{#3}}{#2{#4}}%
}%
}%
\makeatother
\usepackage{hyperref}
%\csname @ifpackageloaded\endcsname{hyperref}{}{\usepackage{nameref}}
\checkAndDef{\nameref}{\newcommand*\refn[1]}{\detokenize{[#1]}}{\nameref{#1}}%
\begin{document}
\section{Test-Section}\label{test}%
Some text. Reference: \refn{test}
\end{document}