This is another question about protection and expansion, that I still don't understand well… (and I guess this is my problem here). I read especially How do I "unprotect" an argument?, and many others.
I'm trying to create automatic and contextual labels for titles (See below for details if needed). If I write eg \myref{My_title_here}, the link to the label is eg “A.II.3.d My title here”, and points to the 4th subsection of the 3rd section of the 2nd chapter in the 1st part. A.II.3.d is the “title number”, and is the result of \getrefnumber {#1} (here #1 is My_title_here), and I want to get it in \templabel, but:
%\edef \templabel {\getrefnumber {#1}} doesn't work
What I want is to get the result (the expansion) of \getrefnumber {#1} (eg A.II.3.d) in \templabel. Again, the code is at the end if needed.
Workaround
\edef didn't work, so I finally tried \protected@edef (Are \protected\edef and \protected@edef the same?):
\protected@edef \templabel {\getrefnumber {#1}}
%\show \templabel->A.\protect \textlatin {I}.1.
I finally found this to remove \protect:
\expandafter \expandafter \expandafter \def \expandafter \expandafter \expandafter \templabel \expandafter \expandafter \expandafter {\getrefnumber {#1}}
%\show \templabel ->A.\textlatin {I}.1.
I looked at the definition of \textlatin and noticed that it really looks like \textbf. It's a formatting command. To remove the \textlatin command, I use the following:
\def \textlatin #1{#1}
Questions
Finally it works, but:
Can you explain briefly what's the problem here, with protection and expansion? Why can't I use
\getrefnumber {#1}directly?I would like to know is there is a better solution, or more general, or at least, if the solution covers all cases here: how to get directly
A.I.1instead ofA.\protect \textlatin {I}.1?Does this solution with
\expandafterworks in each case? Which commands may I encounter here, in\getrefnumber {#1}:\textlatin,\textgreek(because I use\greek?) and what else?The way I deal with the \textlatin command is it the better one? Are there any drawbacks with this solution? (I don't understand the definition of
\textlatin, which is like\textbf)And if I use
-instead of.(A-II-3-4)? Does the-will be considered as an arithmetic operation, eg during expansion?
Feel free give advice on code, I'm learning.
The context, just in case
I use the following numbering:
\def \thepart {\Alph {part}}
\def \thechapter {\Roman {chapter}}
\def \thesection {\arabic {section}}
\def \thesubsection {\alph {subsection}}
\def \thesubsubsection {\greek {\value{subsubsection}}}
\setcounter {secnumdepth} {3} % Paragraphs and subparagraphs unnumbered
I create “informative” numbering for the titles (Source: (Re)define \ref for chapter that includes the part number):
\def \p@chapter {\thepart.}
\def \p@section {\thepart.\thechapter.}
\def \p@subsection {\thepart.\thechapter.\thesection.}
\def \p@subsubsection {\thepart.\thechapter.\thesection.\thesubsection.}
Then I create my label command that I will patch to sectionning commands (Sources:
— Sectioning command that automatically creates label,
— Changing the output of \ref depending on the position of the corresponding \label,
— How to change the appearance of \ref depending on where it's called relative to the \label,
— Automatic creations of labels).
\newcommand {\myref }[1]{%
\@ifundefined {r@#1} {??} {\begingroup
%\edef \templabel {\getrefnumber {#1}} doesn't work
To get A.I.2.b in \templabel, this is the problem
Then I will split the string with xstrings:
\StrCut \templabel {.} \part@number \part@tail
\StrCut \part@tail {.} \chapter@number \chapter@tail
% …
\StrCut \paragraph@tail {.} \subparagraph@number \subparagraph@tail
and create the contextual link (the link, his number is eg “A-III-2-b The title here” but if the link is in A-III, it will be only “2-b The title here”; it's contextual):
\edef \templink {\getrefbykeydefault {#1} {anchor} {}}
\IfStrEq \thepart \part@number
{\IfStrEq \thechapter \chapter@number
%…
{\textcolor{red}{X} \hyperlink \templink \part@tail}}%
{\textcolor{red}{X} \hyperlink \templink \templabel}%
\endgroup}}
The MWE
\documentclass[greek]{book} % THE GREEK OPTION IS THE CAUSE
\usepackage {hyperref}
\usepackage {babel}
\makeatletter
\def \p@chapter {\thepart.}
\def \p@section {\thepart.\thechapter.}
\def \p@subsection {\thepart.\thechapter.\thesection.}
\def \p@subsubsection {\thepart.\thechapter.\thesection.\thesubsection.}
\newcommand {\myref}[1]{%
\@ifundefined {r@#1} {??} {\begingroup
\edef \temp {\getrefnumber {#1}}
% \show \temp->A.\textlatin {I}.1.
\endgroup }}
\makeatother
\begin{document}
\mainmatter
\part{Hi :\\introduction}\label{Hi}
\chapter{Chapter}\label{Chapter}
See \myref{Test} below.
\section{Test}\label{Test}
\enddocument
nameref,cleveref, .... – jon Nov 24 '16 at 05:30\documentclassand end with\end{document}. – Werner Nov 24 '16 at 05:39\getrefnumber {#1}is a command fromnameref, which I use. I read the documentation ofcleveref, quickly, and others too, but didn't find anything. I prefer not to use too many packages, but if there is one… I'm still interested in the answer here. – user73438 Nov 24 '16 at 05:40{\def …}) the command to do the same job as the protected command. And that's what I've done. There is no other way. Am I right? – user73438 Nov 24 '16 at 09:14\DeclareRobustCommand\foo{\def\zzz{aaa}[\zzz]}if you really just need[aaa]then you can define\def\foo{[aaa]}which is the equivalent of what you have done with textlatin, but if you actually need\zzzto be defined after the call to\foothen there is no way for it to work. Similarly your textlatin redefinition only works as you don't actually need to switch font encodings in this context. – David Carlisle Nov 24 '16 at 09:20\edef), and commands that rely on commands unexpandable by nature (assignments like\def, text typesetting like\textbfor\textlatin, …), so they will throw errors if expanded in expansion-only context, so they are protected. In some cases, eg if the text is not typeset and I want only access to the plain text itself, like in this question, I cannot remove the protection but I can simulate the behavior of the original command by redefining it locally in a suitable way. – user73438 Nov 24 '16 at 10:36\protected(\protected\edef,\protected\def…). The other one, based on LaTeX2e, uses\protect,DeclareRobustCommand,\protected@\edef… Are there other command names associated with these mechanisms? — I'm still not sure if one is (always) better than the other, or if there are use cases when I should use one or the other — As a guideline to code, it's better to write expandable commands (when it's possible), or to protect them (to prevent errors, but rewrite them when needed). – user73438 Nov 24 '16 at 10:57\newcommandalso defines\protect-ed commands if used with an optional argument as do several other latex constructs. (almost) all expl3/xparse declarations use the etex\protectedmechanism – David Carlisle Nov 24 '16 at 11:02