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ê já está no final de uma frase, acaba ficando no final, em vez de passar para o final depois dessa, por causa da maneira como is
funciona. Você pode tentar substituí-lo as
por 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 MoveToEnd
cuja ú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 MoveToEnd
funçã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 is
mostion, 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.
<esc>
s? Você só precisa de um.