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.
@@ -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)] = constants.map { |c| to_constant(c) }
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
@@ -1,5 +1,3 @@
1
- #!/usr/local/bin/ruby -w
2
-
3
1
  # import.rb
4
2
  #
5
3
  # Created by James Edward Gray II on 2005-04-26.
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 @nil_on_handled and not action.nil?
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})."
@@ -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 a english explination of the current range settings.
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