Могу ли я использовать «gf» (или аналогичный), чтобы открыть файл и перейти к поисковому запросу?


9

Есть ли способ заставить gfкоманду vim (или что-то подобное) распознать +{cmd}аргумент для пути к файлу?

Можно запустить vim и перейти непосредственно к поисковому запросу, выполнив:

$ 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, и Vim сделать правильные вещи.


Я не думаю, что есть способ сделать это по умолчанию, но вы могли бы создать плагин, который это делает.
EvergreenTree

Ответы:


6

Нет, первая проблема заключается в том, что необходимый пробел между командой и именем файла не является частью isfname'опции ' , и добавление его будет означать, что границы файла вообще не могут быть распознаны. Вам либо нужно всегда использовать визуальный выбор (как команды, так и имени файла), либо реализовать пользовательский анализ в gfперегрузке команды.

Во-вторых, встроенный gfне распознает +{cmd}синтаксис, поэтому на самом деле нет способа реализовать собственное отображение. Это, безусловно, возможно (с использованием таких функций, как expand('<cfile>'), getline()и т. Д.), Но, вероятно, занимает несколько строк функции Vimscript.

Если вы выберете другой синтаксис ( filename:+command), вы можете оставить исходные gfкоманды и реализовать разбиение в :autocmd, аналогично тому, для чего предназначен очень связанный файл: плагин linefilespec: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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.