ค้นหาด่วน จำกัด เฉพาะฟังก์ชัน C ++


13

ฉันทำงานในโครงการ C ++ ที่ค่อนข้างใหญ่ ด้านที่น่าผิดหวังอีกอย่างหนึ่งขององค์กรก็คือฟังก์ชั่นที่มีขนาดใหญ่มาก ๆ อยู่ในไฟล์ขนาดใหญ่ที่น่าขัน

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

(ฉันมี ctags ติดตั้งและใช้ Tagbar ... ซึ่งอาจเป็นประโยชน์สำหรับสิ่งนี้)

คำตอบ:


9

นี่คือวิธีที่ฉันจะทำมัน เพิ่มไปยังของคุณ.vimrc

vnoremap if [[O][

คำอธิบาย: vnoremap หมายถึงแผนที่ทางด้านซ้ายมือifไปทางด้านขวามือ[[mO][ในขณะที่คุณอยู่ในโหมดภาพ ifหมายถึงในฟังก์ชั่นแม้ว่าคุณจะสามารถเปลี่ยนชื่อได้ถ้าคุณต้องการ [[ข้ามไปยังจุดเริ่มต้นของฟังก์ชัน Oย้ายไปยังส่วนอื่น ๆ ของข้อความที่คุณเลือกแล้ว][ย้ายไปยังส่วนท้ายของฟังก์ชัน

ดังนั้นถ้าคุณต้องการค้นหาในฟังก์ชั่นตอนนี้คุณเข้าสู่โหมดภาพกับและเลือกฟังก์ชั่นทั้งหมดที่มีv ifตอนนี้ออกจากโหมดภาพกับและค้นหาด้วย<esc> จำกัด การค้นหาของคุณไว้ที่ข้อความที่เลือกก่อนหน้า หากคุณไม่ต้องการตีคุณสามารถเพิ่มสิ่งนี้ใน:/\%V\%V<esc>/\%V.vimrc

vnoremap / <esc>/\%V

จากนั้นลำดับการกดแป้นของคุณจะมีลักษณะดังนี้:

vif/foo<enter>

และสิ่งนี้จะค้นหาการเกิดขึ้นของ foo ทั้งหมดในฟังก์ชันปัจจุบัน


ข้อเสียเพียงอย่างเดียวของวิธีนี้คือคาดว่าวงเล็บปีกกาเปิดและปิดของทั้งคู่จะมี 0 เยื้อง หากคุณทำงานกับรหัสที่ไม่มีอยู่เป็นประจำเช่น

int foo() {
    bar()
}

ดังนั้นเวอร์ชันที่ซับซ้อนกว่านี้เล็กน้อยจะใช้งานได้:

vnoremap if ][ma%O'a

สิ่งนี้คาดว่าวงเล็บปีกกาปิดจะมี 0 การเยื้องเท่านั้น หากวงเล็บปีกกาเปิดมีการเยื้องก็ยังคงทำงานแม้ว่ามันจะใช้เวลาทำเครื่องหมาย หากคุณใช้เครื่องหมาย 'a' เป็นประจำคุณสามารถย้ายได้เช่น

vnoremap if ][mb%O'b
vnoremap if ][mc%O'c
...

อนิจจามันใช้งานไม่ได้กับฟังก์ชั่น C ++ แตกต่างจากฟังก์ชั่น C พวกเขามีแนวโน้มที่จะเยื้อง (เป็นกรณีที่มีฟังก์ชั่นสมาชิกแบบอินไลน์ที่กำหนดไว้ในคำจำกัดความของชั้นเรียนและมีการเยื้องเริ่มต้นของฟังก์ชั่นภายใน namespaces) อย่างไรก็ตามความคิดของคุณสามารถสร้างขึ้นได้ด้วยช่วงความหมายฟังก์ชันที่สามารถรับได้ด้วย ctags ฉันทำมันในฟังก์ชั่นlh#dev#find_function_boundariesจาก lh-dev
Luc Hermitte

3
วิธีการที่ดี หากคุณสามารถค้นหาบรรทัดบนสุดของฟังก์ชั่นได้อย่างน่าเชื่อถือคุณสามารถย้ายไปยัง{และจากนั้นใช้%เพื่อเข้าถึงบรรทัดล่าง ไม่แน่ใจว่าคุณจะพบว่าฟังก์ชันเริ่มต้นใน C ++ ได้อย่างไร แต่วิธีนี้ใช้ได้สำหรับ Javascript:vnoremap if <Esc>?^\s*function<CR>v/{<CR>%o
joeytwiddle

1
เกี่ยวกับการแก้ไขครั้งล่าสุดของคุณ CTRL-]ข้ามไปยังแท็กที่อยู่ใต้เคอร์เซอร์ ไม่ใช่ที่จุดเริ่มต้นของฟังก์ชั่นปัจจุบัน มันจะไม่ช่วย
Luc Hermitte

เกี่ยวกับการแก้ไขใหม่ มันไม่ง่ายอย่างนั้น ความยากลำบากคือการให้ vim รู้ถึงฟังก์ชั่นปัจจุบัน หากมีข้อมูลมันจะไม่ต้องการความช่วยเหลือ ctags วิธีเดียวที่จะได้รับข้อมูล (จาก ctags) คือการวิเคราะห์คำสั่งข้ามไปประกาศที่ผลิตโดย ctags หากคำสั่งเหล่านี้เป็น:linenumberกลุ่มจะทำสิ่งที่ฉันทำในปลั๊กอินของฉัน แต่ไม่มีการรับประกันและคำสั่งเหล่านี้สามารถเป็นตัวแทนได้/pattern- Vim ไม่สามารถทดสอบรูปแบบทั้งหมดเพื่อให้รู้ว่าอันไหนที่ตรงกับฟังก์ชั่นปัจจุบันฉันไม่ทราบถึงการกระทำใด ๆ ของกลุ่มเพื่อข้ามไปยังจุดเริ่มต้นของกระแส ฟังก์ชั่น
Luc Hermitte

6

วิธีการแก้ปัญหาของ DJ McMayhem เป็นแรงบันดาลใจให้ฉันเขียนของฉันเองที่อาศัย ctags และ matchit เพื่อทำการวิเคราะห์ขอบเขตของฟังก์ชั่นที่เหมาะสม

ส่วนที่ยากได้ทำไปแล้วโดยlh-devและ lh-tags เป็นเวลาหลายปี:

  • ไฟล์ปัจจุบันจะถูกแยกวิเคราะห์ผ่าน ctags ด้วยตัวเลือกที่เหมาะสม
  • เรามองหาคำจำกัดความของฟังก์ชั่นทั้งหมดในฐานข้อมูลแท็กซึ่งถูก จำกัด ไว้ที่แท็กที่ได้รับสำหรับไฟล์ปัจจุบัน
  • ขอบคุณฐานข้อมูลเรามีหมายเลขบรรทัดเริ่มต้นสำหรับฟังก์ชั่นทั้งหมด (ดีtemplateและinlineอาจจะพลาดส่วน ctags)
  • ด้วยการค้นหาแบบวนซ้ำอย่างง่าย (การค้นหาแบบไบนารี่สามารถทำได้ แต่ไฟล์ที่ควรจะเป็น "สั้น") ซึ่งเป็นจุดเริ่มต้นของฟังก์ชั่นปัจจุบัน
  • และด้วยการจับคู่กับปลั๊กอินบรรทัดสุดท้ายก็พบได้เช่นกัน - ฉันเห็นว่า ctags สากลนำเสนอendฟิลด์ที่สามารถใช้กับ C, C ++, Python และ Vim ที่สามารถใช้เพื่อค้นหาจุดสิ้นสุดของฟังก์ชัน

โปรดทราบว่าส่วนใด ๆ ของอัลกอริทึมนี้อาจถูกเขียนทับบนพื้นฐานชนิดไฟล์ เช่นการตรวจจับขอบเขตของฟังก์ชั่น python สามารถค้นหาdefและวิเคราะห์การเยื้องเราสามารถค้นหาfunctionใน javascript และอื่น ๆ - ในคำอื่น ๆ รุ่นปัจจุบันยังทำงานร่วมกับ Java, Vim และภาษาอื่น ๆ (ฉันยังมีงานบางอย่าง ทำเพื่อหลาม)

ดังนั้นฉันจึงกำหนดการแมปใหม่สองรายการในขณะนี้: การแมปโหมดภาพและการแมปโหมดที่ดำเนินการอยู่ระหว่างดำเนินการ:

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

ซึ่งพึ่งพา:

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

ฉันขอให้คุณรหัสหลายร้อยบรรทัดของ lh#dev#find_function_boundaries()

และต้องขอบคุณการทำแผนที่ของ DJ McMayhem

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

เราสามารถvif/patternทำการค้นหาpatternในฟังก์ชั่นปัจจุบัน

นอกจากนี้เรายังสามารถลบฟังก์ชั่นด้วยdifดึงมันด้วยyifฯลฯ

นี่คือสิ่งที่ดูเหมือนว่าเมื่อนำไปใช้กับฟังก์ชั่น C ++ ที่เหมือนจริง (เช่นไม่เยื้อง 0):Screencast: เลือกฟังก์ชั่น C ++


4

การค้นหาจุดเริ่มต้นและจุดสิ้นสุดของฟังก์ชันอาจเป็นเรื่องยากโดยเฉพาะอย่างยิ่งในภาษาที่ไม่มีfunctionคำหลัก…และรูปแบบการเยื้องที่ขัดแย้งกันมากมาย

หากฟังก์ชั่นของคุณลงท้ายด้วยวงเล็บปีกกาปิดเพียงอย่างเดียวในบรรทัดของตัวเอง (ดังใน 10 จาก 13 รูปแบบที่แสดงไว้ที่นี่ ) คุณสามารถเลือกใช้สิ่งนี้:

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

จากนั้นการค้นหาfooภายในฟังก์ชั่นของคุณเป็นเพียงเรื่อง:

:'<,'>g/foo/#

เมื่อรวมทั้งหมดเข้าด้วยกันเราสามารถทำแผนที่ได้ค่อนข้างดี:

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

ค้นหาในฟังก์ชั่น

ที่กล่าวว่าการทำแผนที่โหมดภาพอาจจะถูกหลอกได้ง่ายwhileหรือifดังนั้นมันอาจจะได้รับประโยชน์จากการขัดเล็กน้อย นอกจากนี้การรักษาการเลือกภาพอาจไม่ใช่ความคิดที่ดีมาก ...


นี่เป็นเพียงการเลือกบล็อกถัดไปที่สามารถพบได้ มันไม่ทำงานเลยเมื่อคุณเพิ่มif, for, whileฯลฯ
เจมส์

3

วิธีการแก้ปัญหาที่ไม่สมบูรณ์จะใช้เท่า พับทุกอย่าง:

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

แจ้งให้ Vim ทราบเพื่อไม่เปิดพื้นที่พับสำหรับผลการค้นหา:

set foldopen-=search

จากนั้นเปิดฝาพับบนฟังก์ชันที่เป็นปัญหา ( zO)

ตอนนี้เพลงฮิตทั้งหมดสำหรับการค้นหาข้อความในพื้นที่พับจะส่งผลให้ Vim กระโดดไปที่เส้นพับหนึ่งครั้งจากนั้นดำเนินการต่อในการตีต่อไป

ตัวอย่างเช่นในกรณีด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่

ฟังก์ชั่นพับมีประโยชน์หลายอย่างsizeแต่nจะไม่นำฉันไปรอบ ๆ ทุกการใช้งานsizeในฟังก์ชั่นนั้น


3

อีกวิธีหนึ่ง:

  • ใช้ ctags ฯลฯ เพื่อค้นหาฟังก์ชันเป้าหมายไปที่นั่น
  • เลื่อนเคอร์เซอร์ไปข้างหน้าภายในส่วนของฟังก์ชั่น
  • ใช้โอเปอเรเตอร์การค้นหาของ Osyo Manga (ขึ้นอยู่กับvim-operator-user ) เพื่อค้นหาเฉพาะภายในบล็อกปัจจุบัน เช่น:

    " 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{
    

... ตอนนี้คุณสามารถแทรกข้อความค้นหาของคุณในพร้อมท์ที่กำหนด กดnเพื่อดูว่าผลลัพธ์การค้นหาถูก จำกัด การเคลื่อนไหว / ข้อความวัตถุ เนื่องจากนี่คือโอเปอเรเตอร์ Vim (เช่นเรียงต่อกัน) หากคุณมี text-object ฟังก์ชั่นที่ดีคุณไม่จำเป็นต้องย้ายเข้าไปใน body definition ก่อนทำการค้นหา แต่ใช้ smthing like g/ifหรือคล้ายกันโดยตรง

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