Wie füge ich das Ergebnis eines Befehls in vim in den Text ein?

42

Zeigt zum Beispiel :echo strftime(%c)die aktuelle Uhrzeit unten an, aber wie fügt man diese Zeitzeichenfolge in den Text ein (direkt nach dem Cursor)?

xzhu
quelle
1
Ich glaube, das OP bedeutet "Wie füge ich das Ergebnis eines Vim-Ausdrucks in den Text ein?"
Alastair Irvine
Erwähnenswert ist auch, dass dies nicht die gleiche Frage ist wie das Schreiben einer VIM-Funktion zum Einfügen eines statischen Textblocks. Einige der Antworten gelten jedoch weiterhin.
Alastair Irvine
Ihr Beispiel ist buchstäblich mein Anwendungsfall und ich begrüße Sie dafür.
Joe
Siehe auch Umleiten in ein Register: stackoverflow.com/questions/2573021/…
NeilG

Antworten:

49

Sie können die Verwendung Ausdrucksregister, "=, mit p(oder P) im Normalmodus oder <C-R>im Einfügemodus:

Im normalen Modus:
( <C-M>hier bedeutet Control+ Moder einfach Enter/ drücken Return)

"=strftime('%c')<C-M>p

Im Einfügemodus:
( <C-M>hat die gleiche Bedeutung wie oben, <C-R>bedeutet Control+ R)

<C-R>=strftime('%c')<C-M>

Wenn Sie das Ergebnis desselben Ausdrucks mehrmals einfügen möchten, möchten Sie sie möglicherweise den folgenden Schlüsseln zuordnen .vimrc:
(hier sollte das <C-M>und <C-R>wörtlich geschrieben werden (eine Folge von fünf druckbaren Zeichen - Vim übersetzt sie intern))

:nmap <F2> "=strftime('%c')<C-M>p
:imap <F2> <C-R>=strftime('%c')<C-M>
Chris Johnsen
quelle
2
+1 Aus dem Kurs! Das "=Register. : - /
Eelvex
2
um den Wert einer vim-Variablen zu erhalten (zum Beispiel sessionoptions): <C-R>=&sessionoptions- Es wird sogar die Wildmode-Tab-Vervollständigung ausgeführt!
Justin M. Keyes
2
: put = strftime ('% c') <CM>
brunch875
Im Einfügemodus ist die Verwendung von <c-r>=langsam für Befehle, die möglicherweise sehr viele Ausgaben enthalten und den Einzug unterbrechen, sodass der Ausgabetext nicht lesbar ist. Beispielsweise wird <c-r>=execute('nmap')die Ausgabe zeilenweise geschrieben, was sehr langsam ist.
JDHAO
22

:r!date +\%c

sehen :help :r!

Glenn Jackman
quelle
1
dateist ein externer Befehl und !ruft externe Befehle auf, während OP nach vim-Befehlen fragt.
Eelvex
@eelvex nein hat er nicht. und das ! ist ein vim und vi Befehl. Dies ist die kanonische Methode. Funktioniert auch für viele andere Dinge.
Keith
5
@ Keith: yes !ist ein vi (m) -Befehl, der externe Befehle aufruft . Möglicherweise haben Sie Recht, dass OP nicht nur vim-Befehle ausgeben möchte, aber wenn er dies tut, tut er dies !nicht.
Eelvex
11

Diese Befehle fügen die Ausgabe von strftime("%c")rechts dort ein, wo sich Ihr Cursor befindet:

:exe ":normal i" . strftime("%c")

und

:call feedkeys("i". strftime("%c"))

Es gibt andere Möglichkeiten, um das zu tun, was Sie wollen (wie zum Beispiel die auf Mikels Antwort ).

Bearbeiten : Noch besser, für In-Place-Insert verwenden Sie das =Register, wie Chris Johnsen beschreibt

Eelvex
quelle
10

Wenn Sie die Ausgabe eines vim- Befehls einfügen möchten (im Gegensatz zum Rückgabewert eines Funktionsaufrufs ), müssen Sie ihn erfassen. Dies erfolgt über den :redirBefehl, mit dem Sie das Äquivalent der Standardausgabe von vim in eine Variable, eine Datei, ein Register oder ein anderes Ziel umleiten können.

:redirist irgendwie schmerzlich unbequem zu bedienen; Ich würde eine Funktion schreiben, um ihre Funktionalität auf eine bequemere Art und Weise zu kapseln, so etwas wie

funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    return output
endfunct!

Sobald Sie eine solche Funktion deklariert haben, können Sie das Ausdrucksregister (wie von Chris Johnsen erklärt) verwenden, um die Ausgabe eines Befehls an der Cursorposition einzufügen. Drücken Sie im normalen Modus, i^R=Exec('ls')um die Liste der aktuellen Puffer von vim einzufügen.

Beachten Sie, dass der Befehl im Funktionsnamensraum ausgeführt wird. Wenn Sie also eine globale Variable verwenden, müssen Sie diesem explizit einen Namensraum voranstellen g:. Beachten Sie auch, dass Exec(), wie oben beschrieben, eine abschließende neue Zeile an eine Ausgabe mit nur einer Zeile angehängt wird. Möglicherweise möchten Sie substitute()der Funktion einen Aufruf hinzufügen , um dies zu vermeiden.

Unter https://stackoverflow.com/questions/2573021/vim-how-to-redirect-ex-command-output-into-current-buffer-or-file/2573054#2573054 finden Sie weitere Informationen zu redirund einen Link zu ein verwandter Befehl.

intuitiert
quelle
2
Das funktioniert super. Ich habe einen set pasteBefehl hinzugefügt, bevor die Ausgabe zurückgegeben wurde, und einen Befehl set nopaste, um den Treppeneinzug zu vermeiden, wenn die Zeilen mit Leerzeichen beginnen. Eigentlich wollte ich den Wert der aktuellen Einfügeoption speichern und zurückgeben, konnte es aber nicht.
Juan Lanus
1
@ JuanLanus Das set nopastesollte danach nicht funktionieren return output, da die return-Anweisung ein Exit-Point aus der Funktion ist. Ich habe meine Lösung für dieses Problem als separate Antwort auf dieser Seite angegeben.
Evgeni Sergeev
4
:call append(line('.'), strftime("%c"))

Wird es in die nächste Zeile gestellt, können Sie J( Shift+ J) drücken , um es an die aktuelle Position zu setzen.

Oder wenn Sie alles in einem Befehl benötigen, können Sie dies tun

:call setline(line('.'), getline(line('.')) . strftime("%c"))

oder

:call setline(line('.'), getline(line('.')) . " " . strftime("%c"))

abhängig davon, ob Sie ein Leerzeichen vor dem Datum einfügen möchten oder nicht.

Mikel
quelle
4

@Intuited answer verbessern, um das Problem mit führenden Leerzeichen und wachsendem Einzug zu vermeiden:

"Examples:
":call Exec('buffers')
"This will include the output of :buffers into the current buffer.
"
"Also try:
":call Exec('ls')
":call Exec('autocmd')
"
funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    let @o = output
    execute "put o"
    return ''
endfunct!

Dies wird einfach an der aktuellen Position in der Datei eingefügt, wenn Sie :call Exec('command')aus dem normalen Modus. Wie im Kommentar erwähnt , kann der ursprüngliche (Einfügemodus) Strg + R- =Exec('command')Ansatz mit der Exec(..)Rückgabe eines Strings teilweise mithilfe von korrigiert werden, set pastebietet jedoch keine Möglichkeit, das set nopasteNirgendwo unterzubringen.

Die let @o = outputSyntax setzt das Register oauf den Inhalt der Variablen output, wie hier erläutert: https://stackoverflow.com/a/22738310/1143274

Die return ''Zeile ist so, dass der Standardrückgabewert von 0nicht in den Puffer eingefügt wird.

Evgeni Sergeev
quelle
2

So mache ich es. Es setzt es direkt nach dem Cursor, weil es verwendet p.

" save previous yank
let reg_save = @@

" save your text to the '@' register
let @@ = strftime('%c')
" paste it after the cursor
exec "normal! p"

" restore previous yank
let @@ = reg_save
Juan Ibiapina
quelle