tty-prompt 0.19.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -0
- data/LICENSE.txt +1 -1
- data/README.md +485 -233
- data/lib/tty-prompt.rb +1 -2
- data/lib/tty/prompt.rb +159 -147
- data/lib/tty/prompt/answers_collector.rb +5 -5
- data/lib/tty/prompt/block_paginator.rb +1 -1
- data/lib/tty/prompt/choice.rb +31 -13
- data/lib/tty/prompt/choices.rb +30 -12
- data/lib/tty/prompt/confirm_question.rb +42 -16
- data/lib/tty/prompt/const.rb +17 -0
- data/lib/tty/prompt/converter_dsl.rb +6 -7
- data/lib/tty/prompt/converter_registry.rb +31 -26
- data/lib/tty/prompt/converters.rb +139 -32
- data/lib/tty/prompt/enum_list.rb +58 -25
- data/lib/tty/prompt/errors.rb +31 -0
- data/lib/tty/prompt/evaluator.rb +2 -2
- data/lib/tty/prompt/expander.rb +27 -15
- data/lib/tty/prompt/keypress.rb +5 -3
- data/lib/tty/prompt/list.rb +101 -38
- data/lib/tty/prompt/mask_question.rb +9 -5
- data/lib/tty/prompt/multi_list.rb +108 -29
- data/lib/tty/prompt/multiline.rb +9 -7
- data/lib/tty/prompt/paginator.rb +1 -1
- data/lib/tty/prompt/question.rb +67 -36
- data/lib/tty/prompt/question/checks.rb +20 -2
- data/lib/tty/prompt/question/modifier.rb +4 -2
- data/lib/tty/prompt/question/validation.rb +3 -3
- data/lib/tty/prompt/selected_choices.rb +77 -0
- data/lib/tty/prompt/slider.rb +110 -23
- data/lib/tty/prompt/statement.rb +3 -3
- data/lib/tty/prompt/suggestion.rb +7 -6
- data/lib/tty/prompt/symbols.rb +58 -58
- data/lib/tty/prompt/test.rb +36 -0
- data/lib/tty/prompt/utils.rb +1 -3
- data/lib/tty/prompt/version.rb +1 -1
- metadata +27 -196
- data/Rakefile +0 -8
- data/examples/ask.rb +0 -7
- data/examples/ask_blank.rb +0 -9
- data/examples/ask_valid.rb +0 -12
- data/examples/collect.rb +0 -21
- data/examples/echo.rb +0 -11
- data/examples/enum_select.rb +0 -7
- data/examples/enum_select_disabled.rb +0 -16
- data/examples/enum_select_paged.rb +0 -9
- data/examples/enum_select_wrapped.rb +0 -15
- data/examples/expand.rb +0 -29
- data/examples/expand_auto.rb +0 -29
- data/examples/in.rb +0 -9
- data/examples/inputs.rb +0 -10
- data/examples/key_events.rb +0 -15
- data/examples/keypress.rb +0 -9
- data/examples/mask.rb +0 -13
- data/examples/multi_select.rb +0 -8
- data/examples/multi_select_disabled.rb +0 -17
- data/examples/multi_select_disabled_paged.rb +0 -22
- data/examples/multi_select_paged.rb +0 -9
- data/examples/multi_select_wrapped.rb +0 -15
- data/examples/multiline.rb +0 -9
- data/examples/pause.rb +0 -9
- data/examples/select.rb +0 -24
- data/examples/select_disabled.rb +0 -18
- data/examples/select_disabled_paged.rb +0 -22
- data/examples/select_enum.rb +0 -8
- data/examples/select_filtered.rb +0 -11
- data/examples/select_paginated.rb +0 -11
- data/examples/select_wrapped.rb +0 -15
- data/examples/slider.rb +0 -6
- data/examples/validation.rb +0 -9
- data/examples/yes_no.rb +0 -7
- data/lib/tty/prompt/messages.rb +0 -49
- data/lib/tty/test_prompt.rb +0 -20
- data/spec/spec_helper.rb +0 -61
- data/spec/unit/ask_spec.rb +0 -173
- data/spec/unit/block_paginator_spec.rb +0 -84
- data/spec/unit/choice/eql_spec.rb +0 -22
- data/spec/unit/choice/from_spec.rb +0 -112
- data/spec/unit/choices/add_spec.rb +0 -12
- data/spec/unit/choices/each_spec.rb +0 -13
- data/spec/unit/choices/find_by_spec.rb +0 -10
- data/spec/unit/choices/new_spec.rb +0 -10
- data/spec/unit/choices/pluck_spec.rb +0 -9
- data/spec/unit/collect_spec.rb +0 -96
- data/spec/unit/converters/convert_bool_spec.rb +0 -58
- data/spec/unit/converters/convert_char_spec.rb +0 -11
- data/spec/unit/converters/convert_custom_spec.rb +0 -14
- data/spec/unit/converters/convert_date_spec.rb +0 -34
- data/spec/unit/converters/convert_file_spec.rb +0 -18
- data/spec/unit/converters/convert_number_spec.rb +0 -39
- data/spec/unit/converters/convert_path_spec.rb +0 -15
- data/spec/unit/converters/convert_range_spec.rb +0 -22
- data/spec/unit/converters/convert_regex_spec.rb +0 -12
- data/spec/unit/converters/convert_string_spec.rb +0 -21
- data/spec/unit/converters/on_error_spec.rb +0 -9
- data/spec/unit/distance/distance_spec.rb +0 -73
- data/spec/unit/enum_select_spec.rb +0 -518
- data/spec/unit/error_spec.rb +0 -20
- data/spec/unit/evaluator_spec.rb +0 -67
- data/spec/unit/expand_spec.rb +0 -290
- data/spec/unit/keypress_spec.rb +0 -66
- data/spec/unit/mask_spec.rb +0 -140
- data/spec/unit/multi_select_spec.rb +0 -741
- data/spec/unit/multiline_spec.rb +0 -77
- data/spec/unit/new_spec.rb +0 -20
- data/spec/unit/ok_spec.rb +0 -10
- data/spec/unit/paginator_spec.rb +0 -92
- data/spec/unit/question/checks_spec.rb +0 -97
- data/spec/unit/question/default_spec.rb +0 -31
- data/spec/unit/question/echo_spec.rb +0 -38
- data/spec/unit/question/in_spec.rb +0 -115
- data/spec/unit/question/initialize_spec.rb +0 -12
- data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
- data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
- data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
- data/spec/unit/question/modify_spec.rb +0 -41
- data/spec/unit/question/required_spec.rb +0 -92
- data/spec/unit/question/validate_spec.rb +0 -115
- data/spec/unit/question/validation/call_spec.rb +0 -31
- data/spec/unit/question/validation/coerce_spec.rb +0 -30
- data/spec/unit/result_spec.rb +0 -40
- data/spec/unit/say_spec.rb +0 -67
- data/spec/unit/select_spec.rb +0 -942
- data/spec/unit/slider_spec.rb +0 -142
- data/spec/unit/statement/initialize_spec.rb +0 -15
- data/spec/unit/subscribe_spec.rb +0 -22
- data/spec/unit/suggest_spec.rb +0 -28
- data/spec/unit/timer_spec.rb +0 -29
- data/spec/unit/warn_spec.rb +0 -21
- data/spec/unit/yes_no_spec.rb +0 -251
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -29
- data/tty-prompt.gemspec +0 -31
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "question"
|
4
4
|
|
5
5
|
module TTY
|
6
6
|
class Prompt
|
7
7
|
class MaskQuestion < Question
|
8
|
+
# Names for delete keys
|
9
|
+
DELETE_KEYS = %i[backspace delete].freeze
|
10
|
+
|
8
11
|
# Create masked question
|
9
12
|
#
|
10
13
|
# @param [Hash] options
|
@@ -27,19 +30,20 @@ module TTY
|
|
27
30
|
# @api public
|
28
31
|
def mask(char = (not_set = true))
|
29
32
|
return @mask if not_set
|
33
|
+
|
30
34
|
@mask = char
|
31
35
|
end
|
32
36
|
|
33
|
-
def keyreturn(
|
37
|
+
def keyreturn(_event)
|
34
38
|
@done_masked = true
|
35
39
|
end
|
36
40
|
|
37
|
-
def keyenter(
|
41
|
+
def keyenter(_event)
|
38
42
|
@done_masked = true
|
39
43
|
end
|
40
44
|
|
41
45
|
def keypress(event)
|
42
|
-
if
|
46
|
+
if DELETE_KEYS.include?(event.key.name)
|
43
47
|
@input.chop! unless @input.empty?
|
44
48
|
elsif event.value =~ /^[^\e\n\r]/
|
45
49
|
@input += event.value
|
@@ -75,7 +79,7 @@ module TTY
|
|
75
79
|
def read_input(question)
|
76
80
|
@done_masked = false
|
77
81
|
@failure = false
|
78
|
-
@input =
|
82
|
+
@input = ""
|
79
83
|
@prompt.print(question)
|
80
84
|
until @done_masked
|
81
85
|
@prompt.read_keypress
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "list"
|
4
|
+
require_relative "selected_choices"
|
4
5
|
|
5
6
|
module TTY
|
6
7
|
class Prompt
|
@@ -9,8 +10,6 @@ module TTY
|
|
9
10
|
#
|
10
11
|
# @api private
|
11
12
|
class MultiList < List
|
12
|
-
HELP = '(Use %s arrow%s keys, press Space to select and Enter to finish%s)'
|
13
|
-
|
14
13
|
# Create instance of TTY::Prompt::MultiList menu.
|
15
14
|
#
|
16
15
|
# @param [Prompt] :prompt
|
@@ -19,12 +18,20 @@ module TTY
|
|
19
18
|
# @api public
|
20
19
|
def initialize(prompt, **options)
|
21
20
|
super
|
22
|
-
@selected =
|
21
|
+
@selected = SelectedChoices.new
|
23
22
|
@help = options[:help]
|
24
23
|
@echo = options.fetch(:echo, true)
|
24
|
+
@min = options[:min]
|
25
25
|
@max = options[:max]
|
26
26
|
end
|
27
27
|
|
28
|
+
# Set a minimum number of choices
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def min(value)
|
32
|
+
@min = value
|
33
|
+
end
|
34
|
+
|
28
35
|
# Set a maximum number of choices
|
29
36
|
#
|
30
37
|
# @api public
|
@@ -32,19 +39,54 @@ module TTY
|
|
32
39
|
@max = value
|
33
40
|
end
|
34
41
|
|
42
|
+
# Callback fired when enter/return key is pressed
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
def keyenter(*)
|
46
|
+
valid = true
|
47
|
+
valid = @min <= @selected.size if @min
|
48
|
+
valid = @selected.size <= @max if @max
|
49
|
+
|
50
|
+
super if valid
|
51
|
+
end
|
52
|
+
alias keyreturn keyenter
|
53
|
+
|
35
54
|
# Callback fired when space key is pressed
|
36
55
|
#
|
37
56
|
# @api private
|
38
57
|
def keyspace(*)
|
39
58
|
active_choice = choices[@active - 1]
|
40
59
|
if @selected.include?(active_choice)
|
41
|
-
@selected.
|
60
|
+
@selected.delete_at(@active - 1)
|
42
61
|
else
|
43
62
|
return if @max && @selected.size >= @max
|
44
|
-
|
63
|
+
|
64
|
+
@selected.insert(@active - 1, active_choice)
|
45
65
|
end
|
46
66
|
end
|
47
67
|
|
68
|
+
# Selects all choices when Ctrl+A is pressed
|
69
|
+
#
|
70
|
+
# @api private
|
71
|
+
def keyctrl_a(*)
|
72
|
+
return if @max && @max < choices.size
|
73
|
+
|
74
|
+
@selected = SelectedChoices.new(choices.enabled, choices.enabled_indexes)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Revert currently selected choices when Ctrl+I is pressed
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
def keyctrl_r(*)
|
81
|
+
return if @max && @max < choices.size
|
82
|
+
|
83
|
+
indexes = choices.each_with_index.reduce([]) do |acc, (choice, idx)|
|
84
|
+
acc << idx if !choice.disabled? && !@selected.include?(choice)
|
85
|
+
acc
|
86
|
+
end
|
87
|
+
@selected = SelectedChoices.new(choices.enabled - @selected.to_a, indexes)
|
88
|
+
end
|
89
|
+
|
48
90
|
private
|
49
91
|
|
50
92
|
# Setup default options and active selection
|
@@ -53,12 +95,23 @@ module TTY
|
|
53
95
|
def setup_defaults
|
54
96
|
validate_defaults
|
55
97
|
# At this stage, @choices matches all the visible choices.
|
56
|
-
|
98
|
+
default_indexes = @default.map do |d|
|
99
|
+
if d.to_s =~ INTEGER_MATCHER
|
100
|
+
d - 1
|
101
|
+
else
|
102
|
+
choices.index(choices.find_by(:name, d.to_s))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@selected = SelectedChoices.new(@choices.values_at(*default_indexes),
|
106
|
+
default_indexes)
|
57
107
|
|
58
|
-
if
|
108
|
+
if @default.empty?
|
109
|
+
# no default, pick the first non-disabled choice
|
110
|
+
@active = choices.index { |choice| !choice.disabled? } + 1
|
111
|
+
elsif @default.last.to_s =~ INTEGER_MATCHER
|
59
112
|
@active = @default.last
|
60
|
-
|
61
|
-
@active =
|
113
|
+
elsif default_choice = choices.find_by(:name, @default.last.to_s)
|
114
|
+
@active = choices.index(default_choice) + 1
|
62
115
|
end
|
63
116
|
end
|
64
117
|
|
@@ -68,37 +121,63 @@ module TTY
|
|
68
121
|
#
|
69
122
|
# @api private
|
70
123
|
def selected_names
|
71
|
-
@selected.map(&:name).join(
|
124
|
+
@selected.map(&:name).join(", ")
|
72
125
|
end
|
73
126
|
|
74
|
-
# Header part showing the maximum number of choices
|
127
|
+
# Header part showing the minimum/maximum number of choices
|
75
128
|
#
|
76
129
|
# @return [String]
|
77
130
|
#
|
78
131
|
# @api private
|
79
|
-
def
|
80
|
-
|
132
|
+
def minmax_help
|
133
|
+
help = []
|
134
|
+
help << "min. #{@min}" if @min
|
135
|
+
help << "max. #{@max}" if @max
|
136
|
+
"(%s) " % [help.join(", ")]
|
137
|
+
end
|
138
|
+
|
139
|
+
# Build a default help text
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
#
|
143
|
+
# @api private
|
144
|
+
def default_help
|
145
|
+
str = []
|
146
|
+
str << "(Press "
|
147
|
+
str << "#{arrows_help} arrow"
|
148
|
+
str << " or 1-#{choices.size} number" if enumerate?
|
149
|
+
str << " to move, Space"
|
150
|
+
str << "/Ctrl+A|R" if @max.nil?
|
151
|
+
str << " to select"
|
152
|
+
str << " (all|rev)" if @max.nil?
|
153
|
+
str << (filterable? ? "," : " and")
|
154
|
+
str << " Enter to finish"
|
155
|
+
str << " and letters to filter" if filterable?
|
156
|
+
str << ")"
|
157
|
+
str.join
|
81
158
|
end
|
82
159
|
|
83
160
|
# Render initial help text and then currently selected choices
|
84
161
|
#
|
85
162
|
# @api private
|
86
163
|
def render_header
|
87
|
-
instructions = @prompt.decorate(help,
|
88
|
-
|
164
|
+
instructions = @prompt.decorate(help, @help_color)
|
165
|
+
minmax_suffix = @min || @max ? minmax_help : ""
|
166
|
+
print_selected = @selected.size.nonzero? && @echo
|
89
167
|
|
90
168
|
if @done && @echo
|
91
169
|
@prompt.decorate(selected_names, @active_color)
|
92
|
-
elsif @
|
93
|
-
|
94
|
-
|
95
|
-
(
|
96
|
-
|
97
|
-
max_suffix + instructions
|
170
|
+
elsif (@first_render && (help_start? || help_always?)) ||
|
171
|
+
(help_always? && !@filter.any? && !@done)
|
172
|
+
minmax_suffix +
|
173
|
+
(print_selected ? "#{selected_names} " : "") +
|
174
|
+
instructions
|
98
175
|
elsif filterable? && @filter.any?
|
99
|
-
|
100
|
-
|
101
|
-
|
176
|
+
minmax_suffix +
|
177
|
+
(print_selected ? "#{selected_names} " : "") +
|
178
|
+
@prompt.decorate(filter_help, @help_color)
|
179
|
+
else
|
180
|
+
minmax_suffix + (print_selected ? selected_names : "")
|
102
181
|
end
|
103
182
|
end
|
104
183
|
|
@@ -121,9 +200,9 @@ module TTY
|
|
121
200
|
|
122
201
|
sync_paginators if @paging_changed
|
123
202
|
paginator.paginate(choices, @active, @per_page) do |choice, index|
|
124
|
-
num = enumerate? ? (index + 1).to_s + @enum +
|
125
|
-
indicator = (index + 1 == @active) ? @symbols[:marker] :
|
126
|
-
indicator +=
|
203
|
+
num = enumerate? ? (index + 1).to_s + @enum + " " : ""
|
204
|
+
indicator = (index + 1 == @active) ? @symbols[:marker] : " "
|
205
|
+
indicator += " "
|
127
206
|
message = if @selected.include?(choice) && !choice.disabled?
|
128
207
|
selected = @prompt.decorate(@symbols[:radio_on], @active_color)
|
129
208
|
"#{selected} #{num}#{choice.name}"
|
@@ -134,7 +213,7 @@ module TTY
|
|
134
213
|
"#{@symbols[:radio_off]} #{num}#{choice.name}"
|
135
214
|
end
|
136
215
|
end_index = paginated? ? paginator.end_index : choices.size - 1
|
137
|
-
newline = (index == end_index) ?
|
216
|
+
newline = (index == end_index) ? "" : "\n"
|
138
217
|
output << indicator + message + newline
|
139
218
|
end
|
140
219
|
|
data/lib/tty/prompt/multiline.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "question"
|
4
|
+
require_relative "symbols"
|
5
5
|
|
6
6
|
module TTY
|
7
7
|
class Prompt
|
@@ -9,9 +9,9 @@ module TTY
|
|
9
9
|
#
|
10
10
|
# @api private
|
11
11
|
class Multiline < Question
|
12
|
-
HELP =
|
12
|
+
HELP = "(Press Ctrl+D or Ctrl+Z to finish)".freeze
|
13
13
|
|
14
|
-
def initialize(prompt, options
|
14
|
+
def initialize(prompt, **options)
|
15
15
|
super
|
16
16
|
@help = options[:help] || self.class::HELP
|
17
17
|
@first_render = true
|
@@ -25,6 +25,7 @@ module TTY
|
|
25
25
|
# @api public
|
26
26
|
def help(value = (not_set = true))
|
27
27
|
return @help if not_set
|
28
|
+
|
28
29
|
@help = value
|
29
30
|
end
|
30
31
|
|
@@ -42,7 +43,7 @@ module TTY
|
|
42
43
|
if !echo?
|
43
44
|
header
|
44
45
|
elsif @done
|
45
|
-
header << @prompt.decorate(
|
46
|
+
header << @prompt.decorate(@input.to_s, @active_color)
|
46
47
|
elsif @first_render
|
47
48
|
header << @prompt.decorate(help, @help_color)
|
48
49
|
@first_render = false
|
@@ -55,8 +56,9 @@ module TTY
|
|
55
56
|
@prompt.print(question)
|
56
57
|
@lines = read_input
|
57
58
|
@input = "#{@lines.first.strip} ..." unless @lines.first.to_s.empty?
|
58
|
-
if Utils.blank?(@input)
|
59
|
-
@input = default
|
59
|
+
if Utils.blank?(@input) && default?
|
60
|
+
@input = default
|
61
|
+
@lines = default
|
60
62
|
end
|
61
63
|
@evaluator.(@lines)
|
62
64
|
end
|
data/lib/tty/prompt/paginator.rb
CHANGED
data/lib/tty/prompt/question.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
3
|
+
require_relative "converters"
|
4
|
+
require_relative "evaluator"
|
5
|
+
require_relative "question/modifier"
|
6
|
+
require_relative "question/validation"
|
7
|
+
require_relative "question/checks"
|
8
|
+
require_relative "utils"
|
9
9
|
|
10
10
|
module TTY
|
11
11
|
# A class responsible for shell prompt interactions.
|
@@ -35,23 +35,30 @@ module TTY
|
|
35
35
|
#
|
36
36
|
# @api public
|
37
37
|
def initialize(prompt, **options)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@
|
45
|
-
@
|
46
|
-
@
|
38
|
+
# Option deprecation
|
39
|
+
if options[:validation]
|
40
|
+
warn "[DEPRECATION] The `:validation` option is deprecated. Use `:validate` instead."
|
41
|
+
options[:validate] = options[:validation]
|
42
|
+
end
|
43
|
+
|
44
|
+
@prompt = prompt
|
45
|
+
@prefix = options.fetch(:prefix) { @prompt.prefix }
|
46
|
+
@default = options.fetch(:default) { UndefinedSetting }
|
47
|
+
@required = options.fetch(:required) { false }
|
48
|
+
@echo = options.fetch(:echo) { true }
|
49
|
+
@in = options.fetch(:in) { UndefinedSetting }
|
50
|
+
@modifier = options.fetch(:modifier) { [] }
|
51
|
+
@validation = options.fetch(:validate) { UndefinedSetting }
|
52
|
+
@convert = options.fetch(:convert) { UndefinedSetting }
|
47
53
|
@active_color = options.fetch(:active_color) { @prompt.active_color }
|
48
|
-
@help_color
|
49
|
-
@error_color
|
50
|
-
@value
|
51
|
-
@
|
52
|
-
@
|
54
|
+
@help_color = options.fetch(:help_color) { @prompt.help_color }
|
55
|
+
@error_color = options.fetch(:error_color) { :red }
|
56
|
+
@value = options.fetch(:value) { UndefinedSetting }
|
57
|
+
@quiet = options.fetch(:quiet) { @prompt.quiet }
|
58
|
+
@messages = Utils.deep_copy(options.fetch(:messages) { {} })
|
59
|
+
@done = false
|
53
60
|
@first_render = true
|
54
|
-
@input
|
61
|
+
@input = nil
|
55
62
|
|
56
63
|
@evaluator = Evaluator.new(self)
|
57
64
|
|
@@ -60,6 +67,7 @@ module TTY
|
|
60
67
|
@evaluator << CheckRange
|
61
68
|
@evaluator << CheckValidation
|
62
69
|
@evaluator << CheckModifier
|
70
|
+
@evaluator << CheckConversion
|
63
71
|
end
|
64
72
|
|
65
73
|
# Stores all the error messages displayed to user
|
@@ -85,7 +93,7 @@ module TTY
|
|
85
93
|
if template && !template.match(/\%\{/).nil?
|
86
94
|
[template % tokens]
|
87
95
|
else
|
88
|
-
[template ||
|
96
|
+
[template || ""]
|
89
97
|
end
|
90
98
|
end
|
91
99
|
|
@@ -96,7 +104,7 @@ module TTY
|
|
96
104
|
# @return [self]
|
97
105
|
#
|
98
106
|
# @api public
|
99
|
-
def call(message =
|
107
|
+
def call(message = "", &block)
|
100
108
|
@message = message
|
101
109
|
block.call(self) if block
|
102
110
|
@prompt.subscribe(self) do
|
@@ -122,8 +130,8 @@ module TTY
|
|
122
130
|
total_lines = @prompt.count_screen_lines(input_line)
|
123
131
|
@prompt.print(refresh(question.lines.count, total_lines))
|
124
132
|
end
|
125
|
-
@prompt.print(render_question)
|
126
|
-
|
133
|
+
@prompt.print(render_question) unless @quiet
|
134
|
+
result.value
|
127
135
|
end
|
128
136
|
|
129
137
|
# Render question
|
@@ -141,7 +149,7 @@ module TTY
|
|
141
149
|
elsif @done
|
142
150
|
header << @prompt.decorate(@input.to_s, @active_color)
|
143
151
|
elsif default? && !Utils.blank?(@default)
|
144
|
-
header << @prompt.decorate("(#{default})", @help_color) +
|
152
|
+
header << @prompt.decorate("(#{default})", @help_color) + " "
|
145
153
|
end
|
146
154
|
header << "\n" if @done
|
147
155
|
header.join
|
@@ -162,12 +170,12 @@ module TTY
|
|
162
170
|
#
|
163
171
|
# @api private
|
164
172
|
def read_input(question)
|
165
|
-
options = {echo: echo}
|
173
|
+
options = { echo: echo }
|
166
174
|
if value? && @first_render
|
167
175
|
options[:value] = @value
|
168
176
|
@first_render = false
|
169
177
|
end
|
170
|
-
@prompt.read_line(question, options).chomp
|
178
|
+
@prompt.read_line(question, **options).chomp
|
171
179
|
end
|
172
180
|
|
173
181
|
# Handle error condition
|
@@ -177,7 +185,7 @@ module TTY
|
|
177
185
|
# @api private
|
178
186
|
def render_error(errors)
|
179
187
|
errors.reduce([]) do |acc, err|
|
180
|
-
acc << @prompt.decorate(
|
188
|
+
acc << @prompt.decorate(">>", :red) + " " + err
|
181
189
|
acc
|
182
190
|
end.join("\n")
|
183
191
|
end
|
@@ -211,8 +219,13 @@ module TTY
|
|
211
219
|
#
|
212
220
|
# @api private
|
213
221
|
def convert_result(value)
|
214
|
-
if convert?
|
215
|
-
|
222
|
+
if convert? && !Utils.blank?(value)
|
223
|
+
case @convert
|
224
|
+
when Proc
|
225
|
+
@convert.call(value)
|
226
|
+
else
|
227
|
+
Converters.convert(@convert, value)
|
228
|
+
end
|
216
229
|
else
|
217
230
|
value
|
218
231
|
end
|
@@ -221,8 +234,13 @@ module TTY
|
|
221
234
|
# Specify answer conversion
|
222
235
|
#
|
223
236
|
# @api public
|
224
|
-
def convert(value)
|
225
|
-
|
237
|
+
def convert(value = (not_set = true), message = nil)
|
238
|
+
messages[:convert?] = message if message
|
239
|
+
if not_set
|
240
|
+
@convert
|
241
|
+
else
|
242
|
+
@convert = value
|
243
|
+
end
|
226
244
|
end
|
227
245
|
|
228
246
|
# Check if conversion is set
|
@@ -239,6 +257,7 @@ module TTY
|
|
239
257
|
# @api public
|
240
258
|
def default(value = (not_set = true))
|
241
259
|
return @default if not_set
|
260
|
+
|
242
261
|
@default = value
|
243
262
|
end
|
244
263
|
|
@@ -259,9 +278,10 @@ module TTY
|
|
259
278
|
def required(value = (not_set = true), message = nil)
|
260
279
|
messages[:required?] = message if message
|
261
280
|
return @required if not_set
|
281
|
+
|
262
282
|
@required = value
|
263
283
|
end
|
264
|
-
|
284
|
+
alias required? required
|
265
285
|
|
266
286
|
# Set validation rule for an argument
|
267
287
|
#
|
@@ -280,6 +300,7 @@ module TTY
|
|
280
300
|
# @api public
|
281
301
|
def value(val)
|
282
302
|
return @value if val.nil?
|
303
|
+
|
283
304
|
@value = val
|
284
305
|
end
|
285
306
|
|
@@ -309,18 +330,20 @@ module TTY
|
|
309
330
|
# @api public
|
310
331
|
def echo(value = nil)
|
311
332
|
return @echo if value.nil?
|
333
|
+
|
312
334
|
@echo = value
|
313
335
|
end
|
314
|
-
|
336
|
+
alias echo? echo
|
315
337
|
|
316
338
|
# Turn raw mode on or off. This enables character-based input.
|
317
339
|
#
|
318
340
|
# @api public
|
319
341
|
def raw(value = nil)
|
320
342
|
return @raw if value.nil?
|
343
|
+
|
321
344
|
@raw = value
|
322
345
|
end
|
323
|
-
|
346
|
+
alias raw? raw
|
324
347
|
|
325
348
|
# Set expected range of values
|
326
349
|
#
|
@@ -333,6 +356,7 @@ module TTY
|
|
333
356
|
@in = Converters.convert(:range, @in)
|
334
357
|
end
|
335
358
|
return @in if not_set
|
359
|
+
|
336
360
|
@in = Converters.convert(:range, value)
|
337
361
|
end
|
338
362
|
|
@@ -345,6 +369,13 @@ module TTY
|
|
345
369
|
@in != UndefinedSetting
|
346
370
|
end
|
347
371
|
|
372
|
+
# Set quiet mode.
|
373
|
+
#
|
374
|
+
# @api public
|
375
|
+
def quiet(value)
|
376
|
+
@quiet = value
|
377
|
+
end
|
378
|
+
|
348
379
|
# @api public
|
349
380
|
def to_s
|
350
381
|
message.to_s
|