¿Puedo usar "gf" (o similar) para abrir un archivo y saltar a un término de búsqueda?

9

¿Hay alguna manera de obtener el gfcomando de vim (o algo similar) para reconocer un +{cmd}argumento para las rutas de archivo?

Se puede iniciar vim e ir directamente a un término de búsqueda haciendo:

$ vim +/coding_effort ~/project/file

Del mismo modo, en modo comando puede hacer:

:e +/coding_effort ~/project/file

A menudo tomo notas y me refiero a otros archivos como este:

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

Me encantaría poder seleccionar +/coding_effort ~/project/file, escribir algo parecido gfy hacer que vim haga lo correcto.

Oliver Taylor
fuente
No creo que haya ninguna forma de hacerlo de forma predeterminada, pero probablemente podría crear un complemento que lo haga.
EvergreenTree

Respuestas:

6

No, el primer problema es que el espacio necesario entre el comando y el nombre de archivo no es parte de la isfname'opción ' , y agregarlo significaría que los bordes del archivo no podrían reconocerse en absoluto. Debería usar siempre una selección visual (tanto de comando como de nombre de archivo) o implementar un análisis personalizado en una gfsobrecarga de comandos.

En segundo lugar, el incorporado gfno reconoce la +{cmd}sintaxis, por lo que realmente no hay forma de implementar su propia asignación personalizada. Esto es ciertamente posible (usando funciones como expand('<cfile>'), getline()etc.), pero probablemente tome algunas líneas de la función Vimscript.

Si elige una sintaxis diferente ( filename:+command), puede mantener los gfcomandos originales e implementar la división en un :autocmd, similar a lo que hace el muy relacionado archivo: plugin de líneafilespec:linenumber ).

Ingo Karkat
fuente
2

Aquí hay una función que debería replicar el gfcomportamiento incorporado , y también busca trabajos que comiencen y +luego pasen a: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>

Los comentarios deberían explicar lo que hace la función con más detalle ... Escribí esto en el tren la mañana, y (obviamente) no lo probé extensamente ;-)

Martin Tournoij
fuente
1

Una opción sería (suponiendo que +cmd file/pathse selecciona) para tirar la selección a un registro, luego insertar ese registro en el símbolo del sistema. Hice esto con el siguiente mapeo:

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

Oliver Taylor
fuente
1

Esta notación funciona ( 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/

con función y mapeo a continuación.

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
fuente