É possível fazer com que uma tecla de atalho com prefixo numérico execute uma função tantas vezes?

7

Acho que, se você digitar um prefixo numérico antes de executar um comando ex, a convenção que se aplica é configurar o comando para preparar uma operação em um intervalo de linhas. É explicado na documentação,

UM NÚMERO DE LINHAS

Quando você souber quantas linhas deseja alterar, digite o número e depois ":". Por exemplo, quando você digita "5:", você obtém:

    :.,.+4

Agora você pode digitar o comando que deseja usar. Ele usará o intervalo "." (linha atual) até ". + 4" (quatro linhas abaixo). Assim, abrange cinco linhas.

Agora, o que eu estou lidando é uma função personalizada minha, esta:

function! MyAmazingEnhancedDot()
    if v:hlsearch == 1
        :normal! .n
    else
        :normal! .j
    endif
endfun

Essa é apenas uma maneira de otimizar tarefas repetitivas que incluem a repetição de uma operação em um intervalo de linhas ou em uma série de correspondências de pesquisa.

Esta função está vinculada a uma tecla de atalho. Como Alt+ .ou o que for.

Meu objetivo é ser capaz de fazer algo muito poderoso: eu deveria ser capaz de digitar /varName<CR>ciwnew-var<ESC>n9<Alt+.>para conseguir renomear 10 instâncias de varNamepara new-var.

O que realmente acontece se eu fizer isso é que ele não executa a renomeação e as 9 linhas são manipuladas com a .operação de edição salva pela minha coluna 0.

Só posso supor que Vim está interpretando minhas teclas digitadas assim: :.,.+8 normal! .n.

No lado meio cheio de vidro, o :normal! .jcaso da ligação realmente funciona, porque o jmovimento que não tem efeito não tem conseqüências nessa situação. (Eu ainda preciso jfazê-lo funcionar em um caso de uso interativo com prefixo não numérico).

Portanto, minha pergunta é como posso substituir o comportamento de expansão de linha que o Vim aplica ao meu vínculo? O que seria fantástico é se eu puder ler o prefixo numérico como argumento ou algo assim.

Steven Lu
fonte

Respostas:

6

Por padrão, o vim trata todas as funções como se fossem comandos ex padrão, ou seja, qualquer número prefixado é usado como {range}. Para mudar isso, você precisa modificar sua função e seu mapa para usar uma contagem.

Mapa com contagem

Os mapas podem contar e são disponibilizados via v:counte v:count1. O primeiro contém 0 se nenhuma contagem é fornecida e o posterior contém 1 como padrão. Você pode criar um mapa para sua função:

nnoremap <M-.> :<C-u>call MyAmazingEnhancedDot(v:count1)<cr>

Para mais informações :h v:count

Comandos com contagem

Os comandos podem ter a opção de a {range}ou a countcomo prefixo. Ao criar o comando, o sinalizador -countdesativa a opção range e padroniza a <count>variável para 0. Opcionalmente, um valor padrão pode ser fornecido -count=N. O valor do prefixo está disponível através da variável countem sua função.

Um comando usando count ficaria assim:

:command -count=1 EDot call MyAmazingEnhancedDot(<count>)

Agora, quando você chama, 9EDotsua função é chamada com a contagem de em 9vez de um intervalo.

Para mais informações, consulte :h command-count

Ambos os exemplos

Aqui está o seu código:

function MyAmazingEnhancedDot(count)
  let c = a:count
  while c > 0
    if v:hlsearch == 1
      :normal! .n
    else
      :normal! .j
    endif
    let c -= 1
  endwhile
endfunction

command -count=1 EDot call MyAmazingEnhancedDot(<count>)

nnoremap <M-.> :<C-u>exe v:count1 . "EDot"<CR>

Agora você pode fazer o seu exemplo

/varName<CR>ciwvar-name<esc>n9<M-.>
jecxjo
fonte
1
Legal. Agora parece haver muitas maneiras de resolver meu problema! Entendo que você combinou os dois mecanismos no exemplo que você deu para ilustrar como usá-los. Mas eu me pergunto se não é suficiente apenas usar nnoremap <M-.> :<C-u>call MyAmazingEnhancedDot(v:count1)<cr>e pular o command -count=1 EDot call MyAmazingEnhancedDot(<count>)?
Steven Lu
Ignorar a opção de comando está correto. O único benefício que você obtém da opção de comando é poder chamá-lo de comandos ex, como :9EDot. Se você não usa muito os comandos ex, pule-o.
Jecxjo # 7/15
Impressionante. Agora sua resposta perfeita está completa!
Steven Lu