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.
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
 
@@ -23,13 +23,13 @@ class NameClass
23
23
  def initialize(first, last)
24
24
  @first, @last = first, last
25
25
  end
26
-
26
+
27
27
  attr_reader :first, :last
28
28
  end
29
29
 
30
30
  begin
31
31
  entry = Hash.new
32
-
32
+
33
33
  # basic output
34
34
  say("Enter a contact:")
35
35
 
@@ -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'
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "highline/import"
5
+
6
+ choices = "ynaq"
7
+ answer = ask("Your choice [#{choices}]? ") do |q|
8
+ q.echo = false
9
+ q.character = true
10
+ q.validate = /\A[#{choices}]\Z/
11
+ end
12
+ say("Your choice: #{answer}")
data/examples/limit.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby -w
2
2
 
3
3
  # limit.rb
4
- #
4
+ #
5
5
  # Created by James Edward Gray II on 2008-11-12.
6
6
  # Copyright 2008 Gray Productions. All rights reserved.
7
7
 
data/examples/menus.rb CHANGED
@@ -51,9 +51,9 @@ say("\nYou can even build shells...")
51
51
  loop do
52
52
  choose do |menu|
53
53
  menu.layout = :menu_only
54
-
54
+
55
55
  menu.shell = true
56
-
56
+
57
57
  menu.choice(:load, "Load a file.") do |command, details|
58
58
  say("Loading file with options: #{details}...")
59
59
  end
@@ -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'
@@ -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.15".freeze
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 turn set a HighLine color scheme.
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 it's own output, but readline only supports
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 amoung the provided items. You might use this in a case
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 it's own line. The _option_
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
- if statement[-1, 1] == " " or statement[-1, 1] == "\t"
613
- @output.print(statement)
614
- @output.flush
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 determing the columns
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 determing the rows available
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
-