highline 1.6.1 → 1.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/AUTHORS +3 -0
- data/CHANGELOG +76 -0
- data/COPYING +340 -0
- data/Rakefile +9 -41
- data/doc/.cvsignore +1 -0
- data/examples/ansi_colors.rb +1 -1
- data/examples/asking_for_arrays.rb +1 -1
- data/examples/basic_usage.rb +1 -1
- data/examples/menus.rb +1 -1
- data/examples/overwrite.rb +1 -1
- data/examples/page_and_wrap.rb +1 -1
- data/examples/password.rb +1 -1
- data/examples/repeat_entry.rb +21 -0
- data/examples/trapping_eof.rb +1 -1
- data/examples/using_readline.rb +1 -1
- data/highline.gemspec +36 -0
- data/lib/highline/color_scheme.rb +20 -4
- data/lib/highline/import.rb +0 -2
- data/lib/highline/menu.rb +7 -6
- data/lib/highline/question.rb +17 -7
- data/lib/highline/simulate.rb +48 -0
- data/lib/highline/string_extensions.rb +131 -0
- data/lib/highline/style.rb +181 -0
- data/lib/highline/system_extensions.rb +106 -100
- data/lib/highline.rb +406 -202
- data/site/.cvsignore +1 -0
- data/site/highline.css +65 -0
- data/site/images/logo.png +0 -0
- data/site/index.html +58 -0
- data/test/string_methods.rb +32 -0
- data/test/tc_color_scheme.rb +42 -2
- data/test/tc_highline.rb +215 -11
- data/test/tc_import.rb +0 -2
- data/test/tc_menu.rb +0 -2
- data/test/tc_string_extension.rb +20 -0
- data/test/tc_string_highline.rb +38 -0
- data/test/tc_style.rb +567 -0
- data/test/ts_all.rb +3 -2
- metadata +62 -52
- /data/{README → README.rdoc} +0 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/local/bin/ruby -w
|
|
2
|
-
|
|
3
1
|
# color_scheme.rb
|
|
4
2
|
#
|
|
5
3
|
# Created by Jeremy Hinegardner on 2007-01-24
|
|
@@ -70,11 +68,29 @@ class HighLine
|
|
|
70
68
|
def []( color_tag )
|
|
71
69
|
@scheme[to_symbol(color_tag)]
|
|
72
70
|
end
|
|
71
|
+
|
|
72
|
+
# Retrieve the original form of the scheme
|
|
73
|
+
def definition( color_tag )
|
|
74
|
+
style = @scheme[to_symbol(color_tag)]
|
|
75
|
+
style && style.list
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Retrieve the keys in the scheme
|
|
79
|
+
def keys
|
|
80
|
+
@scheme.keys
|
|
81
|
+
end
|
|
73
82
|
|
|
74
83
|
# Allow the scheme to be set like a Hash.
|
|
75
84
|
def []=( color_tag, constants )
|
|
76
|
-
@scheme[to_symbol(color_tag)] =
|
|
85
|
+
@scheme[to_symbol(color_tag)] = HighLine::Style.new(:name=>color_tag.to_s.downcase.to_sym,
|
|
86
|
+
:list=>constants, :no_index=>true)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Retrieve the color scheme hash (in original definition format)
|
|
90
|
+
def to_hash
|
|
91
|
+
@scheme.inject({}) { |hsh, pair| key, value = pair; hsh[key] = value.list; hsh }
|
|
77
92
|
end
|
|
93
|
+
|
|
78
94
|
|
|
79
95
|
private
|
|
80
96
|
|
|
@@ -86,7 +102,7 @@ class HighLine
|
|
|
86
102
|
# Return a normalized representation of a color setting.
|
|
87
103
|
def to_constant( v )
|
|
88
104
|
v = v.to_s if v.is_a?(Symbol)
|
|
89
|
-
if v.is_a?(String) then
|
|
105
|
+
if v.is_a?(::String) then
|
|
90
106
|
HighLine.const_get(v.upcase)
|
|
91
107
|
else
|
|
92
108
|
v
|
data/lib/highline/import.rb
CHANGED
data/lib/highline/menu.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/local/bin/ruby -w
|
|
2
|
-
|
|
3
1
|
# menu.rb
|
|
4
2
|
#
|
|
5
3
|
# Created by Gregory Thomas Brown on 2005-05-10.
|
|
@@ -178,7 +176,7 @@ class HighLine
|
|
|
178
176
|
@index = style
|
|
179
177
|
|
|
180
178
|
# Default settings.
|
|
181
|
-
if @index == :none or @index.is_a?(String)
|
|
179
|
+
if @index == :none or @index.is_a?(::String)
|
|
182
180
|
@index_suffix = " "
|
|
183
181
|
@select_by = :name
|
|
184
182
|
end
|
|
@@ -306,13 +304,14 @@ class HighLine
|
|
|
306
304
|
end
|
|
307
305
|
|
|
308
306
|
# Run or return it.
|
|
309
|
-
if not
|
|
307
|
+
if not action.nil?
|
|
310
308
|
@highline = highline_context
|
|
311
309
|
if @shell
|
|
312
|
-
action.call(name, details)
|
|
310
|
+
result = action.call(name, details)
|
|
313
311
|
else
|
|
314
|
-
action.call(name)
|
|
312
|
+
result = action.call(name)
|
|
315
313
|
end
|
|
314
|
+
@nil_on_handled ? nil : result
|
|
316
315
|
elsif action.nil?
|
|
317
316
|
name
|
|
318
317
|
else
|
|
@@ -388,6 +387,8 @@ class HighLine
|
|
|
388
387
|
:not_in_range =>
|
|
389
388
|
"Your answer isn't within the expected range " +
|
|
390
389
|
"(#{expected_range}).",
|
|
390
|
+
:mismatch =>
|
|
391
|
+
"Your entries didn't match.",
|
|
391
392
|
:not_valid =>
|
|
392
393
|
"Your answer isn't valid (must match " +
|
|
393
394
|
"#{@validate.inspect})."
|
data/lib/highline/question.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/local/bin/ruby -w
|
|
2
|
-
|
|
3
1
|
# question.rb
|
|
4
2
|
#
|
|
5
3
|
# Created by James Edward Gray II on 2005-04-26.
|
|
@@ -33,9 +31,9 @@ class HighLine
|
|
|
33
31
|
#
|
|
34
32
|
def initialize( question, answer_type )
|
|
35
33
|
# initialize instance data
|
|
36
|
-
@question = question
|
|
34
|
+
@question = question.dup
|
|
37
35
|
@answer_type = answer_type
|
|
38
|
-
|
|
36
|
+
|
|
39
37
|
@character = nil
|
|
40
38
|
@limit = nil
|
|
41
39
|
@echo = true
|
|
@@ -49,19 +47,20 @@ class HighLine
|
|
|
49
47
|
@in = nil
|
|
50
48
|
@confirm = nil
|
|
51
49
|
@gather = false
|
|
50
|
+
@verify_match = false
|
|
52
51
|
@first_answer = nil
|
|
53
52
|
@directory = Pathname.new(File.expand_path(File.dirname($0)))
|
|
54
53
|
@glob = "*"
|
|
55
54
|
@responses = Hash.new
|
|
56
55
|
@overwrite = false
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
# allow block to override settings
|
|
59
58
|
yield self if block_given?
|
|
60
59
|
|
|
61
60
|
# finalize responses based on settings
|
|
62
61
|
build_responses
|
|
63
62
|
end
|
|
64
|
-
|
|
63
|
+
|
|
65
64
|
# The ERb template of the question to be asked.
|
|
66
65
|
attr_accessor :question
|
|
67
66
|
# The type that will be used to convert this answer.
|
|
@@ -152,6 +151,12 @@ class HighLine
|
|
|
152
151
|
#
|
|
153
152
|
attr_accessor :gather
|
|
154
153
|
#
|
|
154
|
+
# When set to +true+ multiple entries will be collected according to
|
|
155
|
+
# the setting for _gather_, except they will be required to match
|
|
156
|
+
# each other. Multiple identical entries will return a single answer.
|
|
157
|
+
#
|
|
158
|
+
attr_accessor :verify_match
|
|
159
|
+
#
|
|
155
160
|
# When set to a non *nil* value, this will be tried as an answer to the
|
|
156
161
|
# question. If this answer passes validations, it will become the result
|
|
157
162
|
# without the user ever being prompted. Otherwise this value is discarded,
|
|
@@ -236,6 +241,8 @@ class HighLine
|
|
|
236
241
|
:not_in_range =>
|
|
237
242
|
"Your answer isn't within the expected range " +
|
|
238
243
|
"(#{expected_range}).",
|
|
244
|
+
:mismatch =>
|
|
245
|
+
"Your entries didn't match.",
|
|
239
246
|
:not_valid =>
|
|
240
247
|
"Your answer isn't valid (must match " +
|
|
241
248
|
"#{@validate.inspect})." }.merge(@responses)
|
|
@@ -289,6 +296,7 @@ class HighLine
|
|
|
289
296
|
# Pathname:: Same as File, save that a Pathname object is
|
|
290
297
|
# returned.
|
|
291
298
|
# String:: Answer is converted with Kernel.String().
|
|
299
|
+
# HighLine::String:: Answer is converted with HighLine::String()
|
|
292
300
|
# Regexp:: Answer is fed to Regexp.new().
|
|
293
301
|
# Symbol:: The method to_sym() is called on answer and
|
|
294
302
|
# the result returned.
|
|
@@ -301,6 +309,8 @@ class HighLine
|
|
|
301
309
|
def convert( answer_string )
|
|
302
310
|
if @answer_type.nil?
|
|
303
311
|
answer_string
|
|
312
|
+
elsif [::String, HighLine::String].include?(@answer_type)
|
|
313
|
+
HighLine::String(answer_string)
|
|
304
314
|
elsif [Float, Integer, String].include?(@answer_type)
|
|
305
315
|
Kernel.send(@answer_type.to_s.to_sym, answer_string)
|
|
306
316
|
elsif @answer_type == Symbol
|
|
@@ -329,7 +339,7 @@ class HighLine
|
|
|
329
339
|
end
|
|
330
340
|
end
|
|
331
341
|
|
|
332
|
-
# Returns
|
|
342
|
+
# Returns an English explanation of the current range settings.
|
|
333
343
|
def expected_range( )
|
|
334
344
|
expected = [ ]
|
|
335
345
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# simulate.rb
|
|
2
|
+
#
|
|
3
|
+
# Created by Andy Rossmeissl on 2012-04-29.
|
|
4
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# This is Free Software. See LICENSE and COPYING for details.
|
|
7
|
+
#
|
|
8
|
+
# adapted from https://gist.github.com/194554
|
|
9
|
+
class HighLine
|
|
10
|
+
|
|
11
|
+
# Simulates Highline input for use in tests.
|
|
12
|
+
class Simulate
|
|
13
|
+
|
|
14
|
+
# Creates a simulator with an array of Strings as a script
|
|
15
|
+
def initialize(strings)
|
|
16
|
+
@strings = strings
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Simulate StringIO#gets by shifting a string off of the script
|
|
20
|
+
def gets
|
|
21
|
+
@strings.shift
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Simulate StringIO#getbyte by shifting a single character off of the next line of the script
|
|
25
|
+
def getbyte
|
|
26
|
+
line = gets
|
|
27
|
+
if line.length > 0
|
|
28
|
+
char = line.slice! 0
|
|
29
|
+
@strings.unshift line
|
|
30
|
+
char
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The simulator handles its own EOF
|
|
35
|
+
def eof?
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A wrapper method that temporarily replaces the Highline instance in $terminal with an instance of this object for the duration of the block
|
|
40
|
+
def self.with(*strings)
|
|
41
|
+
@input = $terminal.instance_variable_get :@input
|
|
42
|
+
$terminal.instance_variable_set :@input, new(strings)
|
|
43
|
+
yield
|
|
44
|
+
ensure
|
|
45
|
+
$terminal.instance_variable_set :@input, @input
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Extensions for class String
|
|
2
|
+
#
|
|
3
|
+
# HighLine::String is a subclass of String with convenience methods added for colorization.
|
|
4
|
+
#
|
|
5
|
+
# Available convenience methods include:
|
|
6
|
+
# * 'color' method e.g. highline_string.color(:bright_blue, :underline)
|
|
7
|
+
# * colors e.g. highline_string.magenta
|
|
8
|
+
# * RGB colors e.g. highline_string.rgb_ff6000
|
|
9
|
+
# or highline_string.rgb(255,96,0)
|
|
10
|
+
# * background colors e.g. highline_string.on_magenta
|
|
11
|
+
# * RGB background colors e.g. highline_string.on_rgb_ff6000
|
|
12
|
+
# or highline_string.on_rgb(255,96,0)
|
|
13
|
+
# * styles e.g. highline_string.underline
|
|
14
|
+
#
|
|
15
|
+
# Additionally, convenience methods can be chained, for instance the following are equivalent:
|
|
16
|
+
# highline_string.bright_blue.blink.underline
|
|
17
|
+
# highline_string.color(:bright_blue, :blink, :underline)
|
|
18
|
+
# HighLine.color(highline_string, :bright_blue, :blink, :underline)
|
|
19
|
+
#
|
|
20
|
+
# For those less squeamish about possible conflicts, the same convenience methods can be
|
|
21
|
+
# added to the builtin String class, as follows:
|
|
22
|
+
#
|
|
23
|
+
# require 'highline'
|
|
24
|
+
# Highline.colorize_strings
|
|
25
|
+
|
|
26
|
+
class HighLine
|
|
27
|
+
def self.String(s)
|
|
28
|
+
HighLine::String.new(s)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module StringExtensions
|
|
32
|
+
def self.included(base)
|
|
33
|
+
HighLine::COLORS.each do |color|
|
|
34
|
+
base.class_eval <<-END
|
|
35
|
+
if public_instance_methods.map { |m| m.to_s }.
|
|
36
|
+
include? "#{color.downcase}"
|
|
37
|
+
undef :#{color.downcase}
|
|
38
|
+
end
|
|
39
|
+
def #{color.downcase}
|
|
40
|
+
color(:#{color.downcase})
|
|
41
|
+
end
|
|
42
|
+
END
|
|
43
|
+
base.class_eval <<-END
|
|
44
|
+
if public_instance_methods.map { |m| m.to_s }.
|
|
45
|
+
include? "on_#{color.downcase}"
|
|
46
|
+
undef :on_#{color.downcase}
|
|
47
|
+
end
|
|
48
|
+
def on_#{color.downcase}
|
|
49
|
+
on(:#{color.downcase})
|
|
50
|
+
end
|
|
51
|
+
END
|
|
52
|
+
HighLine::STYLES.each do |style|
|
|
53
|
+
base.class_eval <<-END
|
|
54
|
+
if public_instance_methods.map { |m| m.to_s }.
|
|
55
|
+
include? "#{style.downcase}"
|
|
56
|
+
undef :#{style.downcase}
|
|
57
|
+
end
|
|
58
|
+
def #{style.downcase}
|
|
59
|
+
color(:#{style.downcase})
|
|
60
|
+
end
|
|
61
|
+
END
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
base.class_eval do
|
|
66
|
+
if public_instance_methods.map { |m| m.to_s }.include? "color"
|
|
67
|
+
undef :color
|
|
68
|
+
end
|
|
69
|
+
if public_instance_methods.map { |m| m.to_s }.include? "foreground"
|
|
70
|
+
undef :foreground
|
|
71
|
+
end
|
|
72
|
+
def color(*args)
|
|
73
|
+
self.class.new(HighLine.color(self, *args))
|
|
74
|
+
end
|
|
75
|
+
alias_method :foreground, :color
|
|
76
|
+
|
|
77
|
+
if public_instance_methods.map { |m| m.to_s }.include? "on"
|
|
78
|
+
undef :on
|
|
79
|
+
end
|
|
80
|
+
def on(arg)
|
|
81
|
+
color(('on_' + arg.to_s).to_sym)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if public_instance_methods.map { |m| m.to_s }.include? "uncolor"
|
|
85
|
+
undef :uncolor
|
|
86
|
+
end
|
|
87
|
+
def uncolor
|
|
88
|
+
self.class.new(HighLine.uncolor(self))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if public_instance_methods.map { |m| m.to_s }.include? "rgb"
|
|
92
|
+
undef :rgb
|
|
93
|
+
end
|
|
94
|
+
def rgb(*colors)
|
|
95
|
+
color_code = colors.map{|color| color.is_a?(Numeric) ? '%02x'%color : color.to_s}.join
|
|
96
|
+
raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
|
|
97
|
+
color("rgb_#{color_code}".to_sym)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
if public_instance_methods.map { |m| m.to_s }.include? "on_rgb"
|
|
101
|
+
undef :on_rgb
|
|
102
|
+
end
|
|
103
|
+
def on_rgb(*colors)
|
|
104
|
+
color_code = colors.map{|color| color.is_a?(Numeric) ? '%02x'%color : color.to_s}.join
|
|
105
|
+
raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
|
|
106
|
+
color("on_rgb_#{color_code}".to_sym)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if public_instance_methods.map { |m| m.to_s }.include? "method_missing"
|
|
110
|
+
undef :method_missing
|
|
111
|
+
end
|
|
112
|
+
# TODO Chain existing method_missing
|
|
113
|
+
def method_missing(method, *args, &blk)
|
|
114
|
+
if method.to_s =~ /^(on_)?rgb_([0-9a-fA-F]{6})$/
|
|
115
|
+
color(method)
|
|
116
|
+
else
|
|
117
|
+
raise NoMethodError, "undefined method `#{method}' for #<#{self.class}:#{'%#x'%self.object_id}>"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class HighLine::String < ::String
|
|
125
|
+
include StringExtensions
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.colorize_strings
|
|
129
|
+
::String.send(:include, StringExtensions)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# color_scheme.rb
|
|
2
|
+
#
|
|
3
|
+
# Created by Richard LeBer on 2011-06-27.
|
|
4
|
+
# Copyright 2011. All rights reserved
|
|
5
|
+
#
|
|
6
|
+
# This is Free Software. See LICENSE and COPYING for details
|
|
7
|
+
|
|
8
|
+
class HighLine
|
|
9
|
+
|
|
10
|
+
def self.Style(*args)
|
|
11
|
+
args = args.compact.flatten
|
|
12
|
+
if args.size==1
|
|
13
|
+
arg = args.first
|
|
14
|
+
if arg.is_a?(Style)
|
|
15
|
+
Style.list[arg.name] || Style.index(arg)
|
|
16
|
+
elsif arg.is_a?(::String) && arg =~ /^\e\[/ # arg is a code
|
|
17
|
+
if styles = Style.code_index[arg]
|
|
18
|
+
styles.first
|
|
19
|
+
else
|
|
20
|
+
Style.new(:code=>arg)
|
|
21
|
+
end
|
|
22
|
+
elsif style = Style.list[arg]
|
|
23
|
+
style
|
|
24
|
+
elsif HighLine.color_scheme && HighLine.color_scheme[arg]
|
|
25
|
+
HighLine.color_scheme[arg]
|
|
26
|
+
elsif arg.is_a?(Hash)
|
|
27
|
+
Style.new(arg)
|
|
28
|
+
elsif arg.to_s.downcase =~ /^rgb_([a-f0-9]{6})$/
|
|
29
|
+
Style.rgb($1)
|
|
30
|
+
elsif arg.to_s.downcase =~ /^on_rgb_([a-f0-9]{6})$/
|
|
31
|
+
Style.rgb($1).on
|
|
32
|
+
else
|
|
33
|
+
raise NameError, "#{arg.inspect} is not a defined Style"
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
name = args
|
|
37
|
+
Style.list[name] || Style.new(:list=>args)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Style
|
|
42
|
+
|
|
43
|
+
def self.index(style)
|
|
44
|
+
if style.name
|
|
45
|
+
@@styles ||= {}
|
|
46
|
+
@@styles[style.name] = style
|
|
47
|
+
end
|
|
48
|
+
if !style.list
|
|
49
|
+
@@code_index ||= {}
|
|
50
|
+
@@code_index[style.code] ||= []
|
|
51
|
+
@@code_index[style.code].reject!{|indexed_style| indexed_style.name == style.name}
|
|
52
|
+
@@code_index[style.code] << style
|
|
53
|
+
end
|
|
54
|
+
style
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.rgb_hex(*colors)
|
|
58
|
+
colors.map do |color|
|
|
59
|
+
color.is_a?(Numeric) ? '%02x'%color : color.to_s
|
|
60
|
+
end.join
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.rgb_parts(hex)
|
|
64
|
+
hex.scan(/../).map{|part| part.to_i(16)}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.rgb(*colors)
|
|
68
|
+
hex = rgb_hex(*colors)
|
|
69
|
+
name = ('rgb_' + hex).to_sym
|
|
70
|
+
if style = list[name]
|
|
71
|
+
style
|
|
72
|
+
else
|
|
73
|
+
parts = rgb_parts(hex)
|
|
74
|
+
new(:name=>name, :code=>"\e[38;5;#{rgb_number(parts)}m", :rgb=>parts)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.rgb_number(*parts)
|
|
79
|
+
parts = parts.flatten
|
|
80
|
+
16 + parts.inject(0) {|kode, part| kode*6 + (part/256.0*6.0).floor}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.ansi_rgb_to_hex(ansi_number)
|
|
84
|
+
raise "Invalid ANSI rgb code #{ansi_number}" unless (16..231).include?(ansi_number)
|
|
85
|
+
parts = (ansi_number-16).to_s(6).rjust(3,'0').scan(/./).map{|d| (d.to_i*255.0/6.0).ceil}
|
|
86
|
+
rgb_hex(*parts)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.list
|
|
90
|
+
@@styles ||= {}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.code_index
|
|
94
|
+
@@code_index ||= {}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.uncolor(string)
|
|
98
|
+
string.gsub(/\e\[\d+(;\d+)*m/, '')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
attr_reader :name, :list
|
|
102
|
+
attr_accessor :rgb, :builtin
|
|
103
|
+
|
|
104
|
+
# Single color/styles have :name, :code, :rgb (possibly), :builtin
|
|
105
|
+
# Compound styles have :name, :list, :builtin
|
|
106
|
+
def initialize(defn = {})
|
|
107
|
+
@definition = defn
|
|
108
|
+
@name = defn[:name]
|
|
109
|
+
@code = defn[:code]
|
|
110
|
+
@rgb = defn[:rgb]
|
|
111
|
+
@list = defn[:list]
|
|
112
|
+
@builtin = defn[:builtin]
|
|
113
|
+
if @rgb
|
|
114
|
+
hex = self.class.rgb_hex(@rgb)
|
|
115
|
+
@name ||= 'rgb_' + hex
|
|
116
|
+
elsif @list
|
|
117
|
+
@name ||= @list
|
|
118
|
+
end
|
|
119
|
+
self.class.index self unless defn[:no_index]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def dup
|
|
123
|
+
self.class.new(@definition)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def to_hash
|
|
127
|
+
@definition
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def color(string)
|
|
131
|
+
code + string + HighLine::CLEAR
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def code
|
|
135
|
+
if @list
|
|
136
|
+
@list.map{|element| HighLine.Style(element).code}.join
|
|
137
|
+
else
|
|
138
|
+
@code
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def red
|
|
143
|
+
@rgb && @rgb[0]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def green
|
|
147
|
+
@rgb && @rgb[1]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def blue
|
|
151
|
+
@rgb && @rgb[2]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def variant(new_name, options={})
|
|
155
|
+
raise "Cannot create a variant of a style list (#{inspect})" if @list
|
|
156
|
+
new_code = options[:code] || code
|
|
157
|
+
if options[:increment]
|
|
158
|
+
raise "Unexpected code in #{inspect}" unless new_code =~ /^(.*?)(\d+)(.*)/
|
|
159
|
+
new_code = $1 + ($2.to_i + options[:increment]).to_s + $3
|
|
160
|
+
end
|
|
161
|
+
new_rgb = options[:rgb] || @rgb
|
|
162
|
+
self.class.new(self.to_hash.merge(:name=>new_name, :code=>new_code, :rgb=>new_rgb))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def on
|
|
166
|
+
new_name = ('on_'+@name.to_s).to_sym
|
|
167
|
+
self.class.list[new_name] ||= variant(new_name, :increment=>10)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def bright
|
|
171
|
+
raise "Cannot create a bright variant of a style list (#{inspect})" if @list
|
|
172
|
+
new_name = ('bright_'+@name.to_s).to_sym
|
|
173
|
+
if style = self.class.list[new_name]
|
|
174
|
+
style
|
|
175
|
+
else
|
|
176
|
+
new_rgb = @rgb == [0,0,0] ? [128, 128, 128] : @rgb.map {|color| color==0 ? 0 : [color+128,255].min }
|
|
177
|
+
variant(new_name, :increment=>60, :rgb=>new_rgb)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|