Eu vou assumir que você usa a matchit
versão mais recente do plugin 1.13.3 que eu encontrei no momento no repositório github do Vim.
[%
na maioria das vezes pula para function!
, ocasionalmente (inconsistentemente dependendo da posição do cursor) pula para if
e ignora totalmente (
s.
Quando você pressiona [%
, a s:MultiMatch()
função é invocada. No final deste último, há um while
loop cujo número de iterações é v:count1
. Esta variável armazena a contagem para o último comando normal. Aqui deve ser 1
, porque você não atingiu nenhum número antes [%
. Mas no meio da função, alguns :normal
comandos são executados para salvar a tela e a posição do cursor. Esses comandos normais alteram o valor de v:count1
.
Você pode verificar isso assim:
nno cd :<c-u>call Func()<cr>
fu! Func()
echom v:count1
endfu
Origem deste código, e pressione cd
, leia suas mensagens ( :messages
): você deve ver 1
, porque você não atingiu nenhum número antes cd
. Agora, forneça este código:
nno cd :<c-u>call Func()<cr>
fu! Func()
norm! 3G
echom v:count1
endfu
E faça o mesmo experimento, pressione cd
um arquivo com mais de 3 linhas. Desta vez, nas mensagens, você deve ver 3
, não 1
.
Por esse motivo, a searchpair()
função dentro do loop é invocada muitas vezes, o que, suspeito, explica o comportamento que você descreveu. Pelo menos, ele faz na minha máquina ( 8.0
patches Linux, Vim 1-134
).
Para corrigir isso, você pode excluir a linha 729 :
let level = v:count1
E mova-o no início da função (antes que outros comandos, incluindo :normal
comandos, tenham a chance de alterar v:count1
):
fun! s:MultiMatch(spflag, mode)
if !exists("b:match_words") || b:match_words == ""
return ""
end
let level = v:count1
Eu apenas tentei o matchit do neovim no vim (surpreendentemente é diferente do do vim) e parece funcionar .. estranho
Provavelmente, é por causa da solicitação de recebimento nº 5124 que o neovim foi mesclado há um ano. De acordo com a mensagem de confirmação, seu objetivo era impedir matchit
a adição de uma entrada indesejada no jumplist. Para resolver isso, a confirmação mudou como as posições da tela e do cursor foram salvas. Ele não usa :normal
mais comandos, mas chama a função winsaveview()
e winrestview()
. Ao se livrar :normal
, para uma finalidade diferente, eles também corrigiram o problema que você descreveu anteriormente, porque v:count1
não é mais modificado. Embora possa ser no futuro se alguns comandos forem adicionados no meio da função.
]%
salta para se )
nada mais.
No final da s:MultiMatch()
função, linha 722 , o padrão que descreve a parte final de um grupo de tokens é definido assim:
let closepat = substitute(closepat, ',', '\\|', 'g')
O objetivo da substituição é substituir cada vírgula, que separa 2 grupos consecutivos de tokens, por uma barra de escape duplo que será interpretada pelo mecanismo de expressão regular do Vim como uma alternância (separação entre 2 ramificações). Penso que a substituição também deve substituir os dois pontos :
que separam os tokens dentro de cada grupo. Então, você pode reescrever a substituição assim:
let closepat = substitute(closepat, '[,:]', '\\|', 'g')
Com essa alteração, ]%
mova o cursor nos vários tokens descritos em b:match_words
e &l:matchpairs
, não apenas )
. Pelo menos, faz na minha máquina.
va%
se comporta de maneira idêntica [%
neste exemplo e não seleciona nada.
Com as alterações anteriores, em particular a 2ª, va%
deve-se selecionar o texto entre os 2 tokens circundantes. Embora, o plug-in pareça tratar a parte do meio de um grupo de tokens (como else
em if|else|endif
) como uma parte final (é passada para searchpair()
o terceiro argumento, não o segundo). Portanto, o que considera serem os tokens circundantes às vezes pode surpreendê-lo.
No entanto, o neovim va%
((( )))
não "expande" após repetido a%
. Não tenho certeza se vim já fez, mas eu deveria. assim como a(
.
Atualmente, o mapeamento visual a%
é definido na linha 71, assim:
vmap a% <Esc>[%v]%
Quando adiciono o
no início do {rhs}
, para mover o cursor para o início da seleção ( :h v_o
), recebo o comportamento que você deseja:
vmap a% o<Esc>[%v]%
Aqui está uma versão do matchit
plugin, com as três pequenas alterações descritas até agora.
E aqui está outro onde eu tentei incluir também o PR # 5124 da Neovim.
Se você deseja testar o código em sua máquina, mas não tem o direito de alterar o matchit
plug-in padrão (ou não deseja), é possível criar o arquivo ~/.vim/plugin/matchit.vim
e escrever matchit
nele o plug-in experimental .
Como no caminho de execução, ~/.vim
vem antes $VIMRUNTIME
, o Vim deve originar sua versão personalizada antes da versão padrão. E desde então, o plugin padrão tem a guarda:
if exists("loaded_matchit") || &cp
finish
endif
let loaded_matchit = 1
... apenas sua versão deve ser totalmente originada.
]%
, quase nada. Vou ter que dar uma olhada no código.