Skip to content

Instantly share code, notes, and snippets.

@ayosec
Created January 6, 2022 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ayosec/67522ae0c9f7b773c860babf9b5783c1 to your computer and use it in GitHub Desktop.
Save ayosec/67522ae0c9f7b773c860babf9b5783c1 to your computer and use it in GitHub Desktop.
Launch a program and remove bright colors from its output.
#!/usr/bin/ruby
CHILD_CMD = ARGV.dup
# If either stdout or stderr is not a TTY, executes the program with no color
# translation.
if !STDOUT.tty? or !STDERR.tty?
exec(*CHILD_CMD)
end
# Map bright colors to the default color..
COLOR_TABLE = {
"1" => "0",
"38;5;9" => "31",
"38;5;09" => "31",
"38;5;10" => "32",
"38;5;11" => "33",
"38;5;12" => "34",
"38;5;13" => "35",
"38;5;14" => "36",
"38;5;15" => "0",
"90" => "30",
"91" => "31",
"92" => "32",
"93" => "33",
"94" => "34",
"95" => "35",
"96" => "36",
"97" => "30",
}
require "pty"
require "io/console"
# Launch the program in a new TTY.
master, slave = PTY.open
master.winsize = STDOUT.winsize
pid = fork do
STDIN.reopen("/dev/null")
STDOUT.reopen(slave)
STDERR.reopen(slave)
exec(*CHILD_CMD)
end
slave.close
# Forward signals
trap "TERM" do
Process.kill("TERM", pid)
end
trap "SIGWINCH" do
master.winsize = STDOUT.winsize
end
# Main loop.
#
# Read up to 1024 bytes from the TTY, and replace colors (CSI color m) if they
# are found in COLOR_TABLE.
#
# If a sequence is at the end of the input it may be incomplete. In such case,
# it will not be replaced. This should be very unlikely for most CLI programs.
loop do
begin
line = master.
readpartial(1024).
gsub(/\e\[([0-9;]+?)m/) { "\e[#{COLOR_TABLE[$1] || $1}m" }
print line
rescue Errno::EIO
break
rescue Interrupt
Process.kill("INT", pid)
puts
end
end
Process.waitpid(pid)
exit $?.exitstatus || 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment