jueves, 29 de enero de 2015

Pandoc: Plantillas personalizadas de LaTeX para generación de documentos pdf

[Esta entrada es una traducción libre al castellano de la versión original escrita en inglés en este mismo blog.]

Una de las características más interesantes, aunque pocas veces comentada, de Pandoc es la de sus plantillas para LaTeX. Las plantillas de Pandoc nos permiten seguir escribiendo en Markdown, en lugar de volver de nuevo a LaTeX puro, incluso en los casos en que tengamos que producir documentos que no se considerarían "normales". En tales situaciones es posible también aprovecharse de la simplicidad de Markdown y relegar todos los detalles engorrosos a nuestras plantillas, siempre y cuando nuestras plantillas se atengan a la sintaxis y semántica de Pandoc.

Como ejemplo ilustrativo, supongamos que debemos entregar con regularidad actas del día de reuniones en pdf, siguiendo un diseño formal, especializado y con mucho texto repetido de un acta a otra como el que se muestra en la siguiente imagen:

Pandoc no parece ser la mejor herramienta para esta tarea. Trataré de demostrar que, por el contrario, Pandoc es especialmente apropiado para ella.

Plantillas de Pandoc

Como todo usuario de Pandoc sabe, la conversión de Markdown a LaTeX en Pandoc se basa en una plantilla por defecto que viene incluida en la instalación de Pandoc. Si se ejecuta esta orden:
pandoc --standalone --output mi_documento.pdf mi_documento.md

O, con las formas abreviadas de las opciones:

pandoc -s -o mi_documento.pdf mi_documento.md

se está aplicando un plantilla LaTeX por defecto, llamada default.latex, que en mi sistema y versión actual de Pandoc (1.12.2.1) se encuentra en $PANDOC_DIR/data/templates/default.latex. El resultado de aplicar esa plantilla al documento Markdown es un fichero que la máquina LaTeX (actualmente, pdflatex es la máquina por defecto) procesa de forma transparente para producir el pdf final.

Un rápido vistazo a la plantilla por defecto muestra que dicha plantilla no es más que un fichero LaTeX normal y corriente en el que, además, se incluyen, ciertos determinados constructos (variables, condicionales y bucles).

Si queremos usar otra plantilla, en lugar de la plantilla por defecto, ya sea una versión personalizada de dicha plantilla, ya una plantilla que creemos nosotros mismos completamente desde cero, necesitaremos pasar el nombre del fichero que la contiene a la opción --template. Suponiendo que el fichero de entrada y nuestra plantilla están en el mismo directorio, la orden correspondiente sería algo parecido a esto:

pandoc -s --template="mi_plantilla.latex" -o mi_documento.pdf mi_documento.md

Variables en Pandoc

Una variable en Pandoc tiene la siguiente sintaxis:
$nombre-de-variable$

Cuando ejecutamos pandoc cada variable de la plantilla se substituye por su valor. Este valor se puede pasar a Pandoc de distintas formas. Una de ellas, como veremos más adelante, es pasárselo a través de la opción de línea de órdenes -M nombre-de-variable=valor(donde -M es la forma abreviada de --metadata).

Por lo respecta a las variables pre-definidas por Pandoc y que están incluidas en la plantilla por defecto, más información sobre la mayoría de ellas se encuentra en la documentación oficial (http://johnmacfarlane.net/pandoc/README.html#templates).

Para saber en concreto qué variables hay en la plantilla por defecto podemos también utilizar un filtro Unix como el siguiente:

grep -o '\$.*\$' /usr/share/pandoc/data/templates/default.latex \
| grep -v '\$endif\$\|\$else\$\|\$endfor\$'

Es especialmente importante destacar que hay una variable crítica pre-definida, la variable $body$, que toda plantilla debería incluir, puesto que el contenido propiamente tal de nuestro documento de entrada será introducido en su lugar.

Comprobemos esto último. Creemos una platilla LaTeX simple.latex con este contenido:

\documentclass{minimal}
\begin{document}
$body$
\end{document}

y ejecutemos pandoc para que reciba el input de la entrada estándar desde terminal. El resultado de nuestra sesión de prueba es el siguiente:

$ pandoc -s --template="simple.latex" --to latex
Hola
Ctrl+D
\documentclass{minimal}
\begin{document}
Hola
\end{document}

La primera línea es el comando ejecutado. Estoy pidiendo a Pandoc que aplique nuestra plantilla, simple.latex a la entrada que le vamos a pasar y que la convierta a formato LaTeX. Las dos siguientes líneas reproducen lo que he tecleado para que Pandoc lo consuma. Ctrl+D señala EOF (fin de fichero) y cierra la entrada estándar. El resto es la salida que Pandoc produce. Nótese que lo que he tecleado, "Hola", aparece tras el procesamiento, como esperábamos, en el lugar en que estaba $body$ en la plantilla.

Intentemos algo un poco más complicado. Añadamos una variable de nuestra cosecha, que llamaremos $saludo$, a la plantilla:

\documentclass{minimal}
\begin{document}
$saludo$
$body$
\end{document}
y comprobemos qué pasa:
$ pandoc -s -M saludo="Hola gente" --template="simple.latex" --to latex
Esto es Pandoc
Ctrl+D
\documentclass{minimal}
\begin{document}
Hola gente
Esto es Pandoc
\end{document}

La orden es casi idéntica a la de antes. El añadido clave es la opción -M comentada previamente. A diferencia de la variable predefinida $body$, tenemos ahora que pasar los valores de nuestras propias variables a pandoc a través de la opción -M. Como vemos, en la salida, la variable en la plantilla es sustituida por el que valor que hemos dado.

Condicionales

Los condicionales tienen esta sintaxis:
$if(variable)$
X
$else$
Y
$endif$ 

donde la cláusula $else$ es opcional.

Supongamos que nos interesa poder elegir, cuando sea necesario, entre diferentes clases de documentos para el mismo documento de entrada. En concreto, supongamos que queremos crear un documento minimal por defecto, a no ser que pidamos expresamente que el documento sea de otra determinada clase. Podemos conseguirlo a través de este condicional:

$if(mi-clase-doc)$
$mi-clase-doc$
$else$
minimal
$endif$

Hay que tener cuidado con la sintaxis. Cada cláusula (if(), else, endif) va rodeada por el signo $. Las variables que serán remplazadas por sus valores también van entre $. Los valores literales, así como las referencias a la variable en la cláusula if van sin ese signo.

Naturalmente, nuestro condicional debe colocarse en el lugar adecuado en la plantilla, a saber, la instrucción \documentclass:

\documentclass{$if(mi-clase-doc)$
               $mi-clase-doc$
               $else$
               minimal
               $endif$}
Escribir lo anterior en una sola línea quizá sea menos legible, pero también más característico del estilo LaTeX. Pongámosla, pues, así:
\documentclass{$if(mi-clase-doc)$$mi-clase-doc$$else$minimal$endif$}
\begin{document}
$saludo$
$body$
\end{document}

Toca poner a prueba la plantilla:

$ pandoc -s -M saludo="Hola gente" --template="simple.latex" --to latex
Esto debería ser minimal
Ctrl+D
\documentclass{minimal}
\begin{document}
Hola gente
Esto debería ser minimal
\end{document}

¡Funciona!

Probemos ahora la otra posibilidad:

$ pandoc -s -M saludo="Hola gente" -M mi-clase-doc="book" --template="simple.latex" --to latex
Y esto, book
Ctrl+D
\documentclass{book}
\begin{document}
Hola gente
Y esto, book
\end{document}

¡También funciona! Nótese que en esta ocasión hemos establecido el valor de la variable mi-clase-doc a "book" a través de la opción -M, tal como hicimos anteriormente con $saludo$.

Bucles

Los bucles funcionan de una manera semejante. La sintaxis básica de un bucle es la siguiente:
$for(variable)$
X
$sep$separador
$endfor$

La línea $sep$separador es opcional. Sirve para definir un separador entre elementos consecutivos.

Digamos que queremos anotar los participantes a una reunión en la primera línea de nuestro documento. Podemos definir una variable $partipante$ en nuestra plantilla y dejar que Pandoc rellene su contenido. Queremos además que los nombres de los participantes aparezcan separados por una coma. Podríamos hacer todo esto añadiendo lo siguiente a nuestra plantilla:

$for(participante)$
$participante$
$sep$, 
$endfor$

O en una sola línea y en el lugar de la plantilla que corresponde:

\documentclass{$if(mi-clase-doc$$mi-clase-doc$$else$minimal$endif$}

\begin{document}
Participantes: $for(participante)$$participante$$sep$, $endfor$

$saludo$
$body$
\end{document}

Hagamos de nuevo una prueba. Ahora añadiremos a la orden pandoc tantos -M participante=... como participantes queremos incluir.

$ pandoc -s -M saludo="Hola gente" -M participante="W. Shakespeare" -M participante="Edgar A. Poe" --template="simple.latex" --to latex
Menudo plantel
Ctrl+D
\documentclass{minimal}
\begin{document}
Participantes: W. Shakespeare, Edgar A. Poe

Hola gente
Menudo plantel
\end{document}

¡Estupendo! Todo funciona perfecto.

Bloques de meta-datos

Es, como poco, engorroso tener que pasar todas estas cosas a la línea de órdenes. No es obligatorio, por supuesto. Pandoc proporciona para esta tarea los así llamados bloques de meta-datos. Un bloque de meta-datos para nuestro experimento anterior tendría este aspecto:
---
mi-clase-doc: minimal
saludo: Hola gente
participante:
- William Shakespeare
- Edgar A. Poe
---

Este bloque no es más que un fragmento de texto que sigue las especificación YAML (http://yaml.org/spec). Aparte de esto, los bloques YAML que se incluyen en un documento para que Pandoc lo procese deben empezar con una línea de tres guiones y terminar con una línea de tres puntos o tres guiones como se ve en el ejemplo.

Un bloque de meta-datos consta de campos. Cada campo tiene un nombre y un valor asociado a ese nombre, separado del nombre por dos puntos. Algunos campos pueden contener varios valores, los cuales van precedidos por un guion, tal y como aparecen para el campo 'participante' en el ejemplo.

Estos bloques nos permiten pasar a pandoc toda la información requerida sin tener que complicarnos la vida con las opciones en la línea de órdenes. La forma habitual de usar estos bloques es añadirlos al principio de nuestro documento de entrada. Otra forma, en mi opinión mejor, es crear un fichero yaml que pasamos a la vez que el fichero de entrada.

Por ejemplo, si guardamos la entrada de nuestro último experimento (la cadena "Menudo plantel") en un fichero con nombre mi_documento.md y el bloque de meta-datos en un fichero con nombre variables.yaml, podemos llamar a pandoc como sigue para conseguir exactamente la misma salida que obtuvimos antes:

pandoc -s --template="simple.latex" --to latex mi_documento.md variables.yaml

El documento final de la reunión

Nuestra tarea inicial se vuelve realizable gracias a la flexibilidad de Pandoc, que acabamos de explicar. Es cuestión sencillamente de crear un documento LaTeX normal y corriente (nuestra plantilla) con unas pocas variables y un bucle. Todos los detalles complicados y el texto repetitivo se desplaza a la plantilla, mientras que el contenido relevante y propiamente tal puede escribirse como de costumbre y muy convenientemente en Markdown puro.

Como referencia reproduzco todos los ficheros implicados en la creación del documento que mostré al principio de esta entrada. No voy a añadir nada más acerca del LaTeX que he usado, que es, dicho sea de paso, un poco chapucero ;-) En cualquier caso, asumo que los lectores conocen LaTeX lo suficiente.

mi_documento.md

1.  Lorem ipsum dolor sit amet,

    Lorem ipsum dolor sit amet consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore
    magna aliqua.

2.  Ut enim ad minim veniam,

    Ut enim ad minim veniam, quis nostrud exercitation ullamco
    laboris nisi ut aliquip ex ea commodo consequat.

3.  Duis aute irure dolor

    Duis aute irure dolor in reprehenderit in voluptate velit
    esse cillum dolore eu fugiat nulla pariatur.

4.  Excepteur sint occaecat

    Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum

mi_plantilla.latex

\documentclass[a4paper]{extreport}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[spanish]{babel}
\usepackage{marginnote}
\usepackage{background}

\setlength{\parindent}{0pt}

\SetBgScale{1}
\SetBgColor{black}
\SetBgAngle{0}
\SetBgHshift{-0.52\textwidth}
\SetBgVshift{-1mm}
\SetBgContents{\rule{0.4pt}{\textheight}}

\setlength{\marginparwidth}{32mm}
\renewcommand*{\raggedleftmarginnote}{}
\reversemarginpar

\begin{document}
\textbf{Informe}\marginnote{$for(asistente)$$asistente$$sep$\\ $endfor$}

$body$

\section{}
Freedonia, $dia$ de $mes$ de $ano$ 

\section{}
Jefe del Departamento

\vspace{2cm}
\emph{Firma: átopos}
\end{document}

variables.yaml

---
dia: 25
mes: Enero
ano: 2015
asistente:
- William Shakespeare
- Edgar A. Poe
- Miguel de Cervantes
---

La orden de Pandoc que genera el pdf

pandoc -s --template="mi_plantilla.latex" -o mi_documento.pdf mi_documento.md variables.yaml

domingo, 25 de enero de 2015

Pandoc: Customized LaTeX templates for PDF generation

One of the most interesting, however rarely commented, features of Pandoc is its support for LaTeX templates. Pandoc templates allows us to keep writing mostly in Markdown, instead of falling back to LaTeX, even if we have to produce documents that wouldn't be considered as "normal". In those cases we can still take advantage of Markdown simplicity by delegating all the gory-details to our own templates as long as they stick to the Pandoc syntax and semantics.

As an illustration, let us suppose we have to regularly deliver very formalized (with a lot of boilerplate text) but at the same time really specialized (as for design) pdfs of meeting minutes such as the following:

It would seem that Pandoc is not the best option for this task. I'll try to prove that Pandoc might be, on the contrary, particularly suitable.

Pandoc templates

As every Pandoc user knows converting to LaTeX from markdown relies on a default template included in the Pandoc installation. Issuing this command
pandoc --standalone --output my_document.pdf my_document.md

Or, using short options, for brevity

pandoc -s -o my_document.pdf my_document.md

applies a default LaTeX template named default.latex that, on my system and current version (1.12.2.1), can be found at $PANDOC_DIR/data/templates/default.latex. The result of applying the template to the markdown document is a file processed transparently by a LaTeX engine (currently, pdflatex by default) that produces the final pdf output.

A quick inspection into the default template reveals that a Pandoc template is just a normal LaTeX file in which certain specific constructs (variables, conditionals and loops) are included.

To use another template, either a customized version of the default template, or our own template written from scratch, we need to pass its filename to the option --template. Assuming that the template file is in the same directory as the input file the pandoc command would be as follows:

pandoc -s --template="my_template.latex" -o my_document.pdf my_document.md

Pandoc Variables

A variable in Pandoc has the following syntax.
$variable-name$

Every variable in the template will be replaced with its actual value. This value can be passed in different ways. One of them is to pass it via the -M variable-name=value (--metadata is the long name switch) Pandoc command line option, as we will see later.

As for pre-defined variables contained in the default template, you can see more information about most of them in the Pandoc documentation (http://johnmacfarlane.net/pandoc/README.html#templates).

Another useful way to know what variables are actually present in the default template is to extract them with a Unix filter:

grep -o '\$.*\$' /usr/share/pandoc/data/templates/default.latex \
| grep -v '\$endif\$\|\$else\$\|\$endfor\$'

A very important thing to point out is that there is a critical variable, $body$ that should be present in every template. This variable is implicitly replaced with the actual content of our input.

Let's check the latter by creating a minimal LaTeX template simple.latex

\documentclass{minimal}
\begin{document}
$body$
\end{document}

and issuing pandoc to take our input from the terminal [Below is a reproduction of the test]

$ pandoc -s --template="simple.latex" --to latex
Hi
Ctrl+D
\documentclass{minimal}
\begin{document}
Hi
\end{document}

The first line is the command issued. I'm telling Pandoc to apply our own template over whatever input is going to be passed, and convert it to LaTeX. The following lines are what I've actually typed in to be consumed by pandoc, hitting Ctrl+D (in Linux and other Unixes) signals EOF and closes the standard input. The rest is the output produced by pandoc. Note that what I've typed in, "Hi", is now in place of the $body$ variable, as expected.

Let's try something a bit more complicated, adding our own variable, say $greeting$, to our template:

\documentclass{minimal}
\begin{document}
$greeting$
$body$
\end{document}

and test it as before

$ pandoc -s -M greeting="Hi, World" --template="simple.latex" --to latex
This is Pandoc!
Ctrl+D
\documentclass{minimal}
\begin{document}
Hi, World
This is Pandoc!
\end{document}

The command is almost the same. The critical add-on is the -M option referred above. Unlike the variable $body$, the values for our variables need to be passed to pandoc explicitly via the -M option. Again, the variable in the template is replaced with the given value to produce the output.

Conditionals

Conditionals have this syntax:
$if(variable)$
X
$else$
Y
$endif$ 

where the $else$ part is optional.

Let's suppose that we want to be able to choose between different document classes for the same document as needed. In particular, we want to create a minimal document by default, or another document class on demand. We can do this by creating this conditional:

$if(my-doc-class)$
$my-doc-class$
$else$
minimal
$endif$

Be careful about the syntax. Each syntactic part (if(), else, endif) is enclosed in dollar signs. Variables to be replaced by their values are also surrounded by that sign. Literal values, as well as the variable reference in the if section go without them, though. Of course, we have to put this conditional in the suitable place, the LaTeX \documentclass macro:

\documentclass{$if(my-doc-class)$
               $my-doc-class$
               $else$
               minimal
               $endif$}

One-liners maybe less readable but more LaTeX-style aware. So put the corresponding one-liner into the template:

\documentclass{$if(my-doc-class)$$my-doc-class$$else$minimal$endif$}
\begin{document}
$greeting$
$body$
\end{document}
Now, Let's check:
$ pandoc -s -M greeting="Hi, World" --template="simple.latex" --to latex
This should be a minimal
Ctrl+D
\documentclass{minimal}
\begin{document}
Hi, World
This should be a minimal
\end{document}

It works!

Let's try the second use case:

$ pandoc -s -M greeting="Hi, World" -M my-doc-class="book" --template="simple.latex" --to latex
And this one, a book
Ctrl+D
\documentclass{book}
\begin{document}
Hi, World
And this one, a book
\end{document}

It also works! Note that this time the previously defined variable my-doc-class is set to the value "book" by means of the option -M as we did before with $greeting$

Loops

Loops behave in a similar manner. The basic syntax is as follows:
$for(variable)$
X
$sep$separator
$endfor$

The $sep$separator line (for defining a separator between consecutive items) is optional.

Let's say we want to take note of participants in a meeting as the very first line in our document. We can define a variable participant in our template and leave Pandoc to fill its content. We want to separate by commas the names of participants. So we can add this to the template:

$for(participant)$
$participant$
$sep$, 
$endfor$
Or just a one-liner in the corresponding place:
\documentclass{$if(my-doc-class)$$my-doc-class$$else$minimal$endif$}

\begin{document}
Participants: $for(participant)$$participant$$sep$, $endfor$

$greeting$
$body$
\end{document}

Testing again ... Now we add as many -M participant=... options as participants we wish to set.

$ pandoc -s -M greeting="Hi, World" -M participant="W. Shakespeare" -M participant="Edgar A. Poe" --template="simple.latex" --to latex
Good staff!
Ctrl+D
\documentclass{minimal}
\begin{document}
Participants: W. Shakespeare, Edgar A. Poe

Hi, World
Good staff!
\end{document}
Nice. Everything works fine!

Metadata blocks

It's cumbersome, to say the least, being forced to pass all those things to the command line. You aren't, of course. Pandoc provides the so-called metadata blocks for this task. A metadata block for our previous experiments would look like as follows:
---
my-doc-class: minimal
greeting: Hi, World
participant:
- William Shakespeare
- Edgar A. Poe
---

This is just a chunk of text following the YAML specification (http://yaml.org/spec). YAML blocks included in a document to be consumed by pandoc must begin with three hyphens and end with three points or three hyphens.

A metadata block consists of fields. Each field has a name and its associated value separated by semicolon. Some fields can contain multiple values preceded by a hyphen like the participant field in the previous example.

These blocks allow us to pass to pandoc all the required information without bothering with the command line switches. The customary way is to add the block at the beginning of our input document. Another way, even better in my opinion, is to create a yaml file that we pass to pandoc along with our input file.

For instance, if we save the input of our last experiment (the "Good staff!" string) in a file named my_document.md and the metadata block above in a file named variables.yaml, pandoc can be called to produce exactly the same output as the one we obtained before (try it!) as follows:

pandoc -s --template="simple.latex" --to latex my_document.md variables.yaml

The final meeting document

Our initial task becomes feasible due to the explained Pandoc flexibility. It's just a matter of creating a normal LaTeX document (our template) with a bit of variables and loops. All of the gory-details and boilerplate text will be shifted to the template while the actual and relevant content could be written, as usual and conveniently, in pure Markdown.

For reference I reproduce all the files involved in the creation of the document shown at the beginning of this entry. No further comments about LaTeX here, that is a bit quick&dirty, BTW ;-) I'm assuming readers already know LaTeX, anyway.

my_document.md

1.  Lorem ipsum dolor sit amet,

    Lorem ipsum dolor sit amet consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore
    magna aliqua.

2.  Ut enim ad minim veniam,

    Ut enim ad minim veniam, quis nostrud exercitation ullamco
    laboris nisi ut aliquip ex ea commodo consequat.

3.  Duis aute irure dolor

    Duis aute irure dolor in reprehenderit in voluptate velit
    esse cillum dolore eu fugiat nulla pariatur.

4.  Excepteur sint occaecat

    Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum

my_template.latex

\documentclass[a4paper]{extreport}
\usepackage[T1]{fontenc}
\usepackage{marginnote}
\usepackage{background}

\setlength{\parindent}{0pt}

\SetBgScale{1}
\SetBgColor{black}
\SetBgAngle{0}
\SetBgHshift{-0.52\textwidth}
\SetBgVshift{-1mm}
\SetBgContents{\rule{0.4pt}{\textheight}}

\setlength{\marginparwidth}{32mm}
\renewcommand*{\raggedleftmarginnote}{}
\reversemarginpar

\begin{document}
\textbf{Report}\marginnote{$for(attendee)$$attendee$$sep$\\ $endfor$}

$body$

\section{}
Freedonia, $month$ $day$, $year$ 

\section{}
Chief of Departament

\vspace{2cm}
\emph{Signature: atopos}
\end{document}

variables.yaml

---
day: 25
month: January
year: 2015
attendee:
- William Shakespeare
- Edgar A. Poe
- Miguel de Cervantes
---

The Pandoc command to generate the pdf

pandoc -s --template="my_template.latex" -o my_document.pdf my_document.md variables.yaml

[Spanish translation on the way...]

domingo, 11 de enero de 2015

Typesetting code with latex and minted. A real-world example.

More than 4 years without writing a word in this blog :(

What if I blend the trend right now? What about something on (what else!) LaTeX?

I was trying to reread some pages from the K&R's C book taking notes along the way for my own use, and I wondered what LaTeX has to offer nowadays beyond the venerable listings package.

And I've found out minted

listings and minted user interfaces are similar. So the transition from one to the other is most of the time seamless. Anyway, both interfaces are clean and easy to use. Though listings may be more flexible, minted has an advantage for lazy users like me: no need to create custom syntax highlighting styles since, thanks to the Python Pygments library integration provided by minted, we can get state of the art and wonderful highlighting niceties automatically!

The only requirement (of course) is to have Python installed as well as the Pygments library. That's probably the case if you are using a modern Linux (MacOSX?) distro. For Windows users you may need to consult minted package documentation (particularly, section 2.4).

If Pygments is not already installed (I assume Python is installed, it will be on almost all modern Unixes):

pip install Pygments

should do the job.

This is what I get (just a draft):

Nice, isn't it? The LaTeX I've used is as follows.

The preamble is self-explanatory:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{minted}  % The expected way to load minted macros
The C code for this file comes from the same single file strlen2.c. It's natural to search for a way to input text from files directly instead of writing it over and over. The \inputminted command provides the desirable support:
\begin{document}
...
\inputminted[linenos]{c}{strlen2.c}
In general, the \inputminted macro expects an optional set of key-value pairs (some options will be explained later) and two mandatory arguments: the programming language in which the code is written, C in my case, and the name of the file containing the actual code.
\inputminted[<options>]{<language>}{<filename>}
Interestingly, there is no need to rewrite code fragments, a really boring and error-prone task. We can select lines in the file on demand. For listings users this is a piece of cake, both packages provide practically the same keywords for options related to inputting code fragments. For the text at hand:
  • firstline=<number>
  • lastline=<number>
These options are self-explanatory. They select lines of interest from the first one to the last one, both included. To display line numbers we have the option:
  • linenos=true
Or, simpler, as every LaTeX user knows:
  • linenos
I want to print the actual C code line numbers as they appear in the source. By default the line-number counter is reset to 1 for any code fragment, though. Therefore, I also have to provide the actual initial line number for each chunk:
  • firstnumber=<number>
Finally, a colored frame background might make things more readable and beautiful:
  • background=<color>
I've defined a color for this purpose in the preamble:
\definecolor{bg}{rgb}{0.95,0.95,0.95}
and refer to it as the value for background to obtain the final macro. Thus, the LaTeX code for the third C code fragment above would look like this:
\inputminted[background=bg,linenos,firstnumber=6,firstline=6,lastline=7]{c}{strlen2.c}
Copy&pasting such a huge macro is awful. As usual, laziness can be our best friend. This is a suitable place for putting a familiar macro shorthand in the preamble:
\newcommand{\Cfrag}[3]{%
\inputminted[%
  bgcolor=bg,
  linenos,
  firstnumber=#1,
  firstline=#1,
  lastline=#2
]{c}{#3}}
This way each chunk of code can be included with a more friendly macro. For instance:
\Cfrag{6}{7}{strlen2.c}
All in all, the final LaTeX file looks as follows:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{minted}

\definecolor{bg}{rgb}{0.95,0.95,0.95}
\newcommand{\Code}[1]{\texttt{#1}}
\renewcommand{\labelitemi}{\color{red!50!black}\guilsinglright}

\newcommand{\Cfrag}[3]{%
\inputminted[%
  bgcolor=bg,
  linenos,
  firstnumber=#1,
  firstline=#1,
  lastline=#2
]{c}{#3}}

\begin{document}
\section{The \Code{strlen} function}
\inputminted[linenos]{c}{strlen2.c}

\section{Commentary}
\Cfrag{1}{2}{strlen2.c}

\begin{itemize}
...
\end{itemize}

\Cfrag{4}{4}{strlen2.c}

\begin{itemize}
...
\end{itemize}

\Cfrag{6}{7}{strlen2.c}

\begin{itemize}
...
\end{itemize}

\Cfrag{8}{8}{strlen2.c}

\begin{itemize}
...
\end{itemize}
\end{document}
And a last one important thing. You need to pass the option -shell-escape to pdflatex in order to get a pdf from a latex file containing minted macros. Something like this:
pdflatex -shell-escape strlen_commentary.tex