Preenchimento automático para valores de opção no cmdline

10

Não consigo contar o número de vezes que tentei fazer isso:

:set foldmethod=syn^I

Parece que a conclusão não funciona nos valores das opções!

Em alguns casos, as opções são cadeias complexas em que a conclusão pode não fazer sentido. (Por exemplo 'comments')

Mas houve algum esforço para fornecer a conclusão de caracteres curinga para os casos de uso comuns?

Caso contrário, como eu poderia fazer o exemplo acima funcionar? (Supondo que eu deseje concluir uma das seqüências de caracteres ['manual', 'indent', 'expr', 'marker', 'syntax'].)

joeytwiddle
fonte

Respostas:

3

Você pode tentar o seguinte código:

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

Primeiro, define um dicionário s:option_valuescujo objetivo é conter suas opções (como chaves) e seus valores (como valores que são listas). Aqui, por exemplo, 3 opções + valores são armazenados:
'foldmethod', 'bufhidden', 'virtualedit'.

set wildcharm=<c-z>

Essa linha define a 'wildcharm'opção e informa ao Vim que, se vir <c-z>em um mapeamento, deverá ativar o menu curinga. Sem definir essa opção, se você escrever <tab>em um mapeamento, ele simplesmente inserirá um caractere de tabulação literal.

cnoremap <expr> <tab>

Comece a definição de um mapeamento que digitará a avaliação de uma expressão sempre que você pressionar <tab>na linha de comando.

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

O mapeamento testa se a linha de comando corresponde ao padrão ^\s*set\s\+\w\+=, que é uma linha após o formulário set option=, ou se o menu curinga está ativo.

\ '<c-z>' :

Se o teste anterior for bem-sucedido, o mapeamento ativa o menu curinga.

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

Caso contrário, ele substitui o comando do sistema pelo comando :setpersonalizado :Sete ativa o menu curinga.

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

Defina o comando personalizado :Setque faz a mesma coisa que :set, exceto que ele pode usar uma função de conclusão personalizada cujo nome está aqui s:SetComplete().

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

Comece a definição da função de conclusão customizada.

Ele deve retornar sugestões / candidatos através de uma lista.
O :Setcomando enviará automaticamente 3 argumentos para ele:

  • a parte principal do argumento atualmente sendo concluída em (ie option=...)
  • toda a linha de comando
  • a posição do cursor nele

Veja :h :command-completion-customlistpara mais informações.

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

Extraia o nome da opção do argumento que está sendo concluído.

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

Verifique se optionestá no seu dicionário. Caso contrário, a função não retorna nada.

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

Obtenha uma cópia da lista de valores que a opção pode obter do seu dicionário.

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

Para cada valor na lista candidates, acrescente a sequência de caracteres option=(onde optionserá avaliada).

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

Remova os itens candidatescujo início não corresponde ao argumento que está sendo concluído e retorne o resultado.

user9433424
fonte
2

AFAIK, não podemos adicionar a conclusão do cmdline aos comandos internos que não o fornecem. Ou "substituímos" o comando por outro que suporte a conclusão (aqui, você pode definir :Setcom maiúsculas S), ou invadimos o código-fonte do vim para adicionar o que está faltando.

Luc Hermitte
fonte