VIM rückgängig machen: Warum springt der Cursor beim Rückgängigmachen von "Rückgängigmachen" an die falsche Position?

9

BEARBEITUNGEN:

  • Ich habe die Funktion vereinfacht und die Frage geklärt.
    Die ursprüngliche Frage steht weiter unten auf der Seite zur Verfügung.

  • In die Mailingliste vim_dev eingefügt: Ссылка

  • Als Fehler bei Neovim gemeldet:
    Ссылка

Warum ist der Cursor in den folgenden zwei Beispielen anders positioniert?

  1. [KORREKTE CURSORPOSITION] Der folgende Test bewirkt, dass die erwartete Ergebnisaustauschänderung mit der vorherigen Änderung im Puffer verknüpft wird (Hinzufügen von Zeile 3), die Cursorposition wird in der zweiten Zeile korrekt wiederhergestellt im Puffer.

    %Vor%
  2. [FALSCHE CURSORPOSITION] Der folgende Test führt zu einem unerwarteten Ergebnis: Substitutionsänderung wird mit der vorherigen Änderung im Puffer verknüpft (Addition von Zeile 4), die Cursorposition wird falsch auf die erste zurückgesetzt Zeile im Puffer (sollte Zeile 3 sein).

    %Vor%

Ursprüngliche Frage

Wie bei der Einrichtung meines VIM wird beim Speichern eines Puffers in einer Datei eine benutzerdefinierte Funktion StripTrailingSpaces () (am Ende der Frage angefügt) ausgelöst:

%Vor%

Nachdem Sie die Cursorposition nach dem Rückgängigmachen der Textänderung durch ein Skript wiederhergestellt haben , habe ich eine Idee, die Änderungen auszuschließen Diese Funktion wird von meiner StripTrailingSpaces () - Funktion aus der Rückgängig-Historie ausgeführt, indem der von der Funktion erstellte Undo-Datensatz mit dem Ende der vorherigen Änderung im Puffer zusammengeführt wird.

Auf diese Weise scheint es beim Rückgängigmachen von Änderungen so zu sein, dass die Funktion keinen eigenen Undo-Datensatz erstellt hat.

Um meine Idee zu validieren, habe ich einen einfachen Testfall benutzt: Erstelle einen sauberen Puffer und gebe die folgenden Befehle manuell ein, oder speichere den folgenden Block als Datei und gib ihn über:

vim +"source <saved-filename-here>"

%Vor%

Wie Sie sehen können, wird nach dem Rückgängigmachen der letzten Änderung des Puffers, der die dritte Zeile erstellt, der Cursor korrekt in die zweite Zeile der Datei zurückgeführt.

Da mein Test funktioniert hat, habe ich ein fast identisches undojoin in meinem StripTrailingSpaces () implementiert. Wenn ich jedoch die letzte Änderung rückgängig mache, nachdem die Funktion ausgeführt wurde, wird der Cursor an die oberste Änderung in der Datei zurückgegeben. Dies ist oft ein leerer Bereich und ist nicht die Position der Änderung, für die ich undojoin -ed bin.

Kann jemand daran denken, warum das wäre? Besser noch, kann jemand eine Lösung vorschlagen?

%Vor%     
UmkaDK 21.07.2015, 19:32
quelle

1 Antwort

3

Das sieht definitiv nach einem Fehler mit dem Ersatzbefehl für mich aus. Von dem, was ich sagen kann, wird der Ersatzbefehl sporadisch den Änderungsort übernehmen, zu dem der Rückgängig-Block springen soll, wenn er eingefügt wird. Ich kann das Muster nicht isolieren - manchmal wird es das tun, wenn die Substitution passiert & gt; einige Male. Zu anderen Zeiten scheint der Ort der Substitution zu beeinflussen, wenn dies geschieht. Es scheint sehr unzuverlässig zu sein. Ich glaube nicht, dass es tatsächlich etwas mit dem Rückgängigmachen-Befehl zu tun hat, da ich diesen Effekt für andere Funktionen reproduzieren konnte, die das nicht nutzen. Wenn Sie interessiert sind, versuchen Sie Folgendes:

%Vor%

Probieren Sie es auf verschiedenen Texten aus, die unterschiedliche Nummern von "Einsen" enthalten und an verschiedenen Orten platziert sind. Sie werden bemerken, dass danach manchmal das Rückgängigmachen zu der Zeile springt, in der die erste Ersetzung stattfand, und andere Male, dass es zu der Stelle springt, an der der erste normale Befehl seine Änderung vornimmt.

Ich denke, die Lösung hier für dich wird sein, so etwas zu tun:

%Vor%

an der Spitze Ihrer Funktion und dann binden Sie sich an etwas wie u'a in Ihrer Funktion, so dass nach dem rückgängig machen wird es zurück zu dem Ort springen, wo die tatsächliche erste Änderung aufgetreten ist im Gegensatz zu was auch immer Zufälligkeit: s Kräfte auf Sie . Natürlich kann es nicht ganz so einfach sein, weil du dich entmapseln musst, nachdem du deinen Sprung gemacht hast, etc., aber dieses Muster sollte dir im Allgemeinen helfen, den richtigen Ort zu speichern und dann zurückzuspringen zu ihm. Natürlich wirst du das alles mit einer globalen Variable machen wollen, statt mit Hijacking-Marken, aber du hast die Idee.

BEARBEITEN : Nachdem Sie einige Zeit damit verbracht haben, den Quellcode zu durchsuchen, sieht es tatsächlich so aus, als wäre das Verhalten, nach dem Sie suchen, der Fehler. Dies ist der Codeabschnitt, der bestimmt, wo der Cursor nach einem Rückgängigmachen platziert werden soll:

%Vor%

Es ist ziemlich involviert, aber im Grunde prüft das, wo sich der Cursor befand, als die Änderung gemacht wurde, und dann, wenn es sich innerhalb des Änderungsblocks für das Rückgängigmachen befindet, setzte den Cursor auf diese Position für den Befehl gw zurück. Andernfalls springt es zur obersten geänderten Zeile und bringt Sie dorthin. Was mit substitute passiert, ist, dass es diese Logik für jede Zeile aktiviert, die ersetzt wird. Wenn also eine dieser Substitutionen im Rückgängig-Block ist, springt sie an die Position des Cursors vor dem Rückgängigmachen (Ihr gewünschtes Verhalten). Zu anderen Zeiten wird keine der Änderungen in diesem Block sein, so dass es zur obersten geänderten Zeile springt (wahrscheinlich, was es tun sollte). Daher denke ich, die Antwort auf Ihre Frage ist, dass Ihr gewünschtes Verhalten (eine Änderung vornehmen, aber mit der vorherigen Änderung zusammenführen, außer dass Sie bestimmen, wo der Cursor platziert werden soll, wenn die Änderung rückgängig gemacht wird) nicht von vim unterstützt wird.

BEARBEITEN: Dieser bestimmte Codeabschnitt befindet sich in Zeile 2711 innerhalb der Undo-Funktion in undo.c. Innerhalb von u_savecommon wird das Ganze eingerichtet, bevor das Rückgängigmachen tatsächlich aufgerufen wird und dort wird die Cursorposition, die für die gw-Befehlsausnahme verwendet wird, gespeichert (Zeile 385 rückgängig machen und in Zeile 548 gespeichert, wenn sie in einem synchronisierten Puffer aufgerufen wird) ). Die Logik für den Ersetzungsbefehl befindet sich in ex_cmds.c in Zeile 4268, die u_savecommon indirekt in Zeile 5208 aufruft (Aufrufe von u_savesub, die u_savecommon aufrufen).

    
doliver 29.07.2015, 22:15
quelle

Tags und Links