Refactoring in Vim


98

Natürlich ist die Tatsache, dass Sie IDEs umgestalten können, für viele von unschätzbarem Wert. Ich mache es kaum, wenn ich programmiere, aber ich kann versuchen, es zu tun, wenn ich die Quelle eines anderen bearbeite. Wie können Sie eine so triviale Aufgabe in Vim über mehrere Dateien hinweg ausführen?

Ich habe dieses Plugin für das Refactoring von Ruby gefunden, aber wie wäre es mit "irgendeiner" Sprache?


2
Refactoring ist sehr sprachspezifisch. Sie müssen nach spezifischen Add-Ons für jede Sprache suchen, an der Sie interessiert sind. Vermutlich finden Sie Add-Ons für einige und nicht für andere. Wenn Sie eine suchen und nicht finden können, können Sie versuchen, eine zu schreiben, indem Sie ein vorhandenes Add-On für eine andere ähnliche Sprache als Ausgangspunkt verwenden.
Steve Jorgensen

2
VIM wurde entwickelt, um einzelne Dateien und möglicherweise Dateien in einem Verzeichnis zu bearbeiten - keine Projekte . Viele IDE-unterstützte Refactorings wirken sich auf Dateien im gesamten Projekt aus (z. B. Umbenennen einer Klasse). Ich denke, es wäre schwierig, dies mit einem Editor wie (g) VI (m) "richtig" zu machen, bis zu dem Punkt, an dem ich denke, dass ein Unternehmen oder ein großes Projekt es übernehmen müsste. Grundsätzlich müssten sie jede Sprache analysieren, um einfache Zeichenfolgenersetzungen zu vermeiden und fehleranfällig zu werden (ctags gibt einen Teil davon) sowie die entsprechenden Projekttypen (um zu wissen, welche Dateien bearbeitet werden müssen).
Merlyn Morgan-Graham

1
Vielen Dank für die Kommentare. Ich denke, hier wird es langsam schwierig, und der Versuch, VIM an eine IDE zu biegen, ist keine elegante Lösung, um nur ein Programm zum Bearbeiten mehrerer Sprachen zu verwenden. Ich möchte VIM wirklich nicht aufgeben, da einige der "erweiterten" Funktionen in IDEs verfügbar sind.
Helmut Granda

@ MerlynMorgan-Graham - Einige Leute behalten ihren Code nur in wenigen (vielleicht großen) Dateien. Vermeidet dieses Problem insgesamt.
Turm

7
@ldigas: Das würde das Problem umgehen. Es ist jedoch ziemlich gegen die empfohlenen Praktiken für einige Sprachen (z. B. Java). Grundsätzlich biegt sich der Code, um den Anforderungen des Werkzeugs zu entsprechen, wenn es eigentlich umgekehrt sein sollte.
Merlyn Morgan-Graham

Antworten:


75

Ich stimme dem Paradigma „Vim ist keine IDE“ zu. Aber es gibt Zeiten, in denen es keine IDE gibt. Folgendes verwende ich in diesen Situationen:

: grep ,: vimgrep ,: Ag ,: Ggrep

Refactoring, das mehr mit regelmäßigen Ersetzungen zu tun hat, verwende ich normalerweise : grep in meinem Projektbaum und zeichne dann ein Makro auf, um den Refactor auszuführen -: g und: s sind keine Denker. Normalerweise kann ich so eine große Anzahl von Dateien mit sehr geringem Aufwand schnell ändern. Ehrlich gesagt verwende ich diese Methode mehr als jede andere.

Abhängig von Ihrem Workflow können die integrierten Befehle langsam / unpraktisch sein. Wenn Sie git verwenden, möchten Sie das hervorragende Fugitive- Plugin und seinen :GgrepBefehl verwenden, um nur Dateien zu durchsuchen, die in git eingecheckt sind. Ich mag auch den Silver Searcher wegen seiner Schnelligkeit.

: argdo ,: cdo und: bufdo

: cdo und : argdo sind praktisch, um vim-Befehle über eine Reihe von Dateien auszuführen.

Befehlszeile

Wenn es schwieriger ist, die Liste der Dateien zu ermitteln, die geändert werden müssen, greife :vimgrepich auf die Befehlszeile grep / find-Befehle zurück, um die Liste der Dateien, die ich umgestalten muss, genauer zu kuratieren. Speichern Sie die Liste in einer Textdatei und verwenden Sie :eein Mashup von Makroaufzeichnungen, um die Änderungen vorzunehmen, die ich vornehmen muss.

Ich finde, je weniger verrostet ich meine Makroaufzeichnungsfähigkeiten behalte, desto nützlicher finde ich Vim für das Refactoring: Wohlfühlen beim Speichern / Wiederherstellen aus Registern, Inkrementieren / Dekrementieren von Registerzählervariablen, Bereinigen / Speichern von Makroaufzeichnungen in Dateien zur späteren Verwendung usw.


Aktualisieren

Seit dem Schreiben dieser weiteren Videocasts für die von mir beschriebenen Methoden wurden sie auf vimcasts.org veröffentlicht (ich empfehle Ihnen, ALLE Vimcasts anzusehen! ). Beachten Sie zum Refactoring die folgenden:

Vimgolf ist auch eine großartige Möglichkeit zum Üben.

Die Allgegenwart von Language Server Protocol-Servern seit ich diese Antwort geschrieben habe, hat Vim (und anderen Editoren) auch einige Refactoring-Funktionen eingebracht. IMO sind sie weit davon entfernt, die Fähigkeit zum Refactoring zu erreichen, die Sie in einer speziell entwickelten IDE sehen würden (ich verwende sie und bevorzuge Coc und ALE). Weitere Antworten auf diese Frage finden Sie unter!


12
Refactoring ist weit mehr als Mustervergleich. Deshalb werden IDEs benötigt, um dies auf sichere Weise zu automatisieren. Natürlich können Sie dies manuell tun, aber angesichts der verfügbaren Optionen und der Tatsache, dass es meistens sicherer ist, dies manuell zu tun, warum sollten Sie überhaupt eine andere Option in Betracht ziehen?
Cutberto Ocampo

1
@CutbertoOcampo Ich stimme Ihnen in gewissem Maße zu: Abhängig von unzähligen Aspekten eines Projekts (Struktur, Sprache (n), Fähigkeiten und Ressourcen des Personals, um nur einige zu nennen) kann es ein großartiges Refactoring-Tool geben, das auf Ihr Problem anwendbar ist. Meine Antwort gilt für Situationen, in denen dies nicht der Fall ist und Sie das Problem in Vim angehen möchten.
dsummersl

2
Das ist in Ordnung, ich verstehe, dass die Leute sich mit ihren seit langem bevorzugten Tools wohler fühlen und dass es einige Hacks gibt, die wirklich gut funktionieren können, wahrscheinlich besser als jede andere IDE da draußen, aber für einen Außenseiter -box Lösung Ich würde sagen, eine tatsächliche IDE würde für die meisten Benutzer eine bessere Leistung erbringen. Ich würde über eine Situation von 80 bis 20% nachdenken (noch mehr, mit dem Gleichgewicht zugunsten der IDE).
Cutberto Ocampo

1
Für praktisch jede Sprache gibt es eine Idee. Der Versuch, mit Vim oder Regex umzugestalten, klingt absolut verrückt. Warum würdest du es überhaupt versuchen?
rollt

1
@rolls, um stark genug zu sein, um die bedürftige Maschine eines zufälligen Kollegen mit not-your-ide oder was auch immer cfg zu greifen, mit der Sie nur leben können, und einen guten Eindruck zu hinterlassen (nicht für "nur Eindruck", sondern für Ruf und zukünftige Position).
blutiger

23

Language Server Protocol (LSP)

Das Sprachserverprotokoll enthält die Funktion zum intelligenten Umbenennen von Symbolen in einem Projekt:

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

Zum Beispiel unterstützen folgende Sprachserver dies:

Weitere Sprachserver finden Sie unter https://langserver.org/ .

Vim

Ein vim editor client ist erforderlich, um sie in vim zu verwenden. Folgende Optionen stehen zur Verfügung:

  1. LanguageClient-neovim (benötigt Rost) schlägt die Zuordnung vor:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (erfordert node.js) schlägt die Zuordnung vor:

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

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

    Ale definiert keine Tastenkombinationen. Dies muss vom Benutzer durchgeführt werden.

  4. vim-lsp bietet den folgenden Befehl

    :LspRename
    

    Ähnlich wie bei Ale wird keine Zuordnung vorgeschlagen. Natürlich können Sie eine wie folgt definieren

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

    ( <leader>rsoll durch deine Wahl ersetzt werden; ich kenne keine, über die sich die meisten Plugins einig sind)

  5. vim-lsc hat eine Standardzuordnung:

    'Rename': 'gR'
    

Siehe auch YouCompleteMe , das auch LSPs unterstützt.

Neovim

Neovim hat seit dem 13.11.2019 erste integrierte Unterstützung für lsp

Allgemeine Konfigurationen von LSPs finden Sie unter https://github.com/neovim/nvim-lsp

Ich konnte jedoch nicht herausfinden, wie intelligentes Umbenennen funktioniert. Wenn jemand dies weiß, aktualisieren Sie bitte diesen Abschnitt.

Andere Refactorings

Ich weiß nicht, ob es Pläne für das LSP-Protokoll gibt, komplexere Refactorings zu unterstützen, z. B. das Ändern der Klassenstruktur, das Hinzufügen von Parametern zu Methoden / Funktionen oder das Verschieben einer Methode in eine andere Klasse. Eine Liste der Refactorings finden Sie unter https://refactoring.com/catalog/ .


Leider ist die Unterstützung für das Refactoring im LSP derzeit im Vergleich zum Stand der Technik ziemlich schwach. github.com/Microsoft/language-server-protocol/issues/61
Mickael

AFAIK, dass das Umbenennen coc-renamenur für den aktuellen Puffer funktioniert. Die Verwendung des exportierten Namens global im Projekt (über Dateien hinweg) wurde nicht aktualisiert.
Oligofren

15

Python

Für die Python- Sprache bieten die folgenden Plugins 'intelligente' Umbenennungsfunktionen für vim:

  • jedi-vim( Github )<leader>r
  • ropevim( Github )CTRL-c r r
  • python-mode( Github ):h pymode-rope-refactoring

13

C-Familie

  1. Probieren Sie das Plugin Clighter zum Umbenennen-Refactoring für die C-Familie aus. Es basiert auf Clang, aber es gibt Einschränkungen und das Plugin ist als veraltet markiert.

    Vorgeschlagene Zuordnung von Clighter ist

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

    Beachten Sie, dass das Nachfolge-Plugin clighter8 die Umbenennungsfunktion im Commit 24927db42 entfernt hat .

  2. Wenn Sie neovim verwenden, können Sie sich die Plugin- Klemme ansehen . Es schlägt vor

     nmap <silent> <Leader>r :call ClampRename()<CR>
    

5

Ich habe dieses Plugin für generisches Refactoring geschrieben. Es sind noch viele Verbesserungen erforderlich. Irgendwann in der Zukunft werde ich versuchen, ctags zugunsten von Clang für C & C ++ Refactorings aufzugeben.


4

Vielleicht nicht die eleganteste Lösung, aber ich fand sie sehr praktisch: Ich verwende ECLIM , um VIM und Eclipse zu verbinden. Natürlich erfolgt die gesamte Bearbeitung meines Quellcodes in VIM, aber wenn es Zeit für eine Umgestaltung ist, kann man die überlegenen Funktionen von Eclipse in dieser Angelegenheit nutzen.

Versuche es.


3

Plugin Factorus

Es gibt ein weiteres Vim-Plugin für das Refactoring namens Factorus, das auf Github verfügbar ist .

Derzeit (2017-12) unterstützt es die Sprachen

  • c,
  • Java und
  • Python.

3

Plugin YouCompleteMe (YCM) (20.000 Sterne auf Github)

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

:h RefactorRename-new-name

In unterstützten Dateitypen versucht dieser Befehl, eine semantische Umbenennung des Bezeichners unter dem Cursor durchzuführen. Dies umfasst das Umbenennen von Deklarationen, Definitionen und Verwendungen des Bezeichners oder jede andere sprachgerechte Aktion. Das spezifische Verhalten wird von der verwendeten semantischen Engine definiert.

Ähnlich wie bei FixItdiesem Befehl werden automatische Änderungen an Ihren Quelldateien vorgenommen. Umbenennungsvorgänge können Änderungen an mehreren Dateien beinhalten, die zu diesem Zeitpunkt möglicherweise in Vim-Puffern geöffnet sind oder nicht. YouCompleteMe erledigt das alles für Sie. Das Verhalten wird im folgenden Abschnitt beschrieben.

Unterstützt in Dateitypen: c, cpp, objc, objcpp, cuda, java, Javascript, Typoskript, Rost, cs

Standardmäßig gibt es keine Zuordnung.


Im Moment funktioniert dies also nur für Javascript, Typoskript und Java?
SR

2

Setzen Sie den Cursor auf den Namen, um ihn umzugestalten und einzugeben

gd(oder gDwenn Sie eine globale Variable umgestalten).

Dann

cgn neuer Name esc

und

. ein oder mehrere Male, um die nächsten Vorkommnisse umzugestalten

oder

:%norm . um alle Vorkommen im Puffer auf einmal umzugestalten.


1

Ich schreibe viel C / C ++ - Code in vim. Das häufigste Refactoring, das ich durchführe, ist das Umbenennen von Variablen, Klassennamen usw. Normalerweise verwende ich das :bufdo :%s/source/dest/gSuchen / Ersetzen in Dateien, was fast dem Umbenennen entspricht, das von großen IDEs bereitgestellt wird.
In meinem Fall stellte ich jedoch fest, dass ich normalerweise ähnliche Entitäten umbenenne, die in verschiedenen Fällen geschrieben wurden (z. B. CamelCase, snake_case usw.), und entschied mich daher, ein kleines Dienstprogramm zu schreiben, um bei dieser Art der Suche nach "intelligenten Fällen" zu helfen. ersetzen, es wird hier gehostet . Es ist ein Befehlszeilenprogramm, kein Plugin für vim. Ich hoffe, Sie finden es nützlich.


0

Wenn Sie für das Refactoring Unite verwenden (und sollten), können Sie vim-qfreplace verwenden und es extrem einfach machen. Überprüfen Sie dieses Video , das zeigt, wie es funktioniert. Sobald Ihr Workflow festgelegt ist, können Sie einige Zuordnungen vornehmen, um ihn zu optimieren (anstatt die meisten Dinge wie im Video einzugeben).


0

Eine Kombination aus zwei Plugins: vim-ripgrep , um Dateien zu finden und die Ergebnisse in das Quickfix-Fenster zu stellen, und Quickfix-Reflector , um die Änderungen direkt im Quickfix-Fenster zu speichern und jede Änderung automatisch in den Dateien zu speichern.


0

Ich würde in Betracht ziehen, die Spacemacs-Version von Emacs zu verwenden. Es verwendet die gleichen Modi und die meisten Tastenanschläge wie Vim, verfügt jedoch aufgrund seiner Lisp-Natur über viel mehr Add-Ons. Wenn Sie in C ++ programmieren möchten, fügen Sie einfach die C ++ - Ebene hinzu und der größte Teil der IDE ist bereits für Sie eingerichtet. Für andere interpretierte Sprachen wie Python oder Bash müssen Sie keine Spacemacs hinterlassen, um sie zu verwenden. Sie haben sogar die Möglichkeit, Codeblöcke direkt in Ihrem Text auszuführen, was sich hervorragend für die literarische Programmierung oder reproduzierbare Programmierung eignet, bei der sich Code und Daten in derselben Datei befinden. Beides als Text gemacht.

Spacemacs ist in seiner anfänglichen Ladung viel schwerer zu handhaben, aber das zusätzliche Zeug, das Sie damit machen können, ist die wenigen Sekunden Startkosten wert. Ein Layer-Org-Modus ist einen Besuch wert. Es ist der beste Outliner, Programmierer, Day Timer / ToDo-Liste, den ich je benutzt habe.


0

Gehen

  1. Der Tool Godoctor ( Github ) unterstützt verschiedene Refactoring-Funktionen
  • Umbenennen
  • Funktion extrahieren
  • Lokale Variable extrahieren
  • Var ⇔: = umschalten
  • Godoc-Stubs hinzufügen

Es gibt ein Vim-Plugin https://github.com/godoctor/godoctor.vim , das sie zur Verfügung stellt

Mit dem Cursor in Sache umbenennen:

:Rename <newname>

Markierungsblock zum Extrahieren:

:Refactor extract newfunc
  1. vim-go

    • Präzise typsichere Umbenennung von Bezeichnern mit :GoRename.
  2. Sprachserver gopls

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.