35

Is it possible to give the letters a,e,i,o,u,y a different color in a piece of text? For instance, color all the a's red, the e's blue, the i's green, etc.

EDIT: Without doing it manually of course.

Ludovic C.
  • 8,888
maryJane
  • 491
  • 3
  • 4

3 Answers3

37

enter image description here

Requires xelatex:

\documentclass{article}
\usepackage{color}
\XeTeXinterchartokenstate = 1
\newXeTeXintercharclass \vowelsclass

\XeTeXcharclass \a \vowelsclass \XeTeXcharclass\e \vowelsclass \XeTeXcharclass \i \vowelsclass \XeTeXcharclass\o \vowelsclass \XeTeXcharclass `\u \vowelsclass

\XeTeXcharclass \A \vowelsclass \XeTeXcharclass\E \vowelsclass \XeTeXcharclass \I \vowelsclass \XeTeXcharclass\O \vowelsclass \XeTeXcharclass `\U \vowelsclass

\XeTeXinterchartoks 0 \vowelsclass = {\bgroup\color{blue}} \XeTeXinterchartoks 1 \vowelsclass = {\bgroup\color{blue}} \XeTeXinterchartoks 2 \vowelsclass = {\bgroup\color{blue}} \XeTeXinterchartoks 3 \vowelsclass = {\bgroup\color{blue}} \XeTeXinterchartoks 4095 \vowelsclass = {\bgroup\color{blue}} \XeTeXinterchartoks \vowelsclass 0 = {\egroup} \XeTeXinterchartoks \vowelsclass 1 = {\egroup} \XeTeXinterchartoks \vowelsclass 2 = {\egroup} \XeTeXinterchartoks \vowelsclass 4095 = {\egroup}

\begin{document}

One two three four five six seven eight.

\end{document}


Note that the word boundary class currently has the number 4095 (since 2016) orginally it was 255

David Carlisle
  • 757,742
34

This is just for practicing with LaTeX3 code.

\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\colorize}{mm}
 {
  \cs_set:cpn { maryjane_color_#1: } { \textcolor{#2}{#1} }
 }
\tl_new:N \l_maryjane_text_tl
\NewDocumentCommand{\changecolors}{ O{aeiou} m }
 {
  \tl_set:Nn \l_maryjane_text_tl { #2 }
  \tl_map_inline:nn { #1 } 
   {
    \tl_replace_all:Nnn \l_maryjane_text_tl { ##1 } { \use:c { maryjane_color_##1: } }
   }
  \l_maryjane_text_tl
 }
\ExplSyntaxOff

\colorize{a}{red}
\colorize{e}{blue}
\colorize{i}{green}
\colorize{o}{yellow}
\colorize{u}{blue!30}

\begin{document}

\changecolors{The quick brown fox jumped over the lazy dog}

\changecolors[a]{The quick brown fox jumped over the lazy dog}

\end{document}

In the optional argument you can specify a subset of the declared letters. If you specify an undeclared letter (with \colorize), it will be gobbled.

enter image description here

egreg
  • 1,121,712
  • 1
    Very nice. So this works in the style of \textbf{...} or \textcolor{...}. How would you modify this to make it work in the style of \bfseries or \color{...}? – A.Ellett Oct 13 '13 at 21:41
  • @A.Ellett I need to get the text before starting to change the colors. – egreg Oct 13 '13 at 21:47
4

A luatex solution to the problem:

\RequirePackage{luatex85}
\documentclass[varwidth]{standalone}
\usepackage{luacode}
\begin{luacode}
vowels = {'a', 'e', 'i', 'o', 'u', 'y',
          'A', 'E', 'I', 'O', 'U', 'Y'}

vowels_char = {}
for _, value in pairs(vowels) do
  vowels_char[#vowels_char + 1] = string.byte(value)
end

function table.contains(table, element)
  for _, value in pairs(table) do
    if value == element then
      return true
    end
  end
  return false
end

function color_vowels(head)
  for n in node.traverse_id(node.id("glyph"), head) do
    if table.contains(vowels_char, n.char) then
        local n1, n2
        n1 = node.new(node.id("whatsit"), node.subtype("pdf_literal"))
        n2 = node.new(node.id("whatsit"), node.subtype("pdf_literal"))
        n1.data = "q 1 0 0 rg"
        n1.mode = 1
        node.insert_before(head, n, n1)
        n2.data = " Q"
        n2.mode = 1
        node.insert_after(head, n, n2)
    end
  end
  return head
end
luatexbase.add_to_callback("pre_linebreak_filter", color_vowels, "Color vowels")
luatexbase.add_to_callback("hpack_filter", color_vowels, "Color vowels")
\end{luacode}

\begin{document}

The quick brown fox jumped Over the lazy dog

\hbox{The quick brown fox jumped Over the lazy dog}

$a^2$
\end{document}

enter image description here

A few notes about the code. string.byte returns the ASCII value of its argument. Color change is done at pdf level with a 'whatits' pdf_literal node (q is a kind of begin group and Q a kind of end group in pdf, rg is the rgb model for non stroking operations).

A final note: my method does not work with inline math.

cjorssen
  • 10,032
  • 4
  • 36
  • 126