Parent

HighLine::Question

Question objects contain all the details of a single invocation of HighLine.ask(). The object is initialized by the parameters passed to HighLine.ask() and then queried to make sure each step of the input process is handled according to the users wishes.

Attributes

question[RW]

The ERb template of the question to be asked.

answer_type[RW]

The type that will be used to convert this answer.

character[RW]

Can be set to true to use HighLine’s cross-platform character reader instead of fetching an entire line of input. (Note: HighLine’s character reader ONLY supports STDIN on Windows and Unix.) Can also be set to :getc to use that method on the input stream.

WARNING: The echo and overwrite attributes for a question are ignored when using the :getc method.

limit[RW]

Allows you to set a character limit for input.

WARNING: This option forces a character by character read.

echo[RW]

Can be set to true or false to control whether or not input will be echoed back to the user. A setting of true will cause echo to match input, but any other true value will be treated as to String to echo for each character typed.

This requires HighLine’s character reader. See the character attribute for details.

Note: When using HighLine to manage echo on Unix based systems, we recommend installing the termios gem. Without it, it’s possible to type fast enough to have letters still show up (when reading character by character only).

readline[RW]

Use the Readline library to fetch input. This allows input editing as well as keeping a history. In addition, tab will auto-complete within an Array of choices or a file listing.

WARNING: This option is incompatible with all of HighLine’s character reading modes and it causes HighLine to ignore the specified input stream.

whitespace[RW]

Used to control whitespace processing for the answer to this question. See HighLine::Question.remove_whitespace() for acceptable settings.

case[RW]

Used to control character case processing for the answer to this question. See HighLine::Question.change_case() for acceptable settings.

default[RW]

Used to provide a default answer to this question.

validate[RW]

If set to a Regexp, the answer must match (before type conversion). Can also be set to a Proc which will be called with the provided answer to validate with a true or false return.

above[RW]

Used to control range checks for answer.

below[RW]

Used to control range checks for answer.

in[RW]

If set, answer must pass an include?() check on this object.

confirm[RW]

Asks a yes or no confirmation question, to ensure a user knows what they have just agreed to. If set to true the question will be, “Are you sure? “ Any other true value for this attribute is assumed to be the question to ask. When false or nil (the default), answers are not confirmed.

gather[RW]

When set, the user will be prompted for multiple answers which will be collected into an Array or Hash and returned as the final answer.

You can set gather to an Integer to have an Array of exactly that many answers collected, or a String/Regexp to match an end input which will not be returned in the Array.

Optionally gather can be set to a Hash. In this case, the question will be asked once for each key and the answers will be returned in a Hash, mapped by key. The @key variable is set before each question is evaluated, so you can use it in your question.

first_answer[W]

When set to a non nil value, this will be tried as an answer to the question. If this answer passes validations, it will become the result without the user ever being prompted. Otherwise this value is discarded, and this Question is resolved as a normal call to HighLine.ask().

directory[RW]

The directory from which a user will be allowed to select files, when File or Pathname is specified as an answer_type. Initially set to Pathname.new(File.expand_path(File.dirname($0))).

glob[RW]

The glob pattern used to limit file selection when File or Pathname is specified as an answer_type. Initially set to "*".

responses[R]

A Hash that stores the various responses used by HighLine to notify the user. The currently used responses and their purpose are as follows:

:ambiguous_completion

Used to notify the user of an ambiguous answer the auto-completion system cannot resolve.

:ask_on_error

This is the question that will be redisplayed to the user in the event of an error. Can be set to :question to repeat the original question.

:invalid_type

The error message shown when a type conversion fails.

:no_completion

Used to notify the user that their selection does not have a valid auto-completion match.

:not_in_range

Used to notify the user that a provided answer did not satisfy the range requirement tests.

:not_valid

The error message shown when validation checks fail.

overwrite[RW]

When set to true the question is asked, but output does not progress to the next line. The Cursor is moved back to the beginning of the question line and it is cleared so that all the contents of the line disappear from the screen.

Public Class Methods

new( question, answer_type ) click to toggle source

Create an instance of HighLine::Question. Expects a question to ask (can be "") and an answer_type to convert the answer to. The answer_type parameter must be a type recognized by Question.convert(). If given, a block is yeilded the new Question object to allow custom initializaion.

    # File lib/highline/question.rb, line 34
34:     def initialize( question, answer_type )
35:       # initialize instance data
36:       @question    = question
37:       @answer_type = answer_type
38:       
39:       @character    = nil
40:       @limit        = nil
41:       @echo         = true
42:       @readline     = false
43:       @whitespace   = :strip
44:       @case         = nil
45:       @default      = nil
46:       @validate     = nil
47:       @above        = nil
48:       @below        = nil
49:       @in           = nil
50:       @confirm      = nil
51:       @gather       = false
52:       @first_answer = nil
53:       @directory    = Pathname.new(File.expand_path(File.dirname($0)))
54:       @glob         = "*"
55:       @responses    = Hash.new
56:       @overwrite    = false
57:       
58:       # allow block to override settings
59:       yield self if block_given?
60: 
61:       # finalize responses based on settings
62:       build_responses
63:     end

Public Instance Methods

answer_or_default( answer_string ) click to toggle source

Returns the provided answer_string or the default answer for this Question if a default was set and the answer is empty.

     # File lib/highline/question.rb, line 209
209:     def answer_or_default( answer_string )
210:       if answer_string.length == 0 and not @default.nil?
211:         @default
212:       else
213:         answer_string
214:       end
215:     end
build_responses( ) click to toggle source

Called late in the initialization process to build intelligent responses based on the details of this Question object.

     # File lib/highline/question.rb, line 221
221:     def build_responses(  )
222:       ### WARNING:  This code is quasi-duplicated in     ###
223:       ### Menu.update_responses().  Check there too when ###
224:       ### making changes!                                ###
225:       append_default unless default.nil?
226:       @responses = { :ambiguous_completion =>
227:                        "Ambiguous choice.  " +
228:                        "Please choose one of #{@answer_type.inspect}.",
229:                      :ask_on_error         =>
230:                        "?  ",
231:                      :invalid_type         =>
232:                        "You must enter a valid #{@answer_type}.",
233:                      :no_completion        =>
234:                        "You must choose one of " +
235:                        "#{@answer_type.inspect}.",
236:                      :not_in_range         =>
237:                        "Your answer isn't within the expected range " +
238:                        "(#{expected_range}).",
239:                      :not_valid            =>
240:                        "Your answer isn't valid (must match " +
241:                        "#{@validate.inspect})." }.merge(@responses)
242:       ### WARNING:  This code is quasi-duplicated in     ###
243:       ### Menu.update_responses().  Check there too when ###
244:       ### making changes!                                ###
245:     end
change_case( answer_string ) click to toggle source

Returns the provided answer_string after changing character case by the rules of this Question. Valid settings for whitespace are:

nil

Do not alter character case. (Default.)

:up

Calls upcase().

:upcase

Calls upcase().

:down

Calls downcase().

:downcase

Calls downcase().

:capitalize

Calls capitalize().

An unrecognized choice (like :none) is treated as nil.

     # File lib/highline/question.rb, line 261
261:     def change_case( answer_string )
262:       if [:up, :upcase].include?(@case)
263:         answer_string.upcase
264:       elsif [:down, :downcase].include?(@case)
265:         answer_string.downcase
266:       elsif @case == :capitalize
267:         answer_string.capitalize
268:       else
269:         answer_string
270:       end
271:     end
convert( answer_string ) click to toggle source

Transforms the given answer_string into the expected type for this Question. Currently supported conversions are:

[...]

Answer must be a member of the passed Array. Auto-completion is used to expand partial answers.

lambda {...}

Answer is passed to lambda for conversion.

Date

Date.parse() is called with answer.

DateTime

DateTime.parse() is called with answer.

File

The entered file name is auto-completed in terms of directory + glob, opened, and returned.

Float

Answer is converted with Kernel.Float().

Integer

Answer is converted with Kernel.Integer().

nil

Answer is left in String format. (Default.)

Pathname

Same as File, save that a Pathname object is returned.

String

Answer is converted with Kernel.String().

Regexp

Answer is fed to Regexp.new().

Symbol

The method to_sym() is called on answer and the result returned.

any other Class

The answer is passed on to Class.parse().

This method throws ArgumentError, if the conversion cannot be completed for any reason.

     # File lib/highline/question.rb, line 301
301:     def convert( answer_string )
302:       if @answer_type.nil?
303:         answer_string
304:       elsif [Float, Integer, String].include?(@answer_type)
305:         Kernel.send(@answer_type.to_s.to_sym, answer_string)
306:       elsif @answer_type == Symbol
307:         answer_string.to_sym
308:       elsif @answer_type == Regexp
309:         Regexp.new(answer_string)
310:       elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type)
311:         # cheating, using OptionParser's Completion module
312:         choices = selection
313:         choices.extend(OptionParser::Completion)
314:         answer = choices.complete(answer_string)
315:         if answer.nil?
316:           raise NoAutoCompleteMatch
317:         end
318:         if @answer_type.is_a?(Array)
319:           answer.last
320:         elsif @answer_type == File
321:           File.open(File.join(@directory.to_s, answer.last))
322:         else
323:           Pathname.new(File.join(@directory.to_s, answer.last))
324:         end
325:       elsif [Date, DateTime].include?(@answer_type) or @answer_type.is_a?(Class)
326:         @answer_type.parse(answer_string)
327:       elsif @answer_type.is_a?(Proc)
328:         @answer_type[answer_string]
329:       end
330:     end
expected_range( ) click to toggle source

Returns a english explination of the current range settings.

     # File lib/highline/question.rb, line 333
333:     def expected_range(  )
334:       expected = [ ]
335: 
336:       expected << "above #{@above}" unless @above.nil?
337:       expected << "below #{@below}" unless @below.nil?
338:       expected << "included in #{@in.inspect}" unless @in.nil?
339: 
340:       case expected.size
341:       when 0 then ""
342:       when 1 then expected.first
343:       when 2 then expected.join(" and ")
344:       else        expected[0..2].join(", ") + ", and #{expected.last}"
345:       end
346:     end
first_answer( ) click to toggle source

Returns first_answer, which will be unset following this call.

     # File lib/highline/question.rb, line 349
349:     def first_answer( )
350:       @first_answer
351:     ensure
352:       @first_answer = nil
353:     end
first_answer?( ) click to toggle source

Returns true if first_answer is set.

     # File lib/highline/question.rb, line 356
356:     def first_answer?( )
357:       not @first_answer.nil?
358:     end
in_range?( answer_object ) click to toggle source

Returns true if the answer_object is greater than the above attribute, less than the below attribute and included?()ed in the in attribute. Otherwise, false is returned. Any nil attributes are not checked.

     # File lib/highline/question.rb, line 366
366:     def in_range?( answer_object )
367:       (@above.nil? or answer_object > @above) and
368:       (@below.nil? or answer_object < @below) and
369:       (@in.nil? or @in.include?(answer_object))
370:     end
remove_whitespace( answer_string ) click to toggle source

Returns the provided answer_string after processing whitespace by the rules of this Question. Valid settings for whitespace are:

nil

Do not alter whitespace.

:strip

Calls strip(). (Default.)

:chomp

Calls chomp().

:collapse

Collapses all whitspace runs to a single space.

:strip_and_collapse

Calls strip(), then collapses all whitspace runs to a single space.

:chomp_and_collapse

Calls chomp(), then collapses all whitspace runs to a single space.

:remove

Removes all whitespace.

An unrecognized choice (like :none) is treated as nil.

This process is skipped, for single character input.

     # File lib/highline/question.rb, line 391
391:     def remove_whitespace( answer_string )
392:       if @whitespace.nil?
393:         answer_string
394:       elsif [:strip, :chomp].include?(@whitespace)
395:         answer_string.send(@whitespace)
396:       elsif @whitespace == :collapse
397:         answer_string.gsub(/\s+/, " ")
398:       elsif [:strip_and_collapse, :chomp_and_collapse].include?(@whitespace)
399:         result = answer_string.send(@whitespace.to_s[/^[a-z]+/])
400:         result.gsub(/\s+/, " ")
401:       elsif @whitespace == :remove
402:         answer_string.gsub(/\s+/, "")
403:       else
404:         answer_string
405:       end
406:     end
selection( ) click to toggle source

Returns an Array of valid answers to this question. These answers are only known when answer_type is set to an Array of choices, File, or Pathname. Any other time, this method will return an empty Array.

     # File lib/highline/question.rb, line 413
413:     def selection(  )
414:       if @answer_type.is_a?(Array)
415:         @answer_type
416:       elsif [File, Pathname].include?(@answer_type)
417:         Dir[File.join(@directory.to_s, @glob)].map do |file|
418:           File.basename(file)
419:         end
420:       else
421:         [ ]
422:       end      
423:     end
to_str( ) click to toggle source

Stringifies the question to be asked.

     # File lib/highline/question.rb, line 426
426:     def to_str(  )
427:       @question
428:     end
valid_answer?( answer_string ) click to toggle source

Returns true if the provided answer_string is accepted by the validate attribute or false if it’s not.

It’s important to realize that an answer is validated after whitespace and case handling.

     # File lib/highline/question.rb, line 437
437:     def valid_answer?( answer_string )
438:       @validate.nil? or 
439:       (@validate.is_a?(Regexp) and answer_string =~ @validate) or
440:       (@validate.is_a?(Proc)   and @validate[answer_string])
441:     end

Private Instance Methods

append_default( ) click to toggle source

Adds the default choice to the end of question between |...|. Trailing whitespace is preserved so the function of HighLine.say() is not affected.

     # File lib/highline/question.rb, line 450
450:     def append_default(  )
451:       if @question =~ /([\t ]+)\Z/
452:         @question << "|#{@default}|#{$1}"
453:       elsif @question == ""
454:         @question << "|#{@default}|  "
455:       elsif @question[1, 1] == "\n"
456:         @question[2, 0] =  "  |#{@default}|"
457:       else
458:         @question << "  |#{@default}|"
459:       end
460:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.