5

I am trying to convert a string as in the example, with all lowercase characters except the first. However, xmakefirstuc does not like me that much. Here's my MWE:

% arara: pdflatex
\documentclass{book}
\usepackage{xstring}
\usepackage{textcase}
\usepackage{mfirstuc}
\newcommand{\howtodothis}[1]{%
    \StrSubstitute{#1}{ }{-}[\mylong]%
    \xmakefirstuc{\MakeTextLowercase{\mylong}}\\%
    \xmakefirstuc\expandafter{\MakeTextLowercase{\mylong}}\\%
    \xmakefirstuc{\expandafter\MakeTextLowercase{\mylong}}\\%
    \xmakefirstuc{\MakeTextLowercase\expandafter{\mylong}}\\%
    \xmakefirstuc{\MakeTextLowercase{\expandafter\mylong}}\\%
    \xmakefirstuc\expandafter\relax{\MakeTextLowercase{\mylong}}\\%
    \xmakefirstuc{\expandafter\relax\MakeTextLowercase{\mylong}}\\%
    \xmakefirstuc{\MakeTextLowercase\expandafter\relax{\mylong}}\\%
    \xmakefirstuc{\MakeTextLowercase{\expandafter\relax\mylong}}\\%
    \expandafter\xmakefirstuc{\MakeTextLowercase{\mylong}}\\%
    \expandafter\xmakefirstuc\expandafter{\MakeTextLowercase{\mylong}}\\%
    \expandafter\xmakefirstuc{\expandafter\MakeTextLowercase{\mylong}}\\%
    \expandafter\xmakefirstuc{\MakeTextLowercase\expandafter{\mylong}}\\%
    \expandafter\xmakefirstuc{\MakeTextLowercase{\expandafter\mylong}}\\%
    \expandafter\xmakefirstuc\expandafter\relax{\MakeTextLowercase{\mylong}}\\%
    \expandafter\xmakefirstuc{\expandafter\relax\MakeTextLowercase{\mylong}}\\%
    \expandafter\xmakefirstuc{\MakeTextLowercase\expandafter\relax{\mylong}}\\%
    \expandafter\xmakefirstuc{\MakeTextLowercase{\expandafter\relax\mylong}}\\%
}
\begin{document}\noindent%
\howtodothis{First Letter Should Be Uppercase, All Others Lowercase.}
\end{document}
1
5
\xmakefirstuc{\MakeTextLowercase{\mylong}}

is a shortcut for

\expandafter\makefirstuc\expandafter{\MakeTextLowercase{\mylong}}

which attempts to expand \MakeTextLowercase{\mylong}. Since \MakeTextLowercase is robust, no expansion is performed. The TeX primitive \lowercase also doesn't expand, so trying to expand to lowercase and then applying \makefirstuc won't work. However, it will work if you first expand \mylong. Like this:

\expandafter\makefirstuc\expandafter{\expandafter\MakeTextLowercase\expandafter{\mylong}}

Or using \xmakefirstuc:

\xmakefirstuc{\expandafter\MakeTextLowercase\expandafter{\mylong}}

Here's the MWE:

% arara: pdflatex
\documentclass{book}
\usepackage{xstring}
\usepackage{textcase}
\usepackage{mfirstuc}
\newcommand{\howtodothis}[1]{%
    \StrSubstitute{#1}{ }{-}[\mylong]%
    \xmakefirstuc{\expandafter\MakeTextLowercase\expandafter{\mylong}}%
}
\begin{document}\noindent%
\howtodothis{First Letter Should Be Uppercase, All Others Lowercase.}
\end{document}

This is the result:

First-letter-should-be-uppercase-all-others-lowercase

Edit: This is actually equivalent to:

\MakeTextLowercase{\MakeUppercase{F}irst-Letter-Should-Be-Uppercase,-All-Others-Lowercase.}

This may seem a bit contradictory as logic suggests that the \MakeTextLowercase should counteract the \MakeUppercase, but this is a result of the way that TeX processes tokens (see @egreg's comment below). You can see this from:

\lowercase{\uppercase{f}}

which produces an uppercase F.

4
  • 2
    \lowercase{\uppercase{f}} simply passes \uppercase{f} to the next stage; the character tokens are transformed using the \lccode table and the resulting token list is placed back in the main input stream; then \uppercase{f} is processed in a similar way, which produces F. If you do \uppercase{\lowercase{f}} or \uppercase{\lowercase{F}}, you get f.
    – egreg
    Aug 19 '14 at 16:01
  • 1
    @egreg I think the point being made in the edit is that people might expect a 'functional' outcome (lowercase-of-uppercase-of-'f'), which as the TeX experts know is not what you get :-)
    – Joseph Wright
    Aug 19 '14 at 16:03
  • @JosephWright There is a functional outcome, but in the reverse order.
    – egreg
    Aug 19 '14 at 16:04
  • 1
    @egreg It's contrary to what most computer programmers would expect (as quite often happens with TeX). In most languages newString = lowercase(uppercase(orgString)) would result in a lowercase string. I'll edit my edit. Aug 19 '14 at 16:45
4

Case changing use TeX primitives is not expandable, which is why trying to 'force the issue' isn't easy to get right here. Nicola has shown how to handle this using mfirstuc. A 'classical' approach to the same issue is to split the first token off from all of the rest, for example

\documentclass{book}
\usepackage{xstring}
\usepackage{textcase}
\newcommand\howtodothis[1]{%
  \howtodothisaux#1\stop
}
\newcommand\howtodothisaux{}
\long\def\howtodothisaux#1#2\stop{%
  \MakeTextUppercase{#1}%
  \MakeTextLowercase{#2}%
}
\begin{document}\noindent%
\howtodothis{First Letter Should Be Uppercase, All Others Lowercase.}
\end{document}

With an up-to-date expl3, you can do this using the expandable \text_titlecase:n function and no need to split the input:

\documentclass{book}
\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\howtodothis}[1]{%
  \text_titlecase:n {#1}%
}
\ExplSyntaxOff
\begin{document}\noindent%
\howtodothis{First Letter Should Be Uppercase, All Others Lowercase.}
\end{document}

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.