NeoVim True colors

Hola,

Ayer, después un año investigando (no muy bien por lo que he visto finalmente) he conseguido configurar NeoVim para que utilice true colors. La última vez que me puse con esto lo di por imposible pero he vuelto a ello porque he añadido un ColorColumn y necesitaba que tuviera un color más oscuro.

Resulta que no era para nada difícil pero no sé por qué me costó tanto en el pasado.

Antes de empezar NeoVim es una extensión de VIM para añadir alguna funcionalidad extra que seguramente nunca se verán en VIM. Os dejo la página del proyecto y vosotros investigáis.

Ahora al lío.

Para que soporte true colors hay que tener una variable de entorno activada: NEOVIM_TUI_ENABLE_TRUE_COLOR. Que se puede hacer en la propia terminal con un export o haciendo un let en la configuración de NeoVim.

En muchos sitios pone que esta configuración es suficente pero no es cierto. NeoVim necesita más cosas para que los true colors se vean. Si se añade :set termguicolors empezará a funcionar como debe. Esto es un bypass muy loco que hace que la terminal utilice los colores de la GUI.

En Vim hay dos modos de trabajo: el clásico de la terminal y el de la GUI. GUI implica que hay una aplicación de escritorio con sus ventanitas y eso que muestra Vim (gvim, por ejemplo). Los colores de una a la otra opción son diferentes porque se supone que la terminal no es capaz de manejar los mismos colores que una interfaz gráfica, pero eso ya no es del todo cierto. Muchos terminales modernos soportan true colors por lo que pueden usar los colores que, en principio, están hechos para mostrarse en la GUI.

NeoVim sabe esto así que diciéndole que use los colores de la GUI en la terminal lo hará y tendremos los true colors. Otro problema es que muchos esquemas de color comprueban si se está utilizando el modo GUI o el de terminal para decidir qué esquema utilizan (el complejo o uno simplificado especial para la terminal). Esa comprobación se hace con has('gui_running'), cuidado con eso. Hay algunos esquemas de color que son para true colors y algunos no lo comprueban y funcionarán bien (ejemplo).

Ya que estaba me decidí también por buscar otras opciones similares. Existe una muy chula que te cambia la forma del cursor dependiendo del modo en el que estés. Usa el cuadradito para modo normal, un subrayado del carácter en el modo reemplazar y una barrita vertical que se sitúa entre caracteres en el modo insertar. De esta manera tenemos un pequeño apoyo visual al trabajar. Esto se activa con NVIM_TUI_ENABLE_CURSOR_SHAPE que igual que la de antes de “enable true color” se puede setear como variable de entorno en la terminal o con un let dentro de la configuración de NeoVim.

Otro día os hablo más de NeoVim e incluso puede que haga una especie de manual a mi manera. Pero eso otro día.

Os dejo con el patch que he aplicado a mi configuración:


" Enable TRUE COLORS
+let $NVIM_TUI_ENABLE_TRUE_COLOR=1
+let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1
+set termguicolors

" Highlight where the lines are more than 80 characters wide
set colorcolumn=80
-highlight ColorColumn ctermbg=DarkGrey
+highlight ColorColumn ctermbg=DarkGrey guibg=#262626

Como veis en el ColorColumn, ahora aplico el guibg=#262626 que es un gris bastante oscuro en su color RGB. Al estar aplicado el termguicolors utilizará ese color también en la terminal.

¡Conseguido!

Probad y me decís.


PD: Os dejo mis dotfiles para que veáis mi configuración entera: https://github.com/ekaitz-zarraga/dotfiles

Funciones asíncronas Javascript

JavaScript es una broma, una jodida broma. Una broma digna del Comediante.

Todo es asíncrono pero para hacer cosas asíncronas hay que hacer trampas. Esto es un ejemplo:

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}


console.log('EMPIEZA');

function count(){
  setTimeout(

    function(){
      for(var i = 0; i < 10; i++){
        console.log(i);
        wait(1000);
      }
    }

  );     // ¿Va el hilo principal a esperar a que 
         // termine el count()?
}
count();

console.log("TERMINA");

Paso de explicar esta mierda.

A veces lo amas y a veces lo odias, esto es JavaScript.

He dejado una preguntilla en el código para que probéis. No soy tan malo, investigad un poco. 🙂

Preguntad lo que necesitéis.

Un abrazo.

Preprocessor Magic en C

Hola,

He estado jugando con C y dando el coñazo a la gente de mi entorno con esto así que voy a hablar un poco “del C sostenido”1, es decir, la magia del preprocesador, todo propiciado por un fantástico hack que he visto en la librería cURL.

No voy a entrar a explicar el hack del que hablo más arriba porque tampoco lo entiendo aunque creo que sé por dónde puede ir. Investigadlo vosotros y me comentáis si queréis. En lugar de eso voy a hablar del preprocesador de C y voy a jugar un poco con alguna macro, sin meternos demasiado en harina. Esta entrada está más orientada a la gente que sabe algo de C y puede pegarse con el lenguaje pero no tiene más que un conocimiento superficial del mismo y no se lleva bien con esas órdenes que empiezan por una almohadilla (o hashtag para los modernos).

Primero, ¿qué son las Directivas del Preprocesador?

Básicamente son las frasecitas del hashtag, como los #include, #define, #ifdef, #ifndef, #pragma or whatever. Sirven para dar información al preprocesador como su propio nombre indica. El preprocesador analiza nuestro código fuente antes de que se realice la compilación así que, en realidad, no formarán parte del binario de nuestro programa de forma explícita, pero sí afectarán a cómo se hace la compilación. Las más usadas solamente facilitan la programación, nada más, pero ahora explico un poco de eso.

Define

Define sirve para definir mierdas (¿En serio? No lo hubiese dicho nunca). Sirve tanto con valores como con macros pero el concepto es el mismo. Sustituye el texto del primer argumento por el texto del segundo dentro de tu programa. Y cuando digo texto, digo texto, literalmente.

Está un poco más trabajado que eso y permite macros con parámetros tal que así:

#define error(a) fprintf(stderr, "ERROR: %s", a)

Este define permitiría que escribiésemos error() con un string dentro en lugar de tener que escribir un fprintf(stderr, "ERROR: %s", ) con ese string. Es decir, sustituirá error por el fprintf pero usando a como parámetro.

Habiendo dicho esto, en el siguiente bloque de código fuente defino dos veces el número pi. ¿Podríais decirme cuál es la diferencia entre la variable a y la b? ¿Y la diferencia entre pi y PI?

La respuesta está debajo del código, no la miréis, no seáis tramposos.

// Define constante PI
#define PI 3.1416
// const es para que el valor sea constante
const float pi = 3.1416;

int main(int argc, char * argv[]){
    float a = PI; // a = 3.1416
    float b = pi; // b = 3.1416
    return 0;
}

Vamos a por las respuestas. Entre a y b no hay ninguna diferencia, ambas valen 3.1416. Sin embargo, el caso de pi y PI es diferente. Tanto PI como pi son invariantes, no puede editarse su valor, pero pi es una variable global y PI “es un define” que, si os fijáis, no podríamos decir siquiera si es un float u otra cosa, porque no lo pone. Tal y como he dicho antes, en todos los lugares del código donde ponga PI pondrá 3.1416 después del preprocesado, pero no pasará lo mismo con pi que es una variable con su pedacito de memoria, que se cargará con ese valor y, después, b será igualada con él. Por eso es importante evitar escribir constantes como pi si lo que realmente queremos algo literal.

Como digo, el código mostrado es completamente equivalente a no definir PI y poner 3.1416 en su lugar.

También es interesante que, si definiésemos el tamaño de un array con un const int size;, como hemos hecho con pi el compilador podría reirse de nosotros y no dejarnos porque por muy const que sean, los arrays no pueden tener longitud de variable en algunos estándares de C. Un define sí que nos sirve, porque no es una variable sino una sustitución literal de texto. Sacaría un error de esta pinta2 si estuviésemos compilando en modo estricto:

warning: ISO C90 forbids variable length array

Por otro lado, si lo que queréis es borrar la definición de algo que hayáis definido antes lo que estáis buscando es #undef.

Include

Include, tan simple como define, sirve para incluir mierdas. Su movida es coger el archivo que le indicamos y a lo brutus meterlo ahí donde aparece el include. Más o menos.

Hay dos formas de usar el include:

#include<archivo>
#include"archivo"
  • La primera de las que muestro utiliza <> para cerrar el nombre del archivo a incluir. Esto sirve para incluir archivos desde los directorios habituales, en linux /usr/include/ entre otros. Esto significa que el sistema automáticamente buscará en esos directorios (llamados include path) el archivo que queremos incluir. Con el compilador GCC, el include path puede ser editado a la hora de compilar añadiendo -I seguido de la ruta al directorio que queremos incluir. Haciendo esto, el directorio añadido sería incluido en el path y sus archivos podrían ser objeto de un #include que use <>.

  • La segunda manera usa "" o comillas dobles. Este include busca el archivo a incluir partiendo del directorio en el que se encuentra el archivo que tiene el include.

Normalmente el primer modo se utiliza para incluir archivos independientes a la solución, archivos aportados por el sistema. Cabeceras de librerías externas, por ejemplo. El segundo modo suele servir para incluir archivos de cabecera del propio proyecto.

Pragma

Pues #pragma ya no es tan evidente, pero no por ello es menos sencillo. Sirve para darle indicaciones al compilador, marcándole unos parámetros. Yo no la he visto muy a menudo, sobre todo la he visto a la hora de programar microcontroladores en C. Os pongo un ejemplo de un Microchip PIC18F45503:

// Microchip PIC PIC18F4550
#pragma config WDT = OFF //Disable watchdog timer

Las directivas pragma no son una parte del lenguaje C en realidad, son unos datos para el compilador y cada compilador tiene las suyas, por eso al programar microcontroladores tenemos algunas especiales.

Si el compilador que usamos no reconoce la directiva pragma la ignora y no avisa, cuidado con eso.

Error

Error sirve para marcar un error y abortar la compilación. Si en algún momento el preprocesador llega hasta un #error la compilación se abortará con el mensaje que hayamos puesto. Ejemplo cortito y al pie:

#error Pues parece que algo ha ido mal

Como he dicho antes, estas cosas ocurren al preprocesar, así que no puedo hacer esto:

// WTF, this is wrong
if (codigo_error != 0){
#error Sal con error
}

No mezclemos preprocesado con código C por favor.

Ifdef, ifndef, y cambios de flujo

Claro, si habéis visto que se puede abortar la compilación, os habréis quedado esperando que haya una manera de que el preprocesador esquive esos #error para que no aborte. Pues la hay. Las directivas que os muestro sirven para incluir o quitar código de forma condicional. Si la condicional no se cumple, el efecto del bloque no va a verse ni compilarse ni nada, ese texto, ese código, no va a existir para el compilador.

Os pongo la lista de convocados para este bloque:

#ifdef, #ifndef, #if, #endif, #else y #elif

Y un ejemplo para que veáis como irían con los #error:

#ifndef _cplusplus
#error C++ es obligatorio
#endif

En este ejemplo se abortaría la compilación si no se hubiese definido la constante _cplusplus que viene definida en todos los compiladores de C++. Es decir, sólo permitiría compilar este código fuente si el compilador es de C++.

Y este sería un ejemplo bestia quitando código fuente del medio, basándose en lo mismo:

#ifdef __cplusplus
extern "C" {
#endif

... CÓDIGO C AQUÍ...

#ifdef __cplusplus
}
#endif

Haciendo esto tendíamos un programa en C, que podría ser compilado en C++ porque se añadiría extern "C"{} alrededor de él si el compilador fuera de C++. Si fuese compilado en un compilador de C, éste ni se enteraría del extern.

Line

De esto no os voy a hablar mucho porque la he encontrado mientras preparaba la entrada4 pero nunca lo había visto. Sirve para cambiar el mensaje de error en caso de que algo esté mal en el código. Cambiaría nuestro número de línea y/o el nombre de archivo. Cuando encuentra la directiva #line cuenta el número de línea desde el número asignado en adelante. Se usa así:

#line NUMERO_LINEA "Nombre de archivo"

 

Y punto. Por mi parte he terminado, esto es todo lo que sé del tema. Si tenéis preguntas, para eso está la sección de comentarios más abajo. Os dejo, como siempre, un pequeño listado de links interesantes:

Creo que con esto tenéis investigación para rato, ¿no?

Pues nada, os dejo con ello. Espero que hayáis aprendido algo nuevo, porque yo he aprendido bastante preparando esta entrada y he afianzado conocimientos.

¡Quitadle el miedo a la parte sostenida de C1!

Un abrazo.


  1. En música, el símbolo del “sostenido” se marca con una almohadilla, como las directivas del preprocesador de las que hablo. 
  2. C90 es el estándar de C de 1990. Se definen con los dos últimos dígitos del año, así que C16 sería el de este año 2016 y C89 sería el de 1989. No por ser más grande tiene que ser mejor, que hace overflow. 
  3. Ahí os dejo un superdocumento de las configuraciones de los Microcontroladores PIC para que veáis que directivas pragma permiten:
    http://ww1.microchip.com/downloads/en/devicedoc/C18_Config_Settings_51537f.pdf&#160;
  4. Sí amigos, a veces me preparo las entradas. No siempre uso el teorema del Mono infinito

Vim para escribir

Muy buenas,

Hoy vengo otra vez con mis dotfiles, de los que ya hablé en una entrada anterior pero quiero tocar un poco en concreto el caso de Vim.

Veis la estructura de directorio aquí:

~/projects/dotfiles/vim (master)$ tree . -a
.
├── .vim
│   ├── ftplugin
│   │   ├── css.vim
│   │   ├── c.vim
│   │   ├── groovy.vim
│   │   ├── html.vim
│   │   ├── javascript.vim
│   │   ├── markdown.vim
│   │   ├── perl.vim
│   │   ├── python.vim
│   │   ├── sh.vim
│   │   └── tex.vim
│   └── spell
│       ├── en.utf-8.spl
│       ├── en.utf-8.sug
│       ├── es.utf-8.spl
│       └── es.utf-8.sug
└── .vimrc

Y podéis navegar aquí:

https://github.com/ekaitz-zarraga/dotfiles/tree/master/vim

Bien partiendo de esto entro un poco a lo que os quiero contar. En lugar de tener modos de ejecución como puede tener Emacs, yo baso mi configuración en el tipo de archivo que estoy editando. Hay muchas formas más de hacerlo, es lo bueno de esto, si tenéis otras me comentáis y las investigo.

Para poder gestionar todo basándome en el tipo de archivo utilizo el plugin filetype que automáticamente cargará los archivos de la carpeta ftplugin dependiendo del tipo de archivo que se abra. Normalmente se basa en la extensión, aunque sabemos que en UNIX no hacen falta, al programar se utilizan y a mí me gusta mantenerlas para saber qué tipo de archivo tengo sin tener que abrirlo (cuando no añado extensión considero que es texto plano sin marcado).

Bien ahora al grano, quiero hablaros del archivo que define el tipo MarkDown. Seguro que ya he hablado de MarkDown antes (aquí, y aquí, por ejemplo) así que no digo nada más del tema. Lo que quiero mencionar es que lo uso para escribir, tanto documentación como texto normal, por lo que me gusta que quede bonito y bien. Me interesa porque puedo convertir a PDF, HTML o cualquier otro formato manteniendo una gran legibilidad en el archivo fuente de MarkDown. Para no perderte en la sintaxis como puede pasar en LaTeX (que también me gusta pero sufre mucho de este efecto, leer fuente se vuelve complicado) y para mantener una experiencia de escritura agradable, trato de mantener varias cosas. Os las desgloso en desde el archivo markdown.md:


Líneas de 80 caracteres como máximo

Así los párrafos no son infumables líneas únicas cuando muestras el archivo. Para enlaces y otro tipo de cosas hay excepciones.
En MarkDown los saltos de línea únicos no se consideran, por lo que nuestro archivo puede tener saltos para hacer el texto más estrecho sin afectar al resultado.
Es cierto que en las tablas afectarían y en otras cosas también, pero se puede desactivar la opción para esos casos.

Esto se realiza de la siguente manera:

" Textwidth for automatic wrap `gq` is formatting operation
setlocal textwidth=79
setlocal formatoptions+=t
setlocal formatoptions-=l

Y además, añado una linea vertical verde para saber cuándo me estoy pasando:

" Highlight where the lines are more than 80 characters wide
setlocal colorcolumn=80
highlight ColorColumn ctermbg=LightGreen

Comprobación de ortografía

Ya hablé de esto aquí.

" Spellcheck in markdown (automatic to english)
setlocal spelllang=en
setlocal spell

Mayúsculas automáticas

Esto se debe a un pique con mi hermana, que me dijo que hay un modo de mayúsculas automáticas en Emacs, e incluso lo publicó en su blog. Pues también se puede hacer en Vim, aunque no es una cosa por defecto, puede configurarse.

" Auto-capitalize script
augroup SENTENCES
au!
autocmd InsertCharPre * if search('\v(%^|[.!?]\_s+|\_^\-\s|\_^title\:\s|\n\n)%#', 'bcnw') != 0 | let v:char = toupper(v:char) | endif
augroup END

Este caso, como casi todo, está cogido de internet. Este lo explico menos y os enseño la fuente porque lo he añadido hace muy poco y no es tan evidente. Esta es la fuente. Básicamente captura las teclas y si la anterior es un punto o encuentra un cambio de párrafo cambia la letra pulsada a mayúsculas.

Syntax Highlighting de Markdown

Nada que decir, te marca con colores lo que haces o te formatea el texto un poco. Muy poco pero ayuda para saber si lo has puesto bien y ayuda a leer, aunque no hace falta. Esta entrada la estoy escribiendo en el editor de wordpress en Markdown y no tengo highlight.

setlocal syntax=markdown

No hay mucho que decir de esta parte del archivo, la verdad. Bastante evidente.

Cosas genéricas para todos los lenguajes

Esto se encuentra en el archivo .vimrc porque es genérico.

Marcado en rojo de los Trailing Spaces y eliminación de sobrantes.

highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()

Highlight en búsquedas.

" HighLight search and map CarrierReturn to remove highlight
set hlsearch
nnoremap :noh

Las tabulaciones

Me las coge de forma automática así que no las he configurado, pero suelo hacerlo en el resto de lenguajes.
Están configuradas a dos espacios. Como se suele hacer en HTML u otros. Podría ser algo así:

set tabstop=2 softtabstop=0 expandtab shiftwidth=2
set autoindent

Con esta configuración puedo escribir bastante tranquilo. Podría añadir cosas seguramente pero de momento voy bastante bien. Voy añadiendo cuando se me ocurren o me cuentan y va creciendo, creo que es la mejor manera.

Así da gusto escribir documentos de texto, la verdad.

Espero que os guste por lo menos el enfoque. Recordad, la entrada es estática pero los links no, puede que si venís otro día el archivo de configuración haya cambiado y no coincida con esto.

Si se os ocurren más cosas, tenéis la sección de comentarios más abajo.

Un saludo.

No os pongo links, creo que tenéis para investigar un rato sólo con lo que hay. 😉

GitHub Pages, Markdown y mi CV

Hola hijos,

No sé si llegué a mencionarlo por aquí pero desde hace tiempo tengo ganas de poner mi currículum vitae online, en un sitio propio o similar, de forma que lo pueda actualizar con facilidad.

Y lo he hecho.

Para hacerlo me hice uno rellenando los campos de Stack Overflow Careers, que están muy bien y lo exporté a MarkDown usando sus herramientas. Desde ese archivo en MarkDown hice varios cambios y fui creando un proyecto en GitHub para poder tenerlo todo bajo control de versiones. Aquí lo tenéis.

Veréis que tiene un curioso árbol de directorios y un MakeFile. Os lo muestro aquí hecho con un tree para que no tengáis que andar navegando:

.
├── Curriculum.md
├── formats
│   ├── Curriculum.html
│   └── Curriculum.pdf
├── index.html
├── Makefile
├── Readme.md
└── style
    └── style.css

2 directories, 7 files

Curriculum.md tendría lo que es el contenido del currículum vitae. Al ser MarkDown el propio GitHub es capaz de renderizarlo, pero si queréis ver el original le dáis a RAW en la esquina superior derecha y lo ojeáis un poco.

El Makefile es para construir los archivos Curriculum.pdf y Curriculum.html de forma automática desde el MarkDown. Está basado en un MakeFile genérico que tengo para documentación, del que hablé en otra entrada anterior. Tiene un par de cosas extra, como que use un archivo CSS para crear el HTML más bonito.

El CSS lo tenéis en la carpeta style, es un archivo extremadamente simple que vale para darle un poco de formato a la página y que no quede como HTML limpio, que es bastante feo. Creo que un poco de magia sí que le he conseguido aportar.

Ahora lo interesante de todo esto.

Para los que no lo conocéis, GitHub tiene una cosa que se llama GitHub pages. Resulta que si tienes una rama llamada gh-pages en tu repositorio, automáticamente te genera una página estática a éste, para que puedas tener una página web de tu proyecto de software con documentación o lo que sea. En mi caso sirve para poder tener una página con mi currículum. Podríamos añadir JavaScript si quisiéramos, pero no podríamos poner ningún Server Side Scripting, aunque no nos hace ninguna falta en nuestro caso.

Para acceder al proyecto como página web en lugar de ir al path habitual, (que sería algo así como github.com/usuario/proyecto) tendremos que acceder así:

usuario.github.io/proyecto

Ahora si accedéis a http://ekaitz-zarraga.github.io/cv veréis el index.html y desde ahí podréis acceder a la versión HTML del currículum o descargaros la versión en PDF.

No tengo intención de que la gente acceda al índice, pero lo mantengo por si alguien llega al link corto y quiere descargarse la versión en PDF o lo que sea.

Lo bueno de prepararlo todo así es que tengo todo bajo control de versiones, que genero los archivos HTML y PDF sólo haciendo un make all o, simplemente, make y que tengo un sitio concreto donde poder mantenerlo, con una URL relativamente simple y clara.

Espero que os guste.

Es mi currículum pero lo mismo podría ser un proyecto de software con su documentación o lo que fuera.

Probad cositas con GitHub pages.

Os dejo un par de links interesantes:

Y eso es todo, si tenéis algún comentario sobre cómo he creado esto, mi currículum, o lo que sea, no os cortéis.

¡Un abrazo!

Vim, ese pedazo de editor

Hola hijos,

Hoy he estado profundizando un poco en Vim y he estado viendo algunos vídeos en youtube sobre ello. El tema es que lo utilizo constantemente como editor, pero me siento un poco limitado con el partido que le saco así que estoy investigando para subir un poco el nivel. Sí que es cierto que, en general, cuando me paso a otro editor diferente tengo problemas porque intento ejecutar teclas rápidas que no existen y trabajar con los diferentes modos de Vim, pero un poco más de manejo me haría mucho más eficiente. En fin.

Hoy voy a hablaros un poco de Vim.

Vim es un editor de texto plano muy potente, principalmente se usa para programar o para editar simples archivos de texto (esta entrada ha sido escrita en Markdown usando Vim). Como originalmente fue diseñado para trabajar en una terminal, aunque también hay versiones con interfaz de escritorio (aunque no se usen tanto como el original), está completamente orientado a usar el teclado de la forma más eficiente. Esto significa que el plan del desarrollador es que nunca tengamos que apartar las manos de las letras del teclado. De esta forma podemos centrarnos en escribir y no en coger el ratón para movernos etc. Para conseguir esto se basa en un par de conceptos básicos:

  • Diferentes modos de ejecución.
  • Millones de teclas rápidas.

Modos:

Vim dispone de 4 modos de ejecución:

  • Modo normal: Es el modo habitual donde se ejecutan casi todos los comandos, se navega por el archivo, etc.
  • Modo insertar: No hay comandos que valgan aquí. Este es el modo de edición, lo que se teclea va al contenido del archivo.
  • Modo visual: Es un modo para seleccionar texto, tiene varios modos: por línea, por bloque y por carácter.
  • Modo ejecución: Parecido a ejecutar órdenes en el modo normal en la línea de comandos (:) pero este modo no nos devuelve al modo normal al ejecutarlos. Sirve para hacer procesamiento, etc. Investigad un poco, es un poco más complicado y está fuera del alcance de este artículo.

En general, el modo normal será el modo en el que siempre estemos y tendremos que movernos a los otros desde él.

Si quisiéramos activar el modo visual serviría pulsando la tecla v (de visual) y entraríamos en el modo, para salir, pulsar ESC. Como he dicho, visual tiene varios modos, la v sólo activa el de caracteres, el normal, el de bloques se activa con CTRL+v y el de línea con SHIFT+v.

Lo mismo pasa con el de edición, hay muchos modos de entrar a él. Se puede entrar añadiendo una linea debajo de la actual (o) o encima (O), escribiendo caracteres en la posición del cursor (i) o en la siguiente (a), al final de la línea (A) o al principio (I), etc (más abajo hay un enlace de todos estos comandos). Todos nos llevan al modo insertar pero a diferente posición. Para salir, ESC, como desde  visual.

El modo ejecución es más loco, para entrar hay que pulsar Q (mayúscula, sí) y, para salir, escribir visual, aunque, si estáis empezando no os recomiendo que entréis porque senos suele olvidar cómo salir y probamos de todo. Sabiendo esto, los desarrolladores han añadido una línea que te dice cómo salir cuando se ve que tienes problemas. 😉

Teclas rápidas:

Las teclas rápidas se utilizarán en los modos normal y visual. Definen millones de operaciones diferentes, que pueden ser concatenadas, guardadas en macros, repetidas, etc. Es extremadamente complejo pero muy potente.

Estas teclas pueden servir para navegar por el fichero (como h,j,k,l), borrar (d), cambiar de modo (i, a, v), copiar (y), pegar (p), grabar macros (q), repetir la última operación (.) y millones de cosas más. Además, estas teclas pueden combinarse para hacer cosas más complicadas añadiendo repeticiones (como borrar 10 líneas d10d) o utilizando indicadores que indicarán desde dónde hasta dónde queremos utilizar la orden (como borrar un párrafo con: delete in paragraph dip), llamados “motions”.

A parte de esto, podremos buscar o sustituir por el archivo usando / o ejecutar órdenes más complejas usando : o entrando al modo de ejecución.

El chorro de teclas que menciono es extremadamente pequeño en comparación con lo que existe, pero lo que tienen en común es que nunca te obligan a apartar los dedos del teclado permitiéndote ser rápido como el rayo.

Podéis ver más en internet o en la ayuda de Vim (:help). Aquí os dejo una chuleta:

http://bullium.com/support/vim.html

Extras:

Pero eso no es nada. Vim puede configurarse hasta el infinito y más allá. Pueden añadirse módulos, scripts y configuraciones que hagan que el editor se ajuste a nuestras necesidades. Desde comprobación de sintaxis y ortografía, hasta un módulo de XMPP o plugins para postear en WordPress.

Además permite navegar por tus archivos, abrir diferentes pestañas, ejecutar órdenes en la terminal y muchísimas más cosas.

¿Por qué Vim?

La pregunta es, entonces: ¿Por qué usar Vim si es tan complicado?

Básicamente por eso.

La complicación que tiene permite que lo llevemos al extremo en la dirección que nos interese o que lo configuremos de forma diferente dependiendo de lo que estemos haciendo. Es una locura.

Como ya he mencionado antes, nos hace realmente eficientes también y eso siempre es interesante, tanto al escribir como al programar.

Como me gusta, seguiré escribiendo cosas al respecto, espero que os parezca interesante. Os animo a que lo probéis.

Un abrazo.


He hablado de Vim en otras entradas aunque sea de pasada, aquí las tenéis:

De configuraciones y puntos

Hola chiquillos,

Este título extraño viene porque voy a hablar de archivos de configuración para sistemas UNIX (como tu GNU-Linux favorito). Muchos programas, como Vim, Bash, Git, Tmux, etc. utilizan archivos ocultos en nuestra carpeta personal para guardar su configuración.

Como, muchos ya sabréis, los archivos ocultos en UNIX empiezan por un punto. Por ejemplo: ‘.vimrc’, ‘.bash_aliases’, etc1. Es por eso que a estos archivos de configuración se les conoce como Dotfiles2.

En general, estos archivos definen el comportamiento de los programas y toda la personalización que el usuario ha hecho, por lo que son relativamente importantes. Perderlos puede desatar el pánico si tu sistema tiene una configuración complicada.

Para evitar situaciones desagradables suelen mantenerse bajo control de versiones (ya que son archivos de texto plano generalmente3) y esto es lo que quería explicar hoy.

Ya he mencionado alguna vez sistemas de control de versiones (creo que he hablado de Git, pero hay otros: Subversion, Mercurial…) así que me voy a saltar un poco esa parte y os voy a dejar un link a mis propios dotfiles en GitHub donde podéis ver como configuro yo algunas de mis cosas y podéis copiar, aportar ideas o preguntar por qué, etc:

https://github.com/ekaitz-zarraga/dotfiles

Haciendo esto, tendríamos nuestros dotfiles bajo control de versiones en un servidor externo, por lo que podríamos recuperarlos si se nos borran, podríamos copiarlos en otro equipo con facilidad, o podríamos ver cómo han ido evolucionando con el tiempo y podríamos ir atrás en cambios que hayamos hecho. Todo ventajas.

Sin embargo, como veis, el orden de estos archivos no es como deberían estar en nuestra carpeta personal, si no que aquí están agrupados por programa. Aquí es cuando entra una herramienta superchula llamada Stow.

Stow es un gestor de symlinks o enlaces simbólicos con el que podemos crear referencias a nuestros archivos en la carpeta personal para que el sistema pueda acceder a nuestro proyecto con los dotfiles a través de ellas. Podríamos también hacer los links a mano pero es un poco coñazo (comando ln).

Si vamos nuestra carpeta con los dotfiles y lanzamos Stow, añadiendo el directorio donde queremos añadir los enlaces (en nuestro caso el directorio personal, es decir, ~) nos creará enlaces al lugar, tal que así:

dotfiles$ stow vim -t ~
dotfiles$ ls -la ~
26 Dec 19 23:37 .vim -> projects/dotfiles/vim/.vim
28 Dec 19 23:37 .vimrc -> projects/dotfiles/vim/.vimrc
...

(He resumido la salida del comando ls para que podáis verlo mejor)

De esta forma, nuestra configuración quedará ordenada en nuestra carpeta con los dotfiles y en nuestra carpeta personal referenciaremos ahí.

Esto es muy interesante porque, por ejemplo, si hacemos cambios en nuestra configuración en el trabajo porque hemos añadido alguna característica, con hacer un git pull en casa ya tendríamos la misma configuración y no tendríamos que volver a editar los dotfiles en nuestro directorio personal porque ya estarían haciendo referencia a los que manejamos con el sistema de control de versiones.

Y simplemente quería contaros un poco esto y ya de paso hacer que investiguéis cosas interesantes a cerca de los sistemas UNIX que hemos tocado para hacer esto. Recapitulando:

  • Archivos ocultos.

  • Hard and soft links.

  • Control de versiones.

  • Filosofía UNIX y los archivos de texto plano.

Investigad un poco y me contáis. 🙂

Además, más arriba os he dejado el link a mis dotfiles, podéis mirar un poco y sugerirme mejoras, preguntarme cosas, o lo que queráis.

Un abrazo.


  1. Podéis verlos haciendo un ls -a por ejemplo. Os dejo un link de la wikipedia que explica un poco más
  2. Ya sabéis, inglés y esas cosas: Dot => Punto. File => Archivo. 
  3. Eso es parte de la filosofía UNIX. Ficheros de texto plano everywhere.