Mapeando com movimento

12

Estou tentando entender como posso usar o operador com o movimento subsequente dentro de um mapeamento. Por exemplo:

nmap /c c{here we pending for a motion}/<C-r>"<CR>

O mapa deve fazer o seguinte:

  1. Ative o coperador e ouça o próximo movimento;
  2. Por exemplo, eu posso digitar aqui t,para alterar tudo antes da próxima vírgula;
  3. Vá para o modo de inserção excluindo tudo entre o cursor e a vírgula;
  4. O texto excluído é pesquisado automaticamente como padrão

Então, para simplificar, depois que o texto em movimento é removido, eu saio no modo de inserção com ocorrências realçadas do texto excluído. Ficaria muito grato se alguém me ajudasse a resolver esse caso.

ATUALIZAR

As respostas são quase o que eu quero. Mas! Quando pressiono /cw, digite algo em vez da palavra e pressione <Esc>. Depois, espero fazer o mesmo com as próximas ocorrências. Mas, depois de pressionar n(ir para a próxima ocorrência) e .(repetir o último comando), ele apenas precede o último texto digitado em vez de substituí-lo. O objetivo principal do mapeamento é usá-lo com n/Ne .para repetir. Perdi alguma coisa?

Timur Fayzrakhmanov
fonte

Respostas:

9

O vim suporta o mapeamento de operadores :h map-operator.

O que você precisa é um operatorfunce um mapeamento. para suas necessidades, os códigos a seguir funcionam. Bem, é apenas um exemplo, você refina ainda mais.

nmap  <silent> /c :set opfunc=SpecialChange<CR>g@
function! SpecialChange(type)
    silent exec 'normal! `[v`]d'    
    silent exec 'let @/=@"' 
    startinsert
endfunction

Observe que exec 'let @/=@"'apenas para destacar os códigos no buffer. Se você não quiser ver o destaque imediatamente, bastalet @/=@"

Kent
fonte
Atualizei minha pergunta. Parece que a sua resposta é a mais próxima das minhas necessidades, mas não faz o mesmo com a próxima ocorrência, por isso expliquei esse momento na pergunta.
Timur Fayzrakhmanov
Você tem dois operadores (the /ce i) vim .apenas repete o último. Se você deseja estendê-lo, verifique o repeatplugin. @TimurFayzrakhmanov também existem :ge :scomandos, podem ajudá-lo também.
Kent
Existe algum "código estranho no seu código 'let @/=@""'? Eu pensei que era possível, por exemplo silent exec 'normal! [v ]c', porque o coperador faz o que eu espero, exceto que não adiciona o texto alterado ao padrão de pesquisa.
Timur Fayzrakhmanov
1
@TimurFayzrakhmanov, "" foi um erro de digitação .. corri .. Eu ctambém inventei , mas acrescentou um espaço, porque há mudança de modo, n-i-n-ieu acho ... faça algum teste que você verá.
Kent
@TimurFayzrakhmanov você pode fazer isso repetível sem qualquer plugin mudando dpara ye startinsertpara call feedkeys("cgn", 'n')(ver minha resposta abaixo)
Jerome Dalbert
4

É mais fácil implementar (e documentar) mapeamentos complexos usando funções:

function! DoMagic()
   execute "normal! d".input("enter motion: ")
   let @/=@"
   startinsert
endfunction

Em seguida, faça seu mapeamento chamar essa função:

nmap /c :call DoMagic()<CR>

Editar:

Se sua intenção é realizar pesquisa e substituir em um grande número de lugares que você deve tentar o comando de substituição: :s. Você pode alterar seu mapeamento para copiar a seleção visual para o padrão de pesquisa:

function! DoMagic2()
   normal! gv"ay
   return @a
endfunction

vmap /c :<c-w>%s/<C-r>=DoMagic2()<CR>//gc<left><left><left>
mMontu
fonte
1
isso ocorre mesmo com uma interface do usuário "legal", funciona para a necessidade do OP e pode ser "mais" do que o esperado, depende do que você insere. Por exemplo, quando alguém vê enter motion:, ele deu: t,ggVGJZZ ^ _ ^ É um problema comum para concatenação de comandos
Kent
Isso é quase o que eu quero. Por exemplo: eu pressiono /cwe digito algo em vez da palavra e, em seguida, pressione <Esc>. Depois eu quero fazer o mesmo com as próximas ocorrências. Mas, depois de pressionar n(ir para a próxima ocorrência) e .(repetir o último comando), ele apenas precede o último texto digitado em vez de substituí-lo. O objetivo principal do mapeamento é usá-lo com n/Ne .para repetir. Perdi alguma coisa?
Timur Fayzrakhmanov
1
Esta função é para esclarecer a idéia de usar funções quando você tiver problemas com mapeamentos complexos. Você deve alterá-lo para atender às suas necessidades; tente seguir o conselho de Kent para .repetir seu comando.
MMontu
Obrigado pela resposta. Também é útil, mas aceito o do @Kent, porque ele é acionado imediatamente depois que eu os digito (sem pendência <CR>de input()).
Timur Fayzrakhmanov
1
@TimurFayzrakhmanov, você também pode tentar o substituto, conforme explicado na atualização.
MMontu
1

Esta solução funciona com "repita o último comando" (aka .):

nmap <silent> /c :set opfunc=ChangeOccurence<CR>g@

function! ChangeOccurence(type)
  exec 'normal! `[v`]y'
  let @/ = @"
  call feedkeys('cgn', 'n')
endfunction

Ao repetir, você nem precisa usar n, basta usar .para buscar e substituir diretamente a próxima ocorrência, se quiser ir mais rápido.

Opcionalmente, se você gosta de destacar as palavras correspondentes, pode substituir 'cgn'por 'n``cgn'.

Jerome Dalbert
fonte