In XeLaTeX there is an UppercaseSmallCaps font option (as mentioned in this question for example) that will cause upper-case letters to be rendered in small-caps and lower-case letters to remain.

Question: How can UppercaseSmallCaps be implemented in plain LaTeX (or pdfLaTeX) so that text like \upsc{ABCdef} will be rendered as \textsc{abc}def?

  • Hmmm. Having a really hard time deciding between egreg and Joseph Wright's solutions! – mforbes Jan 4 '12 at 5:53



Doesn't work with accented letters, of course.

enter image description here

  • Isn't the point of the question that we're not allowed to use XeTeX? – Joseph Wright Jan 2 '12 at 14:37
  • 1
    @JosephWright Now it works with pdflatex (and does ligatures and kerning when possible). – egreg Jan 2 '12 at 15:49
  • Nice fast solution! Better than Joseph's solution in that it is an order of magnitude faster and does ligatures and kerning, but it does not allow for spaces, paragraphs etc. – mforbes Jan 4 '12 at 5:53
  • @mforbes No, of course. But I believed it was for acronyms or abbreviations. – egreg Jan 4 '12 at 9:41
  • \def\upsc#1{{...}} should have an enclosing group so that the smallcaps do not leak. Will fix later when I test more thoroughly. – mforbes Jan 17 '12 at 6:07

Maybe a bit over the top, but you could use l3regex to achieve this

\cs_generate_variant:Nn \tl_rescan:nn { nV } 
\NewDocumentCommand \upsc { m }
    \tl_set:Nn \l_tmpa_tl {#1}
    \regex_replace_all:nnN { ([A-Z]+) }
      { \c{textsc} \cB\{ \c{lowercase} \cB\{ \1 \cE\} \cE\} } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl

This uses the latest experimental version of l3regex, which is on CTAN and which has an 'extended regex' system to allow the inclusion of category-code information in the search and replace text.

You could set up a search for upper-case letters in the same way using alternative methods (such as xstring).

Explanation of the code

The basic idea here is to store the text, do a replacement then print it again. I've chosen to replace each upper case <Letter> by


The search part is a simple regex ([A-Z]+), which will capture the letter as \1 (in the replace part). There, \c{textsc} will create the control sequence \textsc in the updated text and \c{lowercase} creates \lowercase. \1 is the captured letter from the search part, while \cB\{ and \cE\} possibly need a bit of explanation. In the replacement text, \cB\{ creates the character { (which needs to be escaped) with category code 'Begin group'. Similarly, \cE\} creates the character } with category code 'End group'.

The final stage is to insert the result into the input stream. If you want to see what is happening, try adding \tl_show:N \l_tmpa_tl after the \tl_use:N line.

  • You can't use fontspec with pdfTeX, so UppercaseSmallCaps is not directly relevant. – Joseph Wright Jan 2 '12 at 14:25
  • Support for accents would be more challenging (they'll work in the lower case part but not the upper case part). – Joseph Wright Jan 2 '12 at 14:38
  • Nice demonstration of LaTeX3! Better than egreg's in that it works with spaces and paragraphs (with a small modification), but an order of magnitude slower, and disables kerning... – mforbes Jan 4 '12 at 5:48
  • One comment: if you want this to work with macros, then you should replace \tl_set:Nn with \tl_set:Nx so that those macros get expanded. This is needed, for example, if trying to use this with the glossaries package: \renewcommand*{\acronymfont}[1]{\upsc{#1}}. – mforbes Jul 12 '19 at 9:16
  • 1
    @mforbes No, I just meant \protected@edef \l_tmpa_tl {#1}: there are some 2e concepts that really can't be avoided. – Joseph Wright Jul 12 '19 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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