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 NONE
und 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{p
funktionieren 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>x
umgebende 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 x
dem 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]}x
oder [{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 v
nicht 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{p
oderyi{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
- 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
- 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>x
Dies 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 |
+----+------------------------+----------------------------+------------+
return -1;
kommt. Können Sie auch genau angeben, wo Sie den Cursor platzieren, bevor Sie die einzelnen Tastenfolgen ausführen?