Como passo para o último caractere de uma frase?

9

No modo normal (e )vá para o primeiro caractere anterior ou o próximo na frase, respectivamente. Como passo para o último caractere.

Se todas as minhas frases terminarem com um período que eu possa usar )T.(primeiro caractere da próxima frase e depois no primeiro período), mas quero uma solução mais robusta para usar em uma macro.

Eu sei sobre ase isenquanto estou no modo visual, então vis<ESC>funciona (modo visual, selecione dentro da frase e saia do modo visual), mas isso me parece bastante feio e não posso usá-lo como movimento com outros comandos.

Estou perdida. Socorro!

bsmith89
fonte
Por que dois <esc>s? Você só precisa de um.
Maçaneta
Opa, eu estava apenas me confundindo por causa do atraso no vim para responder. Eu vou editar a pergunta.
bsmith89
11
Eu só posso sugerir )gE. Eu sei que você disse que sempre termina as frases com um ponto final, mas é melhor nem precisar assumir isso.
superjer
Observe também que ase isnão funcionam apenas no modo visual. Você pode fazer dasno modo normal para excluir uma frase.
Super

Respostas:

10

Da minha pesquisa sobre isso, você precisa definir pelo menos dois movimentos personalizados. O primeiro será apenas para mover o cursor e o segundo será para uso em operadores. Para uma configuração de funcionamento completo, é muito mais complicado, e eu recomendaria olhar o código no CamelCaseMotion de Ingo Karkat, que mostra muito mais ideias sobre como fazer isso corretamente do que eu abaixo. A maior parte da minha resposta é baseada em informações rápidas encontradas na ajuda e experimentação do Vim.

Nos exemplos a seguir, vou remapear os movimentos )e (para fazer cada extremidade de uma frase. Você pode usar outros caracteres como desejar, modificando o exemplo. Também vou dar o seu exemplo de vis<ESC>como a opção mais robusta (em comparação com )T.). Ao fazer isso, se você está no final de uma frase, acaba ficando no final, em vez de passar para o final depois dessa, por causa da maneira como isfunciona. Você pode tentar substituí-lo aspor resultados diferentes. Isso realmente deve funcionar para transformar os dois lados de um objeto de texto em movimento.

Primeiro, o movimento no modo normal

Nota Isso não funciona no modo visual ou no modo pendente do operador

function! MoveToEnd(type, ...)
    exe "normal `]"
endfunction
map <silent> \) :set opfunc=MoveToEnd<CR>g@
nmap ) \)is

Primeiro, definimos uma nova função chamada MoveToEndcuja única tarefa é colocar o cursor no "último caractere do texto alterado ou arrancado anteriormente", que é a ]marca (consulte :help ']).

Em seguida, criamos um operador personalizado \)que chama nossa MoveToEndfunção em qualquer movimento que lhe seja dado. Dessa forma, a ]marca se torna o fim da seleção dada ao nosso novo operador. (ver :help map-operator)

Por fim, mapeamos )para chamar nosso operador personalizado com o ismostion, dando efetivamente o equivalente a vis<ESC>sem alterar a última seleção visual e sem alterar os modos.

O inverso é semelhante, apenas usando as outras direções:

function! MoveToBeginning(type, ...)
    exe "normal `["
endfunction
map <silent> \( :set opfunc=MoveToBeginning<CR>g@
:nmap ( \(is

Segundo, o movimento do operador

Este é mais complicado. Nosso movimento acima destrói a posição inicial, de modo que operadores como 'd' acabam trabalhando contra nada. O que precisamos é ser capaz de salvar nossa posição inicial e adicionar a posição final. :help omap-info(mapeamento pendente do operador) fornece uma dica para fazer isso, que é realmente usar o modo visual.

O que faremos então é salvar nossa posição em uma extremidade do registro de seleção visual, usar nosso movimento no modo normal de cima, definir o outro registro de seleção visual e ativar o modo visual:

function! SelectToEnd()
    normal m<  "Set start point of visual selection
    normal )   "Move to end of sentance (relies on mapping from earlier)
    normal m>  "Set end point of visual selection
    normal gv  " 'Go Visual' activate visual mode using selection marks
endfunction
omap ) :call SelectToEnd()<CR>

E para o nosso movimento de costas:

function! SelectToBeginning()
    normal m>  "Set end point to current position (since we are moving backwards)
    normal (   "Move to beginning of sentence (relies on mapping from earlier)
    normal m<  "Set start point
    normal gv  "Activate visual mode based on our new marks
endfunction
omap ( :call SelectToBeginning()

Com isso, você pode d)excluir para o final da frase (em vez de excluir o original para o início da próxima). Todos os outros operadores devem funcionar também.

John O'M.
fonte
4

Pés Ninja

Eu escrevi um plugin chamado ninja-feet.vim que visa ajudar com esse problema.

Operadores com movimento

Ele define alguns operadores dinâmicos 1 que permitem operar o texto do cursor até a extremidade de um objeto de texto. O uso [ou ]entre o operador e o objeto de texto faz com que o operador opere no texto do cursor para o limite esquerdo ou direito (respectivamente) do objeto de texto.

Também existem operadores no modo Normal para iniciar o modo Inserir no início ou no final de um objeto de texto: z[e z], respectivamente.

Exemplo 1: mude daqui para o final da string

Neste exemplo, vamos |indicar a posição do cursor.

foo("This is a string| with superfluous text at the end", bar);

A digitação d]i"mudará isso para:

foo("This is a string", bar);
  1. d: use o operador de exclusão
  2. ]: até o final do seguinte objeto de texto
  3. i": objeto de texto de cadeia entre aspas

Exemplo 2: Comece a inserir após a frase atual

Mais uma vez, vamos |denotar a posição do cursor.

Here is |some sentence. And here is another.

A digitação z]isiniciará o modo Inserir no final da primeira frase.

  1. z]: inicie o modo Inserir após o seguinte objeto de texto
  2. is: objeto de texto da frase

Ressalvas

  • Esses mapeamentos não podem ser repetidos com .. É bem complicado e estou tentando acertar.
  • Os operadores [e ](usados ​​entre o operador e o objeto de texto) funcionam apenas para objetos de texto que começam com iou a. Tecnicamente, isso é porque eles são mapas realmente para [i, ]i, [ae ]a. Eu adoraria melhorar isso, mas também é muito complicado.
  • Não há movimentos no modo Normal para simplesmente mover o cursor para o final de um objeto de texto. Eu consegui fazê-lo funcionar, mas pelo preço do movimento, na verdade, sou um operador (o significado .repetirá o movimento). Não acho esse comportamento aceitável.

1 Eu os chamo de operadores com movimento porque são operadores mapeados no modo Operador pendente, que é o modo em que você está digitando um operador e um movimento (por exemplo, entre o de o win dw).

tommcdo
fonte