TeX - LaTeX Asked on April 10, 2021
Consider the following MWE
documentclass{article}
usepackage{amsthm}
usepackage{thmtools}
usepackage[nameinlink]{cleveref}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{ IfEmptyTF }{ m m m }
{
sbox0{#1}
ifdimwd0=0pt
#2
else
#3
fi
}
ExplSyntaxOff
makeatletter
declaretheoremstyle[
postheadspace=.5em,
headpunct={},
notebraces={}{},
notefont=bfseries,
headformat=IfEmptyTF{NOTE}{NAME~NUMBER}{letthmt@space@emptyNOTE}
]{theorem}
makeatother
declaretheorem[
style=theorem,
name=Theorem
]{theorem}
crefname{theorem}{Theorem}{Theorems}
begin{document}
begin{theorem}[label=thm:a]
A theorem.
end{theorem}
begin{theorem}[name=Important theorem, label=thm:b]
Another theorem.
end{theorem}
cref{thm:a} and cref{thm:b} % <-- should be 'Theorem 1 and Important theorem'
end{document}
which produces
I’d like to modify the content of crefname{theorem}{..}{..}
so that cref{..}
prints Theorem n
if the nth theorem doesn’t have a name, but if it does it just prints the name.
I know it can probably be done using nameref
or autoref
, but is a cref
only solution possible?
I'm not sure this is doable using the cleveref
machinery, because crefformat
doesn't seem to have access to the label. Moreover, cleveref
is designed to be able to combine several numbered items while not repeating the item type (e.g., “theorems 1, 3 and 10”), which doesn't fit very well with what you want to do (articles would need to be added...).
That being said, one can redefine cref
to:
detect if the argument consists of only one label;
if this is the case and if it has a name recorded by the nameref
package, retrieve this name and print it (I use the great refcount
package for this);
otherwise, let the normal cref
command handle the situation.
Unrelated: your dimension test in IfEmptyTF
is a bit weird. I reimplemented it in a better way,1 but it may be that you'd rather want to test whether the first-level expansion of the first argument of IfEmptyTF
is empty. It's easy to do, but I kept the principle of “boxing + dimension test” in case this matters for your real life documents.
documentclass{article}
usepackage{letltxmacro}
usepackage{nameref}
usepackage{refcount}
usepackage{amsthm}
usepackage{thmtools}
usepackage[nameinlink]{cleveref}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand { IfEmptyTF } { m }
{
hbox_set:Nw l_tmpa_box #1 hbox_set_end:
dim_compare:nNnTF { box_wd:N l_tmpa_box } = { c_zero_dim }
% The T and F clauses are taken from what follows in the input stream
}
% Save the original cref commmand
LetLtxMacro{__noibe_orig_cref:n}{cref}
tl_new:N l__noibe_theorem_name_tl
RenewDocumentCommand{ cref }{ m }
{
int_compare:nNnTF { clist_count:n {#1} } > { 1 }
{ __noibe_orig_cref:n {#1} }
{
exp_args:NNo tl_set:No l__noibe_theorem_name_tl
{ getrefbykeydefault {#1} { name } { } }
tl_if_empty:NTF l__noibe_theorem_name_tl
{ __noibe_orig_cref:n {#1} }
{ l__noibe_theorem_name_tl }
}
}
ExplSyntaxOff
makeatletter
declaretheoremstyle[
postheadspace=.5em,
headpunct={},
notebraces={}{},
notefont=bfseries,
headformat=IfEmptyTF{NOTE}{NAME~NUMBER}{letthmt@space@emptyNOTE}
]{theorem}
makeatother
declaretheorem[
style=theorem,
name=Theorem
]{theorem}
crefname{theorem}{Theorem}{Theorems}
begin{document}
begin{theorem}[label=thm:a]
A theorem.
end{theorem}
begin{theorem}[name=Important theorem, label=thm:b]
Another theorem.
end{theorem}
cref{thm:a} and cref{thm:b} % “Theorem 1 and Important theorem”
cref{thm:a,thm:b} % “Theorems 1 and 2”
end{document}
IfEmptyTF
Here is a simple example where my implementation of IfEmptyTF
works fine whereas yours produces an error:
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{ YourIfEmptyTF }{ m m m }
{
sbox0{#1}
ifdimwd0=0pt
#2
else
#3
fi
}
NewDocumentCommand { MyIfEmptyTF } { m }
{
hbox_set:Nw l_tmpa_box #1 hbox_set_end:
dim_compare:nNnTF { box_wd:N l_tmpa_box } = { c_zero_dim }
}
ExplSyntaxOff
begin{document}
%YourIfEmptyTF{}{textbf}{textit}{foo bar} % Error: Too many }'s.
MyIfEmptyTF{}{textbf}{textit}{foo bar} % 'foo bar' is typeset in bold
MyIfEmptyTF{non-empty}{textbf}{textit}{foo bar} % 'foo bar' is typeset in italics
end{document}
Footnote
#2
when reading the second ⟨dimen⟩ and, more importantly, allow each of the T and F clauses to act on tokens that follow the IfEmptyTF{...}{T}{F}
in the input stream (with your code, #2
is followed by else
in the input stream, and #3
is followed by fi
, which can be a showstopper when you want to implement certain things—this is demonstrated under Problematic example for your IfEmptyTF
in this answer).Correct answer by frougon on April 10, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP