I have an external input file which I am reading line by line. This file contains text as well as some tex/latex macros. My goal is to write the content of this file into another external output file, and I would like to be able to replace some of the latex commands by symbols (to be more specific: I would like to be able to translate simple latex commands into their corresponding markdown counterpart).
So far, it works well for simple commands, eg \textbf{bold} is translated into bold. I have achieved this by redefining \textbf before writing back to the output file (I am using \write for this):
\def\textbf#1{*#1*}
Now I would like to be able to do the same for itemize. I would like the following code:
\begin{itemize}
\item one
\item two
\item three
\end{itemize}
to be translated into:
* one
* two
* three
A first idea would be to ignore \begin{itemize} and \end{itemize} and simply redefine \item so that is expands into the markdown itemize prefix.
However, I want to be able to handle nested itemize. I have been using the same method (redefining \begin and \end, which in turn will use a modified \itemize and \enditemize), keeping track of the nesting level and increasing the markdown prefix accordingly. As you can imagine, things went wrong: since there is a lot of \def, \if, \begingroup etc. involved in the process, what I get at the end in my output file is a sequence of latex code, mainly containing \def's, braces, and so on.
This brings me to my question: before I send a line containing both text and "procedural latex code" (eg \def, \if and so on) to \write, is there a way to "execute" the procedural code it contains, and then write the output to the external file?
I have been using all the tricks I know (\edef, \expandafter's, \romannumeral, ...) to force the expansion, with no success so far.
This is a very minimal example to illustrate what I am trying to achieve:
\documentclass{minimal}
\usepackage{filecontents}
\begin{filecontents*}{temp.tex}
This is \textbf{bold}
This is itemize:
\begin{itemize}
\item one
\item two
\item three
\end{itemize}
\end{filecontents*}
\newread\filein
\newwrite\fileout
\def\markdownbf#1{**#1**}
\def\markdownbegin#1{\csname markdown#1\endcsname}
\def\markdownend#1{\csname markdownend#1\endcsname}
\def\markdownitemize{\edef\markdownprefix{* }}
\def\markdownenditemize{}
\def\markdownitem{}
\def\markdownpar{}
\def\activatemarkdowncommands{%
\let\textbf=\markdownbf%
\let\begin=\markdownbegin%
\let\end=\markdownend%
\let\itemize=\markdownitemize%
\let\enditemize=\markdownenditemize%
\let\item=\markdownitem%
\let\par=\markdownpar%
}
\def\translatefileA{%
\begingroup%
\edef\markdownprefix{}%
\activatemarkdowncommands%
\immediate\openin\filein temp.tex%
\immediate\openout\fileout out.txt%
\loop\unless\ifeof\filein%
\immediate\read\filein to\fileline%
\immediate\write\fileout{\markdownprefix\fileline}%
\repeat%
\immediate\closeout\fileout%
\immediate\closein\filein%
\endgroup%
}
\def\premarkdownbf#1{}
\def\premarkdownbegin#1{\csname premarkdown#1\endcsname}
\def\premarkdownend#1{\csname premarkdownend#1\endcsname}
\def\premarkdownitemize{\edef\storemarkdownprefix{* }}
\def\premarkdownenditemize{\edef\markdownprefix{}}
\def\premarkdownitem{\let\markdownprefix\storemarkdownprefix}
\def\premarkdownpar{}
\def\postmarkdownbf#1{**#1**}
\def\postmarkdownbegin#1{\csname postmarkdown#1\endcsname}
\def\postmarkdownend#1{\csname postmarkdownend#1\endcsname}
\def\postmarkdownitemize{}
\def\postmarkdownenditemize{}
\def\postmarkdownitem{}
\def\postmarkdownpar{}
\def\activatepremarkdowncommands{%
\let\textbf=\premarkdownbf%
\let\begin=\premarkdownbegin%
\let\end=\premarkdownend%
\let\itemize=\premarkdownitemize%
\let\enditemize=\premarkdownenditemize%
\let\item=\premarkdownitem%
\let\par=\premarkdownpar%
}
\def\activatepostmarkdowncommands{%
\let\textbf=\postmarkdownbf%
\let\begin=\postmarkdownbegin%
\let\end=\postmarkdownend%
\let\itemize=\postmarkdownitemize%
\let\enditemize=\postmarkdownenditemize%
\let\item=\postmarkdownitem%
\let\par=\postmarkdownpar%
}
\def\translatefileB{%
\begingroup%
\edef\markdownprefix{}%
\immediate\openin\filein temp.tex%
\immediate\openout\fileout out.txt%
\loop\unless\ifeof\filein%
\immediate\read\filein to\fileline%
\activatepremarkdowncommands%
{\nullfont\fileline}%
\activatepostmarkdowncommands%
\immediate\write\fileout{\markdownprefix\fileline}%
\repeat%
\immediate\closeout\fileout%
\immediate\closein\filein%
\endgroup%
}
\begin{document}
\translatefileB
\end{document}
If I use \translatefileA
, then I get in out.txt
:
This is **bold**
This is itemize:
\edef {* }
one
two
three
If I use \translatefileB
, then I get:
This is **bold**
This is itemize:
* one
* two
* three
The first version is wrong because \markdownprefix
is not set as it should, because \markdown\itemize
is not expanded as intended I guess.
The second version is ok. Unwanted output in the PDF file is deleted using \nullfont. So far it seems the best solution I could come up with.
\textbf
, and what you want to work? Then we don't have to redo all of that :)\write
. If the code is\zzzz
which has been defined by\newcommand\zzzz{hello}
you can of course writehello
(that will happen by default) but if it is\hbox{hello}
what do you want to\write
\hbox
,{
and}
are all non expandable primitives