From 13c142a0cfd5b17514397dee0e0b713619bea6cf Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Sun, 26 Mar 2017 21:52:44 +0900 Subject: [PATCH 1/4] Refactor Colorize#surround This is one of the separations of #3925. Remove `surround` and rename `push` to `surround`, now `push` is derecated. (This reason is dscribed in https://github.com/crystal-lang/crystal/pull/3925#issuecomment-275852281) --- spec/std/colorize_spec.cr | 46 ++++++++++++++++------- src/colorize.cr | 78 ++++++++++++++++++++++++--------------- 2 files changed, 82 insertions(+), 42 deletions(-) diff --git a/spec/std/colorize_spec.cr b/spec/std/colorize_spec.cr index cd680317cdbe..0d3989f0f473 100644 --- a/spec/std/colorize_spec.cr +++ b/spec/std/colorize_spec.cr @@ -9,6 +9,14 @@ private def with_color_wrap(*args) with_color(*args).toggle(true) end +private class ColorizeToS + def to_s(io) + io << "hello" + io << "world".colorize.blue + io << "bye" + end +end + describe "colorize" do it "colorizes without change" do colorize("hello").to_s.should eq("hello") @@ -121,44 +129,56 @@ describe "colorize" do colorize("hello", :red).inspect.should eq("\e[31m\"hello\"\e[0m") end - it "colorizes io with method" do + it "colorizes with surround" do io = IO::Memory.new with_color_wrap.red.surround(io) do io << "hello" + with_color.green.surround(io) do + io << "world" + end + io << "bye" end - io.to_s.should eq("\e[31mhello\e[0m") + io.to_s.should eq("\e[31mhello\e[0;32mworld\e[0;31mbye\e[0m") end - it "colorizes io with symbol" do + it "colorizes with surround and reset" do io = IO::Memory.new - with_color_wrap(:red).surround(io) do + with_color_wrap.red.surround(io) do io << "hello" + with_color_wrap.green.bold.surround(io) do + io << "world" + end + io << "bye" end - io.to_s.should eq("\e[31mhello\e[0m") + io.to_s.should eq("\e[31mhello\e[0;32;1mworld\e[0;31mbye\e[0m") end - it "colorizes with push and pop" do + it "colorizes with surround and no reset" do io = IO::Memory.new - with_color_wrap.red.push(io) do + with_color_wrap.red.surround(io) do io << "hello" - with_color_wrap.green.push(io) do + with_color_wrap.red.surround(io) do io << "world" end io << "bye" end - io.to_s.should eq("\e[31mhello\e[0;32mworld\e[0;31mbye\e[0m") + io.to_s.should eq("\e[31mhelloworldbye\e[0m") end - it "colorizes with push and pop resets" do + it "colorizes with surround and default" do io = IO::Memory.new - with_color_wrap.red.push(io) do + with_color_wrap.red.surround(io) do io << "hello" - with_color_wrap.green.bold.push(io) do + with_color_wrap.surround(io) do io << "world" end io << "bye" end - io.to_s.should eq("\e[31mhello\e[0;32;1mworld\e[0;31mbye\e[0m") + io.to_s.should eq("\e[31mhello\e[0mworld\e[31mbye\e[0m") + end + + it "colorizes with to_s" do + ColorizeToS.new.colorize.red.to_s.should eq("\e[31mhello\e[0;34mworld\e[0;31mbye\e[0m") end it "toggles off" do diff --git a/src/colorize.cr b/src/colorize.cr index 1e18a2d9c906..06aa2bb2d0c3 100644 --- a/src/colorize.cr +++ b/src/colorize.cr @@ -296,64 +296,88 @@ struct Colorize::Object(T) end def surround(io = STDOUT) - must_append_end = append_start(io) - yield io - append_end(io) if must_append_end - end + return yield io unless @enabled - STACK = [] of Colorize::Object(String) + Object.surround(io, to_named_tuple) do |io| + yield io + end + end + # DEPRECATED: Use `#surround`. def push(io = STDOUT) - last_color = STACK.last? - - append_start(io, !!last_color) + {{ puts "Warning: `Colorize::Object#push` is deprecated and will be removed, use `Colorize::Object#surround` instead".id }} + surround(io) { |io| yield io } + end - STACK.push self - yield io - STACK.pop + private def to_named_tuple + { + fore: @fore, + back: @back, + mode: @mode, + } + end - if last_color - last_color.append_start(io, true) - else - append_end(io) + @@last_color = { + fore: ColorANSI::Default.as(Color), + back: ColorANSI::Default.as(Color), + mode: 0, + } + + protected def self.surround(io, color) + last_color = @@last_color + must_append_end = append_start(io, color) + @@last_color = color + + begin + yield io + ensure + append_start(io, last_color) if must_append_end + @@last_color = last_color end end - protected def append_start(io, reset = false) - return false unless @enabled + private def self.append_start(io, color) + last_color_is_default = + @@last_color[:fore] == ColorANSI::Default && + @@last_color[:back] == ColorANSI::Default && + @@last_color[:mode] == 0 + + fore = color[:fore] + back = color[:back] + mode = color[:mode] - fore_is_default = @fore == ColorANSI::Default - back_is_default = @back == ColorANSI::Default - mode_is_default = @mode == 0 + fore_is_default = fore == ColorANSI::Default + back_is_default = back == ColorANSI::Default + mode_is_default = mode == 0 - if fore_is_default && back_is_default && mode_is_default && !reset + if fore_is_default && back_is_default && mode_is_default && last_color_is_default || @@last_color == color false else io << "\e[" printed = false - if reset + unless last_color_is_default io << MODE_DEFAULT printed = true end unless fore_is_default io << ';' if printed - @fore.fore io + fore.fore io printed = true end unless back_is_default io << ';' if printed - @back.back io + back.back io printed = true end unless mode_is_default # Can't reuse MODES constant because it has bold/bright duplicated {% for name in %w(bold dim underline blink reverse hidden) %} - if @mode.bits_set? MODE_{{name.upcase.id}}_FLAG + if mode.bits_set? MODE_{{name.upcase.id}}_FLAG io << ';' if printed io << MODE_{{name.upcase.id}} printed = true @@ -366,8 +390,4 @@ struct Colorize::Object(T) true end end - - protected def append_end(io) - Colorize.reset(io) - end end From dfa057fead1079691a59a1175ee65f120f3480a3 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Tue, 3 Apr 2018 23:47:09 +0900 Subject: [PATCH 2/4] Use #surround instead of #push --- src/compiler/crystal/tools/print_hierarchy.cr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/crystal/tools/print_hierarchy.cr b/src/compiler/crystal/tools/print_hierarchy.cr index 15d94f183d11..f789335ca966 100644 --- a/src/compiler/crystal/tools/print_hierarchy.cr +++ b/src/compiler/crystal/tools/print_hierarchy.cr @@ -27,7 +27,7 @@ module Crystal compute_targets(@program.types, exp, false) end - with_color.light_gray.bold.push(STDOUT) do + with_color.light_gray.bold.surround(STDOUT) do print_type @program.object end end @@ -126,7 +126,7 @@ module Crystal if (type.is_a?(NonGenericClassType) || type.is_a?(GenericClassInstanceType)) && !type.is_a?(PointerInstanceType) && !type.is_a?(ProcInstanceType) size = @llvm_typer.size_of(@llvm_typer.llvm_struct_type(type)) - with_color.light_gray.push(STDOUT) do + with_color.light_gray.surround(STDOUT) do print " (" print size.to_s print " bytes)" @@ -176,7 +176,7 @@ module Crystal print " " end - with_color.light_gray.push(STDOUT) do + with_color.light_gray.surround(STDOUT) do print name.ljust(max_name_size) print " : " print var @@ -211,13 +211,13 @@ module Crystal print " " end - with_color.light_gray.push(STDOUT) do + with_color.light_gray.surround(STDOUT) do print ivar.name.ljust(max_name_size) print " : " if ivar_type = ivar.type? print ivar_type.to_s.ljust(max_type_size) size = @llvm_typer.size_of(@llvm_typer.llvm_embedded_type(ivar_type)) - with_color.light_gray.push(STDOUT) do + with_color.light_gray.surround(STDOUT) do print " (" print size.to_s.rjust(max_bytes_size) print " bytes)" From e68515c74539aa1e1768fbc85d3b6de14bb47033 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Wed, 4 Apr 2018 00:38:56 +0900 Subject: [PATCH 3/4] Apply 'crystal tool format' --- src/colorize.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/colorize.cr b/src/colorize.cr index 06aa2bb2d0c3..ffb8a1f30e1e 100644 --- a/src/colorize.cr +++ b/src/colorize.cr @@ -338,7 +338,7 @@ struct Colorize::Object(T) private def self.append_start(io, color) last_color_is_default = - @@last_color[:fore] == ColorANSI::Default && + @@last_color[:fore] == ColorANSI::Default && @@last_color[:back] == ColorANSI::Default && @@last_color[:mode] == 0 From ea1dea0c86755a64acc09db1b302e0b629cd1ff1 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Thu, 5 Apr 2018 22:01:50 +0900 Subject: [PATCH 4/4] Remove Colorize#push --- src/colorize.cr | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/colorize.cr b/src/colorize.cr index ffb8a1f30e1e..11db372574e1 100644 --- a/src/colorize.cr +++ b/src/colorize.cr @@ -303,12 +303,6 @@ struct Colorize::Object(T) end end - # DEPRECATED: Use `#surround`. - def push(io = STDOUT) - {{ puts "Warning: `Colorize::Object#push` is deprecated and will be removed, use `Colorize::Object#surround` instead".id }} - surround(io) { |io| yield io } - end - private def to_named_tuple { fore: @fore,