diff options
-rw-r--r-- | Rakefile | 2 | ||||
-rw-r--r-- | lib/highline.rb | 49 | ||||
-rw-r--r-- | lib/highline/color_scheme.rb | 3 | ||||
-rw-r--r-- | lib/highline/style.rb | 90 | ||||
-rw-r--r-- | test/tc_style.rb | 528 | ||||
-rw-r--r-- | test/ts_all.rb | 2 |
6 files changed, 608 insertions, 66 deletions
@@ -12,7 +12,7 @@ task :default => [:test] Rake::TestTask.new do |test| test.libs << "test" - test.test_files = [ "test/ts_all.rb", "test/tc_string_extension.rb"] + test.test_files = [ "test/ts_all.rb"] test.verbose = true end diff --git a/lib/highline.rb b/lib/highline.rb index 19b6cd3..3c8a2c3 100644 --- a/lib/highline.rb +++ b/lib/highline.rb @@ -50,6 +50,13 @@ class HighLine @@use_color end + # For checking if the current version of HighLine supports RGB colors + # Usage: HighLine.supports_rgb_color? rescue false # rescue for compatibility with older versions + # Note: color usage also depends on HighLine.use_color being set + def self.supports_rgb_color? + true + end + # The setting used to disable EOF tracking. @@track_eof = true @@ -86,37 +93,37 @@ class HighLine # done before the program exits! # - ERASE_LINE_STYLE = Style.new(:name=>'erase_line', :code=>"\e[K") # Erase the current line of terminal output - ERASE_CHAR_STYLE = Style.new(:name=>'erase_char', :code=>"\e[P") # Erase the character under the cursor. - CLEAR_STYLE = Style.new(:name=>'clear', :code=>"\e[0m") # Clear color settings - RESET_STYLE = Style.new(:name=>'reset', :code=>"\e[0m") # Alias for CLEAR. - BOLD_STYLE = Style.new(:name=>'bold', :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect, + ERASE_LINE_STYLE = Style.new(:name=>:erase_line, :builtin=>true, :code=>"\e[K") # Erase the current line of terminal output + ERASE_CHAR_STYLE = Style.new(:name=>:erase_char, :builtin=>true, :code=>"\e[P") # Erase the character under the cursor. + CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings + RESET_STYLE = Style.new(:name=>:reset, :builtin=>true, :code=>"\e[0m") # Alias for CLEAR. + BOLD_STYLE = Style.new(:name=>:bold, :builtin=>true, :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect, # for example bold black. Bold without a color displays # the system-defined bold color (e.g. red on Mac iTerm) - DARK_STYLE = Style.new(:name=>'dark', :code=>"\e[2m") # Dark; support uncommon - UNDERLINE_STYLE = Style.new(:name=>'underline', :code=>"\e[4m") # Underline - UNDERSCORE_STYLE = Style.new(:name=>'underscore', :code=>"\e[4m") # Alias for UNDERLINE - BLINK_STYLE = Style.new(:name=>'blink', :code=>"\e[5m") # Blink; support uncommon - REVERSE_STYLE = Style.new(:name=>'reverse', :code=>"\e[7m") # Reverse foreground and background - CONCEALED_STYLE = Style.new(:name=>'concealed', :code=>"\e[8m") # Concealed; support uncommon + DARK_STYLE = Style.new(:name=>:dark, :builtin=>true, :code=>"\e[2m") # Dark; support uncommon + UNDERLINE_STYLE = Style.new(:name=>:underline, :builtin=>true, :code=>"\e[4m") # Underline + UNDERSCORE_STYLE = Style.new(:name=>:underscore, :builtin=>true, :code=>"\e[4m") # Alias for UNDERLINE + BLINK_STYLE = Style.new(:name=>:blink, :builtin=>true, :code=>"\e[5m") # Blink; support uncommon + REVERSE_STYLE = Style.new(:name=>:reverse, :builtin=>true, :code=>"\e[7m") # Reverse foreground and background + CONCEALED_STYLE = Style.new(:name=>:concealed, :builtin=>true, :code=>"\e[8m") # Concealed; support uncommon STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED} # These RGB colors are approximate; see http://en.wikipedia.org/wiki/ANSI_escape_code - BLACK_STYLE = Style.new(:name=>'black', :code=>"\e[30m", :rgb=>[ 0, 0, 0]) - RED_STYLE = Style.new(:name=>'red', :code=>"\e[31m", :rgb=>[128, 0, 0]) - GREEN_STYLE = Style.new(:name=>'green', :code=>"\e[32m", :rgb=>[ 0,128, 0]) - BLUE_STYLE = Style.new(:name=>'blue', :code=>"\e[34m", :rgb=>[ 0, 0,128]) - YELLOW_STYLE = Style.new(:name=>'yellow', :code=>"\e[33m", :rgb=>[128,128, 0]) - MAGENTA_STYLE = Style.new(:name=>'magenta', :code=>"\e[35m", :rgb=>[128, 0,128]) - CYAN_STYLE = Style.new(:name=>'cyan', :code=>"\e[36m", :rgb=>[ 0,128,128]) + BLACK_STYLE = Style.new(:name=>:black, :builtin=>true, :code=>"\e[30m", :rgb=>[ 0, 0, 0]) + RED_STYLE = Style.new(:name=>:red, :builtin=>true, :code=>"\e[31m", :rgb=>[128, 0, 0]) + GREEN_STYLE = Style.new(:name=>:green, :builtin=>true, :code=>"\e[32m", :rgb=>[ 0,128, 0]) + BLUE_STYLE = Style.new(:name=>:blue, :builtin=>true, :code=>"\e[34m", :rgb=>[ 0, 0,128]) + YELLOW_STYLE = Style.new(:name=>:yellow, :builtin=>true, :code=>"\e[33m", :rgb=>[128,128, 0]) + MAGENTA_STYLE = Style.new(:name=>:magenta, :builtin=>true, :code=>"\e[35m", :rgb=>[128, 0,128]) + CYAN_STYLE = Style.new(:name=>:cyan, :builtin=>true, :code=>"\e[36m", :rgb=>[ 0,128,128]) # On Mac OSX Terminal, white is actually gray - WHITE_STYLE = Style.new(:name=>'white', :code=>"\e[37m", :rgb=>[192,192,192]) + WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) # Alias for WHITE, since WHITE is actually a light gray on Macs - GRAY_STYLE = Style.new(:name=>'gray', :code=>"\e[37m", :rgb=>[192,192,192]) + GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192]) # On Mac OSX Terminal, this is black foreground, or bright white background. # Also used as base for RGB colors, if available - NONE_STYLE = Style.new(:name=>'none', :code=>"\e[38m", :rgb=>[ 0, 0, 0]) + NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0]) BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY NONE} diff --git a/lib/highline/color_scheme.rb b/lib/highline/color_scheme.rb index ead095b..3148bd0 100644 --- a/lib/highline/color_scheme.rb +++ b/lib/highline/color_scheme.rb @@ -73,7 +73,8 @@ class HighLine # Allow the scheme to be set like a Hash. def []=( color_tag, constants ) - @scheme[to_symbol(color_tag)] = constants.map { |c| to_constant(c) } + # @scheme[to_symbol(color_tag)] = constants.map { |c| to_constant(c) } + @scheme[to_symbol(color_tag)] = HighLine::Style.new(:name=>color_tag.to_sym, :list=>constants, :no_index=>true) end private diff --git a/lib/highline/style.rb b/lib/highline/style.rb index 7b4a354..22cebc5 100644 --- a/lib/highline/style.rb +++ b/lib/highline/style.rb @@ -7,6 +7,7 @@ # # This is Free Software. See LICENSE and COPYING for details +# TODO Re-engineer this to not use hashie/mash require 'rubygems' require 'hashie/mash' require 'pp' @@ -14,30 +15,29 @@ require 'pp' class HighLine def self.Style(*args) - args = args.flatten + args = args.compact.flatten if args.size==1 arg = args.first if arg.is_a?(Style) - name = arg.name - Style.list[name] || Style.new(arg) + Style.list[arg.name] || Style.index(arg) elsif arg.is_a?(::String) && arg =~ /^\e\[/ # arg is a code - if style = Style.code_index[arg] - style + if styles = Style.code_index[arg] + styles.first else - Style.new(:name=>'_code_'+arg[2..-1].gsub(/\W+/,'_'), :code=>arg) + Style.new(:code=>arg) end - elsif style = Style.list[arg.to_s.downcase] + elsif style = Style.list[arg] style elsif HighLine.color_scheme && HighLine.color_scheme[arg] - Style(HighLine.color_scheme[arg]) + HighLine.color_scheme[arg] elsif arg.is_a?(Hash) Style.new(arg) - elsif arg.to_s.downcase =~ /^rgb_(\d{6})$/ + elsif arg.to_s.downcase =~ /^rgb_([a-f0-9]{6})$/ Style.rgb($1) - elsif arg.to_s.downcase =~ /^on_rgb_(\d{6})$/ + elsif arg.to_s.downcase =~ /^on_rgb_([a-f0-9]{6})$/ Style.rgb($1).on else - raise NameError, "Don't know how to convert #{arg.inspect} to a Style" + raise NameError, "#{arg.inspect} is not a defined Style" end else name = args @@ -47,15 +47,16 @@ class HighLine class Style < Hashie::Mash - def self.define(style) - name = style.name.to_s.downcase - @@styles ||= {} - @@styles[name] ||= Style.new(nil, nil, :no_define=>true) - @@styles[name].merge! style + def self.index(style) + if style.name + @@styles ||= {} + @@styles[style.name] = style + end if !style.list? @@code_index ||= {} - @@code_index[style.code] ||= Style.new(nil, nil, :no_define=>true) - @@code_index[style.code].merge! style + @@code_index[style.code] ||= [] + @@code_index[style.code].reject!{|indexed_style| indexed_style.name == style.name} + @@code_index[style.code] << style end style end @@ -72,16 +73,20 @@ class HighLine def self.rgb(*colors) hex = rgb_hex(*colors) - name = 'rgb_' + hex + name = ('rgb_' + hex).to_sym if style = list[name] style else parts = rgb_parts(hex) - rgb_number = 16 + parts.inject(0) {|kode, part| kode*6 + (part/256.0*6.0).floor} - new(:name=>name, :code=>"\e[38;5;#{rgb_number}m", :rgb=>parts) + new(:name=>name, :code=>"\e[38;5;#{rgb_number(parts)}m", :rgb=>parts) end end + def self.rgb_number(*parts) + parts = parts.flatten + 16 + parts.inject(0) {|kode, part| kode*6 + (part/256.0*6.0).floor} + end + def self.list @@styles ||= {} end @@ -99,16 +104,16 @@ class HighLine # For a style (like :blink): name, code # For a compound style (like :underline, :red): list - def initialize(hsh = nil, default = nil, options={}, &blk) - super(hsh, default, &blk) + def initialize(defn = {}, default=nil, &blk) + super if rgb hex = self.class.rgb_hex(rgb) rgb = self.class.rgb_parts(hex) - name ||= 'rgb_' + hex - else - name ||= list + self.name ||= 'rgb_' + hex + elsif list? + self.name ||= list end - self.class.define self unless options[:no_define] + self.class.index self unless defn[:no_index] end def color(string) @@ -135,31 +140,30 @@ class HighLine rgb && rgb[2] end - def bumped(name, increment) - new_style = self.dup - new_style.name = name - raise "Unexpected code in #{self.inspect}" unless code =~ /^(.*?)(\d+)(.*)/ - new_style.code = $1 + ($2.to_i + increment).to_s + $3 - self.class.define new_style + def variant(new_name, options={}) + raise "Cannot create a variant of a style list (#{inspect})" if list? + new_code = options[:code] || code + if options[:increment] + raise "Unexpected code in #{inspect}" unless new_code =~ /^(.*?)(\d+)(.*)/ + new_code = $1 + ($2.to_i + options[:increment]).to_s + $3 + end + new_rgb = options[:rgb] || rgb + new_style = self.class.new(self.to_hash.merge(:name=>new_name, :code=>new_code, :rgb=>new_rgb)) end def on - new_name = 'on_'+name - self.class.list[new_name] ||= bumped(new_name, 10) + new_name = ('on_'+name.to_s).to_sym + self.class.list[new_name] ||= variant(new_name, :increment=>10) end def bright - new_name = 'bright_'+name + raise "Cannot create a bright variant of a style list (#{inspect})" if list? + new_name = ('bright_'+name.to_s).to_sym if style = self.class.list[new_name] style else - new_style = bumped(new_name, 60) - if self.rgb == [0,0,0] - new_style.rgb = [128, 128, 128] - else - new_style.rgb = self.rgb.map {|color| color==0 ? 0 : 255 } - end - new_style + new_rgb = rgb == [0,0,0] ? [128, 128, 128] : rgb.map {|color| color==0 ? 0 : [color+128,255].min } + variant(new_name, :increment=>60, :rgb=>new_rgb) end end end diff --git a/test/tc_style.rb b/test/tc_style.rb new file mode 100644 index 0000000..1e5fc2e --- /dev/null +++ b/test/tc_style.rb @@ -0,0 +1,528 @@ +#!/usr/local/bin/ruby -w + +# tc_style.rb +# +# Created by Richard LeBer on 2011-06-11. +# +# This is Free Software. See LICENSE and COPYING for details. + +require "test/unit" + +require "highline" +require "stringio" + +class TestStyle < Test::Unit::TestCase + + def setup + @input = StringIO.new + @output = StringIO.new + @terminal = HighLine.new(@input, @output) + @style1 = HighLine::Style.new(:name=>:foo, :code=>"\e[99m", :rgb=>[1,2,3]) + @style2 = HighLine::Style.new(:name=>:lando, :code=>"\e[98m") + @style3 = HighLine::Style.new(:name=>[:foo, :lando], :list=>[:foo, :lando]) + @style4 = HighLine::Style(:rgb_654321) + end + + def teardown + # HighLine::Style.clear_index + end + + def test_style_method + # Retrieve a style from an existing Style (no new Style created) + new_style = @style1.dup # This will replace @style1 in the indexes + s = HighLine.Style(@style1) + assert_instance_of HighLine::Style, s + assert_same new_style, s # i.e. s===the latest style created, but not the one searched for + + # Retrieve a style from a new Style (no new Style created) + s2 = HighLine::Style.new(:name=>:bar, :code=>"\e[97m") + s = HighLine.Style(s2) + assert_instance_of HighLine::Style, s + assert_same s2, s + + # Create a builtin style from an existing ANSI escape string + s = HighLine.Style("\e[1m") + assert_instance_of HighLine::Style, s + assert_nil s.list + assert_equal "\e[1m", s.code + assert_equal :bold, s.name + + # Create a builtin style from a new ANSI escape string + s = HighLine.Style("\e[96m") + assert_instance_of HighLine::Style, s + assert_nil s.list + assert_equal "\e[96m", s.code + + # Create a builtin style from a symbol + s = HighLine.Style(:red) + assert_instance_of HighLine::Style, s + assert_nil s.list + assert_equal :red, s.name + + # Retrieve an existing style by name (no new Style created) + s = HighLine.Style(@style2.name) + assert_instance_of HighLine::Style, s + assert_same @style2, s + + # See below for color scheme tests + + # Create style from a Hash + s = HighLine.Style(:name=>:han, :code=>"blah", :rgb=>'phooey') + assert_instance_of HighLine::Style, s + assert_equal :han, s.name + assert_equal "blah", s.code + assert_equal "phooey", s.rgb + + # Create style from an RGB foreground color code + s = HighLine.Style(:rgb_1f2e3d) + assert_instance_of HighLine::Style, s + assert_equal :rgb_1f2e3d, s.name + assert_equal "\e[38;5;23m", s.code # Trust me; more testing below + assert_equal [31,46,61], s.rgb # 0x1f==31, 0x2e==46, 0x3d=61 + + # Create style from an RGB background color code + s = HighLine.Style(:on_rgb_1f2e3d) + assert_instance_of HighLine::Style, s + assert_equal :on_rgb_1f2e3d, s.name + assert_equal "\e[48;5;23m", s.code # Trust me; more testing below + assert_equal [31,46,61], s.rgb # 0x1f==31, 0x2e==46, 0x3d=61 + + # Create a style list + s1 = HighLine.Style(:bold, :red) + assert_instance_of HighLine::Style, s1 + assert_equal [:bold, :red], s1.list + + # Find an existing style list + s2 = HighLine.Style(:bold, :red) + assert_instance_of HighLine::Style, s2 + assert_same s1, s2 + + # Create a style list with nils + s1 = HighLine.Style(:underline, nil, :blue) + assert_instance_of HighLine::Style, s1 + assert_equal [:underline, :blue], s1.list + + # Raise an error for an undefined style + assert_raise(::NameError) { HighLine.Style(:fubar) } + end + + def test_no_color_scheme + HighLine.color_scheme = nil + assert_raise(::NameError) { HighLine.Style(:critical) } + end + + def test_with_color_scheme + HighLine.color_scheme = HighLine::SampleColorScheme.new + s = HighLine.Style(:critical) + assert_instance_of HighLine::Style, s + assert_equal :critical, s.name + assert_equal [:yellow, :on_red], s.list + end + + def test_builtin_foreground_colors_defined + HighLine::COLORS.each do |color| + style = HighLine.const_get(color+'_STYLE') + assert_instance_of HighLine::Style, style + assert_equal color.downcase.to_sym, style.name + assert style.builtin + code = HighLine.const_get(color) + assert_instance_of String, code, "Bad code for #{color}" + end + end + + def test_builtin_background_colors_defined + HighLine::COLORS.each do |color| + style = HighLine.const_get('ON_' + color+'_STYLE') + assert_instance_of HighLine::Style, style + assert_equal ('ON_'+color).downcase.to_sym, style.name + assert style.builtin + code = HighLine.const_get('ON_' + color) + assert_instance_of String, code, "Bad code for ON_#{color}" + end + end + + def test_builtin_styles_defined + HighLine::STYLES.each do |style_constant| + style = HighLine.const_get(style_constant+'_STYLE') + assert_instance_of HighLine::Style, style + assert_equal style_constant.downcase.to_sym, style.name + assert style.builtin + code = HighLine.const_get(style_constant) + assert_instance_of String, code, "Bad code for #{style_constant}" + end + end + + def test_index + # Add a Style with a new name and code + assert_nil HighLine::Style.list[:s1] + assert_nil HighLine::Style.code_index['foo'] + s1 = HighLine::Style.new(:name=>:s1, :code=>'foo') + assert_not_nil HighLine::Style.list[:s1] + assert_same s1, HighLine::Style.list[:s1] + assert_equal :s1, HighLine::Style.list[:s1].name + assert_equal 'foo', HighLine::Style.list[:s1].code + styles = HighLine::Style.list.size + codes = HighLine::Style.code_index.size + assert_instance_of Array, HighLine::Style.code_index['foo'] + assert_equal 1, HighLine::Style.code_index['foo'].size + assert_same s1, HighLine::Style.code_index['foo'].last + assert_equal :s1, HighLine::Style.code_index['foo'].last.name + assert_equal 'foo', HighLine::Style.code_index['foo'].last.code + + # Add another Style with a new name and code + assert_nil HighLine::Style.list[:s2] + assert_nil HighLine::Style.code_index['bar'] + s2 = HighLine::Style.new(:name=>:s2, :code=>'bar') + assert_equal styles+1, HighLine::Style.list.size + assert_equal codes+1, HighLine::Style.code_index.size + assert_not_nil HighLine::Style.list[:s2] + assert_same s2, HighLine::Style.list[:s2] + assert_equal :s2, HighLine::Style.list[:s2].name + assert_equal 'bar', HighLine::Style.list[:s2].code + assert_instance_of Array, HighLine::Style.code_index['bar'] + assert_equal 1, HighLine::Style.code_index['bar'].size + assert_same s2, HighLine::Style.code_index['bar'].last + assert_equal :s2, HighLine::Style.code_index['bar'].last.name + assert_equal 'bar', HighLine::Style.code_index['bar'].last.code + + # Add a Style with an existing name + s3_before = HighLine::Style.list[:s2] + assert_not_nil HighLine::Style.list[:s2] + assert_nil HighLine::Style.code_index['baz'] + s3 = HighLine::Style.new(:name=>:s2, :code=>'baz') + assert_not_same s2, s3 + assert_not_same s3_before, s3 + assert_equal styles+1, HighLine::Style.list.size + assert_equal codes+2, HighLine::Style.code_index.size + assert_not_nil HighLine::Style.list[:s2] + assert_same s3, HighLine::Style.list[:s2] + assert_not_same s2, HighLine::Style.list[:s2] + assert_equal :s2, HighLine::Style.list[:s2].name + assert_equal 'baz', HighLine::Style.list[:s2].code + assert_instance_of Array, HighLine::Style.code_index['baz'] + assert_equal 1, HighLine::Style.code_index['baz'].size + assert_same s3, HighLine::Style.code_index['baz'].last + assert_equal :s2, HighLine::Style.code_index['baz'].last.name + assert_equal 'baz', HighLine::Style.code_index['baz'].last.code + + # Add a Style with an existing code + assert_equal 1, HighLine::Style.code_index['baz'].size + s4 = HighLine::Style.new(:name=>:s4, :code=>'baz') + assert_equal styles+2, HighLine::Style.list.size + assert_equal codes+2, HighLine::Style.code_index.size + assert_not_nil HighLine::Style.list[:s4] + assert_same s4, HighLine::Style.list[:s4] + assert_equal :s4, HighLine::Style.list[:s4].name + assert_equal 'baz', HighLine::Style.list[:s4].code + assert_equal 2, HighLine::Style.code_index['baz'].size + assert_same s3, HighLine::Style.code_index['baz'].first # Unchanged from last time + assert_equal :s2, HighLine::Style.code_index['baz'].first.name # Unchanged from last time + assert_equal 'baz', HighLine::Style.code_index['baz'].first.code # Unchanged from last time + assert_same s4, HighLine::Style.code_index['baz'].last + assert_equal :s4, HighLine::Style.code_index['baz'].last.name + assert_equal 'baz', HighLine::Style.code_index['baz'].last.code + end + + def test_rgb_hex + assert_equal "abcdef", HighLine::Style.rgb_hex("abcdef") + assert_equal "ABCDEF", HighLine::Style.rgb_hex("AB","CD","EF") + assert_equal "010203", HighLine::Style.rgb_hex(1,2,3) + assert_equal "123456", HighLine::Style.rgb_hex(18,52,86) + end + + def test_rgb_parts + assert_equal [1,2,3], HighLine::Style.rgb_parts("010203") + assert_equal [18,52,86], HighLine::Style.rgb_parts("123456") + end + + def test_rgb + s = HighLine::Style.rgb(1, 2, 3) + assert_instance_of HighLine::Style, s + assert_equal :rgb_010203, s.name + assert_equal [1,2,3], s.rgb + assert_equal "\e[38;5;16m", s.code + + s = HighLine::Style.rgb("12", "34","56") + assert_instance_of HighLine::Style, s + assert_equal :rgb_123456, s.name + assert_equal [0x12, 0x34, 0x56], s.rgb + assert_equal "\e[38;5;24m", s.code + + s = HighLine::Style.rgb("abcdef") + assert_instance_of HighLine::Style, s + assert_equal :rgb_abcdef, s.name + assert_equal [0xab, 0xcd, 0xef], s.rgb + assert_equal "\e[38;5;189m", s.code + end + + def test_rgb_number + # ANSI RGB coding splits 0..255 into equal sixths, and then the + # red green and blue are encoded in base 6, plus 16, i.e. + # 16 + 36*(red_level) + 6*(green_level) + blue_level, + # where each of red_level, green_level, and blue_level are in + # the range 0..5 + + # This test logic works because 42 is just below 1/6 of 255, + # and 43 is just above + + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 0, 0, 0) + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 0, 0, 42) + assert_equal 16 + 0*36 + 0*6 + 1, HighLine::Style.rgb_number( 0, 0, 43) + + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 0, 42, 0) + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 0, 42, 42) + assert_equal 16 + 0*36 + 0*6 + 1, HighLine::Style.rgb_number( 0, 42, 43) + + assert_equal 16 + 0*36 + 1*6 + 0, HighLine::Style.rgb_number( 0, 43, 0) + assert_equal 16 + 0*36 + 1*6 + 0, HighLine::Style.rgb_number( 0, 43, 42) + assert_equal 16 + 0*36 + 1*6 + 1, HighLine::Style.rgb_number( 0, 43, 43) + + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 42, 0, 0) + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 42, 0, 42) + assert_equal 16 + 0*36 + 0*6 + 1, HighLine::Style.rgb_number( 42, 0, 43) + + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 42, 42, 0) + assert_equal 16 + 0*36 + 0*6 + 0, HighLine::Style.rgb_number( 42, 42, 42) + assert_equal 16 + 0*36 + 0*6 + 1, HighLine::Style.rgb_number( 42, 42, 43) + + assert_equal 16 + 0*36 + 1*6 + 0, HighLine::Style.rgb_number( 42, 43, 0) + assert_equal 16 + 0*36 + 1*6 + 0, HighLine::Style.rgb_number( 42, 43, 42) + assert_equal 16 + 0*36 + 1*6 + 1, HighLine::Style.rgb_number( 42, 43, 43) + + assert_equal 16 + 1*36 + 0*6 + 0, HighLine::Style.rgb_number( 43, 0, 0) + assert_equal 16 + 1*36 + 0*6 + 0, HighLine::Style.rgb_number( 43, 0, 42) + assert_equal 16 + 1*36 + 0*6 + 1, HighLine::Style.rgb_number( 43, 0, 43) + + assert_equal 16 + 1*36 + 0*6 + 0, HighLine::Style.rgb_number( 43, 42, 0) + assert_equal 16 + 1*36 + 0*6 + 0, HighLine::Style.rgb_number( 43, 42, 42) + assert_equal 16 + 1*36 + 0*6 + 1, HighLine::Style.rgb_number( 43, 42, 43) + + assert_equal 16 + 1*36 + 1*6 + 0, HighLine::Style.rgb_number( 43, 43, 0) + assert_equal 16 + 1*36 + 1*6 + 0, HighLine::Style.rgb_number( 43, 43, 42) + assert_equal 16 + 1*36 + 1*6 + 1, HighLine::Style.rgb_number( 43, 43, 43) + + assert_equal 16 + 5*36 + 5*6 + 5, HighLine::Style.rgb_number(255,255,255) + end + + def test_list + list_size = HighLine::Style.list.size + # Add a Style with a new name and code + assert_nil HighLine::Style.list[:s5] + s5 = HighLine::Style.new(:name=>:s5, :code=>'foo') + assert_not_nil HighLine::Style.list[:s5] + assert_equal list_size+1, HighLine::Style.list.size + assert_not_nil HighLine::Style.list[:s5] + assert_same s5, HighLine::Style.list[:s5] + assert_equal :s5, HighLine::Style.list[:s5].name + assert_equal 'foo', HighLine::Style.list[:s5].code + + # Add another Style with a new name and code + assert_nil HighLine::Style.list[:s6] + s6 = HighLine::Style.new(:name=>:s6, :code=>'bar') + assert_equal list_size+2, HighLine::Style.list.size + assert_not_nil HighLine::Style.list[:s6] + assert_same s6, HighLine::Style.list[:s6] + assert_equal :s6, HighLine::Style.list[:s6].name + assert_equal 'bar', HighLine::Style.list[:s6].code + + # Add a Style with an existing name + s7 = HighLine::Style.new(:name=>:s6, :code=>'baz') + assert_equal list_size+2, HighLine::Style.list.size # No net addition to list + assert_not_nil HighLine::Style.list[:s6] + assert_same s7, HighLine::Style.list[:s6] # New one replaces old one + assert_not_same s6, HighLine::Style.list[:s6] + assert_equal :s6, HighLine::Style.list[:s6].name + assert_equal 'baz', HighLine::Style.list[:s6].code + end + + def test_code_index + list_size = HighLine::Style.code_index.size + + # Add a Style with a new name and code + assert_nil HighLine::Style.code_index['chewie'] + s8 = HighLine::Style.new(:name=>:s8, :code=>'chewie') + assert_equal list_size+1, HighLine::Style.code_index.size + assert_instance_of Array, HighLine::Style.code_index['chewie'] + assert_equal 1, HighLine::Style.code_index['chewie'].size + assert_equal :s8, HighLine::Style.code_index['chewie'].last.name + assert_equal 'chewie', HighLine::Style.code_index['chewie'].last.code + + # Add another Style with a new name and code + assert_nil HighLine::Style.code_index['c3po'] + s9 = HighLine::Style.new(:name=>:s9, :code=>'c3po') + assert_equal list_size+2, HighLine::Style.code_index.size + assert_instance_of Array, HighLine::Style.code_index['c3po'] + assert_equal 1, HighLine::Style.code_index['c3po'].size + assert_equal :s9, HighLine::Style.code_index['c3po'].last.name + assert_equal 'c3po', HighLine::Style.code_index['c3po'].last.code + + # Add a Style with an existing code + assert_equal 1, HighLine::Style.code_index['c3po'].size + s10 = HighLine::Style.new(:name=>:s10, :code=>'c3po') + assert_equal list_size+2, HighLine::Style.code_index.size + assert_equal 2, HighLine::Style.code_index['c3po'].size + assert_equal :s10, HighLine::Style.code_index['c3po'].last.name + assert_equal 'c3po', HighLine::Style.code_index['c3po'].last.code + end + + def test_uncolor + # Normal color + assert_equal "This should be reverse underlined magenta!\n", + HighLine::Style.uncolor("This should be \e[7m\e[4m\e[35mreverse underlined magenta\e[0m!\n" ) + + # RGB color + assert_equal "This should be rgb_906030!\n", + HighLine::Style.uncolor("This should be \e[38;5;137mrgb_906030\e[0m!\n" ) + end + + def test_color + assert_equal "\e[99mstring\e[0m", @style1.color("string") # simple style + assert_equal "\e[99m\e[98mstring\e[0m", @style3.color("string") # Style list + end + + def test_code + assert_equal "\e[99m", @style1.code # simple style + assert_equal "\e[99m\e[98m", @style3.code # Style list + end + + def test_red + assert_equal 0x65, @style4.red + assert_equal 0, HighLine::Style(:none).red # Probably reliable + assert_equal 0, HighLine::Style(:black).red # Probably reliable + assert_equal 255, HighLine::Style(:bright_magenta).red # Seems to be reliable + assert_equal 255, HighLine::Style(:on_none).red # Probably reliable + end + + def test_green + assert_equal 0x43, @style4.green + assert_equal 0, HighLine::Style(:none).green # Probably reliable + assert_equal 0, HighLine::Style(:black).green # Probably reliable + assert 240 <= HighLine::Style(:bright_cyan).green # Probably reliable + assert_equal 255, HighLine::Style(:on_none).green # Probably reliable + end + + def test_blue + assert_equal 0x21, @style4.blue + assert_equal 0, HighLine::Style(:none).blue # Probably reliable + assert_equal 0, HighLine::Style(:black).blue # Probably reliable + assert_equal 255, HighLine::Style(:bright_blue).blue # Probably reliable + assert_equal 255, HighLine::Style(:on_none).blue # Probably reliable + end + + def test_builtin + assert HighLine::Style(:red).builtin + assert !@style1.builtin + end + + def test_variant + style1_name = @style1.name + style1_code = @style1.code + style1_rgb = @style1.rgb + + s1 = @style1.variant(:new_foo1, :code=>'abracadabra') + assert_instance_of HighLine::Style, s1 + assert_not_same @style1, s1 # This is a copy + assert_equal :new_foo1, s1.name # Changed + assert_equal 'abracadabra', s1.code # Changed + assert_equal [1,2,3], s1.rgb # Unchanged + + s2 = @style1.variant(:new_foo2, :increment=>-15) + assert_instance_of HighLine::Style, s2 + assert_not_same @style1, s2 # This is a copy + assert_equal :new_foo2, s2.name # Changed + assert_equal "\e[84m", s2.code # 99 (original code) - 15 + assert_equal [1,2,3], s2.rgb # Unchanged + + s3 = @style1.variant(:new_foo3, :code=>"\e[55m", :increment=>15) + assert_instance_of HighLine::Style, s3 + assert_not_same @style1, s3 # This is a copy + assert_equal :new_foo3, s3.name # Changed + assert_equal "\e[70m", s3.code # 99 (new code) + 15 + assert_equal [1,2,3], s3.rgb # Unchanged + + s4 = @style1.variant(:new_foo4, :code=>"\e[55m", :increment=>15, :rgb=>"blah") + assert_instance_of HighLine::Style, s4 + assert_not_same @style1, s4 # This is a copy + assert_equal :new_foo4, s4.name # Changed + assert_equal "\e[70m", s4.code # 99 (new code) + 15 + assert_equal 'blah', s4.rgb # Changed + + s5 = @style1.variant(:new_foo5) + assert_instance_of HighLine::Style, s5 + assert_not_same @style1, s5 # This is a copy + assert_equal :new_foo5, s5.name # Changed + assert_equal "\e[99m", s5.code # Unchanged + assert_equal [1,2,3], s5.rgb # Unchanged + + # No @style1's have been harmed in the running of this test + assert_equal style1_name, @style1.name + assert_equal style1_code, @style1.code + assert_equal style1_rgb, @style1.rgb + + assert_raise(::RuntimeError) { @style3.variant(:new_foo6) } # Can't create a variant of a list style + end + + def test_on + style1_name = @style1.name + style1_code = @style1.code + style1_rgb = @style1.rgb + + s1 = @style1.on + assert_instance_of HighLine::Style, s1 + assert_not_same @style1, s1 # This is a copy + assert_equal :on_foo, s1.name # Changed + assert_equal "\e[109m", s1.code # Changed + assert_equal [1,2,3], s1.rgb # Unchanged + + # No @style1's have been harmed in the running of this test + assert_equal style1_name, @style1.name + assert_equal style1_code, @style1.code + assert_equal style1_rgb, @style1.rgb + + assert_raise(::RuntimeError) { @style3.on } # Can't create a variant of a list style + end + + def test_bright + style1_name = @style1.name + style1_code = @style1.code + style1_rgb = @style1.rgb + + s1 = @style1.bright + assert_instance_of HighLine::Style, s1 + assert_not_same @style1, s1 # This is a copy + assert_equal :bright_foo, s1.name # Changed + assert_equal "\e[159m", s1.code # Changed + assert_equal [129,130,131], s1.rgb # Changed + + # No @style1's have been harmed in the running of this test + assert_equal style1_name, @style1.name + assert_equal style1_code, @style1.code + assert_equal style1_rgb, @style1.rgb + + s2_base = HighLine::Style.new(:name=>:leia, :code=>"\e[92m", :rgb=>[0,0,14]) + s2 = s2_base.bright + assert_instance_of HighLine::Style, s2 + assert_not_same s2_base, s2 # This is a copy + assert_equal :bright_leia, s2.name # Changed + assert_equal "\e[152m", s2.code # Changed + assert_equal [0,0,142], s2.rgb # Changed + + s3_base = HighLine::Style.new(:name=>:luke, :code=>"\e[93m", :rgb=>[20,21,0]) + s3 = s3_base.bright + assert_instance_of HighLine::Style, s3 + assert_not_same s3_base, s3 # This is a copy + assert_equal :bright_luke, s3.name # Changed + assert_equal "\e[153m", s3.code # Changed + assert_equal [148,149,0], s3.rgb # Changed + + s4_base = HighLine::Style.new(:name=>:r2d2, :code=>"\e[94m", :rgb=>[0,0,0]) + s4 = s4_base.bright + assert_instance_of HighLine::Style, s4 + assert_not_same s4_base, s4 # This is a copy + assert_equal :bright_r2d2, s4.name # Changed + assert_equal "\e[154m", s4.code # Changed + assert_equal [128,128,128], s4.rgb # Changed; special case + + assert_raise(::RuntimeError) { @style3.bright } # Can't create a variant of a list style + end +end diff --git a/test/ts_all.rb b/test/ts_all.rb index 6b93b82..bd9665b 100644 --- a/test/ts_all.rb +++ b/test/ts_all.rb @@ -12,5 +12,7 @@ require "test/unit" require "tc_highline" require "tc_import" require "tc_menu" +require "tc_style" require "tc_color_scheme" require "tc_string_highline" +require "tc_string_extension"
\ No newline at end of file |