Chuyển đến định nghĩa hàm trong vim


241

Làm thế nào tôi có thể chuyển đến một định nghĩa hàm bằng vim? Ví dụ với Visual Assistant, tôi có thể nhập Alt+ gdưới một hàm và nó sẽ mở một menu ngữ cảnh liệt kê các tệp có định nghĩa.

Làm thế nào tôi có thể làm một cái gì đó như thế này trong vim?


2
gnu toàn cầu là tốt hơn so với ctags.
Jichao

6
@Jichao, bạn có thể cho chúng tôi hiểu thêm một chút về trải nghiệm của bạn không? Với những ngôn ngữ nào gnu toàn cầu làm việc tốt hơn cho bạn? Có điều gì khác về bối cảnh bạn thích nó trong đó tôi quan trọng không? Hoặc có lẽ bạn đã sử dụng nó trong nhiều tình huống khác nhau và bạn dường như chủ yếu / luôn thích nó? Bạn thích gì về nó tốt hơn? Cảm ơn.
still_dreaming_1

@Jichao Tôi đã biến bình luận của bạn thành một câu trả lời wiki cộng đồng. Tôi sẽ hoan nghênh những thay đổi và đầu vào của bạn cho câu trả lời này.
still_dreaming_1

Câu trả lời:


213

Sử dụng ctags. Tạo một tệp thẻ và cho vim biết nơi nó đang sử dụng lệnh: tags. Sau đó, bạn có thể chuyển đến định nghĩa hàm bằng cách sử dụng Ctrl-]

Có nhiều thẻ thủ thuật và mẹo trong câu hỏi này .


2
php giống như C đủ để "ctags Exuberant" nên hoạt động với nó. Không biết nó có chế độ python không.
Paul Tomblin

5
Chưa có kinh nghiệm với Cscope. Là gì
Paul Tomblin

10
Sự tương đồng với C không liên quan gì đến CTags hỗ trợ PHP. Nó hỗ trợ PHP cũng như Python. Hãy xem ctags.sourceforge.net/lacular.html để xem hỗ trợ đầy đủ.
dữ liệu

1
Làm thế nào để tôi tạo ctags?
dwaynemac

4
sẽ thật tuyệt khi có được một tài liệu tham khảo về nơi tốt nhất để học cách vận hành các ctags đó.
Fzs2

137

Nếu mọi thứ được chứa trong một tệp, sẽ có lệnh gd(như trong 'định nghĩa goto'), sẽ đưa bạn đến lần xuất hiện đầu tiên trong tệp của từ dưới con trỏ, thường là định nghĩa.


1
Điều gì xảy ra nếu tôi không có từ dưới con trỏ (tôi muốn nhập từ đó)?
Fuad Saud

@FuadSaud chỉ cần tìm kiếm nó bằng cách sử dụng/
LucasB

6
/hầu như luôn luôn không chính xác, vì nó sẽ phù hợp với tất cả các trường. Tôi phát hiện ra rằng bạn thực sự có thể làm :tag <function_name>để chuyển đến định nghĩa thông qua ctags.
Fuad Saud

Tính năng @Faud Jump To Định nghĩa dựa vào việc trỏ một mã định danh bằng một con trỏ (trong mọi IDE). Gõ / tìm kiếm là một tính năng khác, bạn đang nhầm lẫn chúng.
đẫm máu

101

g* làm một công việc tốt mà không có ctags được thiết lập.

Đó là, gõ g, *(hoặc chỉ *- xem bên dưới) để tìm kiếm từ dưới con trỏ (trong trường hợp này là tên hàm). Sau đó nhấn nđể đi đến lần xuất hiện tiếp theo (hoặc Shift- ncho lần trước).

Nó không chuyển trực tiếp đến định nghĩa, vì lệnh này chỉ tìm kiếm từ dưới con trỏ, nhưng nếu bạn không muốn xử lý việc thiết lập ctags vào lúc này, ít nhất bạn có thể tự cứu mình khỏi phải tái -type tên hàm để tìm kiếm định nghĩa của nó.

- Chỉnh sửa-- Mặc dù tôi đã sử dụng g * trong một thời gian dài, gần đây tôi đã phát hiện ra hai phím tắt cho các phím tắt này!

(a) *sẽ nhảy đến lần xuất hiện tiếp theo của từ dưới con trỏ. (Không cần nhập lệnh g, 'goto' trong vi).

(b) #đi đến lần xuất hiện trước, theo cách tương tự.

N và n vẫn hoạt động, nhưng '#' thường rất hữu ích để bắt đầu tìm kiếm ban đầu theo hướng ngược lại, ví dụ như khi tìm kiếm khai báo một biến dưới con trỏ.


10
Sự khác biệt giữa *g*là ranh giới từ trên tìm kiếm. *thực hiện \<keyword\>tìm kiếm (giống như \bkeyword\btrong regex thông thường), trong khi g*tìm kiếm keywordkhông có ranh giới từ.
Nicolai S

nếu bạn có hàng trăm lần xuất hiện của một hàm trong một tệp, *sẽ đưa bạn trung bình 50 lần truy cập trước khi bạn tìm thấy định nghĩa.
ness101

49

Sử dụng gdhoặc gDtrong khi đặt con trỏ trên bất kỳ biến nào trong chương trình của bạn.

  1. gd sẽ đưa bạn đến tờ khai địa phương.
  2. gD sẽ đưa bạn đến tuyên bố toàn cầu.

nhiều tùy chọn điều hướng có thể được tìm thấy ở đây .

Sử dụng cscope để tham chiếu chéo dự án lớn như kernel linux.


14

Như Paul Tomblin đã đề cập, bạn phải sử dụng ctags . Bạn cũng có thể xem xét sử dụng các plugin để chọn một plugin phù hợp hoặc để xem trước định nghĩa của hàm theo con trỏ. Nếu không có plugin, bạn sẽ phải đau đầu khi cố gắng chọn một trong hàng trăm phương thức 'doAction' bị quá tải vì hỗ trợ ctags được tích hợp không tính đến ngữ cảnh - chỉ là một cái tên.

Ngoài ra, bạn có thể sử dụng cscope và chức năng 'tìm biểu tượng toàn cầu' của nó. Nhưng vim của bạn phải được biên dịch với hỗ trợ + cscope không phải là một tùy chọn xây dựng mặc định.

Nếu bạn biết rằng chức năng được xác định trong tệp hiện tại, bạn có thể sử dụng tổ hợp phím 'gD' ở chế độ bình thường để chuyển sang định nghĩa biểu tượng dưới con trỏ.

Dưới đây là plugin được tải xuống nhiều nhất để điều hướng
http://www.vim.org/scripts/script.php?script_id=273

Đây là một cái tôi đã viết để chọn ngữ cảnh trong khi chuyển sang gắn thẻ
http://www.vim.org/scripts/script.php?script_id=2507


Xin chào @ mykola-golubyev, liên kết mà bạn cung cấp trong Detailed descriptionphần #2507tập lệnh bị hỏng. Bạn có thể cung cấp một cái khác xin vui lòng?
FelikZ

12

Một kỹ thuật phổ biến khác là đặt tên hàm trong cột đầu tiên. Điều này cho phép định nghĩa được tìm thấy với một tìm kiếm đơn giản.

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

Hàm trên có thể được tìm thấy /^mainbên trong tệp hoặc :grep -r '^main' *.ctrong một thư mục. Miễn là mã được thụt lề đúng cách, lần duy nhất mã định danh sẽ xuất hiện ở đầu một dòng là ở định nghĩa hàm.

Tất nhiên, nếu bạn không sử dụng ctags từ thời điểm này, bạn nên tự xấu hổ! Tuy nhiên, tôi thấy tiêu chuẩn mã hóa này cũng là một bổ sung hữu ích.


13
Tôi đã luôn tự hỏi tại sao một số lập trình viên viết chữ ký của họ theo cách đó!
Tarrasch

Ngoài ra, khi bạn viết chữ ký hàm, bao gồm '{' trong cột đầu tiên, bạn có thể di chuyển nhanh đến từng chức năng bằng cách nhấn]] để chuyển tiếp trong tệp và [[để đi lùi.
BentChainRing

12

TL; DR:

Cách hiện đại là sử dụng COC để hoàn thành giống như intellisense và một hoặc nhiều máy chủ ngôn ngữ (LS) để chuyển sang định nghĩa (và cách nhiều hơn). Để có nhiều chức năng hơn (nhưng không cần thiết cho bước nhảy định nghĩa), bạn có thể cài đặt một hoặc nhiều trình gỡ lỗi và có được trải nghiệm IDE đầy đủ. Bắt đầu nhanh:

  1. cài đặt vim-plug để quản lý các trình cắm VIM của bạn
  2. thêm COC và (tùy chọn) Vimspector ở đầu ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. gọi :source $MYVIMRC | PlugInstallđể tải xuống các trình cắm VIM
  4. khởi động lại vimvà gọi :CocInstall coc-marketplaceđể có quyền truy cập dễ dàng vào tiện ích mở rộng COC
  5. gọi :CocList marketplacevà tìm kiếm các máy chủ ngôn ngữ, ví dụ:
    • pythonđể tìm coc-jedi,
    • phpđể tìm coc-phpls, vv
  6. (tùy chọn) xem install_gadget.py --helpcác trình gỡ lỗi có sẵn, ví dụ:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-php, Vân vân.

Câu trả lời đầy đủ:

Máy chủ ngôn ngữ (LS) là một ứng dụng độc lập riêng biệt (một cho mỗi ngôn ngữ lập trình) chạy trong nền và phân tích toàn bộ dự án của bạn trong thời gian thực để lộ các khả năng bổ sung cho trình soạn thảo của bạn (không phải trình soạn thảo, không chỉ vim). Bạn nhận được những thứ như:

  • hoàn thành thẻ nhận biết không gian tên
  • nhảy đến định nghĩa
  • nhảy đến lỗi tiếp theo / trước
  • tìm tất cả các tham chiếu đến một đối tượng
  • tìm tất cả các cài đặt giao diện
  • đổi tên trên toàn bộ dự án
  • tài liệu về di chuột
  • đoạn trích, hành động mã, định dạng, linting và nhiều hơn nữa ...

Giao tiếp với các máy chủ ngôn ngữ diễn ra thông qua Giao thức máy chủ ngôn ngữ (LSP). Cả nvimvim8(hoặc cao hơn) đều hỗ trợ LSP thông qua các trình cắm, phổ biến nhất là Chinh phục hoàn thành (COC).

Danh sách các máy chủ ngôn ngữ được phát triển tích cực và khả năng của chúng có sẵn trên trang web của Lang Server . Không phải tất cả những thứ đó được cung cấp bởi các phần mở rộng COC. Nếu bạn muốn sử dụng một trong số đó, bạn có thể tự viết tiện ích mở rộng COC hoặc cài đặt LS theo cách thủ công và sử dụng kết hợp các trình cắm VIM sau thay thế cho COC:

Giao tiếp với trình gỡ lỗi diễn ra thông qua Giao thức gỡ lỗi (DAP). Trình cắm DAP phổ biến nhất cho VIM là Vimspector .

Language Server Protocol (LSP) được Microsoft tạo ra cho Visual Studio Code và được phát hành dưới dạng một dự án nguồn mở với giấy phép MIT cho phép (được chuẩn hóa bởi sự hợp tác với Red Hat và Codenvy). Sau đó, Microsoft cũng phát hành Giao thức bộ điều hợp gỡ lỗi (DAP). Bất kỳ ngôn ngữ nào được hỗ trợ bởi VSCode đều được hỗ trợ trong VIM.

Cá nhân tôi khuyên bạn nên sử dụng các máy chủ ngôn ngữ COC + được cung cấp bởi tiện ích mở rộng COC + ALE để thêm linting (nhưng với hỗ trợ LSP bị vô hiệu hóa để tránh xung đột với COC) + Vimspector + trình gỡ lỗi do Vimspector cung cấp (được gọi là "tiện ích") + sau các trình cắm 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()

Bạn có thể google từng cái để xem những gì họ làm.


11

1- cài đặt ctags quá mức. Nếu bạn đang sử dụng osx, bài viết này cho thấy một mẹo nhỏ: http : //www.r nb-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Nếu bạn chỉ muốn bao gồm các ctags cho các tệp trong thư mục của mình, hãy chạy lệnh này trong thư mục của bạn:

ctags -R

Điều này sẽ tạo ra một tập tin "thẻ" cho bạn.

3- Nếu bạn đang sử dụng Ruby và muốn bao gồm các ctags cho đá quý của bạn (điều này thực sự hữu ích với tôi với RubyMotion và đá quý địa phương mà tôi đã phát triển), hãy làm như sau:

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

tín dụng: https://coderwall.com/p/lv1qww (Lưu ý rằng tôi đã bỏ qua tùy chọn -e tạo thẻ cho emacs thay vì vim)

4- Thêm dòng sau vào ~ / .vimrc của bạn

set autochdir 
set tags+=./tags;

(Tại sao dấu hai chấm: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Chuyển đến từ bạn muốn theo dõi và đánh ctrl + ]; nếu bạn muốn quay lại, hãy sử dụng ctrl+o(nguồn: https://stackoverflow.com/a/53929/226255 )


Liên kết đến bài viết Mac được đề cập bị hỏng. Dưới đây là liên kết Cập nhật: runtime-era.blogspot.com/2012/05/... Tốt nhất là cài đặt ctags với một công cụ như Homebrew
ZaydH

6

Đối với câu trả lời thứ hai của Paul: có, ctags (đặc biệt là exuberant-ctags ( http://ctags.sourceforge.net/ )) là tuyệt vời. Tôi cũng đã thêm nó vào vimrc của mình, vì vậy tôi có thể sử dụng một tệp thẻ cho toàn bộ dự án:

set tags=tags;/

2

Cài đặt cscope. Nó hoạt động rất giống ctagsnhưng mạnh mẽ hơn. Để đi đến định nghĩa, thay vì Ctrl+ ], hãy làm Ctrl+ \+ g. Tất nhiên bạn có thể sử dụng đồng thời cả hai. Nhưng với một dự án lớn (nói Linux kernel), cscope là dặm về phía trước.


1

Sau khi tạo ctags, bạn cũng có thể sử dụng như sau trong vim:

:tag <f_name>

Ở trên sẽ đưa bạn đến định nghĩa chức năng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.