Una odisea de depuración top-down con Vim.

Jrnl

Jrnl es un proyecto que permite a las personas llevar un diario desde la línea de comandos. Proporciona una plataforma segura y fácil de usar para escribir y organizar tus pensamientos, recuerdos y experiencias.

Por otro lado, Termux es una aplicación de terminal de código abierto para dispositivos Android que permite a los usuarios ejecutar comandos y acceder a un entorno similar a una terminal de Linux en sus dispositivos móviles.

En este post, describiré el proceso que seguí para configurar un número de columnas fijo cuando VIM abriese ficheros de tipo JRNL y así escribir desde el teléfono gracias a termux. Y cómo durante el proceso encontré un bug en una biblioteca externa que acabé corrigiendo

Yo utilizaba VIM con mi configuración antigua de ~/.vimrc, conteniendo la siguiente línea:

au BufRead,BufNewFile *.txt setlocal tw=50

El problema consistía en que ahora mi ~/.vimrc venía dado por Vim-bootstrap, un generador de configuraciones de Vim.

Investigando, descubrí un método para ver el fichero en el que una variable en VIM fue asigada por última vez.

:verbose set tw

Así pues, en nuestro caso es el vim.vim del ftplugin. Por cierto, para cargar el .vimrc sin reiniciar VIM se puede usar :so ~/.vim/vimrc o si se está en el propio archvo :so %.

Si no usamos el archivo ~/.vim/vimrc de Vim-Bootstrap, podemos trabajar más facilmente con la depuración de VIM.

Cómo no era capaz de encontrar el fallo, acabé preguntando en Stackoverflow. Donde comuniqué lo que había intentado y cuál era mi hipótesis.

Tuve la suerte de que me respondieran e intenté reproducir sus instrucciones:

Escribo en ~/.vimrc:

au BufRead, BufNewFile jrnl*.txt set filetype=jrnl

Añado en la carpeta ~/.vim/ftplugin

set formatoptions+=t
set textwidth=50

Entonces, comenté todos los plugins y compruebo que funcionaba sin los plugins de Vim-bootstrap. Posteriormente, fui añadiendo uno a uno los plugins para encontrar el que generaba el problema.

¡Capturé la biblioteca culpable! El plugin requirements.txt.vim era el encargado de sobreescribir la configuración. Cuando está activo, Vim no llama ~/.vim/after/ftplugin/jrnl.vim

Inspeccionando el código de requirements.txt.vim vemos que la línea 37 contiene lo siguiente:

au BufNewFile,BufRead *.{txt,ini} if
s:isRequirementsFile() | set ft=requirements

Es decir, que la función isRequirementsFile() es llamada cada vez que se ejecuta un *.txt.

function! s:isRequirementsFile()
     let l:filename = expand("%:p")

    return Requirements_matched_filename(l:filename)
endfunction

function! Requirements_matched_filename(filename)
    if a:filename =~# '\v.*require(ment)?s\.(txt|in)$'
        return 1
    endif

    if a:filename =~# '\vrequire(ment)?s/.*\.(txt|in)$'
        return 1
    endif

    if a:filename =~# '\vconstraints\.(txt|in)$'
        return 1
    endif

    if len(g:requirements#detect_filename_pattern)
        \ && a:filename =~# g:requirements#detect_filename_pattern
         return 1
     endif

     return 0
endfunction

Como vemos, esta función crea una variable filename que contiene la ruta completa del archivo. Devuelve el resultado de aplicarle la función Requirements_matched_filename a la ruta. Comprobamos que la función isReq devolvía 0. Por lo tanto, el bug parecía inencontrable...

Fue entonces cuando se me ocurrió la, quizás obvia pero efectiva, idea de leer la documentación de la sintaxis de vim y nos sorprendemos al ver que a la instrucción

au BufNewFile,BufRead *.{txt,ini} if 
    s:isRequirementsFile() | set ft=requirements

¡le faltaba un endif!

au BufNewFile,BufRead *.{txt,ini} if
 s:isRequirementsFile() | set ft=requirements |
endif

En efecto, la simple ausencia de un endif en uno de los plugins de configuración estaba sobreescribiendo nuestra orden.

Luego, me propuse a escribir un Pull Request que fue aceptado inmediatamente.

Comentario del futuro: La nueva versión de JRNL abre los archivos en formato .jrnl. Ahora basta con cambiar el au BufNewFil a *.jrnl para obtener el mismo efecto.