Pencarian cepat, terbatas pada fungsi C ++

13

Saya bekerja pada proyek C ++ yang agak besar. Salah satu aspek yang lebih menyulitkan dari organisasinya adalah fungsi yang sangat besar ditempatkan di dalam file yang sangat besar.

Saya sering ingin mencari contoh variabel global atau panggilan fungsi tertentu, terbatas pada fungsi saat ini. Apakah ada formula yang cukup sederhana untuk mencapai ini?

(Saya memiliki ctag yang diinstal dan menggunakan Tagbar ... yang mungkin membantu untuk ini)

jerman
sumber

Jawaban:

9

Begini cara saya akan melakukannya. Tambahkan ini ke.vimrc

vnoremap if [[O][

Penjelasan: vnoremap berarti memetakan sisi kiri ifke sisi kanan [[mO][saat Anda dalam mode visual. ifberarti In Function , meskipun Anda dapat mengganti nama ini jika Anda mau. [[melompat ke awal fungsi. Opindah ke ujung teks yang dipilih secara visual, dan kemudian ][pindah ke akhir fungsi.

Jadi, jika Anda ingin mencari dalam suatu fungsi, sekarang Anda masuk ke mode visual dengan v, dan pilih seluruh fungsi dengan if. Sekarang keluar dari mode visual dengan <esc>, dan cari dengan /\%V. \%Vmembatasi pencarian Anda ke teks yang dipilih sebelumnya. Jika Anda tidak ingin harus memukul <esc>/\%VAnda juga bisa menambahkan ini ke .vimrc:

vnoremap / <esc>/\%V

Kemudian, urutan penekanan tombol Anda akan terlihat seperti:

vif/foo<enter>

dan ini akan menemukan semua kemunculan foo di fungsi saat ini.


Satu-satunya downside ke metode ini adalah bahwa ia mengharapkan pembukaan dan penutupan kawat gigi untuk keduanya memiliki lekukan 0. Jika Anda secara teratur bekerja dengan kode yang tidak memiliki ini, mis

int foo() {
    bar()
}

maka versi yang sedikit lebih rumit ini akan berfungsi:

vnoremap if ][ma%O'a

Ini hanya mengharapkan kurung kurawal untuk memiliki 0 indentasi. Jika brace pembuka memiliki indentasi, itu masih berfungsi, meskipun itu mengambil tanda. Jika Anda secara teratur menggunakan tanda 'a', Anda dapat memindahkan ini misalnya

vnoremap if ][mb%O'b
vnoremap if ][mc%O'c
...
James
sumber
Sayangnya ini tidak bekerja dengan baik dengan fungsi C ++. Tidak seperti fungsi C, mereka cenderung diindentasi (seperti halnya fungsi anggota inline didefinisikan dalam definisi kelas mereka, dan dengan lekukan fungsi default dalam ruang nama). Namun ide Anda dapat dibangun berkat rentang definisi fungsi yang dapat diperoleh dengan ctags. Saya melakukannya dalam fungsi lh#dev#find_function_boundariesdari lh-dev
Luc Hermitte
3
Pendekatan yang bagus. Jika Anda dapat menemukan garis atas fungsi dengan andal, maka Anda dapat pindah ke {dan kemudian menggunakan %untuk mencapai garis bawah. Tidak yakin bagaimana Anda dapat menemukan fungsi ini dimulai pada C ++, tetapi ini berfungsi baik untuk Javascript:vnoremap if <Esc>?^\s*function<CR>v/{<CR>%o
joeytwiddle
1
Mengenai hasil edit terakhir Anda. CTRL-]melompat ke tag di bawah kursor. Bukan untuk memulai fungsi saat ini. Itu tidak akan membantu.
Luc Hermitte
Mengenai hasil edit baru. Itu tidak sesederhana itu. Kesulitannya adalah untuk mengetahui fungsi saat ini. Jika memiliki informasi, itu tidak memerlukan bantuan ctag. Satu-satunya cara untuk mendapatkan informasi (dari ctags) adalah dengan menganalisis perintah lompat-ke-deklarasi yang dihasilkan oleh ctags. Jika perintah-perintah ini :linenumber, vim dapat melakukan apa yang saya lakukan di plugin saya. Tetapi tidak ada jaminan, dan perintah ini malah bisa menjadi pencarian /pattern- Vim tidak dapat menguji semua pola untuk mengetahui mana yang cocok dengan fungsi saat ini. function
Luc Hermitte
6

Solusi DJ McMayhem mengilhami saya untuk menulis sendiri yang mengandalkan ctag dan matchit untuk melakukan analisis yang tepat tentang batas fungsi.

Bagian yang sulit telah dilakukan oleh lh-dev dan lh-tag selama beberapa tahun:

  • file saat ini diuraikan melalui ctag dengan opsi yang tepat
  • kami mencari semua definisi fungsi di basis data tag yang terbatas pada tag yang diperoleh untuk file saat ini
  • terima kasih kepada DB, kami memiliki nomor baris awal untuk semua fungsi (baik bagian templatedan inlinemungkin dilewatkan oleh ctags)
  • dengan pencarian berulang sederhana (pencarian biner bisa dilakukan, tetapi yah, file seharusnya "pendek"), awal fungsi saat ini ditemukan
  • Dan berkat plugin matchit, baris terakhirnya juga ditemukan - Saya melihat bahwa ctag universal menawarkan endbidang yang dapat digunakan dengan C, C ++, Python, dan Vim yang juga dapat digunakan untuk menemukan akhir fungsi.

Perhatikan bahwa bagian mana pun dari algoritma ini dapat diganti berdasarkan tipe file. yaitu deteksi batas fungsi python dapat mencari defdan menganalisis indentasi, kita bisa mencari functiondi javascript, dan sebagainya - Dengan kata lain, versi saat ini juga berfungsi dengan Java, Vim dan beberapa bahasa lainnya (saya masih memiliki beberapa pekerjaan lakukan untuk Python)

Jadi saya mendefinisikan sekarang dua pemetaan baru: pemetaan mode visual, dan pemetaan mode menunggu operator:

onoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr>
xnoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr><esc>gv

Yang mengandalkan:

function! lh#dev#_select_current_function() abort
  let fn = lh#dev#find_function_boundaries(line('.'))
  exe fn.lines[0]
  normal! v
  exe fn.lines[1]
endfunction

Saya menghindarkan Anda beberapa ratus baris kode lh#dev#find_function_boundaries()

Dan terima kasih untuk pemetaan DJ McMayhem

" Note that my vim settings requires two backslashes here instead of one
vnoremap / <esc>/\\%V

kita dapat melakukan vif/patternuntuk mencari patterndi fungsi saat ini.

Kami juga dapat menghapus fungsi dengan dif, menariknya dengan yif, dll.

Berikut ini tampilannya ketika diterapkan pada fungsi C ++ yang realistis (mis. Bukan 0 indentasi):Screencast: Pilih fungsi C ++

Luc Hermitte
sumber
4

Menemukan awal dan akhir suatu fungsi bisa sulit, terutama dalam bahasa tanpa functionkata kunci ... dan banyak gaya indent yang saling bertentangan.

Jika fungsi Anda berakhir dengan penjepit penutup sendiri pada barisnya sendiri (seperti pada 10 dari 13 gaya yang tercantum di sini ), Anda dapat memilihnya secara visual dengan sesuatu seperti ini:

xnoremap if /^\s*}<CR><Esc>V%

Dari sana, mencari foodalam fungsi Anda hanya masalah:

:'<,'>g/foo/#

Menyatukan semuanya, kita bisa mendapatkan pemetaan yang agak bagus:

xnoremap if /^\s*}<CR><Esc>V%
nmap <key> vif:g//#<Left><Left>

fungsi pencarian

Yang mengatakan, pemetaan mode visual mungkin akan dengan mudah dibodohi oleh whileatau ifjadi mungkin akan mendapat manfaat dari sedikit pemolesan. Juga, menjaga pemilihan visual mungkin bukan ide yang sangat bagus ...

romainl
sumber
Ini hanya memilih blok berikutnya yang dapat ditemukan. Ini tidak bekerja sama sekali setelah Anda menambahkan if, for, while, dll
James
3

Solusi yang tidak sempurna menggunakan lipatan . Lipat semuanya:

set foldmethod=syntax
set foldlevel=0
set foldminlines=0

Katakan Vim untuk tidak membuka area yang dilipat untuk hasil pencarian:

set foldopen-=search

Dan kemudian buka flip pada fungsi yang dimaksud ( zO).

Sekarang, semua klik untuk pencarian teks di wilayah terlipat akan menghasilkan Vim melompat ke garis lipatan sekali, kemudian melanjutkan ke klik berikutnya.

Misalnya, dalam kasus di bawah ini:

masukkan deskripsi gambar di sini

Fungsi yang dilipat memiliki banyak penggunaan size, tetapi ntidak akan menuntun saya berkeliling setiap penggunaan sizedalam fungsi itu.

muru
sumber
3

Cara lain:

  • gunakan ctag dll. untuk menemukan fungsi target, pergi ke sana
  • gerakkan kursor ke depan di dalam tubuh fungsi
  • gunakan operator pencarian Osyo Manga (tergantung pada vim-operator-pengguna ) untuk hanya mencari di dalam blok saat ini. Misalnya:

    " configure the plugin (once, vimrc):
     map g/ <Plug>(operator-search)
    
    " 1. use ctags etc. to jump to the beginning of the target function;
    " 2. move cursor inside the function definition, then:
    g/i{
    

... sekarang Anda dapat memasukkan istilah pencarian Anda pada prompt yang diberikan; tekan nuntuk melihat bagaimana hasil pencarian terbatas pada gerakan / objek teks yang disediakan saat ini. Karena ini adalah operator Vim (yaitu composable), jika Anda memiliki objek teks fungsi yang baik, Anda bahkan tidak perlu bergerak di dalam badan definisi sebelum mencari, tetapi langsung menggunakan smthing like g/if, atau serupa.

VanLaser
sumber