Class | HighLine::Question |
In: |
lib/highline/question.rb
|
Parent: | Object |
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.
above | [RW] | Used to control range checks for answer. | ||||||||||||
answer_type | [RW] | The type that will be used to convert this answer. | ||||||||||||
below | [RW] | Used to control range checks for answer. | ||||||||||||
case | [RW] | Used to control character case processing for the answer to this question. See HighLine::Question.change_case() for acceptable settings. | ||||||||||||
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 and may not work correctly if STDIN is
redirected.) 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. |
||||||||||||
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. | ||||||||||||
default | [RW] | Used to provide a default answer to this question. | ||||||||||||
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))). | ||||||||||||
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). |
||||||||||||
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(). | ||||||||||||
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. |
||||||||||||
glob | [RW] | The glob pattern used to limit file selection when File or Pathname is specified as an answer_type. Initially set to "*". | ||||||||||||
in | [RW] | If set, answer must pass an include?() check on this object. | ||||||||||||
limit | [RW] |
Allows you to set a character limit for input.
WARNING: This option forces a character by character read. |
||||||||||||
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. | ||||||||||||
question | [RW] | The ERb template of the question to be asked. | ||||||||||||
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. |
||||||||||||
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:
|
||||||||||||
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. | ||||||||||||
whitespace | [RW] | Used to control whitespace processing for the answer to this question. See HighLine::Question.remove_whitespace() for acceptable settings. |
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 recongnized 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
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 210 210: def answer_or_default( answer_string ) 211: if answer_string.length == 0 and not @default.nil? 212: @default 213: else 214: answer_string 215: end 216: end
Called late in the initialization process to build intelligent responses based on the details of this Question object.
# File lib/highline/question.rb, line 222 222: def build_responses( ) 223: ### WARNING: This code is quasi-duplicated in ### 224: ### Menu.update_responses(). Check there too when ### 225: ### making changes! ### 226: append_default unless default.nil? 227: @responses = { :ambiguous_completion => 228: "Ambiguous choice. " + 229: "Please choose one of #{@answer_type.inspect}.", 230: :ask_on_error => 231: "? ", 232: :invalid_type => 233: "You must enter a valid #{@answer_type}.", 234: :no_completion => 235: "You must choose one of " + 236: "#{@answer_type.inspect}.", 237: :not_in_range => 238: "Your answer isn't within the expected range " + 239: "(#{expected_range}).", 240: :not_valid => 241: "Your answer isn't valid (must match " + 242: "#{@validate.inspect})." }.merge(@responses) 243: ### WARNING: This code is quasi-duplicated in ### 244: ### Menu.update_responses(). Check there too when ### 245: ### making changes! ### 246: end
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 262 262: def change_case( answer_string ) 263: if [:up, :upcase].include?(@case) 264: answer_string.upcase 265: elsif [:down, :downcase].include?(@case) 266: answer_string.downcase 267: elsif @case == :capitalize 268: answer_string.capitalize 269: else 270: answer_string 271: end 272: end
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 302 302: def convert( answer_string ) 303: if @answer_type.nil? 304: answer_string 305: elsif [Float, Integer, String].include?(@answer_type) 306: Kernel.send(@answer_type.to_s.to_sym, answer_string) 307: elsif @answer_type == Symbol 308: answer_string.to_sym 309: elsif @answer_type == Regexp 310: Regexp.new(answer_string) 311: elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type) 312: # cheating, using OptionParser's Completion module 313: choices = selection 314: choices.extend(OptionParser::Completion) 315: answer = choices.complete(answer_string) 316: if answer.nil? 317: raise NoAutoCompleteMatch 318: end 319: if @answer_type.is_a?(Array) 320: answer.last 321: elsif @answer_type == File 322: File.open(File.join(@directory.to_s, answer.last)) 323: else 324: Pathname.new(File.join(@directory.to_s, answer.last)) 325: end 326: elsif [Date, DateTime].include?(@answer_type) or @answer_type.is_a?(Class) 327: @answer_type.parse(answer_string) 328: elsif @answer_type.is_a?(Proc) 329: @answer_type[answer_string] 330: end 331: end
Returns a english explination of the current range settings.
# File lib/highline/question.rb, line 334 334: def expected_range( ) 335: expected = [ ] 336: 337: expected << "above #{@above}" unless @above.nil? 338: expected << "below #{@below}" unless @below.nil? 339: expected << "included in #{@in.inspect}" unless @in.nil? 340: 341: case expected.size 342: when 0 then "" 343: when 1 then expected.first 344: when 2 then expected.join(" and ") 345: else expected[0..-2].join(", ") + ", and #{expected.last}" 346: end 347: end
Returns first_answer, which will be unset following this call.
# File lib/highline/question.rb, line 350 350: def first_answer( ) 351: @first_answer 352: ensure 353: @first_answer = nil 354: end
Returns true if first_answer is set.
# File lib/highline/question.rb, line 357 357: def first_answer?( ) 358: not @first_answer.nil? 359: end
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 367 367: def in_range?( answer_object ) 368: (@above.nil? or answer_object > @above) and 369: (@below.nil? or answer_object < @below) and 370: (@in.nil? or @in.include?(answer_object)) 371: end
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 392 392: def remove_whitespace( answer_string ) 393: if @whitespace.nil? 394: answer_string 395: elsif [:strip, :chomp].include?(@whitespace) 396: answer_string.send(@whitespace) 397: elsif @whitespace == :collapse 398: answer_string.gsub(/\s+/, " ") 399: elsif [:strip_and_collapse, :chomp_and_collapse].include?(@whitespace) 400: result = answer_string.send(@whitespace.to_s[/^[a-z]+/]) 401: result.gsub(/\s+/, " ") 402: elsif @whitespace == :remove 403: answer_string.gsub(/\s+/, "") 404: else 405: answer_string 406: end 407: end
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 414 414: def selection( ) 415: if @answer_type.is_a?(Array) 416: @answer_type 417: elsif [File, Pathname].include?(@answer_type) 418: Dir[File.join(@directory.to_s, @glob)].map do |file| 419: File.basename(file) 420: end 421: else 422: [ ] 423: end 424: end
Stringifies the question to be asked.
# File lib/highline/question.rb, line 427 427: def to_str( ) 428: @question 429: end
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 438 438: def valid_answer?( answer_string ) 439: @validate.nil? or 440: (@validate.is_a?(Regexp) and answer_string =~ @validate) or 441: (@validate.is_a?(Proc) and @validate[answer_string]) 442: end
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 451 451: def append_default( ) 452: if @question =~ /([\t ]+)\Z/ 453: @question << "|#{@default}|#{$1}" 454: elsif @question == "" 455: @question << "|#{@default}| " 456: elsif @question[-1, 1] == "\n" 457: @question[-2, 0] = " |#{@default}|" 458: else 459: @question << " |#{@default}|" 460: end 461: end