16

I'd like to apply a function to capitals only so that:

\emphcaps{YaWeH}

Outputs like:

\emph{Y}a\emph{W}e\emph{H}

Preferably without using too many packages (I already use memoir).

NOTES: I use XeLaTeX (as it's bidi support seems best).

5 Answers 5

16
\documentclass[a4paper]{article}

\makeatletter
\DeclareRobustCommand{\emphcap}[1]{\begingroup\emph@cap#1\@nil\endgroup}
\def\emph@cap#1{%
  \ifx#1\@nil
    \expandafter\@gobble
  \else
    \emph@@cap{#1}%
  \fi
  \emph@cap}
\def\emph@@cap#1{%
  \ifnum\uccode`#1=`#1\relax
    \itshape#1\emph@captrue
  \else
    \ifemph@cap\/\else\fi\upshape#1\emph@capfalse
  \fi}
\newif\ifemph@cap
\makeatother


\begin{document}
\emphcap{THiSiSWHaTIWaNT}
\end{document}

This assumes that your input contains only normal letters (no accents). The result is really ugly.

enter image description here

5
  • 2
    My eyes! They bleed!
    – Canageek
    Feb 13, 2012 at 15:53
  • I cannot understand this code, but given what the question asks, could this be adapted to a robust answer to this question: tex.stackexchange.com/questions/33148/…
    – Seamus
    Feb 13, 2012 at 16:33
  • @Seamus No, it won't be robust.
    – egreg
    Feb 13, 2012 at 17:15
  • @egreg You mean it's been uniquely designed for only this question. That is short of a miracle:) Feb 13, 2012 at 17:47
  • Nice answer! I'd have picked it is it weren't for a shorter one i got in irc.
    – cies
    Feb 15, 2012 at 7:47
15

An approach using LaTeX3: the important command is \regex_replace_all:nnN. Its first argument is a regular expression (here, [A-Z] matches any uppercase letter); its second argument the replacement, here \textit followed by \0 (what the regular expression matched); and the third is a token list variable on which we want to do the replacement.

\documentclass[a4paper]{article}
\usepackage{l3regex}
\ExplSyntaxOn
\cs_new_protected:Npn \emphcap #1
  {
    \tl_set:Nn \l_tmpa_tl {#1}
    \regex_replace_all:nnN { [A-Z] } { \c{textit} \0 } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
  }
\ExplSyntaxOff
\begin{document}
\emphcap{THiS iS \texttt{WHaT} I WaNT}
\end{document}

Of course, spaces are preserved, as are any formatting commands within the argument (here I put \texttt for the demo). This should work with any recent enough version of the l3kernel and l3experimental bundles (February 2012, say).

Alternatively, you could use the replacement

\regex_replace_all:nnN { [A-Z]+ } { \c{textit} \cB\{ \0 \cE\} } \l_tmpa_tl

I changed the regex to match any number of consecutive uppercase letters, and I changed the replacement text to add braces around the argument to \textit. This avoids the extra space inserted in \textit{N}\textit{T}. The output:

Output of the code choosing the second replacement

4
  • Thanks a lot for your LaTeX3 code. I like to see how a problem can be solved with different kinds of LaTeX. Maybe in near future it should be good practice to show how one can solve a problem with different kinds of LaTeX like it is shown on this question.
    – Holle
    Feb 13, 2012 at 20:19
  • Awesome code, Bruno! :) Feb 14, 2012 at 9:43
  • Beautiful code Bruno. Feb 14, 2012 at 12:28
  • Very nice and concise answer! I've been searching the regex route myself, but failed.
    – cies
    Feb 15, 2012 at 7:49
14

Ok, here is an other approach dedicated to LuaLaTeX fans (and future fans of LuaLaTeX). I think it is a good example to show how easy it is to write a few (easy to understand) lines of Lua code. In the provided Lua code one can check the input string for every char and format any LaTeX string you need without cryptic TeX commands.

It is good practice to write the lua functions in a separate file with the extension .lua. For this MWE I use the filecontents environment instead to provide an extra file for the lua script.

\documentclass{book}
\usepackage{filecontents}

\begin{filecontents*}{luaFunctions.lua}
function emphcaps(input) 
    outputString = ""
    len = string.len(input)

    for i = 1, len, 1 do --for each char in string
      ascii =  string.byte(input, i) -- convert the char in a decimal 

      if(ascii >= 65 and ascii <= 90) then -- upper case (look to the ASCII table)
        outputString = outputString.."\\emph{"..string.char(ascii).."}"
      else
        outputString = outputString..string.char(ascii)
      end

    end

    tex.print(outputString)
end
\end{filecontents*}

% read the external lua file to declare the defined function,
% but without execute the Lua function
\directlua{dofile("luaFunctions.lua")}

% latex command to execute the lua function
\def\emphcaps#1{\directlua{emphcaps("#1")}}

\begin{document}
\noindent
\emphcaps{YaWeH}\\
\emphcaps{LuaLaTeX}
\end{document}

Edit: After the great comment from Khaled Hosny I want to provide a very straight solution. It shows again the power of Lua ;-). The new function replaces all (thats what the + after %u stands for) upper chars (thats what the %u stands for) with \emph{}. The %1 holds the value which is surrounded by the ( ) in the search pattern.

function emphcaps(input)
    output, count = string.gsub(input, '(%u+)', '\\emph{%1}')
    tex.print(output)
end
4
  • 4
    Good example. In true TeX spirit there is no true way:) Keep these Lua answers coming. Feb 13, 2012 at 15:50
  • 2
    This can be much simplified by using string.gsub() e.g. string.gsub(input, '(%u+)', '\\emph{%1}') (or unicode.utf8.gsub to handle Unicode strings) Feb 13, 2012 at 16:40
  • @Khaled Hosny: Great comment! Thanks a lot! Thats the spirit of Lua, how I like it.
    – Holle
    Feb 13, 2012 at 20:07
  • I use XeTeX, which I believe is different from LuaTex -- I'd love to use Lua over TeX-programming though.
    – cies
    Feb 15, 2012 at 7:51
12

Consider rather writing a macro for this type of issue. For example you can create a command for your example as follows:

\newcommand{\yaweh}{%
  \emph{Y}a\emph{W}e\emph{H}
} 

The advantage of this, is that also your mark-up can be more meaningful.

As per request and a bit of a different approach to egreg's solution.

\documentclass{article}
\makeatletter
\def\uP#1{%
\@tfor\next:=#1\do{%
 \ifnum \expandafter
    \the\expandafter\lccode
      \expandafter`\next=\expandafter
       \number\expandafter`\next
       \next
 \else 
     \textit{\next}%
\fi}%
}
\begin{document}
\uP{aLLah}
\end{document}
4
  • sorry if it was not clear from my question but i want it to be dynamic. i.e. next thing i want to use it for ALLaH and many other words.
    – cies
    Feb 13, 2012 at 11:40
  • @user62152 Please see amended post. Feb 13, 2012 at 15:19
  • 1
    @user62152 Couldn't you set it up one for each deity? I mean, as long as you avoid the Hindu pantheon it shouldn't take you that long.
    – Canageek
    Feb 13, 2012 at 15:54
  • Sorry, but in the post i say already that i'd like to "apply a function to each capital". That function will be something different then \emph eventually.
    – cies
    Feb 15, 2012 at 7:46
-2

I got this answer from dl903 on irc://irc.freenode.net/#latex

\def\capOnlyEmph#1{\mycaps#1\relax.}\def\mycaps#1#2.{\ifnum`#1<97\emph{#1}\else#1\fi\ifx#2\relax\else\mycaps#2.\fi}

\capOnlyEmph{ALLaH, YaWeH}

I use it in my document to format transliterations from semitic/arab languages. (instead of the \emph command i use the relsize package to make the capitals 15% smaller, and i format the whole thing with a different font)

2
  • 5
    Of course you'll have noticed that only the first letter is italicized, provided it's uppercase. This code is wrong, because it only examines the first letter. The cause, of course, is the double L.
    – egreg
    Feb 15, 2012 at 10:03
  • Swapping #2 and \relax would help a bit. Mar 1, 2012 at 2:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .