Como posso usar a conclusão do modo de inserção em uma macro?

11

Estou tentando definir uma macro que gera rapidamente uma lista de palavras aleatórias.
Eu quero que a macro transforme isso em uma lista como

a
b
c
d
e

nisso

arezzo
bywords
czars
détente
eyrie

O que tenho até agora:

  • colocar o cursor na letra a
  • começar a gravar macro qq
  • a entre no modo de inserção
  • <C-x><C-k> - perform dictionary completion on the character before cursor - in this case the lettera`
  • <C-p>selecione o último item na lista de conclusão que aparece, no meu sistema é a palavra arezzo. (NB longestincluí na minha 'completeopt'configuração, necessária para <C-p>trabalhar dessa maneira durante a conclusão:) 'set completeopt=longest,menuone,preview'.
  • <C-y> aceite a conclusão
  • ^[^[ sair do modo de inserção
  • j desça para a próxima linha, pronto para fazer a mesma operação na próxima linha
  • q pare de gravar

quando crio a macro e passo as etapas manualmente, tudo funciona bem; no entanto, quando executo a macro, vejo uma mensagem piscando na linha de comando, algo como:

digitalizando arquivo de dicionário

e nada acontece, apenas os comandos da macro jsão executados, ou seja, o cursor se move para baixo da linha, mas nenhum dos comandos de conclusão é executado.
É possível usar as conclusões do modo de inserção em uma macro e, em caso afirmativo, como posso fazer isso?

the_velour_fog
fonte
Eu não entendo o seu <C-p>passo ... quando eu faço isso no meu vim, ele apenas dá a mensagem back at original- não seleciona o último item. Usei a tecla de seta duas vezes para selecionar a última palavra (meu caso azures), pressione enter e então Esc+j+q.. então funciona muito bem na execução de macro
Sundeep
1
@ spasic ah bom ponto, eu deveria ter mencionado, mas estou usando set completeopt=longest,menuone,previewa longestopção que causa <C-p>a inserção imediata. Se eu remover longestda completeoptstring, recebo o mesmo comportamento que você. Além disso, sim, as teclas de seta funcionaram! obrigado (esqueci que você pode usá-los para navegar na lista de conclusão) #
the_velour_fog
Talvez o menu pop-up esteja interferindo. Talvez tente :set completeopt=e a<c-x><c-k><esc>jcomo sua macro.
Antony
@Antony Não sei por que o <Cp> não estava funcionando, mas as setas direcionais funcionaram.
the_velour_fog

Respostas:

2

EDIT : Realmente você está após a conclusão do dicionário; você não precisa necessariamente do modo de inserção (modo Ctrl + X) para fazer isso. Como você descobriu, isso torna o trabalho com macros uma verdadeira dor. O script abaixo pode ser usado para concluir o dicionário sem o modo de inserção, para que você possa repeti-lo facilmente dentro de uma macro.

Adicione o código abaixo ao seu .vimrcarquivo, feche e reabra todas as janelas do vim para obter a nova função e, em seguida, registre-se pressionando alternadamente <C-k>para concluir e jpassar para a próxima linha. Eu adicionei uma verificação para a longestopção e, se estiver desativada, seleciona uma entrada aleatória usando o tempo aleatório do sistema. Se encontrar a longestopção, ela procurará manualmente a entrada correspondente mais longa do dicionário e a inserirá.

Se você não gosta do <C-k>mapeamento, sinta-se à vontade para alterá-lo como achar melhor. Deve funcionar com qualquer mapeamento que você desejar.

Além disso, o comando para retornar a expressão para o mapeamento a avaliar adiciona um \<esc>caractere ao final, para que deixemos o modo de inserção automaticamente após cada inserção e um 0cwna frente para entrar no modo de inserção para começar e certifique-se de substituir a palavra inteira corretamente. Dependendo do comportamento exato que você deseja (se suas palavras não estiverem bem na frente de cada linha), você poderá usar bcwpara encontrar o início real da palavra. No entanto, você verá algumas esquisitices ao voltar às palavras que começam a linha. Provavelmente existe um comando mais avançado para ignorar o final da linha e fazer as duas coisas ao mesmo tempo, mas não consegui encontrar um.

map <expr> <C-k> CompleteDictionary()
fun! CompleteDictionary()
    let cword = expand(“<cword>”)
    let res = []
    for m in readfile(&dictionary)
        if m =~ '^' . cword
            call add(res, m)
        endif
    endfor
    if &completeopt =~ 'longest'
        let max = 0
        let maxindex = 0
        let index = 0
        for item in res
            if strlen(item) > max
                let max = strlen(item)
                let maxindex = index
            endif
            let index = index + 1
        endfor
        return "0cw" . res[maxindex] . "\<esc>"
    else
        return "0cw" . res[system('@echo %RANDOM%') % len(res)] . "\<esc>"
    endif
endfun

Além disso, não seria difícil estender a lógica aqui para criar mapeamentos alternativos (usando, por exemplo, parâmetros de função) que executam qualquer função fornecida pelo modo de inserção. Ficarei feliz em ajudar com esses requisitos e atualizar esse script, pois tenho tempo.

Tim
fonte
Parece uma explicação plausível para o problema, mas tentei as duas soluções sugeridas e nenhuma parecia ajudar.
Rich
Você tentou o sleepcomando também?
Tim
Sim, embora apenas com o valor sugerido de 5 segundos. Você conseguiu que qualquer solução funcione? Você poderia postar uma lista completa de etapas?
Rich
Eu não sou a pessoa que escreveu a pergunta. No entanto, posso reproduzir o problema: você deve adicionar mais tempo ao completeoptdescrito nos comentários (novamente, não por mim). edit : Ops, 'longest'é necessário para a ctrl-petapa: não ctrl-y. Ainda assim, as etapas descritas pelo questionador funcionam para mim vim -Nu NONEcom as completeoptedições editadas.
Rich
Acho que encontrei uma solução, aguarde alguns minutos para atualizar minha resposta.
Tim