ข้ามไปที่นิยามฟังก์ชันในกลุ่ม


241

ฉันจะข้ามไปยังนิยามฟังก์ชันโดยใช้ vim ได้อย่างไร? ตัวอย่างเช่นกับ Visual Assist ฉันสามารถพิมพ์Alt+ gภายใต้ฟังก์ชันและเปิดเมนูบริบทที่แสดงรายการไฟล์ที่มีคำจำกัดความ

ฉันจะทำอะไรเช่นนี้ในกลุ่ม?


2
gnu global ดีกว่า ctags
Jichao

6
@Jichao คุณช่วยให้เราเข้าใจลึกซึ้งยิ่งขึ้นเกี่ยวกับประสบการณ์ของคุณได้หรือไม่? gnu ทั่วโลกใช้ภาษาใดได้ดีกว่าสำหรับคุณ มีอะไรอีกบ้างเกี่ยวกับบริบทที่คุณต้องการในการที่ฉันจะมีความสำคัญ? หรือบางทีคุณอาจเคยใช้มันในหลาย ๆ สถานการณ์และดูเหมือนว่าคุณชอบ / มักชอบหรือไม่? คุณชอบอะไรเกี่ยวกับเรื่องนี้ดีกว่า ขอบคุณ
still_dreaming_1

@Jichao ฉันเปลี่ยนความคิดเห็นของคุณให้เป็นคำตอบของชุมชน ฉันยินดีต้อนรับการเปลี่ยนแปลงและอินพุตของคุณสำหรับคำตอบนี้
still_dreaming_1

คำตอบ:


213

ใช้ ctags สร้างไฟล์แท็กและแจ้ง vim ว่าไฟล์นั้นใช้คำสั่ง: tags อย่างไร จากนั้นคุณสามารถข้ามไปที่นิยามฟังก์ชันโดยใช้Ctrl-]

มีเทคนิคแท็กและเคล็ดลับเพิ่มเติมในคำถามนี้


2
php เหมือน C มากพอที่ "Extantant ctags" ควรใช้งานได้ ไม่ทราบว่ามีโหมดหลามหรือไม่
พอลทอมบลิน

5
ไม่มีประสบการณ์กับ Cscope คืออะไร
Paul Tomblin

10
ความคล้ายคลึงกับ C นั้นไม่เกี่ยวข้องกับ CTags ที่สนับสนุน PHP รองรับ PHP และ Python ดูที่ctags.sourceforge.net/language.htmlเพื่อดูการสนับสนุนอย่างเต็มที่
ข้อมูล

1
ฉันจะสร้าง ctags ได้อย่างไร
dwaynemac

4
มันจะเป็นการดีหากได้รับการอ้างอิงถึงตำแหน่งที่ดีที่สุดในการเรียนรู้วิธีการใช้ ctags เหล่านั้น
Fzs2

137

หากทุกอย่างมีอยู่ในไฟล์เดียวจะมีคำสั่งgd(เช่นเดียวกับใน 'คำจำกัดความของ goto') ซึ่งจะนำคุณไปสู่การเกิดขึ้นครั้งแรกในไฟล์ของคำใต้เคอร์เซอร์ซึ่งมักจะเป็นคำจำกัดความ


1
ถ้าฉันไม่มีคำที่อยู่ใต้เคอร์เซอร์ (ฉันควรจะพิมพ์)
Fuad Saud

@FuadSaud เพียงค้นหาโดยใช้/
LucasB

6
/เกือบจะไม่แม่นยำเสมอไปเพราะมันจะเข้ากันได้ดีกับทุกรอบ ฉันค้นพบว่าคุณสามารถทำได้:tag <function_name>เพื่อข้ามไปยังคำจำกัดความผ่าน ctags
Fuad Saud

คุณลักษณะ @Faud Jump To Definition อาศัยการชี้ตำแหน่งตัวชี้ด้วยเคอร์เซอร์ (ในทุก IDE) การพิมพ์ / ค้นหาเป็นอีกคุณสมบัติหนึ่งที่ทำให้คุณสับสน
เลือด

101

g* ทำงานที่ดีโดยไม่ต้องตั้งค่า ctags

นั่นคือประเภทg, *(หรือเพียงแค่*- ดูด้านล่าง) เพื่อค้นหาคำภายใต้เคอร์เซอร์ (ในกรณีนี้ชื่อฟังก์ชัน) จากนั้นกดnเพื่อไปยังเหตุการณ์ถัดไป (หรือShift- nสำหรับก่อนหน้า)

มันไม่ได้ข้ามไปที่คำจำกัดความโดยตรงเนื่องจากคำสั่งนี้เพียงแค่ค้นหาคำที่อยู่ใต้เคอร์เซอร์ แต่ถ้าคุณไม่ต้องการจัดการกับการตั้งค่า ctags ในขณะนี้คุณอย่างน้อยก็สามารถช่วยตัวเองไม่ให้ต้อง พิมพ์ชื่อฟังก์ชันเพื่อค้นหาคำจำกัดความ

- แก้ไข - แม้ว่าฉันจะใช้ g * มาเป็นเวลานานฉันเพิ่งค้นพบทางลัดสองทางสำหรับทางลัดเหล่านี้!

(a) *จะข้ามไปที่คำถัดไปที่อยู่ใต้เคอร์เซอร์ (ไม่จำเป็นต้องพิมพ์gคำสั่ง 'goto' ใน vi)

(b) #ไปที่เหตุการณ์ก่อนหน้าในลักษณะเดียวกัน

N และ n ยังคงใช้งานได้ แต่ '#' มักจะมีประโยชน์มากในการเริ่มการค้นหาในขั้นต้นในทิศทางตรงกันข้ามเช่นเมื่อค้นหาการประกาศของตัวแปรภายใต้เคอร์เซอร์


10
ความแตกต่างระหว่าง*และg*คือขอบเขตของคำในการค้นหา *ไม่ได้\<keyword\>ค้นหา (เช่นเดียวกับ\bkeyword\bใน regex ปกติ) ในขณะที่g*การค้นหาkeywordโดยไม่ต้องขอบเขตของคำ
Nicolai S

หากคุณมีหนึ่งร้อยครั้งที่เกิดขึ้นของฟังก์ชั่นในไฟล์*จะนำคุณไปสู่ค่าเฉลี่ย 50 ครั้งก่อนที่คุณจะพบคำจำกัดความ
naught101

49

ใช้gdหรือgDวางเคอร์เซอร์บนตัวแปรใด ๆ ในโปรแกรมของคุณ

  1. gd จะนำคุณไปสู่การประกาศในท้องที่
  2. gD จะนำคุณไปสู่การประกาศระดับโลก

เพิ่มเติมตัวเลือกการนำสามารถพบได้ในที่นี่

ใช้cscopeสำหรับอ้างอิงข้ามโครงการขนาดใหญ่เช่นเคอร์เนล linux


14

ขณะที่พอล Tomblin กล่าวถึงคุณต้องใช้ctags คุณสามารถลองใช้ปลั๊กอินเพื่อเลือกอันที่เหมาะสมหรือเพื่อดูตัวอย่างคำจำกัดความของฟังก์ชั่นภายใต้เคอร์เซอร์ หากไม่มีปลั๊กอินคุณจะปวดหัวพยายามเลือกหนึ่งในวิธีการ 'doAction' ที่เกินพิกัดนับร้อยที่สร้างขึ้นในการสนับสนุน ctags ไม่ได้คำนึงถึงบริบท - เพียงแค่ชื่อ

นอกจากนี้คุณสามารถใช้cscopeและฟังก์ชั่น 'ค้นหาสัญลักษณ์ทั่วโลก' แต่เสียงเรียกเข้าของคุณจะต้องถูกคอมไพล์ด้วยการสนับสนุน + cscope ซึ่งไม่ใช่ตัวเลือกหนึ่งของการสร้าง

หากคุณรู้ว่ามีการกำหนดฟังก์ชันไว้ในไฟล์ปัจจุบันคุณสามารถใช้การกดแป้น 'gD' ในโหมดปกติเพื่อข้ามไปยังนิยามของสัญลักษณ์ภายใต้เคอร์เซอร์

นี่คือปลั๊กอินที่ดาวน์โหลดมากที่สุดสำหรับการนำทาง
http://www.vim.org/scripts/script.php?script_id=273

นี่คือสิ่งที่ฉันเขียนเพื่อเลือกบริบทในขณะที่ข้ามไปยังแท็ก
http://www.vim.org/scripts/script.php?script_id=2507


สวัสดี @ mykola-golubyev ลิงก์ที่คุณให้ไว้ในDetailed descriptionส่วนของ#2507สคริปต์เสียหาย คุณให้อีกอันได้ไหม
FelikZ

12

อีกเทคนิคทั่วไปคือการวางชื่อฟังก์ชั่นในคอลัมน์แรก สิ่งนี้อนุญาตให้ค้นหานิยามได้ด้วยการค้นหาแบบง่าย

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

ฟังก์ชั่นดังกล่าวข้างต้นสามารถพบได้ด้วย/^mainภายในไฟล์หรือ:grep -r '^main' *.cในไดเรกทอรี ตราบใดที่รหัสนั้นถูกย่อหน้าอย่างถูกต้องเพียงครั้งเดียวที่ตัวระบุจะเกิดขึ้นที่จุดเริ่มต้นของบรรทัดจะอยู่ที่นิยามฟังก์ชัน

แน่นอนถ้าคุณไม่ได้ใช้ctagsจากจุดนี้คุณควรละอายใจตัวเอง! อย่างไรก็ตามฉันพบว่ามาตรฐานการเข้ารหัสนี้มีประโยชน์เช่นกัน


13
ฉันสงสัยอยู่เสมอว่าทำไมผู้เขียนบางคนเขียนลายเซ็นของพวกเขาในแบบนั้น!
Tarrasch

นอกจากนี้เมื่อคุณเขียนลายเซ็นฟังก์ชันรวมถึง '{' ในคอลัมน์แรกคุณสามารถเลื่อนไปยังแต่ละฟังก์ชั่นได้อย่างรวดเร็วโดยการกด]] เพื่อไปข้างหน้าในไฟล์และ [[เพื่อย้อนกลับ
BentChainRing

12

TL; DR:

วิธีที่ทันสมัยคือการใช้COCสำหรับการเติมเต็มเหมือนใน Intellisense และเซิร์ฟเวอร์ภาษาหนึ่งภาษาขึ้นไปสำหรับการข้ามไปที่การกำหนด (และอื่น ๆ อีกมากมาย) สำหรับการใช้งานที่มากขึ้น (แต่ไม่จำเป็นสำหรับการข้ามไปสู่คำจำกัดความ) คุณสามารถติดตั้งตัวแก้จุดบกพร่องอย่างน้อยหนึ่งตัวและรับประสบการณ์ IDE แบบเต็มรูปแบบ เริ่มต้นอย่างรวดเร็ว:

  1. ติดตั้งvim-plugเพื่อจัดการปลั๊กอิน VIM ของคุณ
  2. เพิ่มCOCและ (เป็นทางเลือก) Vimspectorที่ด้านบนของ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. โทร:source $MYVIMRC | PlugInstallเพื่อดาวน์โหลดปลั๊กอิน VIM
  4. รีสตาร์ทvimและโทร:CocInstall coc-marketplaceเพื่อรับการเข้าถึงส่วนขยาย COC ได้ง่าย
  5. โทร:CocList marketplaceและค้นหาเซิร์ฟเวอร์ภาษาเช่น:
    • พิมพ์pythonเพื่อค้นหาcoc-jedi,
    • พิมพ์phpเพื่อค้นหาcoc-phplsเป็นต้น
  6. (เป็นทางเลือก) ดูinstall_gadget.py --helpdebuggers ที่มีอยู่เช่น:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-phpฯลฯ

คำตอบแบบเต็ม:

เซิร์ฟเวอร์ภาษา (LS) เป็นโปรแกรมแบบสแตนด์อโลนแยกต่างหาก (สำหรับแต่ละภาษาการเขียนโปรแกรม) ทำงานในพื้นหลังที่และวิเคราะห์โครงการทั้งหมดของคุณในเวลาจริงเปิดเผยความสามารถพิเศษในการแก้ไขของคุณ (แก้ไขใด ๆ ที่ไม่เพียงvim) คุณได้รับสิ่งที่ชอบ:

  • การทำให้แท็ก namespace ทราบเสร็จ
  • ข้ามไปที่คำจำกัดความ
  • ข้ามไปที่ข้อผิดพลาดถัดไป / ก่อนหน้า
  • ค้นหาการอ้างอิงทั้งหมดไปยังวัตถุ
  • ค้นหาการใช้งานอินเตอร์เฟสทั้งหมด
  • เปลี่ยนชื่อในโครงการทั้งหมด
  • เอกสารเกี่ยวกับการโฮเวอร์
  • ตัวอย่างการกระทำโค้ดการจัดรูปแบบการขุยและอื่น ๆ ...

การสื่อสารกับเซิร์ฟเวอร์ภาษาเกิดขึ้นผ่านLanguage Server Protocol (LSP) ทั้งสองnvimและvim8(หรือสูงกว่า) รองรับ LSP ผ่านทางปลั๊กอินซึ่งเป็นที่นิยมมากที่สุดคือConquer of Completion (COC)

รายการเซิร์ฟเวอร์ภาษาที่พัฒนาแล้วและความสามารถของพวกเขานั้นมีอยู่ในเว็บไซต์Lang Server ไม่ใช่ทั้งหมดที่มีให้โดยส่วนขยาย COC หากคุณต้องการใช้หนึ่งในนั้นคุณสามารถเขียนส่วนขยาย COC ด้วยตัวคุณเองหรือติดตั้ง LS ด้วยตนเองและใช้คอมโบของปลั๊กอิน VIM ต่อไปนี้เป็นทางเลือกแทน COC:

  • LanguageClient - จัดการ LSP
  • deoplete - ทริกเกอร์เสร็จเมื่อคุณพิมพ์

การสื่อสารกับ debuggers เกิดขึ้นผ่านDebug Adapter Protocol (DAP) ส่วนใหญ่นิยม DAP ปลั๊กอินสำหรับ VIM เป็นVimspector

Language Server Protocol (LSP) ถูกสร้างขึ้นโดยMicrosoftสำหรับ Visual Studio Code และเปิดตัวเป็นโครงการโอเพ่นซอร์สพร้อมลิขสิทธิ์ MIT ที่ได้รับอนุญาต (มาตรฐานโดยการทำงานร่วมกับ Red Hat และ Codenvy) หลังจากนั้น Microsoft ก็เปิดตัวDebug Adapter Protocol (DAP) เช่นกัน VSCode รองรับภาษาใดก็ได้ที่รองรับ

ฉันส่วนตัวแนะนำให้ใช้เซิร์ฟเวอร์ภาษา COC + ที่จัดทำโดยส่วนขยาย COC + ALEสำหรับการตัดพิเศษ (แต่ด้วยการสนับสนุน LSP ถูกปิดใช้งานเพื่อหลีกเลี่ยงข้อขัดแย้งกับ COC) + Vimspector + debuggers ที่จัดทำโดย Vimspector (เรียกว่า "gadgets") + ปลั๊กอิน 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()

คุณสามารถ google แต่ละคนเพื่อดูว่าพวกเขาทำอะไร


11

1- ติดตั้ง ctags ที่อุดมสมบูรณ์ หากคุณใช้ osx บทความนี้จะแสดงเคล็ดลับเล็กน้อย: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- หากคุณต้องการรวม ctags สำหรับไฟล์ในไดเรกทอรีของคุณเท่านั้นให้เรียกใช้คำสั่งนี้ในไดเรกทอรีของคุณ:

ctags -R

สิ่งนี้จะสร้างไฟล์ "แท็ก" สำหรับคุณ

3- หากคุณใช้ Ruby และต้องการรวม ctags สำหรับอัญมณีของคุณ (สิ่งนี้มีประโยชน์จริง ๆ สำหรับฉันด้วย RubyMotion และอัญมณีในท้องถิ่นที่ฉันได้พัฒนาขึ้น) ทำสิ่งต่อไปนี้:

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

เครดิต: https://coderwall.com/p/lv1qww (โปรดทราบว่าฉันไม่ใช้ตัวเลือก -e ซึ่งสร้างแท็กสำหรับ emacs แทนที่จะเป็นกลุ่ม)

4- เพิ่มบรรทัดต่อไปนี้ใน ~ / .vimrc ของคุณ

set autochdir 
set tags+=./tags;

(ทำไมเครื่องหมายโคลอนกึ่ง: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- ไปที่คำที่คุณต้องการติดตามและกดctrl + ]; หากคุณต้องการกลับไปใช้ctrl+o(ที่มา: https://stackoverflow.com/a/53929/226255 )


ลิงก์ไปยังบทความ Mac ที่กล่าวถึงนั้นใช้งานไม่ได้ นี่คือลิงค์อัพเดท: runtime-era.blogspot.com/2012/05/… ทางออกที่ดีที่สุดของคุณคือติดตั้ง ctags ด้วยเครื่องมือเช่น Homebrew
ZaydH

6

สำหรับคำตอบของ Paul ที่สอง: ใช่ ctags (โดยเฉพาะ exuberant-ctags ( http://ctags.sourceforge.net/ )) นั้นยอดเยี่ยม ฉันได้เพิ่มสิ่งนี้ไว้ใน vimrc ของฉันด้วยดังนั้นฉันจึงสามารถใช้ไฟล์แท็กเดียวสำหรับทั้งโครงการ:

set tags=tags;/

2

cscopeติดตั้ง มันใช้งานได้ดีมากctagsแต่มีประสิทธิภาพมากกว่า ไปกับความหมายแทนCtrl+ ]ทำCtrl+ +\ gแน่นอนคุณอาจใช้ทั้งสองอย่างพร้อมกัน แต่ด้วยโครงการขนาดใหญ่ (เช่นเคอร์เนล Linux), cscope อยู่ห่างออกไปหลายไมล์


1

หลังจากสร้าง ctags คุณยังสามารถใช้สิ่งต่อไปนี้ในกลุ่ม:

:tag <f_name>

ข้างต้นจะนำคุณไปสู่การกำหนดฟังก์ชั่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.