2

In the source below I have a namedtheorem environment which, when used, displays, instead of the usual "Theorem", the value of the key name in its optional argument.

That name has initial letters capitalized (except conjunctions and prepositions), as in any title.

However, when referring to the theorem in text, I want to lowercase all those initial letters — except proper nouns such as "Euler" that should of course remain uppercase.

How can this be done?

\documentclass{article}
\usepackage[left=0.75in,right=0.75in]{geometry}

\usepackage{textcase}

\usepackage{amsthm}
\usepackage{thmtools}
\swapnumbers

\makeatletter
\declaretheoremstyle[
  headfont= \bfseries,
  headpunct={\bfseries.},
  postheadspace=0.5em,
  notefont=\bfseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\itshape,
  spaceabove=12pt,spacebelow=12pt,
]{thmstyle}    
\declaretheoremstyle[
  headfont=\bfseries,
  notefont=\bfseries, notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\itshape,
  spaceabove=12pt,spacebelow=12pt,
]{namedthmstyle}
\makeatother

\theoremstyle{thmstyle}
\declaretheorem[name=Theorem,numberwithin=section]{theorem}
\declaretheorem[
  style=namedthmstyle,name=Theorem,title = {},numberlike=theorem
]{namedtheorem}

\usepackage[pdftex]{hyperref}
\hypersetup{colorlinks,linkcolor=red}
\usepackage[nameinlink,noabbrev,capitalize]{cleveref}

\usepackage{crossreftools}

\begin{document}

\section{The theorems}

\begin{theorem}[equalities of \MakeUppercase{E}uclid]
  \label{thm:prelim}
  $a = b$ and $b = c$

\end{theorem}

\begin{namedtheorem}[name=Fundamental Theorem of \NoCaseChange{Euler}]
  \label{thm:euler}
  $a = c$.
\end{namedtheorem}

\bigskip   
\emph{Original text of name:} Fundamental Theorem of Euler

\bigskip    
\emph{Desired modification:} fundamental theorem of Euler

\bigskip    
\emph{Attempts:}

\begin{itemize}

\item

\MakeTextLowercase{Fundamental Theorem of \NoCaseChange{Euler}} ---\verb!\MakeTextLowercase{Fundamental Theorem of \NoCaseChange{Euler}}!\\
works OK directly.

\item

\MakeTextLowercase{\nameref*{thm:euler}} --- \verb!\MakeTextLowercase{\nameref*{thm:euler}}! \\
of no use.

\item

\crtnameref*{thm:euler} --- \verb!\crtnameref*{thm:euler}!\\
try starting here now.

\item

%\MakeTextLowercase{\crtnameref*{thm:euler}} ---
\verb!\MakeTextLowercase{\crtnameref*{thm:euler}}! causes error:

\begin{verbatim}
./try.tex:84: Missing \endcsname inserted.
<to be read again> 
                   \relax 
l.84 \MakeTextLowercase{\crtnameref*{thm:euler}}

? x
\end{verbatim}

\end{itemize}

\end{document}

In the source above, one line is commented out because it causes an error preventing output.

selective-lowercaseing-named-theorem-reference

Unsatisfactory method: add \crefformat labels

As shown in https://tex.stackexchange.com/a/401600/13492, including immediately after \label{thm:euler}

  \label[fte]{thm:euler}
  \crefformat{fte}{#2fundamental theorem of Euler#3}

and then using `\cref*{thm:euler} does give the desired "fundamental theorem of Euler".

However:

  • it fails if the \cref comes before the environment with the labels; and
  • when there are quite a number of such namedtheorem enviroments, it does require a lot of extra labeling.

A solution: use \MakeTextLowercase together with commands from crossreftools

This modifies the preamble code shown in https://tex.stackexchange.com/a/401438/13492, by:

  • adopting the comment there by @egreg to use \MakeTextLowercase instead of \MakeLowercase; and
  • omitting the phrase \hyperlink{\crtrefanchor{#1}} from the definition of \lowernameref there.

Namely:

\makeatletter
\newcommand{\lowernameref}[1]{{\MakeTextLowercase{\crtrefname{#1}}}}

\def\mynameref#1#2{%
    \begingroup
    \edef\@mytxt{#2}%
    \edef\@mytst{\expandafter\@thirdoffive\@mytxt}%
    \ifx\@mytst\empty\else
    \space(\nameref{#1})\fi
    \endgroup
}
\makeatother

Then in the body of the document,

\lowernameref{thm:euler}

produces the desired output:

fundamental theorem of Euler
murray
  • 7,944

1 Answers1

1

If you make sure that \NoCaseChange is protected you can use the macros from Heiko Oberdiek's refcount package for defining your own nice macro where it is ensured that the phrase forming the desired name is extracted by means of expansion before being passed to \MakeTextLowercase:

\documentclass{article}
\usepackage[left=0.75in,right=0.75in]{geometry}

\usepackage{textcase}

\usepackage{amsthm}
\usepackage{thmtools}
\swapnumbers

\makeatletter
\declaretheoremstyle[
  headfont= \bfseries,
  headpunct={\bfseries.},
  postheadspace=0.5em,
  notefont=\bfseries,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\itshape,
  spaceabove=12pt,spacebelow=12pt,
]{thmstyle}    
\declaretheoremstyle[
  headfont=\bfseries,
  notefont=\bfseries, notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries\itshape,
  spaceabove=12pt,spacebelow=12pt,
]{namedthmstyle}
\makeatother

\theoremstyle{thmstyle}
\declaretheorem[name=Theorem,numberwithin=section]{theorem}
\declaretheorem[
  style=namedthmstyle,name=Theorem,title = {},numberlike=theorem
]{namedtheorem}

\usepackage{refcount}[2010/12/01 v3.2] %!!!!!
\usepackage[pdftex]{hyperref}
\hypersetup{colorlinks,linkcolor=red}
\usepackage[nameinlink,noabbrev,capitalize]{cleveref}

\usepackage{crossreftools}

\makeatletter
\@ifdefinable\MyNiceLowercaseNameref{%
  \DeclareRobustCommand\MyNiceLowercaseNameref{%
    \@ifstar{\MyNiceLowercaseNamerefAtStar}{\MyNiceLowercaseNamerefAtNoStar}%
  }%
}%
\newcommand\MyNiceLowercaseNamerefAtStar[1]{%
  \MyNiceGenericLowercaseNameref{\@firstofone}{#1}%
}%
\newcommand\MyNiceLowercaseNamerefAtNoStar[1]{%
  \MyNiceGenericLowercaseNameref{\hyperref[{#1}]}{#1}%
}%
\newcommand\MyNiceGenericLowercaseNameref[2]{%
  \refused{#2}%
  #1%
  {%
    \expandafter\expandafter\expandafter\MakeTextLowercase
    \expandafter\expandafter\expandafter{%
      \getrefbykeydefault{#2}{name}{%
        \nfss@text{\reset@font\bfseries ??}%
      }%
    }%
  }%
}%
\makeatother

\begin{document}

\section{The theorems}

\begin{theorem}[equalities of \MakeUppercase{E}uclid]
  \label{thm:prelim}
  $a = b$ and $b = c$

\end{theorem}

%!!!!!!!!!!!!!!!!!! \protect\NoCaseChange
\begin{namedtheorem}[name=Fundamental Theorem of \protect\NoCaseChange{Euler}]
  \label{thm:euler}
  $a = c$.
\end{namedtheorem}

\bigskip   
\emph{Original text of name:} Fundamental Theorem of Euler

\bigskip    
\emph{Desired modification:} fundamental theorem of Euler

\bigskip    
\emph{Attempts:}

\begin{itemize}

\item

\MakeTextLowercase{Fundamental Theorem of \NoCaseChange{Euler}} ---\verb!\MakeTextLowercase{Fundamental Theorem of \NoCaseChange{Euler}}!\\
works OK directly.

\item

\MakeTextLowercase{\nameref*{thm:euler}} --- \verb!\MakeTextLowercase{\nameref*{thm:euler}}! \\
of no use.

\item

\crtnameref*{thm:euler} --- \verb!\crtnameref*{thm:euler}!\\
try starting here now.

\item

%\MakeTextLowercase{\crtnameref*{thm:euler}} ---
\verb!\MakeTextLowercase{\crtnameref*{thm:euler}}! causes error:

\begin{verbatim}
./try.tex:84: Missing \endcsname inserted.
<to be read again> 
                   \relax 
l.84 \MakeTextLowercase{\crtnameref*{thm:euler}}

? x
\end{verbatim}


\item

\MyNiceLowercaseNameref{thm:euler} --- \verb!\MyNiceLowercaseNameref{thm:euler}!\\
seems to work out

\item

\MyNiceLowercaseNameref*{thm:euler} --- \verb!\MyNiceLowercaseNameref*{thm:euler}! \\
seems to work out

\end{itemize}

\end{document}

enter image description here


By the way:

The commands \label, \ref and \pageref (and a few more) already get special treatment by the textcase package in the sense that these commands trigger applying \NoCaseChange to themselves and to their arguments inside \MakeTextLowercase/MakeTextUppercase.
But, e.g., the command \nameref (and many others which don't occur in the LaTeX 2ε-kernel but are defined in some package) does not get this special treatment.

Therefore I strongly recommend to wrap into \NoCaseChange any referencing-command that shall go into the argument of \MakeTextLowercase :

If you don't, with non-kernel-referencing-commands the names of the referencing-labels will be lowercased also.

Assume you have referencing-labels foo and FOO:

  • \MakeTextLowercase{\nameref{FOO}} will create a reference to foo, not to FOO.
  • \MakeTextLowercase{\NoCaseChange{\nameref{FOO}}} will create a reference to FOO.

Or, looking at your own example:

\MakeTextLowercase{\nameref*{thm:euler}} is nice and does not trigger warnings about undefined references. (Unfortunately it does not deliver the desired phrase lowercased.)

But what about:

\MakeTextLowercase{\nameref*{THM:EULER}}? Shouldn't this trigger a warning about undefined references? It doesn't. Because THM:EULER gets lowercased to thm:euler and that label is defined.

Ulrich Diez
  • 28,770