0

I would like to be able to redefine something which is supposed to be defined in the preamble.

In this example and in relation to this question : Cross-referencing: more sublevels, and presets, I want to redefine \crefrangelabelformat of the cleveref package, but it doesn't work, see the MWE and its output.

\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}

enter image description here

  • 4
    well I have neither the time nor the will to wade into cleveref and this philex package, but generally: When I want to setup some sophisticated references I avoid cleveref and define the commands myself with zref. There you have more control over the data structure, see e.g. https://tex.stackexchange.com/a/325319/2388 – Ulrike Fischer Mar 28 '22 at 08:42
  • Now I do use zref. If anyone wants to quickly see how this jewel works: https://tex.stackexchange.com/a/644002/262813 – Vincent Krebs May 15 '22 at 21:34

2 Answers2

1

Remarks:

  1. The hyperref-support of the package philex is very messy:

    • It is not ensured at all that each named desination/target/anchor for hyperlinks has a unique name.
      As a consequence you get a lot of warnings like pdfTeX warning (ext4): destination with the same identifier (name{altsub.2}) has been already used, duplicate ignored when using TeX-engines based on pdfTeX. As another consequence with all TeX-engines it is not ensured at all that hyperlinks lead to correct places in the pdf-document. One reason for this is: There may take place a lot of resetting of counters. With hyperref names of many destinations/targets/anchors are created automatically when \refstepcounter is carried out. These destination-names are derived from the names and the values of the counters incremented. Thus if the value of a counter is reset, uniqueness of names of destinations/targets/anchors is not ensured any more. This could probably be fixed: When hyperref is loaded, then each counter, besides the well-known \the⟨counter⟩-macro, also has an associated \theH⟨counter⟩-macro denoting how \refstepcounter shall create names of destinations/targets/anchors when the counter in question is incremented. Seems the package maintainer of philex did not take maintenance of \theH⟨counter⟩-macros into account.
    • On CTAN you get a .sty-file where line-breaking looks weird and where in some places you find many unnecessary % and where in other places % seem to be missing. I won't delve into the code of that package. But I recommend not using it until it is fixed.
  2. You say:

    "I would like to be able to redefine something which is supposed to be defined in the preamble."

    How about not redefining but about already within the preamble defining things so that their behavior depends, e.g., on the value of a counter-flag?
    If you do this, you can select behavior by redefining to another value the macro that denotes the counter-flag.

    With the example below a macro for selecting one of several brace-nested macro-arguments is provided:

    \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⟩}

    In case there is no K-th argument in ⟨list of undelimited arguments⟩:
          Does deliver ⟨tokens in case list of undelimited arguments doesn't have a K-th argument⟩.
    In case there is a K-th argument in ⟨list of undelimited arguments⟩:
          Does deliver that K-th argument with one level of braces removed.

    With the example below a macro \StyleFlag is defined. Expanding \StyleFlag should always yield a valid TeX-⟨number⟩-quantity.

    With the example below a macro \SetStyleFlag{⟨TeX-⟨number⟩-quantity⟩} is defined so that you can easily assign another value to \StyleFlag.

    With the example below a macro \SelectAccordingToStyleFlag is provided. Internally it uses \ExtractKthArg with \StyleFlag as its ⟨TeX-⟨number⟩-quantity of value K⟩-argument. Syntax of \SelectAccordingToStyleFlag is:

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

    ⟨Default-Tokens⟩ is used if \StyleFlag denotes a value K so that the following list does not have a K-th argument.

    You can use \SelectAccordingToStyleFlag, e.g., when setting some \crefrangelabelformat within the preamble.

    Within the document-environment you can change the behavior of corresponding \crefranges by setting the style-flag to another value via \SetStyleFlag.

The example below just exhibits one way of coping with the problem that cleveref's \cref...name- and \cref...format-macros cannot be redefined within the document-environment.

The example below does not cope with the deficiencies of the philex package regarding proper hyperref-support.

\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}

enter image description here

Ulrich Diez
  • 28,770
0

I will take the problem the other way around:

     \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}

enter image description here