# Uppercase until end of group

In LaTeX, all font commands have two versions, one requires an argument (\textbf, \textit, \textsc etc), other changes the font until the end of group (\bfseries, \itshape, \scshape etc). The latter is especially useful when defining fonts for some auto-generated text in some package or class file. For example, with the memoir class:

\captionnamefont{\small\scshape}


or

\renewcommand*{\chapnamefont}{\Large\sffamily\bfseries}


However, now I need a similar command for making text uppercase. \MakeUppercase requires an argument, but I don't know if there is a solution to make all text uppercase until end of a group, so that I could do something like:

\captionnamefont{\small\bfseries\lsstyle\MakeUppercaseUntilEndOfGroup}


In the event of no such command exists, to make this specific case work, I think I need to patch some internal memoir commands, something like this:

\makeatletter
\makeatother


However this is rather inelegant and limited; besides the fact that for other commands such as \setsecheadstyle this would have to be duplicated, even for floats, only captions for figures are changed. I also have tables and other custom float types defined by the \newfloat command. Then is it possible to simply define this new style for every kind of floats in my document? I suppose there is some code that creates new float types and maybe that should be patched...

-

If I understood you right you want to be able to use \captionnamefont{\small\bfseries\lsstyle\MakeUppercase} in order to change the appearance of all of memoir's captions. One possibility of achieving this is to patch \@makecaption where the commands set with \captionnamefont are used.

\captionnamefont simply redefines \@contnfont. This command is now used in \@makecaption in five different places (due to some conditionals) in the following way: \@contnfont #1\@contdelim.

The example below changes all these appearances into \@contnfont{#1\@contdelim} so that the last command in \captionnamefont may have an argument:

\documentclass{memoir}
\usepackage{microtype}
\usepackage{etoolbox}
\makeatletter
\patchcmd[\long]{\@makecaption}
{\@contnfont #1\@contdelim}
{\@contnfont{#1\@contdelim}}
{}{}
\patchcmd[\long]{\@makecaption}
{\@contnfont #1\@contdelim}
{\@contnfont{#1\@contdelim}}
{}{}
\patchcmd[\long]{\@makecaption}
{\@contnfont #1\@contdelim}
{\@contnfont{#1\@contdelim}}
{}{}
\patchcmd[\long]{\@makecaption}
{\@contnfont #1\@contdelim}
{\@contnfont{#1\@contdelim}}
{}{}
\patchcmd[\long]{\@makecaption}
{\@contnfont #1\@contdelim}
{\@contnfont{#1\@contdelim}}
{}{}
\makeatother
\captionnamefont{\small\bfseries\lsstyle\MakeUppercase}

\begin{document}

\begin{table}[ht]
\caption{test caption}
\end{table}

\end{document}


-

I have come up with a semi-elegant answer for my own problem, but I'm still waiting for better answers.

Instead of the suggested way to patch the memoir code that creates new float types, I have come up with a macro that patches each float type individually. But at least there is a central way to specify the style of all float captions:

\makeatletter
\def\redeffloatcapstyle#1{%
\expandafter\renewcommand\expandafter{\csname fnum@#1\endcsname}[1]{%
\small\bfseries\lsstyle\MakeUppercase{%
}
}
}
\makeatother
\redeffloatcapstyle{figure}
\redeffloatcapstyle{table}
% add your own new float types here; you might have to first define \newfloattypename, like this:
\def\codelistingname{Code Listing}
\newfloat{codelisting}{lcd}{\codelistingname}
\newcommand{\cdref}[1]{\codelistingname~\ref{#1}}
\redeffloatcapstyle{codelisting}


With this macro, saying \redeffloatcapstyle{whatever} is equivalent to saying:

\renewcommand{\fnum@whatever}[1]{\small\bfseries\lsstyle\MakeUppercase{\whatevername~\thewhatever}\quad}


This is kinda helpful, but still not as elegant if we could just patch the memoir code that defines new float types. So, still waiting for an answer...

-
I think it's a good way to patch the command. –  egreg Oct 7 '12 at 13:59

Non-LaTeX-y, and perhaps a bit roundabout way for use with XeTeX would be to make a mapping file along the lines of:

; caps.map
LHSName "Caps"
RHSName "UNICODE"
pass(unicode)
U+0061 > U+0041
U+0062 > U+0042
U+0063 > U+0043
; ...
U+007A > U+005A


(compile with teckit_compile caps.map)

\font\caps="Latin Modern Roman:mapping=caps"

{\caps All of this would be in caps}

@kccqzy: I've used letterspace=x in the font loading options, where x is the font size. I know it's not as good as coming up with good values for each individual kerning pair, but still. –  morbusg Oct 7 '12 at 11:14
@kccqzy: heh, no, it doesn't bother me. I'm glad you got answer that helped you :-) –  morbusg Oct 15 '12 at 18:54