2

This is similar to Change the color of capital letters and the MWE below is modelled on egreg's answer. It works up to the point of correctly changing the first character in the input string. What I now want to do is pass a second parameter indicating which character of the string to change i.e. instead of \capme{AVXxx} I want to be able to write e.g. \capme{AVXxx}{V} and have only the colour of the "V" change. The initial string will have a maximum of 8 ASCII letters, it will always contain exactly one letter matching the second parameter (so, in that example, its only valid value is one of A, V or X).

I've tried to pass the first parameter to the string "s" and the second parameter to the string "l" but even hardcoding "l" as "V" isn't working.

MWE:

\documentclass{article}
\usepackage{xcolor}
\usepackage{luacode}

\begin{luacode*}
function wrap(s, l)
l="[%uV]"
s=" "..s -- The first letter may also change
s=unicode.utf8.gsub(s, "([%s{])("..l..")", "%1\\colorlead{%2}")
s=unicode.utf8.sub(s,2) -- Delete leading space
tex.print(s) 
end -- function wrap
\end{luacode*}

\def\capme#1{\directlua{wrap([[#1]])}}

\begin{document}

\def\colorlead#1{{\color{red}#1}}

\capme{AVXxx}

\end{document} 
1

May be you don't need Lua at all. The following code just recurses over the first argument characters and colors those which match the second argument. Also, I've added a simple Lua based command as well.

\documentclass{article}
\usepackage{ifthen}
\usepackage{xcolor}
\usepackage{luacode}

\begin{luacode*}
function wrap(s, l)
s=unicode.utf8.gsub(s, l, "\\colorlead{%1}")
tex.print(s) 
end
\end{luacode*}

\def\luacapme#1#2{\directlua{wrap([[#1]],[[#2]])}}

\makeatletter
\def\capme#1#2{\@capme{#2}#1\relax}

\def\@capme#1#2{%
  \ifthenelse{\equal{\relax}{#2}}{%
    \let\next\relax
  }{%
    \def\next{\@capme{#1}}%
    \ifthenelse{\equal{#2}{#1}}{%
      \colorlead{#2}%
    }{%
      #2%
  }}\next
}
\makeatother

\def\colorlead#1{{\color{red}#1}}

\begin{document}
\luacapme{AVXxx}{A}

\luacapme{AVXxx}{V}

\luacapme{AVXxx}{x}
\end{document}

The result is the following:

enter image description here

  • It's certainly possible without Lua - it just seemed that it should be easy to do that sort of string matching in Lua :-( – DLyons May 14 '18 at 16:04
  • If it's an exercise in Lua then I've added \luacapme which does a simple substitution in Lua. It isn't intended to use patterns in place of the second argument. – Sergei Golovan May 14 '18 at 16:36
  • Excellent. It was sort of a learning experiment to meet an actual need. – DLyons May 14 '18 at 16:38
1

Also without lua; however, it breaks the natural interletter kerning when color change takes place.

It works by creating, at each invocation, a new version of the macro \capmeaux, which sets itself up to parse with #2 as the divider. Thus, \capme{AVXxx}{A} creates the definition

\def\capmeaux#1A#2\relax{#1\textcolor{\colorlead}{A}#2}

and then proceeds to invoke it with \capmeaux AVXxx\relax

The MWE:

\documentclass{article}
\usepackage{xcolor}
\newcommand\colorlead{red}
\newcommand\capme[2]{%
  \def\capmeaux##1#2##2\relax{##1\textcolor{\colorlead}{#2}##2}\capmeaux#1\relax}
\begin{document}
\capme{AVXxx}{A}

\capme{AVXxx}{V}

\capme{AVXxx}{X}
\end{document} 

enter image description here

  • Kerning isn't an issue for these sequences. – DLyons May 14 '18 at 17:37

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.