Contenido

Colorit

El otro día, mi amigo Javi me dijo que es increíble la cantidad de comandos de shell que hay y que pasan desapercibidos. No puedo estar más de acuerdo, para empezar, porque acababa de descubrir este comando: colorit.

Viene con el paquete dict, lo que le hace aún más difícil de encontrar. ¿Y su misión? Pues colorear nuestra salida estándar :D

Lo básico

En realidad no colorea nada, sino que reemplaza expresiones regulares, añadiéndoles un encabezado y un pie. Por eso trae un archivo de configuración con algunas macros para seleccionar los colores.

Por desgracia, este archivo de configuración es un poco enrevesado y tiene pocas reglas, pero puede valer como punto de inicio. De hecho, será necesario que nos lo copiemos, para así aprovecharnos de sus macros.

Otro problema es que no busca ningún archivo de configuración en el directorio local, sino únicamente en el home y el estándar. Copiémonos el estándar, que se encuentra en /etc/dictd/colorit.conf:

 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
dnl /etc/dictd/colorit.conf   vim:ft=m4
dnl
dnl Sample configuration file for colorit(1) program
dnl
divert(-1)
dnl
dnl Define some useful color variables
dnl
define(`black',   `0')
define(`red', 	  `1')
define(`green',   `2')
define(`brown',   `3')
define(`blue', 	  `4')
define(`magenta', `5')
define(`cyan',    `6')
define(`white',   `7')
dnl
dnl Mark macro arguments: regexp foreground-color [background-color]
dnl
define(`mark', ``mark "$1"''  `ifelse(`$#', `3', ``"\033[3$2;4$3m"'', ``"\033[3$2m"'')' `"\033[m"')
dnl
divert
mark(`^From.*$',red,cyan)
mark(`^  [^ ]+',green)
mark(`^ *Note:',red)
mark(`{[^{]+}',green)
mark(`^ *\[[^\[]+\]', cyan)
mark(`^[ 	]*(adj|n|v|adv)? *[0-9]+[\.:]',cyan)
mark(`^ *\([a-z]+\)',cyan)
mark(`(Syn|Ant|syn|ant):', blue, white)
mark(` (t|i|a|adj|adv|n|v)\. ',cyan)
mark(` (t|i|a|adj|adv|n|v)\.$',cyan)

No os asustéis por el formato tan absurdo. Fijaos únicamente en las últimas líneas, que serán las que tocaremos. Podemos crear nuestras propias expresiones regulares para nuestras salidas favoritas.

Adaptándolo

En mi caso, estoy utilizando nose junto con freshen . Así que mi archivo de configuración (aún mejorable) pinta así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
define(`black',   `0')
define(`red', 	  `1')
define(`green',   `2')
define(`brown',   `3')
define(`blue', 	  `4')
define(`magenta', `5')
define(`cyan',    `6')
define(`white',   `7')
dnl
dnl Mark macro arguments: regexp foreground-color [background-color]
dnl
define(`mark', ``mark "$1"''  `ifelse(`$#', `3', ``"\033[3$2;4$3m"'', ``"\033[3$2m"'')' `"\033[m"')
dnl
divert
mark(`^FAIL(ED)?', white, red)
mark(`failures=[0-9]*', red)
mark(`===(=)*', brown)
mark(`^[\.F]+$', cyan)
mark(`^(AssertionError:)|(Exception:) .*$', red)
mark(`^OK$', white, green

Y así me colorea la salida y puedo ver el VERDE o el ROJO, según funcionen o no los tests.

Hay un problema… Y es que nose utiliza la salia de errores en lugar de la salida estándar. Por eso he tenido que rebuscar un pipe que no conocía: |&, que premite redireccionar tanto la salida estándar como la de errores.

De esta manera, mi invocación es algo así:

1
$ nosetests --with-freshen tests -s -v |& colorit -c colorit.conf

Y el resultado queda perfectamente coloreado :D

¡Una gran ayuda!

Mejoras

Lo más terrible del caso creo que es que colorit es un shell-script. Y no sería difícil crear uno mucho mejor, ¿verdad?