这prettyref
包的工作原理是检查表单的标签\label{format:name}
并仅基于创建引用format:
。文档说:
除了将 [sic] 格式与名称分开外,请勿
:
在标签内的任何地方使用该字符。
不幸的是,我有一个用例,其中自动生成了一个带有三部分标签的 .tex 文件\label{first:second:name}
。 下面是一个 MWE。 的实现prettyref
非常简单,所以我想知道它是否可以调整以容忍三部分标签。
\documentclass[a4paper]{article}
\usepackage{graphicx}
\usepackage{prettyref}
\newrefformat{diag:cla}{Class Diagram \ref{#1}}
\newrefformat{diag:seq}{Sequence Diagram \ref{#1}}
\begin{document}
Behold: \prettyref{diag:seq:FirstExportedDiagram}.
\begin{figure}[h]
\includegraphics[scale=0.5]{sequencediagram1.pdf}
\caption{The first sequence diagram.}
\label{diag:seq:FirstExportedDiagram}
\end{figure}
\end{document}
编辑:为了完整起见,我应该补充一下还仍然希望保留使用旧单冒号标签的能力。自动导出的 .tex 文件实际上同时具有这两种功能(例如\label{datatype:integer}
,将使用 格式化\newrefformat{datatype}{\textit{\ref{#1}}}
)。并不是说当前的答案与此不符,但让未来的读者知道这一点是件好事。
我还应该提到,作为作者,我非常依赖自动完成功能来使用这些导出的标签(它们很多,而且很长)。对于某些格式技巧,要记住这一点。
答案1
11
\def\prettyref#1{\@prettyref#1:}
\@prettyref
内部宏\@prettyref
完成所有工作。它需要两个由 分隔的参数:
。第一个参数是格式名称。如果格式尚未定义,则会发出警告并\ref
使用。否则,将格式化引用。\@prettyref
使用 LaTeX 宏\ref
和\pageref
访问\newlabel
数据结构。希望这可以使该包足够强大,可以与其他各种包一起使用。12
\def\@prettyref#1:#2:{%
13\expandafter\ifx\csname pr@#1\endcsname\relax%
14\PackageWarning{prettyref}{Reference format #1\space undefined}%
15\ref{#1:#2}%
16\else%
17\csname pr@#1\endcsname{#1:#2}%
18\fi%
19}
因此,\prettyref
内部使用两个:
-delimited 参数来分割表示格式的参数部分。LaTeX
会删除整个参数周围的花括号。
它也会删除带分隔符的参数。
因此,整个带分隔符的参数周围的花括号可用于隐藏出现在带分隔符的参数内的分隔符实例,这样 TeX 抓取带分隔符的参数的机制就不会应用于这些分隔符实例。
这意味着:您
可以\prettyref{Formatting:RemainderOfLabelName}
执行或或。
\prettyref{{Formatting}:RemainderOfLabelName}
\prettyref{Formatting:{RemainderOfLabelName}}
\prettyref{{Formatting}:{RemainderOfLabelName}}
因此,为了隐藏:
TeX 抓取:
-delimited 参数的机制/让事情顺利进行,只需将\prettyref
参数的整个部分包裹在表示格式的花括号中,即而不是
\prettyref{diag:seq:FirstExportedDiagram}
do
\prettyref{{diag:seq}:FirstExportedDiagram}
或
\prettyref{{diag:seq}:{FirstExportedDiagram}}
。
数学家协会
\documentclass[a4paper]{article}
\usepackage{graphicx}
\usepackage{prettyref}
\newrefformat{diag:cla}{Class Diagram \ref{#1}}
\newrefformat{diag:seq}{Sequence Diagram \ref{#1}}
\begin{document}
Behold: \prettyref{{diag:seq}:FirstExportedDiagram}.
\begin{figure}[h]
%\includegraphics[scale=0.5]{sequencediagram1.pdf}
\includegraphics[scale=0.5]{example-image.pdf}
\caption{The first sequence diagram.}
\label{diag:seq:FirstExportedDiagram}
\end{figure}
\end{document}
产量:
解释:
\prettyref{{diag:seq}:FirstExportedDiagram}
得到:
\@prettyref{diag:seq}:FirstExportedDiagram:
,进而得到:
\expandafter\ifx\csname pr@diag:seq\endcsname\relax
\PackageWarning{prettyref}{Reference format diag:seq\space undefined}%`
\ref{diag:seq:FirstExportedDiagram}%`
\else
\csname pr@diag:seq\endcsname{diag:seq:FirstExportedDiagram}%`
\fi
因此,您似乎实际上不需要重新定义任何东西。对于\prettyref
的参数,只需在此处和那里使用额外的花括号来隐藏:
TeX 抓取:
-delimited 参数的机制中的实例。
如果您不想手动在自动生成的代码中插入花括号,并且存在多个未嵌套在花括号中的冒号始终意味着只有/恰好前两个:
分隔的组件代表格式规范,那么您可以执行如下操作,它在未嵌套在花括号中的冒号处拆分,并且不会删除/剥离花括号:
\documentclass[a4paper]{article}
\usepackage{prettyref}
\usepackage{hyperref}
\makeatletter
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
\newcommand\UD@firstofone[1]{#1}%
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
\expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% Extract first inner undelimited argument:
%%
%% \UD@ExtractFirstArg{ABCDE} yields {A}
%%
%% \UD@ExtractFirstArg{{AB}CDE} yields {AB}
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps/after "hitting" \UD@ExtractFirstArg with \expandafter
%% twice.
%%
%% \UD@ExtractFirstArg's argument must not be blank.
%% This case can be cranked out via \UD@CheckWhetherBlank before calling
%% \UD@ExtractFirstArg.
%%
%% Use frozen-\relax as delimiter for speeding things up.
%% I chose frozen-\relax because David Carlisle pointed out in
%% <https://tex.stackexchange.com/a/578877>
%% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be
%% affected by \uppercase/\lowercase.
%%
%% \UD@ExtractFirstArg's argument may contain frozen-\relax:
%% The only effect is that internally more iterations are needed for
%% obtaining the result.
%%
%%.............................................................................
\@ifdefinable\UD@RemoveTillFrozenrelax{%
\expandafter\expandafter\expandafter\UD@Exchange
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}%
{\long\def\UD@RemoveTillFrozenrelax#1#2}{{#1}}%
}%
\expandafter\UD@PassFirstToSecond\expandafter{%
\romannumeral\expandafter
\UD@PassFirstToSecond\expandafter{\romannumeral
\expandafter\expandafter\expandafter\UD@Exchange
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}{\UD@stopromannumeral#1}%
}{%
\UD@stopromannumeral\romannumeral\UD@ExtractFirstArgLoop
}%
}{%
\newcommand\UD@ExtractFirstArg[1]%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
{\UD@stopromannumeral#1}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
\@ifdefinable\UD@GobbleToColon{\long\def\UD@GobbleToColon#1:{}}%
\@ifdefinable\UD@KeepToColon{\long\def\UD@KeepToColon#1:{{#1}}}%
\newcommand\UD@SplitColon[4]{%
% #1 Tokens to prepend to {<Already splitted stuff>{<stuff splitted in this iteration>}}{<New remainder to split>}
% if <Remainder to split> does contain colon.
% #2 Tokens to prepend to <Already splitted stuff>{<Remainder to split>}
% if <Remainder to split> does not contain colon.
% #3 Already splitted stuff.
% #4 Remainder to split.
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToColon#4:}%
{#2#3{#4}}{%
\expandafter\UD@PassFirstToSecond\expandafter{\UD@GobbleToColon#4}{%
\expandafter\UD@PassFirstToSecond\expandafter{%
\romannumeral
\expandafter\UD@Exchange\expandafter{%
\romannumeral
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\UD@stopromannumeral
\expandafter\UD@ExtractFirstArg\expandafter{\UD@KeepToColon#4}%
}{\UD@stopromannumeral#3}%
}{#1}%
}%
}%
}%
\renewcommand\prettyref[1]{%
\UD@SplitColon{%
\UD@SplitColon{% Here you could nest more \UD@SplitColon.
\expandafter\UD@prettyref@morethanonecolon\UD@firstofone
}{%
\UD@prettyref@onecolon
}%
}{%
\PackageWarning{prettyref}{No referencing format specified}\ref
}{}{#1}%
}%
\newcommand\UD@prettyref@onecolon[2]{%
\expandafter\ifx\csname pr@#1\endcsname\relax
\PackageWarning{prettyref}{Reference format #1\space undefined}%
\ref{#1:#2}%
\else
\csname pr@#1\endcsname{#1:#2}%
\fi
}%
\newcommand\UD@prettyref@morethanonecolon[3]{%
\expandafter\ifx\csname pr@#1:#2\endcsname\relax
\PackageWarning{prettyref}{Reference format #1:#2\space undefined}%
\ref{#1:#2:#3}%
\else
\csname pr@#1:#2\endcsname{#1:#2:#3}%
\fi
}%
\makeatother
% In order to create hyperlinks, you can use
%
% \hyperref[{<referencing label>}]{<textual phrase which shall be a hyperlink>}
%
% As components of <textual phrase which shall be a hyperlink> you can use starred
% referencing-commands \ref*/\pageref* which themselves don't produce hyperlinks.
% This avoids errors due to nesting hyperlinks within hyperlinks.
\newrefformat{diag}{\hyperref[{#1}]{Diagram \ref*{#1}}}
\newrefformat{diag:cla}{\hyperref[{#1}]{Class Diagram \ref*{#1}}}
\newrefformat{diag:seq}{\hyperref[{#1}]{Sequence Diagram \ref*{#1}}}
\newcounter{democounter}
\begin{document}
You should get: Sequence Diagram 1\par
You actually get: \prettyref{diag:seq:FirstExportedDiagram:x:Y}
\medskip
You should get: Sequence Diagram 2\par
You actually get: \prettyref{diag:seq:FirstExportedDiagram}
\medskip
You should get: Class Diagram 3\par
You actually get: \prettyref{diag:cla:FirstExportedDiagram}
\medskip
You should get: Diagram 4\par
You actually get: \prettyref{diag:FirstExportedDiagram}
\medskip
% You should get: 5 plus a warning "No referencing format specified" \par
% You actually get: \prettyref{FirstExportedDiagram}
% \medskip
You should get: 5\par
You actually get: \ref{FirstExportedDiagram}.
\medskip
Here the democounter is stepped. It has the value \refstepcounter{democounter}\thedemocounter.
\label{diag:seq:FirstExportedDiagram:x:Y}%
\bigskip
Here the democounter is stepped. It has the value \refstepcounter{democounter}\thedemocounter.
\label{diag:seq:FirstExportedDiagram}%
\bigskip
Here the democounter is stepped. It has the value \refstepcounter{democounter}\thedemocounter.
\label{diag:cla:FirstExportedDiagram}%
\bigskip
Here the democounter is stepped. It has the value \refstepcounter{democounter}\thedemocounter.
\label{diag:FirstExportedDiagram}%
\bigskip
Here the democounter is stepped. It has the value \refstepcounter{democounter}\thedemocounter.
\label{FirstExportedDiagram}%
\bigskip
\end{document}
答案2
不太清楚为什么 prettyref 要用冒号来界定结尾。这里的正常分隔符是\@nil
:
\documentclass[a4paper]{article}
\usepackage{graphicx}
\usepackage{prettyref}
\newrefformat{diag:cla}{Class Diagram \ref{#1}}
\newrefformat{diag:seq}{Sequence Diagram \ref{#1}}
\makeatletter
\def\prettyref#1{\@prettyref#1\@nil}
\def\@prettyref#1:#2\@nil{%
\expandafter\ifx\csname pr@#1\endcsname\relax%
\PackageWarning{prettyref}{Reference format #1\space undefined}%
\ref{#1:#2}%
\else%
\csname pr@#1\endcsname{#1:#2}%
\fi%
}
\makeatother
\begin{document}
Behold: \prettyref{diag:seq:FirstExportedDiagram}.
\begin{figure}[h]
\includegraphics[scale=0.5]{example-image.pdf}
\caption{The first sequence diagram.}
\label{diag:seq:FirstExportedDiagram}
\end{figure}
\end{document}