def ask(question, answer_type=String, &details)
     $log.debug "XXXX inside ask win #{@window} "
      @window ||= _create_footer_window
      #@window.show #unless @window.visible?
    
      @question ||= Question.new(question, answer_type, &details)
      say(@question) #unless @question.echo == true

      @completion_proc = @question.completion_proc
      @change_proc = @question.change_proc
      @key_handler_proc = @question.key_handler_proc
      @default = @question.default
      $log.debug "XXX: ASK RBGETS got default: #{@default} "
      @help_text = @question.help_text
      @answer_type = @question.answer_type
      if @question.answer_type.is_a? Array
        @completion_proc = Proc.new{|str| @answer_type.dup.grep Regexp.new("^#{str}") }
      end

      begin
        # FIXME a C-c still returns default to user !
        @answer = @question.answer_or_default(get_response) 
        unless @question.valid_answer?(@answer)
          explain_error(:not_valid)
          raise QuestionError
        end

        @answer = @question.convert(@answer)

        if @question.in_range?(@answer)
          if @question.confirm
            # need to add a layer of scope to ask a question inside a
            # question, without destroying instance data
            context_change = self.class.new(@input, @output, @wrap_at, @page_at)
            if @question.confirm == true
              confirm_question = "Are you sure?  "
            else
              # evaluate ERb under initial scope, so it will have
              # access to @question and @answer
              template  = ERB.new(@question.confirm, nil, "%")
              confirm_question = template.result(binding)
            end
            unless context_change.agree(confirm_question)
              explain_error(nil)
              raise QuestionError
            end
          end

          @answer
        else
          explain_error(:not_in_range)
          raise QuestionError
        end
      rescue QuestionError
        retry
      rescue ArgumentError, NameError => error
        #raise
        raise if error.is_a?(NoMethodError)
        if error.message =~ /ambiguous/
          # the assumption here is that OptionParser::Completion#complete
          # (used for ambiguity resolution) throws exceptions containing 
          # the word 'ambiguous' whenever resolution fails
          explain_error(:ambiguous_completion)
        else
          explain_error(:invalid_type)
        end
        retry
      rescue Question::NoAutoCompleteMatch
        explain_error(:no_completion)
        retry
      rescue Interrupt
        $log.warn "User interrupted ask() get_response does not want operation to proceed"
        return nil
      ensure
        @question = nil    # Reset Question object.
        $log.debug "XXX: HIDE B AT ENSURE OF ASK"
        hide_bottomline # assuming this method made it visible, not sure if this is called.
      end
    end
def ask(question, answer_type=String, &details)
     $log.debug "XXXX inside ask win #{@window} "
      @window ||= _create_footer_window
      #@window.show #unless @window.visible?
    
      @question ||= Question.new(question, answer_type, &details)
      say(@question) #unless @question.echo == true

      @completion_proc = @question.completion_proc
      @change_proc = @question.change_proc
      @key_handler_proc = @question.key_handler_proc
      @default = @question.default
      $log.debug "XXX: ASK RBGETS got default: #{@default} "
      @help_text = @question.help_text
      @answer_type = @question.answer_type
      if @question.answer_type.is_a? Array
        @completion_proc = Proc.new{|str| @answer_type.dup.grep Regexp.new("^#{str}") }
      end

      begin
        # FIXME a C-c still returns default to user !
        @answer = @question.answer_or_default(get_response) 
        unless @question.valid_answer?(@answer)
          explain_error(:not_valid)
          raise QuestionError
        end

        @answer = @question.convert(@answer)

        if @question.in_range?(@answer)
          if @question.confirm
            # need to add a layer of scope to ask a question inside a
            # question, without destroying instance data
            context_change = self.class.new(@input, @output, @wrap_at, @page_at)
            if @question.confirm == true
              confirm_question = "Are you sure?  "
            else
              # evaluate ERb under initial scope, so it will have
              # access to @question and @answer
              template  = ERB.new(@question.confirm, nil, "%")
              confirm_question = template.result(binding)
            end
            unless context_change.agree(confirm_question)
              explain_error(nil)
              raise QuestionError
            end
          end

          @answer
        else
          explain_error(:not_in_range)
          raise QuestionError
        end
      rescue QuestionError
        retry
      rescue ArgumentError, NameError => error
        #raise
        raise if error.is_a?(NoMethodError)
        if error.message =~ /ambiguous/
          # the assumption here is that OptionParser::Completion#complete
          # (used for ambiguity resolution) throws exceptions containing 
          # the word 'ambiguous' whenever resolution fails
          explain_error(:ambiguous_completion)
        else
          explain_error(:invalid_type)
        end
        retry
      rescue Question::NoAutoCompleteMatch
        explain_error(:no_completion)
        retry
      rescue Interrupt
        $log.warn "User interrupted ask() get_response does not want operation to proceed"
        return nil
      ensure
        @question = nil    # Reset Question object.
        $log.debug "XXX: HIDE B AT ENSURE OF ASK"
        hide_bottomline # assuming this method made it visible, not sure if this is called.
      end
    end
--- highline classes }}}