ファイルへのリアルタイムの変更をvimで監視できます


104

私の質問は、テキストファイルをリアルタイムで監視する方法に似ています が、vimで実行したいと考えています。開いているファイル使用tail -f sample.xmlファイルを読み取ることができることはわかっています。新しいコンテンツがファイルに書き込まれると、新しいコンテンツも画面に書き込まれます。ファイルが更新されたときにvimに新しいデータを自動的に入力させることはできますか?

回答:


101

:set autoreadファイルが変更されたときにvimがファイルを読み取るようにすることができます。ただし(プラットフォームによって異なります)、それに焦点を当てる必要があります。

ヘルプから:

ファイルがVimの外部で変更されたことが検出され、Vimの内部で変更されていない場合は、自動的に再度読み取ります。ファイルが削除された場合、これは行われません。


5
ヒントをありがとう!これはかなり有望に見えますが、私のシステムでは機能しません:(MacVimでコンパイルされたvimバージョン7.2.303でMac10.6.2 iTermを使用しています。追加できるコメントはありますか?
Patrick

ええと、それはかなり奇妙です。macvim guiまたはターミナルバージョンを使用していますか?Macvim guiがプリコンパイルされてダウンロードされた状態で動作します。(ただし、前述のように、アプリをクリックしてフォーカスを当てる必要があります。)
Peter

1
ターミナルでテストしていたところ、gvim(MacVim GUI)を使用した後、関数が機能し始めました!あなたが言ったように、私はコンテンツを更新するためにgvimに集中する必要があります。集中しなくても更新するコツはありますか?再度ご協力いただきありがとうございます。
Patrick

3
残念ながら、その解決策はわかりません。vimがフォーカスを変更せずにそれを実行できるとしたら、私は驚かされるでしょう。vimがファイルシステムをポーリングして、いつ変更されたかを確認する必要があります。そのためのプラグインが必要だと思います。
Peter

2
@ピーター私しばらく前にそのようなプラグイン作りましたこの質問とそれに対する私の回答も参照してください。autoread動作とその制限についての詳細は、
Martin Tournoij 2016

63

自動についてはわかりませんが、次のように入力できます。

:e!

ファイルを再読み込みする


このアプローチはコンテンツを自動更新しませんが、更新されたコンテンツを表示します。ご回答有難うございます!
Patrick

31

以下をあなたの中に入れてください.vimrc

"通常モードで非アクティブ状態が4秒間続いた後、1回チェック
自動読み取りを設定する                                                                                                                                                                                    
au CursorHold * checktime                                                                                                                                                                       

すごい!最後にリロードしてからそのファイルを変更した場合は、警告が出てもうまく機能します。
zoujyjs 14

1
最初の答えは私にはうまくいきませんでしたが、これはうまくいきます!:-)
IonicăBizău

4
「4秒ごと」は正しくありません。これは、通常モードで4秒間非アクティブになった後、1回だけチェックします。したがって、別のバッファで長時間何もしないと、更新されませんが、カーソルを移動して4秒待つだけで更新されます。別のオプションは、手動で ":checktime"を呼び出して更新することです(自動読み取りの設定後)。残念ながら、vimにはポーリングのサポートはありません。そのため、OPの質問に対する真の答えはありません。
David Ljung Madison Stellar

1
ちょうどこれに遭遇しました。checktimeを変更してカスタム関数を呼び出し、関数の最後に「call feedkeys( "lh")」を追加すると、4秒ごとに実行されます。
flukus 2016年

@DavidLjungMadisonあなたは正しい、私はこの間違いを避けるために投稿を編集するつもりです
ファン

9

@flukusがにコメントして言ったように、以前の回答することができますcall feedkeys["lh"](これは、ログファイルを表示するときにnormaly害をしない、左、右、背面にカーソルを移動します)

したがって、残りの答えを組み合わせると、必要に応じてex(whimin vim)から実行できるonelinerがあります。

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


(ファイルの終わりに(ほぼ)ジャンプする場合は、フィードキーで「lh」の代わりに「G」を使用します)

説明:
- 自動読取りは:なし内部タイマまたはそのようなものは存在しない、外部から変更されたファイルを読み込む(が、それは自分自身で作業をdoesntのそれは唯一のvimを元にコマンドのように、アクションを実行し、ファイルを読み込みます。:!
- CURSORHOLD * checktime:カーソルが「updatetime」を指定した時間のために、ユーザによって動かされていない(デフォルトは4000ミリ秒です)checktimeが実行され、ファイルの外部からの変更をチェック
- コールfeedkeys(「LH」):カーソルが1回右、左に移動し、その後何も起こりません(つまり、CursorHoldがトリガーされます。つまり、ループが発生します)。

さらに:set syntax=logtalk、ログに色を付けることができます

を使用しているときにスクロールを停止するにはcall feedkeys("G")、次を実行します:set noautoread-ファイルが変更されたことをvimが通知し、変更を読み取りたいかどうかを尋ねます)

(これには副作用がありますか?)

編集:副作用が1つあります。フィードキーに「G」を使用すると、現在開いているすべてのバッファを下にスクロールしますか。したがって、右側のバッファにログファイルを自動的にスクロールさせながら、スプリットウィンドウの左側のバッファで作業することはできません


4

これを.vimrcに貼り付ければ、ボスのように機能するはずです。(以下から取得http : //vim.wikia.com/wiki/Have_Vim_check_automatically_if_the_file_has_changed_externally

" 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
これは、端末の自動読み取りの欠点に対処するための推奨される回答です。
mcanfield

3
@mcanfieldいいえ、これはまだ「変更を監視」しないためです。あなたはまだ Vimをアクティブにする必要があり、それはまだ限られた一連のイベントをポーリングしています(見ていません)。一度CursorHold実行さます。したがって、外に出てコーヒーを飲んだり、別のウィンドウで何かをしている場合は更新されません
Martin Tournoij 2016

4
このスクリプトは、Vimプラグインvim-autoreadとしてもバンドルされています。
stephen.hanson

1
@ stephen.hansonリンクをありがとう、そのプラグインは私にとってうまく機能しています!
Tropilio


2

unix + neovimの場合

:term tail -f <filename>

明らかにこれは誰にとってもうまくいくわけではありませんが、私がそうする方法です。



0

VIMは、ファイルが更新されたときに警告を表示し、ファイルを開いてから行われた変更を上書きしないようにします。その時点でファイルをリロードするように求められます。


1
回答ありがとうございます。システムでファイルが変更されたときにvimは警告を表示しませんでした:(
Patrick
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.