Skip to content

Instantly share code, notes, and snippets.

@ayosec
Created January 6, 2022 15:20
Show Gist options
  • Select an option

  • Save ayosec/67522ae0c9f7b773c860babf9b5783c1 to your computer and use it in GitHub Desktop.

Select an option

Save ayosec/67522ae0c9f7b773c860babf9b5783c1 to your computer and use it in GitHub Desktop.

Revisions

  1. ayosec created this gist Jan 6, 2022.
    93 changes: 93 additions & 0 deletions remove-bright-colors.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,93 @@
    #!/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