Class: Canis::Bottomline::Question

Inherits:
Object
  • Object
show all
Defined in:
lib/canis/core/util/extras/bottomline.rb

Overview

do nothing, just creating a unique error type

Direct Known Subclasses

Menu

Defined Under Namespace

Classes: NoAutoCompleteMatch

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(question, answer_type) {|_self| ... } ⇒ Question

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.

Yields:

  • (_self)

Yield Parameters:



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/canis/core/util/extras/bottomline.rb', line 125

def initialize( question, answer_type )
  # initialize instance data
  @question    = question
  @answer_type = answer_type

  @character    = nil
  @limit        = nil
  @echo         = true
  @readline     = false
  @whitespace   = :strip
  @_case         = nil
  @default      = nil
  @validate     = nil
  @above        = nil
  @below        = nil
  @in           = nil
  @confirm      = nil
  @gather       = false
  @first_answer = nil
  @directory    = Pathname.new(File.expand_path(File.dirname($0)))
  @glob         = "*"
  @responses    = Hash.new
  @overwrite    = false
  @history      = nil

  # allow block to override settings
  yield self if block_given?

  #$log.debug " XXX default #{@default}" if $log.debug? 
  #$log.debug " XXX history #{@history}" if $log.debug? 

  # finalize responses based on settings
  build_responses
end

Instance Attribute Details

#_caseObject

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



215
216
217
# File 'lib/canis/core/util/extras/bottomline.rb', line 215

def _case
  @_case
end

#aboveObject

Used to control range checks for answer.



225
226
227
# File 'lib/canis/core/util/extras/bottomline.rb', line 225

def above
  @above
end

#answer_typeObject

The type that will be used to convert this answer.



163
164
165
# File 'lib/canis/core/util/extras/bottomline.rb', line 163

def answer_type
  @answer_type
end

#belowObject

Used to control range checks for answer.



225
226
227
# File 'lib/canis/core/util/extras/bottomline.rb', line 225

def below
  @below
end

#change_procObject

Called when any character is pressed with the string.

q.change_proc = Proc.new {|str| Dir.glob(str +"*") }


314
315
316
# File 'lib/canis/core/util/extras/bottomline.rb', line 314

def change_proc
  @change_proc
end

#characterObject

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.



173
174
175
# File 'lib/canis/core/util/extras/bottomline.rb', line 173

def character
  @character
end

#color_pairObject

Returns the value of attribute color_pair.



326
327
328
# File 'lib/canis/core/util/extras/bottomline.rb', line 326

def color_pair
  @color_pair
end

#completion_procObject

If the user presses tab in ask(), then this proc is used to fill in values. Typically, for files. e.g.

q.completion_proc = Proc.new {|str| Dir.glob(str +"*") }


307
308
309
# File 'lib/canis/core/util/extras/bottomline.rb', line 307

def completion_proc
  @completion_proc
end

#confirmObject

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.



235
236
237
# File 'lib/canis/core/util/extras/bottomline.rb', line 235

def confirm
  @confirm
end

#defaultObject

Used to provide a default answer to this question.



217
218
219
# File 'lib/canis/core/util/extras/bottomline.rb', line 217

def default
  @default
end

#directoryObject

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



262
263
264
# File 'lib/canis/core/util/extras/bottomline.rb', line 262

def directory
  @directory
end

#echoObject

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



194
195
196
# File 'lib/canis/core/util/extras/bottomline.rb', line 194

def echo
  @echo
end

#first_answerObject

Returns first_answer, which will be unset following this call.



478
479
480
481
482
# File 'lib/canis/core/util/extras/bottomline.rb', line 478

def first_answer( )
  @first_answer
ensure
  @first_answer = nil
end

#gatherObject

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.



249
250
251
# File 'lib/canis/core/util/extras/bottomline.rb', line 249

def gather
  @gather
end

#globObject

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



267
268
269
# File 'lib/canis/core/util/extras/bottomline.rb', line 267

def glob
  @glob
end

#help_textObject

text to be shown if user presses M-h



325
326
327
# File 'lib/canis/core/util/extras/bottomline.rb', line 325

def help_text
  @help_text
end

#historyObject

Returns the value of attribute history.



327
328
329
# File 'lib/canis/core/util/extras/bottomline.rb', line 327

def history
  @history
end

#inObject

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



227
228
229
# File 'lib/canis/core/util/extras/bottomline.rb', line 227

def in
  @in
end

#key_handler_procObject

Called when any control-key is pressed, one that we are not handling

q.key_handler_proc = Proc.new {|ch| xxxx) }


320
321
322
# File 'lib/canis/core/util/extras/bottomline.rb', line 320

def key_handler_proc
  @key_handler_proc
end

#limitObject

Allows you to set a character limit for input.

If not set, a default of 100 is used



179
180
181
# File 'lib/canis/core/util/extras/bottomline.rb', line 179

def limit
  @limit
end

#overwriteObject

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.



299
300
301
# File 'lib/canis/core/util/extras/bottomline.rb', line 299

def overwrite
  @overwrite
end

#questionObject

The ERb template of the question to be asked.



161
162
163
# File 'lib/canis/core/util/extras/bottomline.rb', line 161

def question
  @question
end

#readlineObject

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.

this messes up in ncurses RK 2010-10-24 12:23



205
206
207
# File 'lib/canis/core/util/extras/bottomline.rb', line 205

def readline
  @readline
end

#responsesObject (readonly)

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.



292
293
294
# File 'lib/canis/core/util/extras/bottomline.rb', line 292

def responses
  @responses
end

#validateObject

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.



223
224
225
# File 'lib/canis/core/util/extras/bottomline.rb', line 223

def validate
  @validate
end

#whitespaceObject

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



210
211
212
# File 'lib/canis/core/util/extras/bottomline.rb', line 210

def whitespace
  @whitespace
end

Instance Method Details

#answer_or_default(answer_string) ⇒ Object

Returns the provided answer_string or the default answer for this Question if a default was set and the answer is empty. NOTE: in our case, the user actually edits this value (in highline it is used if user enters blank)



335
336
337
338
339
340
341
# File 'lib/canis/core/util/extras/bottomline.rb', line 335

def answer_or_default( answer_string )
  if answer_string.length == 0 and not @default.nil?
    @default
  else
    answer_string
  end
end

#build_responsesObject

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



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/canis/core/util/extras/bottomline.rb', line 347

def build_responses(  )
  ### WARNING:  This code is quasi-duplicated in     ###
  ### Menu.update_responses().  Check there too when ###
  ### making changes!                                ###
  append_default unless default.nil?
  @responses = { :ambiguous_completion =>
    "Ambiguous choice.  " +
      "Please choose one of #{@answer_type.inspect}.",
      :ask_on_error         =>
    "?  ",
      :invalid_type         =>
    "You must enter a valid #{@answer_type}.",
      :no_completion        =>
    "You must choose one of " +
      "#{@answer_type.inspect}.",
      :not_in_range         =>
    "Your answer isn't within the expected range " +
      "(#{expected_range}).",
      :not_valid            =>
      "Your answer isn't valid (must match " +
        "#{@validate.inspect})." }.merge(@responses)
      ### WARNING:  This code is quasi-duplicated in     ###
      ### Menu.update_responses().  Check there too when ###
      ### making changes!                                ###
end

#change_case(answer_string) ⇒ Object

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.



387
388
389
390
391
392
393
394
395
396
397
# File 'lib/canis/core/util/extras/bottomline.rb', line 387

def change_case( answer_string )
  if [:up, :upcase].include?(@_case)
    answer_string.upcase
  elsif [:down, :downcase].include?(@_case)
    answer_string.downcase
  elsif @_case == :capitalize
    answer_string.capitalize
  else
    answer_string
  end
end

#convert(answer_string) ⇒ Object

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.



427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/canis/core/util/extras/bottomline.rb', line 427

def convert( answer_string )
  if @answer_type.nil?
    answer_string
  elsif [Float, Integer, String].include?(@answer_type)
    Kernel.send(@answer_type.to_s.to_sym, answer_string)
  elsif @answer_type == Symbol
    answer_string.to_sym
  elsif @answer_type == Regexp
    Regexp.new(answer_string)
  elsif @answer_type.is_a?(Array) or [File, Pathname].include?(@answer_type)
    # cheating, using OptionParser's Completion module
    choices = selection
    #choices.extend(OptionParser::Completion)
    #answer = choices.complete(answer_string)
    answer = choices # bug in completion of optparse
    if answer.nil?
      raise NoAutoCompleteMatch
    end
    if @answer_type.is_a?(Array)
      #answer.last  # we don't need this anylonger
      answer_string # we have already selected
    elsif @answer_type == File
      File.open(File.join(@directory.to_s, answer_string))
    else
      #Pathname.new(File.join(@directory.to_s, answer.last))
      Pathname.new(File.join(@directory.to_s, answer_string))
    end
  elsif [Date, DateTime].include?(@answer_type) or @answer_type.is_a?(Class)
    @answer_type.parse(answer_string)
  elsif @answer_type.is_a?(Proc)
    @answer_type[answer_string]
  end
end

#expected_rangeObject

Returns a english explination of the current range settings.



462
463
464
465
466
467
468
469
470
471
472
473
474
475
# File 'lib/canis/core/util/extras/bottomline.rb', line 462

def expected_range(  )
  expected = [ ]

  expected << "above #{@above}" unless @above.nil?
  expected << "below #{@below}" unless @below.nil?
  expected << "included in #{@in.inspect}" unless @in.nil?

  case expected.size
  when 0 then ""
  when 1 then expected.first
  when 2 then expected.join(" and ")
  else        expected[0..-2].join(", ") + ", and #{expected.last}"
  end
end

#first_answer?Boolean

Returns true if first_answer is set.

Returns:

  • (Boolean)


485
486
487
# File 'lib/canis/core/util/extras/bottomline.rb', line 485

def first_answer?( )
  not @first_answer.nil?
end

#in_range?(answer_object) ⇒ Boolean

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.

Returns:

  • (Boolean)


495
496
497
498
499
# File 'lib/canis/core/util/extras/bottomline.rb', line 495

def in_range?( answer_object )
  (@above.nil? or answer_object > @above) and
  (@below.nil? or answer_object < @below) and
  (@in.nil? or @in.include?(answer_object))
end

#remove_whitespace(answer_string) ⇒ Object

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.



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/canis/core/util/extras/bottomline.rb', line 520

def remove_whitespace( answer_string )
  if @whitespace.nil?
    answer_string
  elsif [:strip, :chomp].include?(@whitespace)
    answer_string.send(@whitespace)
  elsif @whitespace == :collapse
    answer_string.gsub(/\s+/, " ")
  elsif [:strip_and_collapse, :chomp_and_collapse].include?(@whitespace)
    result = answer_string.send(@whitespace.to_s[/^[a-z]+/])
    result.gsub(/\s+/, " ")
  elsif @whitespace == :remove
    answer_string.gsub(/\s+/, "")
  else
    answer_string
  end
end

#selectionObject

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.



542
543
544
545
546
547
548
549
550
551
552
# File 'lib/canis/core/util/extras/bottomline.rb', line 542

def selection(  )
  if @answer_type.is_a?(Array)
    @answer_type
  elsif [File, Pathname].include?(@answer_type)
    Dir[File.join(@directory.to_s, @glob)].map do |file|
      File.basename(file)
    end
  else
    [ ]
  end      
end

#to_strObject

Stringifies the question to be asked.



555
556
557
# File 'lib/canis/core/util/extras/bottomline.rb', line 555

def to_str(  )
  @question
end

#valid_answer?(answer_string) ⇒ Boolean

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.

Returns:

  • (Boolean)


566
567
568
569
570
# File 'lib/canis/core/util/extras/bottomline.rb', line 566

def valid_answer?( answer_string )
  @validate.nil? or 
  (@validate.is_a?(Regexp) and answer_string =~ @validate) or
  (@validate.is_a?(Proc)   and @validate[answer_string])
end