Dapatkah saya menggunakan "gf" (atau serupa) untuk membuka file dan melompat ke istilah pencarian?

9

Apakah ada cara untuk mendapatkan gfperintah vim (atau yang serupa) untuk mengenali +{cmd}argumen untuk path file?

Seseorang dapat memulai vim dan langsung menuju ke istilah pencarian dengan melakukan:

$ vim +/coding_effort ~/project/file

Demikian pula, dalam mode perintah yang dapat Anda lakukan:

:e +/coding_effort ~/project/file

Saya sering membuat catatan dan merujuk ke file lain seperti ini:

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

Saya ingin dapat memilih +/coding_effort ~/project/file, mengetik sesuatu seperti gf, dan vim melakukan hal yang benar.

Oliver Taylor
sumber
Saya tidak berpikir ada cara untuk melakukan ini secara default, tetapi Anda mungkin bisa membuat plugin yang melakukannya.
EvergreenTree

Jawaban:

6

Tidak, masalah pertama adalah ruang yang diperlukan antara perintah dan nama file bukan bagian dari isfname'opsi ' , dan menambahkan itu berarti batas file tidak dapat dikenali sama sekali. Anda harus selalu menggunakan pemilihan visual (baik dari perintah dan nama file), atau mengimplementasikan penguraian kustom dalam gfperintah yang berlebihan.

Kedua, built-in gftidak mengenali +{cmd}sintaks, jadi benar-benar tidak ada jalan untuk mengimplementasikan pemetaan kustom Anda sendiri. Hal ini tentunya mungkin (menggunakan fungsi seperti expand('<cfile>'), getline(), dll), tapi mungkin membutuhkan beberapa baris fungsi Vimscript.

Jika Anda memilih sintaks yang berbeda ( filename:+command), Anda dapat menyimpan gfperintah asli dan mengimplementasikan pemisahan dalam :autocmd, mirip dengan apa yang terkait dengan file: plugin line lakukan untuk filespec:linenumber).

Ingo Karkat
sumber
2

Berikut adalah fungsi yang harus mereplikasi gfperilaku bawaan, dan juga memindai untuk pekerjaan yang dimulai dengan +yang kemudian diteruskan: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>

Komentar harus menjelaskan apa fungsi tidak lebih detail ... Saya menulis ini di kereta pagi, dan (jelas) tidak mengujinya secara ekstensif ;-)

Martin Tournoij
sumber
1

Salah satu opsi adalah (dengan asumsi yang +cmd file/pathdipilih) untuk menarik pilihan ke register, lalu memasukkan register itu di prompt perintah. Saya melakukan ini dengan pemetaan berikut:

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

Oliver Taylor
sumber
1

Notasi ini berfungsi ( 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/

dengan fungsi dan pemetaan di bawah ini.

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
qeatzy
sumber