highline 1.6.2 → 1.6.5
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/CHANGELOG +24 -0
- data/Rakefile +4 -4
- data/lib/highline.rb +283 -130
- data/lib/highline/color_scheme.rb +20 -2
- data/lib/highline/menu.rb +1 -1
- data/lib/highline/question.rb +3 -0
- data/lib/highline/string_extensions.rb +98 -0
- data/lib/highline/style.rb +184 -0
- data/test/string_methods.rb +34 -0
- data/test/tc_color_scheme.rb +42 -0
- data/test/tc_highline.rb +133 -4
- data/test/tc_string_extension.rb +22 -0
- data/test/tc_string_highline.rb +40 -0
- data/test/tc_style.rb +569 -0
- data/test/ts_all.rb +3 -0
- metadata +32 -30
data/CHANGELOG
CHANGED
@@ -2,6 +2,30 @@
|
|
2
2
|
|
3
3
|
Below is a complete listing of changes for each revision of HighLine.
|
4
4
|
|
5
|
+
== 1.6.5
|
6
|
+
|
7
|
+
* HighLine#list() now correctly handles empty lists (fix by Lachlan Dowding).
|
8
|
+
* HighLine#list() now supports <tt>:uneven_columns_across</tt> and
|
9
|
+
<tt>:uneven_columns_down</tt> modes.
|
10
|
+
|
11
|
+
== 1.6.4
|
12
|
+
|
13
|
+
* Add introspection methods to color_scheme: definition, keys, to_hash.
|
14
|
+
* Add tests for new methods.
|
15
|
+
|
16
|
+
== 1.6.3
|
17
|
+
|
18
|
+
* Add color NONE.
|
19
|
+
* Add RGB color capability.
|
20
|
+
* Made 'color' available as a class or instance method of HighLine, for
|
21
|
+
instance: HighLine.color("foo", :blue)) or highline_obj.color("foo", :blue)
|
22
|
+
are now both possible and equivalent.
|
23
|
+
* Add HighLine::String class with convenience methods: #color (alias
|
24
|
+
#foreground), #on (alias #background), colors, and styles. See
|
25
|
+
lib/string_extensions.rb.
|
26
|
+
* Add (optional) ability to extend String with the same convenience methods from
|
27
|
+
HighLine::String, using Highline.colorize_strings.
|
28
|
+
|
5
29
|
== 1.6.2
|
6
30
|
|
7
31
|
* Correctly handle STDIN being closed before we receive any data (fix by
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require "
|
1
|
+
require "rdoc/task"
|
2
2
|
require "rake/testtask"
|
3
|
-
require "
|
3
|
+
require "rubygems/package_task"
|
4
4
|
|
5
5
|
require "rubygems"
|
6
6
|
|
@@ -12,7 +12,7 @@ task :default => [:test]
|
|
12
12
|
|
13
13
|
Rake::TestTask.new do |test|
|
14
14
|
test.libs << "test"
|
15
|
-
test.test_files = [ "test/ts_all.rb"
|
15
|
+
test.test_files = [ "test/ts_all.rb"]
|
16
16
|
test.verbose = true
|
17
17
|
end
|
18
18
|
|
@@ -63,7 +63,7 @@ minutes of work.
|
|
63
63
|
END_DESC
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
Gem::PackageTask.new(spec) do |pkg|
|
67
67
|
pkg.need_zip = true
|
68
68
|
pkg.need_tar = true
|
69
69
|
end
|
data/lib/highline.rb
CHANGED
@@ -17,6 +17,7 @@ require "highline/system_extensions"
|
|
17
17
|
require "highline/question"
|
18
18
|
require "highline/menu"
|
19
19
|
require "highline/color_scheme"
|
20
|
+
require "highline/style"
|
20
21
|
|
21
22
|
#
|
22
23
|
# A HighLine object is a "high-level line oriented" shell over an input and an
|
@@ -29,7 +30,7 @@ require "highline/color_scheme"
|
|
29
30
|
#
|
30
31
|
class HighLine
|
31
32
|
# The version of the installed library.
|
32
|
-
VERSION = "1.6.
|
33
|
+
VERSION = "1.6.5".freeze
|
33
34
|
|
34
35
|
# An internal HighLine error. User code does not need to trap this.
|
35
36
|
class QuestionError < StandardError
|
@@ -49,6 +50,13 @@ class HighLine
|
|
49
50
|
@@use_color
|
50
51
|
end
|
51
52
|
|
53
|
+
# For checking if the current version of HighLine supports RGB colors
|
54
|
+
# Usage: HighLine.supports_rgb_color? rescue false # rescue for compatibility with older versions
|
55
|
+
# Note: color usage also depends on HighLine.use_color being set
|
56
|
+
def self.supports_rgb_color?
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
52
60
|
# The setting used to disable EOF tracking.
|
53
61
|
@@track_eof = true
|
54
62
|
|
@@ -83,62 +91,85 @@ class HighLine
|
|
83
91
|
#
|
84
92
|
# Embed in a String to clear all previous ANSI sequences. This *MUST* be
|
85
93
|
# done before the program exits!
|
86
|
-
#
|
87
|
-
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
#
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
94
|
+
#
|
95
|
+
|
96
|
+
ERASE_LINE_STYLE = Style.new(:name=>:erase_line, :builtin=>true, :code=>"\e[K") # Erase the current line of terminal output
|
97
|
+
ERASE_CHAR_STYLE = Style.new(:name=>:erase_char, :builtin=>true, :code=>"\e[P") # Erase the character under the cursor.
|
98
|
+
CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings
|
99
|
+
RESET_STYLE = Style.new(:name=>:reset, :builtin=>true, :code=>"\e[0m") # Alias for CLEAR.
|
100
|
+
BOLD_STYLE = Style.new(:name=>:bold, :builtin=>true, :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect,
|
101
|
+
# for example bold black. Bold without a color displays
|
102
|
+
# the system-defined bold color (e.g. red on Mac iTerm)
|
103
|
+
DARK_STYLE = Style.new(:name=>:dark, :builtin=>true, :code=>"\e[2m") # Dark; support uncommon
|
104
|
+
UNDERLINE_STYLE = Style.new(:name=>:underline, :builtin=>true, :code=>"\e[4m") # Underline
|
105
|
+
UNDERSCORE_STYLE = Style.new(:name=>:underscore, :builtin=>true, :code=>"\e[4m") # Alias for UNDERLINE
|
106
|
+
BLINK_STYLE = Style.new(:name=>:blink, :builtin=>true, :code=>"\e[5m") # Blink; support uncommon
|
107
|
+
REVERSE_STYLE = Style.new(:name=>:reverse, :builtin=>true, :code=>"\e[7m") # Reverse foreground and background
|
108
|
+
CONCEALED_STYLE = Style.new(:name=>:concealed, :builtin=>true, :code=>"\e[8m") # Concealed; support uncommon
|
109
|
+
|
110
|
+
STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED}
|
111
|
+
|
112
|
+
# These RGB colors are approximate; see http://en.wikipedia.org/wiki/ANSI_escape_code
|
113
|
+
BLACK_STYLE = Style.new(:name=>:black, :builtin=>true, :code=>"\e[30m", :rgb=>[ 0, 0, 0])
|
114
|
+
RED_STYLE = Style.new(:name=>:red, :builtin=>true, :code=>"\e[31m", :rgb=>[128, 0, 0])
|
115
|
+
GREEN_STYLE = Style.new(:name=>:green, :builtin=>true, :code=>"\e[32m", :rgb=>[ 0,128, 0])
|
116
|
+
BLUE_STYLE = Style.new(:name=>:blue, :builtin=>true, :code=>"\e[34m", :rgb=>[ 0, 0,128])
|
117
|
+
YELLOW_STYLE = Style.new(:name=>:yellow, :builtin=>true, :code=>"\e[33m", :rgb=>[128,128, 0])
|
118
|
+
MAGENTA_STYLE = Style.new(:name=>:magenta, :builtin=>true, :code=>"\e[35m", :rgb=>[128, 0,128])
|
119
|
+
CYAN_STYLE = Style.new(:name=>:cyan, :builtin=>true, :code=>"\e[36m", :rgb=>[ 0,128,128])
|
120
|
+
# On Mac OSX Terminal, white is actually gray
|
121
|
+
WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
|
122
|
+
# Alias for WHITE, since WHITE is actually a light gray on Macs
|
123
|
+
GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
|
124
|
+
# On Mac OSX Terminal, this is black foreground, or bright white background.
|
125
|
+
# Also used as base for RGB colors, if available
|
126
|
+
NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0])
|
127
|
+
|
128
|
+
BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY NONE}
|
129
|
+
|
130
|
+
colors = BASIC_COLORS.dup
|
131
|
+
BASIC_COLORS.each do |color|
|
132
|
+
bright_color = "BRIGHT_#{color}"
|
133
|
+
colors << bright_color
|
134
|
+
const_set bright_color+'_STYLE', const_get(color + '_STYLE').bright
|
135
|
+
end
|
136
|
+
COLORS = colors
|
137
|
+
|
138
|
+
colors.each do |color|
|
139
|
+
const_set color, const_get("#{color}_STYLE").code
|
140
|
+
const_set "ON_#{color}_STYLE", const_get("#{color}_STYLE").on
|
141
|
+
const_set "ON_#{color}", const_get("ON_#{color}_STYLE").code
|
142
|
+
end
|
143
|
+
ON_NONE_STYLE.rgb = [255,255,255] # Override; white background
|
144
|
+
|
145
|
+
STYLES.each do |style|
|
146
|
+
const_set style, const_get("#{style}_STYLE").code
|
147
|
+
end
|
148
|
+
|
149
|
+
# For RGB colors:
|
150
|
+
def self.const_missing(name)
|
151
|
+
if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color
|
152
|
+
on = $1
|
153
|
+
suffix = $4
|
154
|
+
if suffix
|
155
|
+
code_name = $1.to_s + $2 + $3
|
156
|
+
else
|
157
|
+
code_name = name.to_s
|
158
|
+
end
|
159
|
+
style_name = code_name + '_STYLE'
|
160
|
+
style = Style.rgb($3)
|
161
|
+
style = style.on if on
|
162
|
+
const_set(style_name, style)
|
163
|
+
const_set(code_name, style.code)
|
164
|
+
if suffix
|
165
|
+
style
|
166
|
+
else
|
167
|
+
style.code
|
168
|
+
end
|
169
|
+
else
|
170
|
+
raise NameError, "Bad color or uninitialized constant #{name}"
|
171
|
+
end
|
172
|
+
end
|
142
173
|
|
143
174
|
#
|
144
175
|
# Create an instance of HighLine, connected to the streams _input_
|
@@ -328,19 +359,34 @@ class HighLine
|
|
328
359
|
# This method returns the original _string_ unchanged if HighLine::use_color?
|
329
360
|
# is +false+.
|
330
361
|
#
|
331
|
-
def color( string, *colors )
|
332
|
-
return string unless self.
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
362
|
+
def self.color( string, *colors )
|
363
|
+
return string unless self.use_color?
|
364
|
+
Style(*colors).color(string)
|
365
|
+
end
|
366
|
+
|
367
|
+
# In case you just want the color code, without the embedding and the CLEAR
|
368
|
+
def self.color_code(*colors)
|
369
|
+
Style(*colors).code
|
370
|
+
end
|
371
|
+
|
372
|
+
# Works as an instance method, same as the class method
|
373
|
+
def color_code(*colors)
|
374
|
+
self.class.color_code(*colors)
|
375
|
+
end
|
376
|
+
|
377
|
+
# Works as an instance method, same as the class method
|
378
|
+
def color(*args)
|
379
|
+
self.class.color(*args)
|
380
|
+
end
|
381
|
+
|
382
|
+
# Remove color codes from a string
|
383
|
+
def self.uncolor(string)
|
384
|
+
Style.uncolor(string)
|
385
|
+
end
|
386
|
+
|
387
|
+
# Works as an instance method, same as the class method
|
388
|
+
def uncolor(string)
|
389
|
+
self.class.uncolor(string)
|
344
390
|
end
|
345
391
|
|
346
392
|
#
|
@@ -352,20 +398,25 @@ class HighLine
|
|
352
398
|
# to list. A specified _mode_ controls how that list is formed and _option_
|
353
399
|
# has different effects, depending on the _mode_. Recognized modes are:
|
354
400
|
#
|
355
|
-
# <tt>:columns_across</tt>::
|
356
|
-
#
|
357
|
-
#
|
358
|
-
#
|
359
|
-
#
|
360
|
-
#
|
361
|
-
#
|
362
|
-
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
#
|
366
|
-
#
|
367
|
-
#
|
368
|
-
#
|
401
|
+
# <tt>:columns_across</tt>:: _items_ will be placed in columns,
|
402
|
+
# flowing from left to right. If given,
|
403
|
+
# _option_ is the number of columns to be
|
404
|
+
# used. When absent, columns will be
|
405
|
+
# determined based on _wrap_at_ or a
|
406
|
+
# default of 80 characters.
|
407
|
+
# <tt>:columns_down</tt>:: Identical to <tt>:columns_across</tt>,
|
408
|
+
# save flow goes down.
|
409
|
+
# <tt>:uneven_columns_across</tt>:: Like <tt>:columns_across</tt> but each
|
410
|
+
# column is sized independently.
|
411
|
+
# <tt>:uneven_columns_down</tt>:: Like <tt>:columns_down</tt> but each
|
412
|
+
# column is sized independently.
|
413
|
+
# <tt>:inline</tt>:: All _items_ are placed on a single line.
|
414
|
+
# The last two _items_ are separated by
|
415
|
+
# _option_ or a default of " or ". All
|
416
|
+
# other _items_ are separated by ", ".
|
417
|
+
# <tt>:rows</tt>:: The default mode. Each of the _items_ is
|
418
|
+
# placed on it's own line. The _option_
|
419
|
+
# parameter is ignored in this mode.
|
369
420
|
#
|
370
421
|
# Each member of the _items_ Array is passed through ERb and thus can contain
|
371
422
|
# their own expansions. Color escape expansions do not contribute to the
|
@@ -376,58 +427,157 @@ class HighLine
|
|
376
427
|
ERB.new(item, nil, "%").result(binding)
|
377
428
|
end
|
378
429
|
|
379
|
-
|
380
|
-
|
381
|
-
|
430
|
+
if items.empty?
|
431
|
+
""
|
432
|
+
else
|
433
|
+
case mode
|
434
|
+
when :inline
|
435
|
+
option = " or " if option.nil?
|
436
|
+
|
437
|
+
if items.size == 1
|
438
|
+
items.first
|
439
|
+
else
|
440
|
+
items[0..-2].join(", ") + "#{option}#{items.last}"
|
441
|
+
end
|
442
|
+
when :columns_across, :columns_down
|
443
|
+
max_length = actual_length(
|
444
|
+
items.max { |a, b| actual_length(a) <=> actual_length(b) }
|
445
|
+
)
|
446
|
+
|
447
|
+
if option.nil?
|
448
|
+
limit = @wrap_at || 80
|
449
|
+
option = (limit + 2) / (max_length + 2)
|
450
|
+
end
|
451
|
+
|
452
|
+
items = items.map do |item|
|
453
|
+
pad = max_length + (item.length - actual_length(item))
|
454
|
+
"%-#{pad}s" % item
|
455
|
+
end
|
456
|
+
row_count = (items.size / option.to_f).ceil
|
382
457
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
when 2
|
389
|
-
"#{items.first}#{option}#{items.last}"
|
390
|
-
else
|
391
|
-
items[0..-2].join(", ") + "#{option}#{items.last}"
|
392
|
-
end
|
393
|
-
when :columns_across, :columns_down
|
394
|
-
max_length = actual_length(
|
395
|
-
items.max { |a, b| actual_length(a) <=> actual_length(b) }
|
396
|
-
)
|
397
|
-
|
398
|
-
if option.nil?
|
399
|
-
limit = @wrap_at || 80
|
400
|
-
option = (limit + 2) / (max_length + 2)
|
401
|
-
end
|
458
|
+
if mode == :columns_across
|
459
|
+
rows = Array.new(row_count) { Array.new }
|
460
|
+
items.each_with_index do |item, index|
|
461
|
+
rows[index / option] << item
|
462
|
+
end
|
402
463
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
464
|
+
rows.map { |row| row.join(" ") + "\n" }.join
|
465
|
+
else
|
466
|
+
columns = Array.new(option) { Array.new }
|
467
|
+
items.each_with_index do |item, index|
|
468
|
+
columns[index / row_count] << item
|
469
|
+
end
|
408
470
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
471
|
+
list = ""
|
472
|
+
columns.first.size.times do |index|
|
473
|
+
list << columns.map { |column| column[index] }.
|
474
|
+
compact.join(" ") + "\n"
|
475
|
+
end
|
476
|
+
list
|
413
477
|
end
|
478
|
+
when :uneven_columns_across
|
479
|
+
if option.nil?
|
480
|
+
limit = @wrap_at || 80
|
481
|
+
items.size.downto(1) do |column_count|
|
482
|
+
row_count = (items.size / column_count.to_f).ceil
|
483
|
+
rows = Array.new(row_count) { Array.new }
|
484
|
+
items.each_with_index do |item, index|
|
485
|
+
rows[index / column_count] << item
|
486
|
+
end
|
414
487
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
488
|
+
widths = Array.new(column_count, 0)
|
489
|
+
rows.each do |row|
|
490
|
+
row.each_with_index do |field, column|
|
491
|
+
size = field.size
|
492
|
+
widths[column] = size if size > widths[column]
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
if column_count == 1 or
|
497
|
+
widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2
|
498
|
+
return rows.map { |row|
|
499
|
+
row.zip(widths).map { |field, i| "%-#{i}s" % field }.
|
500
|
+
join(" ") + "\n"
|
501
|
+
}.join
|
502
|
+
end
|
503
|
+
end
|
504
|
+
else
|
505
|
+
row_count = (items.size / option.to_f).ceil
|
506
|
+
rows = Array.new(row_count) { Array.new }
|
507
|
+
items.each_with_index do |item, index|
|
508
|
+
rows[index / option] << item
|
509
|
+
end
|
510
|
+
|
511
|
+
widths = Array.new(option, 0)
|
512
|
+
rows.each do |row|
|
513
|
+
row.each_with_index do |field, column|
|
514
|
+
size = field.size
|
515
|
+
widths[column] = size if size > widths[column]
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
return rows.map { |row|
|
520
|
+
row.zip(widths).map { |field, i| "%-#{i}s" % field }.join(" ") +
|
521
|
+
"\n"
|
522
|
+
}.join
|
420
523
|
end
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
524
|
+
when :uneven_columns_down
|
525
|
+
if option.nil?
|
526
|
+
limit = @wrap_at || 80
|
527
|
+
items.size.downto(1) do |column_count|
|
528
|
+
row_count = (items.size / column_count.to_f).ceil
|
529
|
+
columns = Array.new(column_count) { Array.new }
|
530
|
+
items.each_with_index do |item, index|
|
531
|
+
columns[index / row_count] << item
|
532
|
+
end
|
533
|
+
|
534
|
+
widths = Array.new(column_count, 0)
|
535
|
+
columns.each_with_index do |column, i|
|
536
|
+
column.each do |field|
|
537
|
+
size = field.size
|
538
|
+
widths[i] = size if size > widths[i]
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
if column_count == 1 or
|
543
|
+
widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2
|
544
|
+
list = ""
|
545
|
+
columns.first.size.times do |index|
|
546
|
+
list << columns.zip(widths).
|
547
|
+
map { |column, width| "%-#{width}s" %
|
548
|
+
column[index] }.
|
549
|
+
compact.join(" ").strip + "\n"
|
550
|
+
end
|
551
|
+
return list
|
552
|
+
end
|
553
|
+
end
|
554
|
+
else
|
555
|
+
row_count = (items.size / option.to_f).ceil
|
556
|
+
columns = Array.new(option) { Array.new }
|
557
|
+
items.each_with_index do |item, index|
|
558
|
+
columns[index / row_count] << item
|
559
|
+
end
|
560
|
+
|
561
|
+
widths = Array.new(option, 0)
|
562
|
+
columns.each_with_index do |column, i|
|
563
|
+
column.each do |field|
|
564
|
+
size = field.size
|
565
|
+
widths[i] = size if size > widths[i]
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
list = ""
|
570
|
+
columns.first.size.times do |index|
|
571
|
+
list << columns.zip(widths).
|
572
|
+
map { |column, width| "%-#{width}s" %
|
573
|
+
column[index] }.
|
574
|
+
compact.join(" ").strip + "\n"
|
575
|
+
end
|
576
|
+
return list
|
426
577
|
end
|
427
|
-
|
578
|
+
else
|
579
|
+
items.map { |i| "#{i}\n" }.join
|
428
580
|
end
|
429
|
-
else
|
430
|
-
items.map { |i| "#{i}\n" }.join
|
431
581
|
end
|
432
582
|
end
|
433
583
|
|
@@ -540,11 +690,11 @@ class HighLine
|
|
540
690
|
@answers << ask(@question)
|
541
691
|
@gather -= 1
|
542
692
|
end
|
543
|
-
when String, Regexp
|
693
|
+
when ::String, Regexp
|
544
694
|
@answers << ask(@question)
|
545
695
|
|
546
696
|
original_question.question = ""
|
547
|
-
until (@gather.is_a?(String) and @answers.last.to_s == @gather) or
|
697
|
+
until (@gather.is_a?(::String) and @answers.last.to_s == @gather) or
|
548
698
|
(@gather.is_a?(Regexp) and @answers.last.to_s =~ @gather)
|
549
699
|
@question = original_question
|
550
700
|
@answers << ask(@question)
|
@@ -761,3 +911,6 @@ class HighLine
|
|
761
911
|
string_with_escapes.gsub(/\e\[\d{1,2}m/, "").length
|
762
912
|
end
|
763
913
|
end
|
914
|
+
|
915
|
+
require "highline/string_extensions"
|
916
|
+
|