Refactoring dans Vim

99

Bien sûr, le fait que vous puissiez refactoriser sur les IDE n'a pas de prix pour beaucoup, je ne le fais presque jamais lorsque je codifie mais je peux essayer de le faire lors de l'édition de la source de quelqu'un d'autre. Comment accomplissez-vous une tâche aussi triviale sur plusieurs fichiers dans Vim?

J'ai trouvé ce plugin pour refactoriser Ruby, mais qu'en est-il de "n'importe quel" langage?

Helmut Granda
la source
2
Le refactoring est très spécifique à la langue. Vous devez rechercher des modules complémentaires spécifiques pour chaque langue qui vous intéresse. Vous trouverez probablement des modules complémentaires pour certains et pas pour d'autres. S'il y en a un que vous voulez et que vous ne trouvez pas, alors si vous vous sentez ambitieux, vous pouvez essayer d'en écrire un, en utilisant un module complémentaire existant pour un autre langage similaire comme point de départ.
Steve Jorgensen
2
VIM est conçu autour de l'édition de fichiers uniques, et peut-être de fichiers dans un répertoire - pas de projets . De nombreuses refactorisations prises en charge par IDE auront un impact sur les fichiers dans tout le projet (par exemple, renommer une classe). Je pense qu'il serait difficile de faire cela "correctement" avec un éditeur comme (g) VI (m), au point où je pense qu'une entreprise ou un gros projet devrait se charger de cela. Ils devraient essentiellement analyser chaque langue pour éviter de faire de simples substitutions de chaînes et devenir sujets aux erreurs (ctags en donne une partie ), ainsi que les types de projets correspondants (pour savoir quels fichiers modifier).
Merlyn Morgan-Graham
1
Merci pour les commentaires, je pense que c'est là que les choses commencent à devenir délicates et essayer de plier VIM en un IDE n'est pas une solution élégante pour utiliser un seul programme pour éditer plusieurs langues. Je ne veux vraiment pas abandonner VIM car certaines des fonctionnalités "avancées" sont disponibles sur les IDE.
Helmut Granda
@ MerlynMorgan-Graham - Certaines personnes conservent simplement leur code dans quelques fichiers (volumineux, peut-être). Évite complètement ce problème.
Rook
7
@ldigas: Cela contournerait le problème. Mais c'est tout à fait contraire aux pratiques recommandées pour certains langages (par exemple Java). Fondamentalement, le code se plie pour répondre aux besoins de l'outil, alors que cela devrait vraiment être l'inverse.
Merlyn Morgan-Graham

Réponses:

78

Je suis d'accord avec le paradigme «Vim n'est pas un IDE». Mais il y a des moments où il n'y a pas d'IDE. Voici ce que j'utilise dans ces situations:

: grep,: vimgrep,: Ag,: Ggrep

Refactoring qui a plus à voir avec les remplacements réguliers que j'utilise habituellement : grep sur mon arbre de projet, puis enregistre une macro pour faire le refactor -: g et: s ne sont pas des idées. Habituellement, cela me permet de modifier rapidement un grand nombre de fichiers avec très peu d'effort. Honnêtement, j'utilise cette méthode plus que toute autre.

En fonction de votre flux de travail, les commandes intégrées peuvent être lentes / peu pratiques. Si vous utilisez git, vous voudrez utiliser l'excellent plugin Fugitive et sa :Ggrepcommande pour rechercher uniquement les fichiers archivés dans git. J'aime aussi le Silver Searcher pour sa rapidité.

: argdo,: cdo et: bufdo

: cdo et : argdo sont pratiques pour exécuter des commandes vim sur un ensemble de fichiers.

ligne de commande

Lorsqu'il est plus difficile de déterminer la liste des fichiers qui nécessitent des modifications, :vimgrepje recourt aux commandes de ligne de commande grep / find pour organiser plus étroitement la liste des fichiers que je dois refactoriser. Enregistrez la liste dans un fichier texte et utilisez :eun mashup d'enregistrements de macros pour apporter les modifications que je dois apporter.

Je trouve que moins je garde mes compétences d'enregistrement de macros, plus je trouve Vim utile pour la refactorisation: se sentir à l'aise pour enregistrer / restaurer des registres, incrémenter / décrémenter les variables de compteur de registre, nettoyer / enregistrer des enregistrements de macro dans un fichier pour une utilisation ultérieure, etc.


Mettre à jour

Depuis l'écriture de ces vidéos, d'autres vidéos pour les méthodes que je décris ont été publiées sur vimcasts.org (je vous encourage à regarder TOUS les Vimcasts! ). Pour refactoriser, regardez ceux-ci:

Vimgolf est également un excellent moyen de pratiquer.

L'omniprésence des serveurs Language Server Protocol depuis que j'ai écrit cette réponse a également apporté une certaine capacité de refactoring à Vim (et à d'autres éditeurs). IMO, ils sont loin d'être égaux à la capacité de refactorisation des capacités que vous verriez dans un IDE spécialement conçu (je les utilise et je préfère coc et ALE). Voir les autres réponses à cette question pour plus d'informations!

dsummersl
la source
12
Le refactoring est BIEN plus que la correspondance de modèles, c'est pourquoi les IDE sont nécessaires pour automatiser cela de manière sûre. Évidemment, vous pouvez le faire manuellement, mais compte tenu des options disponibles et que la plupart du temps, il est plus sûr de le faire manuellement, pourquoi envisageriez-vous même une autre option?
Cutberto Ocampo
1
@CutbertoOcampo Je suis d'accord avec vous dans une certaine mesure: en fonction de la myriade d'aspects d'un projet (structure, langue (s), compétences et ressources du personnel, pour n'en nommer que quelques-uns), il PEUT y avoir un excellent outil de refactoring applicable à votre problème. Ma réponse s'applique aux situations où ce n'est pas vrai et où vous voulez vous attaquer au problème dans Vim.
dsummersl
2
c'est bien, je comprends que les gens peuvent se sentir plus à l'aise de faire quelque chose en utilisant leurs outils préférés de longue date, et qu'il y a des hacks qui peuvent très bien fonctionner, probablement mieux que n'importe quel IDE, mais pour un hors du commun -box solution Je dirais qu'un IDE réel fonctionnerait mieux pour la plupart des utilisateurs. Je penserais à une situation de 80 à 20% (encore plus, avec l'équilibre en faveur de l'IDE).
Cutberto Ocampo
1
Il existe une idée pour pratiquement toutes les langues. Essayer de refactoriser avec vim ou regex semble absolument insensé. Pourquoi voudriez-vous même essayer?
rouleau le
1
@rolls pour être assez puissant pour attraper la machine dans le besoin d'un collègue aléatoire avec not-your-ide ou tout autre cfg avec lequel vous ne pouvez vivre et laisser une bonne impression (pas pour "juste impression" mais pour la réputation et la position future).
sanglant le
24

Protocole de serveur de langue (LSP)

Le protocole du serveur de langue contient la fonctionnalité permettant de renommer intelligemment les symboles dans un projet:

https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_rename

Par exemple, le serveur de langue suivant prend en charge ceci:

Vous pouvez trouver plus de serveurs de langues sous https://langserver.org/ .

Vigueur

Un client éditeur vim est nécessaire pour les utiliser dans vim. Les options suivantes existent:

  1. LanguageClient-neovim (nécessite rust) suggère le mappage:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (nécessite node.js) suggère le mappage:

    " Remap for rename current word
    nmap <leader>rn <Plug>(coc-rename)
    
  3. Ale a

    nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
    

    Ale ne définit aucune combinaison de touches. Cela doit être fait par l'utilisateur.

  4. vim-lsp fournit la commande suivante

    :LspRename
    

    Semblable à Ale, aucune cartographie n'est suggérée. Cependant, bien sûr, vous pouvez en définir un comme suit

    nmap <leader>r <plug>(lsp-rename)
    

    ( <leader>rdoit être remplacé par votre choix; je n'en connais pas sur lequel la plupart des plugins sont d'accord)

  5. vim-lsc a un mappage par défaut:

    'Rename': 'gR'
    

Voir aussi YouCompleteMe qui facilite également les LSP.

Neovim

Neovim a un support intégré initial pour lsp depuis le 13.11.2019

Consultez les configurations courantes des LSP https://github.com/neovim/nvim-lsp

Cependant, je ne pouvais pas comprendre comment fonctionne le changement de nom intelligent. Si quelqu'un le sait, veuillez mettre à jour cette section.

Autres refactorisations

Je ne sais pas s'il est prévu que le protocole LSP prenne en charge des refactorisations plus complexes, telles que la modification de la structure de classe, l'ajout de paramètres aux méthodes / fonctions ou le déplacement d'une méthode vers une classe différente. Pour une liste des refactorisations, voir https://refactoring.com/catalog/ .

Hotschke
la source
Malheureusement, la prise en charge du refactoring dans le LSP est actuellement assez faible par rapport à l'état de l'art. github.com/Microsoft/language-server-protocol/issues/61
Mickael
AFAIK que renommer pour coc-renamene fonctionne que sur le tampon actuel. Il n'a pas mis à jour l'utilisation du nom exporté globalement dans le projet (entre les fichiers).
oligofren
15

Python

Pour le langage python , les plugins suivants fournissent des capacités de renommage `` intelligentes '' pour vim:

  • jedi-vim( github )<leader>r
  • ropevim( github )CTRL-c r r
  • python-mode( github ):h pymode-rope-refactoring
Hotschke
la source
13

Famille C

  1. Essayez le plugin Clighter pour renommer-refactoring pour la famille c. Il est basé sur clang, mais il y a des limitations et le plugin est marqué comme obsolète.

    La cartographie suggérée par Clighter est

     nmap <silent> <Leader>r :call clighter#Rename()<CR>
    

    Notez que le plug-in successeur clighter8 a supprimé la fonctionnalité de changement de nom dans le commit 24927db42 .

  2. Si vous utilisez neovim, vous pouvez jeter un œil à la pince du plugin . Ça suggère

     nmap <silent> <Leader>r :call ClampRename()<CR>
    
BB Chung
la source
5

J'ai écrit ce plugin pour le refactoring générique. Il nécessite encore de nombreuses améliorations. Dans le futur, j'essaierai d'abandonner les ctags au profit de clang pour les refactorisations C & C ++.

Luc Hermitte
la source
4

Peut-être pas la solution la plus élégante, mais je l'ai trouvée très pratique: j'utilise ECLIM pour connecter VIM et Eclipse. Bien sûr, toute mon édition de code source est effectuée en VIM, mais quand il est temps de refactoriser, on peut profiter des capacités supérieures d'Eclipse dans ce domaine.

Essaie.

fjrg76
la source
3

Plugin Factorus

Il existe un autre plugin vim dédié au refactoring appelé factorus qui est disponible sur github .

Actuellement (2017-12), il prend en charge les langues

  • c,
  • java et
  • python.
Hotschke
la source
3

Plugin YouCompleteMe ( YCM ) (20k étoiles sur github)

http://ycm-core.github.io/YouCompleteMe/#the-refactorrename-new-name-subcommand

:h RefactorRename-new-name

Dans les types de fichiers pris en charge, cette commande tente d'effectuer un changement de nom sémantique de l'identificateur sous le curseur. Cela comprend le changement de nom des déclarations, des définitions et des utilisations de l'identificateur, ou toute autre action appropriée au langage. Le comportement spécifique est défini par le moteur sémantique utilisé.

Similaire à FixIt, cette commande applique des modifications automatiques à vos fichiers source. Les opérations de changement de nom peuvent impliquer des modifications de plusieurs fichiers, qui peuvent ou non être ouverts dans les tampons Vim à ce moment-là. YouCompleteMe gère tout cela pour vous. Le comportement est décrit dans la section suivante.

Pris en charge dans les types de fichiers: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs

Par défaut, il n'y a pas de mappage.

Hotschke
la source
Donc, pour l'instant, cela ne fonctionne que pour javascript, typescript et java?
SR
2

Placez le curseur sur le nom pour refactoriser et taper

gd(ou gDsi vous refactorisez une variable globale).

ensuite

cgn nouveau nom esc

et

. une ou plusieurs fois pour refactoriser l'occurrence (s) suivante (s)

ou

:%norm . pour refactoriser toutes les occurrences dans le tampon à la fois.

Gérémie
la source
1

J'écris beaucoup de code C / C ++ dans vim. Le refactoring le plus courant que je fais est de renommer les variables, les noms de classe, etc. Habituellement, j'utilise :bufdo :%s/source/dest/gpour faire une recherche / remplacement dans des fichiers, ce qui est presque le même que le changement de nom fourni par les grands IDE.
Cependant, dans mon cas, j'ai trouvé que je renomme généralement des entités similaires, épelées dans des cas différents (par exemple, CamelCase, snake_case, etc.), j'ai donc décidé d'écrire un petit utilitaire pour aider à ce genre de recherche "smart-case" / replace, il est hébergé ici . C'est un utilitaire de ligne de commande, pas un plugin pour vim, j'espère que vous pourrez le trouver utile.

dkrikun
la source
0

Pour la refactorisation, si vous utilisez Unite (et vous devriez), vous pouvez alors utiliser vim-qfreplace et le rendre extrêmement facile. Regardez cette vidéo qui montre comment cela fonctionne. Une fois votre flux de travail défini, vous pouvez faire des mappages pour l'optimiser (au lieu de saisir la plupart des choses comme dans la vidéo).

BenC
la source
0

Une combinaison de deux plugins: vim-ripgrep , pour rechercher dans les fichiers et placer les résultats dans la fenêtre quickfix, et quickfix-reflector pour enregistrer les modifications directement dans la fenêtre quickfix et enregistrer automatiquement chaque modification dans les fichiers.

Jason
la source
0

J'envisagerais d'utiliser la version spacemacs d'emacs. Il utilise les mêmes modes et la plupart des frappes de touches que Vim mais a beaucoup plus de modules complémentaires en raison de sa nature lisp. Si vous voulez programmer en C ++, vous ajoutez simplement la couche C ++ et la plupart de l'EDI est déjà configuré pour vous. Pour d'autres langages interprétés comme python ou bash, vous n'avez pas besoin de quitter spacemacs pour les utiliser. Ils ont même un moyen d'exécuter des blocs de code directement dans votre texte, ce qui fonctionne parfaitement pour la programmation littéraire ou la programmation reproductible où le code et les données sont dans le même fichier. Les deux sont faits sous forme de texte.

Spacemacs est beaucoup plus lourd dans sa charge initiale, mais les choses supplémentaires que vous pouvez en faire valent les quelques secondes de coût de démarrage. Un mode d'organisation d'une couche vaut la peine d'être vérifié. C'est le meilleur outliner, programmeur, minuterie de jour / liste de tâches que j'ai jamais utilisé.

C. Kelly Osborn
la source
0

Aller

  1. L'outil godoctor ( github ) prend en charge plusieurs capacités de refactoring
  • Renommer
  • Fonction d'extraction
  • Extraire la variable locale
  • Basculer var ⇔: =
  • Ajouter des stubs Godoc

Il existe un plugin vim https://github.com/godoctor/godoctor.vim qui les rend disponibles

Avec le curseur dans la chose à renommer:

:Rename <newname>

Bloc de surbrillance à extraire:

:Refactor extract newfunc
  1. vim-go

    • Renommage précis des identificateurs de type sécurisé avec :GoRename.
  2. Serveur de langue gopls

Hotschke
la source