Complétion automatique des valeurs d'options sur la ligne de commande

10

Je ne peux pas compter le nombre de fois où j'ai essayé de le faire:

:set foldmethod=syn^I

Il semble que l'achèvement ne fonctionne pas sur les valeurs des options!

Dans certains cas, les options sont des chaînes complexes où l'achèvement peut ne pas avoir de sens. (Par exemple 'comments'.)

Mais y a-t-il eu des efforts pour fournir des compléments de caractères génériques aux cas d'utilisation courants?

Sinon, comment pourrais-je faire fonctionner l'exemple ci-dessus? (En supposant que je voulais compléter l'une des chaînes ['manual', 'indent', 'expr', 'marker', 'syntax'].)

joeytwiddle
la source

Réponses:

3

Vous pouvez essayer le code suivant:

let s:option_values = {'foldmethod'  : ['manual', 'indent', 'expr', 'marker', 'syntax'],
                     \ 'bufhidden'   : ['hide', 'unload', 'delete', 'wipe'],
                     \ 'virtualedit' : ['block', 'insert', 'all', 'onemore'] ,}

set wildcharm=<c-z>

cnoremap <expr> <tab>
            \ getcmdline() !~# '^\s*set\s\+\w\+=' <bar><bar> wildmenumode() ?
            \ '<c-z>' :
            \ '<c-u>' . substitute(getcmdline(), 'set', 'Set', '') . '<c-z>'

command! -nargs=1 -complete=customlist,s:SetComplete Set exe 'set' <q-args>

function! s:SetComplete(A, L, P) abort
    let option = matchstr(a:A, '^.*\ze=')
    if !has_key(s:option_values, option)
        return
    endif
    let candidates = copy(s:option_values[option])
    call map(candidates, 'option . "=" . v:val')
    return filter(candidates, 'v:val =~ "^" . a:A')
endfunction

Il définit d'abord un dictionnaire s:option_valuesdont le but est de contenir vos options (comme ses clés) et leurs valeurs (comme ses valeurs qui sont des listes). Ici, à titre d'exemple, 3 options + valeurs sont stockées:
'foldmethod', 'bufhidden', 'virtualedit'.

set wildcharm=<c-z>

Cette ligne définit l' 'wildcharm'option et indique à Vim que s'il voit <c-z>dans un mappage, il doit activer le menu wild. Sans définir cette option, si vous écrivez <tab>dans un mappage, il insérera simplement un caractère de tabulation littéral.

cnoremap <expr> <tab>

Commencez la définition d'un mappage qui tapera l'évaluation d'une expression chaque fois que vous frappez <tab>sur la ligne de commande.

\ getcmdline() !~# '^\s*set\s\+\w\+=' <bar><bar> wildmenumode() ?

Le mappage teste si la ligne de commande correspond au modèle ^\s*set\s\+\w\+=, qui est une ligne suivant le formulaire set option=, ou si le menu générique est actif.

\ '<c-z>' :

Si le test précédent réussit, le mappage active le menu wild.

\ '<c-u>' . substitute(getcmdline(), 'set', 'Set', '') . '<c-z>'

Sinon, il remplace la commande système :setpar la commande personnalisée :Setet active le menu générique.

command! -nargs=1 -complete=customlist,s:SetComplete Set exe 'set' <q-args>

Définissez la commande personnalisée :Setqui fait la même chose que :set, sauf qu'elle peut utiliser une fonction de complétion personnalisée dont le nom est ici s:SetComplete().

function! s:SetComplete(A, L, P) abort

Commencez la définition de la fonction d'achèvement personnalisée.

Il doit renvoyer des suggestions / candidats à travers une liste.
La :Setcommande lui enverra automatiquement 3 arguments:

  • la partie principale de l'argument en cours de finalisation (c.-à-d. option=...)
  • toute la ligne de commande
  • la position du curseur dedans

Voir :h :command-completion-customlistpour plus d'informations.

let option = matchstr(a:A, '^.*\ze=')

Extrayez le nom de l'option de l'argument en cours de finalisation.

if !has_key(s:option_values, option)
    return
endif

Vérifiez s'il se optiontrouve dans votre dictionnaire. Si ce n'est pas le cas, la fonction ne renvoie rien.

let candidates = copy(s:option_values[option])

Obtenez une copie de la liste des valeurs que l'option peut prendre dans votre dictionnaire.

call map(candidates, 'option . "=" . v:val')

Pour chaque valeur de la liste candidates, ajoutez la chaîne option=(où optionsera évaluée).

return filter(candidates, 'v:val =~ "^" . a:A')

Supprimez les éléments candidatesdont le début ne correspond pas à l'argument en cours de finalisation et retournez le résultat.

user9433424
la source
2

AFAIK, nous ne pouvons pas ajouter cmdline-complétement aux commandes intégrées qui ne le fournissent pas. Soit nous "remplaçons" la commande par une autre qui supportera l'achèvement (ici, vous pouvez définir :Setavec une majuscule S), soit nous piratons le code source de vim pour ajouter ce qui manque.

Luc Hermitte
la source