# Importing text file into Latex by character

So I want to import a text file into latex character by character and format the individual characters by changing their color. So for instance, 'a' would be the color blue, 'b' would be red etc.

How should I go about importing the file? Should I make a database?

The input file is a simple text file extracted from fiction ebooks. I don't care much about the original formatting since the text file will be extracted from pdf or epub. So no equations and no special characters other than the one used in everyday english(. , ! ?).

So the input would probably be like:

"As an instance of what I mean, I remember meeting Monty Byng in Bond Street one morning, looking the last word in a grey check suit, and I felt I should never be happy till I had one like it."

• Welcome to TeX.SX! Can you improve your question with some examples? – egreg Feb 10 '15 at 10:15
• I'm actually new to latex. I'm learning latex in order to solve this problem of mine. That of reformatting normal text files so that letters are of different colors. So I assumed latex would be the way to go about this. The documentation of 'datatool' has left me a little overwhelmed and I needed a jumping off point with respect to what exactly I should use to import the text file into latex. – codemonkeyyy Feb 10 '15 at 10:19
• @codemonkeyyy datatool is for maniuplating databases: if we are talking free-form text there are alternative approaches. What deterimines the colour applicable to each letter? – Joseph Wright Feb 10 '15 at 10:34
• @JosephWright The colors are predetermined. So all 'a's would be one color, 'b's another color. So I'll have a number of conditions for each character I import. Or on parsing each row I import. What do you think the best approach would be? – codemonkeyyy Feb 10 '15 at 10:41
• Have a look at the chickenize package and use LuaTeX. – Martin Schröder Feb 10 '15 at 13:02

For each letter used, let's say "x", there can be a corresponding macro \xxx with its color defined. This can be done with punctuation marks, for example exclamation points, via \expandafter\def\csname!!!\endcsname{...}.

The text is passed by way of macro \colorize.

EDITED for getting data from a file.

EDITED for using triple letters \lll as colorizing name, lest things like \ll confuse the algorithm.

EDITED so that non defined colorizing macros are presented in black.

Added an ADDENDUM (see bottom of this answer) to allow for an escape character to give primitive formatting ability within the \colorize macro argument.

The file sample.tex contains this data

cba def abc!

Here is my next pair of graphs!!!


Here is the file that reads and parses it.

\documentclass{article}
\usepackage{xcolor}
\newcommand\colorize[1]{\expandafter\colorizepars#1\par\relax\relax}
\long\def\colorizepars#1\par#2\relax{%
\ifx#1\relax\else
\colorizewords#1 \relax\relax%
\fi%
\ifx\relax#2\else\par\colorizepars#2\relax\fi%
}
\def\colorizewords#1 #2\relax{%
\ifx#1\relax\else
\colorizeletters#1\relax\relax%
\fi%
\ifx\relax#2\else\ \colorizewords#2\relax\fi%
}
\makeatletter
\def\colorizeletters#1#2\relax{%
\@ifundefined{#1#1#1}{#1}{\csname#1#1#1\endcsname}%
\ifx\relax#2\else\colorizeletters#2\relax\fi}
\makeatother

\def\aaa{\textcolor{red}{a}}
\def\bbb{\textcolor{blue}{b}}
\def\ccc{\textcolor{green}{c}}
\def\ddd{\textcolor{cyan}{d}}
\def\eee{\textcolor{red!40}{e}}
\def\fff{\textcolor{blue!40}{f}}
\def\ggg{\textcolor{red!30!blue}{g}}
\def\hhh{\textcolor{green!40}{h}}
\def\nnn{\textcolor{yellow!40!green}{n}}
\def\ppp{\textcolor{orange}{p}}
\def\rrr{\textcolor{blue!30}{r}}
\def\ttt{\textcolor{green!40!blue}{t}}
\def\xxx{\textcolor{black!50}{x}}
\expandafter\def\csname!!!\endcsname{\textcolor{yellow}{!}}

\def\colorizeentry#1{\edef\tmp{\arrayij{mydata}{#1}{1}}\colorize{\tmp}}

\begin{document}
\colorize{%
abc def!

next paragraph Undefined letters are black.
}

Here is a way to get it from a file, if paragraphs are not needed

\colorize{\x}

If paragraphs are needed, you can place each paragraph in its own single row
of the input file and parse line by line.

\copyrecords{mydata}% USES DATA FROM MOST RECENT \readdef; ASSIGNS ROWS TO "mydata"
\colorizeentry{1}

\colorizeentry{2}

\colorizeentry{3}
\end{document}


ZOOM IN

ZOOM OUT

If you needed some primitive formatting ability in the colorized text, you could build in an escape character (here the [) as such:

\makeatletter
\def\colorizeletters#1#2#3\relax{%
\ifx [#1\EscapeChar{#2}%
\ifx\relax#3\else\colorizeletters#3\relax\fi%
\else%
\@ifundefined{#1#1#1}{#1}{\csname#1#1#1\endcsname}%
\ifx\relax#2\else\colorizeletters#2#3\relax\relax\fi%
\fi%
}
\makeatother
\def\EscapeChar#1{%
\if 0#1\relax \textcolor{blue}{[}\else%
\if 1#1\relax \bfseries\else%
\if 2#1\relax \mdseries\else%
\if 3#1\relax \itshape\else%
\if 4#1\relax \upshape\else%
\fi\fi\fi\fi\fi%
}


Then, the following code

\colorize{%
abc def!

next [1paragraph[2 [0Undefined] [3letters[4 are black.
}


would display as

• Looks awesome. This means I don't need to go the database route at all. It'll take me a little time to understand it fully though. – codemonkeyyy Feb 10 '15 at 12:00
• @codemonkeyyy Please see my revision. I fixed a bug that broke the code on repeated letters. I also added a means to extract data from a file. – Steven B. Segletes Feb 10 '15 at 12:18
• @codemonkeyyy I have revised it so that non-defined sequences are presented in black. I now also use three letters \aaa, for example, since there exist repeated two letter sequences like \ll. – Steven B. Segletes Feb 10 '15 at 12:36
• @codemonkeyyy I have provided an addendum to allow for an "escape character [ that can be used to provide for primitive forms of text formatting. – Steven B. Segletes Feb 10 '15 at 14:24
• there are actually two three-letter commands defined in a fairly commonly-used package, amssymb: \lll (much less than) and \ggg (much greater than). but if the text in question contains no math, that package probably won't be loaded. – barbara beeton Feb 10 '15 at 15:55

With lualatex you could do something along the line of the chickenize package:

\documentclass{article}
\usepackage{fontspec,luacode}
\usepackage{luatexbase}
\begin{luacode}
-- stolen from chickenize
local nodenew = node.new
local nodecopy = node.copy
local nodetail = node.tail
local nodeinsertbefore = node.insert_before
local nodeinsertafter = node.insert_after
local noderemove = node.remove
local nodeid = node.id
local nodetraverseid = node.traverse_id
local nodeslide = node.slide

RULE = nodeid("rule")
GLUE = nodeid("glue")
WHAT = nodeid("whatsit")
COL = node.subtype("pdf_colorstack")
GLYPH = nodeid("glyph")
color_push = nodenew(WHAT,COL)
color_pop = nodenew(WHAT,COL)
color_push.stack = 0
color_pop.stack = 0
color_push.command = 1
color_pop.command = 2

mycolors={}
mycolors[97]="1 0 0" --a
mycolors[98]="0 1 0" --b
mycolors[99]="0 0 1" --c
mycolors[100]="0 1 1" --d

if mycolors[i.char] then
color_push.data = mycolors[i.char].." rg"
else
color_push.data = "0.5 0.5 0.5 rg"  -- gray for undefined
end
end
end
end

\end{luacode}

\def\colortext{
\def\uncolortext{
\directlua{luatexbase.remove_from_callback("post_linebreak_filter","colortext")}}

\newcommand\mytext{abcde}
\begin{document}
\colortext abcdefgabc \section{abcxse}  \mytext

\uncolortext abcdefgabc
\end{document}


Which gives something like this. (I don't know why the number of the section is black).

An expl3 version. The input (that can be from a file) is split into words and each word is split into letters that are colorized according to a table that can be easily augmented.

Limitations: only ASCII characters are allowed (unless you use XeLaTeX or LuaLaTeX and augment the table according to your wishes).

\begin{filecontents*}{filetocolorize.tex}
This file will be input.

Its words will be colorized.
\end{filecontents*}

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\colorize}{+m}
{
\codemonkey_colorize:n { #1 }
}

\NewDocumentCommand{\colorizeinput}{m}
{
\tl_set_from_file:Nnn \l_codemonkey_colorize_input_tl { } { #1 }
\codemonkey_colorize:V \l_codemonkey_colorize_input_tl
}

\tl_new:N \l_codemonkey_colorize_input_tl
\seq_new:N \l_codemonkey_colorize_words_seq

\cs_new_protected:Npn \codemonkey_colorize:n #1
{
\seq_set_split:Nnn \l_codemonkey_colorize_words_seq { ~ } { #1 }
\seq_map_inline:Nn \l_codemonkey_colorize_words_seq
{
\tl_map_inline:nn { ##1 } { \codemonkey_colorize_letter:n { ####1 } }
\c_space_tl
}
\unskip % remove the last added space
}

\cs_generate_variant:Nn \codemonkey_colorize:n { V }

\cs_new_protected:Npn \codemonkey_colorize_letter:n #1
{
\str_case:nnF { #1 }
{
{a}{\textcolor{red}{a}}
{b}{\textcolor{blue}{b}}
{c}{\textcolor{green}{c}}
{d}{\textcolor{cyan}{d}}
{e}{\textcolor{red!40}{e}}
{f}{\textcolor{blue!40}{f}}
{g}{\textcolor{red!30!blue}{g}}
{h}{\textcolor{green!40}{h}}
{n}{\textcolor{yellow!40!green}{n}}
{p}{\textcolor{orange}{p}}
{r}{\textcolor{blue!30}{r}}
{t}{\textcolor{green!40!blue}{t}}
{x}{\textcolor{black!50}{x}}
{!}{\textcolor{yellow}{!}}
}
{ % none of the above
#1
}
}
\ExplSyntaxOff

\begin{document}

\colorize{abc def!

next paragraph Undefined letters are black.}

Here is a way to get it from a file

\colorizeinput{filetocolorize}

\end{document}