Resalta tu código con Pygments

Resalta tu código con Pygments
Escrito 3 years ago

Pygments es una librería para python que se utiliza para resaltar y colorear la sintaxis de cualquier lenguaje de programación y mostrarlo en multitud de salidas: HTML, en una imagen, en código de consola, etc... Es ideal para generar documentos desde python que incluyan código de programación, por ejemplo editores de textos o páginas web.

Instalar pygments

Si tenemos el repositorio pip de Python, instalarlo será muy fácil. Accedemos a la consola de nuestro equipo y escribimos el siguiente comando para descargar e instalar el paquete en nuestro ordenador.

Instalar pygments
1
$ pip install pygments

Ejemplo de Pygments con Django

En esta entrada vamos a desarrollar una pequeña aplicación que estará formada por un formulario donde escribiremos un trozo de código de programación. La aplicación resaltará el código que hemos escrito y nos lo devolverá en formato HTML.

Vamos a ello:

Formulario Django

Lo primero es crear un archivo al que llamaré forms.py con un formulario básico creado con Django.

forms.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Lenguajes de ejemplo que utilizaremos en el formulario
LANGUAGES = (
('html+php', 'php'),
('python', 'python'),
('html+javascript', 'javascript'),
('html', 'html'),
('css', 'css')
)


# Formulario que vamos a usar en el ejemplo
class PygmentsForm(forms.Form):
# Select con los lenguajes disponibles
lang = forms.ChoiceField(label='Lenguaje', choices=LANGUAGES)
# Textarea donde se escribirá el código
code = forms.CharField(label="Código", widget=forms.widgets.Textarea)

# Obtener el código ya transformado con pygments
def get_highlight_code(self):
lang = self.cleaned_data['lang']

# get_lexer_by_name es una función de Pygments, que devuelve un lexer a partir de un texto
lexer = get_lexer_by_name(lang)
code = self.cleaned_data['code']
# HtmlFormatter Genera la salida del código en formato HTML.
# El parámetro linenos=True sirve para añadir los números de linea en la salida html.
formatter = HtmlFormatter(linenos=True)

# Ejecutamos la función highlight para obtener el código en formato html
return highlight(code, lexer, formatter)

En el archivo anterior es un formulario con 2 campos

  • lang: Es un campo tipo select con los lenguajes de programación que vamos a resaltar en este ejemplo. Las opciones de este select se guardan en una variable global llamada LANGUAGES.

  • code: Es el textarea donde escribiremos nuestro trozo de código para que sea resaltado.

Lo importante del archivo es el método get_highlight_code() que es el encargado de resaltar el código y devolverlo en formato html.

Antes de continuar, como funciona Pygments

Vamos hacer una pequeña pausa para ver, rápidamente, cuales son sus principales partes de Pygments:

  • Lo primero es el lexer. Es la parte que se encarga de procesar el código de programación. Existe un lexer por cada lenguaje que admite Pygments, -Lista completa de lenguajes-.

    Por suerte no tendremos que importar un lexer por cada lenguaje que queremos procesar, sino que Pygments nos proporciona de una función get_lexer_by_lang(), a la cual se le pasa como parámetro una cadena con el nombre del lenguaje que queremos procesar 'python', 'php', 'javascript', ... y ella sola busca y nos devuelve un objeto del lexer del lenguaje. Enlace con todos los lexer que tiene Pygments.

  • El Formatter es la parte que se encargará de transformar el código procesado por el lexer y devolverlo en el formato que nosotros queramos. En el ejemplo anterior utilizamos la clase HtmlFormatter() para que el código sea devuelto en un formato html. Todos los formatters disponibles.

  • highlight(): Es la función principal. Se le pasa el código que queremos resaltar, el lexer y el formatter, y la función nos devuelve el resultado en el formato escogido. Más información de la función

Existen más componentes y características. Podéis ver la documentación oficial en este enlace.

Ahora podemos seguir con nuestro ejemplo. El resto de archivos son triviales para aquellos que entiendan como funciona Django. Creamos la vista que procesará el formulario y mostrará el resultado.

Archivo views.py con la vista para procesar el formulario
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from django.shortcuts import render
from pygmentstest.forms import PygmentsForm


def indexView(request):
result = ''

# Comprobamos si hemos enviado el formulario
if request.method == 'POST':
# Creamos el formulario con los datos request.POST
form = PygmentsForm(request.POST)

if form.is_valid():
# Si los datos son válidos transformamos el código con pygments
result = form.get_highlight_code()

else:
# Creamos un formulario con los datos vacíos
form = PygmentsForm()

return render(request, 'index.html', {'form': PygmentsForm(), 'result': result})

El archivo con la url

urls.py
1
2
3
4
5
6
7
from django.conf.urls import url

import pygmentstest.views as views

urlpatterns = [
url(r'^$', views.indexView, name='index'),
]

Y por último la plantilla.

index.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ejemplo pygments</title>
<link href="{% static '/static/css/highlight.css' %}" rel="stylesheet" type="text/css"/>

<style type="text/css">
/* Estilo para el cuerpo de la página*/
body{
font-size: 16px;
color: #444;
font-family: sans-serif;
}

/* Estilo para la caja del código */
.result{
color: #ddd;
border: 1px solid #111;
font-size: 14px;
background: #3b3b3b;

}
</style>
</head>
<body>
<h1>Ejemplo</h1>
<p>
Selecciona un lenguaje y escribe un ejemplo de código en el campo.
Pulsa enviar, para visualizar el código con <b>Pygments</b>
</p>

<form action="{% url 'index' %}" method="post">
{% csrf_token %}

{# Formulario #}
{{ form.as_ul }}
<input type="submit" value="Enviar">
</form>

{% if result %}
<h2>Resultados</h2>
<div class="result">
{{ result|safe }}
</div>
{% endif %}
</body>
</html>

En el la plantilla html hay 2 puntos a destacar:

  1. La hoja de estilo highlight.css, es la que guarda las clases css para resaltar el código html que hemos generado con nuestro formulario PygmentsForm. Esta hoja de estilos se puede construir manualmente o de forma automática utilizando un comando de consola, como veremos más adelante.

  2. La linea {{ result|safe }}. En esta linea, la variable result guarda el resultado html de nuestro código procesado. Es importante añadir el filtro safe para que Django no escape los caracteres html que hay en la variable.

    NOTA

    Django recomienda no utilizar el filtro safe porque puede provocar que un usuario nos inyecte código html en nuestra aplicación web. Pero no os preocupeis, Pygments escapa los caracteres html peligrosos del código igual que haría Django.

Con esto, nuestro ejemplo ya estaría prácticamente terminado. Ahora solo quedaría generar de forma automática la hoja de estilo highlight.css, utilizando un comando que se instala cuando instalamos el paquete Pygments.

comando para generar hoja de estilos para pygments
1
$ pygmentize -f html -S 'monokai' > highlight.css

El comando en pygmentize y nos genera en la misma carpeta un archivo css llamado highlight.css con el tema de colores monokai. Ya solo queda copiar el archivo css generado y pegarlo en la carpeta de archivos estáticos de tu proyecto.

En este enlace están todos los temas oficiales para Pygments y las hojas de estilos listas para descargarse. Si no te gusta ninguno, también puedes crear uno propio con su herramienta online.

Esto solo es un ejemplo. ¿Tu como lo utilizarías?

Aquí hemos visto un pequeño ejemplo de como funciona Pygments y como añadirlo a nuestro proyecto de Django. Pero el número de cosas que se puede hacer con este paquete es enorme. Tanto para aplicaciones web, como para aplicaciones de escritorios.

Comentarios