miércoles, 4 de marzo de 2009

HAL y vim (VII)

Las opciones fundamentales de los menús "Archivo" y "Edición" suelen ser comunes a todos los procesadores de textos y editores de escritorio. No sucede lo mismo con las que forman parte de los menús "Ver" y "Herramientas", cuyo contenido suele ser mucho más variable, hasta el punto de que no queda del todo claro qué corresponde a cada uno de ellos. Por esta razón dejaremos de ateneros literalmente a los menús de Openoffice Writer y construiremos con las opciones que aparecen en él y en otros editores gráficos un par de menús ideales, que tomaremos como referencia para continuar la exposición.

Empezaremos con el menú "Ver", que agruparía funciones relacionadas con los detalles de la interfaz y de la visualización del texto en ella, pero que no afectarían al resultado del proceso de edición propiamente dicho. Un menú "Ver" genérico podría contener esta serie de funciones principales:

Fuente
Determinar la fuente que se utilizará para la presentación del texto en pantalla.

Colores
Determinar los colores con que aparecerán los distintos fragmentos de texto.

Barra de estado
Definir el contenido de la "barra de estado", donde se incluye información sobre el documento que se está editando.

Número de líneas
Mostrar el número de cada línea de texto.

Caracteres no imprimibles
Mostrar caracteres que no se imprimirán en la salida impresa, como saltos de línea, tabuladores, espacios sobrantes, etc.

Ajustar texto
Definir el modo como se ajustará (wrap) el texto cuando las líneas de ese texto sea más largas que la anchura de la ventana de la aplicación en que aparecen.


En los editores de consola la fuente con la que se presentará el texto no es propiamente responsabilidad del editor, sino de la infraestructura de la que depende la interfaz del editor. Puesto que en esta serie de artículos hemos dado por supuesto desde el principio que el editor se ejecutará en un emulador de terminal, la configuración de la fuente del texto será la que haya quedado configurada en ese emulador. Normalmente existe un apartado en los menús del emulador que permite definir exactamente esa fuente (la familia, el tamaño, etc.). Es importante que el lector elija bien aquí de acuerdo a sus necesidades y a las características de su entorno de trabajo, puesto que van a ser muchas las horas que pasará delante del emulador. Una fuente frecuente entre usuarios de aplicaciones sobre emulador de terminal en GNU/Linux es la fuente Terminus, que se puede instalar como cualquier paquete con la orden:

aptitude install xfonts-terminus

Introducir los colores como una opción fundamental de visualización podría parecer algo totalmente extravagante o remilgado. No lo es cuando se piensa en la cantidad de tiempo que se emplea en las tareas de edición de textos y, especialmente, cuando se pretende editar algo más que texto simple, más en concreto, texto que contiene alguna clase de orden o etiquetado, por ejemplo, un guión para HAL, una página en HTML o un programa en cualquier lenguaje de programación.

La paleta de colores empleada para diferenciar el tipo de estructuras sintácticas de la lengua artificial correspondiente (lengua de HAL, lenguajes de programación, etc.) se denomina técnicamente resaltado de sintaxis. Activar el resaltado de sintaxis es una opción con la que nadie que la conoce puede sobrevivir, porque aumenta hasta límites insospechados la legibilidad del texto y, por tanto, la velocidad de edición. La orden que entiende Vim para dicha activación es:

:syntax on

Pruebe el lector a abrir el código HTML de esta misma página con Vim y trate de entender algo. Una vez que empiece a marearse, active el resaltado de sintaxis con la orden indicada. Las cosas se ven de otra forma, ¿no?

Si los colores son demasiado claros u oscuros o el contraste no es el que deseamos, es probable que Vim no haya sido informado correctamente de la tonalidad del fondo de nuestro terminal. Vim refina su paleta sintáctica dependiendo de si ese fondo es claro u oscuro. La orden para proporcionarle esta información es, cuando el fondo es oscuro (dark), la siguiente:

:set background=dark

Si el fondo fuese claro (light), la orden sería:

:set background=light

Puede influir también el esquema de colores activo, que se configura con la orden:

:colorscheme nombre_de_esquema_de_color

Los esquemas de colores actuales se definen en ficheros de configuración que se encuentran en el directorio $VIMRUNTIME/colors. Para activar, por ejemplo, el esquema de colores descrito en el fichero koehler.vim, que se encuentra en dicho directorio, tendríamos que enviar la siguiente orden a Vim:

:colorscheme koehler

En esta toma vemos dos esquemas de colores para visualizar un documento bien conocido:



De la barra de estado ya hablamos al principio de esta serie de artículos sobre Vim. Viene activada y configurada por defecto. Por tanto, no tenemos que preocuparnos de hacer nada en este punto, salvo de comprender cuál es la información presentada allí. El lector sabrá deducirla por su cuenta.

También nos referimos de pasada hace unos días a la forma de solicitar a Vim que nos muestre el número de línea a la izquierda de cada línea del documento, algo muy útil cuando sabemos que podemos movernos a una línea en particular con una instrucción como nG, donde n es el número de esa línea. La orden para mostrar el número de líneas es, como dijimos entonces:

:set number

Para ocultar dichos números utilizamos:

:set nonumber

Es posible utilizar una única función para realizar ambas operaciones:

:set invnumber

Este tipo de instrucciones, que comienzan como el prefijo inv funcionan como un dispositivo lógico de encendido y apagado, que, dependiendo de la configuración actual tiene un efecto o su contrario. El caso típico de inversor en nuestra vida cotidiana es el interruptor de la luz. Si el interruptor se pulsa cuando la luz está apagada, la luz se enciende; en caso contrario, la luz se apaga. La aplicación práctica de este tipo de funciones es inmediata. Lo ideal sería poder disponer de un "interruptor" fácil de pulsar para "encender" o "apagar" a discreción los números de líneas. ¿Qué tal una tecla que no se use nunca para las labores de edición, como una tecla de función, 'Fn'? ¿Podríamos asociar una orden de inversión a una de estas teclas? Podemos, y lo vamos a hacer ahora mismo. La orden que entiende Vim para poder establecer una asociación de este clase tiene la forma:

:map tecla orden

La única dificultad radica en la forma de indicar a Vim la tecla que funcionará como nuestro interruptor y la orden misma, porque no es sólo la orden el término de la asociación, sino el conjunto de operaciones de teclado que realizamos para emitirla. Por ejemplo, para enviar la orden anterior :set invnumber, realizamos tres operaciones de teclado:

  1. Pulsar la tecla Esc

  2. Escribir la orden

  3. Pulsar la tecla Enter


Lo que queremos es que, por ejemplo, la tecla 'F2' haga exactamente lo mismo que esas tres operaciones de emisión de la orden.

Existen formas convencionales de referir literalmente teclas como las teclas de función, la tecla 'Esc' o la tecla 'Enter', también llamada retorno de carro (carriage return). Estas formas son, respectivamente, <F2>, <Esc> y <CR>.

Podemos ahora construir perfectamente nuestra orden de asociación, que sería:

:map <F2> <Esc>:set invnumber<CR>

Tras ejecutarla, bastará pulsar F2 para que aparezcan o desaparezcan los números de línea.

El lector astuto se fijará en que, tras salir de Vim e iniciar una nueva sesión de edición, la asociación realizada dejará de funcionar. Tampoco funcionarán las órdenes que establecían el resaltado de sintaxis o el esquema de colores, por citar sólo las consideradas el día de hoy. Al final de estos artículos describiremos el sencillo método para lograr que este tipo de configuraciones sean permanentes y no tengamos continuamente que recordárselas a Vim.

Aunque de uso menos frecuente, los procesadores de textos suelen incluir una opción para la visualización de caracteres no imprimibles como tabuladores, saltos de línea, espacios sobrantes, etc. En Vim podemos conseguir algo similar mediante la orden:

:set list

Y desactivar la visualización de caracteres no imprimibles mediante:

:set nolist

De igual forma que con :set (no)number, Vim tiene la delicadeza de suministrar el correspondiente inversor:

:set invlist

Conviene personalizar además la forma en que se mostrarán los caracteres no imprimibles. Para ello le damos a Vim la orden:

:set listchars

Esta orden, sin argumentos o, más precisamente, con el argumento '?', nos muestra su configuración actual. En general toda orden de configuración del tipo :set puede recibir el argumento '?' para mostrar su configuración. Así, por ejemplo, la orden:

:set listchars ?

nos dará, seguramente, el siguiente resultado, que aparecerá en la barra de estado:

listchars=eol:$

Para configurar la variable listchars a nuestra medida debemos darle como valores una lista entre comas de los caracteres no imprimibles que queremos visualizar cuando ejecutemos la orden :set list y del carácter que se mostrará en su lugar, de acuerdo con la siguiente sintaxis:

carácter_no_imprimible:carácter_con_que_se_visualizará

En la configuración por defecto, la que acabamos de ver en la barra de estado, el único carácter no imprimible que aparecerá al ejecutar :set list es 'eol' (end of line), el carácter de fin de línea o de salto de línea, que se visualizará como un '$'. Nos puede interesar visualizar además los caracteres tabulador (que se designan mediante 'tab') y los espacios sobrantes en los finales de línea, que se designan mediante 'trail'. Sin entrar en más detalles, pongamos que elegimos los siguientes caracteres para visualizar tales caracteres no imprimibles:

  • eol Se mostrará como $

  • tab Se mostrará como > seguido por tantos guiones (-) como número de espacios ocupe.

  • trail Se mostrará con tantos guiones (-) como espacios sobrantes haya.


La instrucción para esta nueva configuración sería, pues, la siguiente:

:set listchars=eol:$,tab:>-,trail:-

Es normal agrupar varias órdenes :set en una sola orden para que se ejecuten simultáneamente. Basta con iniciar la orden con :set y disponer, uno tras otro, separados por espacios, de sus correspondientes argumentos. Por tanto, podríamos instruir directamente a Vim para que muestre los caracteres no imprimibles y lo haga según la configuración antes propuesta:

:set list listchars=eol:$,tab:>-,trail:-

Como disponemos de un inversor para :set (no)list, podemos volver a crear un "interruptor" de teclado para conmutar la visualización de los caracteres no imprimibles. Por ejemplo, podemos asociar la tecla F3 a la orden anterior, pero ahora usando el inversor invlist en lugar de list:

:map <F3> <Esc>:set invlist listchars=eol:$,tab:>-,trail:-<CR>

Efectuada la asociación, pulsaremos la tecla F3 cuando queramos ver (o dejar de ver) los caracteres no imprimibles del texto en pantalla. Así, para un texto como éste:

En un lugar de la Mancha
de cuyo nombre no quiero
acordarme

pulsar F3 nos mostraría lo siguiente:

En un lugar de>-la>-----Mancha----$
de cuyo>>-------nombre no quiero$
acordarme----$

La última característica que toca ver hoy es la relacionada con el modo en que se presentarán las líneas cuya longitud excede la anchura de la ventana de terminal donde se presentan. Los procesadores de textos resuelven este problema "envolviendo" (wrapping) la línea en la ventana del procesador de manera que se muestre en ella como varias "líneas aparentes". Vim funciona por defecto de la misma forma. Por ejemplo, el texto siguiente consta de tres líneas reales (como indica su número), de las cuales la primera se presenta en tres "líneas aparentes" para adaptarse a la anchura actual del terminal:

1 En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no h
a mucho tiempo que vivía un hidalgo de los de lanza en astillero,
adarga antigua, rocín flaco y galgo corredor.
2
3 (fragmento de Don Quijote)

Salta a la vista inmediatamente un hecho poco común para el usuario habituado a los procesadores de texto: la primera línea aparente termina en medio de una palabra. Vim proporciona una orden para que las cosas suceden del modo al que estamos acostumbrados, esto es, para que cuando la longitud de la última palabra exceda la anchura reservada para ella se pase toda a la siguiente línea aparente. La orden a la que nos referimos es:

:set linebreak

que nos presentará el texto anterior de esta otra forma:

1 En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no
ha mucho tiempo que vivía un hidalgo de los de lanza en
astillero, adarga antigua, rocín flaco y galgo corredor.
2
3
4 (fragmento de Don Quijote)

No obstante, subsiste todavía una diferencia de comportamiento entre los procesadores de texto y Vim, a saber, las órdenes habituales de movimiento de Vim tendrán en consideración la línea real y no las líneas aparentes, cosa que no sucede con los procesadores de textos. Por ejemplo, si el cursor estuviese situado en cualquier parte de la primera línea aparente, la orden '$' lo desplazaría al final de la línea real, es decir, al último carácter de la tercera línea aparente del anterior ejemplo:

# Situación del cursor antes (amarillo) y después (rojo) de ejecutar '$'
1 En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no
ha mucho tiempo que vivía un hidalgo de los de lanza en
astillero, adarga antigua, rocín flaco y galgo corredor.

Existen órdenes especiales para moverse en el interior de las líneas aparentes, pero no las hemos visto, ni las vamos a tratar ahora. Es frecuente adoptar, sin embargo, otra solución: configurar Vim para que añada automáticamente un salto de línea al llegar al extremo derecho de la ventana del terminal. Téngase en cuenta que esta opción no sólo afecta a la visualización del texto en pantalla, sino que lo modifica, puesto que añadir saltos de línea es modificar el texto. La variable de configuración que tendremos que redefinir es la variable wrapmargin, que deberá recibir un valor distinto de 0, su valor por defecto; por ejemplo:

:set wrapmargin=7

Si hubiésemos empezado a escribir el texto de El Quijote con una configuración previa como la que acabamos de establecer, hubiésemos obtenido este otro resultado, donde en lugar de líneas aparentes tendríamos únicamente líneas reales:

1 En un lugar de la Mancha, de cuyo nombre no quiero
2 acordarme, no ha mucho tiempo que vivía un hidalgo de
3 los de lanza en astillero, adarga antigua, rocín flaco
4 y galgo corredor.
5
6
7 (fragmento de Don Quijote)

Se preguntará el lector por qué no es ésta la configuración por defecto de Vim. La razón es simple. En muchos lenguajes artificiales, la lengua de HAL entre ellos, el salto de línea tiene un significado especial y es frecuente la existencia de líneas muy largas. Proponer la división automática de líneas como opción inicial arruinaría nuestros guiones y nuestros programas. Como Vim es un editor pensado inicialmente para programadores, tiene perfecto sentido que el valor por defecto de wrapmargin sea 0.

Queda un último problema relacionado con este asunto. La orden :set wrapmargin=7 ejerce su efecto sobre todos los textos que escribimos con ella activada, pero no afectará a textos que no contengan en sí mismos el salto de línea en el lugar oportuno. En estos casos la solución habitual es recurrir a una orden que dé formato al texto ya existente para que todas sus líneas se acorten como corresponda. Aquí es frecuente el uso de herramientas externas (a través de la orden '!'), como par. Pero también podemos recurrir, si no queremos nada particularmente sofisticado, a órdenes que suministra de fábrica el propio Vim. La orden genérica de Vim para reducir la longitud de todas las líneas mediante la oportuna introducción de saltos de línea tiene la forma:

gqobj

donde obj es el objeto de texto que deseamos formatear.

Dos casos frecuentes de uso son:

gqG

que introduce saltos de línea (por defecto, cada 79 caracteres) en todas las líneas hasta el final del documento.

O también:

gq}

que produce el mismo efecto, pero sólo en el párrafo actual.


Resumen:

  • La fuente con la que se presenta un documento en Vim viene determinada por las opciones de configuración del emulador de terminal desde el que iniciamos Vim.

  • Para activar el resaltado de sintaxis en Vim se usa la orden :syntax on.

  • Los colores resultantes tras la activación del resaltado de sintaxis dependen de la tonalidad del fondo de nuestro terminal, del que se puede informar a Vim con la orden :set background=tonalidad, donde tonalidad es dark (oscura) o light (clara). Dependen también del esquema de colores que seleccionemos con la orden :colorscheme nombre_del_esquema.

  • Vim incluye por defecto una barra de estado que proporciona información dinámica sobre el documento editado.

  • La visualización u ocultamiento del número de líneas se realiza con las órdenes :set number y :set nonumber, respectivamente, o bien con la orden inversora :set invnumber.

  • Las órdenes de configuración cuyo nombre comienza con el prefijo inv son órdenes inversoras, es decir, órdenes que activan o desactivan una característica, dependiendo del estado actual en que esa característica se encuentra.

  • La orden :map permite asociar una tecla a un grupo complejo de operaciones de teclado. Por ejemplo, :map <F2> <Esc>:set invnumber<CR> asocia la operación de invertir el estado de la visualización de números de línea a la tecla F2.

  • Las órdenes de Vim para visualización de caracteres no imprimibles son :set list, :set nolist y :set invlist. La determinación de qué caracteres no imprimibles se mostrarán y de cómo apareceran depende del valor de la variable listchars que se puede redefinir con la orden :set listchars.

  • Para conocer el valor actual de una variable en Vim se usa la orden set variable ?, donde variable es una variable concreta de Vim.

  • Por defecto, Vim ajusta el texto a la dimensión del terminal, de forma que una línea larga en el texto aparezca como varias líneas. Se puede evitar que fragmentos de una misma palabra aparezcan en distintas líneas mediante la :set linebreak.

  • Vim ofrece la posibilidad de introducir automáticamente saltos de línea al llegar al límite derecho de la ventana del terminal. Para ello hay que asignar a la variable wrapmargin un valor distinto de 0, por ejemplo, mediante la orden :set wrapmargin=7.

  • Para modificar documentos existentes de forma que sus líneas no ocupen más caracteres de un valor estipulado (convencionalmente 79 caracteres) se usa la orden gqG o, en caso de que se requiera sólo modificar un párrafo del documento, la orden correlativa gq} ejecutada cuando el cursor está situado en dicho párrafo.

No hay comentarios:

Publicar un comentario