Wie verwende ich einen externen Befehl in Vim, um ausgewählte Wörter und Zeilen zu ändern?

22

In anderen Editoren hat sich Folgendes als nützlich erwiesen:

  • Nimm den ausgewählten Text
  • Führen Sie einen externen Befehl aus und übergeben Sie die Auswahl an den entsprechenden Befehl stdin
  • Nimm die externen Befehle stdoutund ersetze die aktuelle Auswahl damit.

Auf diese Weise können Sie nützliche Textwerkzeuge schreiben, die die Auswahl in jeder Sprache bearbeiten, die grundlegende Funktionen unterstützt.

Wie geht das mit vim über die Auswahl? ... ein einzelnes Zeichen, Wort, Absatz ... usw.

(Direkt in der Kommandozeile oder über eine Tastaturbindung?)


Hinweis

Befehle wie die !sortArbeit auf Leitungsebene, der Grund, warum ich diese Frage stelle, ist, dass ich die Auswahl bearbeiten möchte. (dh der Text, der entfernt würde, wenn xgedrückt würde).

ideasman42
quelle

Antworten:

17

Ich finde, dass es oft am einfachsten ist, den visuellen Modus mit v(oder mit Großbuchstaben V, um ganze Zeilen auszuwählen) zu verwenden und den Text auszuwählen, den Sie weiterleiten möchten.

Dann tippe:

:!cat

Dies macht als solches nichts Sinnvolles. Ein nützlicher Befehl, den ich oft benutze, ist:

:!python -m json.tool

um JSON zu formatieren.

Sie können auch einfach Folgendes eingeben (ohne visuellen Modus):

:<range>!command

Zum Beispiel für die gesamte Datei:

:%!python -m json.tool

Oder für die aktuelle Zeile:

:.!python -m json.tool
Martin Tournoij
quelle
Ein weiteres sehr nützliches Werkzeug ist der sortBefehl.
Cody Poll
4
@CodyPoll Was ist los mit Vim's :sort?
Martin Tournoij
5
@Carpetsmoker Der externe Sortierbefehl hat viel mehr Optionen und erzeugt (je nach Gebietsschema usw.) eine andere Reihenfolge.
Derobert
1
Dies funktioniert nicht für die Auswahl eines einzelnen Wortes in einer Zeile. (Siehe Frage erwähnt die Auswahl der
Wortebene
@ ideasman42 Richtig ... Ich glaube, ich habe diese Frage ursprünglich als "Zeilen oder Wörter" anstelle von "Zeilen und Wörtern" gelesen ... Auf jeden Fall ist es nicht offensichtlich, dass dies mit Wörtern getan wird. UNIX-Programme arbeiten mit Zeilen und Vim ist keine Ausnahme. Ich habe ein bisschen experimentiert und irgendwie eine Lösung gefunden, aber es funktioniert nicht sehr gut ... Vielleicht ist mein Ansatz falsch, also lasse ich es einfach ein paar Tage und komme später darauf zurück.
Martin Tournoij
7

Ich habe ein Plugin namens express.vim geschrieben , das dabei helfen kann. Das Plugin definiert einen Operator g=, mit dem Sie einen VimScript-Ausdruck über eine Bewegung (oder eine visuelle Auswahl) auswerten können. Sie werden zur Eingabe eines Ausdrucks aufgefordert, in dem Sie v:valden Text, der von der Bewegung (oder auch von der visuellen Auswahl) abgedeckt wird, als Platzhalter verwenden können .

In diesem Fall würde ein nützlicher Ausdruck die system()Funktion verwenden, die einen externen Befehl ausführt.

system('tr a-z A-Z', v:val)

(Hier habe ich trals einfaches Beispiel einen externen Befehl verwendet.)

Die Möglichkeit, express.vim für dieses Problem zu verwenden, besteht darin, den Text im visuellen Modus auszuwählen, ihn g=gefolgt von diesem Ausdruck einzugeben und dann zu drücken Enter:

g=system('tr a-z A-Z', v:val)<CR>

Ich gebe zu, es ist nicht einfach zu bedienen. (Tatsächlich verwende ich dieses Plugin selbst selten!) Ich überlege, eine Verknüpfung zum Aufrufen eines externen Befehls hinzuzufügen, beispielsweise den Ausdruck mit !. Ich werde hier ein Update veröffentlichen, wenn ich das mache.

BEARBEITEN

Ich habe express.vim so geändert, dass Ausdrücke, die mit beginnen, !als externe Befehle behandelt werden. Wenn Sie sich also an das trBeispiel halten, wird das oben Genannte viel einfacher. Geben Sie nach einer visuellen Auswahl Folgendes ein:

g=!tr a-z A-Z<CR>

Erläuterung:

  1. Rufen Sie den Express-Operator mit auf g=
  2. Geben Sie !tr a-z A-Zals Ausdruck ein
  3. Drücken Sie Enter
tommcdo
quelle
4

Sie suchen nach den Filterbefehlen in Vim. Sehen :help filter. Hier ist die relevante Dokumentation:

!{motion}{filter}   Filter {motion} text lines through the external
                    program {filter}.
!!{filter}          Filter [count] lines through the external program
                    {filter}.
{Visual}!{filter}   Filter the highlighted lines through the external
                    program {filter} (for {Visual} see |Visual-mode|).
                    {not in Vi}

:{range}![!]{filter} [!][arg]               *:range!*
                    Filter {range} lines through the external program
                   {filter}.  ...[See documentation for details]

Wenn Sie also tippen, 5!!sortwerden die nächsten 5 Zeilen ab dem Cursor sortiert.

Sameer
quelle
Ist es möglich, ein einzelnes Wort zu filtern? (nicht auf
Zeilenebene
Ja. Die dritte Option (visueller Modus) funktioniert für alle hervorgehobenen Elemente (Wörter, Teilzeilen, Mehrzeilen, Rechteckblöcke usw.).
Sameer
1
Die dritte Option filtert auch ganze Zeilen. Wenn Sie ein einzelnes Wort auswählen und es beispielsweise durch filtern, tr [:lower:] [:upper]wird nicht nur dieses Wort, sondern die gesamte Zeile in Großbuchstaben geschrieben.
Maria s
0

Beachten Sie, dass dies mit Folgendem durchgeführt werden kann:

  1. Wählen Sie visuell aus, was Sie möchten
  2. s^R=system('tr a-z A-Z', @")[:-2]^M( ^Rwobei STRG + R und ^ M EINGABE ist)

Es könnte auch mit allem funktionieren, was Auswahl + Ersetzen mag ci"^R=....

Luc Hermitte
quelle
Beim Ausführen dieser Funktion in einer mehrzeiligen Textauswahl (nach Drücken vund Bewegen des Cursors) erhalte ich den Fehler E16: Invalid range\nE16: Invalid range\nE476: Invalid command(unter Linux gibt es also trund andere grundlegende Befehle).
ideasman42
Haben Sie gedrückt, sdass in den Einfügemodus oder :sden Befehl geht?
Luc Hermitte
Verdächtige nicht, aber auch nicht sicher, wie du meinst, vielleicht könnte das Beispiel zeigen, wie man dies an einen Schlüssel bindet?
ideasman42
Triffst du direkt saus dem visuellen Modus oder triffst du :zuerst? :An der Reihenfolge der Tasten, die ich geschrieben habe, ist nichts beteiligt. Eine Zuordnung wäre: vnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>.
Luc Hermitte