Cria automaticamente chaves correspondentes no vim

16

Como faço para criar automaticamente chaves correspondentes no vim?

Deve funcionar da seguinte forma: Se eu introduzir uma chave de abertura, a de fechamento deve aparecem automaticamente e o cursor deve ser colocado entre elas. Para saltar do par de chaves é usada a combinação Ctrl-j .

Existem muitos plugins que fornecem inserção automática de chaves. Mas eles

  • use uma combinação de teclas diferente de Ctrl-j para saltar do par de chaves ou
  • interfira na chave UltiSnips ligações.

Os seguintes trabalhos funcionam como esperado

:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a

Mas com essas configurações, os trechos do UltiSnips não funcionam mais. Então eu usei UltiSnips para inserir a chave de fechamento:

inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>

Isso quase funciona. A chave correspondente é inserida e eu posso pular o fechamento um com Ctrl-j . Isso, no entanto, só funciona se houver um espaço frente da chave aberta.

main () // works, the closing parentheses is added
main(   // fails without a space

Minhas soluções requerem uma ligação de chave diferente para pular o fechamento cinta ou exigir um espaço na frente do aberto. Como consertar isso?

Nota: usei parênteses como exemplo. Deve funcionar com parênteses, chaves, suportes e menos de sinais e não interferir com o UltiSnips plugin.

    
por Marco 06.11.2012 / 15:33

6 respostas

4

How do I automatically create matching braces in vim?

Esse problema não é trivial, como você verá. A resposta simples é: use um plug-in, como autoclose ou smartinput . Apenas ingenuamente remapeando as teclas (.. .. irá apresentá-lo com edgicases em um par de linhas, é por isso que esses plugins são feitos, e porque eles geralmente são bastante complexos (se eles são bons).

So I used UltiSnips to insert the closing brace

Você pode tentar isso (que é diferente da minha sugestão original):

inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>

Onde o UltiSnips dividirá a linha em ( em vez de incluir main na correspondência. O problema com o uso de um plugin de snippet para isso é que eles (geralmente) não suportam aninhamento, então eles irão esquecer qualquer posição de salto quando o próximo snippet (aninhado) for inserido.

To jump out of the brace pair the combination Ctrl-j is used.

Você pode remapear Ctrl-j para o UltiSnips ou o plugin conflitante. Se os mapeamentos não estiverem listados na documentação, você poderá usar :map/imap/nmap <key> para mostrar o mapeamento. Se você quiser Ctrl-j para escolher e fazer o trabalho de ambos os plugins, você está pedindo:

  1. algo muito mais avançado do que suspeito que você possa pensar
  2. algo que eu suspeito que você realmente não quer

Considere este loop do bash:

while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
  [next_snippet_position_marker]
done

Nesse caso, você precisará pressionar Ctrl-j 5 vezes para chegar ao corpo do loop. Usar as chaves de fechamento para saltar de um par correspondente dá a você muito mais controle de onde você quer que o cursor se mova. Você poderia implementar uma pilha para manter o controle dos pares inseridos e usar Ctrl-j para abrir e mover, mas você terá problemas se começar a excluir manualmente as chaves sem removê-las da pilha. Então você vai começar a resolver problemas que os plugins estão tentando resolver. Esta é uma roda dura para reinventar.

Expandindo isso, você pode obter o que inicialmente pediu, usando Ctrl-j para pular fora das chaves e . Se você usar algum valor fictício para representar posições de trechos e empurrá-los para a pilha além das chaves de fechamento, com o remapeamento dinâmico de Ctrl-j para corresponder ao trecho de trechos ou chaves. Mas você precisará implementar algumas heurísticas razoavelmente avançadas para descobrir qual mágica deve acontecer, já que você está essencialmente assumindo dois problemas de uma só vez, o que está sendo resolvido pelos criadores de plugins de inserção de trechos e suporta os plugins correspondentes separadamente. re-resolvendo estes problemas novamente, em cima de suas soluções, para conseguir conveniência e, bem, magia.

Tudo depende do controle versus conveniência. Eu acho que o controle irá atendê-lo melhor neste caso, o que significa que você deve manter esses problemas e seus plugins e mapeamentos associados separados. Se você ainda quer conveniência, é factível, mas é difícil.

    
por 02.01.2013 / 22:45
1

Pessoalmente, uso smartinput para inserção automática de colchetes e citações. Por exemplo, digitar { em qualquer lugar produzirá {} com o cursor no meio. Para deixar o grupo de parênteses { , basta digitar o } quando estiver próximo ao } inserido.

No entanto, isso dá suporte ao seu requisito de tabstops e pula para fora do colchete. Ele também não cria um novo entre seus colchetes, mas você só precisa de uma chave extra para isso - <CR> .

Você pode mapear <C-J> para ir para a próxima linha:

:inoremap <C-J> <C-O>j

ou se você quiser passar para o início da próxima linha:

:inoremap <C-J> <C-O>+

Não há nada de muito novo aqui, no entanto, espero que essas soluções possam ajudar.

    
por 22.11.2012 / 17:33
1

Acho que o delimitMate faz o que você precisa.

Fecha automaticamente os parênteses ou aspas e coloca o cursor no meio. Para saltar de um par de parênteses (estando no modo de inserção) você faria Ctrl-g + g mas você pode remapear isto para ser Ctrl-j adicionando isso ao seu vimrc :

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g
    
por 26.01.2014 / 15:09
1

Eu encontrei o autoclose adicionando um pouco de lag, e também interferindo na minha configuração (Ultisnips e Supertab), mas eu gosto da sua abordagem de emulação do Eclipse CDT.

Eu uso delimitMate com os seguintes mapas para ajudar na navegação e recuo, tentando obter os mesmos resultados:

imap <C-F> <C-G>g           " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)

Eu uso desta forma: insira a abertura { <CR><CR><C-K> e comece a escrever na linha interna recuada.

    
por 30.10.2014 / 11:48
0

Algo parecido com isso pode funcionar para você.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}
    
por 19.11.2012 / 23:23
0

Na verdade, o Ultisnips pode fazer isso quase perfeitamente (isso pode ser novo). Modificando ligeiramente as respostas dadas acima, tenho um bom sucesso com

inoremap () ()<C-R>=UltiSnips#Anon('($1)$0', '()', 'double parentheses', 'i')<CR>

Deve-se digitar () , que é melhor, mas também pode ser alterado para ( . Em seguida, os argumentos adicionais opcionais para UltiSnips#Anon são uma descrição e o modificador i , que permite a expansão na palavra.

Saltar dos parênteses com <c-j> funciona, também aninhado em outros fragmentos. No entanto, chamar parêntesis () aninhados parece interromper esse recurso, o que não é grande coisa.

    
por 05.08.2015 / 15:51

Tags