什么是一种强大的用户定义方法来定义在环境内外工作的交叉引用和附加值?

什么是一种强大的用户定义方法来定义在环境内外工作的交叉引用和附加值?

这个问题是对这两个问题的后续

我想要实现的目标:

  • 我想要一个环境,例如彩色盒子,其中我有
  • 一种定义某种标签的方法,\vref可以与交叉引用一起工作或类似的方法,即顺序一定不事情
  • 定义与标签相关的附加变量的方法,例如<label-name>@definition
  • 我需要能够检查某个标签变量是否可用
  • 该方法必须针对文本中的位置保持稳定,尤其是在环境内部或外部工作时

我目前学到的知识:

参考值

  • zref在环境之外也能很好地工作。您可以使用\zref@newprop\zref@setcurrent\zref@extractdefault\zref@labelbyprops实现惊人的效果。\zifrefundefined即使缺少某些内容,也有助于使您的编译顺利进行。
  • zref在环境中无法工作。我希望有类似zref但可以在环境中工作的东西。

电子工具箱

  • etoolbox(仅包含适合经验丰富的 [La]TeX 用户的文档)完全适应环境. 使用\csgdef\csuse将带你走得很远。
  • 我缺少的补充功能\zifrefundefined,但这可能是我不理解文档
  • etoolbox有一个警告:顺序很重要。事物必须在第一次使用之前定义。

概括

我需要结合环境的稳健性以及发生顺序的etoolbox稳健性。这是我的测试平台:zref

\documentclass[
  a4paper,
  11pt,
  parskip=half
]{scrbook}

\usepackage[nospace]{varioref}
\usepackage[pdfencoding=unicode, psdextra]{hyperref}
\usepackage{cleveref}
\usepackage[user]{zref}
\usepackage{tcolorbox}
\usepackage{etoolbox}

\tcbuselibrary{breakable}

\DeclareNewTOC[
  category=float,
  float,% declares floating environment eq
  floatpos=ht,
  nonfloat,% declares non-floating environment eq-
  listname={Some Items},
  name=TM,
  tocentrystyle=tocline,
  tocentrylevel:=table,
  tocentryindent:=table,
  tocentrynumwidth:=table,
  type=MySpecialEnvFloat,
]{ltm}

\newtcolorbox[
    auto counter,
    crefname={TM}{TMs}]{MyBox}[2][]{
    title={TM\,\thetcbcounter: #2},
    #1}
  
\newcounter{MySpecialEnvCounter}

    
\begin{document}

\makeatletter
\zref@newprop{Definition}{}

\newcommand{\MySpecialEnv}[4]{%
    \refstepcounter{MySpecialEnvCounter}%

    % etoolbox
    \csgdef{#1@Definition}{#2}

    % 
    \zlabel{#1}
    \zref@setcurrent{Definition}{#2}

    \begin{MyBox}[label={#1}]{#2}
        \addcontentsline{ltm}{section}{TM\,\theMySpecialEnvCounter: #2}

        Some text
        \tcblower
        #4
    \end{MyBox}
}%  
\makeatother

\listofMySpecialEnvFloats

\MySpecialEnv{test-id}{Something that looks like a summary}{-}{
    sdjoajhsja sijaoihs siahskah

    Nameuse: \@nameuse{test-id-2@Definition}

    Csname: \emph{\csname test-id-2@Definition\endcsname}

    % Order matters for etoolbox, so this one will fail
    Etoolbox: \csuse{test-id-2@Definition}
}

\MySpecialEnv{test-id-2}{Yet another summary}{-}{
    asjajsaj sakjskaj sjkajs
}

\subsection{varioref test}

\textbf{Varioref test}: Reference to \vref{test-id} and \vref{test-id-2},
\textbf{Pageref test}: \vpageref{test-id-2}

\subsection{Cref Test}

\cref{test-id}  \cpageref{test-id}

\subsection{etoolbox}

\makeatletter

A \csuse{test-id-2@Definition}

% How do I test for test-id-2 to bne defined?
B \ifdef{test-id-2}{\csuse{test-id-2@Definition}}{test-id-2 DOES NOT EXIST}

C \csuse{test-id-4@Definition}

D \ifdef{test-id-4}{\csuse{test-id-4@Definition}}{test-id-4 DOES NOT EXIST}

\makeatother

\subsection{zifrefundefined}

% Not robust against environments
\makeatletter
\zifrefundefined{test-id}{\nfss@text{\reset@font\bfseries??}}{
    \zref@extractdefault{#1}{Definition}{}
}
\makeatother

\end{document}

答案1

Markus,据我所知,您的 MWNE 中有两个错误:

  1. 您的拼写有误\zref@extractdefault{#1}{Definition}{}:我认为#1应该替换为test-id
  2. 可能是代码减少事故:你忘记使用 注册变量\zref@labelbyprops因此zref看起来好像它不适合环境,但它是。所以你的假设zref是错误的。

以下是 MWE:

\documentclass[
  a4paper,
  11pt,
  parskip=half
]{scrbook}

\usepackage[nospace]{varioref}
\usepackage[pdfencoding=unicode, psdextra]{hyperref}
\hypersetup{linkcolor=blue}
\usepackage{cleveref}
\usepackage[user]{zref}
\usepackage{tcolorbox}

\tcbuselibrary{breakable}

\DeclareNewTOC[
  category=float,
  float,% declares floating environment eq
  floatpos=ht,
  nonfloat,% declares non-floating environment eq-
  listname={Some Items},
  name=TM,
  tocentrystyle=tocline,
  tocentrylevel:=table,
  tocentryindent:=table,
  tocentrynumwidth:=table,
  type=MySpecialEnvFloat,
]{ltm}

\newtcolorbox[
    auto counter,
    crefname={TM}{TMs}]{MyBox}[2][]{
    title={TM\,\thetcbcounter: #2},
    #1}
  

\makeatletter
\newcommand{\referToMySpecialEnv}[1]{
    \zifrefundefined{#1}{\nfss@text{\reset@font\bfseries??}}{
        \hyperref[#1]{\zref@extractdefault{#1}{ID}{}: 
        \emph{\zref@extractdefault{#1}{Definition}{}}} \vpageref{#1}
    }
}    
\makeatother
    
    
\begin{document}

\makeatletter
\zref@newprop{Definition}{}
\zref@newprop{ID}{}

\newcommand{\MySpecialEnv}[4]{%

    \begin{MyBox}[label={#1}]{#2}
        \zref@setcurrent{Definition}{#2}%
        \zref@setcurrent{ID}{TM\,\thetcbcounter}
        \zref@labelbyprops{#1}{Definition, ID}
        \addcontentsline{ltm}{section}{TM\,\thetcbcounter: #2}
        Some text
        \tcblower
        #4
    \end{MyBox}
}%  
\makeatother

\listofMySpecialEnvFloats

\MySpecialEnv{test-id}{Something that looks like a summary}{-}{
    Here is a cross-reference to
    % Works like a charm within the box!
    \referToMySpecialEnv{test-id-2}
}

\MySpecialEnv{test-id-2}{Yet another summary}{-}{
    Here is a cross-reference to
    % Works like a charm within the box!
    \referToMySpecialEnv{test-id}
}

\subsection{varioref test}

\textbf{Varioref test}: Reference to \vref{test-id} and \vref{test-id-2},
\textbf{Pageref test}: \vpageref{test-id-2}

\subsection{Cref Test}

\cref{test-id}  \cpageref{test-id}

\subsection{zifrefundefined}

% Works outside in the wild
Let us check \referToMySpecialEnv{test-id} and \referToMySpecialEnv{test-id-2}

\end{document}

相关内容