Puis-je utiliser «gf» (ou similaire) pour ouvrir un fichier et passer à un terme de recherche?

9

Existe-t-il un moyen d'obtenir la gfcommande de vim (ou quelque chose de similaire) pour reconnaître un +{cmd}argument pour les chemins de fichiers?

On peut démarrer vim et aller directement à un terme de recherche en faisant:

$ vim +/coding_effort ~/project/file

De même, en mode commande, vous pouvez faire:

:e +/coding_effort ~/project/file

Je prends souvent des notes et me réfère à d'autres fichiers comme celui-ci:

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

J'adorerais pouvoir sélectionner +/coding_effort ~/project/file, taper quelque chose comme gfet que vim fasse la bonne chose.

Oliver Taylor
la source
Je ne pense pas qu'il y ait moyen de le faire par défaut, mais vous pourriez probablement créer un plugin qui le fait.
EvergreenTree

Réponses:

6

Non, le premier problème est que l'espace nécessaire entre la commande et le nom de fichier ne fait pas partie de l' isfname'option ' , et l'ajouter signifierait que les bordures de fichier ne pourraient pas être reconnues du tout. Vous devez soit toujours utiliser une sélection visuelle (à la fois de la commande et du nom de fichier), soit implémenter une analyse personnalisée dans une gfsurcharge de commandes.

Deuxièmement, le intégré gfne reconnaît pas la +{cmd}syntaxe, il n'y a donc vraiment aucun moyen d'implémenter votre propre mappage personnalisé. Ceci est certainement possible ( en utilisant des fonctions comme expand('<cfile>'), getline(), etc.), mais prend probablement quelques lignes de la fonction Vimscript.

Si vous choisissez une syntaxe différente ( filename:+command), vous pouvez conserver les gfcommandes d' origine et implémenter le fractionnement dans un :autocmd, semblable à ce que fait le plugin de fichier très lié : linefilespec:linenumber ).

Ingo Karkat
la source
2

Voici une fonction qui devrait reproduire le gfcomportement intégré , et recherche également les œuvres commençant par +qui sont ensuite transmises à: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>

Les commentaires devraient expliquer ce que fait la fonction plus en détail ... J'ai écrit cela dans le train le matin, et (évidemment) je ne l'ai pas testé de manière approfondie ;-)

Martin Tournoij
la source
1

Une option serait (en supposant que le +cmd file/pathest sélectionné) de copier la sélection dans un registre, puis d'insérer ce registre dans l'invite de commande. Je l'ai fait avec la cartographie suivante:

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

Oliver Taylor
la source
1

Cette notation fonctionne ( 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/

avec fonction et cartographie ci-dessous.

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
la source