Crea automaticamente le parentesi graffe corrispondenti in vim


17

Come faccio a creare automaticamente le parentesi graffe corrispondenti in vim?

Dovrebbe funzionare come segue: se inserisco una parentesi aperta, quella di chiusura dovrebbe apparire automaticamente e il cursore dovrebbe essere posizionato tra. Per saltare fuori dalla coppia di controventi Ctrl-jviene utilizzata la combinazione .

Ci sono molti plugin che forniscono l'inserimento automatico di parentesi graffe. Ma loro

  • utilizzare una combinazione di tasti diversa rispetto Ctrl-ja saltare fuori dalla coppia di controventi oppure
  • interferire con le associazioni dei tasti UltiSnips .

Di seguito funziona come previsto

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

Ma con queste impostazioni gli snippet di UltiSnips non funzionano più. Quindi ho usato UltiSnips per inserire la parentesi graffa di chiusura:

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

Questo funziona quasi. Viene inserito il tutore corrispondente e posso saltare quello di chiusura con Ctrl-j. Questo, tuttavia, funziona solo se c'è uno spazio davanti alla parentesi graffa aperta.

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

Le mie soluzioni richiedono un'associazione di tasti diversa per saltare sopra la parentesi graffa di chiusura o richiedere uno spazio davanti a quello aperto. Come risolvere questo?

Nota: ho usato le parentesi come esempio. Dovrebbe funzionare con parentesi, parentesi graffe, parentesi e segni meno di e non interferire con il plugin UltiSnips.


1
Hai provato la chiusura automatica ? Puoi saltare fuori dalle coppie con ), rimappare c-ja quello potrebbe funzionare.
Kevin,

Risposte:


4

Come faccio a creare automaticamente le parentesi graffe corrispondenti in vim?

Questo problema non è banale, come vedrai. La semplice risposta è: utilizzare un plug-in, come autoclose o smartinput . Rimappando ingenuamente il ([.. i tasti ti presenteranno le edgecase in un paio di righe, ecco perché questi plugin sono fatti e perché di solito sono abbastanza complessi (se sono buoni).

Quindi ho usato UltiSnips per inserire la parentesi graffa di chiusura

Potresti invece provare questo (che è diverso dal mio suggerimento originale):

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

Dove UltiSnips dividerà la linea (anziché includerla mainnella partita. Il problema con l'utilizzo di un plug-in di frammento per questo è che (di solito) non supportano l'annidamento, quindi dimenticheranno qualsiasi posizione di salto quando viene inserito il frammento successivo (nidificato).

Per saltare fuori dalla coppia di controventi Ctrl-jviene utilizzata la combinazione .

Puoi rimappare Ctrl-jUltiSnips o il plugin in conflitto. Se i mapping non sono elencati nella documentazione, è possibile utilizzare :map/imap/nmap <key>per mostrare il mapping. Se vuoi Ctrl-jscegliere e fare il lavoro di entrambi i plugin, stai chiedendo:

  1. qualcosa di molto più avanzato di quanto sospetto si possa pensare
  2. qualcosa che sospetto non voglia davvero

Considera questo loop bash:

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

In questo caso, dovrai premere Ctrl-j5 volte per accedere al corpo del loop. L'uso delle parentesi graffe di chiusura per saltare fuori da una coppia corrispondente ti dà molto più controllo di dove vuoi spostare il cursore. È possibile implementare uno stack per tenere traccia delle coppie inserite e utilizzare Ctrl-jper pop e spostare, ma si verificheranno problemi se si inizia a eliminare manualmente le parentesi graffe senza rimuoverle dallo stack. Quindi inizierai a risolvere i problemi che i plugin di parentesi stanno cercando di risolvere. Questa è una ruota dura da reinventare.

Espandendo su questo, puoi ottenere ciò che inizialmente hai chiesto, usando Ctrl-jper saltare da parentesi graffe e frammenti. Se si utilizza un valore fittizio per rappresentare le posizioni dei frammenti e spingerli sulla pila oltre alle parentesi graffe di chiusura, con rimappatura dinamica di Ctrl-jcorrispondere alla consegna di frammenti o parentesi graffe. Ma poi dovrai implementare alcune euristiche abbastanza avanzate per capire quale magia dovrebbe accadere, dal momento che stai essenzialmente affrontando due problemi contemporaneamente, che è attualmente risolto dai creatori di plug-in di inserimento snippet e di plug-in di abbinamento separati, e risolvere nuovamente questi problemi, in aggiunta alle loro soluzioni, per ottenere praticità e, beh, magia.

Si riduce a controllare vs convenienza. Penso che il controllo ti servirà meglio in questo caso, il che significa che dovresti tenere separati questi problemi e i relativi plugin e keymapping associati. Se vuoi ancora praticità, è fattibile, ma è difficile.


1

Penso che delimitMate faccia quello che ti serve.

Chiude automaticamente parentesi o virgolette e mette il cursore in mezzo. Per saltare da una coppia di parentesi (pur essendo in modalità insert) faresti Ctrl-g+ gma puoi rimappare questo Ctrl-jaggiungendo questo al tuo vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g

È meglio fornire maggiori dettagli qui e utilizzare il collegamento come riferimento per ulteriori letture. In questo modo la tua risposta non perde tutto il suo valore quando il link diventa non valido.
Anthon,

1

Ho scoperto che la chiusura automatica aggiunge un po 'di ritardo e interferisce anche con la mia configurazione (Ultisnips e Supertab), ma mi piace il suo approccio all'emulazione di Eclipse CDT.

Uso delimitMate con le seguenti mappe per aiutare con la navigazione e il rientro, cercando di ottenere gli stessi risultati:

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)

Lo uso in questo modo: inserire apertura { <CR><CR><C-K>e iniziare a scrivere nella riga interna rientrata.


Ho trovato che anche delimitMate aggiungeva un leggero ritardo
icc97,

1

Personalmente utilizzo smartinput per l'inserimento automatico di parentesi e virgolette. Ad esempio, digitare {ovunque produrrà {}con il cursore nel mezzo. Per lasciare il {gruppo parentesi quadre basta digitare }quando accanto a quello inserito }.

Tuttavia, questo supporta il tuo requisito di tabstops e saltare all'esterno della staffa. Inoltre non crea un nuovo tra parentesi, ma ti serve comunque solo una chiave in più per quello - <CR>.

È possibile mappare <C-J>per passare alla riga successiva in basso:

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

o se si desidera passare all'inizio della riga successiva:

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

0

Qualcosa del genere potrebbe funzionare per te.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}

Quello che suggerisci è una semplice mappatura che non consente di saltare il tutore di chiusura.
Marco,

0

In realtà, Ultisnips può farlo quasi alla perfezione (potrebbe essere nuovo). Risposte leggermente modificanti date sopra, ho un buon successo con

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

Bisogna digitare ()quali trovano meglio ma che possono anche essere cambiate (. Quindi, gli argomenti opzionali aggiuntivi UltiSnips#Anonsono una descrizione e il modificatore iche consente l'espansione in-word.

Saltare fuori dalle parentesi con le <c-j>opere, nidificate anche all'interno di altri frammenti. Tuttavia, invocare ()parentesi nidificate sembra interrompere questa funzione, il che non è un grosso problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.