Porque vi y no volví

Este artículo no es para iniciar un flame war acerca de editores ni para ejercer presión en la gente para que utilice un editor en especial, sólo quiero compartir con el mundo mis experiencias utilizando diferentes editores y mi preferencia por Vi.


Incluso aunque no pueda creerlo, existen muchos usuarios del viejo editor. No son dinosaurios amantes del verde y negro que no desean adaptarse a los tiempos modernos, ya que cada día, la base de usuarios crece. Incluso compañeros del trabajo han empezado a utilizarlo y muchos de nosotros ni siquiera habíamos nacido cuando vi fue escrito.


Esto es porque el modelo de edición de vi es superior al de todos los demás. Hoy en día no hace falta ser un genio de Unix para utilizarlo ya que existen versiones libres y gratuitas para cualquier plataforma imaginable y plug-ins para obtener la misma funcionalidad en muchos de los IDE's más populares. Así que voy a intentar de dar un poco de luz con algunos ejemplos, sobre algunas de las ideas equivocadas que se tienen acerca de vi/vim y porque éste es el mejor.


1. Edición modal


Al iniciar vi/vim la primera idea chocante, es tener que presionar la tecla 'i' para poder empezar a escribir o molestarnos ante la idea de tener que utilizar 'hjkl' para desplazar el cursor sin recordar qué es lo que hace cada tecla. También puede resultar molesto tener que presionar 'a' para insertar texto después del último carácter de la línea. Por lo cual, iniciaremos en modo de edición (insert mode) y utilizaremos las flechas del teclado para mover el cursor sin volver al modo de comandos a menos de que sea absolutamente necesario. Probablemente estará unos 20 minutos en el modo de edición y nunca vuelva a utilizar vi quejándose de que no tiene manera de recordar en cual de los modos se encuentra.


Resulta que nos equivocamos si deseamos utilizar vi de ésta manera. Al utilizar vi apropiadamente, utilizamos el modo de comandos y sólo entramos en el modo de edición cuando sea absolutamente necesario modificar o añadir texto y saliendo inmediatamente pulsando 'Esc'. Por lo que, el problema de recordar el modo en el que nos encontramos no existe. Si estamos escribiendo y suena el teléfono, pulsamos 'Esc' y respondemos a la llamada. Nunca pensamos en el modo de edición como uno en el que pasar la mayor parte del tiempo.


Voy a explicar un poco la filosofía detrás de esto.


Los comandos en vi/vim están diseñados con la idea de ser combinados de diferentes formas - el comando 'd' significa "borrar" y el comando 'e' "mover al final de la palabra" por lo que 'de' elimina todo desde la posición del cursor hasta el final de la palabra (algo como Ctrl-Shift-Derecha, Izquierda, Supr). Un claro beneficio de esto lo podemos observar si añadimos la tecla '.' a la ecuación ya que '.' repite el último comando combinado de edición que hayamos realizado y no los comandos de navegación. Después de ejecutar 'dw' el comando '.' funcionara para eliminar el texto hasta el principio de la próxima palabra. Podemos navegar por todo el texto y cuando volvamos a presionar '.' seguirá haciendo lo mismo, lo cual resulta extremadamente poderoso.


Nota: 'de' elimina toda la palabra hasta el último carácter, y 'dw' borra toda la palabra hasta el primer carácter de la próxima, por lo cual se incluye el espacio que hay entre ambas.


Vamos ahora a los comando del modo de edición. Estos son todos los comandos incluidos desde que entramos en modo de edición, hasta que salimos presionando 'Esc'. En el caso más sencillo tenemos el comando 'i' Hola 'Esc', el cual introduce la palabra "Hola" donde estaba posicionado el cursor. Así que ahora el comando '.' añadirá la palabra "Hola" en la posición del cursor. Como podéis ver, esto es bastante útil, pero mucho más aun es la posibilidad de pulsar 'A' añadir un texto 'Esc' y ahora cada vez que pulsemos '.' la misma palabra se añadirá al final de la línea sin tener que posicionar el cursos allí (ya que 'A' lo que hace es iniciar la edición después del último carácter de la línea). Intentadlo, os gustará.


Otro ejemplo que muestra el poder de vi es el comando 'ce' compuesto por el comando 'c'ambiar que elimina todo lo indicado por el rango que especifiquemos y entra en modo de edición. Es igual a 'd' pero con la diferencia de que entra en modo de edición en lugar de mantenerse en el modo de comandos. Lo genial de esto es que el texto que introducimos a continuación es parte del comando. Así que si ejecutamos 'ce' Hola 'Esc' lo que se hace es sustituir "Hola" por todo el texto desde la posición del cursor hasta el último carácter de la palabra y si pulsamos '.' la próxima palabra también será reemplazada por "Hola". Este tipo de movimientos pueden llegar a ser muy complejos y existe una amplia variedad de comandos para entrar en el modo de edición ( 'o' inicia una línea debajo, 'O' un línea por encima, 'S' sustituye toda una línea, etc.).


Ejemplo #1: El poder del punto



Veamos un ejemplo en concreto. Supongamos que tenemos declaradas tres funciones y deseamos implementarlas, así que copiamos lo siguiente en el fichero de implantación:


bool ProcesarParams( int ncosas, bool nbool );
bool ObtenerObjeto( bool nbool );
bool EliminarTodosObjetos( int ncosas );


Por lo que a continuación tenemos que eliminar los ';' del final y añadir un cuerpo vació. Desde cualquier posición en la línea pulsamos 'A' y eliminamos el ';' pulsando la tecla de retroceso, añadimos '{' 'Intro' '}' y finalmente 'Esc' para volver al modo normal.


bool ProcesarParams( int ncosas, bool nbool ){
}
bool ObtenerObjeto( bool nbool );
bool EliminarTodosObjetos( int ncosas );


Luego nos situamos en la próxima línea pulsando 'j' y pulsamos '.' repitiendo con todas las demás hasta obtener esto.


bool ProcesarParams( int ncosas, bool nbool ){
}
bool ObtenerObjeto( bool nbool ){
}
bool EliminarTodosObjetos( int ncosas ){
}


Es decir, sólo con pulsar 'j.j.' realizamos todo esto. La arquitectura de vim ha sido clave, con el hecho de que la tecla de retroceso forma parte del proceso de edición como si de cualquier otra tecla se tratase. Así que piense ¿cuánto de vuestras labores de edición son tareas repetitivas? Me lo imaginaba.


2. No todo es sobre Expresiones Regulares


Las expresiones regulares en vi/vim son muy útiles y todos los editores medio serios, soportan expresiones regulares para buscar, sustituir, etc. Pero sólo vi (que yo sepa) permite utilizarlas de maneras tan complejas como para realizar cierta búsqueda y reemplazar la segunda ocurrencia de "Hola" después de las lineas que contengan "Adios" y cosas por el estilo. Pero no todo en vi/vim necesita de expresiones regulares ya que tenemos la principal fortaleza de vi en su modo básico de edición, algo con lo que no querrá vivir después de haber experimentado:


Movimientos con una o dos teclas para moverse hasta cualquier lugar de una línea, párrafo o de la pantalla.


Los comandos 'd' o 'c' pueden ser combinados con cualquier movimiento para editar directamente o iniciar el modo de edición, pudiendo repetir toda la operación pulsando '.'


Todo puede hacerse sin mover las manos del teclado. No hay que seguir sufriendo con interfaces molestas como el "clítoris" o el "mousepad" y ni siquiera será necesario buscar una mesa para utilizar nuestro portátil. Tampoco tendremos que estar a la caza de las teclas 'Supr' y de navegación.


Ejemplo #2: Rangos inteligentes


A continuación veamos un ejemplo típico: una llamada a una función en una expresión algo compleja:


if (!entrada.usada && equivalente( entrada.clave(), qk.clave ) && (contexto & entrada.contexto ));


Lo que hacemos es posicionar el cursor al principio de la llamada 'equivalente' y lo que queremos hacer es extraer todo eso e incluirlo en una variable. Lo primero es seleccionar, luego copiar y borrarlo para moverlo a la línea superior, escribir el nombre de la variable, etc. Con un editor cualquiera, tendriamos que ir tanteando con el ratón hasta obtener el resultado que queremos o quizas con 'Ctrl+Shift' + 'Izq' o 'Der'.


En vi/vim tenemos '%' el cual se mueve desde un paréntesis hasta el paréntesis apropiado que lo cierra u objetos similares ([], {}, <>, etc.). Incluso si no estamos posicionados sobre el paréntesis, el comando buscará hacia la derecha al primero que encuentra y lo utilizará como origen. Así que en el ejemplo, si pulsamos '%' el cursor se moverá hasta el siguiente paréntesis y nos marcará el paréntesis que lo cierra. Si volvemos a pulsar '%' el cursos ira a éste último paréntesis.


Sabiendo que 'c' corta el rango que le indiquemos (copiandolo a memoria) y entra en el modo de edición podemos pulsar 'c%' para obtener lo siguiente:


if (!entrada.usada && && (contexto & entrada.contexto ));


¡Nada mal para dos teclas! Ahora escribimos el nombre de la variable, pulsamos 'Esc' para salir al modo normal.


if (!entrada.usada && equiv && (contexto & entrada.contexto ));


Seguimos pulsando 'O' para añadir una línea por encima de esta y añadimos la declaración de la variable.


bool equiv =
if (!entrada.usada && equiv && (contexto & entrada.contexto ));


Dado que lo que cortamos se encuentra aun en memoria, pulsamos 'Esc' y a continuación 'p'egar, añadimos el ';' y ya terminamos.


bool equiv = equivalent( entrada.clave(), qk.clave );
if (!entrada.usada && equiv && (contexto & entrada.contexto ));


Todo esto lo hemos hecho con pulsar cuatro comandos ('c'ortar, '%' rango, 'O' y 'p'egar) y sin mover las manos del teclado.


Pronto continuare con más ideas equivocadas sobre vi/vim.