highline 1.6.15 → 1.6.16

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.
@@ -4,7 +4,7 @@
4
4
  # Copyright 2005 Gray Productions. All rights reserved.
5
5
  #
6
6
  # This is Free Software. See LICENSE and COPYING for details.
7
-
7
+
8
8
  require "optparse"
9
9
  require "date"
10
10
  require "pathname"
@@ -26,13 +26,14 @@ class HighLine
26
26
  # Create an instance of HighLine::Question. Expects a _question_ to ask
27
27
  # (can be <tt>""</tt>) and an _answer_type_ to convert the answer to.
28
28
  # The _answer_type_ parameter must be a type recognized by
29
- # Question.convert(). If given, a block is yeilded the new Question
30
- # object to allow custom initializaion.
29
+ # Question.convert(). If given, a block is yielded the new Question
30
+ # object to allow custom initialization.
31
31
  #
32
32
  def initialize( question, answer_type )
33
33
  # initialize instance data
34
34
  @question = question.dup
35
35
  @answer_type = answer_type
36
+ @completion = @answer_type
36
37
 
37
38
  @character = nil
38
39
  @limit = nil
@@ -65,31 +66,33 @@ class HighLine
65
66
  attr_accessor :question
66
67
  # The type that will be used to convert this answer.
67
68
  attr_accessor :answer_type
69
+ # For Auto-completion
70
+ attr_accessor :completion
68
71
  #
69
72
  # Can be set to +true+ to use HighLine's cross-platform character reader
70
73
  # instead of fetching an entire line of input. (Note: HighLine's character
71
74
  # reader *ONLY* supports STDIN on Windows and Unix.) Can also be set to
72
75
  # <tt>:getc</tt> to use that method on the input stream.
73
76
  #
74
- # *WARNING*: The _echo_ and _overwrite_ attributes for a question are
75
- # ignored when using the <tt>:getc</tt> method.
76
- #
77
+ # *WARNING*: The _echo_ and _overwrite_ attributes for a question are
78
+ # ignored when using the <tt>:getc</tt> method.
79
+ #
77
80
  attr_accessor :character
78
81
  #
79
82
  # Allows you to set a character limit for input.
80
- #
83
+ #
81
84
  # *WARNING*: This option forces a character by character read.
82
- #
85
+ #
83
86
  attr_accessor :limit
84
87
  #
85
88
  # Can be set to +true+ or +false+ to control whether or not input will
86
89
  # be echoed back to the user. A setting of +true+ will cause echo to
87
- # match input, but any other true value will be treated as to String to
90
+ # match input, but any other true value will be treated as a String to
88
91
  # echo for each character typed.
89
- #
92
+ #
90
93
  # This requires HighLine's character reader. See the _character_
91
94
  # attribute for details.
92
- #
95
+ #
93
96
  # *Note*: When using HighLine to manage echo on Unix based systems, we
94
97
  # recommend installing the termios gem. Without it, it's possible to type
95
98
  # fast enough to have letters still show up (when reading character by
@@ -98,13 +101,13 @@ class HighLine
98
101
  attr_accessor :echo
99
102
  #
100
103
  # Use the Readline library to fetch input. This allows input editing as
101
- # well as keeping a history. In addition, tab will auto-complete
104
+ # well as keeping a history. In addition, tab will auto-complete
102
105
  # within an Array of choices or a file listing.
103
- #
104
- # *WARNING*: This option is incompatible with all of HighLine's
106
+ #
107
+ # *WARNING*: This option is incompatible with all of HighLine's
105
108
  # character reading modes and it causes HighLine to ignore the
106
109
  # specified _input_ stream.
107
- #
110
+ #
108
111
  attr_accessor :readline
109
112
  #
110
113
  # Used to control whitespace processing for the answer to this question.
@@ -132,25 +135,25 @@ class HighLine
132
135
  # Asks a yes or no confirmation question, to ensure a user knows what
133
136
  # they have just agreed to. If set to +true+ the question will be,
134
137
  # "Are you sure? " Any other true value for this attribute is assumed
135
- # to be the question to ask. When +false+ or +nil+ (the default),
138
+ # to be the question to ask. When +false+ or +nil+ (the default),
136
139
  # answers are not confirmed.
137
- #
140
+ #
138
141
  attr_accessor :confirm
139
142
  #
140
143
  # When set, the user will be prompted for multiple answers which will
141
144
  # be collected into an Array or Hash and returned as the final answer.
142
- #
145
+ #
143
146
  # You can set _gather_ to an Integer to have an Array of exactly that
144
147
  # many answers collected, or a String/Regexp to match an end input which
145
148
  # will not be returned in the Array.
146
- #
149
+ #
147
150
  # Optionally _gather_ can be set to a Hash. In this case, the question
148
151
  # will be asked once for each key and the answers will be returned in a
149
- # Hash, mapped by key. The <tt>@key</tt> variable is set before each
152
+ # Hash, mapped by key. The <tt>@key</tt> variable is set before each
150
153
  # question is evaluated, so you can use it in your question.
151
- #
154
+ #
152
155
  attr_accessor :gather
153
- #
156
+ #
154
157
  # When set to +true+ multiple entries will be collected according to
155
158
  # the setting for _gather_, except they will be required to match
156
159
  # each other. Multiple identical entries will return a single answer.
@@ -159,20 +162,20 @@ class HighLine
159
162
  #
160
163
  # When set to a non *nil* value, this will be tried as an answer to the
161
164
  # question. If this answer passes validations, it will become the result
162
- # without the user ever being prompted. Otherwise this value is discarded,
165
+ # without the user ever being prompted. Otherwise this value is discarded,
163
166
  # and this Question is resolved as a normal call to HighLine.ask().
164
- #
167
+ #
165
168
  attr_writer :first_answer
166
169
  #
167
170
  # The directory from which a user will be allowed to select files, when
168
171
  # File or Pathname is specified as an _answer_type_. Initially set to
169
172
  # <tt>Pathname.new(File.expand_path(File.dirname($0)))</tt>.
170
- #
173
+ #
171
174
  attr_accessor :directory
172
- #
175
+ #
173
176
  # The glob pattern used to limit file selection when File or Pathname is
174
177
  # specified as an _answer_type_. Initially set to <tt>"*"</tt>.
175
- #
178
+ #
176
179
  attr_accessor :glob
177
180
  #
178
181
  # A Hash that stores the various responses used by HighLine to notify
@@ -206,7 +209,7 @@ class HighLine
206
209
  # the screen.
207
210
  #
208
211
  attr_accessor :overwrite
209
-
212
+
210
213
  #
211
214
  # Returns the provided _answer_string_ or the default answer for this
212
215
  # Question if a default was set and the answer is empty.
@@ -218,7 +221,7 @@ class HighLine
218
221
  answer_string
219
222
  end
220
223
  end
221
-
224
+
222
225
  #
223
226
  # Called late in the initialization process to build intelligent
224
227
  # responses based on the details of this Question object.
@@ -250,21 +253,21 @@ class HighLine
250
253
  ### Menu.update_responses(). Check there too when ###
251
254
  ### making changes! ###
252
255
  end
253
-
256
+
254
257
  #
255
258
  # Returns the provided _answer_string_ after changing character case by
256
259
  # the rules of this Question. Valid settings for whitespace are:
257
260
  #
258
- # +nil+:: Do not alter character case.
261
+ # +nil+:: Do not alter character case.
259
262
  # (Default.)
260
263
  # <tt>:up</tt>:: Calls upcase().
261
264
  # <tt>:upcase</tt>:: Calls upcase().
262
265
  # <tt>:down</tt>:: Calls downcase().
263
266
  # <tt>:downcase</tt>:: Calls downcase().
264
267
  # <tt>:capitalize</tt>:: Calls capitalize().
265
- #
268
+ #
266
269
  # An unrecognized choice (like <tt>:none</tt>) is treated as +nil+.
267
- #
270
+ #
268
271
  def change_case( answer_string )
269
272
  if [:up, :upcase].include?(@case)
270
273
  answer_string.upcase
@@ -281,13 +284,13 @@ class HighLine
281
284
  # Transforms the given _answer_string_ into the expected type for this
282
285
  # Question. Currently supported conversions are:
283
286
  #
284
- # <tt>[...]</tt>:: Answer must be a member of the passed Array.
287
+ # <tt>[...]</tt>:: Answer must be a member of the passed Array.
285
288
  # Auto-completion is used to expand partial
286
289
  # answers.
287
290
  # <tt>lambda {...}</tt>:: Answer is passed to lambda for conversion.
288
291
  # Date:: Date.parse() is called with answer.
289
292
  # DateTime:: DateTime.parse() is called with answer.
290
- # File:: The entered file name is auto-completed in
293
+ # File:: The entered file name is auto-completed in
291
294
  # terms of _directory_ + _glob_, opened, and
292
295
  # returned.
293
296
  # Float:: Answer is converted with Kernel.Float().
@@ -305,7 +308,7 @@ class HighLine
305
308
  #
306
309
  # This method throws ArgumentError, if the conversion cannot be
307
310
  # completed for any reason.
308
- #
311
+ #
309
312
  def convert( answer_string )
310
313
  if @answer_type.nil?
311
314
  answer_string
@@ -361,15 +364,15 @@ class HighLine
361
364
  ensure
362
365
  @first_answer = nil
363
366
  end
364
-
367
+
365
368
  # Returns true if _first_answer_ is set.
366
369
  def first_answer?( )
367
370
  not @first_answer.nil?
368
371
  end
369
-
372
+
370
373
  #
371
374
  # Returns +true+ if the _answer_object_ is greater than the _above_
372
- # attribute, less than the _below_ attribute and included?()ed in the
375
+ # attribute, less than the _below_ attribute and include?()ed in the
373
376
  # _in_ attribute. Otherwise, +false+ is returned. Any +nil+ attributes
374
377
  # are not checked.
375
378
  #
@@ -378,7 +381,7 @@ class HighLine
378
381
  (@below.nil? or answer_object < @below) and
379
382
  (@in.nil? or @in.include?(answer_object))
380
383
  end
381
-
384
+
382
385
  #
383
386
  # Returns the provided _answer_string_ after processing whitespace by
384
387
  # the rules of this Question. Valid settings for whitespace are:
@@ -386,18 +389,18 @@ class HighLine
386
389
  # +nil+:: Do not alter whitespace.
387
390
  # <tt>:strip</tt>:: Calls strip(). (Default.)
388
391
  # <tt>:chomp</tt>:: Calls chomp().
389
- # <tt>:collapse</tt>:: Collapses all whitspace runs to a
392
+ # <tt>:collapse</tt>:: Collapses all whitespace runs to a
390
393
  # single space.
391
394
  # <tt>:strip_and_collapse</tt>:: Calls strip(), then collapses all
392
- # whitspace runs to a single space.
395
+ # whitespace runs to a single space.
393
396
  # <tt>:chomp_and_collapse</tt>:: Calls chomp(), then collapses all
394
- # whitspace runs to a single space.
397
+ # whitespace runs to a single space.
395
398
  # <tt>:remove</tt>:: Removes all whitespace.
396
- #
399
+ #
397
400
  # An unrecognized choice (like <tt>:none</tt>) is treated as +nil+.
398
- #
399
- # This process is skipped, for single character input.
400
- #
401
+ #
402
+ # This process is skipped for single character input.
403
+ #
401
404
  def remove_whitespace( answer_string )
402
405
  if @whitespace.nil?
403
406
  answer_string
@@ -419,39 +422,39 @@ class HighLine
419
422
  # Returns an Array of valid answers to this question. These answers are
420
423
  # only known when _answer_type_ is set to an Array of choices, File, or
421
424
  # Pathname. Any other time, this method will return an empty Array.
422
- #
425
+ #
423
426
  def selection( )
424
- if @answer_type.is_a?(Array)
425
- @answer_type
426
- elsif [File, Pathname].include?(@answer_type)
427
+ if @completion.is_a?(Array)
428
+ @completion
429
+ elsif [File, Pathname].include?(@completion)
427
430
  Dir[File.join(@directory.to_s, @glob)].map do |file|
428
431
  File.basename(file)
429
432
  end
430
433
  else
431
434
  [ ]
432
- end
435
+ end
433
436
  end
434
-
437
+
435
438
  # Stringifies the question to be asked.
436
439
  def to_str( )
437
440
  @question
438
441
  end
439
442
 
440
443
  #
441
- # Returns +true+ if the provided _answer_string_ is accepted by the
444
+ # Returns +true+ if the provided _answer_string_ is accepted by the
442
445
  # _validate_ attribute or +false+ if it's not.
443
- #
446
+ #
444
447
  # It's important to realize that an answer is validated after whitespace
445
448
  # and case handling.
446
449
  #
447
450
  def valid_answer?( answer_string )
448
- @validate.nil? or
451
+ @validate.nil? or
449
452
  (@validate.is_a?(Regexp) and answer_string =~ @validate) or
450
453
  (@validate.is_a?(Proc) and @validate[answer_string])
451
454
  end
452
-
455
+
453
456
  private
454
-
457
+
455
458
  #
456
459
  # Adds the default choice to the end of question between <tt>|...|</tt>.
457
460
  # Trailing whitespace is preserved so the function of HighLine.say() is
@@ -15,7 +15,7 @@ class HighLine
15
15
  def initialize(strings)
16
16
  @strings = strings
17
17
  end
18
-
18
+
19
19
  # Simulate StringIO#gets by shifting a string off of the script
20
20
  def gets
21
21
  @strings.shift
@@ -17,8 +17,8 @@
17
17
  # highline_string.color(:bright_blue, :blink, :underline)
18
18
  # HighLine.color(highline_string, :bright_blue, :blink, :underline)
19
19
  #
20
- # For those less squeamish about possible conflicts, the same convenience methods can be
21
- # added to the builtin String class, as follows:
20
+ # For those less squeamish about possible conflicts, the same convenience methods can be
21
+ # added to the built-in String class, as follows:
22
22
  #
23
23
  # require 'highline'
24
24
  # Highline.colorize_strings
@@ -27,7 +27,7 @@ class HighLine
27
27
  def self.String(s)
28
28
  HighLine::String.new(s)
29
29
  end
30
-
30
+
31
31
  module StringExtensions
32
32
  def self.included(base)
33
33
  HighLine::COLORS.each do |color|
@@ -61,7 +61,7 @@ class HighLine
61
61
  END
62
62
  end
63
63
  end
64
-
64
+
65
65
  base.class_eval do
66
66
  if public_instance_methods.map { |m| m.to_s }.include? "color"
67
67
  undef :color
@@ -73,7 +73,7 @@ class HighLine
73
73
  self.class.new(HighLine.color(self, *args))
74
74
  end
75
75
  alias_method :foreground, :color
76
-
76
+
77
77
  if public_instance_methods.map { |m| m.to_s }.include? "on"
78
78
  undef :on
79
79
  end
@@ -87,7 +87,7 @@ class HighLine
87
87
  def uncolor
88
88
  self.class.new(HighLine.uncolor(self))
89
89
  end
90
-
90
+
91
91
  if public_instance_methods.map { |m| m.to_s }.include? "rgb"
92
92
  undef :rgb
93
93
  end
@@ -96,7 +96,7 @@ class HighLine
96
96
  raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
97
97
  color("rgb_#{color_code}".to_sym)
98
98
  end
99
-
99
+
100
100
  if public_instance_methods.map { |m| m.to_s }.include? "on_rgb"
101
101
  undef :on_rgb
102
102
  end
@@ -105,7 +105,7 @@ class HighLine
105
105
  raise "Bad RGB color #{colors.inspect}" unless color_code =~ /^[a-fA-F0-9]{6}/
106
106
  color("on_rgb_#{color_code}".to_sym)
107
107
  end
108
-
108
+
109
109
  if public_instance_methods.map { |m| m.to_s }.include? "method_missing"
110
110
  undef :method_missing
111
111
  end
@@ -120,12 +120,12 @@ class HighLine
120
120
  end
121
121
  end
122
122
  end
123
-
123
+
124
124
  class HighLine::String < ::String
125
125
  include StringExtensions
126
126
  end
127
-
127
+
128
128
  def self.colorize_strings
129
129
  ::String.send(:include, StringExtensions)
130
130
  end
131
- end
131
+ end
@@ -6,7 +6,7 @@
6
6
  # This is Free Software. See LICENSE and COPYING for details
7
7
 
8
8
  class HighLine
9
-
9
+
10
10
  def self.Style(*args)
11
11
  args = args.compact.flatten
12
12
  if args.size==1
@@ -37,9 +37,9 @@ class HighLine
37
37
  Style.list[name] || Style.new(:list=>args)
38
38
  end
39
39
  end
40
-
40
+
41
41
  class Style
42
-
42
+
43
43
  def self.index(style)
44
44
  if style.name
45
45
  @@styles ||= {}
@@ -53,17 +53,17 @@ class HighLine
53
53
  end
54
54
  style
55
55
  end
56
-
56
+
57
57
  def self.rgb_hex(*colors)
58
58
  colors.map do |color|
59
59
  color.is_a?(Numeric) ? '%02x'%color : color.to_s
60
60
  end.join
61
61
  end
62
-
62
+
63
63
  def self.rgb_parts(hex)
64
64
  hex.scan(/../).map{|part| part.to_i(16)}
65
65
  end
66
-
66
+
67
67
  def self.rgb(*colors)
68
68
  hex = rgb_hex(*colors)
69
69
  name = ('rgb_' + hex).to_sym
@@ -74,33 +74,33 @@ class HighLine
74
74
  new(:name=>name, :code=>"\e[38;5;#{rgb_number(parts)}m", :rgb=>parts)
75
75
  end
76
76
  end
77
-
77
+
78
78
  def self.rgb_number(*parts)
79
79
  parts = parts.flatten
80
80
  16 + parts.inject(0) {|kode, part| kode*6 + (part/256.0*6.0).floor}
81
81
  end
82
-
82
+
83
83
  def self.ansi_rgb_to_hex(ansi_number)
84
84
  raise "Invalid ANSI rgb code #{ansi_number}" unless (16..231).include?(ansi_number)
85
85
  parts = (ansi_number-16).to_s(6).rjust(3,'0').scan(/./).map{|d| (d.to_i*255.0/6.0).ceil}
86
86
  rgb_hex(*parts)
87
87
  end
88
-
88
+
89
89
  def self.list
90
90
  @@styles ||= {}
91
91
  end
92
-
92
+
93
93
  def self.code_index
94
94
  @@code_index ||= {}
95
95
  end
96
-
96
+
97
97
  def self.uncolor(string)
98
98
  string.gsub(/\e\[\d+(;\d+)*m/, '')
99
99
  end
100
-
100
+
101
101
  attr_reader :name, :list
102
102
  attr_accessor :rgb, :builtin
103
-
103
+
104
104
  # Single color/styles have :name, :code, :rgb (possibly), :builtin
105
105
  # Compound styles have :name, :list, :builtin
106
106
  def initialize(defn = {})
@@ -118,19 +118,19 @@ class HighLine
118
118
  end
119
119
  self.class.index self unless defn[:no_index]
120
120
  end
121
-
121
+
122
122
  def dup
123
123
  self.class.new(@definition)
124
124
  end
125
-
125
+
126
126
  def to_hash
127
127
  @definition
128
128
  end
129
-
129
+
130
130
  def color(string)
131
131
  code + string + HighLine::CLEAR
132
132
  end
133
-
133
+
134
134
  def code
135
135
  if @list
136
136
  @list.map{|element| HighLine.Style(element).code}.join
@@ -138,7 +138,7 @@ class HighLine
138
138
  @code
139
139
  end
140
140
  end
141
-
141
+
142
142
  def red
143
143
  @rgb && @rgb[0]
144
144
  end
@@ -150,7 +150,7 @@ class HighLine
150
150
  def blue
151
151
  @rgb && @rgb[2]
152
152
  end
153
-
153
+
154
154
  def variant(new_name, options={})
155
155
  raise "Cannot create a variant of a style list (#{inspect})" if @list
156
156
  new_code = options[:code] || code
@@ -161,12 +161,12 @@ class HighLine
161
161
  new_rgb = options[:rgb] || @rgb
162
162
  self.class.new(self.to_hash.merge(:name=>new_name, :code=>new_code, :rgb=>new_rgb))
163
163
  end
164
-
164
+
165
165
  def on
166
166
  new_name = ('on_'+@name.to_s).to_sym
167
167
  self.class.list[new_name] ||= variant(new_name, :increment=>10)
168
168
  end
169
-
169
+
170
170
  def bright
171
171
  raise "Cannot create a bright variant of a style list (#{inspect})" if @list
172
172
  new_name = ('bright_'+@name.to_s).to_sym