Excluir automaticamente o par de fechamento sem causar pares desequilibrados

8

Estou escrevendo uma função VimL que, no modo de inserção, permite que uma <BS>parte da abertura de um par ( [, {etc.) exclua a parte de fechamento do par se for o próximo caractere após o cursor (como pares automáticos e vim-autoclose ). Esta função será diferente porque a parte de fechamento do par não será excluída se houver pares desequilibrados.

Exemplos:

O formato é <initial> => <result-after-backspace>onde meu cursor está na frente do |.

((|)    =>   (|)

((|))   =>   (|)

(|)     =>   |

(defn   =>   (defn
  (|)          |)

Como posso determinar se os pares estão desequilibrados antes de prosseguir e excluir o par final?

Eu testei os pares automáticos e o vim-autoclose . Nos dois plugins, a parte de fechamento do par é sempre excluída.

200_success
fonte
Você poderia esclarecer seu prefácio? Deseja evitar todos os plugins, ou apenas similares aos dois mencionados? Se este último, o que você acha desses dois?
Tom
Eu não quero usar nenhum plug-in para isso. Eu atualizei o prefácio.
1
Votei para encerrar esta pergunta. Eu acho que o tópico básico é bom, mas suas restrições o tornam uma pergunta "por favor, escreva algum código para mim plz kthxbye" agora. Eu não acho que nós queremos permitir este tipo de perguntas aqui ...
Martin Tournoij
1
@Carpetsmoker Além da redação desta pergunta, existe um problema que ainda não foi resolvido em qualquer plug-in que eu já tenha visto. Parece-me claro que, uma vez que essa pergunta seja respondida com êxito, todos os plug-ins de fechamento automático ou tipo de par automático poderão se beneficiar de sua solução. Como você sugere que eu mude o texto para torná-lo aceitável?
2
@merb, o plugin paredit faz exatamente o que você deseja. Se você deseja essa funcionalidade sem usar o plug-in, sugiro que você examine a fonte no github. Eu acho que seria mais instrutivo do que eu tentar reproduzir uma versão dela aqui. github.com/kovisoft/paredit
Quincy Bowers

Respostas:

1

Se entendi sua pergunta corretamente, a chave é determinar se o caractere no cursor é um delimitador correspondente.

Considere os comandos do modo normal v%"zye v%%"zy.

  • Se o cursor estiver em um delimitador correspondente, o primeiro comando puxará uma sequência de comprimento de pelo menos 2 - o delimitador, seu par e qualquer texto no meio - para @z. O segundo puxará uma sequência de comprimento exatamente 1 - novamente, o próprio delimitador - para dentro @z.
  • Se o cursor estiver em um delimitador sem correspondência, o primeiro comando puxará uma sequência de comprimento 1 - o próprio delimitador - para @z. Abortar.
  • Se o cursor não estiver em um delimitador e houver um delimitador na linha, o segundo comando puxará uma sequência de comprimento maior que 1 @z. Abortar.
  • Se o cursor não estiver em um delimitador e não houver outro delimitador na linha, o primeiro comando puxará uma sequência de comprimento exatamente 1 - o próprio caractere - para @z. Abortar.

Assim, temos o seguinte resultado:

O cursor está em um delimitador correspondente se e somente se o comando do modo normal v%"zypuxar uma sequência de comprimento de pelo menos 2 @ze o comando do modo normal v%%"zypuxar uma sequência de comprimento de exatamente 1 @z.

Dicas para o VimL: :norm ...e strlen(@z)ajudará aqui.

wchargin
fonte
Isso responde à sua pergunta ou estou faltando alguma coisa?
wchargin
Determinar se o caractere no cursor é correspondido ou não não é exatamente a chave. A chave é determinar se um determinado formulário está ou não equilibrado. Se o formulário estiver equilibrado e nos encontrarmos nesta posição (|):, pressionar <BS>deve excluir os dois. No entanto, se o formulário de nível superior estiver desequilibrado, desta forma:, (defn (|)pressionar <BS>deve excluir apenas o que normalmente seria excluído - nesse caso, deixando-nos com (defn |).
1

Ok, então acabei passando pelo paredit.vim e retirando algumas funções para criar isso: vim-pear . Ele insere e exclui delimitadores em pares, mantendo um estado equilibrado.


fonte
Legal :-) Como eu o uso? Posso apenas instalá-lo e ele será ativado por padrão? Também é possível ativar / desativar isso apenas para tipos de arquivos específicos?
Martin Tournoij 23/02
Ativado para tudo por padrão. Envie um PR, se quiser algo assim. Eu posso fazer isso sozinho em algum momento.
O link está (atualmente) quebrado.
Rich