Mehrere Cursor an gewünschter Stelle

13

Ich verwende das Plugin vim-multiple-cursors .

Ich möchte Cursor genau dort platzieren, wo ich will. Zum Beispiel ( [x]sind die Cursorpositionen):

Lorem ipsum dolor sit amet[1], consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna[2]
aliqua.

In Sublime Text setze ich normalerweise den ersten Cursor, gehe dann mit den Pfeiltasten zur nächsten Position und setze den zweiten.

Gibt es etwas Ähnliches in VIM? Mit diesem oder einem anderen Plugin.

BEARBEITEN

Nach einem Kommentar zeigte sich mein Interesse daran, als ich versuchte,
\section[My first section in this book]{My first section in this book}
in eine .texDatei zu schreiben . Meine erste Reaktion war zu schreiben \section[]{}und dann zwei Cursor zu setzen, um dasselbe in das []und zu schreiben {}.

Ein anderes Beispiel wäre, _someStuffnach mehreren verschiedenen Variablen Namen hinzuzufügen . Beispiel:

variable1 = 2
my_variable2 = 12
var3 = 14

das mögen:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

Bei mehreren Cursorn kann ich einen Spaltencursor auswählen und dann zum Ende des Wortes gehen, dann einfügen usw. Aber ich denke, es wäre einfach, genau zu wählen, wo ich die Cursor haben möchte.

tomasyany
quelle
1
Ich denke, dass eine wichtige Frage ist, warum Sie das tun wollen? Was versuchst du zu machen? Die Verwendung mehrerer Cursor ist nicht wirklich "nach dem Vorbild von Vim", es gibt wahrscheinlich eine andere Möglichkeit, mit den integrierten Funktionen das zu tun, was Sie wollen, zumindest so effizient.
statox
@statox. Siehe Bearbeiten. Ich gab zwei Beispiele, die mir in den Sinn kamen. Das zweite kann ich mit dem Plugin vim-multiple-cursors machen, das erste kann ich nicht, zumindest auf einfache Weise.
Tomasyany
@ Nobe4. Danke, das zweite Skript hat es geschafft.
Tomasyany

Antworten:

29

Die Verwendung mehrerer Cursor ist keine Sache von Vimmer

Wie ich in den Kommentaren bereits sagte, ist die Verwendung von Multi-Cursorn (auch mit einem Plugin) nicht wirklich "nach dem Vim-Prinzip". Ich verstehe vollkommen, dass es für jemanden attraktiv ist, der aus Sublime-Text stammt, aber es gibt oft Alternativen, bei denen es sich zumindest um Alternativen handelt So effizient wie die in Vim integrierten Funktionen.

Natürlich ist es nicht immer einfach, diese alternativen Lösungen zu finden, und manchmal dauert es eine Weile, aber es wird mit Ihrem Vim-Erlebnis einfacher, und Sie werden feststellen, dass Ihnen mehrere Cursor mit der Zeit völlig nutzlos erscheinen.

Das ist cool, aber wie finde ich einen alternativen Weg?

Es gibt keine allgemeingültige Antwort, da dies stark davon abhängt, was Sie tun möchten. Ich werde nur versuchen, einige Tipps für die ersten Dinge zu geben, die Sie versuchen sollten:


Der Punktbefehl .

Der Punktbefehl ist wahrscheinlich eines der leistungsstärksten Werkzeuge in Vim. Er ermöglicht es uns lediglich, die letzte Änderung zu wiederholen. Ich könnte es nicht besser erklären als Drew Neil in seinem Practical Vim . Ich denke, dass jeder Vimmer darüber nachdenken sollte, dieses Buch zu lesen.

Die Stärke dieses Befehls besteht darin, dass die letzte Änderung eine Aktion sein kann, die an einem Zeichen, einer Zeile oder einer ganzen Datei ausgeführt wird. Beispielsweise kann eine Änderung durch den Moment begrenzt werden, in dem Sie in den Einfügemodus wechseln und in den normalen Modus zurückkehren.

In diesem Sinne ist es einfach, mit Multicursor das zu tun, was Sie wollten:

  • Zuerst richten wir unsere Umgebung ein: Schreiben wir, wie Sie es vorgeschlagen haben

    \section[]{}

  • Nehmen Sie dann eine wiederholbare Änderung vor. Der Cursor ist jetzt eingeschaltet }. Drücken Sie F[, um zum [Charakter zurückzukehren. Dann wechseln Sie mit in den Einfügemodus iund tippen My first section in this bookund kehren mit in den normalen Modus zurück ESC:

    \section[My first section in this book]{}

  • Und hier kommt der magische Teil: Geben Sie ein f{, um den Cursor auf das {Zeichen zu setzen, und drücken Sie ., um die letzte Änderung zu wiederholen:

    \section[My first section in this book]{My first section in this book}

Die Herausforderung des Punktbefehls besteht darin, zu lernen, wie man wiederholbare Änderungen vornimmt: Es wird mit grokking Vim kommen, aber das Grundlegende ist, zu verstehen, wie man Änderungen auf wiederholbare Weise vornimmt.

Wenn Sie beispielsweise ein Semikolon am Ende einer Zeile einfügen möchten, verwenden Sie A;statt $a;. Warum?

Da A;eine atomare Aktion erstellt wird, wird bei Verwendung .in einer anderen Zeile, unabhängig davon, wo Sie sich in der Zeile befinden, das Semikolon am Ende eingefügt. Während $a;Sie Ihre Änderung bei der Verwendung in zwei Teile teilen $aund das Einfügen von ;so, wenn Sie es verwenden ., wird das Semikolon an der aktuellen Position des Cursors eingefügt.

HINWEIS Die Zauberformel in Vim lautet n.. Ein wirklich cooler Workflow ist:

  • Suchen Sie nach dem Ort, an dem Sie eine Bearbeitung vornehmen möchten /pattern
  • Machen Sie Ihre wiederholbare Bearbeitung
  • Mit nzum nächsten zu bearbeitenden Ort wechseln
  • Verwenden Sie ., um die Bearbeitung zu wiederholen
  • Wiederholen Sie die letzten beiden Schritte: Sie sind der König der Welt (oder zumindest der Bearbeitungen)

Makros

Makros sind ein weiteres äußerst wichtiges Werkzeug in Vim, da Sie eine Folge von Tastenanschlägen aufzeichnen und wiederholen können, als ob Sie sie erneut eingeben würden.

Ich werde als Beispiel Ihren zweiten Anwendungsfall verwenden:

variable1 = 2
my_variable2 = 12
var3 = 14

Wieder einmal ist es wichtig zu lernen, wie man seine Makros effizienter macht (ich werde gleich ein Gegenbeispiel geben):

  • Stellen Sie den Cursor auf das Wort variable1und beginnen Sie mit der Aufzeichnung Ihres Makros qq. Dies bedeutet "Aufzeichnung aller meiner zukünftigen Tastenanschläge in dem genannten Register starten q".

  • Beginnen Sie mit der Bearbeitung:

    • 0 am Anfang der Zeile gehen
    • e am Ende des ersten Wortes gehen
    • a Nach dem Cursor anhängen
    • .someStuff den gewünschten Text anhängen
    • <Esc> um das Einfügen zu stoppen
    • j in die nächste Zeile gehen
    • q um die Aufzeichnung des Makros zu beenden
  • Du wirst kriegen:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Jetzt können Sie das Makro verwenden, um die Bearbeitung zu wiederholen. Da Sie sich in der richtigen Zeile zum Bearbeiten befinden, können Sie das Makro einfach mit ausführen @q. Da wir es zweimal ausführen möchten, können Sie es verwenden 2@qund erhalten das folgende Ergebnis:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

HINWEIS 1 Wie Sie vielleicht bemerkt haben, war die Verwendung 0eaam Anfang des Makros sehr wichtig. Wenn Sie den Cursor an das Ende des ersten Wortes gesetzt hätten, bevor Sie das Makro aufgenommen und erneut ausgeführt haben, wäre das Ergebnis in der Tat:

variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff

Als Cursor wäre der Text nach dem Zeilenwechsel (in diesem Fall das Zeilenende) an der Position des Cursors eingefügt worden

HINWEIS 2 Makros sind äußerst leistungsstark und Sie können sogar rekursive Makros erstellen, wenn Sie mit ihnen vertraut sind. Hier könnte Ihr Makro gewesen sein:

`0ea.someStuff<Esc>j@q`

Das Finale @qhätte das Makro selbst aufgerufen, anstatt es zu verwenden 2@q. du hättest es nur benutzt @qund die ganze Arbeit wäre erledigt.


Sichtblock

Hier kommt ein weiterer Trick, der nicht direkt auf Ihren Anwendungsfall zutrifft, aber sehr nützlich sein kann, um eine große Anzahl von Zeilen gleichzeitig zu bearbeiten. Holen wir uns diesen Auszug aus dem CSS-Code:

li.one   a{ background-image: url('/images/sprite.png'); }
li.two   a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }

Was ist, wenn Sie die Sprites von imagesnach verschoben haben components?

Nun können Sie Ihren Cursor auf das ivon setzen imagesund drücken <C-v>. Dadurch wird der visuelle Blockmodus gestartet, in dem Blöcke ausgewählt werden können. Jetzt können Sie eingeben t/ , um das Wort auszuwählen, das Sie ändern möchten, und 2jum alle Vorkommen des Wortes auszuwählen.

Danach müssen Sie nur noch tippen c, um das Wort zu ändern und dann components. Wenn Sie den Einfügemodus verlassen, sehen Sie:

li.one   a{ background-image: url('/components/sprite.png'); }
li.two   a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }

Der globale Befehl

Der globale Befehl ist ein Tool, mit dem Sie einen ex-Modus-Befehl auf Zeilen anwenden können, die mit einem Muster übereinstimmen. Wiederum ist dies eine gute Möglichkeit, dieselbe Änderung an einer anderen Stelle anzuwenden, ohne mehrere Cursor zu benötigen.

Die Syntax lautet wie folgt:

:[range] g / pattern / command

Weitere Details zum [range]Parameter finden Sie unter :h :range. Ich werde hier nicht näher darauf eingehen, sondern nur daran erinnern, dass dies %die gesamte Datei darstellt, '<,'> die letzte Auswahl darstellt und 1,5die Zeilen 1 bis 5 der Datei darstellt.

Dieser Parameter definiert die Zeilen, die vom globalen Befehl behandelt werden. Wenn kein Bereich angegeben ist, wird %standardmäßig der globale Befehl verwendet .

Das Argument [Muster] ist ein Suchmuster, wie Sie es für die Suchmaschine verwenden. Da das Suchprotokoll integriert ist, können Sie dieses Feld leer lassen. Der globale Befehl verwendet dann das letzte Suchmuster im Suchprotokoll.

Schließlich ist der Parameter [command] ein ex-Befehl, wie Sie es wahrscheinlich gewohnt sind.

Nun ist das Verhalten des globalen Befehls ziemlich einfach:

  • Durchlaufen Sie alle im Parameter [range] definierten Zeilen
  • Wenn die aktuelle Zeile dem definierten Muster entspricht, wenden Sie den Befehl an

Da der Parameter [command] ein ex-Befehl ist, können Sie viele Dinge tun. Nehmen wir den folgenden Pseudocode, der nicht sehr interessant ist und viele Debugging-Meldungen enthält:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"

echo "end of for loop"

Angenommen, Sie sind sicher, dass dieser Code funktioniert und Sie diese nutzlosen echoAnweisungen löschen möchten :

  • Sie können Ihren globalen Befehl auf die gesamte Datei anwenden, sodass Sie dem Befehl voranstellen müssen %(oder nichts, da dies %der Standardbereich ist).

  • Sie wissen, dass die zu löschenden Zeilen alle mit dem Muster übereinstimmen echo

  • Wenn Sie diese Zeilen löschen möchten, müssen Sie den Befehl verwenden, :delete der auch als abgekürzt werden kannd

Sie müssen also einfach die folgende Funktion verwenden:

:%global/echo/delete

Was auch als abgekürzt werden kann

:g/echo/d

Beachten Sie, dass %verschwunden globalist, als gund deleteals abgekürzt d. Wie Sie sich vorstellen können, ist das Ergebnis:

var myList  = null
var i       = 0

myList = new List()

for (i=0; i<10; i++)
    myList.Add(i)

ANMERKUNG 1 Es hat einige Zeit gedauert , bis mir klar wurde, dass der normalBefehl ein ex-Befehl ist. Das bedeutet, dass Sie ihn mit dem globalen Befehl verwenden können. Das kann sehr mächtig sein: Nehmen wir an, ich möchte alle Zeilen duplizieren, die Echo enthalten, ich brauche weder ein Makro noch die Zauberformel n.. Ich kann es einfach benutzen

:g/echo/normal YP

Und voila:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"
    echo i . " added to the list"

echo "end of for loop"
echo "end of for loop"

ANMERKUNG 2 "Hey, was ist, wenn ich meinen Befehl für Zeilen verwenden möchte, die keinem bestimmten Muster entsprechen?"

globalhat einen umgekehrten Befehl vglobalabgekürztv der genau so funktioniert, globalaußer dass der Befehl auf Zeilen angewendet wird, die nicht mit dem Parameter [pattern] übereinstimmen. Auf diese Weise, wenn wir uns bewerben

:v/echo/d

Auf unserem vorherigen Beispiel erhalten wir:

echo "List instantiated"
    echo i . " added to the list"
echo "end of for loop"

Das delete Befehl wurde auf Zeilen angewendet, die nichts enthielten echo.


Hier hoffe ich, dass diese paar Hinweise Ihnen Anregungen geben, wie Sie Ihr Multi-Cursor-Plugin entfernen und Vim auf die Vim-Art und Weise verwenden können ;-)

Wie Sie sich vorstellen können, sind diese Beispiele ziemlich einfach und sollen nur zeigen, dass Sie, wenn Sie der Vim-Methode folgen, wirklich selten mehrere Cursor benötigen. Mein Rat wäre, wenn Sie in eine Situation geraten, in der Sie es für nützlich halten, schreiben Sie es auf und nehmen Sie sich später etwas Zeit, um eine bessere Lösung zu finden. In 99% der Fälle werden Sie schließlich einen schnelleren / effizienteren Weg finden, dies zu tun.

Ich werde mich auch noch einmal wiederholen, aber ich empfehle Ihnen wirklich, Practical Vim von Drew Neil zu lesen, denn in diesem Buch geht es nicht um "Wie man das oder das in Vim macht", sondern um "Wie man lernt, wie man in Vim denkt". Auf diese Weise können Sie Ihre eigenen Lösungen für Ihre zukünftigen Probleme auf gute Weise erstellen.


PS Besonderer Dank geht an @Alex Stragies für seine Bearbeitung und die Korrekturen, die er an diesem langen Beitrag vorgenommen hat.

statox
quelle
Sehr vollständige Antwort. Ich kannte eigentlich alle diese Befehle, habe aber nie daran gedacht, sie so zu verwenden ... Ich glaube, ich brauche mehr Übung. Allerdings muss ich sagen, dass der 'vim-way' manchmal länger dauert als nur die Verwendung eines Plugins (zum Beispiel kann Ihr CSS-Beispiel mit dem Plugin, das ich erwähnt habe, viel schneller ausgeführt werden), und manchmal dauert er viel kürzer (eigentlich das gewaltige) Meistens ist vim schneller als jeder Texteditor (wenn es richtig verwendet wird).
Tomasyany
Übrigens, ich denke deine Antwort ist schon ziemlich vollständig. Ich werde es akzeptieren, aber wenn Sie weitere Details hinzufügen möchten, tun Sie dies bitte und ich werde froh sein, sie zu lesen.
Tomasyany
1
@tomasyany: In der Tat scheint es manchmal länger zu dauern, den "vim way" zu verwenden (ich kann nicht zählen, wie oft ich mehr Zeit für das Erstellen eines funktionierenden Makros aufgewendet habe, als wenn ich die Änderungen manuell vorgenommen hätte), aber mit der Zeit wird es schließlich schneller. Ich benutze Vim erst seit einem Jahr und bin (sehr) weit davon entfernt, ein Experte zu sein, aber ich kann spüren, dass sich mein Schnitt während des Trainings kontinuierlich verbessert.
statox
1
Sollte wahrscheinlich auch das Textobjekt erwähnen gn. Es werden einige Anwendungsfälle mit mehreren Cursorn behandelt. Suchen mit /, dann dgnoder cgn, dann wiederholen mit ..
Justin M. Keyes
@ Justin Ich bin nicht wirklich vertraut mit gnIch werde es versuchen und fügen Sie es nach. Danke für den Kopf hoch!
statox
5

Ihre gegebenen Anwendungsfälle klingen für mich so, als wollten Sie den .Tastaturbefehl kennen (wiederholen Sie den letzten Bearbeitungsbefehl).

  • Gehen Sie zum ersten Ort, drücken Sie i, geben Sie Ihren Text ein,<ESC>
  • bewegen Sie sich zu Position 2 und drücken Sie .(Punkt) ==> Identischer Text wird eingefügt
  • Um hier eine Zeile nach unten zu verschieben und erneut einzufügen (beim Einfügen in aufeinanderfolgende Zeilen), drücken Sie <ALT>-j.

Ihr Textbeispiel für mich wird gelöst durch:

I\section[]{}<ESC>hhiMy first Sec...<ESC>lll.

Alex Stragies
quelle
Es ist eine ziemlich schöne Lösung. Ich kannte den .Schlüsselbefehl perfekt , dachte aber nie daran, ihn so zu verwenden. Ich bin damit einverstanden, dass es ein schöner Weg ist. Aber Ihre Antwort bezieht sich nicht wirklich auf die eigentliche Frage, daher wäre es wohl nicht angebracht, sie anzunehmen.
Tomasyany
1
Nun, Ihre Frage (nachdem Sie die gewünschten Anwendungsfälle hinzugefügt haben) erinnerte mich an "Ich mag meine Schere wirklich und möchte eine Schraube damit anziehen. Sagen Sie mir, wie". Und ich weise Sie auf eine raffinierte Verwendung für einen Schraubenzieher hin;) (Ich fügte als Antwort hinzu, weil ich nicht weiß, wie die Formatierung in Kommentaren zu tun ist)
Alex Stragies
4

Mehr Vim-Wege.

Erste Aufgabe:

\section[foobar baz]{foobar baz}

Arbeitsablauf:

\section[]{}
hh
ifoobar baz<Esc>
$.

Zweite Aufgabe:

variable1 = 2
my_variable2 = 12
var3 = 14

Befehl:

3:norm ea_somestuff

Ergebnis:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
romainl
quelle