highline 1.6.15 → 1.6.16
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -3
- data/INSTALL +1 -1
- data/README.rdoc +2 -2
- data/Rakefile +2 -2
- data/examples/basic_usage.rb +2 -2
- data/examples/color_scheme.rb +2 -2
- data/examples/get_character.rb +12 -0
- data/examples/limit.rb +1 -1
- data/examples/menus.rb +2 -2
- data/examples/overwrite.rb +2 -2
- data/examples/page_and_wrap.rb +11 -11
- data/highline.gemspec +1 -0
- data/lib/highline.rb +156 -112
- data/lib/highline/color_scheme.rb +13 -13
- data/lib/highline/import.rb +4 -4
- data/lib/highline/menu.rb +64 -64
- data/lib/highline/question.rb +61 -58
- data/lib/highline/simulate.rb +1 -1
- data/lib/highline/string_extensions.rb +11 -11
- data/lib/highline/style.rb +21 -21
- data/lib/highline/system_extensions.rb +11 -9
- data/setup.rb +6 -6
- data/site/index.html +1 -1
- data/test/tc_highline.rb +91 -3
- data/test/tc_style.rb +3 -3
- metadata +5 -3
data/CHANGELOG
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
Below is a complete listing of changes for each revision of HighLine.
|
4
4
|
|
5
|
+
== 1.6.16
|
6
|
+
|
7
|
+
* Added the new indention feature (by davispuh).
|
8
|
+
* Separated auto-completion from the answer type (by davispuh).
|
9
|
+
* Improved JRuby support (by rsutphin).
|
10
|
+
* General code clean up (by stomar).
|
11
|
+
* Made HighLine#say() a little smarter with regard to color escapes (by Kenneth Murphy).
|
12
|
+
|
5
13
|
== 1.6.15
|
6
14
|
|
7
15
|
* Added support for nil arguments in lists (by Eric Saxby).
|
@@ -88,12 +96,12 @@ Below is a complete listing of changes for each revision of HighLine.
|
|
88
96
|
* Fixed raw_no_echo_mode so that it uses stty -icanon rather than cbreak
|
89
97
|
as cbreak does not appear to be the posixly correct argument. It fails
|
90
98
|
on Solaris if cbreak is used.
|
91
|
-
* Fixed an issue that kept Menu from showing the correct choices for
|
99
|
+
* Fixed an issue that kept Menu from showing the correct choices for
|
92
100
|
disambiguation.
|
93
101
|
* Removed a circular require that kept Ruby 1.9.2 from loading HighLine.
|
94
102
|
* Fixed a bug that caused infinite looping when wrapping text without spaces.
|
95
103
|
* Fixed it so that :auto paging accounts for the two lines it adds.
|
96
|
-
* On JRuby, improved error message about ffi-ncurses. Before 1.5.3,
|
104
|
+
* On JRuby, improved error message about ffi-ncurses. Before 1.5.3,
|
97
105
|
HighLine was silently swallowing error messages when ffi-ncurses gem
|
98
106
|
was installed without ncurses present on the system.
|
99
107
|
* Reverted Aaron Simmons's patch to allow redirecting STDIN on Windows. This
|
@@ -261,7 +269,7 @@ Patch by Jeremy Hinegardner:
|
|
261
269
|
make fetching passwords trivial.
|
262
270
|
* Fixed an auto-complete bug that could cause a crash when the user gave an
|
263
271
|
answer that didn't complete to any valid choice.
|
264
|
-
* Implemented +case+ for HighLine::Question objects to provide character case
|
272
|
+
* Implemented +case+ for HighLine::Question objects to provide character case
|
265
273
|
conversions on given answers. Can be set to <tt>:up</tt>, <tt>:down</tt>, or
|
266
274
|
<tt>:capitalize</tt>.
|
267
275
|
* Exposed <tt>@answer</tt> to the response system, to allow response that are
|
data/INSTALL
CHANGED
@@ -35,7 +35,7 @@ without a working ncurses installation. First, ensure that you have
|
|
35
35
|
ncurses installed and then install the ffi-ncurses gem.
|
36
36
|
|
37
37
|
If ffi-ncurses fails to find your ncurses library, you may need to set the
|
38
|
-
RUBY_FFI_NCURSES envirionment variable, i.e:
|
38
|
+
RUBY_FFI_NCURSES envirionment variable, i.e:
|
39
39
|
|
40
40
|
RUBY_FFI_NCURSES_LIB=ncursesw ruby examples/hello.rb
|
41
41
|
|
data/README.rdoc
CHANGED
@@ -46,11 +46,11 @@ Menus:
|
|
46
46
|
|
47
47
|
choose do |menu|
|
48
48
|
menu.prompt = "Please choose your favorite programming language? "
|
49
|
-
|
49
|
+
|
50
50
|
menu.choice(:ruby) { say("Good choice!") }
|
51
51
|
menu.choices(:python, :perl) { say("Not from around here, are you?") }
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
For more examples see the examples/ directory of this project.
|
55
55
|
|
56
56
|
== Installing
|
data/Rakefile
CHANGED
@@ -39,8 +39,8 @@ end
|
|
39
39
|
desc "Show library's code statistics"
|
40
40
|
task :stats do
|
41
41
|
require 'code_statistics'
|
42
|
-
CodeStatistics.new( ["HighLine", "lib"],
|
43
|
-
["Functionals", "examples"],
|
42
|
+
CodeStatistics.new( ["HighLine", "lib"],
|
43
|
+
["Functionals", "examples"],
|
44
44
|
["Units", "test"] ).to_s
|
45
45
|
end
|
46
46
|
|
data/examples/basic_usage.rb
CHANGED
data/examples/color_scheme.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby -w
|
2
2
|
|
3
3
|
# color_scheme.rb
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Created by Jeremy Hinegardner on 2007-01-24
|
6
|
-
# Copyright 2007 Jeremy Hinegardner. All rights reserved
|
6
|
+
# Copyright 2007 Jeremy Hinegardner. All rights reserved
|
7
7
|
|
8
8
|
require 'rubygems'
|
9
9
|
require 'highline/import'
|
data/examples/limit.rb
CHANGED
data/examples/menus.rb
CHANGED
data/examples/overwrite.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# overwrite.rb
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Created by Jeremy Hinegardner on 2007-01-24
|
6
|
-
# Copyright 2007 Jeremy Hinegardner. All rights reserved
|
6
|
+
# Copyright 2007 Jeremy Hinegardner. All rights reserved
|
7
7
|
|
8
8
|
require 'rubygems'
|
9
9
|
require 'highline/import'
|
data/examples/page_and_wrap.rb
CHANGED
@@ -249,14 +249,14 @@ Delaware
|
|
249
249
|
|
250
250
|
Geo: Read
|
251
251
|
Gunning Bedford jun
|
252
|
-
John Dickinson
|
253
|
-
Richard Bassett
|
254
|
-
Jaco: Broom
|
252
|
+
John Dickinson
|
253
|
+
Richard Bassett
|
254
|
+
Jaco: Broom
|
255
255
|
|
256
256
|
Maryland
|
257
257
|
|
258
258
|
James MCHenry
|
259
|
-
Dan of ST ThoS. Jenifer
|
259
|
+
Dan of ST ThoS. Jenifer
|
260
260
|
DanL Carroll.
|
261
261
|
|
262
262
|
Virginia
|
@@ -268,7 +268,7 @@ North Carolina
|
|
268
268
|
|
269
269
|
WM Blount
|
270
270
|
RichD. Dobbs Spaight.
|
271
|
-
Hu Williamson
|
271
|
+
Hu Williamson
|
272
272
|
|
273
273
|
South Carolina
|
274
274
|
|
@@ -290,7 +290,7 @@ Nicholas Gilman
|
|
290
290
|
Massachusetts
|
291
291
|
|
292
292
|
Nathaniel Gorham
|
293
|
-
Rufus King
|
293
|
+
Rufus King
|
294
294
|
|
295
295
|
Connecticut
|
296
296
|
WM. SamL. Johnson
|
@@ -304,8 +304,8 @@ New Jersey
|
|
304
304
|
|
305
305
|
Wil: Livingston
|
306
306
|
David Brearley.
|
307
|
-
WM. Paterson.
|
308
|
-
Jona: Dayton
|
307
|
+
WM. Paterson.
|
308
|
+
Jona: Dayton
|
309
309
|
|
310
310
|
Pennsylvania
|
311
311
|
|
@@ -313,9 +313,9 @@ B Franklin
|
|
313
313
|
Thomas Mifflin
|
314
314
|
RobT Morris
|
315
315
|
Geo. Clymer
|
316
|
-
ThoS. FitzSimons
|
317
|
-
Jared Ingersoll
|
318
|
-
James Wilson.
|
316
|
+
ThoS. FitzSimons
|
317
|
+
Jared Ingersoll
|
318
|
+
James Wilson.
|
319
319
|
Gouv Morris
|
320
320
|
|
321
321
|
Attest William Jackson Secretary
|
data/highline.gemspec
CHANGED
@@ -27,6 +27,7 @@ SPEC = Gem::Specification.new do |spec|
|
|
27
27
|
spec.email = "james@graysoftinc.com"
|
28
28
|
spec.rubyforge_project = "highline"
|
29
29
|
spec.homepage = "http://highline.rubyforge.org"
|
30
|
+
spec.license = "Ruby"
|
30
31
|
spec.description = <<END_DESC
|
31
32
|
A high-level IO library that provides validation, type conversion, and more for
|
32
33
|
command-line interfaces. HighLine also includes a complete menu system that can
|
data/lib/highline.rb
CHANGED
@@ -18,7 +18,7 @@ require "highline/color_scheme"
|
|
18
18
|
require "highline/style"
|
19
19
|
|
20
20
|
#
|
21
|
-
# A HighLine object is a "high-level line oriented" shell over an input and an
|
21
|
+
# A HighLine object is a "high-level line oriented" shell over an input and an
|
22
22
|
# output stream. HighLine simplifies common console interaction, effectively
|
23
23
|
# replacing puts() and gets(). User code can simply specify the question to ask
|
24
24
|
# and any details about user interaction, then leave the rest of the work to
|
@@ -28,41 +28,41 @@ require "highline/style"
|
|
28
28
|
#
|
29
29
|
class HighLine
|
30
30
|
# The version of the installed library.
|
31
|
-
VERSION = "1.6.
|
32
|
-
|
31
|
+
VERSION = "1.6.16".freeze
|
32
|
+
|
33
33
|
# An internal HighLine error. User code does not need to trap this.
|
34
34
|
class QuestionError < StandardError
|
35
35
|
# do nothing, just creating a unique error type
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# The setting used to disable color output.
|
39
39
|
@@use_color = true
|
40
|
-
|
40
|
+
|
41
41
|
# Pass +false+ to _setting_ to turn off HighLine's color escapes.
|
42
42
|
def self.use_color=( setting )
|
43
43
|
@@use_color = setting
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
# Returns true if HighLine is currently using color escapes.
|
47
47
|
def self.use_color?
|
48
48
|
@@use_color
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
# For checking if the current version of HighLine supports RGB colors
|
52
52
|
# Usage: HighLine.supports_rgb_color? rescue false # rescue for compatibility with older versions
|
53
53
|
# Note: color usage also depends on HighLine.use_color being set
|
54
54
|
def self.supports_rgb_color?
|
55
55
|
true
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# The setting used to disable EOF tracking.
|
59
59
|
@@track_eof = true
|
60
|
-
|
60
|
+
|
61
61
|
# Pass +false+ to _setting_ to turn off HighLine's EOF tracking.
|
62
62
|
def self.track_eof=( setting )
|
63
63
|
@@track_eof = setting
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# Returns true if HighLine is currently tracking EOF for input.
|
67
67
|
def self.track_eof?
|
68
68
|
@@track_eof
|
@@ -71,7 +71,7 @@ class HighLine
|
|
71
71
|
# The setting used to control color schemes.
|
72
72
|
@@color_scheme = nil
|
73
73
|
|
74
|
-
# Pass ColorScheme to _setting_ to
|
74
|
+
# Pass ColorScheme to _setting_ to set a HighLine color scheme.
|
75
75
|
def self.color_scheme=( setting )
|
76
76
|
@@color_scheme = setting
|
77
77
|
end
|
@@ -87,13 +87,13 @@ class HighLine
|
|
87
87
|
end
|
88
88
|
|
89
89
|
#
|
90
|
-
# Embed in a String to clear all previous ANSI sequences. This *MUST* be
|
90
|
+
# Embed in a String to clear all previous ANSI sequences. This *MUST* be
|
91
91
|
# done before the program exits!
|
92
92
|
#
|
93
|
-
|
93
|
+
|
94
94
|
ERASE_LINE_STYLE = Style.new(:name=>:erase_line, :builtin=>true, :code=>"\e[K") # Erase the current line of terminal output
|
95
95
|
ERASE_CHAR_STYLE = Style.new(:name=>:erase_char, :builtin=>true, :code=>"\e[P") # Erase the character under the cursor.
|
96
|
-
CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings
|
96
|
+
CLEAR_STYLE = Style.new(:name=>:clear, :builtin=>true, :code=>"\e[0m") # Clear color settings
|
97
97
|
RESET_STYLE = Style.new(:name=>:reset, :builtin=>true, :code=>"\e[0m") # Alias for CLEAR.
|
98
98
|
BOLD_STYLE = Style.new(:name=>:bold, :builtin=>true, :code=>"\e[1m") # Bold; Note: bold + a color works as you'd expect,
|
99
99
|
# for example bold black. Bold without a color displays
|
@@ -104,7 +104,7 @@ class HighLine
|
|
104
104
|
BLINK_STYLE = Style.new(:name=>:blink, :builtin=>true, :code=>"\e[5m") # Blink; support uncommon
|
105
105
|
REVERSE_STYLE = Style.new(:name=>:reverse, :builtin=>true, :code=>"\e[7m") # Reverse foreground and background
|
106
106
|
CONCEALED_STYLE = Style.new(:name=>:concealed, :builtin=>true, :code=>"\e[8m") # Concealed; support uncommon
|
107
|
-
|
107
|
+
|
108
108
|
STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED}
|
109
109
|
|
110
110
|
# These RGB colors are approximate; see http://en.wikipedia.org/wiki/ANSI_escape_code
|
@@ -116,15 +116,15 @@ class HighLine
|
|
116
116
|
MAGENTA_STYLE = Style.new(:name=>:magenta, :builtin=>true, :code=>"\e[35m", :rgb=>[128, 0,128])
|
117
117
|
CYAN_STYLE = Style.new(:name=>:cyan, :builtin=>true, :code=>"\e[36m", :rgb=>[ 0,128,128])
|
118
118
|
# On Mac OSX Terminal, white is actually gray
|
119
|
-
WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
|
119
|
+
WHITE_STYLE = Style.new(:name=>:white, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
|
120
120
|
# Alias for WHITE, since WHITE is actually a light gray on Macs
|
121
121
|
GRAY_STYLE = Style.new(:name=>:gray, :builtin=>true, :code=>"\e[37m", :rgb=>[192,192,192])
|
122
|
-
# On Mac OSX Terminal, this is black foreground, or bright white background.
|
122
|
+
# On Mac OSX Terminal, this is black foreground, or bright white background.
|
123
123
|
# Also used as base for RGB colors, if available
|
124
|
-
NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0])
|
125
|
-
|
124
|
+
NONE_STYLE = Style.new(:name=>:none, :builtin=>true, :code=>"\e[38m", :rgb=>[ 0, 0, 0])
|
125
|
+
|
126
126
|
BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY NONE}
|
127
|
-
|
127
|
+
|
128
128
|
colors = BASIC_COLORS.dup
|
129
129
|
BASIC_COLORS.each do |color|
|
130
130
|
bright_color = "BRIGHT_#{color}"
|
@@ -132,18 +132,18 @@ class HighLine
|
|
132
132
|
const_set bright_color+'_STYLE', const_get(color + '_STYLE').bright
|
133
133
|
end
|
134
134
|
COLORS = colors
|
135
|
-
|
135
|
+
|
136
136
|
colors.each do |color|
|
137
137
|
const_set color, const_get("#{color}_STYLE").code
|
138
138
|
const_set "ON_#{color}_STYLE", const_get("#{color}_STYLE").on
|
139
139
|
const_set "ON_#{color}", const_get("ON_#{color}_STYLE").code
|
140
140
|
end
|
141
141
|
ON_NONE_STYLE.rgb = [255,255,255] # Override; white background
|
142
|
-
|
142
|
+
|
143
143
|
STYLES.each do |style|
|
144
144
|
const_set style, const_get("#{style}_STYLE").code
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
# For RGB colors:
|
148
148
|
def self.const_missing(name)
|
149
149
|
if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color
|
@@ -174,14 +174,17 @@ class HighLine
|
|
174
174
|
# and _output_.
|
175
175
|
#
|
176
176
|
def initialize( input = $stdin, output = $stdout,
|
177
|
-
wrap_at = nil, page_at = nil )
|
178
|
-
super()
|
177
|
+
wrap_at = nil, page_at = nil, indent_size=3, indent_level=0 )
|
179
178
|
@input = input
|
180
179
|
@output = output
|
181
|
-
|
180
|
+
|
181
|
+
@multi_indent = true
|
182
|
+
@indent_size = indent_size
|
183
|
+
@indent_level = indent_level
|
184
|
+
|
182
185
|
self.wrap_at = wrap_at
|
183
186
|
self.page_at = page_at
|
184
|
-
|
187
|
+
|
185
188
|
@question = nil
|
186
189
|
@answer = nil
|
187
190
|
@menu = nil
|
@@ -190,22 +193,30 @@ class HighLine
|
|
190
193
|
@gather = nil
|
191
194
|
@answers = nil
|
192
195
|
@key = nil
|
196
|
+
|
197
|
+
initialize_system_extensions if respond_to?(:initialize_system_extensions)
|
193
198
|
end
|
194
|
-
|
199
|
+
|
195
200
|
include HighLine::SystemExtensions
|
196
|
-
|
201
|
+
|
197
202
|
# The current column setting for wrapping output.
|
198
203
|
attr_reader :wrap_at
|
199
204
|
# The current row setting for paging output.
|
200
205
|
attr_reader :page_at
|
201
|
-
|
206
|
+
# Indentation over multiple lines
|
207
|
+
attr_accessor :multi_indent
|
208
|
+
# The indentation size
|
209
|
+
attr_accessor :indent_size
|
210
|
+
# The indentation level
|
211
|
+
attr_accessor :indent_level
|
212
|
+
|
202
213
|
#
|
203
214
|
# A shortcut to HighLine.ask() a question that only accepts "yes" or "no"
|
204
215
|
# answers ("y" and "n" are allowed) and returns +true+ or +false+
|
205
216
|
# (+true+ for "yes"). If provided a +true+ value, _character_ will cause
|
206
217
|
# HighLine to fetch a single character response. A block can be provided
|
207
218
|
# to further configure the question as in HighLine.ask()
|
208
|
-
#
|
219
|
+
#
|
209
220
|
# Raises EOFError if input is exhausted.
|
210
221
|
#
|
211
222
|
def agree( yes_or_no_question, character = nil )
|
@@ -214,11 +225,11 @@ class HighLine
|
|
214
225
|
q.responses[:not_valid] = 'Please enter "yes" or "no".'
|
215
226
|
q.responses[:ask_on_error] = :question
|
216
227
|
q.character = character
|
217
|
-
|
228
|
+
|
218
229
|
yield q if block_given?
|
219
230
|
end
|
220
231
|
end
|
221
|
-
|
232
|
+
|
222
233
|
#
|
223
234
|
# This method is the primary interface for user input. Just provide a
|
224
235
|
# _question_ to ask the user, the _answer_type_ you want returned, and
|
@@ -226,20 +237,20 @@ class HighLine
|
|
226
237
|
# handled. See HighLine.say() for details on the format of _question_, and
|
227
238
|
# HighLine::Question for more information about _answer_type_ and what's
|
228
239
|
# valid in the code block.
|
229
|
-
#
|
240
|
+
#
|
230
241
|
# If <tt>@question</tt> is set before ask() is called, parameters are
|
231
242
|
# ignored and that object (must be a HighLine::Question) is used to drive
|
232
243
|
# the process instead.
|
233
|
-
#
|
244
|
+
#
|
234
245
|
# Raises EOFError if input is exhausted.
|
235
246
|
#
|
236
247
|
def ask( question, answer_type = String, &details ) # :yields: question
|
237
248
|
@question ||= Question.new(question, answer_type, &details)
|
238
|
-
|
249
|
+
|
239
250
|
return gather if @question.gather
|
240
|
-
|
241
|
-
# readline() needs to handle
|
242
|
-
# full line reading. Therefore if @question.echo is anything but true,
|
251
|
+
|
252
|
+
# readline() needs to handle its own output, but readline only supports
|
253
|
+
# full line reading. Therefore if @question.echo is anything but true,
|
243
254
|
# the prompt will not be issued. And we have to account for that now.
|
244
255
|
# Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt
|
245
256
|
# to handle line editing properly.
|
@@ -250,14 +261,14 @@ class HighLine
|
|
250
261
|
explain_error(:not_valid)
|
251
262
|
raise QuestionError
|
252
263
|
end
|
253
|
-
|
264
|
+
|
254
265
|
@answer = @question.convert(@answer)
|
255
|
-
|
266
|
+
|
256
267
|
if @question.in_range?(@answer)
|
257
268
|
if @question.confirm
|
258
269
|
# need to add a layer of scope to ask a question inside a
|
259
270
|
# question, without destroying instance data
|
260
|
-
context_change = self.class.new(@input, @output, @wrap_at, @page_at)
|
271
|
+
context_change = self.class.new(@input, @output, @wrap_at, @page_at, @indent_size, @indent_level)
|
261
272
|
if @question.confirm == true
|
262
273
|
confirm_question = "Are you sure? "
|
263
274
|
else
|
@@ -271,7 +282,7 @@ class HighLine
|
|
271
282
|
raise QuestionError
|
272
283
|
end
|
273
284
|
end
|
274
|
-
|
285
|
+
|
275
286
|
@answer
|
276
287
|
else
|
277
288
|
explain_error(:not_in_range)
|
@@ -283,7 +294,7 @@ class HighLine
|
|
283
294
|
raise if error.is_a?(NoMethodError)
|
284
295
|
if error.message =~ /ambiguous/
|
285
296
|
# the assumption here is that OptionParser::Completion#complete
|
286
|
-
# (used for ambiguity resolution) throws exceptions containing
|
297
|
+
# (used for ambiguity resolution) throws exceptions containing
|
287
298
|
# the word 'ambiguous' whenever resolution fails
|
288
299
|
explain_error(:ambiguous_completion)
|
289
300
|
else
|
@@ -302,21 +313,23 @@ class HighLine
|
|
302
313
|
# This method is HighLine's menu handler. For simple usage, you can just
|
303
314
|
# pass all the menu items you wish to display. At that point, choose() will
|
304
315
|
# build and display a menu, walk the user through selection, and return
|
305
|
-
# their choice
|
316
|
+
# their choice among the provided items. You might use this in a case
|
306
317
|
# statement for quick and dirty menus.
|
307
|
-
#
|
318
|
+
#
|
308
319
|
# However, choose() is capable of much more. If provided, a block will be
|
309
320
|
# passed a HighLine::Menu object to configure. Using this method, you can
|
310
321
|
# customize all the details of menu handling from index display, to building
|
311
322
|
# a complete shell-like menuing system. See HighLine::Menu for all the
|
312
323
|
# methods it responds to.
|
313
|
-
#
|
324
|
+
#
|
314
325
|
# Raises EOFError if input is exhausted.
|
315
|
-
#
|
326
|
+
#
|
316
327
|
def choose( *items, &details )
|
317
328
|
@menu = @question = Menu.new(&details)
|
318
329
|
@menu.choices(*items) unless items.empty?
|
319
|
-
|
330
|
+
|
331
|
+
# Set auto-completion
|
332
|
+
@menu.completion = @menu.options
|
320
333
|
# Set _answer_type_ so we can double as the Question for ask().
|
321
334
|
@menu.answer_type = if @menu.shell
|
322
335
|
lambda do |command| # shell-style selection
|
@@ -335,11 +348,11 @@ class HighLine
|
|
335
348
|
else
|
336
349
|
@menu.options # normal menu selection, by index or name
|
337
350
|
end
|
338
|
-
|
351
|
+
|
339
352
|
# Provide hooks for ERb layouts.
|
340
353
|
@header = @menu.header
|
341
354
|
@prompt = @menu.prompt
|
342
|
-
|
355
|
+
|
343
356
|
if @menu.shell
|
344
357
|
selected = ask("Ignored", @menu.answer_type)
|
345
358
|
@menu.select(self, *selected)
|
@@ -353,11 +366,11 @@ class HighLine
|
|
353
366
|
# This method provides easy access to ANSI color sequences, without the user
|
354
367
|
# needing to remember to CLEAR at the end of each sequence. Just pass the
|
355
368
|
# _string_ to color, followed by a list of _colors_ you would like it to be
|
356
|
-
# affected by. The _colors_ can be HighLine class constants, or symbols
|
369
|
+
# affected by. The _colors_ can be HighLine class constants, or symbols
|
357
370
|
# (:blue for BLUE, for example). A CLEAR will automatically be embedded to
|
358
371
|
# the end of the returned String.
|
359
|
-
#
|
360
|
-
# This method returns the original _string_ unchanged if HighLine::use_color?
|
372
|
+
#
|
373
|
+
# This method returns the original _string_ unchanged if HighLine::use_color?
|
361
374
|
# is +false+.
|
362
375
|
#
|
363
376
|
def self.color( string, *colors )
|
@@ -369,28 +382,28 @@ class HighLine
|
|
369
382
|
def self.color_code(*colors)
|
370
383
|
Style(*colors).code
|
371
384
|
end
|
372
|
-
|
385
|
+
|
373
386
|
# Works as an instance method, same as the class method
|
374
387
|
def color_code(*colors)
|
375
388
|
self.class.color_code(*colors)
|
376
389
|
end
|
377
|
-
|
390
|
+
|
378
391
|
# Works as an instance method, same as the class method
|
379
392
|
def color(*args)
|
380
393
|
self.class.color(*args)
|
381
394
|
end
|
382
|
-
|
395
|
+
|
383
396
|
# Remove color codes from a string
|
384
397
|
def self.uncolor(string)
|
385
398
|
Style.uncolor(string)
|
386
399
|
end
|
387
|
-
|
400
|
+
|
388
401
|
# Works as an instance method, same as the class method
|
389
402
|
def uncolor(string)
|
390
403
|
self.class.uncolor(string)
|
391
404
|
end
|
392
|
-
|
393
|
-
#
|
405
|
+
|
406
|
+
#
|
394
407
|
# This method is a utility for quickly and easily laying out lists. It can
|
395
408
|
# be accessed within ERb replacements of any text that will be sent to the
|
396
409
|
# user.
|
@@ -416,13 +429,13 @@ class HighLine
|
|
416
429
|
# _option_ or a default of " or ". All
|
417
430
|
# other _items_ are separated by ", ".
|
418
431
|
# <tt>:rows</tt>:: The default mode. Each of the _items_ is
|
419
|
-
# placed on
|
432
|
+
# placed on its own line. The _option_
|
420
433
|
# parameter is ignored in this mode.
|
421
|
-
#
|
434
|
+
#
|
422
435
|
# Each member of the _items_ Array is passed through ERb and thus can contain
|
423
|
-
# their own expansions. Color escape expansions do not contribute to the
|
436
|
+
# their own expansions. Color escape expansions do not contribute to the
|
424
437
|
# final field width.
|
425
|
-
#
|
438
|
+
#
|
426
439
|
def list( items, mode = :rows, option = nil )
|
427
440
|
items = items.to_ary.map do |item|
|
428
441
|
if item.nil?
|
@@ -431,14 +444,14 @@ class HighLine
|
|
431
444
|
ERB.new(item, nil, "%").result(binding)
|
432
445
|
end
|
433
446
|
end
|
434
|
-
|
447
|
+
|
435
448
|
if items.empty?
|
436
449
|
""
|
437
450
|
else
|
438
451
|
case mode
|
439
452
|
when :inline
|
440
453
|
option = " or " if option.nil?
|
441
|
-
|
454
|
+
|
442
455
|
if items.size == 1
|
443
456
|
items.first
|
444
457
|
else
|
@@ -459,7 +472,7 @@ class HighLine
|
|
459
472
|
"%-#{pad}s" % item
|
460
473
|
end
|
461
474
|
row_count = (items.size / option.to_f).ceil
|
462
|
-
|
475
|
+
|
463
476
|
if mode == :columns_across
|
464
477
|
rows = Array.new(row_count) { Array.new }
|
465
478
|
items.each_with_index do |item, index|
|
@@ -472,7 +485,7 @@ class HighLine
|
|
472
485
|
items.each_with_index do |item, index|
|
473
486
|
columns[index / row_count] << item
|
474
487
|
end
|
475
|
-
|
488
|
+
|
476
489
|
list = ""
|
477
490
|
columns.first.size.times do |index|
|
478
491
|
list << columns.map { |column| column[index] }.
|
@@ -588,79 +601,113 @@ class HighLine
|
|
588
601
|
end
|
589
602
|
end
|
590
603
|
end
|
591
|
-
|
604
|
+
|
592
605
|
#
|
593
606
|
# The basic output method for HighLine objects. If the provided _statement_
|
594
607
|
# ends with a space or tab character, a newline will not be appended (output
|
595
608
|
# will be flush()ed). All other cases are passed straight to Kernel.puts().
|
596
609
|
#
|
597
610
|
# The _statement_ parameter is processed as an ERb template, supporting
|
598
|
-
# embedded Ruby code. The template is evaluated with a binding inside
|
611
|
+
# embedded Ruby code. The template is evaluated with a binding inside
|
599
612
|
# the HighLine instance, providing easy access to the ANSI color constants
|
600
613
|
# and the HighLine.color() method.
|
601
614
|
#
|
602
615
|
def say( statement )
|
603
616
|
statement = statement.to_str
|
604
617
|
return unless statement.length > 0
|
605
|
-
|
618
|
+
|
606
619
|
template = ERB.new(statement, nil, "%")
|
607
620
|
statement = template.result(binding)
|
608
|
-
|
621
|
+
|
609
622
|
statement = wrap(statement) unless @wrap_at.nil?
|
610
623
|
statement = page_print(statement) unless @page_at.nil?
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
624
|
+
|
625
|
+
statement = statement.gsub(/\n(?!$)/,"\n#{indentation}") if @multi_indent
|
626
|
+
|
627
|
+
# Don't add a newline if statement ends with whitespace, OR
|
628
|
+
# if statement ends with whitespace before a color escape code.
|
629
|
+
if /[ \t](\e\[\d+(;\d+)*m)?\Z/ =~ statement
|
630
|
+
@output.print(indentation+statement)
|
631
|
+
@output.flush
|
615
632
|
else
|
616
|
-
@output.puts(statement)
|
633
|
+
@output.puts(indentation+statement)
|
617
634
|
end
|
618
635
|
end
|
619
|
-
|
636
|
+
|
620
637
|
#
|
621
638
|
# Set to an integer value to cause HighLine to wrap output lines at the
|
622
639
|
# indicated character limit. When +nil+, the default, no wrapping occurs. If
|
623
|
-
# set to <tt>:auto</tt>, HighLine will attempt to
|
640
|
+
# set to <tt>:auto</tt>, HighLine will attempt to determine the columns
|
624
641
|
# available for the <tt>@output</tt> or use a sensible default.
|
625
642
|
#
|
626
643
|
def wrap_at=( setting )
|
627
644
|
@wrap_at = setting == :auto ? output_cols : setting
|
628
645
|
end
|
629
|
-
|
646
|
+
|
630
647
|
#
|
631
648
|
# Set to an integer value to cause HighLine to page output lines over the
|
632
649
|
# indicated line limit. When +nil+, the default, no paging occurs. If
|
633
|
-
# set to <tt>:auto</tt>, HighLine will attempt to
|
650
|
+
# set to <tt>:auto</tt>, HighLine will attempt to determine the rows available
|
634
651
|
# for the <tt>@output</tt> or use a sensible default.
|
635
652
|
#
|
636
653
|
def page_at=( setting )
|
637
654
|
@page_at = setting == :auto ? output_rows - 2 : setting
|
638
655
|
end
|
639
|
-
|
640
|
-
#
|
656
|
+
|
657
|
+
#
|
658
|
+
# Outputs indentation with current settings
|
659
|
+
#
|
660
|
+
def indentation
|
661
|
+
return ' '*@indent_size*@indent_level
|
662
|
+
end
|
663
|
+
|
664
|
+
#
|
665
|
+
# Executes block or outputs statement with indentation
|
666
|
+
#
|
667
|
+
def indent(increase=1, statement=nil, multiline=nil)
|
668
|
+
@indent_level += increase
|
669
|
+
multi = @multi_indent
|
670
|
+
@multi_indent = multiline unless multiline.nil?
|
671
|
+
if block_given?
|
672
|
+
yield self
|
673
|
+
else
|
674
|
+
say(statement)
|
675
|
+
end
|
676
|
+
@multi_indent = multi
|
677
|
+
@indent_level -= increase
|
678
|
+
end
|
679
|
+
|
680
|
+
#
|
681
|
+
# Outputs newline
|
682
|
+
#
|
683
|
+
def newline
|
684
|
+
@output.puts
|
685
|
+
end
|
686
|
+
|
687
|
+
#
|
641
688
|
# Returns the number of columns for the console, or a default it they cannot
|
642
689
|
# be determined.
|
643
|
-
#
|
690
|
+
#
|
644
691
|
def output_cols
|
645
692
|
return 80 unless @output.tty?
|
646
693
|
terminal_size.first
|
647
694
|
rescue
|
648
695
|
return 80
|
649
696
|
end
|
650
|
-
|
651
|
-
#
|
697
|
+
|
698
|
+
#
|
652
699
|
# Returns the number of rows for the console, or a default if they cannot be
|
653
700
|
# determined.
|
654
|
-
#
|
701
|
+
#
|
655
702
|
def output_rows
|
656
703
|
return 24 unless @output.tty?
|
657
704
|
terminal_size.last
|
658
705
|
rescue
|
659
706
|
return 24
|
660
707
|
end
|
661
|
-
|
708
|
+
|
662
709
|
private
|
663
|
-
|
710
|
+
|
664
711
|
#
|
665
712
|
# A helper method for sending the output stream and error and repeat
|
666
713
|
# of the question.
|
@@ -673,13 +720,13 @@ class HighLine
|
|
673
720
|
say(@question.responses[:ask_on_error])
|
674
721
|
end
|
675
722
|
end
|
676
|
-
|
723
|
+
|
677
724
|
#
|
678
|
-
# Collects an Array/Hash full of answers as described in
|
725
|
+
# Collects an Array/Hash full of answers as described in
|
679
726
|
# HighLine::Question.gather().
|
680
|
-
#
|
727
|
+
#
|
681
728
|
# Raises EOFError if input is exhausted.
|
682
|
-
#
|
729
|
+
#
|
683
730
|
def gather( )
|
684
731
|
original_question = @question
|
685
732
|
original_question_string = @question.question
|
@@ -748,10 +795,10 @@ class HighLine
|
|
748
795
|
#
|
749
796
|
# Read a line of input from the input stream and process whitespace as
|
750
797
|
# requested by the Question object.
|
751
|
-
#
|
798
|
+
#
|
752
799
|
# If Question's _readline_ property is set, that library will be used to
|
753
800
|
# fetch input. *WARNING*: This ignores the currently set input stream.
|
754
|
-
#
|
801
|
+
#
|
755
802
|
# Raises EOFError if input is exhausted.
|
756
803
|
#
|
757
804
|
def get_line( )
|
@@ -764,12 +811,12 @@ class HighLine
|
|
764
811
|
say(@question)
|
765
812
|
question = @output.string
|
766
813
|
@output = old_output
|
767
|
-
|
814
|
+
|
768
815
|
# prep auto-completion
|
769
816
|
Readline.completion_proc = lambda do |string|
|
770
817
|
@question.selection.grep(/\A#{Regexp.escape(string)}/)
|
771
818
|
end
|
772
|
-
|
819
|
+
|
773
820
|
# work-around ugly readline() warnings
|
774
821
|
old_verbose = $VERBOSE
|
775
822
|
$VERBOSE = nil
|
@@ -803,16 +850,14 @@ class HighLine
|
|
803
850
|
# Return a line or character of input, as requested for this question.
|
804
851
|
# Character input will be returned as a single character String,
|
805
852
|
# not an Integer.
|
806
|
-
#
|
853
|
+
#
|
807
854
|
# This question's _first_answer_ will be returned instead of input, if set.
|
808
|
-
#
|
855
|
+
#
|
809
856
|
# Raises EOFError if input is exhausted.
|
810
857
|
#
|
811
858
|
def get_response( )
|
812
859
|
return @question.first_answer if @question.first_answer?
|
813
860
|
|
814
|
-
stty = (CHARACTER_MODE == "stty")
|
815
|
-
|
816
861
|
if @question.character.nil?
|
817
862
|
if @question.echo == true and @question.limit.nil?
|
818
863
|
get_line
|
@@ -894,15 +939,15 @@ class HighLine
|
|
894
939
|
@question.change_case(response)
|
895
940
|
end
|
896
941
|
end
|
897
|
-
|
898
|
-
#
|
942
|
+
|
943
|
+
#
|
899
944
|
# Page print a series of at most _page_at_ lines for _output_. After each
|
900
945
|
# page is printed, HighLine will pause until the user presses enter/return
|
901
946
|
# then display the next page of data.
|
902
947
|
#
|
903
948
|
# Note that the final page of _output_ is *not* printed, but returned
|
904
949
|
# instead. This is to support any special handling for the final sequence.
|
905
|
-
#
|
950
|
+
#
|
906
951
|
def page_print( output )
|
907
952
|
lines = output.scan(/[^\n]*\n?/)
|
908
953
|
while lines.size > @page_at
|
@@ -913,18 +958,18 @@ class HighLine
|
|
913
958
|
end
|
914
959
|
return lines.join
|
915
960
|
end
|
916
|
-
|
917
|
-
#
|
961
|
+
|
962
|
+
#
|
918
963
|
# Ask user if they wish to continue paging output. Allows them to type "q" to
|
919
964
|
# cancel the paging process.
|
920
|
-
#
|
965
|
+
#
|
921
966
|
def continue_paging?
|
922
967
|
command = HighLine.new(@input, @output).ask(
|
923
968
|
"-- press enter/return to continue or q to stop -- "
|
924
969
|
) { |q| q.character = true }
|
925
970
|
command !~ /\A[qQ]\Z/ # Only continue paging if Q was not hit.
|
926
971
|
end
|
927
|
-
|
972
|
+
|
928
973
|
#
|
929
974
|
# Wrap a sequence of _lines_ at _wrap_at_ characters per line. Existing
|
930
975
|
# newlines will not be affected by this process, but additional newlines
|
@@ -950,15 +995,14 @@ class HighLine
|
|
950
995
|
end
|
951
996
|
return wrapped.join
|
952
997
|
end
|
953
|
-
|
954
|
-
#
|
998
|
+
|
999
|
+
#
|
955
1000
|
# Returns the length of the passed +string_with_escapes+, minus and color
|
956
1001
|
# sequence escapes.
|
957
|
-
#
|
1002
|
+
#
|
958
1003
|
def actual_length( string_with_escapes )
|
959
1004
|
string_with_escapes.to_s.gsub(/\e\[\d{1,2}m/, "").length
|
960
1005
|
end
|
961
1006
|
end
|
962
1007
|
|
963
1008
|
require "highline/string_extensions"
|
964
|
-
|