Cuando busco con el /
comando de modo normal:
/\vSEARCHTERM
Vim comienza la búsqueda desde la posición del cursor y continúa hacia abajo, envolviendo hasta arriba. Sin embargo, cuando busco y reemplazo usando el :substitute
comando:
:%s/\vBEFORE/AFTER/gc
En cambio, Vim comienza en la parte superior del archivo.
¿Hay alguna manera de hacer que Vim realice la búsqueda y reemplace comenzando desde la posición del cursor y envolviendo hasta la parte superior una vez que llega al final?
\vpattern
- patrón 'muy mágico': los caracteres no alfanuméricos se interpretan como símbolos regex especiales (no es necesario escapar)%
? No veo ningún uso razonable para que estés revisando todo el archivo de todos modos.Respuestas:
1. No es difícil lograr el comportamiento mediante una sustitución de dos pasos:
Primero, el comando de sustitución se ejecuta para cada línea comenzando desde la actual hasta el final del archivo:
Luego, ese
:substitute
comando se repite con el mismo patrón de búsqueda, cadena de reemplazo y banderas, usando el:&
comando (ver:help :&
):Este último, sin embargo, realiza la sustitución en el rango de líneas desde la primera línea del archivo hasta la línea donde se estableció la marca de contexto anterior, menos uno. Dado que el primer
:substitute
comando almacena la posición del cursor antes de iniciar los reemplazos reales, la línea a la que se dirige''
es la línea que era la actual antes de que se ejecutara el comando de sustitución. (La''
dirección se refiere a la'
pseudo-marca; consulte:help :range
y:help ''
para obtener más detalles).Tenga en cuenta que el segundo comando (después del
|
separador de comandos, consulte:help :bar
) no requiere ningún cambio cuando el patrón o las banderas se modifican en el primero.2. Para ahorrar algo de escritura, para que aparezca el esqueleto del comando de sustitución anterior en la línea de comando, se puede definir un mapeo en modo normal, así:
La
<c-b><right><right><right><right>
parte final es necesaria para mover el cursor al principio de la línea de comando (<c-b>
) y luego cuatro caracteres a la derecha (<right>
× 4), poniéndolo así entre los dos primeros signos de barra, listo para que el usuario comience a escribir el patrón de búsqueda. . Una vez que el patrón deseado y el reemplazo están listos, el comando resultante se puede ejecutar presionando Enter.(Se podría considerar tener en
//
lugar de///
en el mapeo anterior, si se prefiere escribir el patrón, luego escribir la barra inclinada de separación, seguida de la cadena de reemplazo, en lugar de usar la flecha derecha para mover el cursor sobre una barra inclinada de separación ya presente que comienza la pieza de repuesto.)fuente
:noremap <leader>R :,$s///gc\|1,''-&&<c-b><right><right><right><right>
. Se coloca:,$s///gc|1,''-&&
en la línea de comando con el cursor entre los dos primeros signos de barra. Una vez que escriba el patrón y el reemplazo deseados, puede ejecutar el comando resultante presionando Enter .Ya está utilizando un rango,
%
que es la abreviatura de1,$
significar todo el archivo. Para ir de la línea actual al final que usa.,$
. El punto significa la línea actual y$
significa la última línea. Entonces el comando sería:Pero
.
se puede suponer la línea o actual, por lo tanto, se puede eliminar:Para obtener más ayuda, consulte
fuente
10:s/pattern/replace/gc
%
es un atajo para1,$
(Vim help =>
:help :%
igual a 1, $ (el archivo completo).).
es la posición del cursor para que pueda hacerReemplazar desde el principio del documento hasta el cursor
etc
Le sugiero encarecidamente que lea el manual sobre el rango,
:help range
ya que casi todos los comandos funcionan con un rango.fuente
FINALMENTE se me ocurrió una solución al hecho de que al salir de la búsqueda se llega al principio del archivo sin escribir una función enorme ...
No creerías cuánto tiempo me tomó pensar en esto. Simplemente agregue un mensaje si desea ajustar: si el usuario presiona
q
nuevamente, no ajuste. Básicamente, salga de la búsqueda tocando enqq
lugar deq
! (Y si desea ajustar, simplemente escribay
).De hecho, tengo esto asignado a una tecla de acceso rápido. Entonces, por ejemplo, si desea buscar y reemplazar cada palabra debajo del cursor, comenzando desde la posición actual, con
q*
:fuente
q
,l
o Esc ) y no desea continuar desde arriba, ya puede presionarq
o Esc nuevamente para salir del segundo comando de inmediato. Es decir, la adición propuesta del mensaje parece duplicar efectivamente la funcionalidad ya presente.yyyq
, continuar editando, sin saltos desorientadores. Peroyyyqq
es casi tan bueno, si considera un doble toque prácticamente un solo toque en términos de facilidad de uso.q
la segunda vez). Este último deja el cursor en la última aparición que se reemplazó (justo antes deq
presionar la primera ).norm!``
comando::,$s/BEFORE/AFTER/gc|1,''-&&|norm!``
.Aquí hay algo muy aproximado que aborda las preocupaciones acerca de envolver la búsqueda con el enfoque de dos pasos (
:,$s/BEFORE/AFTER/gc|1,''-&&
) o con un intermedio "¿Continuar al principio del archivo?" Acercarse:Esta función utiliza un par de trucos para comprobar si deberíamos pasar al principio:
fuente
Llegué tarde a la fiesta, pero confié demasiado a menudo en respuestas de stackoverflow tan tardías para no hacerlo. Reuní sugerencias sobre reddit y stackoverflow, y la mejor opción es usar el
\%>...c
patrón en la búsqueda, que coincide solo después del cursor.Dicho esto, también estropea el patrón para el siguiente paso de reemplazo y es difícil de escribir. Para contrarrestar esos efectos, una función personalizada debe filtrar el patrón de búsqueda posteriormente, restableciéndolo. Vea abajo.
Me he enfrentado a un mapeo que reemplaza la siguiente ocurrencia y salta al siguiente después, y no más (era mi objetivo de todos modos). Estoy seguro de que, basándose en esto, se puede elaborar una sustitución global. Tenga en cuenta que cuando trabaje en una solución que tenga como objetivo algo así,
:%s/.../.../g
el patrón a continuación filtra las coincidencias en todas las líneas que quedan hasta la posición del cursor, pero se limpia después de que se completa la sustitución única, por lo que pierde ese efecto directamente después, salta al siguiente partido y, por lo tanto, puede ejecutar todos los partidos uno por uno.fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
fuente