9

Generally, I tend to see LaTeX commands as subroutines rather than functions. I was wondering if LaTeX allows the definition of functions for, say, transforming text by replacing substrings.

I suppose that feature is something possible, because some packages let the user to use functions, real functions, to transform text. Even MakeUppercase does it.

If I wanted to make a function that replaces all "U"s for "V"s, and all "W"s for "VV"s, what would it be the anatomy of that function?

10
\documentclass{article}
\usepackage{stringstrings}
\newcommand\latinify[1]{%
  \convertchar[q]{#1}{U}{V}%
  \convertchar{\thestring}{W}{VV}%
}
\begin{document}
\def\myphrase{CUSTWINIUS}
\myphrase{} versus \latinify{\myphrase}
\end{document}

enter image description here

And now for some sleight of hand:

\documentclass{article}
\usepackage{stringstrings}
\newcommand\latinify[1]{%
  \encodetoken{\kern}%
  \encodetoken[2]{\footnotesize}%
  \encodetoken[3]{\normalsize}%
  \convertchar[e]{#1}{U}{\footnotesize V\normalsize}%
  \convertchar[e]{\thestring}{W}{V\kern-5pt\footnotesize V\normalsize}%
  \retokenize{\thestring}\thestring%
  \decodetoken{\kern}%
  \decodetoken[2]{\footnotesize}%
  \decodetoken[3]{\normalsize}%
}
\begin{document}
\def\myphrase{UNCLE CUSTWINIUS WABBLEWAUSER}
\myphrase{} versus 

\latinify{\myphrase}
\end{document}

enter image description here

  • 1
    UNCLE CUSTWINIUS WABBLEWAUSER... he has a cousin, you know? – Steven B. Segletes Apr 15 '16 at 19:11
  • 2
    Release Roderick? – Ian Thompson Apr 15 '16 at 20:13
  • 2
    @IanThompson Slightly off in my recollection: "He has a wife, you know. You know what she's called? She's called... 'Incontinentia'... " imdb.com/title/tt0079470/quotes – Steven B. Segletes Apr 15 '16 at 20:17
  • Yes, he has a German cousin. – egreg Apr 15 '16 at 20:33
8

The \replacestrings from OPmac can be used. It is implemented by few lines of TeX code:

\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\bgroup \catcode`!=3 \catcode`?=3
\gdef\replacestrings#1#2{\long\def\replacestringsA##1#1##2!{%
   \ifx!##2!\addto\tmpb{##1}\else\addto\tmpb{##1#2}\replacestringsA##2!\fi}%
   \edef\tmpb{\expandafter}\expandafter\replacestringsA\tmpb?#1!%
   \long\def\replacestringsA##1?{\def\tmpb{##1}}\expandafter\replacestringsA\tmpb
}
\egroup

\def\cnvUVW#1{\def\tmpb{#1}%
   \replacestrings{U}{V}\replacestrings{W}{V\kern-.5emV}\tmpb}

\cnvUVW{UNCLE CUSTWINIUS WABBLEWAUSER}

Edit I am surprised that nobody suggested usage of active characters here. I repair it:

\def\adef#1{\catcode`#1=13 \begingroup \lccode`\~=`#1\lowercase{\endgroup\def~}}
\def\setUW{\adef U{V}\adef W{V\kern-.5emV}}

{\setUW UNCLE CUSTWINIUS WABBLEWAUSER}
7

A pure LuaLaTeX solution: A Lua function (named u2v_w2vv) and a LaTeX macro (named \uvwvv) that invokes the Lua function.

enter image description here

\documentclass{article}

%% Lua-side code
\usepackage{luacode}
\begin{luacode}
function u2v_w2vv ( s )
  s = string.gsub ( s , "U" , "V" )
  s = string.gsub ( s , "W" , "VV" )
  return tex.sprint ( s )
end
\end{luacode}

%% LaTeX-side code
\newcommand\uvwvv[1]{\directlua{u2v_w2vv(\luastring{#1})}}

\begin{document}
UNCLE CUSTWINIUS WABBLEWAUSER vs. 

\uvwvv{UNCLE CUSTWINIUS WABBLEWAUSER}
\end{document}
6

Transformations like \MakeUppercase are not really text manipulations, because they rely on a predefined one-to-one mapping. With LuaTeX it's certainly possible to modify the input stream before typesetting it in fairly general ways. With legacy engines one can just make substitutions to the argument of a macro (like for \MakeUppercase).

Here's a way with l3regex; the example involves the German cousin of Uncle Custwinius, who spells his name with an Ä and wants his surname in italics.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\useV}{m}
 {
  \tl_set:Nn \l_corbal_withuw_tl { #1 }
  \regex_replace_all:nnN { U } { V } \l_corbal_withuw_tl
  \regex_replace_all:nnN { W } { VV } \l_corbal_withuw_tl
  \tl_use:N \l_corbal_withuw_tl
 }
\ExplSyntaxOff

\begin{document}

\useV{UNCLE CUSTWINIUS \textit{WABBLEWÄUSER}}

\end{document}

enter image description here

6

This answer addresses the letter replacements by a OpenType feature file for LuaTeX:

\documentclass{article}

\usepackage{filecontents}
\usepackage{fontspec}

\begin{filecontents*}{uw2v.fea}
languagesystem DFLT dflt;
languagesystem latn dflt;

feature uw2v {
  lookup U_TO_V {
    sub U by V;
  } U_TO_V;
  lookup W_TO_VV {
    sub W by V V;
  } W_TO_VV;
} uw2v;
\end{filecontents*}

\DeclareRobustCommand*{\textuwtov}[1]{%
  \begingroup
    \addfontfeatures{
      FeatureFile=uwtovs.fea,
      RawFeature=+uw2v,
    }%
    #1%
  \endgroup
}
\setmainfont[FeatureFile=uwtovs.fea]{latinmodernroman}
\setsansfont[FeatureFile=uwtovs.fea]{latinmodernsans}

\begin{document}

\noindent
UNCLE CUSTWINIUS WABBLEWAUSER\\
\textuwtov{UNCLE CUSTWINIUS WABBLEWAUSER}

\bigskip
\noindent
\textsf{UNCLE CUSTWINIUS WABBLEWAUSER\\
\textuwtov{UNCLE CUSTWINIUS WABBLEWAUSER}}
\end{document}

Result

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.