0

(This is a somewhat of a continuation of this question of mine, which @egreg provided an easy solution to.)

In the following (slight variation of egreg's) MWE, three commands are defined. \mylabel creates \label (to be used by \Cref in the next two commands) and a \RecordProperties that will be used to record other info. Then there are \mychapref and \mysecref that produce the "conditional"/"relative" references.

\documentclass{book}

\usepackage{hyperref} \usepackage{cleveref}

\NewProperty{chapter}{now}{\bfseries??}{\Roman{chapter}} \NewProperty{section}{now}{\bfseries??}{\arabic{section}}

\NewDocumentCommand{\mylabel}{m}{% \label{#1}% \RecordProperties{#1@recProp}{chapter,section,target}% }

\ExplSyntaxOn

\NewDocumentCommand{\myref}{m}{ % If \Cref{#1} begins with "Chapter", then execute \mychapref{#1}. % If \Cref{#1} begins with "Section", then execute \mysecref{#1}. }

\NewDocumentCommand{\mychapref}{m}{ \str_if_eq:eeTF { \RefProperty{#1@recProp}{chapter} } { \Roman{chapter} } { % we are in the same chap this~chapter } { % in a diff chap \Cref{#1} } }

\NewDocumentCommand{\mysecref}{m}{ \str_if_eq:eeTF { \RefProperty{#1@recProp}{chapter} } { \Roman{chapter} } { % we are in the same chap \str_if_eq:eeTF{ \RefProperty{#1@recProp}{section} } { \arabic{section}} { % in the same sec this~section } { %same chap diff sec \Cref{#1} } }

{
    % in a diff chap
    \Cref{#1},\nobreakspace Chapter\nobreakspace\RefProperty{#1@recProp}{chapter}
}

}

\ExplSyntaxOff

\begin{document} \chapter{First chapter}\mylabel{CHAP: I} \mychapref{CHAP: I}

\section{abc}\mylabel{SEC: I.1}

\mysecref{SEC: I.1}

\section{efg}

\mysecref{SEC: I.1}


\chapter{Second chapter}

\mychapref{CHAP: I}

\mysecref{SEC: I.1}

\end{document}

What is wanted: I want to "combine" \mychapref and \mysecref in a command \myref as described in the comment above. However, I came across the fact that \Cref* is not expandable and hence I can't assign it to string variables using \str_set:Ne, or try \exp_args:Ne, and then procees with the logic.

Is there a way to implement what is intended here?


Edit:

So, I tried to define \myref via \mycreftype that @gusbrs defines here, like so:

\NewDocumentCommand{\myref}{m}{
    \str_if_eq:eeTF { \mychapref{#1} } { chapter } { \mychapref{#1} } {}
    \str_if_eq:eeTF { \mycreftype{#1} } { section } { \mysecref{#1} } {}
}

However, running the MWE (with just the above and @gusbrs' definition of \mycreftype added to the preamble, along with replacing \mychapref{CHAP: I} with \myref{CHAP: I}), I get error messages, the first being

Argument of \@firstoftwo has an extra }. \myref{CHAP: I}

Any help?

Atom
  • 665
  • 2
    You already know \cref is not expandable, and the very link you provided, also shows that crossreftools has a simplified expandable one \crtcref, which you could use. But, in your case, you might prefer to get the type directly with https://tex.stackexchange.com/a/692754/105447. – gusbrs Jan 29 '24 at 18:36
  • 1
    Alternatively, you could also store the counter property in your \RecordProperties{#1@recProp} call, then use it to assume the type. – gusbrs Jan 29 '24 at 18:40
  • Brilliant options! The type best solves my case, for I plan to have theorem environments as well. Thanks tons! – Atom Jan 29 '24 at 19:08
  • I must say I do agree with @egreg in that this style of referencing is somewhat jarring... Anyway, and off-topic, you could get away from needing \mylabel by just setting your properties on the label hook (with \AddToHookWithArguments). – gusbrs Jan 29 '24 at 19:22
  • @gusbrs Ooh, thanks! I will update my code to incorporate this \AddToHookWithArguments. Btw, something is not working when I incorporated your \mycreftype in my MWE to define \myref. I have edited my question. Can you have a look? Many thanks! – Atom Jan 29 '24 at 19:42
  • 1
    It's really simple, \mycreftype itself is non expandable since it performs an assignment, but you can use the assignment it does to store the value of interest in a variable, and then compare that. I'll add an answer, it may be simpler. – gusbrs Jan 29 '24 at 20:06

1 Answers1

1

You can use the procedure at https://tex.stackexchange.com/a/692754/105447 to retrieve the reference type, and than compare that.

\documentclass{book}

\usepackage{hyperref} \usepackage{cleveref}

\NewProperty{chapter}{now}{\textbf{??}}{\Roman{chapter}} \NewProperty{section}{now}{\textbf{??}}{\arabic{section}}

\AddToHookWithArguments{label}{% \RecordProperties{#1@recProp}{chapter,section,target}% }

\ExplSyntaxOn \makeatletter \tl_new:N \l_mytempvar_tl \NewDocumentCommand{\myref}{m}{ \cref@gettype {#1} { \l_mytempvar_tl } \str_case:VnF \l_mytempvar_tl { % If type is "chapter", then execute \mychapref{#1}. { chapter } { \mychapref{#1} } % If type is "section", then execute \mysecref{#1}. { section } { \mysecref{#1} } } { % Anything else, just \Cref \Cref {#1} } } \makeatother

\NewDocumentCommand{\mychapref}{m}{ \str_if_eq:eeTF { \RefProperty { #1 @recProp } { chapter } } { \Roman{chapter} } { % we are in the same chap this~chapter } { % in a diff chap \Cref {#1} } }

\NewDocumentCommand{\mysecref}{m}{ \str_if_eq:eeTF { \RefProperty { #1@recProp } { chapter } } { \Roman{chapter} } { % we are in the same chap \str_if_eq:eeTF{ \RefProperty { #1 @recProp } { section } } { \arabic{section} } { % in the same sec this~section } { %same chap diff sec \Cref {#1} } } { % in a diff chap \Cref {#1},\nobreakspace Chapter\nobreakspace \RefProperty { #1 @recProp } { chapter } } }

\ExplSyntaxOff

\begin{document}

\chapter{First chapter} \label{CHAP:I}

\mychapref{CHAP:I}\par \myref{CHAP:I}

\section{abc} \label{SEC:I.1}

\mysecref{SEC:I.1}\par \myref{SEC:I.1}

\section{efg}

\mysecref{SEC:I.1}\par \myref{SEC:I.1}

\chapter{Second chapter}

\mychapref{CHAP:I}\par \myref{CHAP:I}\par \mysecref{SEC:I.1}\par \myref{SEC:I.1}

\end{document}

gusbrs
  • 13,740
  • I went through the documentation for adding hooks. The impression that I got is to use cmd/label/after rather than simply label in \AddToHookWithArguments. However, trying to do so raises errors. Can you clarify? (I really appreciate your patience with me!) – Atom Jan 29 '24 at 21:15
  • What I understood was that generic hooks for commands (Sec 3.1.2 here) are of the form cmd/<name>/before or cmd/<name>/after. – Atom Jan 29 '24 at 21:20
  • 1
    @Atom Well, the answer tells you how to do it. It works. And then you ask me why when you do it differently you get an error? That's unfair. ;-) Anyway, the answer is simple, the label is the the argument to \label, how do you expect to use that value in \AddToHook{cmd/label/after} if it does not pass the argument around? Check texdoc ltnews37 for more info on the label hook. – gusbrs Jan 29 '24 at 21:21
  • Okay, I won't take further of your time. But I really wish I had a TeXnician like you with whom I could talk and clarify my things. Nevertheless, many thanks for such great help! Oh, you mentioned about the label hook documentation! Just looked and my questions are dissolved. – Atom Jan 29 '24 at 21:26