Mengubah nama variabel di Vim

96

Saya mencoba membaca banyak kode C / Perl melalui Vim yang berisi banyak nama variabel huruf tunggal.

Alangkah baiknya memiliki beberapa perintah yang dapat membantu saya mengubah nama variabel menjadi sesuatu yang lebih bermakna saat saya dalam proses membaca kode sehingga saya dapat membaca sisanya dengan lebih cepat.

Apakah ada perintah di Vim yang memungkinkan saya melakukan ini dengan cepat?

Saya tidak berpikir regex akan berfungsi karena:

  1. nama satu huruf yang sama mungkin memiliki tujuan yang berbeda di blok cakupan yang berbeda

  2. kombinasi huruf yang sama dapat menjadi bagian dari nama var lain yang lebih besar, atau dalam string atau komentar ... tidak ingin mengubahnya

Ada solusi yang diketahui?

Aditya Mukherji
sumber

Jawaban:

198

Berikut ini adalah cara mengganti nama variabel yang didefinisikan dalam lingkup saat ini {}.

Pindahkan kursor Anda ke penggunaan variabel. Tekan gd. Artinya - pindahkan kursor ke definisi. Sekarang Tekan [{- ini akan membawa Anda ke ruang lingkup dimulai. Tekan V- akan mengaktifkan pemilihan Garis Visual. Tekan %- akan melompat ke arah sebaliknya }sehingga akan memilih seluruh cakupan. Tekan :s/- mulai dari perintah pengganti. <C-R>/- akan memasukkan pola yang cocok dengan nama variabel (nama yang Anda gunakan sebelum menekan gd). /newname/gc<CR>- akan memulai pencarian dan mengganti dengan konfirmasi pada setiap pertandingan.

Sekarang Anda harus merekam makro atau bahkan lebih baik - memetakan kunci.

Berikut adalah pemetaan terakhir:

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

Taruh ini untuk Anda .vimrcatau jalankan saja. Setelah ini menekan grpada variabel lokal akan membawa Anda ke :sperintah di mana Anda harus masuk new_variable_namedan menekan Enter.

Mykola Golubyev
sumber
40
1 untuk mempelajari lebih dari 5 trik Vim baru yang seharusnya saya ketahui sebelumnya. Terima kasih
Kenny Meyer
6
Catatan: gd tidak berfungsi untuk menemukan variabel dalam cakupan definisi langsung dalam mode Javascript di macvim. Ini membawa saya ke penggunaan pertama nama variabel di beberapa fungsi dalam file :( Jika Anda berada dalam lingkup tertentu dan ingin memilih lingkup itu, "va {" - "visual select around {" - adalah cara yang tepat Saya pikir.
Srikumar
3
Versi yang sedikit lebih baik: gist.github.com/048616a2e3f5d1b5a9ad meminta pengguna, menunjukkan nama lama, mengembalikan posisi kursor setelah diganti
Andy Ray
7
+1 vimgineering yang sangat bagus (Saya rasa saya baru saja membuat istilah baru). Catatan: Saya sebenarnya perlu menekan titik dua ( :) dua kali. Pertama kali saya menekannya, saya melihat :'<,'>. Jika saya hanya mengetik s/dari sana, itu tidak berhasil; Saya harus mengetikkan titik dua lain sebelum s/.
Kelvin
6
Perhatikan bahwa Anda tidak perlu <C-R>menggunakan perintah pengganti, cukup menghilangkan pencarian akan menyebabkan vim menggunakan pola pencarian terakhir, yang dalam hal ini dibuat dari gdperintah. Jadi, melakukan saja :s//<newname>/gcsudah cukup.
shangxiao
10

AFAIK, sebenarnya tidak ada dukungan refactoring di VIM. Saat melakukan penggantian nama dengan maksud refactor, saya biasanya melakukan tindakan pencegahan berikut:

  1. Batasi ruang lingkup perubahan yang saya gunakan tanda.
  2. Saat memasukkan regex, beri tanda kurung pada nama dengan \ <dan>. Ini akan membuatnya cocok dengan seluruh kata yang mengurangi jenis penggantian nama yang salah yang akan terjadi.
  3. Jangan lakukan penggantian multiline untuk mengurangi kemungkinan penggantian yang buruk
  4. Lihat kode diff dengan hati-hati jika itu selain perubahan kecil.

Perubahan akhir saya terlihat seperti ini

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

Saya ingin sekali jika salah tentang tidak adanya alat refactoring untuk VIM tetapi saya belum melihatnya.

JaredPar
sumber
Di Perl Anda juga dapat menambahkan tipe ke pola pencarian. yaitu $ untuk skalar, @ untuk array,% untuk hash
Nathan Fellman
@Nathan: sayangnya, ini sedikit lebih sulit di Perl (5.X), karena sigil array dan hashes berubah dengan penggunaan:% hash -> whole hash, $ hash {key} -> nilai tunggal, @hash { potongan hash qw / ab /}.
pengguna55400
10

Saya tahu itu pertanyaan lama, dan cara @ mykola-golubyev jelas ADALAH jawaban terbaik untuk kasus tertentu dalam pertanyaan OP (yang, saya asumsikan akan melalui kode yang dikaburkan di mana Anda cenderung memiliki beberapa blok dengan nama var yang sama) ; tetapi dengan nama pertanyaan seperti itu, banyak orang yang datang ke sini dari penelusuran google mungkin mencari cara yang tidak terlalu spesifik untuk situasi tertentu untuk mengganti nama variabel di VIM - dan itu bisa lebih ringkas

Saya terkejut tidak ada yang menyarankan seperti ini:

* :s// NAMA BARU /gc

Ini *sama dengan gn- ini mencari kemunculan berikutnya dari kata di bawah kursor DAN itu menjadi pola pencarian terakhir, jadi ketika Anda menghilangkan pola pencarian dalam perintah pengganti, VIM menganggap ini adalah pola yang akan dicari.

Untuk sejumlah kecil salinan var, bahkan lebih cepat:

* cw NEWNAME <esc> kemudian ulangi n.untuk kejadian lain

Cari kejadian, cwadalah perintah untuk mengubah kata , npergi ke kejadian berikutnya dari istilah yang dicari terakhir dan .mengulangi perintah terakhir (yaitu mengubah kata menjadi NEWNAME )

(Penghargaan untuk saya mengetahui semua ini masuk ke @doomedbunnies di Reddit )

Trik keren lainnya adalah ini: ( kredit untuk @ nobe4 )

* cgn NEWNAME <esc> kemudian ulangi .untuk kejadian lain

cgnadalah "mengubah apa pun hasil dari (temukan kejadian berikutnya)". Sekarang ini adalah perintah terakhir , Anda tidak perlu npergi ke kejadian berikutnya, jadi lebih sedikit pukulan lagi, dan, yang lebih penting, tidak perlu bergantian ndan .. Tapi, jelas, yang satu ini memiliki kelemahan karena tidak memiliki cara untuk melewatkan kejadian.

Berikut beberapa manfaatnya:

  • tanpa pemetaan, tidak ada .vimrc (atau init.vim), sehingga Anda dapat menggunakannya di salinan VIM apa pun yang Anda temui (misalnya, tugas cepat di beberapa VPS atau mesin teman Anda di mana mengkonfigurasi VIM dengan cara Anda akan mengalahkan tujuan 'cepat' )
  • menggunakan *atau gnuntuk pemilihan kata sangat cepat - hanya satu penekanan tombol (yah, katakanlah 1,5)
  • menggunakan *atau gnmemastikan Anda tidak mendapatkan kecocokan di dalam kata lain, seperti :%s/<C-R>//gchalnya. Ketukan mengetik :%s/\<OLDNAME\>/NEWNAME/gcdengan tangan: Saya pribadi cenderung lupa menggunakan \<hal - hal untuk membatasi kecocokan hanya untuk seluruh kata.
  • Tidak menggunakan cakupan hanya akan menghasilkan beberapa pukulan ekstra nuntuk melewati pertandingan yang tidak diinginkan - bahkan mungkin lebih sedikit dari pukulan ekstra yang diperlukan untuk membatasi cakupan. Dalam keadaan normal, variabel Anda kemungkinan besar agak dilokalkan ke blok kode tertentu.
Ivan Bartsov
sumber
8

Taruh ini di .vimrc Anda

" 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

Sebut saja dengan :call Rnvar()

expand("<cword>")mendapatkan kata di bawah kursor. String pencarian menggunakan %untuk file-scope, dan \(\W\)polanya mencari karakter non-kata di batas kata yang akan diganti, dan menyimpannya dalam variabel \1dan \2untuk dimasukkan kembali ke dalam pola penggantian.

Mike
sumber
3

Anda dapat menggunakan pengubah 'c' dalam pencarian global dan mengganti yang akan meminta Anda untuk konfirmasi untuk setiap penggantian. Ini akan memakan waktu lebih lama tetapi mungkin berfungsi untuk file kode yang tidak besar:

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

C berarti konfirmasi.

Adnan
sumber
I singkatan dari ignore-case. Anda ingin c, konfirmasikan setiap perubahan.
Michael Kristofik
Ups .. maaf tentang itu .. Memperbaiki jawabannya
Adnan
Jawaban masih belum diperbaiki sepenuhnya;)
user55400
maksud Anda $ yang lolos? Itu adalah preferensi pribadi saya. $ bekerja tanpa melarikan diri dan juga dengan dan karena di dunia regex dan di vi $ memiliki arti khusus, saya suka melarikan diri hanya untuk kejelasan.
Adnan
0

Di c, Anda mungkin dapat membuat beberapa kemajuan menggunakan cscope. Itu membuat upaya untuk memahami sintaks, jadi akan memiliki kesempatan untuk mengetahui kapan surat itu variabel.

Kim Reece
sumber
0

Jika ini ada di beberapa file, Anda dapat mempertimbangkan untuk melihat sed. Gunakan find untuk mengambil file dan xargs plus sed Anda untuk diganti. Katakanlah Anda ingin mengganti a dengan a_better_name di semua file yang cocok dengan * .c, Anda bisa melakukannya

Temukan . -nama "* .c" | xargs sed -i -e 's / a / a_better_name / g'

Ingatlah bahwa ini akan menggantikan SEMUA kemunculan a, jadi Anda mungkin menginginkan regex yang lebih kuat.

Drew Olson
sumber