blob: 53b8988f0781a7bcec6a632340fb66dd52994cd5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
|
class QuestionAsker
attr_reader :question
include CustomErrors
def initialize(question, highline)
@question = question
@highline = highline
end
#
# Gets one answer, as opposed to #gather
#
def ask_once
# readline() needs to handle its own output, but readline only supports
# full line reading. Therefore if question.echo is anything but true,
# the prompt will not be issued. And we have to account for that now.
# Also, JRuby-1.7's ConsoleReader.readLine() needs to be passed the prompt
# to handle line editing properly.
@highline.say(question) unless ((question.readline) and (question.echo == true and !question.limit))
begin
question.get_response_or_default(@highline)
raise NotValidQuestionError unless question.valid_answer?
question.convert
if question.confirm
# need to add a layer of scope (new_scope) to ask a question inside a
# question, without destroying instance data
raise NoConfirmationQuestionError unless @highline.send(:confirm, question)
end
rescue NoConfirmationQuestionError
explain_error(nil)
retry
rescue NotInRangeQuestionError
explain_error(:not_in_range)
retry
rescue NotValidQuestionError
explain_error(:not_valid)
retry
rescue QuestionError
retry
rescue ArgumentError => error
case error.message
when /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)
retry
when /invalid value for/
explain_error(:invalid_type)
retry
else
raise
end
rescue NoAutoCompleteMatch
explain_error(:no_completion)
retry
end
question.answer
end
## Multiple questions
#
# Collects an Array/Hash full of answers as described in
# HighLine::Question.gather().
#
def gather_answers
original_question_template = question.template
verify_match = question.verify_match
begin # when verify_match is set this loop will repeat until unique_answers == 1
question.template = original_question_template
answers =
case question.gather
when Integer
gather_integer
when ::String, Regexp
gather_regexp
when Hash
gather_hash
end
if verify_match && (@highline.send(:unique_answers, answers).size > 1)
explain_error(:mismatch)
else
verify_match = false
end
end while verify_match
question.verify_match ? @highline.send(:last_answer, answers) : answers
end
public :gather_answers
def gather_integer
answers = []
answers << ask_once
question.template = ""
(question.gather-1).times do
answers << ask_once
end
answers
end
def gather_regexp
answers = []
answers << ask_once
question.template = ""
until (question.gather.is_a?(::String) and answers.last.to_s == question.gather) or
(question.gather.is_a?(Regexp) and answers.last.to_s =~ question.gather)
answers << ask_once
end
answers.pop
answers
end
def gather_hash
answers = {}
question.gather.keys.sort.each do |key|
@highline.key = key
answers[key] = ask_once
end
answers
end
## Delegate to Highline
private
def explain_error(error)
@highline.say(question.responses[error]) if error
@highline.say(question.ask_on_error_msg)
end
end
|