J'essaie de lire beaucoup de code C/Perl via Vim qui contient de nombreux noms de variables à lettre unique.
Ce serait bien d'avoir une commande qui pourrait m'aider à changer le nom d'une variable en quelque chose de plus significatif pendant que je suis en train de lire le code afin de pouvoir lire le reste plus rapidement.
Y a-t-il un commandement à Vim qui pourrait me permettre de le faire rapidement?
Je ne pense pas que les regex fonctionneraient parce que:
le même nom d'une seule lettre peut avoir des objectifs différents dans différents blocs de portée
la même combinaison de lettres pourrait faire partie d'un autre nom var plus grand, ou dans une chaîne ou un commentaire ... ne voudrait pas les modifier
Des solutions connues?
Voici comment renommer une variable définie dans la portée actuelle {}
.
Déplacez votre curseur sur l'utilisation variable. Appuyez sur Gd
. Ce qui signifie - déplacer le curseur sur la définition. Maintenant, appuyez sur [{
- cela vous amènera à la portée de commencer. Appuyez sur V
- pour activer la sélection de la ligne visuelle. Presse %
- passera à l'opposé }
sélectionnera donc toute la portée. Presse :s/
- début de la commande de substitution. <C-R>/
- insérera un modèle qui correspond au nom de la variable (ce nom que vous utilisiez avant d'appuyer sur Gd
). /newname/gc<CR>
- lancera la recherche et la remplacera par une confirmation à chaque correspondance.
Vous devez maintenant enregistrer une macro ou mieux encore - mapper une clé.
Voici les mappages finaux:
" For local replace
nnoremap gr Gd[{V%::s/<C-R>///gc<left><left><left>
" For global replace
nnoremap gR Gd:%s/<C-R>///gc<left><left><left>
Mettez ceci à votre .vimrc
ou simplement exécuter. Après cela, appuyer sur gr
sur la variable locale vous amènera à :s
commande où vous devez simplement entrer new_variable_name
et appuyez sur Enter.
AFAIK, il n'y a pas de support de refactoring réel dans VIM. Lorsque je fais un changement de nom avec l'intention d'un refactor, je prends généralement les précautions suivantes:
Mon changement de fin ressemble à ceci
:'a,'bs/\<foo\>/bar
J'aimerais avoir tort de ne pas avoir d'outil de refactoring pour VIM mais je ne l'ai pas vu.
Mettez ceci dans votre .vimrc
" Function to rename the variable under the cursor
function! Rnvar()
let Word_to_replace = expand("<cword>")
let replacement = input("new name: ")
execute '%s/\(\W\)' . Word_to_replace . '\(\W\)/\1' . replacement . '\2/gc'
endfunction
Appelez-le avec :call Rnvar()
expand("<cword>")
place le mot sous le curseur. La chaîne de recherche utilise %
Pour la portée du fichier, et les modèles \(\W\)
recherchent des caractères non Word à la limite du mot à remplacer et les enregistrent dans des variables \1
et \2
pour être réinsérés dans le motif de remplacement.
Je sais que c'est une vieille question, et la manière de @ mykola-golubyev est évidemment IS la meilleure réponse pour le cas particulier de la question OP (qui, je suppose, passe par du code obscurci où vous êtes susceptible de avoir plusieurs blocs avec les mêmes noms var); mais avec le nom de la question comme ça, beaucoup de gens venant ici de recherches Google recherchent probablement des moyens moins spécifiques à la situation pour renommer des variables dans VIM - et ceux-ci peuvent être plus concis
Je suis surpris que personne n'ait suggéré de cette façon:
*
:s//
[~ # ~] nouveau nom [~ # ~]/gc
*
Est identique à gn
- il recherche la prochaine occurrence du mot sous le curseur ET il devient le dernier modèle recherché, donc lorsque vous omettez le modèle de recherche dans la commande de remplacement, VIM suppose que c'est le modèle à rechercher.
Pour de petites quantités de copies var, encore plus rapide:
*
cw
[~ # ~] nouveau nom [~ # ~]<esc>
puis répétezn.
pour d'autres occurrences
Rechercher l'occurrence, cw
est la commande pour changer Word, n
passe à l'occurrence suivante pour la dernière recherche et .
Répète la dernière commande ( qui est changez Word en NEWNAME)
(Les crédits pour moi sachant tout cela vont à @ doomedbunnies sur Reddit )
Une autre astuce intéressante est la suivante: ( crédits à @ nobe4 )
*
cgn
[~ # ~] nouveau nom [~ # ~]<esc>
puis répétez.
pour d'autres occurrences
cgn
est "changer le résultat de (trouver l'occurrence suivante)". Maintenant que c'est la dernière commande, vous n'avez plus besoin de n
pour passer à l'occurrence suivante, donc moins de coups à nouveau et, plus important encore, pas besoin d'alterner n
et .
. Mais, évidemment, celui-ci a l'inconvénient de ne pas pouvoir ignorer un événement.
Voici quelques avantages:
*
ou gn
pour la sélection de Word est très rapide - une seule touche (enfin, disons 1,5)*
ou gn
garantit que vous n'obtiendrez aucune correspondance dans les autres mots, tout comme :%s/<C-R>//gc
. Beats tapant le :%s/\<OLDNAME\>/NEWNAME/gc
À la main: J'ai personnellement tendance à oublier d'utiliser les choses \<
Pour limiter les correspondances aux mots entiers uniquement.n
pour ignorer les correspondances indésirables - probablement encore moins que les coups supplémentaires nécessaires pour limiter la portée. Dans des circonstances normales, vos variables sont très probablement quelque peu localisées dans un certain bloc de code de toute façon.Vous pouvez utiliser le modificateur "c" dans la recherche globale et remplacer qui vous demanderait une confirmation pour chaque remplacement. Cela prendrait plus de temps, mais cela pourrait fonctionner pour un fichier de code non gigantesque:
%s/\$var/\$foo/gc
Le c signifie confirmer.
S'il s'agit de plusieurs fichiers, vous pouvez envisager de jeter un œil à sed. Utilisez find pour récupérer vos fichiers et xargs plus sed pour un remplacement. Supposons que vous souhaitiez remplacer a par a_better_name dans tous les fichiers correspondant à * .c, vous pouvez le faire
trouver . -nom "* .c" | xargs sed -i -e 's/a/a_better_name/g'
Gardez à l'esprit que cela remplacera TOUTES les occurrences d'un, donc vous voudrez peut-être une expression régulière plus robuste.
En c, vous pourrez peut-être faire des progrès en utilisant cscope. Il essaie de comprendre la syntaxe, donc aurait une chance de savoir quand la lettre était une variable.