An Interest In:
Web News this Week
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
- March 26, 2024
vim y el quickfix list: saltar a una ubicacin, buscar y reemplazar en mltiples archivos, y otras curiosidades
En esta ocasin cubriremos una funcionalidad avanzada de vim, la lista de cambios rpidos, A.K.A. the quickfix list. Aprenderemos cmo usarla para buscar (y reemplazar) un patrn en mltiples archivos y tambin para saltar rpidamente a la ubicacin de un error generado por un comando externo.
Quickfix list
Es una modalidad especial de vim en donde se muestra una lista de posiciones, es decir filas y columnas en un archivo. El propsito de esta lista es guardar las posiciones que se encuentran en los mensajes de error que genera un compilador. De esta forma uno puede saltar rpidamente a esta ubicacin, arreglar el problema y luego ir al siguiente o intentar compilar nuevamente.
Puede que suene como una funcionalidad limitada, pero no teman, como todo en vim hay ms de lo que aparenta a simple vista. Esta lista de cambios puede generarse por varios mtodos. Para empezar tenemos algunos comandos que pueden generarla automticamente, entre ellos est :make
, :vimgrep
y :grep
. Adicionalmente, es posible generarla de manera programtica usando la funcion setqflist
, lo que nos da una flexibilidad increble.
Debo mencionar que cuando hablo del quickfix list me refiero solamente a la lista de posiciones, deben saber que esta lista puede mostrarse de dos formas. Tenemos el quickfix window
y el location list
. Estas son bsicamente "ventanas" donde se muestra la lista de posiciones. El quickfix window
es "global", es decir que slo podemos tener una en la sesin activa de vim. Por otro lado, podemos tener mltiples location list
asociados a diferentes ventanas en una misma sesin.
Saltar a una ubicacin
Para comenzar vamos a explorar el comando :make
, es la manera en la que vim invoca un compilador. El nombre les parece familiar? Eso es porque vim asume que estaremos trabajando con la herramienta make
. Pueden hacer una prueba si lo tienen instalado en su sistema. Crean un archivo llamado Makefile
y colocan lo siguiente:
.PHONY: test otratest: @echo 'hola'otra: @echo 'otra'
No cubrir en detalle cmo funciona
make
pero si quieren saber cmo utilizarlo para automatizar tareas pueden leer este artculo (en ingls).
Al invocar el comando :make
deberan obtener algo como esto.
hola(1 de 1): hola
Por defecto make
ejecutar la primera "tarea" que vea en nuestro Makefile
. Bien, pero entonces Cmo hacemos para ejecutar otra
? Podemos proveer ms argumentos al comando, de esta manera :make [argumento]
. Si intentan ejecutar :make otra
deberan ver esto.
otra(1 de 1): otra
Interesante, pero esos comandos no generan ningn error. Despus de ver estos mensajes no ocurre nada.
Ya que vim sabe cmo "leer" los errores del compilador gcc
vamos a ver un ejemplo usando el lenguaje C.
Un ejemplo en C
Creamos un archivo llamado hello.c
, en l ponemos el siguiente contenido.
#include <stdio.h>int main() { printf("Hola, Mundo!
"); return 0;}
Aqu no hay ningn error. Podemos compilar y ejecutarlo tranquilamente usando make
. As que el siguiente paso ser crear un Makefile
.
.PHONY: run-hellorun-hello: gcc -Wall -o hello hello.c ./hello rm ./hello
Todo est en su lugar. Ahora podemos ejecutar el comando :make --silent run-hello
. Si todo sale bien vim les mostrar su hola mundo
.
Hola, Mundo!(1 de 1): Hola, Mundo!
Si introducimos un error esto es lo que deberamos obtener.
hello.c: In function main:hello.c:4:28: error: expected ; before return printf("Hola, Mundo!
") ^ ; return 0; ~~~~~~make: *** [Makefile:7: run-hello] Error 1(2 de 8): error: expected ; before return
Luego de ver el mensaje notarn que vim los llev automticamente a la ubicacin del error (no es genial?). Para visualizar el quickfix window
tenemos que ejecutar el comando :copen
, el cual debera mostrarle esto.
|| hello.c: In function main:hello.c|4 col 28| error: expected ; before return || printf("Hola, Mundo!
")|| ^|| ;|| return 0;|| ~~~~~~make: *** [Makefile|7| run-hello] Error 1
Para cerrar el
quickfix window
se utiliza el comando:cclose
.
Presten atencin a esta lnea.
hello.c|4 col 28| error: expected ; before return
Aqu vim nos est sealando el archivo, la lnea y la columna donde gcc
dice que est nuestro error, as como tambin el mensaje de error. Es en este punto donde arreglamos el desperfecto e intentamos compilar nuevamente. En su mayora ese sera el flujo de trabajo que queremos cuando usamos el quickfix list.
Muy bonito, y qu pasa si no usamos gcc
? Y si normalmente trabajamos con Node.js
? vim podra manejar eso tambin? S, con algo de ayuda.
errorformat
Si empiezan a experimentar con diferentes compiladores e interpretes se darn cuenta rpidamente que vim no puede leer de manera apropiada todos los tipos de errores. Para sobrepasar esta limitacin vim nos ofrece algo llamado errorformat
, una variable con la cual podemos especificar el formato del error que genera un comando externo, de esta forma vim puede reconocerlo cuando se encuentre en el quickfix list.
Ahora intentemos hacer que vim entienda los errores que genera node
. Vamos a crear un archivo llamado greeting.js
, en l vamos a tener un "hola mundo" con un error.
console.log(greeting);const greeting = 'Hola, Mundo!';
En nuestro habitual Makefile
creamos otra tarea.
run-greeting: node ./greeting.js
Si ejecutamos :make --silent run-greeting
obtendremos este resultado.
console.log(greeting); ^ReferenceError: Cannot access 'greeting' before initialization at Object.<anonymous> (/tmp/test/greeting.js:1:13) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) at internal/main/run_main_module.js:17:47make: *** [Makefile:4: run-greeting] Error 1
vim intentar llevarnos al lugar donde est el error pero probablemente falle miserablemente. En mi caso particular, me lleva a un archivo que no existe.
Para arreglar esto tenemos que decirle a vim cmo leer ese mensaje. Una manera de hacerlo sera esta.
set errorformat=%E%.%#ReferenceError:\ %m,%Z%.%#%at\ Object.<anonymous>\ (%f:%l:%c)
Lo que hacemos es especificar qu "forma" tiene cada linea en el mensaje error. Cada linea tiene su propio formato y debemos separarlos con una coma. Entonces tenemos que.
%E%.%#ReferenceError:\ %m
Y
%Z%.%#%at\ Object.<anonymous>\ (%f:%l:%c)
Son dos expresiones distintas que le dicen a vim cmo leer el error. Le estoy diciendo dnde puede encontrar el tipo de error (ReferenceError
) y dnde est la informacin sobre la ruta y la ubicacin del error. Ya que esas dos piezas de informacin se encuentran en dos lineas diferentes debo tener dos expresiones separadas por una coma.
Para mejorar la legibilidad tambin podemos escribirlo de esta manera.
set errorformat=%E%.%#ReferenceError:\ %mset errorformat+=%Z%.%#%at\ Object.<anonymous>\ (%f:%l:%c)
Noten que as no tenemos que colocar la coma al final de cada expresin. Pero an tenemos que colocar un \
antes de cada caracter que vim considere especial (como un espacio en blanco) para no generar un conflicto entre la sintaxis de vim y el formato del error. An hay otra forma que tambin podemos usar.
let &errorformat = \ '%E%.%#ReferenceError: %m,' . \ '%Z%.%#at Object.<anonymous> (%f:%l:%c)'
Al usar let
tenemos la posibilidad de crear nuestro formato usando una cadena de texto, sin generar conflictos entre vim y el errorformat
. Para mejorar la legibilidad he puesto cada expresin en su propia linea tomando ventaja del operador .
para concatenar cadenas de texto.
Ahora al intentar ejecutar :make --silent run-greeting
vim debera llevarnos al lugar exacto donde node
dice que est el error. Y en el quickfix window
debera mostrarnos esto.
|| /tmp/test/greeting.js:1|| console.log(greeting);|| ^|| greeting.js|1 col 13 error| Cannot access 'greeting' before initialization|| at Module._compile (internal/modules/cjs/loader.js:1063:30)|| at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)|| at Module.load (internal/modules/cjs/loader.js:928:32)|| at Function.Module._load (internal/modules/cjs/loader.js:769:14)|| at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)|| at internal/main/run_main_module.js:17:47|| make: *** [Makefile:4: run-greeting] Error 1
Noten que ya no aparece ReferenceError
, y tampoco la lnea que va debajo. Esa parte especfica del mensaje ha sido reemplazada por esto.
greeting.js|1 col 13 error| Cannot access 'greeting' before initialization
Si les aparece as es porque el formato en el errorformat
funcion.
Pero tenemos un problema, y es que esas dos expresiones slo funcionaran con el tipo de error ReferenceError
. Si queremos abarcar otros tipos de errores haramos algo como esto.
let &errorformat = \ '%E%.%#AssertionError %m,' . \ '%E%.%#TypeError: %m,' . \ '%E%.%#ReferenceError: %m,' . \ '%E%.%#SyntaxError: %m,' . \ '%E%.%#RangeError: %m,' . \ '%Z%.%#at Object.<anonymous> (%f:%l:%c),' . \ '%-G%.%#'
Tokens especiales
Ahora probablemente quieren saber sobre la sintaxis que he usado en este formato. Especficamente, qu son todos esas cosas con %
. Vamos a dar un repaso sobre esos "tokens" especiales.
%f
: Indica la ubicacin de la ruta del archivo donde se encuentra el error.%l
: Indica la lnea donde se encuentra el error.%c
: Indica la columna donde se encuentra el error.%m
: Se usa para indicar la ubicacin del contenido del mensaje. En nuestro ejemplo lo usamos para asignar la cadena de texto que viene inmediatamente despus del tipo de error.%E
: Indica el inicio de un mensaje de error que abarca mltiples lneas. La letraE
le dice a vim que esto es un error. Tambin podemos sealar mensajes de advertencia (%W
), mensajes informativos (%I
) generales (%G
).%Z
: Indica que es la ltima lnea del mensaje.%.%#
: Esto es un comodn, bascamente coincide con todo. En otras palabras, significa "cualquier cosa." Por ejemplo, la expresin%Z%.%#at Object.<anonymous> (%f:%l:%c)
puede leerse de la siguiente forma: La ltima lnea de este mensaje (%Z
) puede comenzar con cualquier cosa (%.%#
) seguido deat Object.<anonymous>
y entre parntesis el archivo (%f
), un nmero de lnea (%l
) y la columna (%c
).%-
: Le indica a vim que no debe incluir este fragmento en elquickfix window
. Entonces la expresin%-G
se puede leer como "no incluyas este mensaje." En nuestro ejemplo usamos%-G%.%#
que bascamente le dice a vim "ignora todo lo dems." Ya que%.%#
es una expresin que coincide con todo lo colocamos de ltimo.
Si quieren saber con ms detalle lo que pueden hacer con errorformat
pueden ejecutar el comando :help errorformat
.
makeprg
Ya saben que con un poco de esfuerzo podemos hacer que vim lea cualquier tipo de error pero la configuracin actual an nos tiene atados a make
. No tiene que ser as. Podemos cambiar el comando externo que vim ejecuta cuando invocamos :make
.
Digamos que queremos usar node
directamente, para lograr nuestro objetivo slo tenemos que modificar la variable makeprg
.
set makeprg=node
O tambin.
let &makeprg = 'node'
Ahora en lugar de usar :make --silet run-greeting
podemos ejecutar :make ./greeting.js
:make %
si estamos editando greeting.js
.
Buscar
El quickfix list no solamente es til para saltar a un error, tambin puede ser un mecanismo conveniente con el cual podemos explorar un proyecto. Mencion antes que vim nos ofrece los comandos :grep
y :vimgrep
, ellos pueden crear un quickfix list con los resultados de una bsqueda.
vimgrep
Con este comando podremos hacer uso del mecanismo de bsqueda que viene incorporado en vim. Est diseado para ser similar a la herramienta grep, con la pequea diferencia que usa el "intrprete de expresiones regulares" de vim. En otras palabras, con :vimgrep
podemos buscar un patrn (una expresin regular) en mltiples archivos. Se usa de la siguiente manera:
:vimgrep /<patrn>/ <archivos>
Los /
no son estrictamente obligatorios, pero es una buena idea incluirlos si el patrn que estn buscando contiene algn caracter que cause conflicto con la sintaxis de vim. Por ejemplo:
:vimgrep /create table/ db/**/*.sql
Aqu estaramos realizando una bsqueda del patrn create table
en un directorio llamado db
, y seleccionando especficamente todos los archivos que terminen con la extensin .sql
.
Los delimitadores del patrn de bsqueda no tienen que ser /
. Pueden ser cualquier caracter que vim no considere un "identificador," pueden encontrar ms detalles en la documentacin de vim :help isident
. Esto puede resultar til si /
ya se encuentra en nuestro patrn. Si estuviramos buscando una ruta en nuestro cdigo podramos hacer algo as.
:vimgrep #/home/user/code# scripts/*.sh
Pero qu pasa si queremos ignorar algn directorio de nuestra bsqueda? Hay algo que pueden hacer. Para empezar, podran intentar usar la opcin wildignore
. Algo as.
:set wildignore=*/cache/*,*/tmp/*
Hasta donde tengo entendido esto le dice a vim que ignore los directorios cache
y tmp
de cualquier expansin de ruta o autocompletado. Por ejemplo, al buscar, si usamos un patrn como este **/*.js
vim no incluir ningn directorio que contenga en su ruta /cache/
o /tmp/
. Entonces, :vimgrep
no buscar en esos directorios porque tcnicamente nunca los recibe como parmetro. Quiere decir tambin que esta opcin no es especfica para :vimgrep
, tambin puede afectar otros comandos.
Algunas preguntas en stackoverflow sugieren que este mtodo puede que no funcione. En ese caso podramos intentar con una expresin encerrada en (acento grave), las cuales se usan para invocar un comando en nuestro "shell." Podemos hacer cosas interesantes como buscar slo en los archivos que son manejados por git
.
:vimgrep /function/ `git ls-files`
En el caso de :vimgrep
cualquier comando externo que nos devuelva una lista de archivos es vlido.
grep
Ya habrn notado que vim por defecto asume que tenemos a nuestra disposicin ciertas herramientas. Vimos que por ejemplo asume que tenemos instalado make
. Ahora vamos a explorar el comando :grep
, que es la manera de vim de integrarse con la herramienta de bsqueda grep
. En su mayora funciona igual que :vimgrep
con la diferencia de que todos los argumentos deben ser compatibles con la sintaxis de grep
. Por ejemplo.
:grep -r "create table" db/**/*.sql
Noten que no estoy usando /
sino comillas dobles y le aado el parmetro -r
(para habilitar la bsqueda recursiva en directorios), esto es porque el comando :grep
lo que hace es invocar un "shell" no interactivo para ejecutar el programa grep
y le pasa todos los argumentos tal cual como los escribimos.
Ahora surge la pregunta Cundo debemos usar :grep
por encima de :vimgrep
? Resulta que :grep
es ms rpido y eficiente que :vimgrep
. Entonces, :grep
es la mejor opcin si tienen que buscar en muchos archivos o archivos que son tienen mucho contenido.
Por otro lado podramos preguntarnos Qu ventajas tiene :vimgrep
sobre :grep
? No mucho dira yo. Lo primero sera que la sintaxis para las expresiones regulares es la misma que usa vim, si estn familiarizados con esa sintaxis pueden tomar ventaja de sus bondades. Tambin, :vimgrep
funciona de manera consistente en todas las plataformas.
Qu pasa si nos encontramos en una plataforma que no tiene instalado grep
? :grep
con su configuracin por defecto no funcionara. Pero al igual que :make
, con :grep
podemos modificar el comando externo que vim ejecuta, usando la variable grepprg
. Digamos que no tenemos grep
sino ripgrep instalado en nuestro sistema, en ese caso podremos hacer esto.
set grepprg=rg\ --vimgrep\ --smart-case\ --follow
Con esto vim usar rg
con los parmetros especificados para realizar las bsquedas cuando nosotros usemos :grep
.
Invitado especial: FZF
La ltima herramienta de bsqueda que voy a mencionar es fzf.vim. Este es un plugin que nos proporciona una especie de interfaz en la que podemos realizar bsquedas de manera interactiva. No entrar en detalle de cmo funciona o se usa. Slo les dir un tip que yo descubr mucho tiempo despus de empezar a usarlo.
Curiosamente, tambin podemos poblar el quickfix list usando FZF, especficamente con los comandos Rg
y Ag
. Despus de realizar una bsqueda y se encuentren con su lista de resultados, pueden seleccionar mltiples items (con la tecla tab
para seleccionar uno o Alt + a
para seleccionar todos) y presionar enter
. Eso es todo. Despus el quickfix list debera tener todo lo que ustedes seleccionaron. Esto resulta muy til cuando quieren ejecutar comandos slo en unas partes del cdigo usando :cdo
.
Reemplazar
Hablando de :cdo
, voy a mostrarles una de las cosas ms tiles que podemos hacer ese comando: buscar y reemplazar un patrn en mltiples archivos. Una tarea bastante comn, y seguramente se han preguntado cmo pueden hacerlo usando vim. La respuesta a eso es el quickfix list y el comando :cdo
.
En el caso ms simple donde queremos reemplazar cada instancia de un patrn esto es lo que hacemos:
- Paso 1:
Buscamos nuestro patrn usando :grep
, :vimgrep
o cualquier otro comando que pueda generar un quickfix list.
- Paso 2 (opcional):
Abrimos el quickfix window usando el comando :copen
.
- Paso 3:
Usamos el comando :cdo
para ejecutar una accin sobre cada item en el quickfix list. En este caso la accin que queremos hacer es sustituir y en vim lo hacemos con esta sintaxis s/{patrn}/{reemplazo}
.
Imaginemos que en nuestro quickfix list tenemos los resultados de esta bsqueda.
:vimgrep node **/*.js
Una vez que tengamos los resultados lo que haremos ser reemplazar node
con deno
y para eso usamos este comando.
:cdo s/node/deno/ | update
Lo que va a pasar es que vim ejecutar el comando s/node/deno | update
en cada item de nuestro quickfix list. En realidad :cdo
puede ejecutar cualquier comando vlido de vim. En nuestro ejemplo en concreto lo usamos para hacer dos cosas, reemplazar el texto node
y guardar los cambios en el archivo.
Caso avanzado
Digamos que tenemos los resultados de una bsqueda y por supuesto queremos hacer una substitucin, pero tambin queremos filtrar los resultados. En otras palabras queremos reemplazar un patrn pero no queremos reemplazar todas las instancias de ese patrn. Cmo haramos? En ese caso lo que podemos hacer es modificar el quickfix list para que refleje slo los resultados que queremos reemplazar.
Este proceso requiere algo de esfuerzo por nuestra parte. Para empezar necesitamos decirle a vim cmo leer el quickfix list, para que podemos crear versiones modificadas de un quickfix list que existente. Para lograr nuestro objetivo necesitamos agregrar un patrn al errorformat
. Entonces en su .vimrc
pueden colocar algo como esto.
set errorformat+=%f\|%l\ col\ %c\|%m
An con esto no pueden modificar el quickfix list, vim no los dejar. Cuando quieran eliminar algn resultado deben hacer que el buffer donde est el quickfix list sea modificable. Deben ejecutar este comando.
:set modifiable
Luego eliminan los items que ustedes quieran, pero no ejecuten :cdo
todava. Tienen que asegurarse de crear un quickfix list basado en los resultados que quieren. Entonces, luego de hacer sus modificaciones en el buffer ejecutan este comando.
:cgetbuffer
Lo siguiente es asegurarse que estn usando la versin actualizada del quickfix list abriendo y cerrando el quickfix window. Creo que este paso es opcional, pero a m no me gusta arriesgarme. Ejecutan :cclose
y luego :copen
.
Por ltimo ejecutan el comando para sustituir.
Aqu les dejo un demo de todo el proceso.
Ver en asciinema.
Mejorando la experiencia
Como habrn notado el uso del quickfix list en ocasiones no es muy intuitivo que digamos. Pero podemos mejorarlo. Puedo darles algunas sugerencias que pueden colocar en su .vimrc
.
- Un mejor grep.
Lo primero sera crear un comando que ejecute el comando de bsqueda y que luego abra el quickfix window automticamente. Por suerte para nosotros la documentacin nos da una sugerencia, esta de aqu:
command! -nargs=+ Grep execute 'silent grep! <args>' | copen
Pueden cambiar grep
por vimgrep
si eso desean. Lo importante aqu es que ahora podrn invocar el comando :Grep
(con G
mayscula) para realizar sus bsquedas.
- Navegar por los resultados.
Podramos "navegar" por los items del quickfix list sin siquiera abrir el quickfix window de una manera cmoda con estos atajos.
" Ir a la ubicacin anteriornnoremap [q :cprev<CR>" Ir a la siguiente ubicacinnnoremap ]q :cnext<CR>
- Manejo de la ventana.
Si tienden a usar el quickfix window con frecuencia ser mejor que se creen unos atajos para abrir y cerrarlo con ms facilidad.
" Mostrar el quickfix windownnoremap <Leader>co :copen<CR>" Ocultar el quickfix windownnoremap <Leader>cc :cclose<CR>
- El errorformat.
Vamos a asegurarnos de que vim siempre pueda leer el formato del quickfix list si queremos actualizarlo.
augroup quickfix_mapping autocmd! autocmd filetype qf setlocal errorformat+=%f\|%l\ col\ %c\|%maugroup END
- Atajos
Tambin necesitamos atajos que funcionen slo en el quickfix window. Ya saben, para hacer ms cmoda la navegacin y tambin hacer que el "caso avanzado" que les present no sea tan engorroso.
function! QuickfixMapping() " Ir a la ubicacin anterior y mantenerse en el quickfix window nnoremap <buffer> K :cprev<CR>zz<C-w>w " Ir a la siguiente ubicacin y mantenerse en el quickfix window nnoremap <buffer> J :cnext<CR>zz<C-w>w " Haz que el quickfix list sea modificable nnoremap <buffer> <leader>u :set modifiable<CR> " Actualiza el quickfix window nnoremap <buffer> <leader>w :cgetbuffer<CR>:cclose<CR>:copen<CR> " Buscar y reemplazar nnoremap <buffer> <leader>r :cdo s/// \| update<C-Left><C-Left><Left><Left><Left>endfunctionaugroup quickfix_mapping autocmd! autocmd filetype qf call QuickfixMapping()augroup END
- Ahora todo junto.
" Comando Grep que busca y abre el quickfix windowcommand! -nargs=+ Grep execute 'silent grep! <args>' | copen" Ir a la ubicacin anteriornnoremap [q :cprev<CR>" Ir a la siguiente ubicacinnnoremap ]q :cnext<CR>" Mostrar el quickfix windownnoremap <Leader>co :copen<CR>" Ocultar el quickfix windownnoremap <Leader>cc :cclose<CR>function! QuickfixMapping() " Ir a la ubicacin anterior y mantenerse en el quickfix window nnoremap <buffer> K :cprev<CR>zz<C-w>w " Ir a la siguiente ubicacin y mantenerse en el quickfix window nnoremap <buffer> J :cnext<CR>zz<C-w>w " Haz que el quickfix list sea modificable nnoremap <buffer> <leader>u :set modifiable<CR> " Actualiza el quickfix window nnoremap <buffer> <leader>w :cgetbuffer<CR>:cclose<CR>:copen<CR> " Buscar y reemplazar nnoremap <buffer> <leader>r :cdo s/// \| update<C-Left><C-Left><Left><Left><Left>endfunctionaugroup quickfix_mapping autocmd! " Asignar los atajos especficos para el quickfix window autocmd filetype qf call QuickfixMapping() " Agregar formato para modificar el quickfix list autocmd filetype qf setlocal errorformat+=%f\|%l\ col\ %c\|%maugroup END
Plugins
Si estn dispuestos y saben cmo instalar plugins en vim yo recomendara estos:
Este hace que el quickfix window tenga un comportamiento ms intuitivo. Por ejemplo, puede hacer que se abra automticamente cuando ejecutamos :grep
, :vimgrep
e incluso :make
sin tener que crear otros comandos. Pero si queremos disfrutar de algunas de sus bondades tenemos que crear nuestros propios atajos.
- Abrir o cerrar el quickfix window.
nmap <Leader>cc <Plug>(qf_qf_toggle)
- Navegar por los resultados
" Ir a la ubicacin anteriornmap [q <Plug>(qf_qf_previous)zz" Ir a la siguiente ubicacinnmap ]q <Plug>(qf_qf_next)zzfunction! QuickfixMapping() " Ir a la ubicacin anterior y mantenerse en el quickfix window nmap <buffer> K <Plug>(qf_qf_previous)zz<C-w>w " Ir a la siguiente ubicacin y mantenerse en el quickfix window nmap <buffer> J <Plug>(qf_qf_next)zz<C-w>wendfunctionaugroup quickfix_mapping autocmd! autocmd filetype qf call QuickfixMapping()augroup END
La diferencia entre estos comandos y los que trae vim por defecto es que los de vim-qf
no dan error cuando llegamos al final de la lista. Es decir que si estamos visualizando el ltimo item y usamos ]q
para ir al siguiente, en lugar de tener un error este comando nos lleva al primer item del quickfix list.
Este plugin hace que todos los comandos que ejecutamos en el "caso avanzado" queden obsoletos. Nos da la posibilidad de modificar el quickfix window como un buffer normal. Pero eso no es todo, cada cambio que guardemos quedar "reflejado" en el archivo original.
Tomemos el ejemplo que mostr en el demo. Digamos que tenemos esto en el quickfix list.
./test dir/a-file.txt|1 col 11| nnoremap <leader>f :FZF./test dir/a-file.txt|2 col 11| nnoremap <leader>ff :FZF<CR>./test dir/a-file.txt|3 col 11| nnoremap <leader>fh :History<CR>./test dir 2/another-file.txt|1 col 11| nnoremap <leader>? :Maps<CR>./test dir 2/another-file.txt|2 col 11| nnoremap <leader>bb :Buffers<CR>
Y digamos que modifico el primer y cuarto item en la lista de manera manual.
- ./test dir/a-file.txt|1 col 11| nnoremap <leader>f :FZF+ ./test dir/a-file.txt|1 col 11| nnoremap <AAA>f :FZF ./test dir/a-file.txt|2 col 11| nnoremap <leader>ff :FZF<CR> ./test dir/a-file.txt|3 col 11| nnoremap <leader>fh :History<CR>- ./test dir 2/another-file.txt|1 col 11| nnoremap <leader>? :Maps<CR>+ ./test dir 2/another-file.txt|1 col 11| nnoremap <BBB>? :Maps<CR> ./test dir 2/another-file.txt|2 col 11| nnoremap <leader>bb :Buffers<CR>
Si guardo estos cambios con el comando :write
(o :w
para abreviar) se quedarn reflejados en sus lugares respectivos en cada archivo. Esto resulta sumamente poderoso porque ahora la flexibilidad del quickfix list est limitada a nuestro conocimiento sobre vim.
Cualquier truco que conozcan para modificar varios fragmentos de cdigo deberan funcionar con este plugin. Por ejemplo si queremos replicar el mismo efecto que mostr en el demo anterior lo que tenemos que hacer es esto:
- Borramos las lneas que no queremos modificar.
./test dir/a-file.txt|1 col 11| nnoremap <leader>f :FZF./test dir/a-file.txt|3 col 11| nnoremap <leader>fh :History<CR>./test dir 2/another-file.txt|1 col 11| nnoremap <leader>? :Maps<CR>
- Usamos el comando de substitucin "normal."
:%s/leader/localleader/g
Despus de eso el quickfix list debera quedar en este estado.
./test dir/a-file.txt|1 col 11| nnoremap <localleader>f :FZF./test dir/a-file.txt|3 col 11| nnoremap <localleader>fh :History<CR>./test dir 2/another-file.txt|1 col 11| nnoremap <localleader>? :Maps<CR>
- Guardamos el cambio.
:write
Y eso es todo.
Conclusin
Nos hemos familiarizado con el quickfix list y sus utilidades ms comunes.
Sabemos que podemos usar :make
para invocar cualquier compilador o comando externo que pueda ejecutar nuestro cdigo y darnos mensajes de error. Tenemos las herramientas para hacer que vim entienda un mensaje de error y pueda incorporar la informacin relevante al quickfix list.
Vimos que podemos usar :vimgrep
y :grep
para buscar patrones en mltiples archivos. Tambin pudimos explorar diferentes formas de reemplazar el texto que estamos buscando, con casos simples y otros un poco ms complejos. Con estos casos pudimos aprender cmo hacer la sustitucin sin usar plugins y tambin cmo hacerlo con la ayuda de un par de plugins.
Por ltimo aprendimos sobre comandos, mtodos y configuraciones que podemos agregar en nuestro .vimrc
para hacer que la experiencia al usar el quickfix list sea ms placentera e intuitiva.
Fuentes
Gracias por su tiempo. Si este artculo les pareci til y quieren apoyar mis esfuerzos para crear ms contenido, pueden dejar una propina en buymeacoffee .
Original Link: https://dev.to/vonheikemen/vim-y-el-quickfix-list-saltar-a-una-ubicacion-buscar-y-reemplazar-en-multiples-archivos-y-otras-curiosidades-13n4
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To