ฉันสามารถใช้“ gf” (หรือคล้ายกัน) เพื่อเปิดไฟล์และข้ามไปที่คำค้นหาได้หรือไม่?


9

มีวิธีgfรับคำสั่งเป็นกลุ่ม(หรือคล้ายกัน) เพื่อรับรู้+{cmd}อาร์กิวเมนต์สำหรับเส้นทางไฟล์หรือไม่

หนึ่งสามารถเริ่มต้นเป็นกลุ่มและไปที่คำค้นหาโดยตรงโดยทำ:

$ vim +/coding_effort ~/project/file

ในทำนองเดียวกันในโหมดคำสั่งคุณสามารถทำได้:

:e +/coding_effort ~/project/file

ฉันมักจะจดบันทึกและอ้างถึงไฟล์อื่นเช่นนี้

For more info see +/coding_effort ~/project/file where there's a detailed discussion.

ฉันชอบที่จะสามารถเลือก+/coding_effort ~/project/fileพิมพ์สิ่งที่ชอบgfและมีความสุขที่ได้ทำสิ่งที่ถูกต้อง


ฉันไม่คิดว่าจะมีวิธีใดในการทำเช่นนี้ตามค่าเริ่มต้น แต่คุณอาจสร้างปลั๊กอินที่ใช้งานได้
EvergreenTree

คำตอบ:


6

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

ประการที่สองบิวด์อินgfไม่รู้จัก+{cmd}ไวยากรณ์ดังนั้นจึงไม่มีวิธีแก้ไขการแม็พที่คุณกำหนดเอง สิ่งนี้เป็นไปได้อย่างแน่นอน (ใช้ฟังก์ชันเช่นexpand('<cfile>'), getline()ฯลฯ ) แต่อาจใช้ฟังก์ชัน Vimscript สองสามบรรทัด

หากคุณเลือกไวยากรณ์ที่แตกต่างกัน ( filename:+command) คุณสามารถเก็บเดิมgfคำสั่งและดำเนินการแยกใน:autocmdคล้ายกับสิ่งที่เกี่ยวข้องมากไฟล์: สายปลั๊กอินไม่ให้filespec:linenumber)


2

นี่คือฟังก์ชั่นที่ควรทำซ้ำในตัวที่gfพฤติกรรมและยังสแกนสำหรับการทำงานที่เริ่มต้นด้วย+ซึ่งจากนั้นจะได้รับการส่งผ่านไปยัง:edit

fun! GotoWithCommand()
        let l:file = expand('<cfile>')

        " Replace ~ with the home directory
        let l:file = substitute(l:file, '^\~', $HOME, '')

        " File doesn't exist; return
        if !filereadable(l:file)
                echohl ErrorMsg
                echomsg "E447: Can't find file \"" . l:file . '" in path'
                echohl None
                return 0
        endif

        " Save cursor postion
        let l:save_cursor = getpos(".")

        " Make sure we go to the previous word (B on the first character of the
        " filename goes to the previous word, B anywhere else goes to the start of
        " the filename)
        call search('\(\s\|^\)', 'b')

        " Try to find argument to be executed; these start with a `+'
        let l:commands = ''
        while 1
                " Go one WORD backwards
                normal! B

                " Not a +; stop the loop
                if getline('.')[col('.') - 1] != '+'
                        break
                endif

                let l:commands .= ' ' . expand('<cWORD>')
        endwhile

        " Restore cursor postion
        call setpos('.', l:save_cursor)

        " Now, open the new file...
        execute ':edit ' . l:commands . ' ' . l:file
endfun

nnoremap <Leader>gf :call GotoWithCommand()<CR>

ความคิดเห็นควรอธิบายสิ่งที่ฟังก์ชั่นทำในรายละเอียดมากขึ้น ... ฉันเขียนสิ่งนี้บนรถไฟในตอนเช้าและ (แน่นอน) ไม่ได้ทดสอบอย่างกว้างขวาง ;-)


1

ตัวเลือกหนึ่งคือ (สมมติว่า+cmd file/pathเลือกไว้) เพื่อดึงส่วนที่เลือกไปยังรีจิสเตอร์จากนั้นแทรกเรจิสเตอร์นั้นในพรอมต์คำสั่ง ฉันทำสิ่งนี้ด้วยการทำแผนที่ต่อไปนี้:

vnoremap gsf "0y:e <c-r>0<cr>


1

สัญลักษณ์นี้ใช้งานได้ ( file name+ trailing :+ / pat /)

/usr/include/stdio.h:/int printf/  -- `file name` + `:` + `/ pat /`
/usr/include/stdio.h:+/int printf/
/usr/include/stdio.h: /int printf/
/usr/include/stdio.h: /#define\s/
/usr/include/stdio.h: /^#define\sSEEK/

ด้วยฟังก์ชั่นและการทำแผนที่ด้านล่าง

nn gf :<C-u>call Gf_search()<CR>

func! Gf_search() abort
    let word = expand('<cWORD>')
    let idx = stridx(word, ':')
    if idx != -1
        let remline = strpart(getline('.'),col('.'))
        let pat = substitute(remline, '.*[:+ ]/\([^/]*\)/.*', '\1', "")
        if pat != remline
            let pat = substitute(pat, '\\', '\\\\', 'g')
            let pat = substitute(pat, ' ', '\\ ', 'g')
            let filename = expand('<cfile>')
            exec 'e +/'.pat filename
            return
        endif
    endif
    " fallback to builtin gF
    norm! gF
endfunc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.