robustify Ansi module a bit

This commit is contained in:
Josh Holtrop 2018-11-12 21:50:16 -05:00
parent 7869d38dd8
commit 88fd4bd405
2 changed files with 123 additions and 26 deletions

View File

@ -3,6 +3,8 @@ module Rscons
module Ansi module Ansi
class << self class << self
RESET = "\e[0m"
# Write a message to an IO with ANSI escape codes. # Write a message to an IO with ANSI escape codes.
# #
# @param io [IO] # @param io [IO]
@ -17,27 +19,57 @@ module Rscons
do_color = do_ansi?(io) do_color = do_ansi?(io)
end end
out = "" out = ""
if do_color
current_color = RESET
desired_color = RESET
message.each do |m|
if m.is_a?(String)
lines = m.split("\n", -1)
lines.each_with_index do |line, i|
if line != ""
if current_color != desired_color
out += desired_color
current_color = desired_color
end
out += line
end
if i < lines.size - 1
# A newline follows
if current_color != RESET
out += RESET
current_color = RESET
end
out += "\n"
end
end
else
case m
when :red; desired_color = "\e[0;31m"
when :green; desired_color = "\e[0;32m"
when :yellow; desired_color = "\e[0;33m"
when :blue; desired_color = "\e[0;34m"
when :magenta; desired_color = "\e[0;35m"
when :cyan; desired_color = "\e[0;36m"
when :white; desired_color = "\e[0;37m"
when :boldred; desired_color = "\e[1;31m"
when :boldgreen; desired_color = "\e[1;32m"
when :boldyellow; desired_color = "\e[1;33m"
when :boldblue; desired_color = "\e[1;34m"
when :boldmagenta; desired_color = "\e[1;35m"
when :boldcyan; desired_color = "\e[1;36m"
when :boldwhite; desired_color = "\e[1;37m"
when :bold; desired_color = "\e[1m"
when :reset; desired_color = RESET
end
end
end
if current_color != RESET
out += RESET
end
else
message.each do |m| message.each do |m|
if m.is_a?(String) if m.is_a?(String)
out += m out += m
elsif do_color
case m
when :red
out += "\e[0;31m"
when :green
out += "\e[0;32m"
when :yellow
out += "\e[0;33m"
when :blue
out += "\e[0;34m"
when :magenta
out += "\e[0;35m"
when :cyan
out += "\e[0;36m"
when :white
out += "\e[0;37m"
when :reset
out += "\e[0m"
end end
end end
end end

View File

@ -1,12 +1,79 @@
module Rscons module Rscons
describe Ansi do describe Ansi do
describe ".do_ansi?" do let(:io) {double}
describe ".write" do
context "when not doing color" do
before(:each) do
stub_const("RUBY_PLATFORM", "linux")
allow(io).to receive(:tty?).and_return(false)
end
it "skips color attributes and just writes the String arguments" do
expect(io).to receive(:write).with("line 1\nline 2\n")
Ansi.write(io, :bold, "line ", :red, "1\nline ", :boldblue, "2", "\n")
end
end
context "when doing color" do
before(:each) do
stub_const("RUBY_PLATFORM", "linux")
allow(io).to receive(:tty?).and_return(true)
end
it "writes the expected ANSI escape codes" do
expect(io).to receive(:write).with("\e[1mline \e[0;31m1\e[0m\n\e[0;31mline \e[1;34m2\e[0m\n")
Ansi.write(io, :bold, "line ", :red, "1\nline ", :boldblue, "2", "\n")
end
it "ends with a reset sequence" do
expect(io).to receive(:write).with("\e[1;33mbold yellow\e[0m")
Ansi.write(io, :boldyellow, "bold yellow")
end
it "does not write a color sequence when it would be overwritten" do
expect(io).to receive(:write).with("\e[1;36mBOLD CYAN\e[0m\n")
Ansi.write(io, :boldyellow, :boldcyan, "BOLD CYAN\n")
end
it "uses the correct escape sequences for all colors" do
expect(io).to receive(:write).with("\e[0;31mHI\e[0m")
Ansi.write(io, :red, "HI")
expect(io).to receive(:write).with("\e[0;32mHI\e[0m")
Ansi.write(io, :green, "HI")
expect(io).to receive(:write).with("\e[0;33mHI\e[0m")
Ansi.write(io, :yellow, "HI")
expect(io).to receive(:write).with("\e[0;34mHI\e[0m")
Ansi.write(io, :blue, "HI")
expect(io).to receive(:write).with("\e[0;35mHI\e[0m")
Ansi.write(io, :magenta, "HI")
expect(io).to receive(:write).with("\e[0;36mHI\e[0m")
Ansi.write(io, :cyan, "HI")
expect(io).to receive(:write).with("\e[0;37mHI\e[0m")
Ansi.write(io, :white, "HI")
expect(io).to receive(:write).with("\e[1;31mHI\e[0m")
Ansi.write(io, :boldred, "HI")
expect(io).to receive(:write).with("\e[1;32mHI\e[0m")
Ansi.write(io, :boldgreen, "HI")
expect(io).to receive(:write).with("\e[1;33mHI\e[0m")
Ansi.write(io, :boldyellow, "HI")
expect(io).to receive(:write).with("\e[1;34mHI\e[0m")
Ansi.write(io, :boldblue, "HI")
expect(io).to receive(:write).with("\e[1;35mHI\e[0m")
Ansi.write(io, :boldmagenta, "HI")
expect(io).to receive(:write).with("\e[1;36mHI\e[0m")
Ansi.write(io, :boldcyan, "HI")
expect(io).to receive(:write).with("\e[1;37mHI\e[0m")
Ansi.write(io, :boldwhite, "HI")
end
end
end
describe ".do_ansi?" do
context "on Windows" do context "on Windows" do
it "returns true when IO is a fifo on an xterm" do it "returns true when IO is a fifo on an xterm" do
stub_const("RUBY_PLATFORM", "mingw") stub_const("RUBY_PLATFORM", "mingw")
expect(ENV).to receive(:[]).with("TERM").and_return("xterm") expect(ENV).to receive(:[]).with("TERM").and_return("xterm")
io = double
expect(io).to receive(:stat).and_return(Struct.new(:ftype).new("fifo")) expect(io).to receive(:stat).and_return(Struct.new(:ftype).new("fifo"))
expect(Ansi.__send__(:do_ansi?, io)).to be_truthy expect(Ansi.__send__(:do_ansi?, io)).to be_truthy
end end
@ -14,7 +81,6 @@ module Rscons
it "returns false when TERM is not set appropriately" do it "returns false when TERM is not set appropriately" do
stub_const("RUBY_PLATFORM", "mingw") stub_const("RUBY_PLATFORM", "mingw")
expect(ENV).to receive(:[]).with("TERM").and_return(nil) expect(ENV).to receive(:[]).with("TERM").and_return(nil)
io = double
expect(Ansi.__send__(:do_ansi?, io)).to be_falsey expect(Ansi.__send__(:do_ansi?, io)).to be_falsey
end end
end end
@ -22,12 +88,11 @@ module Rscons
context "on POSIX" do context "on POSIX" do
it "returns true when IO is a TTY" do it "returns true when IO is a TTY" do
stub_const("RUBY_PLATFORM", "linux") stub_const("RUBY_PLATFORM", "linux")
io = double
expect(io).to receive(:tty?).and_return(true) expect(io).to receive(:tty?).and_return(true)
expect(Ansi.__send__(:do_ansi?, io)).to be_truthy expect(Ansi.__send__(:do_ansi?, io)).to be_truthy
end end
end end
end
end end
end end
end