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)
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
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
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>
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 ...
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:
Fungsi yang dilipat memiliki banyak penggunaan size, tetapi ntidak akan menuntun saya berkeliling setiap penggunaan sizedalam fungsi itu.
" 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.
lh#dev#find_function_boundaries
dari lh-dev{
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
CTRL-]
melompat ke tag di bawah kursor. Bukan untuk memulai fungsi saat ini. Itu tidak akan membantu.: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. functionSolusi 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:
template
daninline
mungkin dilewatkan oleh ctags)end
bidang 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
def
dan menganalisis indentasi, kita bisa mencarifunction
di 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:
Yang mengandalkan:
Saya menghindarkan Anda beberapa ratus baris kode
lh#dev#find_function_boundaries()
Dan terima kasih untuk pemetaan DJ McMayhem
kita dapat melakukan
vif/pattern
untuk mencaripattern
di fungsi saat ini.Kami juga dapat menghapus fungsi dengan
dif
, menariknya denganyif
, dll.Berikut ini tampilannya ketika diterapkan pada fungsi C ++ yang realistis (mis. Bukan 0 indentasi):
sumber
Menemukan awal dan akhir suatu fungsi bisa sulit, terutama dalam bahasa tanpa
function
kata 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:
Dari sana, mencari
foo
dalam fungsi Anda hanya masalah:Menyatukan semuanya, kita bisa mendapatkan pemetaan yang agak bagus:
Yang mengatakan, pemetaan mode visual mungkin akan dengan mudah dibodohi oleh
while
atauif
jadi mungkin akan mendapat manfaat dari sedikit pemolesan. Juga, menjaga pemilihan visual mungkin bukan ide yang sangat bagus ...sumber
if
,for
,while
, dllSolusi yang tidak sempurna menggunakan lipatan . Lipat semuanya:
Katakan Vim untuk tidak membuka area yang dilipat untuk hasil pencarian:
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:
Fungsi yang dilipat memiliki banyak penggunaan
size
, tetapin
tidak akan menuntun saya berkeliling setiap penggunaansize
dalam fungsi itu.sumber
Cara lain:
gunakan operator pencarian Osyo Manga (tergantung pada vim-operator-pengguna ) untuk hanya mencari di dalam blok saat ini. Misalnya:
... sekarang Anda dapat memasukkan istilah pencarian Anda pada prompt yang diberikan; tekan
n
untuk 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 likeg/if
, atau serupa.sumber