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)
プラグインから使うプラグインとして、お使い下さい。
setbuf はライブラリ依存なので実行するランタイムに依存します。