使用Ruby'捕捉ANSI彩色输出;s Open3/Process.spawn()

使用Ruby'捕捉ANSI彩色输出;s Open3/Process.spawn(),ruby,ansi-escape,Ruby,Ansi Escape,我正在使用sass lintNPM包对Rake任务中的.scss文件进行样式检查,因此: sass_lint_cmd = "sass-lint --config #{ui_library_path}/scss/.sass-lint.yml '#{ui_library_path}/scss/*.scss' -v -q --max-warnings=0" output, status = Open3.capture2e(sass_lint_cmd) raise IOError, outp

我正在使用
sass lint
NPM包对Rake任务中的
.scss
文件进行样式检查,因此:

  sass_lint_cmd = "sass-lint --config #{ui_library_path}/scss/.sass-lint.yml '#{ui_library_path}/scss/*.scss' -v -q --max-warnings=0"
  output, status = Open3.capture2e(sass_lint_cmd)
  raise IOError, output unless status == 0
这基本上是有效的,只要出现任何linter警告或错误,Rake任务就会中止,并且
sass lint
输出(包括错误)会转储到控制台

但是,当直接运行时,
sass lint
会产生漂亮的彩色输出。当被
capture2e
捕获时,颜色将丢失

我假设问题是
sass lint
(或节点)检测到它没有在TTY中运行,因此输出纯文本。是否有一些
Process.spawn()
选项可以传递到
Open3.capture2e()
,或者其他一些方法,通过这些方法我可以让它认为它正在TTY中运行

(注意:我确实看过,但是macOS附带的
脚本的BSD版本似乎不支持
--return
-c
选项,我正在macOS上运行。)


更新:我根据尝试了
脚本-q/dev/null
PTY.spawn()
,但没有成功

script-q/dev/null…
在命令行中工作,但在
Open3.capture2e()
中不工作(它运行,但产生单色输出和伪
Bundler::GemNotFound
堆栈跟踪)

对于
PTY.spawn()
,将上面的代码替换为以下代码:

r, _w, pid = PTY.spawn(scss_lint_command)
_, proc_status = Process.wait2(pid)
output, status = [r, proc_status.exitstatus]
(warn(output); raise) unless status == 0
子流程似乎永远不会完成;如果在另一个终端中I
ps
,则显示为可中断睡眠状态。终止子进程不会释放父进程

块形式也是如此

output, status = nil
PTY.spawn(scss_lint_command) do |r, _w, pid|
  _, proc_status = Process.wait2(pid)
  output, status = [r, proc_status.exitstatus]
end
(warn(output); raise) unless status == 0

您是否考虑过使用Ruby的优秀库而不是
Open3

伪终端,per,似乎模拟了一个实际的TTY,因此脚本不会知道它不在终端中,除非它检查像
$TERM
这样的东西,但是这也可以相对容易地被欺骗

根据,使用
pty
而不是
Open3
的缺点是
STDERR
没有自己的流


或者,根据,也可以从您链接的线程中,
script-q/dev/null$命令
在Mac OS X上执行此操作

在Mac电脑上,
ls-G
ls
的输出着色,作为一个简单的测试,我将
ls-G
导入
cat
,如下所示:

script -q /dev/null ls -G | cat
它以颜色显示,而只是运行

ls -G | cat
没有

该方法也适用于
irb
,再次使用
ls-G

$ touch regular_file
$ touch executable_file
$ mkdir directory
$ chmod +x executable_file
$ irb
2.4.1 :001 > require 'Open3'
 => true
2.4.1 :002 > output, status = Open3.capture2e("ls -G")
 => ["directory\nexecutable_file\nregular_file\n", #<Process::Status: pid 39299 exit 0>]
2.4.1 :003 > output, status = Open3.capture2e("script -q /dev/null ls -G")
 => ["^D\b\b\e[1m\e[36mdirectory\e[39;49m\e[0m       \e[31mexecutable_file\e[39;49m\e[0m regular_file\r\n", #<Process::Status: pid 39301 exit 0>]
2.4.1 :004 >
$touch常规\u文件
$touch可执行文件
$mkdir目录
$chmod+x可执行文件
$irb
2.4.1:001>要求“Open3”
=>正确
2.4.1:002>输出,状态=Open3.capture2e(“ls-G”)
=>[“目录\n可执行的\n常规\n文件”,#]
2.4.1:003>输出,状态=Open3.capture2e(“脚本-q/dev/null ls-G”)
=>[“^D\b\b\e[1m\e[36M目录\e[39;49m\e[0m\e[31mexecutable\U文件\e[39;49m\e[0m常规\r\n”,#]
2.4.1 :004 >

尝试了这两种方法,但都没有成功。:(请参阅更新。但我可能没有正确调用
PTY.spawn()
/
Process.wait2()
。@DavidMoles-Hmm,不确定
脚本-q/dev/null…
不起作用,但让我看看是否能找出你的
PTY.spawn()有什么问题)
ing.@DavidMoles我试着运行以下命令:
lines=[];PTY.spawn(“ls-G&&sleep 5”){reader,writer,pid{reader。如果将
script-q…
命令行导入
cat,那么每一行代码都可以从命令行运行?