Bagaimana cara memasukkan hasil dari suatu perintah ke dalam teks dalam vim?

42

Misalnya, :echo strftime(%c)akan menampilkan waktu saat ini di bagian bawah, tetapi bagaimana cara memasukkan string waktu ini ke teks (tepat setelah kursor)?

xzhu
sumber
1
Saya percaya OP berarti "Bagaimana cara memasukkan hasil ekspresi Vim ke dalam teks?"
Alastair Irvine
Perlu juga disebutkan bahwa ini bukan pertanyaan yang sama dengan Menulis fungsi vim untuk menyisipkan blok teks statis , namun beberapa jawaban masih berlaku.
Alastair Irvine
Contoh Anda benar-benar kasus penggunaan saya dan saya salut kepada Anda untuk itu.
Joe
Lihat juga mengarahkan ke register: stackoverflow.com/questions/2573021/…
NeilG

Jawaban:

49

Anda dapat menggunakan register ekspresi "=,, dengan p(atau P) dalam mode normal atau <C-R>mode insert:

Dalam mode normal:
(di <C-M>sini berarti Control+ M, atau cukup tekan Enter/ Return)

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

Dalam mode sisipkan:
( <C-M>memiliki arti yang sama seperti di atas, <C-R>berarti Control+ R)

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

Jika Anda ingin menyisipkan hasil dari ekspresi yang sama berkali-kali, maka Anda mungkin ingin memetakannya ke dalam kunci Anda .vimrc:
(di sini <C-M>dan <C-R>harus diketik secara harfiah (urutan lima karakter yang dapat dicetak — Vim akan menerjemahkannya secara internal))

:nmap <F2> "=strftime('%c')<C-M>p
:imap <F2> <C-R>=strftime('%c')<C-M>
Chris Johnsen
sumber
2
+1 Tentu saja! The "=mendaftar. : - /
Eelvex
2
untuk mendapatkan nilai dari variabel vim (misalnya, opsi sesi): <C-R>=&sessionoptions- ia bahkan melakukan wildmode tab-completion!
Justin M. Keyes
2
: put = strftime ('% c') <CM>
brunch875
Dalam mode penyisipan, penggunaan <c-r>=lambat untuk perintah yang mungkin memiliki banyak output dan juga dapat mematahkan indentasi sehingga teks keluaran tidak dapat dibaca. Misalnya, <c-r>=execute('nmap')output akan ditulis baris demi baris, yang sangat lambat.
jdhao
22

:r!date +\%c

Lihat :help :r!

glenn jackman
sumber
1
dateadalah perintah eksternal dan !memanggil perintah eksternal sementara OP meminta perintah vim.
Eelvex
@eelvex tidak, dia tidak. dan! adalah perintah, dan vi, perintah. Ini adalah metode kanonik. Berfungsi untuk banyak hal lain juga.
Keith
5
@Keith: yes !adalah perintah vi (m) yang memanggil perintah eksternal . Anda mungkin benar OP tidak ingin hanya output perintah vim tetapi jika dia melakukannya, !tidak akan melakukannya.
Eelvex
11

Perintah-perintah ini akan memasukkan output strftime("%c")tepat di mana kursor Anda berada:

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

dan

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

Ada cara lain untuk melakukan apa yang Anda inginkan (seperti, misalnya, jawaban Mikel ).

Sunting : Lebih baik lagi, untuk penyisipan di tempat, gunakan =register seperti yang dijelaskan oleh John Johnsen

Eelvex
sumber
10

Jika Anda ingin memasukkan output dari perintah vim (sebagai lawan dari nilai balik dari panggilan fungsi ), Anda harus menangkapnya. Ini dilakukan melalui :redirperintah, yang memungkinkan Anda untuk mengarahkan setara dengan output standar vim ke dalam variabel, file, daftar, atau target lainnya.

:rediragak tidak nyaman untuk digunakan; Saya akan menulis fungsi untuk merangkum fungsinya dengan cara yang lebih nyaman, seperti

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

Setelah Anda mendeklarasikan fungsi tersebut, Anda dapat menggunakan register ekspresi (seperti yang dijelaskan oleh Chris Johnsen) untuk memasukkan output dari perintah pada posisi kursor. Jadi, dari mode normal, tekan i^R=Exec('ls')untuk memasukkan daftar buffer saat vim.

Ketahuilah bahwa perintah akan dieksekusi dalam function namespace, jadi jika Anda menggunakan variabel global Anda harus secara eksplisit namespace dengan awalan dengan g:. Juga perhatikan bahwa Exec(), seperti yang ditulis di atas, akan menambahkan baris baru yang berhenti bahkan untuk output satu baris. Anda mungkin ingin menambahkan panggilan ke substitute()dalam fungsi untuk menghindari ini.

Juga lihat https://stackoverflow.com/questions/2573021/vim-how-to-redirect-ex-command-output-into-current-buffer-or-file/2573054#2573054 untuk ngobrol lebih banyak tentang redirdan tautan ke perintah terkait.

intuisi
sumber
2
Ini sangat bagus. Saya menambahkan set pasteperintah sebelum mengembalikan output dan set nopastesetelahnya, untuk menghindari indentasi tangga ketika garis mulai dengan kosong. Sebenarnya, saya ingin menyimpan nilai opsi tempel saat ini dan mengembalikannya tetapi saya tidak dapat melakukannya.
Juan Lanus
1
@JuanLanus set nopasteSeharusnya tidak berfungsi setelah itu return output, karena pernyataan kembali adalah titik keluar dari fungsi. Saya telah menempatkan solusi untuk masalah ini sebagai jawaban terpisah di halaman ini.
Evgeni Sergeev
4
:call append(line('.'), strftime("%c"))

Akan meletakkannya di baris berikutnya, maka Anda bisa menekan J( Shift+ J) untuk bergabung ke posisi saat ini.

Atau jika Anda membutuhkan semuanya dalam satu perintah, Anda bisa melakukannya

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

atau

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

tergantung pada apakah Anda ingin ruang dimasukkan sebelum tanggal atau tidak.

Mikel
sumber
4

Meningkatkan jawaban @intuited untuk menghindari masalah dengan memimpin spasi putih dan menumbuhkan indentasi:

"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!

Ini hanya akan menyisipkan di lokasi saat ini di file ketika Anda :call Exec('command')dari mode normal. Seperti disebutkan dalam komentar , =Exec('command')pendekatan Ctrl + R asli (mode-sisipan) dengan Exec(..)mengembalikan sebuah string dapat sebagian dikoreksi dengan menggunakan set paste, tetapi tidak menawarkan kesempatan untuk meletakkan di set nopastemana saja.

The let @o = outputsintaks set register odengan isi variabel output, seperti dijelaskan di sini: https://stackoverflow.com/a/22738310/1143274

The return ''line adalah sehingga nilai default kembalinya 0tidak mendapatkan dimasukkan ke buffer.

Evgeni Sergeev
sumber
2

Beginilah cara saya melakukannya. Ini menempatkannya tepat setelah kursor karena digunakan 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
sumber