Variablennamen in Vim ändern

94

Ich versuche, viel C / Perl-Code über Vim zu lesen, der viele Ein-Buchstaben-Variablennamen enthält.

Es wäre schön, einen Befehl zu haben, der mir helfen könnte, den Namen einer Variablen in einen aussagekräftigeren zu ändern, während ich gerade den Code lese, damit ich den Rest schneller lesen kann.

Gibt es in Vim einen Befehl, mit dem ich das schnell erledigen kann?

Ich glaube nicht, dass Regexe funktionieren würden, weil:

  1. Der gleiche Name eines einzelnen Buchstabens kann in verschiedenen Bereichsblöcken unterschiedliche Zwecke haben

  2. Die gleiche Buchstabenkombination könnte Teil eines anderen größeren Variablennamens sein oder in einer Zeichenfolge oder einem Kommentar ... möchte diese nicht ändern

Irgendwelche bekannten Lösungen?

Aditya Mukherji
quelle

Antworten:

196

Im Folgenden wird beschrieben, wie Sie eine Variable umbenennen, die im aktuellen Bereich definiert ist {}.

Bewegen Sie den Cursor auf die variable Verwendung. Drücken Sie gd. Was bedeutet - bewegen Sie den Cursor auf die Definition. Drücken [{Sie jetzt - dies bringt Sie zum Beginn des Bereichs. Drücken Sie V-, um die visuelle Linienauswahl zu aktivieren. Drücken Sie %-, um zum Gegenteil zu springen }und den gesamten Bereich auszuwählen. Drücken Sie :s/- Start des Ersatzbefehls. <C-R>/- fügt ein Muster ein, das dem Variablennamen entspricht (dem Namen, auf dem Sie vor dem Drücken waren gd). /newname/gc<CR>- leitet die Suche ein und ersetzt sie bei jedem Spiel durch eine Bestätigung.

Jetzt müssen Sie ein Makro aufnehmen oder noch besser - einen Schlüssel zuordnen.

Hier sind die endgültigen Zuordnungen:

" 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>

Legen Sie dies auf Ihre .vimrcoder führen Sie es einfach aus. Nach diesem Drücken grauf die lokale Variable gelangen Sie zum :sBefehl, wo Sie einfach eingeben new_variable_nameund drücken sollten Enter.

Mykola Golubyev
quelle
39
+1 für das Erlernen von mehr als 5 neuen Vim-Tricks, die ich vorher hätte kennen müssen. Vielen Dank
Kenny Meyer
6
Hinweis: gd funktioniert nicht, um die Variable im unmittelbaren Definitionsbereich im Javascript-Modus in Macvim zu finden. Ich komme zur ersten Verwendung des Variablennamens in einer Funktion in der Datei :( Wenn Sie sich in einem bestimmten Bereich befinden und diesen Bereich auswählen möchten, ist "va {" - "visuelle Auswahl um {" - der richtige Weg Ich denke.
Srikumar
3
Eine leicht verbesserte Version: gist.github.com/048616a2e3f5d1b5a9ad fordert den Benutzer auf, zeigt den alten Namen an, stellt die Cursorposition nach dem Ersetzen wieder her
Andy Ray
7
+1 sehr gutes Vimgineering (ich glaube, ich habe gerade einen neuen Begriff geprägt). Hinweis: Ich musste tatsächlich :zweimal Doppelpunkt ( ) drücken . Als ich es zum ersten Mal drückte, sah ich :'<,'>. Wenn ich nur s/von dort aus tippte , funktionierte es nicht. Ich musste vor dem einen weiteren Doppelpunkt eingeben s/.
Kelvin
6
Beachten Sie, dass Sie <C-R>den Ersatzbefehl nicht benötigen. Wenn Sie die Suche einfach weglassen, verwendet vim das zuletzt gesuchte Muster, das in diesem Fall aus dem gdBefehl erstellt wurde. Es reicht also aus, es einfach zu tun :s//<newname>/gc.
Shangxiao
10

AFAIK, es gibt keine tatsächliche Refactoring-Unterstützung in VIM. Bei einer Umbenennung mit der Absicht eines Refaktors treffe ich normalerweise die folgenden Vorsichtsmaßnahmen:

  1. Begrenzen Sie den Umfang der Änderung durch die Verwendung von Marken.
  2. Wenn Sie den regulären Ausdruck eingeben, setzen Sie den Namen mit \ <und> in Klammern. Dadurch wird es mit einem ganzen Wort übereinstimmen, wodurch die Anzahl der falschen Umbenennungen verringert wird.
  3. Führen Sie keinen mehrzeiligen Austausch durch, um die Wahrscheinlichkeit eines schlechten Ersatzes zu verringern
  4. Sehen Sie sich den Code diff genau an, wenn es sich nicht um eine kleine Änderung handelt.

Meine Endänderung sieht ungefähr so ​​aus

:'a,'bs/\<foo\>/bar

Ich würde gerne falsch liegen, wenn es kein Refactoring-Tool für VIM gibt, aber ich habe es nicht gesehen.

JaredPar
quelle
In Perl können Sie den Typ auch zum Suchmuster hinzufügen. dh $ für Skalare, @ für Arrays,% für Hashes
Nathan Fellman
@ Nathan: Leider ist es in Perl (5.X) etwas schwieriger, da sich das Siegel von Arrays und Hashes mit der Verwendung ändert:% hash -> ganzer Hash, $ hash {key} -> einzelner Wert, @hash { qw / ab /} Hash-Slice.
user55400
9

Ich weiß, dass es eine alte Frage ist, und @ mykola-golubyevs Weg ist offensichtlich die beste Antwort für den speziellen Fall in der OP-Frage (die vermutlich verschleierten Code durchläuft, bei dem Sie wahrscheinlich mehrere Blöcke mit denselben Variablennamen haben). ;; Aber mit dem Namen dieser Frage suchen viele Leute, die von Google Search hierher kommen, wahrscheinlich nach weniger situationsspezifischen Möglichkeiten, Variablen in VIM umzubenennen - und diese können präziser sein

Ich bin überrascht, dass niemand so vorgeschlagen hat:

* :s// NEUER NAME /gc

Das *ist die gleiche wie gn- es ist für das nächste Vorkommen des Wortes unter Cursor sucht , und es wird die letzte Muster gesucht, so dass , wenn Sie das Suchmuster in dem Ersatz Befehl weglassen, VIM setzt dies voraus , das Muster zu suchen ist.

Für kleine Mengen von Var-Kopien eine noch schnellere:

* cw NEWNAME wird <esc> dann n.für andere Vorkommen wiederholt

Suche nach Vorkommen, cwist der Befehl zum Ändern des Wortes , wechselt nzum nächsten Vorkommen des zuletzt gesuchten Begriffs und .wiederholt den letzten Befehl (das ist das Ändern des Wortes in NEWNAME ).

(Credits für mich, das alles zu wissen, gehen an @doomedbunnies auf Reddit )

Ein weiterer cooler Trick ist folgender: ( Credits für @ nobe4 )

* cgn NEWNAME wird <esc> dann .für andere Vorkommen wiederholt

cgnist "Ändern, was auch immer das Ergebnis ist (nächstes Vorkommen finden)". Jetzt, da dies der letzte Befehl ist , müssen Sie nicht nmehr zum nächsten Vorkommen wechseln, also wieder weniger Striche und, was noch wichtiger ist, müssen Sie nicht abwechseln nund .. Aber offensichtlich hat dieser den Nachteil, dass es nicht möglich ist, ein Ereignis zu überspringen.

Hier sind einige Vorteile:

  • Keine Zuordnung, kein .vimrc (oder init.vim), sodass Sie es in jeder VIM-Kopie verwenden können, auf die Sie stoßen (z. B. eine schnelle Aufgabe auf einem VPS oder dem Computer Ihres Freundes, bei der die Konfiguration von VIM auf Ihre Weise den Zweck von "schnell" zunichte macht. )
  • Die Verwendung von *oder gnzur Wortauswahl ist sehr schnell - nur ein Tastendruck (sagen wir mal 1,5)
  • Verwenden Sie *oder stellen gnSie sicher, dass Sie keine Übereinstimmungen mit anderen Worten erhalten, genau wie dies der :%s/<C-R>//gcFall ist. Beats, die :%s/\<OLDNAME\>/NEWNAME/gcvon Hand tippen : Ich persönlich vergesse oft, die \<Dinge zu verwenden, um Übereinstimmungen nur auf ganze Wörter zu beschränken.
  • Wenn Sie den Bereich nicht verwenden, werden nur einige zusätzliche Striche ausgeführt n, um unerwünschte Übereinstimmungen zu überspringen - wahrscheinlich sogar weniger als die zusätzlichen Striche, die zum Einschränken des Bereichs erforderlich sind. Unter normalen Umständen sind Ihre Variablen höchstwahrscheinlich ohnehin etwas in einem bestimmten Codeblock lokalisiert.
Ivan Bartsov
quelle
8

Tragen Sie dies in Ihre .vimrc ein

" 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

Nennen Sie es mit :call Rnvar()

expand("<cword>")Ruft das Wort unter den Cursor. Die Suchzeichenfolge verwendet %für Datei-Umfang und die \(\W\)aussehen Muster für Nicht-Wort - Zeichen an der Grenze des Wortes, zu ersetzen und sie in Variablen speichern \1und \2so wie im Ersetzungsmuster wieder eingesetzt werden.

Mike
quelle
3

Sie können den Modifikator 'c' in der globalen Suche und Ersetzung verwenden, der Sie für jede Ersetzung um Bestätigung bittet. Es würde länger dauern, aber es könnte für eine nicht humongous Codedatei funktionieren:

%s/\$var/\$foo/gc

Das c steht für bestätigen.

Adnan
quelle
Das i steht für Ignorieren. Sie möchten c, bestätigen Sie jede Änderung.
Michael Kristofik
oops .. sorry das .. Die Antwort wurde
korrigiert
Antwort immer noch nicht vollständig behoben;)
user55400
Meinten Sie die entkommenen $? Das ist eine persönliche Präferenz von mir. $ funktioniert ohne Flucht und auch mit und da in der Regex-Welt und in vi $ eine besondere Bedeutung hat, möchte ich es nur aus Gründen der Klarheit entkommen.
Adnan
0

In c können Sie möglicherweise mit cscope einige Fortschritte erzielen. Es wird versucht, die Syntax zu verstehen, sodass Sie wissen können, wann der Buchstabe eine Variable war.

Kim Reece
quelle
0

Wenn dies mehrere Dateien umfasst, sollten Sie sich sed ansehen. Verwenden Sie find, um Ihre Dateien und xargs plus sed für einen Ersatz abzurufen. Angenommen, Sie möchten a in allen Dateien, die mit * .c übereinstimmen, durch a_better_name ersetzen

finden . -name "* .c" | xargs sed -i -es / a / a_better_name / g '

Denken Sie daran, dass dies ALLE Vorkommen von a ersetzt, sodass Sie möglicherweise einen robusteren regulären Ausdruck wünschen.

Drew Olson
quelle