So entfernen Sie einfach Zahnspangen

8

Einer meiner Freunde sagte mir, dass ich mit dem folgenden Trick ein Paar geschweifte Klammern entfernen kann.

Setzen Sie den Cursor in das geschweifte Klammerpaar, das Sie entfernen möchten.

y i {Um den Text in geschweiften Klammern zu ziehen, v a {fügen Sie ihn ein p.

Es funktioniert gut wie:

for(int i = 0; i < s.length(); i++) {
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Nach dem Ausführen des Befehls:

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];

bis ich diese Situation getroffen habe (Der Platz vor der ersten geschweiften Klammer fehlt).

for(int i = 0; i < s.length(); i++){
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Nach dem Ausführen dieser Befehle wird der Textblock

for(int i = 0; i < s.length(); i++
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
)

Der Bereich, den ich im visuellen Modus auswähle, scheint gut zu sein, aber warum werden die Klammern ausgeblendet?

MrDwZ
quelle
Sind Sie sicher, welches Codebeispiel Sie veröffentlicht haben? Ich verstehe nicht, wie das return -1;kommt. Können Sie auch genau angeben, wo Sie den Cursor platzieren, bevor Sie die einzelnen Tastenfolgen ausführen?
Statox
@statox Entschuldigung ... Ich habe den letzten Block korrigiert und eine Beschreibung hinzugefügt, wo ich den Cursor platziert habe. Vielen Dank für Ihre Empfehlung :-)
MrDwZ
Ich kann das nicht replizieren. yi{zieht zwischen den geschweiften Klammern und vapwählt visuell den Absatz (in diesem Fall den gesamten Text) aus, aber ich sehe nicht, wie dies den Text überhaupt ändert. Bist du sicher, dass du nicht yi{+ va{+ machst p?
Jjaderberg
2
Ich habe gerade yi{+ va{+ pan Ihrem Text in einer sauberen Sitzung versucht (kein vimrc -u NONE), und das gibt Ihr Ergebnis wieder. Ich bin mir nicht sicher , warum, zum Beispiel pund Pbeide dieses Ergebnis geben, trotz i{und a{bewegen charakterlich. Es wäre hilfreich, wenn Sie a) einen Beispieltext geben könnten, an dem Ihre Technik funktioniert, und b) bestätigen könnten, wo in Ihrer Technik die „Änderung“ stattfindet. @Ben weist in seiner Antwort auf eine gute Problemumgehung hin (ich verwende dieses Plugin), aber es würde mir nichts ausmachen zu erfahren, warum dies überhaupt passiert.
Jjaderberg
Ich bin genau wie @jjaderberg. Ich kann das von Ihnen beschriebene Verhalten nicht reproduzieren. Es wäre eine wirklich gute Idee, die in seinen Kommentaren angeforderten Details anzugeben.
Statox

Antworten:

6

Installieren Sie das "Surround" -Plugin . Dann kannst du es einfach tun d s B .

Von der Projektseite:

Bei Surround.vim dreht sich alles um "Umgebung": Klammern, Klammern, Anführungszeichen, XML-Tags und mehr. Das Plugin bietet Zuordnungen zum einfachen Löschen, Ändern und Hinzufügen solcher Umgebungen in Paaren.

Der Befehl, dsdem ein Textobjekt folgt ( Bin diesem Fall für "Blockieren" wie im Textobjekt aBoder iB), löscht die umgebenden Zeichen, die das Textobjekt definieren. So erreicht d s B in Ihrem Fall das, was Sie wollten.

Andere Befehle enthalten c s B b, wenn man wollte ändern die Umgebung {...}in (...)oder y s {jede Cursorbewegung oder Textobjekt} B hinzuzufügen Umgebung {...}auf den Text ausgewählt durch den Cursor.

Weitere Informationen finden Sie auf der Plugin-Seite und in der Dokumentation.

Ben
quelle
Dies ist eine gute Problemumgehung. Würden Sie ein oder zwei Sätze hinzufügen, um zu erklären, wie dieses Plugin funktioniert und warum das jeweilige Mapping die Aufgabe erfüllt?
Jjaderberg
Gibt es eine elegante Möglichkeit, diese Klammern ohne Plugin zu entfernen? : (
MrDwZ
Könnte sein. Aber Surround ist wirklich leicht und eines der "wesentlichen" Plugins. So kann es auch installieren ...
Ben
6

Zusammenfassung

Es ist ein Fehler und es gibt einen Patch (743). Der Fehler betrifft beide Beispiele, wird jedoch in einem Fall nicht angezeigt, da das nach unten verschobene Zeichen ein (Leerzeichen) ist. Die Lösung besteht darin, den Patch zu installieren. Es gibt jedoch auch viele Problemumgehungen oder alternative Methoden, die vom Fehler nicht betroffen sind.

NB : {, }und Bbeziehen sich alle auf dem gleichen Textobjekt: Block ( :help aB, :help iB). Wenn diese oder andere Antworten ein anderes Zeichen als das in der Frage verwendete verwenden, kann dies der Grund sein.

Der Käfer

Ich verstehe es nicht ganz, aber hier ist eine Erklärung, wenn jemand interessiert ist.

Das angezeigte Verhalten ist auf einen von Yukihiro Nakadaira auf vim_dev erwähnten Fehler zurückzuführen, und sein Patch wird als 7.4.743 veröffentlicht: "p" im visuellen Modus verursacht einen unerwarteten Zeilensplit .

Der visuelle Modus put ( :help v_p) soll den visuell ausgewählten Text durch Text aus einem Register ersetzen. Der Fehler tritt auf, wenn a) das Register vom zeilenweisen Typ ist ( :help linewise-register), die visuelle Auswahl jedoch vom zeichenweisen Typ ist und b) die visuelle Auswahl in der letzten Spalte einer Zeile endet. Wenn Sie in Ihrem Fall den inneren Block ziehen und dann einen Block visuell auswählen und einfügen, wird das gezogene Register linienweise und die visuelle Auswahl zeichenweise angezeigt. Wir können sowohl den inneren Block als auch einen Block in benannte Register ziehen und untersuchen:

Auf

for(int i = 0; i < s.length(); i++){  
    int index = s[i] - c;  
    if(root->next[index] == NULL)  
        root->next[index] = new TrieNode;  
    root = root->next[index];  
}

wir tun

"ayi{
"bya{
:registers ab

welche Shows

--- Registers ---
"a       int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J
"b   {^J    int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J}

und

:echo getregtype('a') " displays 'V' for linewise
:echo getregtype('b') " displays 'v' for characterwise

Um eine zeichenweise visuelle Auswahl durch ein zeilenweises Register zu ersetzen, müssen die Zeilen, die den Anfang und das Ende der visuellen Auswahl enthalten, in zwei Teile geteilt werden, damit der Text dazwischen eingefügt werden kann. Dies funktioniert normalerweise einwandfrei:

Vim as ausführen vim -u NONE -U NONEund tippen
( a )

iaaa
bbb
ccc
ddd<Esc>ggYjlvp

führt zu

aaa
b
aaa
b
ccc

und ( b )

iaaa
bbb
ccc
ddd<Esc>ggYjvjp

im

aaa

aaa
cc
ddd

Wenn die zeichenweise visuelle Auswahl jedoch in der letzten Spalte einer Zeile endet (und die neue Zeile /n/ nicht enthält ^J), geht etwas schief. Dies hat mit der Cursorposition zu tun, die plötzlich um -1 abweicht und speziell erhöht werden muss, wie es der Patch tut. Vergleichen Sie ( a ) mit dem Befehl <Esc>ggYjllvp, dh demselben Befehl, außer dass Sie eine weitere Spalte nach rechts verschieben, sodass sich der Cursor auf dem letzten "b" in der Zeile befindet. Das Ergebnis ist das gleiche wie zuvor!

Nehmen Sie nun den folgenden Text:

if (TIRED){
    goto bed;
} else {
    goto work;
}

Mit dem Cursor in der zweiten Zeile yi{va{pfunktionieren Sie einwandfrei und geben

if (TIRED)
    goto bed;
 else {
    goto work;
}

Das Ruckregister ist immer noch linienweise und die visuelle Auswahl zeichenweise, aber die visuelle Auswahl endet nicht mehr in der letzten Spalte und alles ist in Ordnung.

Beispieltexte aus der Frage

Bei den beiden Beispieltexten, bei denen der einzige Unterschied ein Leerzeichen zwischen dem Schließen der Klammer und dem Öffnen der geschweiften Klammer in der ersten Zeile ist, scheint sich Ihr Befehl möglicherweise anders zu verhalten, dies ist jedoch nicht der Fall. Im ersten Fall, der erfolgreich aussieht, sollte in der ersten Zeile ein nachfolgendes Leerzeichen stehen, sobald die Klammern entfernt werden. Das nachfolgende Leerzeichen befindet sich stattdessen in der letzten Zeile. Mityi{va{p

for(int i = 0; i < s.length(); i++) {
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

wird

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
␣

so wie

for(int i = 0; i < s.length(); i++){
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

wird

for(int i = 0; i < s.length(); i++
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
)

Lösungen

Die Lösung wäre, den Patch zu installieren, aber es gibt viele andere Möglichkeiten, die umgebenden Klammern zu entfernen, die nicht unter dem Fehler leiden. Die beste Problemumgehung ist die Antwort von @Gilles. Am einfachsten ist es jedoch, sie vor dem Ziehen visuell auszuwählen, um das Register zeichenweise zu halten.

Das Surround- Plugin von Tim Pope ist ausgezeichnet, aber (zumindest für mich) es entfernt mehr als nur die Klammern: Es verbindet die zweite Zeile mit der ersten, entfernt Einrückungen und bewegt den Cursor an den Anfang der ersten Zeile. Dies lässt einige nicht triviale Bereinigungen zu tun. Ingo Karkat und Luc Hermitte haben Plugins, die sich mit Registern und Einfügen befassen (ich bin sicher, es gibt viele andere) und die dies tun sollten. Ich bin mit ihnen nicht sehr vertraut, aber ich glaube, mit lh-Klammern können Sie <M-b>xumgebende Klammern löschen, und für ein leistungsfähigeres Putten (insbesondere im visuellen Modus) können Sie sich ReplaceWithRegister und UnconditionalPaste ansehen .

Der beste Weg ist der in @ Gilles Antwort gegeben , [{x]}x. Es ist schnell, verarbeitet verschachtelte Blöcke gut und verbindet Zeilen nicht unangemessen oder verwirrt mit Einrückungen. Wenn sich vor der öffnenden Klammer ein Leerzeichen befindet, können Sie xdem Befehl zum Entfernen einfach ein Leerzeichen hinzufügen :[{xx]}x

Andere Vanillebefehle

Wiederum ist der am besten geeignete Befehl, den ich mir vorstellen kann, der in der Antwort von @Gilles, [{x]}xoder [{xx]}x, aber hier sind zwei Alternativen speziell im Hinblick auf diesen Fehler.

Charakterweise ziehen

Da der Fehler nur beim visuellen Setzen eines linienweisen Registers über der zeichenweisen Auswahl auftritt und es nur zufällig für Ihren inneren Block-Ruck ist, dass er zeilenweise ist, können Sie ihn stattdessen zeichenweise ziehen. Eine einfache Möglichkeit besteht darin, den inneren Block vor dem Ziehen visuell auszuwählen und sicherzustellen, dass die visuelle Auswahl zeichenweise erfolgt (dh vnicht verwenden V) : vi{yva{p. Dies ist möglicherweise der einfachste Weg, da er dem aktuellen Vorgang sehr ähnlich ist.

Verwenden Sie keinen visuellen Put

Andere Befehle wie Ändern und Löschen sind von diesem Fehler nicht betroffen. Sie können wie zuvor ziehen, aber dann einen Block in das Schwarzlochregister ( :help quote_) löschen und setzen oder einen Block löschen und aus dem 0-Register ( :help quote0) setzen: yi{"_da{poderyi{da{"0p

Allgemeinheit

Schließlich gibt es ähnliche Möglichkeiten wie bei der @ Gilles-Antwort: Zum Anfang eines Blocks verschieben, Zeichen löschen, zum Ende eines Blocks verschieben, Zeichen löschen -, die jedoch allgemeiner sind. Der einzige Grund, diese zu verwenden, wäre, wenn der "Block", den Sie löschen, exzentrisch ist und keine zugehörigen Bewegungen aufweist, die genauso gut [{funktionieren wie für einen Block, der durch geschweifte Klammern begrenzt ist. Es besteht die Möglichkeit, dass das Vim-Surround-Plugin diese exzentrischen Blöcke gut handhaben kann, aber es gibt zwei Vanille-Möglichkeiten

  1. Wählen Sie den Exzenterblock visuell aus und verlassen Sie den visuellen Modus. Der Cursor befindet sich auf dem letzten Zeichen der Auswahl. Löschen Sie es, gehen Sie zum Anfang der letzten Auswahl ( :help `<) und löschen Sie das Zeichen.va{<Esc>x`<x
  2. Suchen Sie rückwärts nach dem Anfang des exzentrischen Blocks und löschen Sie das Zeichen. Suchen Sie dann vorwärts nach dem Ende des exzentrischen Blocks und löschen Sie das Zeichen. ?{<CR>x/}<CR>xDies funktioniert möglicherweise nicht gut mit verschachtelten Blöcken.

Zeichenanzahl

+----+------------------------+----------------------------+------------+
|    | method                 |          command           | characters |
+----+------------------------+----------------------------+------------+
| 1. | vim-surround           | ds{                        |          3 |
| 2. | @Gilles answer         | [{x]}x                     |          6 |
| 3. | Characterwise yank     | vi{yva{p                   |          8 |
| 4. | Delete, not visual put | yi{"_da{p or yi{da{"0p     |          9 |
| 5. | Visual mark            | va{<Esc>x`<x               |          8 |
| 6. | Search                 | ?{<CR>x/}<CR>x             |          8 |
+----+------------------------+----------------------------+------------+
jjaderberg
quelle
5

Da Sie nicht darum bitten, dass der Cursor an seine ursprüngliche Position zurückgesetzt wird, [{x]}xwird der Job ausgeführt. Es ist 6 Zeichen lang mit zwei Drücken, Shiftaber das Prinzip ist unkompliziert, so dass es leicht zu merken ist.

Wenn Sie zur ursprünglichen Position zurückkehren möchten, können Sie verwenden [{x``]}x``

Gilles 'SO - hör auf böse zu sein'
quelle