Vimで変数名を変更する


94

多くの1文字の変数名を含む多くのC / PerlコードをVimから読み取ろうとしています。

コードを読んでいる最中に変数の名前をより意味のあるものに変更できるように、残りの部分をより速く読み取ることができるコマンドがあると便利です。

Vimにこれをすばやく実行できるコマンドはありますか?

正規表現が機能するとは思わない:

  1. 同じ1文字の名前は、異なるスコープブロックで異なる目的を持つ場合があります

  2. 同じ文字の組み合わせが別の大きなvar名の一部であるか、文字列またはコメントに含まれている可能性があります...それらを変更したくない

既知の解決策はありますか?

回答:


196

以下は、現在のスコープで定義されている変数の名前を変更する方法{}です。

変数の使用法にカーソルを移動します。を押しgdます。つまり、カーソルを定義に移動します。Now Press- [{これでスコープが始まります。V-を押すと、ビジュアルラインの選択がオンになります。%-を押すと反対にジャンプし、}スコープ全体が選択されます。押す:s/-置換コマンドの開始。 <C-R>/-変数名に一致するパターンを挿入します(その名前はを押す前にオンでしたgd)。 /newname/gc<CR>-検索を開始し、すべての一致で確認に置き換えます。

ここで、マクロを記録するか、さらにはキーをマップする必要があります。

最終的なマッピングは次のとおりです。

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

これをあなたに置く.vimrcか、単に実行してください。この後gr、ローカル変数を押すと、:s単に入力してnew_variable_nameを押すだけのコマンドが表示されますEnter


39
以前に知っておくべき5つ以上の新しいVimトリックを学ぶための+1。ありがとう
ケニーマイヤー

6
注:gdは、macvimのJavascriptモードで定義の直接のスコープ内で変数を見つけるために機能しません。ファイル内のいくつかの関数で変数名を最初に使用する:(あるスコープ内にあり、そのスコープを選択する場合は、「va {」-「visual select around {」-を使用する方法です私は思う。
Srikumar

3
少し改良されたバージョン:gist.github.com/048616a2e3f5d1b5a9adはユーザーにプロンプ​​トを表示し、古い名前を表示し、置換後にカーソル位置を復元します
Andy Ray

7
非常に良いvimgineering +1(新しい用語を作ったばかりだと思います)。注:実際には、コロン(:)を2回押す必要がありました。初めて押した時、見ました:'<,'>s/そこから入力しただけではうまくいきませんでした。の前に別のコロンを入力する必要がありましたs/
Kelvin

6
<C-R>置換コマンドでは必要ないことに注意してください。単に検索を省略すると、vimは最後に検索されたパターンを使用しますgd。このパターンは、この場合はコマンドから作成されたものです。したがって、単に実行:s//<newname>/gcするだけで十分です。
shangxiao 2017年

10

AFAIK、VIMでは実際のリファクタリングのサポートはありません。リファクタリングの目的で名前を変更するとき、私は通常、次の予防策を講じます。

  1. 使用マークを変更の範囲を制限します。
  2. 正規表現を入力するときは、名前を\ <と>で囲みます。これにより、単語全体と一致するようになり、発生する不正な名前変更の種類が減ります。
  3. 悪い置換の可能性を減らすために複数行の置換を行わないでください
  4. 小さな変更以外の場合は、コードdiffを注意深く確認してください。

私の最終変更はこのようなものです

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

VIMのリファクタリングツールがないのは間違いですが、見たことがありません。


Perlでは、タイプを検索パターンに追加することもできます。つまり、スカラーの場合は$、配列の場合は@、ハッシュの場合は%
Nathan Fellman

@Nathan:残念ながら、Perl(5.X)では、配列とハッシュのシギルが使用法によって変化するため、少し難しいです:%hash->全体のハッシュ、$ hash {key}->単一の値、@ hash { qw / ab /}ハッシュスライス。
user55400 2009年

9

私はそれが古い質問であることを知っており、@ mykola-golubyevの方法は明らかにOP質問の特定のケースに対する最良の答えです(これは、同じvar名の複数のブロックがある可能性がある難読化されたコードを通過することを想定しています) ; しかし、そのような質問名で、Google検索からここに来る多くの人々は、おそらくVIMで変数の名前を変更するための、状況固有ではない方法を探します-それらはより簡潔にすることができます

私は誰もこの方法を提案していないことに驚いています:

* :s// 新しい名前 /gc

これ*は同じですgn-カーソルの下にある単語の次の出現を検索し、それが最後に検索されたパターンになるので、代用コマンドで検索パターンを省略すると、VIMはこれを検索するパターンであると見なします。

少量のvarコピーの場合、さらに高速なコピー:

* cw NEWNAME <esc>n.、他の発生についても繰り返します

出現を検索、cwするコマンドで変更ワードn最後に検索用語の次の出現に行くと.(ある最後のコマンド繰り返されNEWNAMEに変更単語を

(これをすべて知っている私のクレジットは、Redditの@doomedbunniesに移動します

別のクールなトリックはこれです:(@ nobe4へのクレジット

* cgn NEWNAME <esc>.、他の発生についても繰り返します

cgn「(次のオカレンスを見つける)の結果を変更する」です。さて、これがあることを最後のコマンドは、次のものが必要ませんn、もっと重要なのは、再び、次の発生にとても少ないストロークを行く、とする代替に必要nとします.。しかし、明らかに、これには発生をスキップする方法がないという欠点があります。

ここにいくつかの利点があります:

  • マッピングも.vimrc(またはinit.vim)もないので、出会ったVIMコピーで使用できます(たとえば、VPSを設定したり、友達のマシンで簡単にVIMを構成したりすると、「クイック」の目的が損なわれます。 )
  • *またはgn単語の選択に使用するのは非常に迅速です-たった1回のキーストローク(まあ、1.5としましょう)
  • 使用*またはgnあなたが同じように、つまり内部の任意の一致を得ることはありませんになり:%s/<C-R>//gcません。:%s/\<OLDNAME\>/NEWNAME/gc手でタイプするのに勝る:私は個人的に、\<一致を単語全体に限定するために使用することを忘れがちです。
  • スコープを使用しnないと、不要な一致をスキップするための余分なストロークがいくつか発生します-スコープを制限するために必要な余分なストロークよりもさらに少ない可能性があります。通常の状況下では、変数はとにかく特定のコードブロックにローカライズされる可能性があります。

8

これを.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

で呼び出す :call Rnvar()

expand("<cword>")カーソルの下の単語を取得します。検索文字列が使用する%ファイル・スコープのため、と\(\W\)パターンが交換する単語の境界に非単語の文字を探して、変数に保存\1し、\2その置換パターンに再挿入されるように。


3

グローバル検索で「c」修飾子を使用して、置換ごとに確認を求める置換を行うことができます。時間がかかりますが、それほど大きなコードファイルでは機能しない可能性があります。

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

cは確認を意味します。


iはignore-caseを表します。あなたはcを求め、すべての変更を確認します。
マイケルクリストフィク

おっと..申し訳ありません..答えを修正しました
アドナン

回答はまだ完全に修正されていません;)
user55400 2009年

エスケープされた$を意味しましたか?それは私の個人的な好みのようなものです。$はエスケープなしでも機能します。正規表現の世界ではviでも$は特別な意味があるため、わかりやすくするためにエスケープします。
アドナン

0

cでは、cscopeを使用してある程度の進歩を遂げることができる場合があります。構文を理解しようとするので、文字が変数であるときを知るチャンスがあります。


0

これが複数のファイルにわたる場合は、sedを確認することを検討してください。findを使用してファイルとxargsを取得し、置換のためにsedを使用します。* .cに一致するすべてのファイルでaをa_better_nameに置き換えたいとします。

見つける。-name "* .c" | xargs sed -i -e 's / a / a_better_name / g'

これはaのすべての出現を置き換えることに注意してください。そのため、より堅牢な正規表現が必要になる場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.