Bir dosyadaki gerçek zamanlı değişiklikleri izleyebilir miyim


104

Sorum buna benzer bir metin dosyasını gerçek zamanlı olarak nasıl izlerim ama bunu vim'de yapmak istiyorum. Açılmış bir dosya kullanım tail -f sample.xmldosyasını okuyabildiğimi biliyorum ve dosyaya yeni içerik yazıldığında, yeni içeriği de ekranıma yazacak. Bir dosya güncellendiğinde vim'in yeni verileri otomatik olarak doldurmasını sağlayabilir miyim?

Yanıtlar:


101

:set autoreadVim'in değiştiğinde dosyayı okuması için yapabilirsiniz . Ancak (platformunuza bağlı olarak), ona odaklanmanız gerekir.

Yardımdan:

Bir dosyanın Vim dışında değiştirildiği tespit edildiğinde ve Vim içinde değiştirilmediğinde, otomatik olarak tekrar okuyun. Dosya silindiğinde bu yapılmaz.


5
İpucu için teşekkürler! Bu oldukça umut verici görünüyor, ancak sistemimde çalışmıyor :( Mac10.6.2 iTerm'i MacVim ile derlenmiş vim sürüm 7.2.303 ile kullanıyorum. Deneyebileceğim ek bir yorum var mı?
Patrick

erm, bu oldukça tuhaf. macvim gui mi yoksa terminal sürümünü mü kullanıyorsunuz? önceden derlenmiş olarak indirilen macvim gui ile benim için çalışıyor. (Yine de bahsettiğim gibi, odaklanmak için uygulamaya tıklamam gerekiyor.)
Peter

1
Terminalde test ediyordum, gvim'i (MacVim GUI) kullandıktan sonra fonksiyon çalışmaya başladı! Yine de bahsettiğiniz gibi, içeriği güncellemek için gvim'e odaklanmam gerekiyor. Odaklanmadan bile güncellemek için herhangi bir numaranız var mı? Yardımlarınız için tekrar teşekkürler.
Patrick

3
Maalesef bunun bir çözümünü bilmiyorum. Eğer vim bunu odak değişikliği olmadan yapabilseydi şaşırırdım - değiştiğini görmek için dosya sistemini yoklaması vim'e ihtiyaç duyar. Bunun için bir eklentiye ihtiyacınız olduğunu düşünüyorum.
Peter

2
@Peter Bir süre önce böyle bir eklenti yaptım . Ayrıca bu soruyu ve cevabımı da görün . nasıl autoreadçalıştığı ve sınırlamaları hakkında daha fazla ayrıntı için .
Martin Tournoij

63

Otomatik olarak bilmiyorum, ancak yazabilirsiniz:

:e!

dosyayı yeniden yüklemek için


Bu yaklaşım içeriği otomatik olarak güncellemese de, güncellenen içeriği görüntüler. Cevabınız için teşekkürler!
Patrick

31

Aşağıdakileri sayfanıza koyun .vimrc:

"normal modda 4 saniye işlem yapılmadığında bir kez kontrol et
otomatik okumayı ayarla                                                                                                                                                                                    
au CursorHold * kontrol süresi                                                                                                                                                                       

Harika! Son yeniden yüklemeden sonra o dosyayı değiştirmiş olsanız bile bir uyarı olsa bile iyi çalışır.
zoujyjs

1
İlk cevap benim için işe yaramadı, ama bu işe yarıyor! :-)
Ionică Bizău

4
"Her 4 saniyede" doğru değil. Bu, normal modda 4 saniye hareketsizlikten sonra yalnızca bir kez kontrol edecektir . Yani başka bir arabellekte uzun süre hiçbir şey yapmazsanız, güncellenmez, ancak imleci hareket ettirip 4 saniye beklerseniz güncellenir. Diğer bir seçenek de güncellemek için manuel olarak ": checktime" çağırmaktır (otomatik okumayı ayarladıktan sonra). Maalesef vim'de herhangi bir anket desteği yok gibi görünüyor, bu nedenle OP'lerin sorusuna gerçek bir cevap yok.
David Ljung Madison Stellar

1
Şimdi bununla karşılaştım. Özel bir işlevi çağırmak için denetim zamanını değiştirirseniz ve işlevin sonuna "çağrı besleme tuşları (" lh ")" eklerseniz, her 4 saniyede bir tetiklenir.
2016

@DavidLjungMadison haklısınız, bu hatadan kaçınmak için gönderiyi düzenleyeceğim
Phan Hai Quang

9

@flukus'un bir önceki cevap için yapabileceğiniz bir yorumda söylediği gibi call feedkeys["lh"](imleci sağa ve sola hareket ettirir, bu normalde bir günlük dosyasını görüntülerken zarar vermez)

Öyleyse, cevabın geri kalanını birleştirirseniz, gerektiğinde ex (whithin vim) 'den çalıştırabileceğiniz bir onelineriniz olur:

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


(Dosyanın sonuna (neredeyse) atlamak istiyorsanız, feed anahtarlarıyla "lh" yerine "G" kullanın)

Açıklama:
- otomatik okuma : hayır iç zamanlayıcı ya da böyle bir şey yoktur, dışarıdan değişti dosyasını okur (ama kendi başına doesnt iş sadece vim eski bir komutla gibi bir eylem yapar dosyayı okuyacak. :!
- CursorHold * checktime : imleç kullanıcı tarafından 'güncellemesüresi'nde (varsayılan olarak 4000 milisaniyedir) belirtilen süre boyunca hareket ettirilmediğinde, kontrol zamanı yürütülür, bu da dosyanın dışından değişiklikleri kontrol eder
- besleme anahtarlarını ("lh") çağırır : imleç bir kez, sağa ve sola hareket eder ve sonra hiçbir şey olmaz (... bu, CursorHold'un tetiklendiği anlamına gelir, yani bir döngümüz var )

Ek olarak :set syntax=logtalk, günlüğü renklendirebilirsiniz

Kullanırken kaydırmayı durdurmak için call feedkeys("G") , çalıştır :set noautoread- şimdi vim, dosyanın değiştiğini söyleyecek ve değişiklikleri okumak isteyip istemediğini sor)

(Bunun herhangi bir yan etkisi var mı?)

Düzenleme: Bir yan etki görüyorum: biri besleme anahtarı olarak "G" kullanırsa, o anda açık olan her arabelleği aşağı kaydıracak mı ?! Bu nedenle, sağ arabellek otomatik olarak bir günlük dosyasını aşağı kaydırırken bölme penceresinin sol arabelleğinde çalışmak mümkün değildir.


4

Bunu .vimrc dosyanıza yapıştırın ve patron gibi çalışmalıdır. (Http://vim.wikia.com/wiki/Have_Vim_check_automatically_if_the_file_has_changed_externally adresinden alınmıştır )

" Function to Watch for changes if buffer changed on disk
function! WatchForChanges(bufname, ...)
  " Figure out which options are in effect
  if a:bufname == '*'
    let id = 'WatchForChanges'.'AnyBuffer'
    " If you try to do checktime *, you'll get E93: More than one match for * is given
    let bufspec = ''
  else
    if bufnr(a:bufname) == -1
      echoerr "Buffer " . a:bufname . " doesn't exist"
      return
    end
    let id = 'WatchForChanges'.bufnr(a:bufname)
    let bufspec = a:bufname
  end
  if len(a:000) == 0
    let options = {}
  else
    if type(a:1) == type({})
      let options = a:1
    else
      echoerr "Argument must be a Dict"
    end
  end
  let autoread    = has_key(options, 'autoread')    ? options['autoread']    : 0
  let toggle      = has_key(options, 'toggle')      ? options['toggle']      : 0
  let disable     = has_key(options, 'disable')     ? options['disable']     : 0
  let more_events = has_key(options, 'more_events') ? options['more_events'] : 1
  let while_in_this_buffer_only = has_key(options, 'while_in_this_buffer_only') ? options['while_in_this_buffer_only'] : 0
  if while_in_this_buffer_only
    let event_bufspec = a:bufname
  else
    let event_bufspec = '*'
  end
  let reg_saved = @"
  "let autoread_saved = &autoread
  let msg = "\n"
  " Check to see if the autocommand already exists
  redir @"
    silent! exec 'au '.id
  redir END
  let l:defined = (@" !~ 'E216: No such group or event:')
  " If not yet defined...
  if !l:defined
    if l:autoread
      let msg = msg . 'Autoread enabled - '
      if a:bufname == '*'
        set autoread
      else
        setlocal autoread
      end
    end
    silent! exec 'augroup '.id
      if a:bufname != '*'
        "exec "au BufDelete    ".a:bufname . " :silent! au! ".id . " | silent! augroup! ".id
        "exec "au BufDelete    ".a:bufname . " :echomsg 'Removing autocommands for ".id."' | au! ".id . " | augroup! ".id
        exec "au BufDelete    ".a:bufname . " execute 'au! ".id."' | execute 'augroup! ".id."'"
      end
        exec "au BufEnter     ".event_bufspec . " :checktime ".bufspec
        exec "au CursorHold   ".event_bufspec . " :checktime ".bufspec
        exec "au CursorHoldI  ".event_bufspec . " :checktime ".bufspec
      " The following events might slow things down so we provide a way to disable them...
      " vim docs warn:
      "   Careful: Don't do anything that the user does
      "   not expect or that is slow.
      if more_events
        exec "au CursorMoved  ".event_bufspec . " :checktime ".bufspec
        exec "au CursorMovedI ".event_bufspec . " :checktime ".bufspec
      end
    augroup END
    let msg = msg . 'Now watching ' . bufspec . ' for external updates...'
  end
  " If they want to disable it, or it is defined and they want to toggle it,
  if l:disable || (l:toggle && l:defined)
    if l:autoread
      let msg = msg . 'Autoread disabled - '
      if a:bufname == '*'
        set noautoread
      else
        setlocal noautoread
      end
    end
    " Using an autogroup allows us to remove it easily with the following
    " command. If we do not use an autogroup, we cannot remove this
    " single :checktime command
    " augroup! checkforupdates
    silent! exec 'au! '.id
    silent! exec 'augroup! '.id
    let msg = msg . 'No longer watching ' . bufspec . ' for external updates.'
  elseif l:defined
    let msg = msg . 'Already watching ' . bufspec . ' for external updates'
  end
  echo msg
  let @"=reg_saved
endfunction

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

1
Bu, terminal otomatik okuma eksikliklerini gidermek için tercih edilen cevaptır.
mcanfield

3
@mcanfield Hayır değil, çünkü bu hala "değişiklikleri izlemiyor". Sen hala Vim aktif olması gerekir ve öyle hala olayların sınırlı bir sette yoklama (izlemiyor). CursorHoldbir kez çalıştırılır . Yani sen de gidip bir kahve ya da başka bir Pencerede bir şey yapıyorsun eğer değil güncelleme.
Martin Tournoij

4
Bu komut dosyası ayrıca bir Vim eklentisi olarak paketlenmiştir: vim-autoread .
stephen.hanson

1
@ stephen.hanson Bağlantı için teşekkürler, bu eklenti benim için iyi çalışıyor!
Tropilio


2

Unix + neovim ise

:term tail -f <filename>

Açıkçası bu herkes için işe yaramayacak ama ben böyle yapıyorum.



0

VIM, bir dosya güncellendiğinde, onu açtıktan sonra yapılan değişikliklerin üzerine yazmamanız için sizi uyaracaktır. Bu noktada, dosyayı yeniden yüklemenizi isteyecektir.


1
Cevabınız için teşekkürler, ancak sistemimde dosya değiştirildiğinde vim beni uyarmadı :(
Patrick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.