Mematikan indentasi otomatis ketika menempelkan teks ke vim

1186

Saya berusaha untuk belajar Vim.

Ketika saya menempelkan kode ke dokumen saya dari clipboard, saya mendapatkan ruang ekstra di awal setiap baris baru:

line
  line
    line

Saya tahu Anda dapat mematikan indentasi otomatis tetapi saya tidak dapat mengaktifkannya karena saya memiliki beberapa pengaturan lain yang bertentangan atau sesuatu (yang terlihat cukup jelas di .vimrc saya tetapi tampaknya tidak masalah ketika saya mengeluarkannya).

Bagaimana cara mematikan indentasi otomatis ketika saya menempelkan kode tetapi masih memiliki indentasi otomatis vim ketika saya menulis kode? Ini .vimrcfile saya :

set expandtab  
set tabstop=2  
set shiftwidth=2  
set autoindent  
set smartindent  
set bg=dark  
set nowrap  
Rimian
sumber
4
FWIW, vim 8.0.210 menambahkan dukungan asli untuk pasta yang diberi tanda kurung, sehingga akan menghindari pengindeksan teks yang disisipkan.
sh1
Untuk file baru untuk menghindari mengutak-atik pasta / nopaste vim, Anda dapat cat > mynewfile.txtmenekan Enter , menempelkan teks Anda, tekan Enter lagi, lalu Ctr + D untuk menyimpan. File sekarang dibuat dan Anda dapat mengeditnya dengan vim mynewfile.txt.
ccpizza

Jawaban:

2066

Pembaruan: Jawaban yang lebih baik di sini: https://stackoverflow.com/a/38258720/62202

Untuk mematikan autoindent ketika Anda menempelkan kode, ada mode "tempel" khusus.

Tipe

:set paste

Kemudian tempel kode Anda. Perhatikan bahwa teks dalam tooltip sekarang mengatakan -- INSERT (paste) --.

Setelah Anda menempelkan kode Anda, matikan mode tempel, sehingga indentasi otomatis saat Anda mengetik berfungsi dengan benar.

:set nopaste

Namun, saya selalu merasa tidak praktis. Itu sebabnya saya memetakan <F3>sedemikian rupa sehingga dapat beralih antara mode tempel dan nopaste saat mengedit teks! Saya menambahkan ini ke.vimrc

set pastetoggle=<F3>
P Shved
sumber
38
Ini tidak lebih mudah daripada :set noaidiikuti oleh :set ai. Saran :r! catlebih pendek.
Leopd
69
Saya pikir set pastelebih mudah, pasti. Ini jauh lebih semantik daripada noaiatau bahkan noautoindent, yang lebih penting ketika mengetik "noai" dan "tempel" membutuhkan waktu yang sama ketika Anda cukup mahir sebagai pengetik sentuh.
Victor Zamanian
52
:set noaitidak selalu berfungsi, tergantung pada bagaimana pengaturan terkait indent lain dikonfigurasi sesuai OP. :set pastetampaknya menjadi singkatan untuk beberapa pengaturan sekaligus.
MarkHu
13
Terlambat ke pesta, tetapi set copyindentakan mengurus ini untuk Anda dengan mulus.
Matt Ryan
33
:set pastejuga menonaktifkan fitur lain seperti penyempurnaan kawat gigi, yang juga tidak diinginkan saat menempelkan kode.
Manuel Faux
263

Untuk menghindari efek yang tidak diinginkan saat menempel, ada opsi yang perlu diatur:

set paste

Perintah yang berguna untuk ada di .vimrc Anda adalah set pastetoggle=<F10>atau tombol lain, untuk dengan mudah beralih antara tempel dan nopaste.

Jacob Rask
sumber
13
Akhirnya! Saya terus mengetik: set paste /: set nopaste, betapa bodohnya! Terima kasih.
imwilsonxu
4
dari sudut pandang praktis, jawaban Anda lebih berguna daripada jawaban yang diterima
Lynob
8
Pilihan lain adalah menambahkan makro ke vimrc Anda:nmap <silent> <leader>p :set paste<CR>"*p:set nopaste<CR>
Chris
Saran bagus @ Chris - urutan tombol tunggal untuk menempel tanpa masalah lekukan!
RichVel
bagaimana jika saya tidak pernah ingin berada dalam mode tempel? apakah ada cara untuk menonaktifkan secara permanen?
maks.
132

Saya biasanya menggunakan :r! catlalu menempelkan ( shift + insert )konten, dan CTRL+D.

Tidak perlu mengaktifkan & menonaktifkan, penggunaan langsung.

thegeek
sumber
Saya suka opsi penggunaan langsung ini. Saya masih belajar cara membaca sintaks vim di halaman web, meskipun. Apa langkahmu? Secara khusus, seandainya saya memiliki sesuatu pada clipboard sistem, apa yang saya tekan untuk menempelkannya ke dalam dokumen di vim?
jvriesem
9
Jawaban ini akan lebih membantu dengan informasi tentang mengapa dan bagaimana cara :r! catkerjanya.
K Erlandsson
11
@ KErlandsson, :rmenyisipkan isi file ke dalam dokumen saat ini. !catmengatakan, jalankan cat yang pada dasarnya membuka stdin (* nix shells) (shift + insert)atau untuk beberapa terminal, klik kanan mouse akan menempelkan isi clipboard ke terminal CTRL+Dadalah end-of-file, sehingga menutup :r !catsesi.
Daniel
Apakah ini 'langsung', sungguh? Daripada mengatur opsi yang pastedibuat hanya untuk tujuan ini? @ jvriesem Ini bukan opsi 'langsung', jika apa yang saya anggap pemahaman Anda tentang kata itu benar.
0xc0de
Anda juga dapat menggunakan :r! catkemudian CTRL+SHIFT+Vuntuk menyisipkan di terminal (kemudian CTRL+D).
Paul Rougieux
86

Jika Anda bekerja secara lokal, Anda dapat menempel dari clipboard sistem dengan urutan tombol:

"+p

Ini adalah perintah vim yang tepat, jadi tidak perlu khawatir memasukkan mode penyisipan atau mematikan autindent terlebih dahulu.

Tentu saja jika Anda bekerja dari jarak jauh (konsol lebih dari SSH, misalnya) maka ini tidak akan berhasil dan Anda harus pergi :set noai, masukkan mode, tempelkan ke konsol, tinggalkan metode masukkan, :set airute seperti dijelaskan di tempat lain.

thomasrutter
sumber
10
Saya menulis jawaban ini sejak lama. Saat ini saya menggunakan :set pastedan :set nopastesebagai gantinya karena lebih lama, lebih mudah diingat dan saya tidak harus mencarinya setiap waktu!
thomasrutter
6
Dalam beberapa sistem tertanam (terutama berdasarkan busybox) :set pastetidak diterapkan, jadi :set noaisebaiknya digunakan.
jcarballo
Ketika Anda memiliki teks besar untuk disalin, bukankah lebih cepat menggunakan + register saja?
pedromanoel
1
@pedromanoel yang hanya berfungsi saat bekerja secara lokal. Ini tidak akan berfungsi mengakses vim melalui SSH, misalnya, jika Anda menyalin sesuatu secara lokal dan ingin menempelkannya ke vim yang ada di sesi SSH Anda.
thomasrutter
1
@ Thomas tapi saya memetakan ini untuk <leader>p.. sangat berguna!
Dane
51

Saat mengatur mode tempel dengan paste/nopaste/pastetogglesangat baik, Anda masih harus mengaktifkan mode tempel secara manual sebelum menempel dan menonaktifkan mode tempel setelah menempel. Menjadi orang yang malas seperti saya, di bawah ini adalah solusi terbaik yang saya temukan sejauh ini, yang secara otomatis mengubah mode tempel ketika Anda menempel.

Berikut adalah sedikit trik yang menggunakan mode rekat kurung terminal untuk secara otomatis mengatur / membatalkan mode rekat Vim saat Anda menempel. Masukkan berikut ini di .vimrc Anda:

let &t_SI .= "\<Esc>[?2004h"
let &t_EI .= "\<Esc>[?2004l"

inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()

function! XTermPasteBegin()
  set pastetoggle=<Esc>[201~
  set paste
  return ""
endfunction

Sekarang Anda dapat menempel tanpa mengaktifkan / menonaktifkan mode tempel - ini ditangani secara otomatis untuk Anda.

Sumber: Coderwall

Catatan: Solusi ini tidak berfungsi di WSL (Windows 10 Subsystem untuk Linux). Jika ada yang punya solusi untuk WSL, harap perbarui jawaban ini atau tambahkan dalam komentar.

Tmux Jika menggunakan tmux, maka deklarasi harus diloloskan ganda. Kode untuk ini juga ada di Coderwall

Terima kasih
sumber
Ini brilian. Satu hal ... Dengan setiap pasta saya mendapatkan karakter "0" (nol) di awal setiap pasta. Ada tip untuk itu?
Julius Š.
juga perhatikan jika menggunakan tmux maka Anda harus meloloskan diri. Kode untuk ini ada di tautan Coderwall dalam jawaban
Daithí
1
Jika Anda lebih malas dan menyalin kode di atas ke dalam .vimrc Anda, lakukan perawatan lekukan fungsi XTermPasteBegin ().
k1133
Saya ingin tahu bagaimana ini bekerja, jadi saya mencari Paste Bracketing dan menemukan gitlab.com/gnachman/iterm2/-/wikis/Paste-Bracketing yang menjelaskan bahwa variabel t_SIdan t_EImengaktifkan bracketing paste dan menonaktifkannya. Saat menempelkan tanda kurung aktif, teks yang disisipkan diawali oleh esc[200~dan diikuti oleh esc[201~.
PatS
37

Pengguna Mac dapat menghindari pemformatan otomatis dengan membaca langsung dari papan tulis dengan:

:r !pbpaste
maniacalrobot
sumber
3
Ini adalah respons yang luar biasa. Ketika saya melakukan ini, bagaimanapun, ia menyembunyikan dokumen (sepertinya saya kembali pada baris perintah), tetapi memiliki teks di clipboard saya. Ini meminta saya untuk menekan enter, jadi saya lakukan, dan mengembalikan saya ke dokumen saya tanpa perubahan. Apa yang terjadi, dan bagaimana saya melakukan apa yang Anda katakan?
jvriesem
Jika Anda cukup mengetik :.!pbpaste, ini akan berfungsi dengan mengganti baris saat ini dengan output dari buffer pasta. Secara umum, vim memungkinkan Anda untuk mem-pipe data yang ada di file Anda saat ini ke program lain dan mengganti teks dengan output dari perintah. Jadi, :1,3!pbpasteganti tiga baris pertama file Anda dengan buffer paste. Saya gunakan :.!ppjsonuntuk mengambil string JSON yang sangat panjang (tidak diformat) dan memformatnya dan mengganti string panjang dengan setara yang diformat. ppjson hanyalah skrip bash yang berjalan python -m json.tool.
PatS
19

Ini adalah posting oleh seseorang yang menemukan cara untuk memetakan kembali acara tempel untuk secara otomatis mengaktifkan mode tempel dan kemudian mematikannya. Bekerja untuk saya di tmux / iTerm di MacOSX.

Von
sumber
1
Terima kasih atas tipnya. Saya juga melacak sebuah plugin di mana orang tersebut telah membundel fungsionalitas serupa - stackoverflow.com/a/36512548/255961 .
studgeek
Ini tampaknya menyebabkan string 'eeeeeee' ketika saya memasukkan sepotong teks dari clipboard saya.
John Jiang
16

Tambahkan ini ke Anda ~/.vimrcdan Anda hanya perlu menekan F2 sebelum dan sesudah menempel:

set pastetoggle=<F2>
anh_ng8
sumber
12

Saya baru saja memasukkan set clipboard=unnamed.vimrc saya. Itu membuat peta penyangga tempel default ke papan klip X.

Jadi, jika saya menandai sedikit teks di terminal, saya cukup menekan puntuk menempelkannya di vim. Demikian pula, saya dapat menarik hal-hal di vim (misalnya YYuntuk menarik garis saat ini ke buffer) dan klik tengah di jendela mana saja untuk menempelkannya.

Tidak tahu Saya merasa sangat nyaman.

Soren
sumber
IMHO, ini adalah jawaban terbaik, tidak perlu untuk beralih dengan F11 (yang telah dikonfigurasikan sebelumnya secara default di vim). Ini bekerja di sistem OSX mac, saya tidak tahu tentang yang lain.
LightMan
9

Ketika bekerja di dalam terminal, vim-bracketed-paste vim plugin akan secara otomatis menangani pasta tanpa perlu penekanan tombol apa pun sebelum atau setelah menempel.

Ia bekerja dengan mendeteksi mode rekatkan kurung yang merupakan urutan keluar yang dikirim oleh terminal kompatibel term-term "modern" seperti iTerm2, terminal gnome, dan terminal lain menggunakan libvte. Sebagai bonus tambahan berfungsi juga untuk sesi tmux. Saya berhasil menggunakannya dengan iTerm2 pada Mac yang terhubung ke server linux dan menggunakan tmux.

studgeek
sumber
Waspadalah terhadap apa yang juga dicatat lebih lanjut: Sayangnya, ini berarti bahwa mereka juga akan menjalankan konten buffer input jika ada baris baru dalam apa pun yang Anda rekatkan ke terminal.
0xc0de
1
@ 0xc0de, kutipan itu tidak relevan di sini. Itu berbicara tentang apa yang akan dilakukan shell ketika tidak mendukung mode tempel kurung. Itulah titik dalam mode tempel kurung - untuk menghentikan hal itu terjadi.
sh1
Ini bekerja jauh lebih baik bagi saya daripada solusi lainnya. Terima kasih.
jjj
8

Simpan ini di ~ / .vimrc Anda dan senang:

" enables :Paste to just do what you want
command Paste execute 'set noai | insert | set ai'

Sunting: refleksi, :r !catadalah pendekatan yang jauh lebih baik karena pendek, semantik, dan tidak memerlukan vimrc khusus. Gunakan itu sebagai gantinya!

Dergachev
sumber
5

Meskipun :pastetoggleatau :pastedan :nopasteharus bekerja dengan baik (jika diterapkan - tidak selalu seperti yang dapat kita lihat dari diskusi) Saya sangat merekomendasikan menempel menggunakan pendekatan langsung "+patau "*pdan membaca dengan "+ratau "*r:

Vim memiliki akses ke sepuluh jenis register ( :help registers) dan si penanya tertarik masuk quotestardan quoteplusdari bagian

  1. Daftar seleksi dan lepas "*, "+dan "~

Gunakan register ini untuk menyimpan dan mengambil teks yang dipilih untuk GUI. Lihat quotestardan quoteplus. Ketika clipboard tidak tersedia atau tidak berfungsi, register yang tidak disebutkan namanya digunakan sebagai gantinya. Untuk sistem Unix, clipboard hanya tersedia ketika fitur + xterm_clipboard hadir. {tidak dalam Vi}

Perhatikan bahwa hanya ada perbedaan antara "* dan" + untuk sistem X11.

:help x11-selectionselanjutnya mengklarifikasi perbedaan *dan +:

                                                  quoteplus quote+

Ada tiga pilihan X yang terdokumentasi: PRIMARY (yang diharapkan mewakili pemilihan visual saat ini - seperti dalam mode Visual Vim), SECONDARY (yang tidak terdefinisi) dan CLIPBOARD (yang diharapkan akan digunakan untuk operasi potong, salin dan tempel ).

Dari ketiganya, Vim menggunakan PRIMARY saat membaca dan menulis register "* (karenanya ketika pilihan X11 tersedia, Vim menetapkan nilai default untuk 'clipboard' dari" autoselect "), dan CLIPBOARD saat membaca dan menulis" + register. Vim tidak mengakses pilihan SECONDARY.

Contoh: (dengan asumsi nilai opsi default)

  • Pilih URL dalam mode Visual di Vim. Buka browser Anda dan klik tombol mouse tengah di bidang teks URL. Teks yang dipilih akan dimasukkan (semoga!). Catatan: di Firefox Anda dapat mengatur preferensi middlemouse.contentLoadURL menjadi true di about: config, maka URL yang dipilih akan digunakan ketika menekan tombol tengah mouse di sebagian besar tempat di jendela.

  • Pilih beberapa teks di browser Anda dengan menyeret dengan mouse. Pergi ke Vim dan tekan tombol mouse tengah: Teks yang dipilih dimasukkan.

  • Pilih beberapa teks dalam Vim dan lakukan "+ y. Pergi ke browser Anda, pilih beberapa teks di bidang teks dengan menyeret dengan mouse. Sekarang gunakan tombol mouse kanan dan pilih" Tempel "dari menu sembulan. Teks yang dipilih ditimpa oleh teks dari Vim. Perhatikan bahwa teks dalam register "+ tetap tersedia ketika membuat pilihan Visual, yang membuat teks lain tersedia dalam register" *. Itu memungkinkan menimpa teks yang dipilih.
codingdave
sumber
saya perhatikan menggunakan klik tengah dalam vim tampaknya tidak mengacaukan lekukan sehingga mungkin sebuah ide
Fuseteam
4

Ini berfungsi untuk saya (case untuk + register, apa yang saya gunakan seperti pertukaran buffer antar aps):

imap <silent> <S-Insert> <C-O>:set noai<CR><C-R>+<C-O>:set ai<CR>
Sergey Vakulenko
sumber
2

Jika Anda menggunakan mac, macvim tampaknya menanganinya dengan baik tanpa harus beralih tempel.

buat install macvim --override-system-vim

Marcus Ericsson
sumber
Apakah itu masalahnya jika Anda memasukkan arahan OP dalam .vimrcfile Anda ?
Drew Noakes
1

Silakan baca artikel ini: Beralih indentasi otomatis untuk menempelkan kode

Beberapa orang menyukai umpan balik visual yang ditampilkan di baris status dengan alternatif berikut untuk Anda vimrc:

nnoremap <F2> :set invpaste paste?<CR>
set pastetoggle=<F2>
set showmode
d.danailov
sumber
1

Cara tercepat yang saya sadari untuk dengan cepat pergi ke mode tempel-sisipkan untuk tempel sekali pakai adalah tpope tidak mengalami gangguan , yang menampilkan yodan yO, mungkin mnemonik untuk “Anda buka”. Mereka hanya didokumentasikan dalam vimdoc-nya, sebagai:

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). Alih-alih, tekan yo atau yO untuk memanggil o atau O dengan 'tempel' yang sudah ditetapkan. Membiarkan mode sisipkan mengatur 'nopaste' secara otomatis.

Micah Elliott
sumber
1

Cara lain untuk menempelkan adalah melalui <CR>dan menjatuhkan konten register (di sini register global). Lihat: :h i_ctrl-rdan h i_CTRL-R_CTRL-O.

Dari dokumentasi bantuan vim:
Insert the contents of a register literally and don't auto-indent. Does the same as pasting with the mouse<MiddleMouse>. Does not replace characters! The '.' register (last inserted text) is still inserted as typed.{not in Vi}

Jadi untuk menempelkan konten ke vim tanpa indentasi otomatis, gunakan <CR><CO>*di sebagian besar sistem unix.

Catatan: ini hanya berfungsi jika vim dikompilasi dengan clipboard.

TheChetan
sumber
1

Dari vim: ]p

Dari luar: "*]patau"+]p

Bruno
sumber
1

Jawaban lain yang tidak saya lihat sampai sekarang:

:se paste noai
sja
sumber
1

Pasta asli / braket tempel adalah cara terbaik dan paling sederhana sejak vim 8(dirilis pada 2016). Ia bahkan bekerja lebih dari ssh! (Bracketed paste berfungsi di Linux dan Mac, tetapi bukan Windows Git Bash)

  1. Pastikan Anda memiliki vim 8+ (Anda tidak memerlukan +clipboardatau +xterm_clipboardopsi).

    vim --version | head -1

  2. Cukup gunakan perintah tempel asli OS (mis. ctrl+shift+VAtau cmd+V) dalam Mode Normal. Jangan menekan iuntuk Mode Sisipkan.


Uji

  1. Salin ( ctrl+shift+Catau cmd+C) output dari ini (2 baris dengan indentasi tab) ke clipboard sistem:

    echo -e '\ta\n\tb'

  2. Luncurkan vim 8+ bersih dengan autoindent:

    vim -u NONE --noplugin -c 'set autoindent'

  3. Tempel dari papan klip sistem ( ctrl+shift+Vatau cmd+V) dalam Mode Normal. Jangan menekan iuntuk Mode Sisipkan. The adan bharus sejajar dengan tab indent tunggal. Anda bahkan dapat melakukan ini saat ssh-ing ke mesin jarak jauh (mesin jarak jauh akan membutuhkan vim 8+).

  4. Sekarang coba cara lama, yang akan secara otomatis mengidentifikasi baris kedua dengan tab tambahan: Tekan iuntuk Mode Sisipkan. Kemudian tempel menggunakan ctrl+shift+Vatau cmd+V. The adan btidak selaras sekarang.


Memasang Vim 8

wisbucky
sumber
1
cara terbaik dan paling sederhana! Juga, Google menyarankannya Featured snippetuntuk pencarian saya 'paste konten tanpa tab', mungkin karena, saya menggunakan kata kunci 'tab', hanya dalam jawaban ini disebutkan :)
David
0

Sayangnya saya menemukan plugin vim yang disebutkan tidak dapat bekerja dengan iTerm2 3.0.15 (agar adil saya tidak tahu apakah ini rusak pada versi yang lebih lama) - tetapi saya malah menemukan hack ini.

Map command-p untuk melakukan paste dan menggunakan kunci vim iterm2. Jelas ini hanya berfungsi untuk iTerm2.

Bagaimana itu bekerja. Saya menggunakan "jk" untuk masuk ke mode melarikan diri sehingga Anda juga perlu:

: inoremap jk

di .vimrc Anda.

Kemudian itu hanya memanggil P untuk masuk ke mode tempel, "+ p untuk menempel dari clipboard dan kemudian P untuk menonaktifkan mode tempel. Hth.

masukkan deskripsi gambar di sini

Neil McGill
sumber
1
Tunggu, apa, kamu menggunakan 'jk' untuk ini?
0xc0de
Oh ya, aku lupa menyebutkan itu. Cukup tambahkan ": inoremap jk <esc>" ke .vimrc Anda. Mengenai mengapa saya menggunakan jk, tanyakan kepada Apple dan mengapa mereka merasa perlu untuk bergerak dan menyingkirkan kunci pelarian fisik. 8 (
Neil McGill
BTW butuh beberapa pelatihan tetapi setelah beberapa saat jk merasa lebih cepat dan saya pikir saya lebih suka sekarang daripada melarikan diri ... Pokoknya akan menarik untuk mengetahui apakah iTerm2 menerima <ESC> di sini juga.
Neil McGill
Cara untuk pergi Apple!
0xc0de