2017/08/21

Recent entries from same category

  1. VimConf 2023 Tiny に参加しました
  2. Vim で Go 言語を書くために行った引越し作業 2020年度版
  3. Vim をモダンな IDE に変える LSP の設定
  4. ぼくがかんがえたさいきょうの Vim のこうせい 2019年 年末版
  5. VimConf 2019 を終えて

Windows では子プロセスが出力した標準出力を読み取る際にバッファリングが行われる。これは親プロセスからは無効に出来ない。子プロセスが setbuf を呼び出してバッファを無効にするか、fflush で強制的にバッファをフラッシュする必要がある。

#include <windows.h>
#include <stdio.h>

int
main(int argc, char* argv[]) {
  int n = 0;
  while (1) {
    printf("%d", n++);
    Sleep(1000);
  }
  return 0;
}

Vim に job/channel 機能があるが、これらもこの入出力バッファのせいで改行されるまでの出力を読み取る事が出来ない。:terminal が取り込まれてインタラクティブなプロセスを制御できる様になったけど、Windows の :terminal は winpty を使って画面の要素を読み取って実行されている。なので標準出力そのものをリアルタイム読み取るという事は出来ない。そこで CreateRemoteThread を使ってプロセスに DLL インジェクションし、そこで setbuf を呼び出す物を作った。

GitHub - mattn/vim-iobuf

README.md vim-iobuf On Windows, stdout has a buffer. As you can see, this can be controllable with s...

https://github.com/mattn/vim-iobuf

これを使って以下の様に呼び出すと、子プロセスのバッファリングが無効にされ改行コードを出力しなくても channel を使って読み取る事が出来る。

let job = job_start(['.\\tick.exe'], {
\  'out_mode''raw'
\  'out_cb':{ch,msg->execute('echo msg'1)},
\  'exit_cb':{jo,st->execute('echo "exited"'1)
\}})
call iobuf#nobuffer(job)
iobuf

プラグインから使うプラグインとして、お使い下さい。

setbuf はライブラリ依存なので実行するランタイムに依存します。

Posted at by