Reload otomatis file dalam VIM segera setelah itu berubah pada disk


32

Dengan asumsi bahwa suatu file tidak memiliki perubahan yang belum disimpan dalam buffer VIM, saya ingin memuat ulang secara otomatis jika file berubah pada disk. Kasus penggunaan paling sering untuk ini adalah ketika saya memperbarui copy pekerjaan di mana file berada.

Bagaimana saya bisa mencapai ini?


Saya pikir ini yang Anda maksud, tetapi kasus penggunaan khusus saya adalah ketika saya memeriksa cabang git yang berbeda atau melakukan, saya ingin vim memuat ulang file.
Nathan Long

Jawaban:



11

Inilah yang bekerja untuk saya

set autoread                                                                                                                                                                                    
au CursorHold * checktime  

Baris pertama tidak cukup dengan sendirinya. Anda bisa memasukkan Anda ke dalam.vimrc

kredit untuk Phan Hai Quang


Autocmd seharusnya tidak perlu - waktu checktime seharusnya berjalan secara internal pada saat yang sama event CursorHold dipicu. Dengan kata lain, Anda hanya membuat Vim melakukan checktime kedua.
Heptite

Bagi saya itu perlu. Solusi terbaik yang saya temukan setelah banyak penelitian. @Heptite, apakah Anda memiliki bab dan ayat untuk pernyataan Anda?
Tom Hale

1
@ TomHale Saya telah meninjau dokumen Vim dan tidak secara eksplisit mengatakan, sejauh yang saya tahu, tapi " :help timestamp" tampaknya menunjukkan bahwa saya yang salah, dan bahwa Vim hanya melakukan pemeriksaan pada peristiwa tertentu, jadi autocmd bisa diperlukan untuk membuatnya memeriksa lebih sering.
Heptite

5

Autoread tidak berfungsi dengan benar. Berikut ini berfungsi untuk saya:

Anda harus menginstal skrip terlebih dahulu dari sini .

Saya mendapatkan hasil terbaik dengan memanggil fungsi pengaturan secara langsung, seperti itu.

let autoreadargs={'autoread':1} 
execute WatchForChanges("*",autoreadargs) 

Alasan untuk ini, adalah bahwa saya ingin menjalankan pengaturan ipython / layar / vim.

Anda dapat dengan mudah mengubahnya menjadi versi tampilan yang disempurnakan.

skrip proses ..

mkdir -p ~/bin
cat <<`OUT` > ~/bin/vimviewer
#!/usr/bin/env sh
exec vim -n --cmd "source /home/bryan/.vim/.vimrc.watchforchanges | let autoreadargs={'autoread':1} | execute WatchForChanges('*',autoreadargs)" $@
`OUT`

chmod 755 ~/bin/vimviewer
vimview test.txt

1
Jika Anda menggunakan salah satu GUI vim seperti gVim atau MacVim maka perintah autoread terintegrasi dengan baik dengan seluruh lingkungan. Misalnya mengedit file di beberapa program lain, editor lain atau dari kontrol sumber, kemudian beralih kembali ke vim akan secara otomatis mengembalikan file yang diperbarui. Masalahnya tampaknya dengan bagaimana versi terminal vim terintegrasi. Versi terminal tidak dapat menentukan kapan Anda beralih antar program baik di GUI atau menggunakan multiplexer terminal seperti tmux, sehingga gagal untuk autoread pada waktu yang relevan. Akan lebih baik jika vim hanya berlangganan acara sistem file yang relevan.
bames53

3

Plugin vim-autoread telah bekerja untuk saya sejauh ini:

vim-autoread

Secara otomatis menyebabkan vim memuat ulang file yang telah ditulis pada disk tetapi tidak dimodifikasi dalam buffer sejak penulisan terakhir dari vim. Ini memungkinkan file yang terbuka di vim diedit menggunakan aplikasi lain dan disimpan. Setelah kembali ke vim, selama Anda belum mengubah file sejak perubahan terakhir, file akan diperbarui secara otomatis untuk mencerminkan perubahan yang dibuat pada disk, seolah-olah Anda telah menekan: e secara manual.


Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Burgi

@ Burgi Saya telah menambahkan deskripsi plugin yang menjelaskan bagaimana ini memecahkan masalah.
Wojtek Kruszewski

Saya mencobanya tetapi saya harus mengetikkan perintah navigasi (seperti j) untuk melihat pembaruan yang efektif. Saya membuat masalah di sini tentang ini: github.com/djoshea/vim-autoread/issues/3
Martin Delille

3

dari jawaban ini (merujuk ke jawaban oleh PhanHaiQuang dan komentar oleh @flukus)

Seseorang dapat menjalankan oneliner ini dari ex (whithin vim) saat dibutuhkan (atau menempatkan setiap perintah dalam vimrc, untuk saat file log dibuka.)

:set autoread | au CursorHold * checktime | call feedkeys("lh")

Penjelasan:
- autoread : membaca file ketika diubah dari luar (tetapi tidak bekerja sendiri, tidak ada timer internal atau sesuatu seperti itu. Itu hanya akan membaca file ketika vim melakukan suatu tindakan, seperti perintah dalam ex :!
- CursorHold * checktime : ketika cursor tidak dipindahkan oleh pengguna untuk waktu yang ditentukan dalam 'updatetime' (yang secara default 4000 milidetik) dijalankan, yang memeriksa perubahan dari luar file
- panggilan feedkeys ("lh") : kursor dipindahkan satu kali, kanan dan kiri kiri. dan kemudian tidak ada yang terjadi (... yang berarti, bahwa CursorHold dipicu, yang berarti kita memiliki loop )


lhtidak melakukan apa-apa, jika kursor berada pada posisi terakhir di telepon, lhakan mengubah lokasinya.
Mahmoud Al-Qudsi

Tepat, itu intinya. File dimuat ulang dengan interaksi minimum atau perubahan pada file. Anda bisa melompat ke baris terakhir atau pertama jika Anda mau (ganti saja lh dengan gg atau G), tetapi tujuannya di sini, hanya untuk memuat ulang file dalam vim, dan itulah yang dilakukan oleh liner satu ini, tidak lebih. Apa yang Anda suka dilakukan di sini?
eli

@ MahmoudAl-Qudsi ... yang berarti, bahwa "lh" baru saja memicu tindakan CursorHold (saya sebutkan dalam Penjelasan), yang kemudian lagi memicu autoread
eli

1

Ada beberapa plugin yang tercantum di sini yang mungkin berfungsi tergantung pada versi Vim Anda.

Pendekatan lain adalah mengirim checktimeperintah secara berkala ke vim dari proses eksternal. Berikut ini skrip ShellJS untuk melakukan ini (memerlukan shelljs-plugin-sleep, NeoVim, dan nvr)

while (true) {
  sleep(15);
  var servernames = exec('nvr --serverlist').trim().split('\n');
  if (!servernames.length || !servernames[0]) {
    continue;
  }
  servernames.forEach(
    (sn) => exec(`nvr -c "checktime" --servername ${sn}`) );
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.