Quand je recherche avec
/\vSEARCHTERM
Vim lance la recherche de la position du curseur vers le bas, et le retourne au début. Cependant, lorsque vous recherchez et remplacez en utilisant
:%s/\vBEFORE/AFTER/gc
Vim commence en haut du fichier.
Existe-t-il un moyen de faire rechercher et remplacer Vim en partant de la position du curseur ET en remontant vers le haut une fois la fin atteinte?
Il n’est pas difficile de réaliser le comportement en utilisant une substitution en deux étapes:
:,$s/BEFORE/AFTER/gc|1,''-&&
Tout d’abord, une commande de substitution est exécutée pour chaque ligne à partir de la ligne actuelle jusqu’à la fin du fichier. Ensuite, la commande :substitute
est répétée avec le même modèle de recherche, la même chaîne de remplacement et les mêmes indicateurs, à l’aide de la commande :&
. Ce dernier effectue toutefois la substitution sur la plage de lignes de la première ligne du fichier à la ligne où la marque de contexte précédente a été définie, moins un. Comme la première commande :substitute
stocke la position du curseur avant de commencer les remplacements réels, la ligne adressée par ''
est la ligne qui était la ligne courante avant l’exécution de cette commande de substitution.
Notez que la deuxième commande (après le symbole |
) ne nécessite aucune modification lorsque le modèle ou les indicateurs du premier sont modifiés.
Vous utilisez déjà une plage, %
, qui est une main courte pour 1,$
signifiant le fichier entier. Pour aller de la ligne courante à la fin que vous utilisez .,$
. La période signifie la ligne courante et $
la dernière ligne. Donc, la commande serait:
:.,$s/\vBEFORE/AFTER/gc
Mais le .
ou on peut supposer que la ligne actuelle peut être supprimée:
:,$s/\vBEFORE/AFTER/gc
Pour plus d’aide voir
:h range
%
est un raccourci pour 1,$
(Vim help => :help :%
égal à 1, $ (le fichier entier).)
.
est la position du curseur pour pouvoir faire
:.,$s/\vBEFORE/AFTER/gc
Remplacer depuis le début du document jusqu’au curseur
:1,.s/\vBEFORE/AFTER/gc
etc
Je vous suggère fortement de lire le manuel sur la plage :help range
car à peu près toutes les commandes fonctionnent avec une plage.
J’ai finalement trouvé une solution au fait que quitter la recherche se termine au début du fichier sans écrire une fonction énorme …
Vous ne croiriez pas combien de temps cela m’a pris pour y arriver. Ajoutez simplement une invite pour envelopper: si l’utilisateur appuie à nouveau sur q
, ne pas envelopper. Donc, fondamentalement, quittez la recherche en tapant sur qq
au lieu de q
! (Et si vous voulez envelopper, tapez simplement y
.)
:,$s/BEFORE/AFTER/gce|echo 'Continue at beginning of file? (y/q)'|if getchar()!=113|1,''-&&|en
Je l’ai en fait mappé sur un raccourci clavier. Donc, par exemple, si vous souhaitez rechercher et remplacer chaque mot sous le curseur, à partir de la position actuelle, avec q*
:
exe 'nno q* :,$s/\<=expand("")\>//gce\|echo "Continue at beginning of file? (y/q)"\|if getchar()==121\|1,''''-&&\|en'.repeat('',77)
Voici quelque chose de très rude qui aborde les problèmes liés à la gestion de la recherche avec l’approche en deux étapes ( :,$s/BEFORE/AFTER/gc|1,''-&&
) ou avec un intermédiaire “Continuer au début du fichier?” approche:
" Define a mapping that calls a command. nnoremap e :Substitute/\v<=expand('')>// " And that command calls a script-local function. command! -nargs=1 Substitute call s:Substitute() function! s:Substitute(patterns) if getregtype('s') != '' let l:register=getreg('s') endif normal! qs redir => l:replacements try execute ',$s' . a:patterns . 'gce#' catch /^Vim:Interrupt$/ return finally normal! q let l:transcript=getreg('s') if exists('l:register') call setreg('s', l:register) endif endtry redir END if len(l:replacements) > 0 " At least one instance of pattern was found. let l:last=strpart(l:transcript, len(l:transcript) - 1) " Note: type the literal (^[) here with : if l:last ==# 'l' || l:last ==# 'q' || l:last ==# '^[' " User bailed. return endif endif " Loop around to top of file and continue. " Avoid unwanted "Backwards range given, OK to swap (y/n)?" messages. if line("''") > 1 1,''-&&" endif endfunction
Cette fonction utilise un couple de hacks pour vérifier si nous devons boucler vers le haut: