Parent

Included Modules

HighLine

A HighLine object is a “high-level line oriented” shell over an input and an output stream. HighLine simplifies common console interaction, effectively replacing puts() and gets(). User code can simply specify the question to ask and any details about user interaction, then leave the rest of the work to HighLine. When HighLine.ask() returns, you’ll have the answer you requested, even if HighLine had to ask many times, validate results, perform range checking, convert types, etc.


color_scheme.rb

Created by Jeremy Hinegardner on 2007-01-24 Copyright 2007. All rights reserved

This is Free Software. See LICENSE and COPYING for details


simulate.rb

 Created by Andy Rossmeissl on 2012-04-29.
 Copyright 2005 Gray Productions. All rights reserved.

 This is Free Software.  See LICENSE and COPYING for details.

adapted from gist.github.com/194554


Extensions for class String

HighLine::String is a subclass of String with convenience methods added for colorization.

Available convenience methods include:

  * 'color' method         e.g.  highline_string.color(:bright_blue, :underline)
  * colors                 e.g.  highline_string.magenta
  * RGB colors             e.g.  highline_string.rgb_ff6000
                            or   highline_string.rgb(255,96,0)
  * background colors      e.g.  highline_string.on_magenta
  * RGB background colors  e.g.  highline_string.on_rgb_ff6000
                            or   highline_string.on_rgb(255,96,0)
  * styles                 e.g.  highline_string.underline

Additionally, convenience methods can be chained, for instance the following are equivalent:

  highline_string.bright_blue.blink.underline
  highline_string.color(:bright_blue, :blink, :underline)
  HighLine.color(highline_string, :bright_blue, :blink, :underline)

For those less squeamish about possible conflicts, the same convenience methods can be added to the builtin String class, as follows:

 require 'highline'
 Highline.colorize_strings

color_scheme.rb

Created by Richard LeBer on 2011-06-27. Copyright 2011. All rights reserved

This is Free Software. See LICENSE and COPYING for details

Constants

VERSION

The version of the installed library.

ERASE_LINE_STYLE

Embed in a String to clear all previous ANSI sequences. This MUST be done before the program exits!

ERASE_CHAR_STYLE
CLEAR_STYLE
RESET_STYLE
BOLD_STYLE
DARK_STYLE

for example bold black. Bold without a color displays the system-defined bold color (e.g. red on Mac iTerm)

UNDERLINE_STYLE
UNDERSCORE_STYLE
BLINK_STYLE
REVERSE_STYLE
CONCEALED_STYLE
STYLES
BLACK_STYLE

These RGB colors are approximate; see en.wikipedia.org/wiki/ANSI_escape_code

RED_STYLE
GREEN_STYLE
BLUE_STYLE
YELLOW_STYLE
MAGENTA_STYLE
CYAN_STYLE
WHITE_STYLE

On Mac OSX Terminal, white is actually gray

GRAY_STYLE

Alias for WHITE, since WHITE is actually a light gray on Macs

NONE_STYLE

On Mac OSX Terminal, this is black foreground, or bright white background. Also used as base for RGB colors, if available

BASIC_COLORS
COLORS

Attributes

wrap_at[R]

The current column setting for wrapping output.

page_at[R]

The current row setting for paging output.

Public Class Methods

String(s) click to toggle source
    # File lib/highline/string_extensions.rb, line 27
27:   def self.String(s)
28:     HighLine::String.new(s)
29:   end
Style(*args) click to toggle source
    # File lib/highline/style.rb, line 12
12:   def self.Style(*args)
13:     args = args.compact.flatten
14:     if args.size==1
15:       arg = args.first
16:       if arg.is_a?(Style)
17:         Style.list[arg.name] || Style.index(arg)
18:       elsif arg.is_a?(::String) && arg =~ /^\e\[/ # arg is a code
19:         if styles = Style.code_index[arg]
20:           styles.first
21:         else
22:           Style.new(:code=>arg)
23:         end
24:       elsif style = Style.list[arg]
25:         style
26:       elsif HighLine.color_scheme && HighLine.color_scheme[arg]
27:         HighLine.color_scheme[arg]
28:       elsif arg.is_a?(Hash)
29:         Style.new(arg)
30:       elsif arg.to_s.downcase =~ /^rgb_([a-f0-9]{6})$/
31:         Style.rgb($1)
32:       elsif arg.to_s.downcase =~ /^on_rgb_([a-f0-9]{6})$/
33:         Style.rgb($1).on
34:       else
35:         raise NameError, "#{arg.inspect} is not a defined Style"
36:       end
37:     else
38:       name = args
39:       Style.list[name] || Style.new(:list=>args)
40:     end
41:   end
color( string, *colors ) click to toggle source

This method provides easy access to ANSI color sequences, without the user needing to remember to CLEAR at the end of each sequence. Just pass the string to color, followed by a list of colors you would like it to be affected by. The colors can be HighLine class constants, or symbols (:blue for BLUE, for example). A CLEAR will automatically be embedded to the end of the returned String.

This method returns the original string unchanged if HighLine::use_color? is false.

     # File lib/highline.rb, line 377
377:   def self.color( string, *colors )
378:     return string unless self.use_color?
379:     Style(*colors).color(string)
380:   end
color_code(*colors) click to toggle source

In case you just want the color code, without the embedding and the CLEAR

     # File lib/highline.rb, line 383
383:   def self.color_code(*colors)
384:     Style(*colors).code
385:   end
color_scheme() click to toggle source

Returns the current color scheme.

    # File lib/highline.rb, line 82
82:   def self.color_scheme
83:     @@color_scheme
84:   end
color_scheme=( setting ) click to toggle source

Pass ColorScheme to setting to turn set a HighLine color scheme.

    # File lib/highline.rb, line 77
77:   def self.color_scheme=( setting )
78:     @@color_scheme = setting
79:   end
colorize_strings() click to toggle source
     # File lib/highline/string_extensions.rb, line 128
128:   def self.colorize_strings
129:     ::String.send(:include, StringExtensions)
130:   end
const_missing(name) click to toggle source

For RGB colors:

     # File lib/highline.rb, line 150
150:   def self.const_missing(name)
151:     if name.to_s =~ /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/ # RGB color
152:       on = $1
153:       suffix = $4
154:       if suffix
155:         code_name = $1.to_s + $2 + $3
156:       else
157:         code_name = name.to_s
158:       end
159:       style_name = code_name + '_STYLE'
160:       style = Style.rgb($3)
161:       style = style.on if on
162:       const_set(style_name, style)
163:       const_set(code_name, style.code)
164:       if suffix
165:         style
166:       else
167:         style.code
168:       end
169:     else
170:       raise NameError, "Bad color or uninitialized constant #{name}"
171:     end
172:   end
new( input = $stdin, output = $stdout, wrap_at = nil, page_at = nil ) click to toggle source

Create an instance of HighLine, connected to the streams input and output.

     # File lib/highline.rb, line 178
178:   def initialize( input = $stdin, output = $stdout,
179:                   wrap_at = nil, page_at = nil )
180:     @input   = input
181:     @output  = output
182:     if JRUBY
183:       require 'java'
184:       java_import 'java.io.OutputStreamWriter'
185:       java_import 'java.nio.channels.Channels'
186:       java_import 'jline.ConsoleReader'
187:       java_import 'jline.Terminal'
188: 
189:       @java_input = Channels.newInputStream($stdin.to_channel)
190:       @java_output = OutputStreamWriter.new(Channels.newOutputStream($stdout.to_channel))
191:       @java_terminal = Terminal.getTerminal
192:       @java_console = ConsoleReader.new(@java_input, @java_output)
193:       @java_console.setUseHistory(false)
194:       @java_console.setBellEnabled(true)
195:       @java_console.setUsePagination(false)
196:     end
197:     
198:     self.wrap_at = wrap_at
199:     self.page_at = page_at
200:     
201:     @question = nil
202:     @answer   = nil
203:     @menu     = nil
204:     @header   = nil
205:     @prompt   = nil
206:     @gather   = nil
207:     @answers  = nil
208:     @key      = nil
209:   end
supports_rgb_color?() click to toggle source

For checking if the current version of HighLine supports RGB colors Usage: HighLine.supports_rgb_color? rescue false # rescue for compatibility with older versions Note: color usage also depends on HighLine.use_color being set

    # File lib/highline.rb, line 56
56:   def self.supports_rgb_color?
57:     true
58:   end
track_eof=( setting ) click to toggle source

Pass false to setting to turn off HighLine’s EOF tracking.

    # File lib/highline.rb, line 64
64:   def self.track_eof=( setting )
65:     @@track_eof = setting
66:   end
track_eof?() click to toggle source

Returns true if HighLine is currently tracking EOF for input.

    # File lib/highline.rb, line 69
69:   def self.track_eof?
70:     @@track_eof
71:   end
uncolor(string) click to toggle source

Remove color codes from a string

     # File lib/highline.rb, line 398
398:   def self.uncolor(string)
399:     Style.uncolor(string)
400:   end
use_color=( setting ) click to toggle source

Pass false to setting to turn off HighLine’s color escapes.

    # File lib/highline.rb, line 44
44:   def self.use_color=( setting )
45:     @@use_color = setting
46:   end
use_color?() click to toggle source

Returns true if HighLine is currently using color escapes.

    # File lib/highline.rb, line 49
49:   def self.use_color?
50:     @@use_color
51:   end
using_color_scheme?() click to toggle source

Returns true if HighLine is currently using a color scheme.

    # File lib/highline.rb, line 87
87:   def self.using_color_scheme?
88:     not @@color_scheme.nil?
89:   end

Public Instance Methods

agree( yes_or_no_question, character = nil ) click to toggle source

A shortcut to HighLine.ask() a question that only accepts “yes” or “no” answers (“y” and “n” are allowed) and returns true or false (true for “yes”). If provided a true value, character will cause HighLine to fetch a single character response. A block can be provided to further configure the question as in HighLine.ask()

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 227
227:   def agree( yes_or_no_question, character = nil )
228:     ask(yes_or_no_question, lambda { |yn| yn.downcase[0] == yy}) do |q|
229:       q.validate                 = /\Ay(?:es)?|no?\Z/
230:       q.responses[:not_valid]    = 'Please enter "yes" or "no".'
231:       q.responses[:ask_on_error] = :question
232:       q.character                = character
233:       
234:       yield q if block_given?
235:     end
236:   end
ask( question, answer_type = String ) click to toggle source

This method is the primary interface for user input. Just provide a question to ask the user, the answer_type you want returned, and optionally a code block setting up details of how you want the question handled. See HighLine.say() for details on the format of question, and HighLine::Question for more information about answer_type and what’s valid in the code block.

If @question is set before ask() is called, parameters are ignored and that object (must be a HighLine::Question) is used to drive the process instead.

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 252
252:   def ask( question, answer_type = String, &details ) # :yields: question
253:     @question ||= Question.new(question, answer_type, &details)
254:     
255:     return gather if @question.gather
256:   
257:     # readline() needs to handle it's own output, but readline only supports 
258:     # full line reading.  Therefore if @question.echo is anything but true, 
259:     # the prompt will not be issued. And we have to account for that now.
260:     say(@question) unless (@question.readline and @question.echo == true)
261:     begin
262:       @answer = @question.answer_or_default(get_response)
263:       unless @question.valid_answer?(@answer)
264:         explain_error(:not_valid)
265:         raise QuestionError
266:       end
267:       
268:       @answer = @question.convert(@answer)
269:       
270:       if @question.in_range?(@answer)
271:         if @question.confirm
272:           # need to add a layer of scope to ask a question inside a
273:           # question, without destroying instance data
274:           context_change = self.class.new(@input, @output, @wrap_at, @page_at)
275:           if @question.confirm == true
276:             confirm_question = "Are you sure?  "
277:           else
278:             # evaluate ERb under initial scope, so it will have
279:             # access to @question and @answer
280:             template  = ERB.new(@question.confirm, nil, "%")
281:             confirm_question = template.result(binding)
282:           end
283:           unless context_change.agree(confirm_question)
284:             explain_error(nil)
285:             raise QuestionError
286:           end
287:         end
288:         
289:         @answer
290:       else
291:         explain_error(:not_in_range)
292:         raise QuestionError
293:       end
294:     rescue QuestionError
295:       retry
296:     rescue ArgumentError, NameError => error
297:       raise if error.is_a?(NoMethodError)
298:       if error.message =~ /ambiguous/
299:         # the assumption here is that OptionParser::Completion#complete
300:         # (used for ambiguity resolution) throws exceptions containing 
301:         # the word 'ambiguous' whenever resolution fails
302:         explain_error(:ambiguous_completion)
303:       else
304:         explain_error(:invalid_type)
305:       end
306:       retry
307:     rescue Question::NoAutoCompleteMatch
308:       explain_error(:no_completion)
309:       retry
310:     ensure
311:       @question = nil    # Reset Question object.
312:     end
313:   end
choose( *items, &details ) click to toggle source

This method is HighLine’s menu handler. For simple usage, you can just pass all the menu items you wish to display. At that point, choose() will build and display a menu, walk the user through selection, and return their choice amoung the provided items. You might use this in a case statement for quick and dirty menus.

However, choose() is capable of much more. If provided, a block will be passed a HighLine::Menu object to configure. Using this method, you can customize all the details of menu handling from index display, to building a complete shell-like menuing system. See HighLine::Menu for all the methods it responds to.

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 330
330:   def choose( *items, &details )
331:     @menu = @question = Menu.new(&details)
332:     @menu.choices(*items) unless items.empty?
333:     
334:     # Set _answer_type_ so we can double as the Question for ask().
335:     @menu.answer_type = if @menu.shell
336:       lambda do |command|    # shell-style selection
337:         first_word = command.to_s.split.first || ""
338: 
339:         options = @menu.options
340:         options.extend(OptionParser::Completion)
341:         answer = options.complete(first_word)
342: 
343:         if answer.nil?
344:           raise Question::NoAutoCompleteMatch
345:         end
346: 
347:         [answer.last, command.sub(/^\s*#{first_word}\s*/, "")]
348:       end
349:     else
350:       @menu.options          # normal menu selection, by index or name
351:     end
352:     
353:     # Provide hooks for ERb layouts.
354:     @header   = @menu.header
355:     @prompt   = @menu.prompt
356:     
357:     if @menu.shell
358:       selected = ask("Ignored", @menu.answer_type)
359:       @menu.select(self, *selected)
360:     else
361:       selected = ask("Ignored", @menu.answer_type)
362:       @menu.select(self, selected)
363:     end
364:   end
color(*args) click to toggle source

Works as an instance method, same as the class method

     # File lib/highline.rb, line 393
393:   def color(*args)
394:     self.class.color(*args)
395:   end
color_code(*colors) click to toggle source

Works as an instance method, same as the class method

     # File lib/highline.rb, line 388
388:   def color_code(*colors)
389:     self.class.color_code(*colors)
390:   end
list( items, mode = :rows, option = nil ) click to toggle source

This method is a utility for quickly and easily laying out lists. It can be accessed within ERb replacements of any text that will be sent to the user.

The only required parameter is items, which should be the Array of items to list. A specified mode controls how that list is formed and option has different effects, depending on the mode. Recognized modes are:

:columns_across

items will be placed in columns, flowing from left to right. If given, option is the number of columns to be used. When absent, columns will be determined based on wrap_at or a default of 80 characters.

:columns_down

Identical to :columns_across, save flow goes down.

:uneven_columns_across

Like :columns_across but each column is sized independently.

:uneven_columns_down

Like :columns_down but each column is sized independently.

:inline

All items are placed on a single line. The last two items are separated by option or a default of “ or “. All other items are separated by “, “.

:rows

The default mode. Each of the items is placed on it’s own line. The option parameter is ignored in this mode.

Each member of the items Array is passed through ERb and thus can contain their own expansions. Color escape expansions do not contribute to the final field width.

     # File lib/highline.rb, line 440
440:   def list( items, mode = :rows, option = nil )
441:     items = items.to_ary.map do |item|
442:       ERB.new(item, nil, "%").result(binding)
443:     end
444:     
445:     if items.empty?
446:       ""
447:     else
448:       case mode
449:       when :inline
450:         option = " or " if option.nil?
451:         
452:         if items.size == 1
453:           items.first
454:         else
455:           items[0..2].join(", ") + "#{option}#{items.last}"
456:         end
457:       when :columns_across, :columns_down
458:         max_length = actual_length(
459:           items.max { |a, b| actual_length(a) <=> actual_length(b) }
460:         )
461: 
462:         if option.nil?
463:           limit  = @wrap_at || 80
464:           option = (limit + 2) / (max_length + 2)
465:         end
466: 
467:         items = items.map do |item|
468:           pad = max_length + (item.to_s.length - actual_length(item))
469:           "%-#{pad}s" % item
470:         end
471:         row_count = (items.size / option.to_f).ceil
472:       
473:         if mode == :columns_across
474:           rows = Array.new(row_count) { Array.new }
475:           items.each_with_index do |item, index|
476:             rows[index / option] << item
477:           end
478: 
479:           rows.map { |row| row.join("  ") + "\n" }.join
480:         else
481:           columns = Array.new(option) { Array.new }
482:           items.each_with_index do |item, index|
483:             columns[index / row_count] << item
484:           end
485:       
486:           list = ""
487:           columns.first.size.times do |index|
488:             list << columns.map { |column| column[index] }.
489:                             compact.join("  ") + "\n"
490:           end
491:           list
492:         end
493:       when :uneven_columns_across
494:         if option.nil?
495:           limit = @wrap_at || 80
496:           items.size.downto(1) do |column_count|
497:             row_count = (items.size / column_count.to_f).ceil
498:             rows      = Array.new(row_count) { Array.new }
499:             items.each_with_index do |item, index|
500:               rows[index / column_count] << item
501:             end
502: 
503:             widths = Array.new(column_count, 0)
504:             rows.each do |row|
505:               row.each_with_index do |field, column|
506:                 size           = actual_length(field)
507:                 widths[column] = size if size > widths[column]
508:               end
509:             end
510: 
511:             if column_count == 1 or
512:                widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2
513:               return rows.map { |row|
514:                 row.zip(widths).map { |field, i|
515:                   "%-#{i + (field.to_s.length - actual_length(field))}s" % field
516:                 }.join("  ") + "\n"
517:               }.join
518:             end
519:           end
520:         else
521:           row_count = (items.size / option.to_f).ceil
522:           rows      = Array.new(row_count) { Array.new }
523:           items.each_with_index do |item, index|
524:             rows[index / option] << item
525:           end
526: 
527:           widths = Array.new(option, 0)
528:           rows.each do |row|
529:             row.each_with_index do |field, column|
530:               size           = actual_length(field)
531:               widths[column] = size if size > widths[column]
532:             end
533:           end
534: 
535:           return rows.map { |row|
536:             row.zip(widths).map { |field, i|
537:               "%-#{i + (field.to_s.length - actual_length(field))}s" % field
538:             }.join("  ") + "\n"
539:           }.join
540:         end
541:       when :uneven_columns_down
542:         if option.nil?
543:           limit = @wrap_at || 80
544:           items.size.downto(1) do |column_count|
545:             row_count = (items.size / column_count.to_f).ceil
546:             columns   = Array.new(column_count) { Array.new }
547:             items.each_with_index do |item, index|
548:               columns[index / row_count] << item
549:             end
550: 
551:             widths = Array.new(column_count, 0)
552:             columns.each_with_index do |column, i|
553:               column.each do |field|
554:                 size      = actual_length(field)
555:                 widths[i] = size if size > widths[i]
556:               end
557:             end
558: 
559:             if column_count == 1 or
560:                widths.inject(0) { |sum, n| sum + n + 2 } <= limit + 2
561:               list = ""
562:               columns.first.size.times do |index|
563:                 list << columns.zip(widths).map { |column, width|
564:                   field = column[index]
565:                   "%-#{width + (field.to_s.length - actual_length(field))}s" %
566:                   field
567:                 }.compact.join("  ").strip + "\n"
568:               end
569:               return list
570:             end
571:           end
572:         else
573:           row_count = (items.size / option.to_f).ceil
574:           columns   = Array.new(option) { Array.new }
575:           items.each_with_index do |item, index|
576:             columns[index / row_count] << item
577:           end
578: 
579:           widths = Array.new(option, 0)
580:           columns.each_with_index do |column, i|
581:             column.each do |field|
582:               size      = actual_length(field)
583:               widths[i] = size if size > widths[i]
584:             end
585:           end
586: 
587:           list = ""
588:           columns.first.size.times do |index|
589:             list << columns.zip(widths).map { |column, width|
590:               field = column[index]
591:               "%-#{width + (field.to_s.length - actual_length(field))}s" % field
592:             }.compact.join("  ").strip + "\n"
593:           end
594:           return list
595:         end
596:       else
597:         items.map { |i| "#{i}\n" }.join
598:       end
599:     end
600:   end
output_cols() click to toggle source

Returns the number of columns for the console, or a default it they cannot be determined.

     # File lib/highline.rb, line 654
654:   def output_cols
655:     return 80 unless @output.tty?
656:     terminal_size.first
657:   rescue
658:     return 80
659:   end
output_rows() click to toggle source

Returns the number of rows for the console, or a default if they cannot be determined.

     # File lib/highline.rb, line 665
665:   def output_rows
666:     return 24 unless @output.tty?
667:     terminal_size.last
668:   rescue
669:     return 24
670:   end
page_at=( setting ) click to toggle source

Set to an integer value to cause HighLine to page output lines over the indicated line limit. When nil, the default, no paging occurs. If set to :auto, HighLine will attempt to determing the rows available for the @output or use a sensible default.

     # File lib/highline.rb, line 646
646:   def page_at=( setting )
647:     @page_at = setting == :auto ? output_rows - 2 : setting
648:   end
say( statement ) click to toggle source

The basic output method for HighLine objects. If the provided statement ends with a space or tab character, a newline will not be appended (output will be flush()ed). All other cases are passed straight to Kernel.puts().

The statement parameter is processed as an ERb template, supporting embedded Ruby code. The template is evaluated with a binding inside the HighLine instance, providing easy access to the ANSI color constants and the HighLine.color() method.

     # File lib/highline.rb, line 612
612:   def say( statement )
613:     statement = statement.to_str
614:     return unless statement.length > 0
615:     
616:     template  = ERB.new(statement, nil, "%")
617:     statement = template.result(binding)
618:     
619:     statement = wrap(statement) unless @wrap_at.nil?
620:     statement = page_print(statement) unless @page_at.nil?
621:     
622:     if statement[1, 1] == " " or statement[1, 1] == "\t"
623:       @output.print(statement)
624:       @output.flush  
625:     else
626:       @output.puts(statement)
627:     end
628:   end
uncolor(string) click to toggle source

Works as an instance method, same as the class method

     # File lib/highline.rb, line 403
403:   def uncolor(string)
404:     self.class.uncolor(string)
405:   end
wrap_at=( setting ) click to toggle source

Set to an integer value to cause HighLine to wrap output lines at the indicated character limit. When nil, the default, no wrapping occurs. If set to :auto, HighLine will attempt to determing the columns available for the @output or use a sensible default.

     # File lib/highline.rb, line 636
636:   def wrap_at=( setting )
637:     @wrap_at = setting == :auto ? output_cols : setting
638:   end

Private Instance Methods

actual_length( string_with_escapes ) click to toggle source

Returns the length of the passed string_with_escapes, minus and color sequence escapes.

     # File lib/highline.rb, line 972
972:   def actual_length( string_with_escapes )
973:     string_with_escapes.to_s.gsub(/\e\[\d{1,2}m/, "").length
974:   end
continue_paging?() click to toggle source

Ask user if they wish to continue paging output. Allows them to type “q” to cancel the paging process.

     # File lib/highline.rb, line 937
937:   def continue_paging?
938:     command = HighLine.new(@input, @output).ask(
939:       "-- press enter/return to continue or q to stop -- "
940:     ) { |q| q.character = true }
941:     command !~ /\A[qQ]\Z/  # Only continue paging if Q was not hit.
942:   end
explain_error( error ) click to toggle source

A helper method for sending the output stream and error and repeat of the question.

     # File lib/highline.rb, line 678
678:   def explain_error( error )
679:     say(@question.responses[error]) unless error.nil?
680:     if @question.responses[:ask_on_error] == :question
681:       say(@question)
682:     elsif @question.responses[:ask_on_error]
683:       say(@question.responses[:ask_on_error])
684:     end
685:   end
gather( ) click to toggle source

Collects an Array/Hash full of answers as described in HighLine::Question.gather().

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 693
693:   def gather(  )
694:     @gather           = @question.gather
695:     @answers          = [ ]
696:     original_question = @question
697:     
698:     @question.gather = false
699:     
700:     case @gather
701:     when Integer
702:       @answers << ask(@question)
703:       @gather  -= 1
704: 
705:       original_question.question = ""
706:       until @gather.zero?
707:         @question =  original_question
708:         @answers  << ask(@question)
709:         @gather   -= 1
710:       end
711:     when ::String, Regexp
712:       @answers << ask(@question)
713: 
714:       original_question.question = ""
715:       until (@gather.is_a?(::String) and @answers.last.to_s == @gather) or
716:             (@gather.is_a?(Regexp) and @answers.last.to_s =~ @gather)
717:         @question =  original_question
718:         @answers  << ask(@question)
719:       end
720:       
721:       @answers.pop
722:     when Hash
723:       @answers = { }
724:       @gather.keys.sort.each do |key|
725:         @question     = original_question
726:         @key          = key
727:         @answers[key] = ask(@question)
728:       end
729:     end
730:     
731:     @answers
732:   end
get_line( ) click to toggle source

Read a line of input from the input stream and process whitespace as requested by the Question object.

If Question’s readline property is set, that library will be used to fetch input. WARNING: This ignores the currently set input stream.

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 743
743:   def get_line(  )
744:     if @question.readline
745:       require "readline"    # load only if needed
746: 
747:       # capture say()'s work in a String to feed to readline()
748:       old_output = @output
749:       @output    = StringIO.new
750:       say(@question)
751:       question = @output.string
752:       @output  = old_output
753:       
754:       # prep auto-completion
755:       Readline.completion_proc = lambda do |string|
756:         @question.selection.grep(/\A#{Regexp.escape(string)}/)
757:       end
758:       
759:       # work-around ugly readline() warnings
760:       old_verbose = $VERBOSE
761:       $VERBOSE    = nil
762:       raw_answer  = Readline.readline(question, true)
763:       if raw_answer.nil?
764:         if @@track_eof
765:           raise EOFError, "The input stream is exhausted."
766:         else
767:           raw_answer = String.new # Never return nil
768:         end
769:       end
770:       answer      = @question.change_case(
771:                         @question.remove_whitespace(raw_answer))
772:       $VERBOSE    = old_verbose
773: 
774:       answer
775:     else
776:       if JRUBY
777:         enable_echo_afterwards = @java_terminal.isEchoEnabled
778:         @java_terminal.disableEcho
779:         begin
780:           raw_answer = @java_console.readLine(nil, nil)
781:         ensure
782:           @java_terminal.enableEcho if enable_echo_afterwards
783:         end
784:       else
785:         raise EOFError, "The input stream is exhausted." if @@track_eof and
786:                                                             @input.eof?
787:         raw_answer = @input.gets
788:       end
789: 
790:       @question.change_case(@question.remove_whitespace(raw_answer))
791:     end
792:   end
get_response( ) click to toggle source

Return a line or character of input, as requested for this question. Character input will be returned as a single character String, not an Integer.

This question’s first_answer will be returned instead of input, if set.

Raises EOFError if input is exhausted.

     # File lib/highline.rb, line 813
813:   def get_response(  )
814:     return @question.first_answer if @question.first_answer?
815: 
816:     stty = (CHARACTER_MODE == "stty")
817: 
818:     if @question.character.nil?
819:       if @question.echo == true and @question.limit.nil?
820:         get_line
821:       else
822:         if JRUBY
823:           enable_echo_afterwards = @java_terminal.isEchoEnabled
824:           @java_terminal.disableEcho
825:         elsif stty
826:           raw_no_echo_mode
827:         end
828: 
829:         line            = ""
830:         backspace_limit = 0
831:         begin
832: 
833:           while character = get_single_character(stty)
834:             # honor backspace and delete
835:             if character == 127 or character == 8
836:               line.slice!(1, 1)
837:               backspace_limit -= 1
838:             else
839:               line << character.chr
840:               backspace_limit = line.size
841:             end
842:             # looking for carriage return (decimal 13) or
843:             # newline (decimal 10) in raw input
844:             break if character == 13 or character == 10
845:             if @question.echo != false
846:               if character == 127 or character == 8
847:                 # only backspace if we have characters on the line to
848:                 # eliminate, otherwise we'll tromp over the prompt
849:                 if backspace_limit >= 0 then
850:                   @output.print("\b#{HighLine.Style(:erase_char).code}")
851:                 else
852:                     # do nothing
853:                 end
854:               else
855:                 if @question.echo == true
856:                   @output.print(character.chr)
857:                 else
858:                   @output.print(@question.echo)
859:                 end
860:               end
861:               @output.flush
862:             end
863:             break if @question.limit and line.size == @question.limit
864:           end
865:         ensure
866:           if JRUBY
867:             @java_terminal.enableEcho if enable_echo_afterwards
868:           elsif stty
869:             restore_mode
870:           end
871:         end
872:         if @question.overwrite
873:           @output.print("\r#{HighLine.Style(:erase_line).code}")
874:           @output.flush
875:         else
876:           say("\n")
877:         end
878: 
879:         @question.change_case(@question.remove_whitespace(line))
880:       end
881:     else
882:       if JRUBY
883:         enable_echo_afterwards = @java_terminal.isEchoEnabled
884:         @java_terminal.disableEcho
885:       end
886:       begin
887:         if @question.character == :getc
888:           response = get_single_character(true).chr
889:         else
890:           response = get_single_character(stty).chr
891:           if @question.overwrite
892:             @output.print("\r#{HighLine.Style(:erase_line).code}")
893:             @output.flush
894:           else
895:             echo = if @question.echo == true
896:               response
897:             elsif @question.echo != false
898:               @question.echo
899:             else
900:               ""
901:             end
902:             say("#{echo}\n")
903:           end
904:         end
905:       ensure
906:         if JRUBY
907:           @java_terminal.enableEcho if enable_echo_afterwards
908:         end
909:       end
910:       @question.change_case(response)
911:     end
912:   end
get_single_character(is_stty) click to toggle source
     # File lib/highline.rb, line 794
794:   def get_single_character(is_stty)
795:     if JRUBY
796:       @java_console.readVirtualKey
797:     elsif is_stty
798:       @input.getbyte
799:     else
800:       get_character(@input)
801:     end
802:   end
page_print( output ) click to toggle source

Page print a series of at most page_at lines for output. After each page is printed, HighLine will pause until the user presses enter/return then display the next page of data.

Note that the final page of output is not printed, but returned instead. This is to support any special handling for the final sequence.

     # File lib/highline.rb, line 922
922:   def page_print( output )
923:     lines = output.scan(/[^\n]*\n?/)
924:     while lines.size > @page_at
925:       @output.puts lines.slice!(0...@page_at).join
926:       @output.puts
927:       # Return last line if user wants to abort paging
928:       return (["...\n"] + lines.slice(2,1)).join unless continue_paging?
929:     end
930:     return lines.join
931:   end
wrap( text ) click to toggle source

Wrap a sequence of lines at wrap_at characters per line. Existing newlines will not be affected by this process, but additional newlines may be added.

     # File lib/highline.rb, line 949
949:   def wrap( text )
950:     wrapped = [ ]
951:     text.each_line do |line|
952:       while line =~ /([^\n]{#{@wrap_at + 1},})/
953:         search  = $1.dup
954:         replace = $1.dup
955:         if index = replace.rindex(" ", @wrap_at)
956:           replace[index, 1] = "\n"
957:           replace.sub!(/\n[ \t]+/, "\n")
958:           line.sub!(search, replace)
959:         else
960:           line[$~.begin(1) + @wrap_at, 0] = "\n"
961:         end
962:       end
963:       wrapped << line
964:     end
965:     return wrapped.join
966:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.