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 my document, I'm often setting upper case words and abbreviations in small caps because it avoids breaking the flow (which upper case words does). Also, many words (like CUDA, for instance) are also entered as commands instead of directly as text.

Up to this point I have manually set these words in small caps where appropriate (like \textsc{\cuda}), but this becomes unnecessarily repetitive. What I would like to be able to do is to define a command like \cuda which prints CUDA in small caps where the text "mode" is normal roman, and sets CUDA in upper cases if the text mode is italics. The reason for doing this is the font I'm using doesn't support small caps in italics.

Hence I would like to be able to detect which text "mode" is currently in use, and act accordingly.

I've included a minimal example below to illustrate my point:

\documentclass{article}

\usepackage{textcase}

\newcommand{\cudaString}{CUDA}
\newcommand{\cuda}{\textsc{\MakeTextLowercase{\cudaString}}}

\begin{document}
Set \cuda in small caps here,
\itshape but do not set \cuda in small caps here.
\end{document}
share|improve this question
    
There's little point in \newcommand{\cuda}{\textsc{CUDA}}, as it will appear in all caps anyway; it's probably \textsc{cuda}, isn't it? –  egreg Oct 15 '11 at 19:25
    
Ah of course; I forgot that in my code I use \MakeTextLowercase and I wrote the example code just from memory. –  gablin Oct 17 '11 at 8:51
    
So it would be better to show a real example, as solutions with \MakeUppercase might have problems. –  egreg Oct 17 '11 at 8:57
    
Probably. I've updated the example accordingly. –  gablin Oct 17 '11 at 9:07
    
Related: tex.stackexchange.com/questions/163991/… –  Jubobs Mar 6 at 12:17
add comment

3 Answers

up vote 22 down vote accepted

LaTeX's 'New Font Selection Scheme' (NFSS) stores information about the font in a number of macros. The macro \f@shape stores the shape: n for upright, it for italic and sc for small caps. \f@series stores the series: m for mid-weight and bx for bold, while \f@family stores the family: something like cmr for roman, cmss for sanserif and cmtt for monospaced (it's dependent on the current font).

Thus you can test for small caps using

\makeatletter
\newcommand*{\IfSmallCapsTF}{%
  \ifx\f@shape\my@test@sc
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\newcommand*{\my@test@sc}{sc}
\makeatother

 \IfSmallCapsTF{true-code}{false-code}
share|improve this answer
    
I would actually like to accept two answers - this on and egreg's - as I incorporated both to make a command which sets its argument in small caps if the current style is roman, fake small caps if it is italics, and otherwise just converts it to upper case. –  gablin Oct 17 '11 at 13:18
    
I'm wondering... Do you really have to define a command that expands to sc? Or is that name already stored in some kernel macro? –  Jubobs Mar 6 at 11:22
    
@Jubobs That I know of latex.ltx doesn't provide any useful shortcuts for these. Of course, with an up-to-date engine you can use \pdfstrcmp or similar for the test (\ifx likely faster if used many times). –  Joseph Wright Mar 6 at 12:01
    
@JosephWright Thanks. I need to perform a test on the current font shape, but I was wondering whether I was "reinventing the wheel" by defining those macros. –  Jubobs Mar 6 at 12:05
add comment

You may want to fake an italic small caps font:

\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
  \ifdim\fontdimen\@ne\font>\z@
    \begingroup\check@mathfonts
    \fontsize\sf@size\z@\selectfont
    \MakeUppercase{#1}\endgroup
  \else
    \textsc{#1}%
  \fi
}
\makeatother

\newcommand{\cuda}{\SCorIT{cuda}}

Depending on the font the result can turn out to be as desired. Beware that for bold face another test must be added.

enter image description here

If you use \MakeLowercase or textcase's \MakeTextLowercase for defining the acronym, you should modify the definition into

\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
  \ifdim\fontdimen\@ne\font>\z@
    \begingroup\check@mathfonts
    \fontsize\sf@size\z@\selectfont
    \let\MakeTextLowercase\@firstofone % for textcase
    \let\MakeLowercase\@firstofone     % for standard LaTeX
    \MakeTextUppercase{#1}\endgroup
  \else
    \textsc{#1}%
  \fi
}
\makeatother

that will avoid accumulating case changes.

The example was generated with the following code:

\documentclass{standalone}
\usepackage{textcase}
\makeatletter
\DeclareRobustCommand{\SCorIT}[1]{%
  \ifdim\fontdimen\@ne\font>\z@
    \begingroup\check@mathfonts
    \fontsize\sf@size\z@\selectfont
    \let\MakeTextLowercase\@firstofone
    \MakeTextUppercase{#1}\endgroup
  \else
    \textsc{#1}%
  \fi
}
\makeatother

\newcommand{\cudaString}{CUDA}
\newcommand{\cuda}{\SCorIT{\MakeTextLowercase{\cudaString}}}

\begin{document}

\hbox{Set \cuda{} in small caps here,\strut}
\hbox{\itshape but do not set \cuda{} in small caps here.\strut}

\end{document}
share|improve this answer
    
Could you please extend it to a minimal example? I keep getting compilation errors when I try to use it in my document. –  gablin Oct 17 '11 at 13:00
    
My apologies. I must have done something wrong the first time, because now I got it running. –  gablin Oct 17 '11 at 13:12
add comment

Stealing a bit from the definition of \em (seen using latexdef em), we can create a command \SCorUC that typesets its argument in small caps or uppercase depending on context:

\makeatletter
\newcommand{\SCorUC}[1]{\ifdim\fontdimen\@ne\font>\z@\MakeUppercase{#1}\else\textsc{#1}\fi}
\makeatother
\newcommand{\cuda}{\SCorUC{cuda}}
share|improve this answer
add comment

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.