Adentrándose en Unix


Como colorear código con Pygments

Posted in Documentación,WikiUnix por Noelia en 10 enero 2010
Tags: , ,
El tutorial en sí empieza varios párrafos más abajo: al que no le interese mi vida que pase de este rollo hasta la siguiente sección.
{{Contando mi vida|
Una de mis ideas felices fue colorear el código en LaTeX. Había tenido experiencia con diversos paquetes para introducir código e incluso colorearlo: véase verbatim, fancyverbatim o listings. La verdad no funcionan mal, pero son un poco churros (el resultado siempre es mejorable en estos casos). De los tres el único que se salvaba era listings.
Pero como mi proyecto es especial (es genial poder decir que tu proyecto es especial, hasta que te encuentras con los problemas que esto causa ¬¬) me he encontrado con varios problemillas:
  • El código que tengo que mostrar es Python y en formato wiki. Python lógicamente no da ningún problema, pero para formato wiki no hay grandes ayudas.
  • Además el código en formato wiki no es en inglés, porque precisamente lo bueno de mi proyecto es que es en el mismo idioma que los usuarios que lo van a usar. Este es el problema más serio. Y, ¿por qué? Pues porque el paquete listings que era el bueno de los 3 que comentaba antes casca al primer acento que pille. Hay una forma para que funcione con acentos, con otro pequeñito detalle tonto de nada: solo sigue funcionando cuando los acentos se encuentran entre comentarios. Pues tampoco me vale…
En este momento llegó la inspiración por parte de mi compañero Pablo del proyecto “Resistencia en Cádiz: 1812“: “¿Y por qué no pygments?”.
Después de un par de horas con dolor de cabeza y poco inspirada estaba por darme por vencida y no colorear nada porque no conseguía absolutamente nada. La opción que escogí fue irme a dormir e intentarlo al día siguiente, porque hasta el único apoyo que tenía (Pablo) estaba a puntito de matarme por bruta y cansina.
Primer consejo del día: “Niños, no os emburréis intentando hacer algo cuando no hay ganas y sabéis que no va a salir: id a dormir e intentadlo al día siguiente” (esto no sirve si la práctica hay que entregarla esa misma noche, señores).
Al día siguiente la cosa fue mejor, llegando a conseguir que funcionara medianamente bien. Pero, había un pequeñito problema con el makefile (pygments + makefile = dolor). No había forma de que desde el makefile se pudiera ejecutar pygmentize con varios ficheros contenidos en una variable.
Solución de Pablo: “¿Y por qué no un script en Python que haga…?” – “¿Eso no es más trabajo? ¬¬”. La respuesta a mi pregunta la pude responder yo misma 3 horas más tarde: “NO, no es más trabajo”. Si algo que es doloroso se puede hacer con Python, hazlo xD (no es norma general, pero casi; a mí casi siempre me ha salvado la vida en casos así).
Total, que después de un problema tras otro, os dejo las 2 formas de utilizar pygments, una desde el makefile y otra con el script que hemos desarrollado Pablo y yo (que quede claro que la culpa de todo esto es suya xDD – gracias).
}}

Trabajando con pygments desde la terminal

Antes de nada, para los que no sepan qué es pygments, una definición simple es que es un coloreador de código. Una definición algo más enrevesada sería que es un “resaltador” genérico de sintaxis para el empleo general en todas las clases de software como sistemas de foro, wikis u otros usos que tienen que decorar el código original.
Para utilizarlo, lo primero que necesitas es instalar el siguiente paquete:
sudo apt-get install python-pygments
Si tecleas pygmentize -h puedes ver cómo se utiliza:
Usage: /usr/bin/pygmentize [-l <lexer> | -g]
[-F <filter>[:<options>]] [-f <formatter>][-O <options>]
[-P <option=value>] [-o <outfile>] [<infile>][-P <option=value>]

/usr/bin/pygmentize -S <style> -f <formatter> [-a <arg>] [-O <options>]
/usr/bin/pygmentize -L [<which> ...]
/usr/bin/pygmentize -N <filename>
/usr/bin/pygmentize -H <type> <name>
Así visto resulta un pelín complejo, así que lo voy a explicar lo mejor que pueda. La llamada habitual puede ser tal que:
pygmentize -f latex -O <opciones> -l <lexer> -o <fichero_salida> <fichero_entrada>
donde:
  • opciones: suele ser útil la opción “linenos” que genera la salida con los números de línea incluídos y la opción “full” si prefieres generar un documento LaTeX compilable (aunque seguramente te de problemas también a menos que utilices un makefile).
  • lexer: es el lenguaje o formato en el que está escrito el fichero de entrada. Aquí (http://pygments.org/docs/lexers/) puedes encontrar todos los que están soportados actualmente.
  • fichero_salida: es el .tex que quieres generar
  • fichero_entrada: es el código original
Para poder incluir los .tex generados en tu documento actual necesitas los paquetes fancyvrb y color:

\usepackage{fancyvrb}
\usepackage{color}

Además es necesario generar un documento compilable para copiar las funciones que genera pygments para colorear el código:
pygmentize -f latex -O full,style=friendly -l <lexer> -o <fichero_salida> <fichero_entrada>
El estilo que pongas modifica cómo estarán definicadas las funciones de coloreado. Siempre son las mismas así que las puedes modificar a tu antojo. Si no tienes ganas de definirte un nuevo estilo puedes trastear los que ya existen, entre ellos: friendly, emacs, colorful, native, trac
O bien, si te sientes flojo, aquí tienes las funciones tal y como las tengo definidas yo (son una variación personal del estilo murphy, porque no me gustaba eso de darle color de fondo solo a las cadenas, aunque lo mismo vuelvo a cambiar el estilo):

\newcommand\PYZat{@}
\newcommand\PYZlb{[}
\newcommand\PYZrb{]}
\newcommand\PYbh[1]{\textcolor[rgb]{0.13,0.50,0.56}{\textbf{#1}}}
\newcommand\PYbg[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYbf[1]{\textcolor[rgb]{0.94,0.00,0.00}{\textbf{#1}}}
\newcommand\PYbe[1]{\textcolor[rgb]{0.19,0.19,0.19}{#1}}
\newcommand\PYbd[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYbc[1]{\textcolor[rgb]{0.45,0.16,0.31}{\textbf{#1}}}
\newcommand\PYbb[1]{\textcolor[rgb]{0.00,0.00,0.50}{\textbf{#1}}}
\newcommand\PYba[1]{\textcolor[rgb]{0.00,0.44,0.00}{#1}}
\newcommand\PYaJ[1]{\textcolor[rgb]{0.38,0.38,0.94}{\textbf{#1}}}
\newcommand\PYaK[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYaH[1]{\textcolor[rgb]{0.50,0.00,0.50}{\textbf{#1}}}
\newcommand\PYaI[1]{\textcolor[rgb]{0.94,0.63,0.63}{\textbf{#1}}}
\newcommand\PYaN[1]{\textcolor[rgb]{0.73,0.73,0.73}{#1}}
\newcommand\PYaO[1]{\textcolor[rgb]{0.31,0.44,0.56}{#1}}
\newcommand\PYaL[1]{\textcolor[rgb]{0.31,0.88,0.82}{\textbf{#1}}}
\newcommand\PYaM[1]{\textcolor[rgb]{0.75,0.00,0.00}{\textit{\textbf{#1}}}}
\newcommand\PYaB[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYaC[1]{\textcolor[rgb]{0.31,0.31,0.31}{\textbf{#1}}}
\newcommand\PYaA[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
\newcommand\PYaF[1]{\textcolor[rgb]{0.63,0.00,0.00}{#1}}
\newcommand\PYaG[1]{\textcolor[rgb]{1.00,0.00,0.00}{#1}}
\newcommand\PYaD[1]{\textcolor[rgb]{0.13,0.50,0.56}{\textbf{#1}}}
\newcommand\PYaE[1]{\textcolor[rgb]{0.38,0.38,0.38}{\textit{#1}}}
\newcommand\PYaZ[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYaX[1]{\textcolor[rgb]{0.45,0.16,0.31}{#1}}
\newcommand\PYaY[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
\newcommand\PYaR[1]{\textcolor[rgb]{0.00,0.00,0.44}{#1}}
\newcommand\PYaS[1]{\textcolor[rgb]{0.38,0.00,0.88}{\textbf{#1}}}
\newcommand\PYaP[1]{\textcolor[rgb]{0.88,0.56,0.88}{\textbf{#1}}}
\newcommand\PYaQ[1]{\textcolor[rgb]{0.78,0.36,0.04}{\textbf{#1}}}
\newcommand\PYaV[1]{\textcolor[rgb]{0.38,0.38,0.38}{\textit{#1}}}
\newcommand\PYaW[1]{\textcolor[rgb]{0.05,0.52,0.71}{\textbf{#1}}}
\newcommand\PYaT[1]{\textcolor[rgb]{0.63,0.63,0.94}{#1}}
\newcommand\PYaU[1]{\textcolor[rgb]{0.00,0.31,0.50}{\textbf{#1}}}
\newcommand\PYaj[1]{\textcolor[rgb]{0.00,0.50,0.94}{\textbf{#1}}}
\newcommand\PYak[1]{\textcolor[rgb]{0.45,0.16,0.31}{\textbf{#1}}}
\newcommand\PYah[1]{\textcolor[rgb]{0.56,0.44,0.00}{\textbf{#1}}}
\newcommand\PYai[1]{\textcolor[rgb]{0.00,0.19,0.38}{#1}}
\newcommand\PYan[1]{\textcolor[rgb]{0.38,0.38,0.94}{\textbf{#1}}}
\newcommand\PYao[1]{\textcolor[rgb]{0.45,0.16,0.31}{\textbf{#1}}}
\newcommand\PYal[1]{\textcolor[rgb]{0.13,0.50,0.56}{\textbf{#1}}}
\newcommand\PYam[1]{\textbf{#1}}
\newcommand\PYab[1]{\textit{#1}}
\newcommand\PYac[1]{\textcolor[rgb]{0.50,0.50,0.94}{#1}}
\newcommand\PYaa[1]{\textcolor[rgb]{0.50,0.50,0.50}{#1}}
\newcommand\PYaf[1]{\textcolor[rgb]{0.38,0.38,0.38}{\textit{#1}}}
\newcommand\PYag[1]{\textcolor[rgb]{0.38,0.38,0.94}{\textbf{#1}}}
\newcommand\PYad[1]{\textcolor[rgb]{0.00,0.25,0.82}{#1}}
\newcommand\PYae[1]{\textcolor[rgb]{0.25,0.00,0.88}{\textbf{#1}}}
\newcommand\PYaz[1]{\textcolor[rgb]{0.00,0.63,0.00}{#1}}
\newcommand\PYax[1]{\textcolor[rgb]{0.50,0.00,0.00}{#1}}
\newcommand\PYay[1]{\textcolor[rgb]{0.13,0.50,0.56}{\textbf{#1}}}
\newcommand\PYar[1]{\textcolor[rgb]{0.94,0.50,0.25}{#1}}
\newcommand\PYas[1]{\textcolor[rgb]{0.82,0.25,0.13}{#1}}
\newcommand\PYap[1]{\textcolor[rgb]{0.13,0.50,0.56}{\textbf{#1}}}
\newcommand\PYaq[1]{\textcolor[rgb]{0.31,0.88,0.82}{\textbf{#1}}}
\newcommand\PYav[1]{\textcolor[rgb]{0.00,0.00,0.00}{\textbf{#1}}}
\newcommand\PYaw[1]{\textcolor[rgb]{0.38,0.00,0.88}{\textbf{#1}}}
\newcommand\PYat[1]{\textcolor[rgb]{0.75,0.75,0.94}{#1}}
\newcommand\PYau[1]{\textcolor[rgb]{0.94,0.75,0.50}{#1}}

Una vez incluído esto, solo tienes que incluir desde tu fichero .tex el documento .tex generado con pygments tal que:
\input{ruta/al/fichero.tex}
Y listo, ya tienes incluido un fichero. Ahora bien, en la documentación de un proyecto medianamente grande, lo suyo es generar esto de forma automática... De ahí las siguientes secciones.

Pygmentize en el makefile

En el makefile es necesario tener una variable por cada nuevo fichero código, ya que como he dicho antes no conseguimos hacerlo de forma automática para n ficheros, entonces:

F01-PY = $(RUTA-PY)organizar

Además de las variables generales:

PYGMENTS = pygmentize # Programa a utilizar
OPC-PYG = -O linenos # Opciones extra
IN-WIK-PYG = -l trac-wiki # Lexer para formato wiki
IN-PY-PYG = -l python # Lexer para python
OUT-PYG = -f latex # Formato de salida en LaTeX
# Extensiones
WIKI = .wik
PY = .py
TEX = .tex

Y además hay que incluir la línea de compilación adecuada para cada fichero:

$(F01-PY)$(TEX): $(F01-PY)$(PY)
    $(PYGMENTS) $(OUT-PYG) $(OPC-PYG) $(IN-WIK-PYG) \
    -o $(F01-PY)$(TEX) $(F01-PY)$(PY)

Complejo no es, pero es un latazo tener que poner uno de estos por cada nuevo fichero de código que quieres incluir. De ahí lo del script.

Simplificando el makefile con un script

Total que la solución fue crear este script. Tiene bastantes detallitos tontos que lo hacen algo más complejo de lo que iba a ser en un principio, pero sigue siendo bastante fácil de usar:

# USO CORRECTO: python pygments_script.py [-v] 
#               [-h|-f|-e <extension>|-c|-d|-o <dir_salida>]
#               <fich_o_dir_entrada> ...
#   * -v -> modo chivato activado
#   * -h o --help -> ayuda
#   * -f o --force -> fuerza la reescritura de los ficheros,
#                     si existen se borran
#   * -e o --ext -> lee la extensión de los ficheros que tomará
#                   como entrada
#   * -c o --clean -> limpia los ficheros que se den como entrada
#   * -d o --dirclean -> limpia los directorios que se den
#   * -o o --output -> genera los nuevos ficheros en un directorio
#                      específico, en lugar de en su misma ruta
Ahora el makefile es muchísimo más simple: solo hay que incluir un par de líneas como mucho (unas cuantas más si eres quisquilloso como yo y te gusta que sobren variables globales, en lugar de que falten...).
Las variables globales serán:

RUTA-COD = ../codigo/wiki/
EXTENSION = wik
PYTHON = python
SCRIPT = ../codigo/pygments_script.py
PYG-OPC = -fe
PYG-CLEAN = -d

E incluimos en la directiva "codigos" la ejecución del script, teniendo en cuenta las variables que hemos creado:
codigos:
	$(PYTHON) $(SCRIPT) $(PYG-OPC) \
	$(EXTENSION) $(RUTA-COD)

Además también podemos utilzar el script para la limpieza de ficheros en el makefile (en la directiva clean-all es donde lo pongo yo):

clean:
	$(RM) *.aux *.toc *.log \
	*.lof *.lot *.out *.bbl \
	*.maf *.mtc* *.blg *~ *\#
	$(RM) -r auto

clean-all:
	make clean
	$(RM) $(NOM).dvi
	$(PYTHON) $(SCRIPT) $(PYG-CLEAN) \
	$(RUTA-COD)

Pues listo... Eso es todo. Espero que le sea útil a alguien.
Saludos, unixeros :)
About these ads

5 comentarios to 'Como colorear código con Pygments'

Subscribe to comments with RSS o TrackBack to 'Como colorear código con Pygments'.

  1. iriku87 said,

    Muy completita la entrada, zi zeñó. Por cierto, no me des tanto merito, mi script eran 20 lineas nada más, practicamente todo el resto lo has hecho tu :p

    Probablemente haya alguna manera más sencilla de usar pygments con en un Makefile, pero bueno, no es mala solución esta tampoco :)

    Keep hacking!

  2. Neoshadybeat said,

    Bueno, ya que me ha sido de gran ayuda, y dado los problemillas que me daba, me he creado un cutre-script, para parsearme el latex y poder compilarlo sin problemas los “.tex”, http://pastebin.com/mgae0KbF , no espereís gran cosa,

  3. Neoshadybeat said,

    errata, borrame el anterior, k me equivoqué de url ^o^

    http://pastebin.com/85eq5Hur

  4. Seennarit said,

    !
    I’ve got an account here.
    I just love the environment on this website. .
    How can I become a moderator on this forum?
    I like this site

  5. breakroot said,

    Please let me know if you’re looking for a author for your blog. You have some really great articles and I believe I would be a good asset. If you ever want to take some of the load off, I’d
    really like to write some material for your blog in exchange for a link back to mine.
    Please blast me an e-mail if interested. Many thanks!
    click the following web page
    and Click On this page
    and Click Here
    and also click the following internet page


Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

%d personas les gusta esto: