Atur opsi tempel, tetapi hanya untuk satu penyisipan

16

Saya ingin memiliki cara cepat mengatur 'paste'opsi Vim , memasukkan beberapa teks, dan kembali ke nilai sebelumnya 'paste'.

Sebuah kasus penggunaan tipikal memasukkan konten clipboard OS secara literal, terlepas dari mode penulisan ulang apa pun yang mungkin aktif, seperti lekukan otomatis, dan tanpa mengubah status Vim. Kasus penggunaan lain adalah untuk memungkinkan fitur makro OS untuk menyuntikkan penekanan tombol ke Vim dan meminta mereka ditafsirkan sebagai teks literal.

Ini jelas menggeneralisasi ke opsi lain - ide umumnya adalah untuk mengatur beberapa opsi tetapi hanya untuk durasi satu perjalanan melalui mode penyisipan.

Pada dasarnya saya ingin mengikat urutan kunci (katakanlah _i) ke makro yang melakukan ini

:set paste
i…<Esc>
:set nopaste

di mana i…<Esc>maksud saya beralih ke memasukkan mode (seperti dengan iperintah) dan melanjutkan makro setelah kembali ke mode perintah, kecuali bahwa saya ingin berakhir dengan 'paste'masih aktif jika sudah aktif sebelumnya. Bagaimana saya bisa melakukan ini?

Catatan: Konten clipboard OS dipetakan ke "*register . Ketika itu berhasil, 'paste'opsinya tidak terlalu berguna. Skenario memotivasi untuk pertanyaan ini adalah untuk saat-saat ketika kondisi untuk "*dukungan register tidak terpenuhi - Vim tidak dikompilasi dengan +xterm_clipboardfitur, atau sedang berjalan di terminal seperti Layar atau lebih dari SSH yang mengisolasinya dari server X ambient.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Saya suka pertanyaan Anda (saya sendiri sudah sering ke sana). Namun, bukankah lebih mudah untuk menempel dari +atau *mendaftar?
yo '
@yo ' Hanya saat mereka bekerja . Yang, untuk penggunaan Vim saya, sering tidak demikian.
Gilles 'SO- berhenti bersikap jahat'

Jawaban:

15

Cobalah ini:

function! Paste_Func()
    let s:inPaste = &paste
    if !s:inPaste
        set paste
    endif

    echom s:inPaste
    augroup paste_callback
        autocmd!
        autocmd InsertLeave <buffer> call Paste_End()
    augroup END

    startinsert
endfunction

function! Paste_End()
    augroup paste_callback
        autocmd!
    augroup END
    augroup! paste_callback

    if !s:inPaste
        set nopaste
    endif
endfunction

map _i :call Paste_Func()<cr>

Ini menyimpan status tempel Anda saat ini di variabel inPaste dan menyetel tempel jika belum disetel. Kemudian ia mengatur autocmd ketika Anda meninggalkan mode insert, dan kemudian menempatkan Anda dalam mode insert.

Ketika Anda meninggalkan mode insert, ia menjalankan autocmd, yang pertama-tama menghapus autocmd (sehingga tidak bisa dijalankan ketika Anda meninggalkan mode insert dengan cara lain), dan akhirnya menetapkan nopaste jika Anda tidak berada dalam mode paste semula.

Juga, jika Anda menggunakan vim di terminal, Anda mungkin ingin melihat vim-bracketed-paste , yang menggunakan fitur mode tempel kurung yang disediakan oleh beberapa emulator terminal untuk mendeteksi jika Anda menempel dan mengatur mode secara otomatis.

Edit: memperbaiki skrip

Chad
sumber
Tampaknya ini berada di jalur yang benar (khususnya, saya tidak tahu bagaimana cara "mengurung" serangkaian perintah dunia normal). Terima kasih. Namun, itu tidak benar dan saya tidak melihat di mana masalahnya: setelah _i, pasteopsi tidak aktif, bahkan jika sudah aktif sebelumnya.
Gilles 'SANGAT berhenti menjadi jahat'
Kamu benar! Saya cukup yakin telah mengujinya, tetapi saya harus mengubah sesuatu. Saya telah memperbarui skrip di pos, lihat apakah skrip itu berfungsi untuk Anda sekarang.
Chad
4

kecuali bahwa saya ingin berakhir dengan 'paste'masih aktif jika sudah aktif sebelumnya.

'paste'harus aktif sesingkat mungkin. Ini menonaktifkan banyak fungsi (termasuk peta), karena tujuan utamanya adalah untuk menghindari salah menafsirkan teks yang sedang ditempelkan. Karena itu, saya pikir persyaratan yang dikutip seharusnya tidak perlu.

Yang sedang berkata, itu sebenarnya cukup mudah untuk ditempelkan tanpa perlu mengatur 'paste'. Jika Anda menjalankan gvim atau menggunakan +xterm_clipboardkonsol vim, maka Anda dapat menggunakannya "+puntuk menempel dari clipboard OS.

Masalah lekukan sementara tempel hanya benar-benar terjadi dalam dua skenario. Memasukkan konten register saat dalam mode insert ( <C-r>+) atau menempelkan klik tengah dengan mouse.

Alih-alih menyisipkan konten register saat dalam mode insert, menempelkan dari register dalam mode normal akan menghindari masalah memformat ulang.

Jika Anda ingin melakukan klik tengah menempel dengan mouse, maka gunakan 'mouse'opsi untuk membiarkan Vim, bukan terminal, menangani klik tengah. Vim kemudian akan memasukkan konten secara harfiah alih-alih menafsirkan teks yang masuk sebagai sedang diketik.

jamessan
sumber
2
Tak satu pun dari ini menjawab pertanyaan saya. Saya memasukkan persyaratan eksplisit karena suatu alasan! Biasanya 'paste'memang tidak aktif sebelumnya, tetapi saya tidak mau harus memikirkan hal ini. Saya sering bekerja di Vim yang tidak memiliki akses ke clipboard X atau mouse, baik karena Vim build saya tidak memiliki xterm_clipboardfitur, atau karena saya sedang bekerja di misalnya sesi Layar yang kebetulan saat ini dilampirkan ke sebuah Terminal X.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Lalu bisakah Anda menjelaskan bagaimana Anda menempelkannya? Itu informasi yang relevan untuk dapat memberikan jawaban yang dapat membungkus tindakan itu dengan apa yang ingin Anda lakukan.
jamessan
1
Kasus penggunaan dasar saya adalah untuk menempel dengan tombol tengah mouse atau dengan Shift + Insert. Namun itu tidak terlalu relevan: inti dari pertanyaannya adalah bagaimana mengatur opsi, beralih ke mode penyisipan (dengan i, saya tidak menanyakan bagaimana cara menetapkan parameter ini), dan mengembalikan nilai opsi setelah kembali dari mode penyisipan.
Gilles 'SO- stop being evil'
1
@Gilles Inti dari pertanyaan Anda sebagaimana dinyatakan dalam komentar ini jauh lebih jelas bagi saya daripada pertanyaan awal Anda. Terima kasih.
jamessan
1
@Gilles Tidak relevan bagi Anda , tetapi dapat relevan bagi pengunjung di masa mendatang. Oleh karena itu, Anda dapat memasukkannya ke dalam pertanyaan itu sendiri ("Saya tahu saya dapat menggunakan "*patau "+pmenempel dari clipboard, tetapi saya tidak ingin menggunakan kemampuan tempel sistem") dan kemudian jawaban ini tidak perlu. Atau Anda tidak, dan kemudian saya pikir jawaban ini ada di sini.
yo '
4

Secara pribadi, saya menggunakan yokeybinding dari plugin Tim Pope vim-unimpaired yang sangat baik untuk alasan ini. Dari dokumentasinya:

Sebuah toggle belum disediakan untuk 'paste' karena kasus penggunaan khas pembungkus insersi soliter begitu boros: Anda beralih dua kali, tetapi Anda hanya menempel sekali (YOPO). Sebagai gantinya, tekan yoatau yOuntuk memohon |o|atau |O|dengan 'tempel' sudah diatur. Membiarkan mode sisipkan mengatur 'nopaste' secara otomatis.

Mungkin terlalu sulit untuk menginstal plugin hanya untuk pertanyaan Anda, tetapi saya menemukan plugin ini juga menyediakan banyak sekali keybindings berguna lainnya (informasi lebih lanjut di README ).

Andrew Ferrier
sumber
1

Dengan Vim 8+ di Linux atau Mac, Anda sekarang dapat dengan mudah menggunakan tempel asli terminal (mis. Tombol mouse tengah, ctrl+shift+Vdi Gnome, cmd+Vpada Mac) jika terminal mendukung tempel braket. Jangan menekan iuntuk Mode Sisipkan.

Ini akan menempelkan isi clipboard OS Anda, menjaga spasi dan tab tanpa menambahkan autoindenting. Ini setara dengan tua :set paste, i, ctrl+shift+V, esc, :set nopastemetode.

Anda bahkan tidak perlu menginstal fitur +clipboardatau +xterm_clipboardvim lagi. Fitur ini disebut "braket tempel". Untuk detail lebih lanjut, lihat /programming/2514445/turning-off-auto-indent-when-pasting-text-into-vim/56781763#56781763

wisbucky
sumber