Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}
\setsecheadstyle{\Large\sffamily\raggedright}

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
\renewcommand{\fnum@figure}[1]{\small\bfseries\lsstyle\lsstyle\MakeUppercase{\figurename~\thefigure}\quad}
\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...

share|improve this question

3 Answers 3

up vote 2 down vote accepted

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}

enter image description here

share|improve this answer

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{%
      \expandafter{\csname #1name\endcsname}~\expandafter{\csname the#1\endcsname}\quad
    }
  }
}
\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...

share|improve this 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)

and when loading the font, make use of the mapping:

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

and then you could do

{\caps All of this would be in caps}
share|improve this answer
    
I see what you mean. But limiting the engine to XeTeX is a bit restricting, and apparently it doesn't have microtype support (which is quite important as it is better to letterspace uppercase letters). –  kccqzy Oct 7 '12 at 10:13
    
@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
    
I marked the other answer as accepted because it solves the specific problem better. Your answer is indeed a bit roundabout but is more general. Apparently I could not set two answers as accepted but I upvoted yours. Sorry if that bothers you. –  kccqzy Oct 15 '12 at 6:03
    
@kccqzy: heh, no, it doesn't bother me. I'm glad you got answer that helped you :-) –  morbusg Oct 15 '12 at 18:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.