highline 1.6.15 → 1.6.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -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