Vimにフォーカスがないときにファイルを自動読み取りさせるにはどうすればよいですか?


29

私は、ファイルに書き込まれた出力の監視を含む、すべての種類(またはこの場合はgVim)にVImを使用しています。autoreadVimにファイルを再読み込みさせるために使用します。これは、キーボードフォーカスをファイルに切り替えるたびに行います。

キーボードフォーカスを切り替えなくても、Vimにバッファーを更新させる方法はありますか?設定を試みましたchecktimeが、キーボードフォーカスが他の場所にある間は効果がないようです。

私が監視している出力は、出力ファイルを完全に置き換えています。そして私はそれを見てtail -fいません。毎回新しいインスタンスにパイピングする、lessまたは何かにパイピングするなど、他のオプションがありますが、VImを使用して実行できればクールです。


@Carpetsmoker CursorHoldイベントはどうですか?Vimにフォーカスがない場合、n秒ごとにトリガーする必要があります。
ムル

1
@muruいいえ、CursorHold1回だけ実行されます。これは、「Vimからコーヒーを作るために「更新時間」ミリ秒ごとに起動するわけではありません。)
Martin Tournoij

1
もう一度gvimタグを削除しましたが、大丈夫だと思います;-)ご覧のとおり、この質問はgVim についてのものではありません。フォーカスの変更は、Vimがファイルが変更されたかどうかを確認するイベントの1つにすぎないためです詳細については私の回答をご覧ください)。すべてではありませんが、ほとんどの場合、これを改善する方法はVimとgVimの両方でうまく機能します。
マーティントゥルノイ

@Carpetsmokerああ、私はgVimがキーボードフォーカスを持っている間は定期的にチェックしているという印象を受けていました(そのためgVimの質問になりました)が、間違っていたようです。それを片付けてくれてありがとう。
ファルストロ

回答:


20

更新2015-06-25

  • 機能しすぎたため、「シェル」メソッドを廃止しました。挿入モードを停止し、ゾンビプロセスを残しました。とにかく見たいのであれば、この投稿の改訂履歴を見てください。
  • :私は、このうちのプラグインを作ったauto_autoread.vim。現時点では、以下のコードと事実上同じですが、更新を受け取る可能性が高いため、プラグインを使用することをお勧めします。

何をautoreadするの?

この質問に答えるにautoreadは、まずオプションが何をするのかを理解する必要があります。さらに重要なこと、何をしないのかを理解することです。

残念ながら:help 'autoread' 、これに関する多くの情報はありません。単に、「ファイルがVimの外部で変更されたことが検出された」というだけです。Vimはファイルが変更されたことをどのように検出しますか?特定のアクションで、Vimはファイルの変更時間をチェックします。

いつ:

  • :checktime 使用されている;
  • バッファに入ります。
  • :diffupdate 使用されている;
  • :e 既にバッファがあるファイルに対して発行されます。
  • !;で外部コマンドを実行する
  • (フォアグラウンドに戻って^Zfgシェルがジョブ制御を持っている場合のみ、);

gVimの場合、これは次の場合にも実行されます。

  • 「右クリック」メニューを閉じます(何かを選択するか、単に閉じます)。
  • フォーカスが変更されます(これは既に気づいていることです)。
  • メニューから「ファイル->開く」、「ファイル->名前を付けて保存」を使用した場合にポップアップ表示されるファイルブラウザダイアログを閉じます(その他の場所も同様)。

buf_check_timestamp()check_timestamps()関数、およびにneed_check_timestamps設定されてTRUEいる場所 へのすべての呼び出しを見つけることにより、Vimソースからこの情報を収集 しました。

私はいくつかのイベントを見逃しているかもしれませんが、覚えておくべき重要なことは、Vimはファイルが非常に限られた一連の状況で変更されたかどうかだけをチェックするということです。確かに、n秒ごとの変更に対してファイルを「ポーリング」することはありません。

だから、あなたの目的のためにset autoreadは、十分ではありません。

Pythonを使用する

これにより、Pythonスレッドがバックグラウンドで実行されるようにスケジュールされ、n:checktimeごとに実行さ れます。が有効になっている場合、これはディスクからバッファをリロードします。それ以外の場合は、単に警告します。autoread

これには、Vimが+pythonまたは+python3に必要です:version。すべてのプラットフォーム(Windowsを含む)で動作するはずです。

fun! AutoreadPython()
python << EOF
import time, vim
try: import thread
except ImportError: import _thread as thread # Py3

def autoread():
    vim.command('checktime')  # Run the 'checktime' command
    vim.command('redraw')     # Actually update the display

def autoread_loop():
    while True:
        time.sleep(1)
        autoread()

thread.start_new_thread(autoread_loop, ())
EOF
endfun

を使用してこれを開始でき:call AutoreadPython()ます。もちろん、autocmdでこれを行うことができます。例えば:

autocmd *.c call AutoreadPython()

あとがき

実際にはもっと多くのメソッドがあります。たとえばentr、Python inotifygaminモジュールなどのツールを使用してファイルの変更を監視し たり、:checktime引数が与えられていない場合はすべてのバッファーをチェックしたり、単一のバッファーをチェックしたり、特定のファイル。
しかし、この答えはすでにかなり長いです:-)これらの方法は、(願わくば!)ほとんどのシナリオでうまく機能するか、シナリオに簡単に適応できるはずです。

PS。私もRubyを使用しようとしましたが、残念ながらRubyスレッド(を使用Thread)はPythonのようにバックグラウンドで実行されないため、これを機能させることができませんでした(おそらく別の方法がありますか?)


2

バックグラウンドでバッファを非同期的に更新するために使用する小さなプラグインvim-autoreadを作成しtail -fました。これには明らかにVimバージョン8のジョブ機能が必要です。

を使用:AutoReadしてオンにし、:AutoRead!オフにします。


NeoVim互換バージョンは素晴らしいでしょう!
アンドリュー

@AndrewMacFieわかりません、なぜこれがNeovimで動作しないのでしょうか。
クリスチャンブラバンド

NeoVimでVim 8のジョブサポートが不足していると思いましたか?
アンドリュー

@AndrewMacFieおお、それはおそらく真実でしょう。私はneovimを使用していないため、NeoVimと互換性を持たせることはできません。しかし、PRは大歓迎です:)
クリスチャンブラバンド

十分に公平:)
アンドリュー

1

Neovimでは、tailコマンドを実行するターミナルバッファーを開く次のコマンドを使用できます。

:enew | call termopen('tail --follow=name --retry /path/to/file.log')

これは、ファイルが削除されて再作成されても機能し続けます。

または、以下を追加します $MYVIMRC

" :Tail /path/to/file
function! Tail(file)
  enew
  call termopen('tail --follow=name --retry ' . fnameescape(a:file))
endfunction
command! -nargs=1 Tail call Tail(<f-args>)

1

この回答から(PhanHaiQuangによる回答flukusによるコメントを参照

必要なときにex(whiminから)からこのonelinerを実行できます(または、ログファイルが開かれるときのために、vimrcに各コマンドを入力します)。

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

説明:
- 自動読み取り:外部から変更されたときにファイルを読み取ります(ただし、それ自体では機能せず、内部タイマーなどはありません。vimがexのコマンドのようにアクションを実行する場合にのみファイルを読み取ります:!
- CURSORHOLD * checktime:カーソルが「updatetime」を指定した時間のために、ユーザによって動かされていない(デフォルトは4000ミリ秒です)checktimeが実行され、ファイルの外部からの変更をチェック
- コールfeedkeys(「LH」):カーソルを左右に1回移動した後、何も起こりません(...つまり、CursorHoldがトリガーされ、ループがあることを意味します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.