it-swarm.com.de

Füge automatisch eine passende Klammer in Vim ein

Ich verbringe Art und Weise zu viel Zeit damit, herumzuspielen, weil Vim nicht mit schließenden Klammern umgeht, wie es die meisten IDEs tun. Folgendes möchte ich tun:

Geben Sie dies ein:

if( whatever )
{ <CR>

und hol dir das:

if( whatever )
{
  |  
}

wo <CR> meine traf die ENTER key und | ist die Position des Cursors. Dies ist, was Eclipse tut. Das macht Visual Studio. Und genau das möchte ich, dass Vim es tut.

Ich habe ein paar Plugins gesehen, ein paar ausprobiert und keiner von ihnen scheint mir dieses Verhalten zu geben. Ich kann doch nicht der erste Programmierer sein, der das will.

62
Bob

In VimL können Sie den { zuordnen, um genau das zu tun, was Sie möchten:

inoremap { {<CR>}<Esc>ko

abhängig von Ihrer automatischen Einrichtung können Sie nach <BS> einen <CR> hinzufügen.

Für eine umfassendere Lösung würde ich vorschlagen, dass Sie einen Blick auf Luc Hermittes vim plugins werfen. Sie haben mich bisher noch nie im Stich gelassen.

30

Um die schließenden Klammern in einer neuen Zeile und den Cursor in der Zeile zwischen den beiden Klammern zu erhalten, folgen Sie dem Vorschlag des ersten Kommentars im Artikel mit dem Titel Klammern und Klammern einfacher handhaben.

16
Derek Mahar

Die Verwendung von AutoClose mit den folgenden Funktionen funktioniert ordnungsgemäß.

inoremap {<CR> {<CR>}<C-o>O

Dies gilt zumindest für mein System (Unix-Terminal unter Mac OS X).

9
dmonopoly

Folgendes habe ich in meiner Vimrc:

let s:pairs={
            \'<': '>',
            \'{': '}',
            \'[': ']',
            \'(': ')',
            \'«': '»',
            \'„': '“',
            \'“': '”',
            \'‘': '’',
        \}
call map(copy(s:pairs), 'extend(s:pairs, {v:val : v:key}, "keep")')
function! InsertPair(left, ...)
    let rlist=reverse(map(split(a:left, '\zs'), 'get(s:pairs, v:val, v:val)'))
    let opts=get(a:000, 0, {})
    let start   = get(opts, 'start',   '')
    let lmiddle = get(opts, 'lmiddle', '')
    let rmiddle = get(opts, 'rmiddle', '')
    let end     = get(opts, 'end',     '')
    let prefix  = get(opts, 'prefix',  '')
    let start.=prefix
    let rmiddle.=prefix
    let left=start.a:left.lmiddle
    let right=rmiddle.join(rlist, '').end
    let moves=repeat("\<Left>", len(split(right, '\zs')))
    return left.right.moves
endfunction
 noremap! <expr> ,f   InsertPair('{')
 noremap! <expr> ,h   InsertPair('[')
 noremap! <expr> ,s   InsertPair('(')
 noremap! <expr> ,u   InsertPair('<')

Und für einige Dateitypen:

inoremap {<CR> {<C-o>o}<C-o>O

// Ich weiß, dass die InsertPair-Funktion trivial ist, aber sie spart Zeit, da ich damit sowohl Befehls- als auch Normalmoduszuordnungen mit einem Befehl definieren kann, ohne viele <Left>s schreiben zu müssen.

4
ZyX

Für jeden, der darüber stößt wie ich und nach etwas jüngerer Aktualisierung als AutoClose suchte: delimitMate Ich habe festgestellt, dass dies nicht nur eine bevorzugte Lösung für AutoClose ist, sondern auch in Bezug auf die aktive Entwicklung. Laut vim.org wurde AutoClose seit 2009 nicht aktualisiert.

3
Eric H

Fügen Sie Folgendes in Ihre .vimrc-Datei ein:

inoremap { {}<ESC>ha

Wenn Sie im Einfügemodus auf { drücken, wird {} generiert und setzt den Cursor auf die rechte Klammer, sodass Sie sofort mit dem Tippen beginnen können. Indem Sie die geschweiften Klammern nacheinander statt in andere Zeilen setzen, können Sie die Registerkarten manuell vor } setzen. Auf diese Weise haben Sie nie die falsche Anzahl von Registern vor sich.

Vielleicht kann jemand herausfinden, wie die Anzahl der Registerkarten gezählt wird, auf denen sich der Cursor befindet, und dann eine gleiche Anzahl von Registerkarten vor dem } in einer neuen Zeile generiert.

2
user1534664

delimitMate hat dafür eine Einstellung.

2
Henrik N

Wie Sie im wikia Tipp sehen werden, gibt es viele Lösungen für diese wiederkehrende Frage (ich habe sogar meine ). 

Das ist, wenn Sie sich auf Klammerpaare beschränken. Hier befinden Sie sich im Kontext einer Kontrollanweisung. Sie finden daher mit größerer Wahrscheinlichkeit Snippet-Systeme, die nicht erwarten, dass Sie das ") {" eingeben, wenn Sie eine if-Anweisung eingeben. Vim Shortcut ist in der Regel kürzer als ich in Ihrer Frage gelesen habe. Auch hier gibt es eine Vielzahl von Optionen, die Sie höchstwahrscheinlich als Snipmate finden und möglicherweise meine C & C++ - Suite .

2
Luc Hermitte

Ich habe verschiedene Plugins ausprobiert, fand aber die genauesten und am einfachsten zu verwendenden Auto-Paare . Es ist wirklich intuitiv und wenn Sie es installieren, bekommen Sie das, was Sie erwartet haben.

2
egelev

Ich habe schon immer etwas vorgezogen, was sublimer Text an der schließenden geschweiften Klammer als nächstes Zeichen anhängt, und fügte meiner .vimrc folgendes hinzu:

inoremap (  ()<ESC>hli

dadurch wird der Cursor zwischen den beiden Klammern verschoben.

1
Aneesh Durg

Nur eine Anmerkung an @Bob.

Karl Guertins AutoClose hat eine Funktion namens `` double brace '', das heißt, Sie können die geschweifte Klammer zweimal wie unten eingeben.

int func_name(void) {{ ==> Type `{' twice here.

würde ergeben:

int func_name(void) {
| ==> Cursor here.
}

Dann können Sie ein single-Tab eingeben, um entsprechend Ihrer Einstellung von "shiftwidth" eingerückt zu werden, und geben Sie dann ein.

1
jtuki

Installieren und verwenden Sie das Vim-Skript AutoClose , wie in dem Artikel mit dem Titel empfohlen. Abschließende Zeichen automatisch anhängen .

1
Derek Mahar

Eine Lösung für Zahnspangen, Klammern und Klammern mit Tabulator dazwischen.

" Automatically closing braces
inoremap {<CR> {<CR>}<Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>

Ergebnis:

function() {
  |
}
1
Rodrigo Pedroso

Vim Patch 7.4.849 fügte eine Bindung hinzu, um Cursorbewegungen zu ermöglichen, ohne die Undo-Sequenz erneut zu starten. Einmal auf> = 7.4.849 aktualisiert, funktioniert so etwas gut.

inoremap ( ()<C-G>U<Left>

Beachten Sie, dass ich das direkt aus der im Patch enthaltenen Dokumentation herausgeholt habe. Beste einfache Lösung für diese Funktion bisher.

1
John Eikenberry

Meine Lösung:

inoremap <expr> <CR> InsertMapForEnter()
function! InsertMapForEnter()
    if pumvisible()
        return "\<C-y>"
    elseif strcharpart(getline('.'),getpos('.')[2]-1,1) == '}'
        return "\<CR>\<Esc>O"
    elseif strcharpart(getline('.'),getpos('.')[2]-1,2) == '</'
        return "\<CR>\<Esc>O"
    else
        return "\<CR>"
    endif
endfunction

Erklärung:

Der obige Code überprüft zuerst, ob Sie Enter verwenden, um die Vervollständigung des Codes zu bestätigen. Andernfalls wird der {|} eingerückt, wenn Sie Enter eingeben. Außerdem werden HTML-Tags mit automatischem Einzug bereitgestellt.

Beispiele:

if( whatever ){|}

drücke Enter und du wirst bekommen

if( whatever )
{
  |  
}

Dies funktioniert auch für HTML-Dateien. Siehe folgendes Beispiel

<html>|<html>

drücke Enter und du wirst bekommen

<html>
    |
</html>
0
Yun Zhi
inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O
0
alvy

Sie benötigen dazu kein spezielles Plugin - es ist jedoch ein zweistufiger Prozess. 

Fügen Sie Ihrem .vimrc zunächst Folgendes hinzu, um das auslösende Zeichen zu essen:

" eat characters after abbreviation
function! Eatchar(pat)
    let c = nr2char(getchar(0))
    return (c =~ a:pat) ? '' : c
endfunction

und fügen Sie diese Abkürzung dann zu Ihrem .vimrc hinzu: 

inoreabbr <silent> { {
      \<cr><space><space>
      \<cr><esc>0i}<esc>k$i<c-r>=Eatchar('\m\s\<bar>\r')<cr>

Der \ am Anfang der Zeilen zwei und drei ist nur ein Zeilenfortsetzungszeichen. Sie hätten das alles in einer Zeile machen können, und ich habe es hinzugefügt, damit ich die Abkürzung auf eine Art und Weise verbreiten könnte, die die Ausgabe widerspiegelt, nach der Sie suchen - nur damit die Dinge intuitiver sind. 

0
ricardo