15

I'm trying to make uppercase the first letter in string and lowercase other letters. Example: Input:eXample String and output Example string. How can I do that?

4 Answers4

23
\documentclass{article}
\newcommand\capmystring[1]{\capmystringaux#1\relax}
\def\capmystringaux#1#2\relax{\uppercase{#1}\lowercase{#2}}
\begin{document}
eXample String

\capmystring{eXample String}
\end{document}

enter image description here

In this case, \capmystring sends the argument to an auxiliary routine with an attached \relax token appended at the end. The auxiliary routine reads two arguments up to the \relax (one would hope and assume that the argument itself contains no \relax tokens). The way TeX absorbs arguments, the argument #1 will be a single token, whereas #2 will be all the remaining tokens up to (but not including) the originally supplied \relax. At that point it is as simple as applying \uppercase to the first token stored in #1, and \lowercase to the remaining tokens, all of which are stored in #2.

  • Thank you very much and can you explain the code for me? – user138843 Jul 13 '17 at 11:57
  • 1
    @user138843 I have added an explanation. – Steven B. Segletes Jul 13 '17 at 13:30
  • 2
    If anyone is worried about assuming that the argument contains no \relax, one could write something like \endcapmystringaux instead of \relax. (Then the assumption would be that the argument contains no \endcapmystringaux… you have to draw the line somewhere!) – ShreevatsaR Jul 13 '17 at 17:14
  • Hi Steven, I tried to apply your \capmystring to my \mystr{} (\mystr is a macro defined by : \newcommand{\mystr}{abc}), but nothing happend. So \capmystring doesn't work in this situation? How can I make it work? – BioCoder May 31 '21 at 03:41
  • 1
    @BioCoder \expandafter\capmystring\expandafter{\mystr}. You could \newcommand\xcapmystring[1]{\expandafter\capmystring\expandafter{#1}}, to define a macro that expands the argument once before applying \capmystring. – Steven B. Segletes May 31 '21 at 13:55
15

The expl3 language can do this using Unicode data:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand \firstcap { m } { \text_titlecase:n {#1} }
\ExplSyntaxOff
\begin{document}
eXample String

\firstcap{eXample String}
\end{document}

(assuming a new enough LaTeX2e format; for older cases, add \usepackage[utf8]{inputenc} with pdfTeX.)

We might extend this approach to allow for language-specific case mappings

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand \firstcap { O{} m }
  { \text_titlecase:nn {#1} {#2} }
\ExplSyntaxOff
\begin{document}
\firstcap{IJSSELMEER}     % Ijsselmeer
\firstcap[nl]{IJSSELMEER} % IJsselmeer
\end{document}
Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • Please be a bit more specific about the packages that need to be loaded to enable \firstcap to operate on utf8-encoded characters such as ö, ü, é, à, è, ł, ó, and ż. – Mico Jul 13 '17 at 15:24
  • 1
    @Mico I've updated the answer here: currently the pdfTeX version with direct input of Unicode chars needs the 'burning edge' version to avoid an error: CTAN update tomorrow. – Joseph Wright Jul 14 '17 at 21:51
  • Thanks so much! We all appreciate the hard work you put in for us! – Mico Jul 15 '17 at 07:17
3

Another solution using the stringstrings package:

\documentclass{article}

\usepackage{stringstrings}
\newcommand{\firstcap}[1]{\caselower[e]{#1}\capitalize{\thestring}}

\begin{document}
eXample String

\firstcap{eXample String}
\end{document}

Explanation: \caselower makes the whole string lowercase, the option [e] saves the result in \thestring such that it can be further processed, finally \capitalize does what it says and outputs the result.

crixstox
  • 1,784
  • Is there a way to extend your code so that it can handle non-ASCII-encoded characters, such as ä ö ü é à ê ł ó ż? (I picked these characters, more or less randomly, from German, French, and Polish keyboards...) – Mico Jul 15 '17 at 08:08
  • @Mico As far as I know the stringstrings package does not handle these special characters (please correct me if I am wrong). Thus I do not see a straight forward way to extend my solution. Sorry. – crixstox Jul 16 '17 at 12:21
3

Here's a LuaLaTeX-based solution that works with all UTF8-encoded characters. This approach can handle UTF8-encoded characters because it uses -- in place of the "standard" Lua string functions string.gsub, string.upper, and string.lower -- the functions unicode.utf8.gsub, unicode.utf8.upper, and unicode.utf8.lower. These functions are provided by the unicode.utf8 library, which is loade automatically by LuaTeX.

enter image description here

% !TeX program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function first_cap ( s )
   s = unicode.utf8.gsub ( s , "(%a)(%a*)", function(x,y)
          return ( unicode.utf8.upper(x) .. unicode.utf8.lower(y) )
          end )
   tex.sprint ( s )
end
\end{luacode}
\newcommand{\firstcap}[1]{\directlua{first_cap(\luastring{#1})}}

\begin{document}
\firstcap{eXample String}

\firstcap{Once upOn A tIMe i saw a BAT.}

\firstcap{ä ö ü é à è ł óÓÓÓ żĄĄĄ }
\end{document}

Addendum -- I just realized that I may have misinterpreted the OP's requirements: I had assumed that the uppercasing of the first letter in a word should apply to every word in the argument of \firstcap, not just the very first word. To make the uppercasing operation apply to the first word only (and thus applying the lowercasing operation to all other words in the argument of \firstcap), simply change the second argument of the Lua function unicode.utf8.gsub from "(%a)(%a*)" to "(%a)(.*)".

Mico
  • 506,678
  • 1
    One problem with the Lua UTF-8 support is it's not really clear what version of Unicode it is based on, and the treatment of contextual mappings is not documented. (Not a flaw in the answer, more a general frustration.) – Joseph Wright Jul 13 '17 at 15:22
  • @JosephWright - Thanks. So far, I've experienced only good results with the string functions of the unicode.utf8 library, which is loaded automatically by LuaTeX. (I don't know if this library is loaded by "plain" Lua5.2 or Lua5.3 as well, though.) I'll keep an eye out for potential problems. – Mico Jul 13 '17 at 15:28
  • 1
    Not arguing with that: like I say, the issue isn't that it doesn't work but that it's not clear (to me) what exactly the detail is. As someone who has read the Unicode docs on case changing, I would feel happier knowing what has been implemented! – Joseph Wright Jul 13 '17 at 15:33