34

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.

  • How big is this piece of text? Can you be more precise about your need? – egreg Oct 13 '13 at 21:07
  • 2
    Coloring all vowels is more difficult than just coloring a,e,i,o,u,y. For instance, y is a vowel in "tyre" but not in "hay". – Tim N Oct 14 '13 at 15:37
  • Just want to link these two questions: tex.stackexchange.com/q/120397/17423 – Sean Allred Jul 4 '18 at 17:41
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 255 \vowelsclass = {\bgroup\color{blue}}
\XeTeXinterchartoks \vowelsclass 0 = {\egroup}
\XeTeXinterchartoks \vowelsclass 1 = {\egroup}
\XeTeXinterchartoks \vowelsclass 2 = {\egroup}
\XeTeXinterchartoks \vowelsclass 255 = {\egroup}


\begin{document}

One two three four five six seven eight.

\end{document}
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

  • 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.

  • ...or more precisely works too good, even for inline math :) – cjorssen Oct 4 '16 at 21:25

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.