Langsung ke definisi fungsi di vim

241

Bagaimana saya bisa beralih ke definisi fungsi menggunakan vim? Sebagai contoh dengan Visual Assist, saya dapat mengetik Alt+ di gbawah fungsi dan itu membuka menu konteks daftar file dengan definisi.

Bagaimana saya bisa melakukan sesuatu seperti ini di vim?

Jon Clegg
sumber
2
gnu global lebih baik daripada ctags.
Jichao
6
@Jichao, bisakah Anda memberi kami sedikit wawasan tentang pengalaman Anda? Dengan bahasa apa gnu global bekerja lebih baik untuk Anda? Apakah ada hal lain tentang konteks yang Anda sukai sehingga saya menjadi penting? Atau mungkin Anda telah menggunakannya dalam banyak skenario yang berbeda dan sepertinya Anda sebagian besar / selalu lebih suka? Apa yang Anda sukai lebih baik? Terima kasih.
still_dreaming_1
@Jichao Saya mengubah komentar Anda menjadi jawaban wiki komunitas. Saya akan menyambut perubahan dan masukan Anda untuk jawaban ini.
still_dreaming_1

Jawaban:

213

Gunakan ctags. Buat file tag, dan beri tahu vim di mana ia menggunakan perintah: tag. Maka Anda bisa langsung beralih ke definisi fungsi menggunakan Ctrl-]

Ada lebih banyak trik tag dan tips dalam pertanyaan ini .

Paul Tomblin
sumber
2
php cukup mirip C sehingga "Ctag bersemangat" harus bekerja dengannya. Tidak tahu apakah ini memiliki mode python.
Paul Tomblin
5
Tidak ada pengalaman dengan Cscope. Apa itu
Paul Tomblin
10
Kemiripan dengan C tidak ada hubungannya dengan CTags mendukung PHP. Ini mendukung PHP dan juga Python. Lihat ctags.sourceforge.net/languages.html untuk melihat dukungan penuh.
data
2
bagaimana cara menghasilkan ctag?
dwaynemac
4
alangkah baiknya untuk mendapatkan referensi ke tempat yang terbaik untuk belajar bagaimana mengoperasikan ctag tersebut.
Fzs2
138

Jika semuanya terkandung dalam satu file, ada perintah gd(seperti dalam 'definisi goto'), yang akan membawa Anda ke kemunculan pertama di file kata di bawah kursor, yang sering kali merupakan definisi.

Scottie T
sumber
1
bagaimana jika saya tidak memiliki kata di bawah kursor (saya lebih suka mengetiknya)?
Fuad Saud
@ FuadSaud hanya mencarinya menggunakan/
LucasB
6
/hampir selalu tidak tepat, karena itu akan cocok dengan semua ocurrences. Saya tahu Anda benar-benar dapat melakukannya :tag <function_name>untuk melompat ke definisi melalui ctags.
Fuad Saud
@Faud Fitur Jump To Definition bergantung pada penunjuk pengenal dengan kursor (di setiap IDE). Mengetik / mencari adalah fitur lain, Anda membingungkan mereka.
Berdarah
101

g* melakukan pekerjaan yang layak tanpa ctag didirikan.

Yaitu, ketik g, *(atau hanya *- lihat di bawah) untuk mencari kata di bawah kursor (dalam hal ini, nama fungsi). Kemudian tekan nuntuk pergi ke kejadian berikutnya (atau Shift- nuntuk sebelumnya).

Itu tidak langsung melompat ke definisi, mengingat bahwa perintah ini hanya mencari kata di bawah kursor, tetapi jika Anda tidak ingin berurusan dengan pengaturan ctag saat ini, Anda setidaknya dapat menyelamatkan diri dari keharusan untuk kembali -type nama fungsi untuk mencari definisinya.

--Edit - Meskipun saya telah menggunakan g * untuk waktu yang lama, saya baru saja menemukan dua pintasan untuk pintasan ini!

(a) *akan melompat ke kemunculan kata berikutnya di bawah kursor. (Tidak perlu mengetik g, perintah 'goto' di vi).

(B) #pergi ke kejadian sebelumnya, dengan cara yang sama.

N dan n masih berfungsi, tetapi '#' seringkali sangat berguna untuk memulai pencarian pada awalnya di arah sebaliknya, misalnya, ketika mencari deklarasi variabel di bawah kursor.

Brent Faust
sumber
10
Perbedaan antara *dan g*merupakan batas kata pada pencarian. *melakukan \<keyword\>pencarian (sama seperti \bkeyword\bpada regex reguler), sementara g*mencari keywordtanpa batas kata.
Nicolai S
jika Anda memiliki seratus kemunculan fungsi dalam file, *akan membawa Anda rata-rata 50 hit sebelum Anda menemukan definisi.
naught101
49

Gunakan gdatau gDsaat menempatkan kursor pada variabel apa pun di program Anda.

  1. gd akan membawa Anda ke deklarasi lokal.
  2. gD akan membawa Anda ke deklarasi global.

lebih banyak opsi navigasi dapat ditemukan di sini .

Gunakan cscope untuk referensi silang proyek besar seperti kernel linux.

0x90
sumber
14

Seperti yang dikatakan Paul Tomblin, Anda harus menggunakan ctag . Anda juga dapat mempertimbangkan menggunakan plugin untuk memilih yang sesuai atau untuk melihat dulu definisi fungsi di bawah kursor. Tanpa plugin Anda akan pusing mencoba untuk memilih salah satu dari ratusan metode 'doAction' yang kelebihan beban karena dukungan yang dibangun di ctag tidak memperhitungkan konteksnya - hanya sebuah nama.

Anda juga dapat menggunakan cscope dan fungsinya 'menemukan simbol global'. Tetapi vim Anda harus dikompilasi dengan dukungan + cscope yang bukan merupakan salah satu opsi build.

Jika Anda tahu bahwa fungsi didefinisikan dalam file saat ini, Anda dapat menggunakan penekanan tombol 'gD' dalam mode normal untuk melompat ke definisi simbol di bawah kursor.

Berikut ini adalah plugin yang paling banyak diunduh untuk navigasi
http://www.vim.org/scripts/script.php?script_id=273

Ini adalah salah satu yang saya tulis untuk memilih konteks sambil melompat ke tag
http://www.vim.org/scripts/script.php?script_id=2507

Mykola Golubyev
sumber
Hai @ mykola-golubyev, tautan yang Anda berikan di Detailed descriptionbagian #2507skrip rusak. Bisakah Anda memberikan yang lain?
FelikZ
12

Teknik umum lainnya adalah dengan menempatkan nama fungsi di kolom pertama. Ini memungkinkan definisi ditemukan dengan pencarian sederhana.

int
main(int argc, char *argv[])
{
    ...
}

Fungsi di atas kemudian dapat ditemukan dengan /^maindi dalam file atau dengan :grep -r '^main' *.cdalam direktori. Selama kode diindentasi dengan benar, satu-satunya waktu pengidentifikasi akan terjadi pada awal baris adalah pada definisi fungsi.

Tentu saja, jika Anda tidak menggunakan ctag mulai saat ini, Anda harus malu pada diri sendiri! Namun, saya menemukan standar pengkodean ini juga bermanfaat.

Hakim Maygarden
sumber
13
Saya selalu bertanya-tanya mengapa beberapa coders menulis tanda tangan mereka seperti itu!
Tarrasch
Juga, ketika Anda menulis tanda tangan fungsi Anda, termasuk '{' di kolom pertama, Anda dapat berpindah dengan cepat ke setiap fungsi dengan menekan]] untuk maju dalam file dan [[untuk mundur.
BentChainRing
12

TL; DR:

Cara modern adalah dengan menggunakan COC untuk penyelesaian seperti intellisense dan satu atau lebih server bahasa (LS) untuk melompat-ke-definisi (dan cara jauh lebih). Untuk fungsionalitas yang lebih banyak (tetapi tidak diperlukan untuk lompat-ke-definisi), Anda dapat menginstal satu atau lebih debugger dan mendapatkan pengalaman IDE yang penuh sesak nafas. Mulai cepat:

  1. instal vim-plug untuk mengelola plug-in VIM Anda
  2. tambahkan COC dan (opsional) Vimspector di bagian atas ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. panggilan :source $MYVIMRC | PlugInstalluntuk mengunduh plug-in VIM
  4. restart vimdan panggil :CocInstall coc-marketplaceuntuk mendapatkan akses mudah ke ekstensi COC
  5. panggilan :CocList marketplacedan cari server bahasa, mis:
    • ketik pythonuntuk menemukan coc-jedi,
    • ketik phpuntuk menemukan coc-phpls, dll.
  6. (opsional) lihat install_gadget.py --helpdebuggers yang tersedia, misalnya:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-php, dll.

Jawaban lengkap:

Server bahasa (LS) adalah aplikasi mandiri yang terpisah (satu untuk setiap bahasa pemrograman) yang berjalan di latar belakang dan menganalisis seluruh proyek Anda secara real time dengan memperlihatkan kemampuan tambahan untuk editor Anda (editor apa pun, tidak hanya vim). Anda mendapatkan hal-hal seperti:

  • penyelesaian tag sadar namespace
  • lompat ke definisi
  • lompat ke kesalahan berikutnya / sebelumnya
  • temukan semua referensi ke suatu objek
  • temukan semua implementasi antarmuka
  • ganti nama di seluruh proyek
  • dokumentasi tentang melayang
  • snippet, aksi kode, pemformatan, linting, dan lainnya ...

Komunikasi dengan server bahasa terjadi melalui Language Server Protocol (LSP). Baik nvimdan vim8(atau lebih tinggi) mendukung LSP melalui plug-in, yang paling populer adalah Conquer of Completion (COC).

Daftar server bahasa yang dikembangkan secara aktif dan kemampuannya tersedia di situs Lang Server . Tidak semua disediakan oleh ekstensi COC. Jika Anda ingin menggunakan salah satunya, Anda dapat menulis sendiri ekstensi COC atau menginstal LS secara manual dan menggunakan kombo plug-in VIM berikut sebagai alternatif untuk COC:

Komunikasi dengan debugger dilakukan melalui Debug Adapter Protocol (DAP). Plug-in DAP paling populer untuk VIM adalah Vimspector .

Language Server Protocol (LSP) dibuat oleh Microsoft untuk Visual Studio Code dan dirilis sebagai proyek open source dengan lisensi MIT yang permisif (distandarisasi melalui kolaborasi dengan Red Hat dan Codenvy). Kemudian Microsoft merilis Protokol Adaptor Debug (DAP) juga. Bahasa apa pun yang didukung oleh VSCode didukung dalam VIM.

Saya pribadi merekomendasikan menggunakan server bahasa COC + yang disediakan oleh ekstensi COC + ALE untuk tambahan linting (tetapi dengan dukungan LSP dinonaktifkan untuk menghindari konflik dengan COC) + Vimspector + debuggers yang disediakan oleh Vimspector (disebut "gadget") + berikut plug-in VIM:

call plug#begin()
Plug 'neoclide/coc.nvim'
Plug 'dense-analysis/ale'
Plug 'puremourning/vimspector'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter'
Plug 'sheerun/vim-polyglot'
Plug 'yggdroot/indentline'
Plug 'tpope/vim-surround'
Plug 'kana/vim-textobj-user'
  \| Plug 'glts/vim-textobj-comment'
Plug 'janko/vim-test'
Plug 'vim-scripts/vcscommand.vim'
Plug 'mhinz/vim-signify'
call plug#end()

Anda dapat google masing-masing untuk melihat apa yang mereka lakukan.

cprn
sumber
11

1- menginstal ctag riang. Jika Anda menggunakan osx, artikel ini menunjukkan sedikit trik: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Jika Anda hanya ingin memasukkan ctag untuk file dalam direktori Anda saja, jalankan perintah ini di direktori Anda:

ctags -R

Ini akan membuat file "tag" untuk Anda.

3 - Jika Anda menggunakan Ruby dan ingin memasukkan ctag untuk permata Anda (ini sangat membantu saya dengan RubyMotion dan permata lokal yang telah saya kembangkan), lakukan hal berikut:

ctags --exclude=.git --exclude='*.log' -R * `bundle show --paths`

kredit: https://coderwall.com/p/lv1qww (Perhatikan bahwa saya menghapus opsi -e yang menghasilkan tag untuk emacs bukannya vim)

4- Tambahkan baris berikut ke ~ / .vimrc Anda

set autochdir 
set tags+=./tags;

(Mengapa titik koma: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Buka kata yang ingin Anda ikuti dan tekan ctrl + ]; jika Anda ingin kembali, gunakan ctrl+o(sumber: https://stackoverflow.com/a/53929/226255 )

Abdo
sumber
Tautan ke artikel Mac yang disebutkan terputus. Inilah tautan yang diperbarui: runtime-era.blogspot.com/2012/05/... Taruhan terbaik Anda adalah memasang ctag dengan alat seperti Homebrew
ZaydH
6

Menanggapi tanggapan Paulus yang kedua: ya, ctags (khususnya ctag yang riang ( http://ctags.sourceforge.net/ )) sangat bagus. Saya juga menambahkan ini ke vimrc saya, jadi saya bisa menggunakan satu file tag untuk seluruh proyek:

set tags=tags;/
David Wolever
sumber
2

Instal cscope. Ia bekerja sangat mirip ctagstetapi lebih kuat. Untuk menuju ke definisi, alih-alih Ctrl+ ], lakukan Ctrl+ \+ g. Tentu saja Anda dapat menggunakan keduanya secara bersamaan. Tetapi dengan proyek besar (katakanlah kernel Linux), cscope berada jauh di depan.

Diptendu Roy Chowdhury
sumber
1

Setelah membuat ctag, Anda juga dapat menggunakan yang berikut di vim:

:tag <f_name>

Di atas akan membawa Anda ke definisi fungsi.

Karun
sumber