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 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
-