如何使 \crefrangelabelformat 适应子示例格式?

如何使 \crefrangelabelformat 适应子示例格式?

我希望能够重新定义一些应该在序言中定义的东西。

在这个例子中,关于这个问题: 交叉引用:更多子级别和预设,我想重新定义cleveref包的 \crefrangelabelformat,但是不起作用,请参阅 MWE 及其输出。

\documentclass{article}

\usepackage{indentfirst}
\usepackage[hidelinks]{hyperref}
\usepackage{cleveref}
\usepackage{xstring}
\usepackage{philex}


%MyStripToColon (requires xstring)
\newcommand{\mystriptocolon}[2]{\StrCut{#1}{.}{\myonea}{\myoneb}%
    \StrCut{#2}{.}{\mytwoa}{\mytwob}%
    \IfStrEq{\myonea}{\mytwoa}{\mytwob}{#2}}



    % Cleveref Label Formatting

            \crefname{ExNo}{}{}
            \crefname{SubExNo}{}{}
            \crefname{SubSubExNo}{}{}
        
            \creflabelformat{ExNo}{#2#1#3}          % The output of the \cref command doesn't include parentheses.
            \creflabelformat{SubExNo}{#2#1#3}
            \creflabelformat{SubSubExNo}{#2#1#3}        
            
            \crefrangelabelformat{ExNo}{#3#1#4--#5#2#6}                 
            \crefrangelabelformat{SubExNo}{#3#1#4--#5\crefstripprefix{#1}{#2}#6}        
            \crefrangelabelformat{SubSubExNo}{#3#1#4--#5\mystriptocolon{#1}{#2}#6}
            
            \newcommand{\crefrangeconjunction}{–} 

\begin{document}


    % Philex Label Formatting
    
            \phildashes{}{.}        
            \subformat{a}{}{.}
            \subsubformat{i}{(}{)}

        \lb{main1}{This is main1.
            \lba{sub1}{This is sub1.
                \lba{subsub11}{This is subsub11.}
                \lbz{subsub12}{This is subsub12.}}
            \lbz{sub2}{This is sub2.
                \lba{subsub21}{This is subsub21.}
                \lbz{subsub22}{This is subsub22.}}}
                
        \lb{main2}{This is main2.}
                


\textbackslash mystriptocolon works like a charm:

\vspace{6pt}

\textbackslash crefrange\{sub1\}\{sub2\} \textrightarrow{} \crefrange{sub1}{sub2}

\vspace{6pt}

\textbackslash crefrange\{subsub11\}\{subsub12\} \textrightarrow{} \crefrange{subsub11}{subsub12}

\vspace{6pt}


\textbf{Now I change label formatting.}
    
            \phildashes{.}{}    
            \subformat{1}{}{.}  
            \subsubformat{a}{}{.}   
    
\lb{main3}{This is main3.
    \lba{sub31}{This is sub31.
        \lba{subsub311}{This is subsub311.}
        \lbz{subsub312}{This is subsub312.}}
    \lbz{sub32}{This is sub32.}}
    
\vspace{6pt}
            
\textbf{Trying to redefine \textbackslash crefrangelabelformat in order for the new subsublevel format to be supported, now that there is no separator:}

\vspace{6pt}
        
\textbackslash crefrangelabelformat\{SubSubExNo\}\{\#3\#1\#4--\#5\textbackslash crefstripprefix\{\#1\}\{\#2\}\#6\}

\crefrangelabelformat{SubSubExNo}{#3#1#4--#5\crefstripprefix{#1}{#2}#6}

\textbackslash crefrange\{subsub311\}\{subsub312\} \textrightarrow{} \crefrange{subsub311}{subsub312}

\vspace{6pt}

As you can see, the new \textbackslash crefrangelabelformat has not been taken into account and I cannot use \textbackslash crefstripprefix, I would like to obtain 3.1a--b but the 1 is repeated.

\end{document}

在此处输入图片描述

答案1

评论:

  1. philex 包的 hyperref 支持非常混乱:

    • 根本无法确保每个命名的超链接目的地/目标/锚点都有唯一的名称。
      因此,您会收到很多警告,就像pdfTeX warning (ext4): destination with the same identifier (name{altsub.2}) has been already used, duplicate ignored使用基于 pdfTeX 的 TeX 引擎时一样。所有 TeX 引擎的另一个后果是根本无法确保超链接指向 pdf 文档中的正确位置。原因之一是:可能会发生多次计数器重置。使用 hyperref 时,许多目的地/目标/锚点的名称都会在\refstepcounter执行时自动创建。这些目的地名称来自计数器的名称和递增的值。因此,如果计数器的值被重置,则不再能确保目的地/目标/锚点名称的唯一性。这个问题可能可以修复:加载 hyperref 时,每个计数器除了众所周知的-macro 之外,还有一个关联的-macro,表示当相关计数器递增时应如何创建目的地/目标/锚点的名称。似乎 philex 的软件包维护者没有考虑到 -macros的维护。\the⟨counter⟩\theH⟨counter⟩\refstepcounter\theH⟨counter⟩
    • 在 CTAN 上,你会得到一个 .sty 文件,其中的换行看起来很奇怪,在某些地方你会发现很多不必要的东西%,而其他地方%似乎缺失了一些东西。我不会深入研究该包的代码。但我建议在修复之前不要使用它。
  2. 你说:

    “我希望能够重新定义一些本应在序言中定义的东西。”

    为什么不重新定义,而是在序言中定义事物,使其行为取决于例如反标志的值?
    如果这样做,您可以通过将表示反标志的宏重新定义为另一个值来选择行为。

    下面的示例提供了一个用于选择几个括号嵌套的宏参数之一的宏:

    \ExtractKthArg{⟨TeX-⟨number⟩-quantity of value K⟩}%
                  {⟨tokens in case list of undelimited arguments doesn't have a K-th argument⟩}%
                  {⟨list of undelimited arguments⟩}

    如果⟨无界参数列表⟩:
          是否提供⟨如果未限定参数列表没有第 K 个参数,则使用 tokens⟩.
    假设有第 K 个参数⟨无界参数列表⟩
          传递第 K 个参数,并删除一层括号。

    以下示例\StyleFlag定义了一个宏。扩展\StyleFlag应始终产生有效的 TeX-⟨number⟩-quantity。

    通过下面的示例,定义了一个宏,以便您可以轻松地为分配另一个值。\SetStyleFlag{⟨TeX-⟨number⟩-quantity⟩}\StyleFlag

    下面的示例\SelectAccordingToStyleFlag提供了一个宏。它在内部使用\ExtractKthArgwith\StyleFlag作为其⟨TeX-⟨number⟩-K 值的数量⟩-argument。语法为\SelectAccordingToStyleFlag

    \SelectAccordingToStyleFlag{⟨Default-Tokens⟩}{%
       {⟨Tokens if value of \StyleFlag is 1⟩}%
       {⟨Tokens if value of \StyleFlag is 2⟩}%
       {⟨Tokens if value of \StyleFlag is 3⟩}%
       ...%
    }%

    ⟨默认代币⟩如果表示值 K,则使用\StyleFlag,以便以下列表没有第 K 个参数。

    例如,您可以在序言中\SelectAccordingToStyleFlag设置一些内容时使用。\crefrangelabelformat

    在文档环境中,您可以\crefrange通过将 style-flag 设置为另一个值来更改相应 的行为\SetStyleFlag

下面的例子仅仅展示了解决 cleveref和macros 不能在文档环境中重新定义这个问题的一种方法。\cref...name\cref...format

下面的例子没有解决 philex 包在正确的超链接支持方面的缺陷。

\makeatletter
%% Code for \ExtractKthArg
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%%    \UD@stopromannumeral, \UD@CheckWhetherNull
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% 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 K-th inner undelimited argument:
%%
%% \ExtractKthArg{<TeX-<number>-quantity of value K>}%
%%               {<tokens in case list of undelimited args doesn't have a k-th argumnent>}%
%%               {<list of undelimited args>} %
%% 
%% In case there is no K-th argument in <list of indelimited args> : 
%%   Does deliver <tokens in case list of undelimited args doesn't have a k-th argumnent.
%% In case there is a K-th argument in <list of indelimited args> : 
%%   Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%%   \ExtractKthArg{0}{not available}{ABCDE} yields: not available
%%
%%   \ExtractKthArg{3}{not available}{ABCDE} yields:  C
%%
%%   \ExtractKthArg{3}{not available}{AB{CD}E} yields:  CD
%%
%%   \ExtractKthArg{4}{not available}{{001}{002}{003}{004}{005}} yields: 004
%%
%%   \ExtractKthArg{6}{not available}{{001}{002}{003}} yields: not available 
%% 
%%=============================================================================
\newcommand\ExtractKthArg[2]{%
  \romannumeral%
  % #1: <integer number K>
  % #2: <action if there is no K-th argument>
  \expandafter\UD@ExtractKthArgCheck
  \expandafter{\romannumeral\number\number#1 000}{#2}%
}%
\newcommand\UD@ExtractKthArgCheck[3]{%
  \UD@CheckWhetherNull{#1}{\UD@stopromannumeral#2}{% empty
    \expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
  }%
}%
\begingroup
\def\UD@ExtractFirstArgLoop#1{%
  \endgroup
  \@ifdefinable\UD@RemoveTillFrozenrelax{%
    \long\def\UD@RemoveTillFrozenrelax##1##2#1{{##1}}%
  }%
  \newcommand\UD@ExtractKthArgLoop[3]{%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo##3{}.}{\UD@stopromannumeral##2}{%
      \UD@CheckWhetherNull{##1}{%
        \UD@ExtractFirstArgLoop{##3#1}%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}##3}%
        {\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}##1}{##2}}%
      }%
    }%
  }%
}%
\expandafter\expandafter\expandafter\UD@ExtractFirstArgLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}%
%% Usage of frozen-\relax as delimiter is for speeding things up by reducing the
%% amount of iterations needed. 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.
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\expandafter\UD@stopromannumeral\UD@firstoftwo#1{}}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
%% End of code for \ExtractKthArg.
\makeatother


%==============================================================================
% \SelectAccordingToStyleFlag
%==============================================================================
%
% Syntax:
%
% \SetStyleFlag{1} or \SetStyleFlag{2} or \SetStyleFlag{3} or ....
%
% \SelectAccordingToStyleFlag{<Default-Tokens>}{%
%   {<Tokens if value of \StyleFlag is 1>}%
%   {<Tokens if value of \StyleFlag is 2>}%
%   {<Tokens if value of \StyleFlag is 3>}%
%   ...%
% }%
%
\makeatletter
\newcommand\StyleFlag{1}%
\newcommand\SetStyleFlag[1]{\@bsphack\def\StyleFlag{#1}\@esphack}%
\newcommand\SelectAccordingToStyleFlag{%
  \ExtractKthArg{\StyleFlag}%
}%
\makeatother
%==============================================================================


\documentclass{article}

\usepackage{indentfirst}
\usepackage[hyper]{philex}
\usepackage[hidelinks]{hyperref}
\usepackage{cleveref}
\usepackage{xstring}

%% Enable the following lines to see the coming into being of duplicate
%% destination/target/anchor-names more explicitly in the console-output - the
%% problem about warnings of pattern
%%    pdfTeX warning (ext4): destination with the same identifier (name{altsubsub.1}) 
%%    has been already used, duplicate ignored
%% still needs to be fixed by fixing what the macros coming from the philex-package
%% do. Probably by taking \theH<counter>-macros associated to philex's counters
%% into account:
%\makeatletter
%\AtBeginDocument{%
%  \let\oldhypertarget\hypertarget
%  \def\hypertarget#1{\message{^^J!!!Target-Name: #1^^J}\oldhypertarget{#1}}%
%  \let\oldrefstepcounter\refstepcounter
%  \def\refstepcounter{\message{^^J!!!Href: \detokenize\expandafter{\@currentHref}^^J}\oldrefstepcounter}%
%}%
%\makeatother

%MyStripToColon (requires xstring)
\newcommand{\mystriptocolon}[2]{\StrCut{#1}{.}{\myonea}{\myoneb}%
  \StrCut{#2}{.}{\mytwoa}{\mytwob}%
  \IfStrEq{\myonea}{\mytwoa}{\mytwob}{#2}%
}

% Cleveref Label Formatting

\crefname{ExNo}{}{}
\crefname{SubExNo}{}{}
\crefname{SubSubExNo}{}{}

\creflabelformat{ExNo}{#2#1#3}          % The output of the \cref command doesn't include parentheses.
\creflabelformat{SubExNo}{#2#1#3}
\creflabelformat{SubSubExNo}{#2#1#3}        

\crefrangelabelformat{ExNo}{#3#1#4--#5#2#6}                 
\crefrangelabelformat{SubExNo}{#3#1#4--#5\crefstripprefix{#1}{#2}#6}        
\crefrangelabelformat{SubSubExNo}{%
  \SelectAccordingToStyleFlag{#3#1#4--#5\mystriptocolon{#1}{#2}#6}{% <- default-format
    {#3#1#4--#5\mystriptocolon{#1}{#2}#6}% <- Format if value of \StyleFlag is 1
    {#3#1#4--#5\crefstripprefix{#1}{#2}#6}% <- Format if value of \StyleFlag is 2
    % Append more if \StyleFlag can also be 3 or 4 or etc
  }%
}%

\newcommand{\crefrangeconjunction}{–} 

\begin{document}

% Philex Label Formatting

\phildashes{}{.}        
\subformat{a}{}{.}
\subsubformat{i}{(}{)}

\lb{main1}{This is main1.
    \lba{sub1}{This is sub1.
        \lba{subsub11}{This is subsub11.}
        \lbz{subsub12}{This is subsub12.}}
    \lbz{sub2}{This is sub2.
        \lba{subsub21}{This is subsub21.}
        \lbz{subsub22}{This is subsub22.}}}
\lb{main2}{This is main2.}
                

\verb|\mystriptocolon| works like a charm:

\vspace{6pt}

\SetStyleFlag{1}%
\verb|\crefrange{sub1}{sub2}| \textrightarrow{} \crefrange{sub1}{sub2}

\vspace{6pt}

\verb|\crefrange{subsub11}{subsub12}| \textrightarrow{} \crefrange{subsub11}{subsub12}

\vspace{6pt}

\textbf{The philex-formatting is changed:}
    
\phildashes{.}{}    
\subformat{1}{}{.}  
\subsubformat{a}{}{.}   
    
\lb{main3}{This is main3.
    \lba{sub31}{This is sub31.
        \lba{subsub311}{This is subsub311.}
        \lbz{subsub312}{This is subsub312.}}
    \lbz{sub32}{This is sub32.}}
    
\vspace{6pt}
            
\textbf{The Style-flag is changed from 1 to 2 to have other branch of 
        \texttt{\string\crefrangelabelformat\string{SubSubExNo\string}} in effect:}

\vspace{6pt}
        
\verb|\SetStyleFlag{2}|\SetStyleFlag{2}%

\verb|\crefrange{subsub311}{subsub312}| \textrightarrow{} \crefrange{subsub311}{subsub312}

\vspace{6pt}

As you can see, you obtain 3.1a--b without the 1 being repeated.

\end{document}

在此处输入图片描述

答案2

我将反过来看待这个问题:

     \documentclass{article}
        
        \usepackage{indentfirst}
        \usepackage[hidelinks]{hyperref}
        \usepackage{cleveref}
        \usepackage{philex}
        
        \setlength{\parskip}{1ex}
       
        % Cleveref Label Formatting
        
                    \crefname{ExNo}{}{}
                    \crefname{SubExNo}{}{}
                    \crefname{SubSubExNo}{}{}
                
                    \creflabelformat{ExNo}{#2#1#3}      
                    \creflabelformat{SubExNo}{#2#1#3}
                    \creflabelformat{SubSubExNo}{#2#1#3}        
                    
                    \crefrangelabelformat{ExNo}{#3#1#4--#5#2#6}                 
                    \crefrangelabelformat{SubExNo}{#3#1#4--#5\crefstripprefix{#1}{#2}#6}        
                    \crefrangelabelformat{SubSubExNo}{#3#1#4--#5\crefstripprefix{#1}{#2}#6}
                    
                    \newcommand{\crefrangeconjunction}{–}
                    
                    
                    
       % Skips everything before the dot.
                        
                \makeatletter
            \@ifdefinable\gobbletodot{\long\def\gobbletodot#1.{}}% refcount package
            \newcommand\delbefdot[1]{%
                    \ifcat$\detokenize\expandafter{\gobbletodot#1.}$%
                    \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
                          {#1}{\expandafter\delbefdot\expandafter{\gobbletodot#1}}%
                        }%
            \@ifdefinable\rfxx{%
                    \DeclareRobustCommand\rfxx[1]{%
                      \IfRefUndefinedBabel{#1}{\refused{#1}\nfss@text{\reset@font\bfseries??}}%
                                                {%
                                                  \@ifundefined{hyperref}{\@firstofone}{\hyperref[{#1}]}%
                                                  {%
                                                    (\expandafter\expandafter\expandafter\delbefdot
                                                    \expandafter\expandafter\expandafter{\getrefbykeydefault{#1}{}{??}})%
                                                  }%
                                                }%
                          }%
                        }%
                        
            \@ifdefinable\rnxx{%
                    \DeclareRobustCommand\rnxx[1]{%
                      \IfRefUndefinedBabel{#1}{\refused{#1}\nfss@text{\reset@font\bfseries??}}%
                                                {%
    \@ifundefined{hyperref}{\@firstofone}{\hyperref[{#1}]}%
                                                  {%
    \expandafter\expandafter\expandafter\delbefdot
    \expandafter\expandafter\expandafter{\getrefbykeydefault{#1}{}{??}}%
                                                  }%
                                                }%
                          }%
                        }%
                \makeatother
                            
                            
                            
                            
       \newcommand{\rfstrip}[2]{(\rn{#1}--\rnx{#2})} % (3.1--2)
       \newcommand{\rnstrip}[2]{\rn{#1}--\rnx{#2}} % 3.1--2
       \newcommand{\rfdoublestrip}[2]{(\rn{#1}--\rnxx{#2})} %  (3.1a--b)
       \newcommand{\rndoublestrip}[2]{\rn{#1}--\rnxx{#2}} % 3.1a--b
    
\begin{document}
    
        % Philex Label Formatting
        
                \phildashes{}{.}        
                \subformat{a}{}{.}
                \subsubformat{i}{(}{)}
    
            \lb{main1}{This is main1.
                \lba{sub11}{This is sub11.
                    \lba{subsub111}{This is subsub111.}
                    \lbz{subsub112}{This is subsub112.}}
                \lbz{sub12}{This is sub12.
                    \lba{subsub121}{This is subsub121.}
                    \lbz{subsub122}{This is subsub122.}}}
                    
            \lb{main2}{This is main2.}
         
\textbackslash crefrange\{sub11\}\{sub12\} \textrightarrow{} \crefrange{sub11}{sub12}  This works (no roman numbering).

\textbackslash crefrange\{subsub111\}\{subsub112\} \textrightarrow{}  This will NOT compile fine (roman).
    
\textbackslash rnstrip\{sub11\}\{sub12\} \textrightarrow{} \rnstrip{sub11}{sub12} This works, because \textbackslash rnx doesn't work on the base of stripping to a delimiter.

\textbackslash rndoublestrip\{subsub111\}\{subsub112\} \textrightarrow{} \rndoublestrip{subsub111}{subsub112} Works, thanks to the dot.

    \vspace{3ex}
    \textbf{Now I change label formatting.}
        
                \phildashes{.}{}    
                \subformat{1}{}{.}  
                \subsubformat{a}{}{.}   
        
    \lb{main3}{This is main3.
        \lba{sub31}{This is sub31.
            \lba{subsub311}{This is subsub311.}
            \lbz{subsub312}{This is subsub312.}}
        \lbz{sub32}{This is sub32.}}

\textbackslash rnstrip\{sub31\}\{sub32\} \textrightarrow{} \rnstrip{sub31}{sub32} This works fine, thanks to the dot.

\textbackslash rndoublestrip\{subsub311\}\{subsub312\} \textrightarrow{} \rndoublestrip{subsub311}{subsub312} Cannot work (no delim.)

\textbackslash crefrange\{sub31\}\{sub32\} \textrightarrow{} \crefrange{sub31}{sub32} This works fine (no roman).

\textbackslash crefrange\{subsub311\}\{subsub312\} \textrightarrow{} \crefrange{subsub311}{subsub312} This works fine (no roman).


\end{document}

在此处输入图片描述

相关内容