6

I was wondering if it was possible to color every second letter in a text string in LaTeX. I'm writing a report on decrypting a Vigenere cipher, and have a text string that I would like to have every alternate letter be colored differently.

So for example the string might be 'abcdefg', and I would like the output to show 'aceg' in blue and 'bdf' in red, or something like that. Is this easily feasible in LaTeX?

Thank you guys!

7
  • 2
    Did you mean automatically? The simple-but-tedious way with color package is just to do \textcolor{red}{a}\textcolor{blue}{b} etc
    – Thruston
    Jan 4, 2016 at 18:35
  • 1
    Did you mean to use the luatex tag? Are you looking for a lua solution?
    – Thruston
    Jan 4, 2016 at 18:37
  • And while I'm at it... Welcome to TeX.SX! You can have a look at our starter guide to familiarize yourself further with our format.
    – Thruston
    Jan 4, 2016 at 18:39
  • @Thruston Yes -- I advised OP to post this question here. It was originally posted on reddit where there are far fewer LuaTeX users. Jan 4, 2016 at 19:34
  • In ciphertext spaces are usually ignored. Is this your case?
    – egreg
    Jan 4, 2016 at 23:30

3 Answers 3

8

Here's an expl3 version for alternating colours, but not for strings with whitespace (so far)

\documentclass{article}
\usepackage{xparse}

\usepackage[x11names]{xcolor}
\ExplSyntaxOn
\newcommand{\colorstring}[3]{% 
  \str_set:Nn \l_tmpa_str {#3}% store the string to a string variable
  % Now loop through the string variable and get each 'letter' 
  \int_step_inline:nnnn {1} {1} {\str_count:N \l_tmpa_str } {%
    \int_if_odd:nTF{##1}{% Is the number odd → use the first colour
      \textcolor{#1}{\str_item:Nn \l_tmpa_str {##1}}
    }{% No, use the 2nd colour
      \textcolor{#2}{\str_item:Nn \l_tmpa_str {##1}}
    }%
  }%
}
\ExplSyntaxOff

\begin{document}

\bfseries
\huge \colorstring{blue}{red}{abcdefgh}


\huge \colorstring{brown}{Green4}{ABCEDEFGH}

\end{document}

enter image description here

Another version, with alternating colours

... and providing more than two colours, as well as using in an environment. However, no empty lines are allowed! No real tests on printable characters are done so far.

\documentclass{article}
\usepackage{xparse}
\usepackage{environ}

\usepackage[x11names]{xcolor}
\ExplSyntaxOn

\NewDocumentCommand{\colorstring}{O{blue,red}+m}{%
  \clist_set:Nn \l_tmpa_clist {#1}%
  \int_zero:N \l_tmpa_int%
  \str_set:Nx \l_tmpa_str {#2}%
  \int_step_inline:nnnn {1} {1} {\str_count:N \l_tmpa_str } {%
    \str_case_x:nnF {\str_item:Nn \l_tmpa_str {##1}} {%
      {\space}{\space}
    }{%
      \int_compare:nNnTF {\l_tmpa_int } < {\clist_count:N \l_tmpa_clist } {
        \int_incr:N \l_tmpa_int
      }{%
        \int_set:Nn \l_tmpa_int {\c_one}
      }
      \textcolor{\clist_item:Nn \l_tmpa_clist {\l_tmpa_int }}{\str_item:Nn \l_tmpa_str {##1}}
    }
  }
}



\ExplSyntaxOff

\NewEnviron{ColorLettersInternal}[1]{\colorstring[#1]{\BODY}} % Internal environment for `\Body`

\NewDocumentEnvironment{ColorLetters}{O{blue,red}}{%
  \ttfamily%
  \ColorLettersInternal{#1}%
}{%
  \endColorLettersInternal%
}


\parindent=0pt
\begin{document}


\bfseries
\huge \colorstring{abcdefgh}
\huge \colorstring[brown,Green4,Aquamarine4]{ABCEDEFGH}

\colorstringnew[violet,Green4,Red4,Blue2]{TCGATGGAGGGACCAT}

\begin{ColorLetters}[Blue4,Red4,Green4,LightBlue4]
And now for something completely different
Number Three -- the Larch!
\end{ColorLetters}

\end{document}

enter image description here

11
  • Could this be adaptable to use as an environment? Jan 4, 2016 at 19:46
  • And couldn't you use \exp_args: to say \textcolor{\int_if_odd: ...}? Jan 4, 2016 at 19:47
  • @SeanAllred: I am still new to expl3 .... thanks for any suggestion. About the environment: Well, I must grab the environment body then, I assume?
    – user31729
    Jan 4, 2016 at 20:22
  • This works with color I guess, as well as xcolor.
    – Thruston
    Jan 4, 2016 at 21:03
  • @Thruston: Of course, but the colornames may be different (I am not sure color provides the x11names` etc. color names sets)
    – user31729
    Jan 4, 2016 at 21:09
5

Here, I use a simple recursion, until the end of the string is reached.

\documentclass{article}
\usepackage{xcolor}
\newcommand\colorstring[3]{\def\colorA{#1}\def\colorB{#2}\colorstringhelp#3%
  \relax\relax\relax}
\def\colorstringhelp#1#2#3\relax{\textcolor{\colorA}{#1}\textcolor{\colorB}{#2}%
  \ifx\relax#3\else\colorstringhelp#3\relax\relax\fi}
\begin{document}%
\colorstring{blue}{red}{abcdef}\par
\colorstring{green}{orange}{abcdefg}
\end{document}

enter image description here

2

Since ciphertext is usually typeset without spaces, doing a mapping on the input is simple (and automatically gobbles spaces). With environ we can define an environment that collects its body.

\documentclass{article}
\usepackage{xparse}
\usepackage{environ}

\usepackage[x11names]{xcolor}

\ExplSyntaxOn

\seq_new:N \l_kaddon_colors_seq
\int_new:N \l_kaddon_color_int

\cs_new_protected:Nn \kaddon_color_string:nn
 {
  \seq_set_from_clist:Nn \l_kaddon_colors_seq { #1 }
  \int_zero:N \l_kaddon_color_int
  \tl_map_inline:nn { #2 } { \kaddon_color:n { ##1 } }
 }
\cs_generate_variant:Nn \kaddon_color_string:nn { nV }

\cs_new_protected:Nn \kaddon_color:n
 {
  \int_incr:N \l_kaddon_color_int
  \int_compare:nT { \l_kaddon_color_int > \seq_count:N \l_kaddon_colors_seq }
   { % exhausted colors, restart
    \int_set:Nn \l_kaddon_color_int { 1 }
   }
  \str_if_eq:nnTF { #1 } { \par }
   {
    \int_decr:N \l_kaddon_color_int
    \par
   }
   {
    \textcolor{\seq_item:Nn \l_kaddon_colors_seq { \l_kaddon_color_int } } { #1 }
    \hspace{0pt plus 0.1pt }
   }
 }

\NewDocumentCommand{\colorstring}{ O{red,blue} m }
 {
  \kaddon_color_string:nn { #1 } { #2 }
  \unskip % remove the last \hspace
 }

\NewEnviron{colorpar}[1][red,blue]
 {
  \begin{quote}
  \kaddon_color_string:nV { #1 } \BODY
  \end{quote}
 }
\ExplSyntaxOff

\begin{document}

\colorstring{abcdefgh}

\colorstring[red,red,blue]{abcd efgh}

\colorstring[brown,Green4,Aquamarine4]{ABCEDEFGH abcdef}

\begin{colorpar}[Blue4,Red4,Green4,LightBlue4]
And now for something completely different
And now for something completely different
And now for something completely different
And now for something completely different
\end{colorpar}

\begin{colorpar}
And now for something completely different
And now for something completely different

And now for something completely different
And now for something completely different
\end{colorpar}

\end{document}

enter image description here

You must log in to answer this question.

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