以前Open3.popen3で外部コマンドの出力を随時受け取って表示するということをやったけど、それでは不便な場面が出てきた。
というのも、例えばgrepでマッチした部分を色付けしたものを得ようとしてもOpen3.popen3
で受け取ることはできない。これはgrepが出力先がttyのときだけ色付けするようになっているのに対して、Open3.popen3
のやりとりにttyが使われていないことが原因らしい。((出力先のIOがttyかどうかはrubyだとIO#tty?
で調べられる。))
正直ttyってなんなのかわからないけど、とりあえずPTY.spawn
を使うと擬似ttyをruby上に作ったうえで外部コマンドとやりとりできるとのことがわかったのでやってみた。
require "pty" PTY.spawn("long-long-command") do |r, w, pid| # rはコマンドの出力IO。標準出力と標準エラーの両方が同じところから出てくる # wはコマンドへの書き込みIO w.close_write r.sync = true begin r.each do |line| next if line.nil? || line.empty? puts line rescue Errno::EIO ensure ::Process.wait pid end end
ちなみにknife-soloでの変更点などの出力の色付けは出力先がttyでないと行われないんだけど、それを裏で叩いているpaknifeではOpen3.popen3
を使っているため色付けされない。
なので色付けされた出力を得ようとPTY.spawn
を使うようにしてみたんだけど、一部分だけが色づくだけで変更箇所などは色付けされないので、どこが原因かまだ探っているところだ。