tty-prompt 0.1.0 → 0.2.0
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/.travis.yml +0 -2
- data/CHANGELOG.md +12 -0
- data/README.md +223 -59
- data/lib/tty/prompt/choice.rb +83 -0
- data/lib/tty/prompt/choices.rb +92 -0
- data/lib/tty/prompt/codes.rb +32 -0
- data/lib/tty/prompt/cursor.rb +131 -0
- data/lib/tty/prompt/list.rb +209 -0
- data/lib/tty/prompt/mode/echo.rb +10 -9
- data/lib/tty/prompt/mode/raw.rb +10 -9
- data/lib/tty/prompt/multi_list.rb +105 -0
- data/lib/tty/prompt/question/validation.rb +12 -27
- data/lib/tty/prompt/question.rb +58 -107
- data/lib/tty/prompt/reader.rb +44 -11
- data/lib/tty/prompt/response.rb +31 -36
- data/lib/tty/prompt/response_delegation.rb +3 -2
- data/lib/tty/prompt/statement.rb +10 -10
- data/lib/tty/prompt/test.rb +15 -0
- data/lib/tty/prompt/version.rb +3 -3
- data/lib/tty/prompt.rb +72 -9
- data/lib/tty-prompt.rb +11 -0
- data/spec/unit/ask_spec.rb +32 -35
- data/spec/unit/choice/eql_spec.rb +24 -0
- data/spec/unit/choice/from_spec.rb +25 -0
- data/spec/unit/choices/add_spec.rb +14 -0
- data/spec/unit/choices/each_spec.rb +15 -0
- data/spec/unit/choices/new_spec.rb +12 -0
- data/spec/unit/choices/pluck_spec.rb +11 -0
- data/spec/unit/cursor/new_spec.rb +74 -0
- data/spec/unit/error_spec.rb +4 -8
- data/spec/unit/multi_select_spec.rb +163 -0
- data/spec/unit/question/character_spec.rb +5 -16
- data/spec/unit/question/default_spec.rb +4 -10
- data/spec/unit/question/in_spec.rb +15 -12
- data/spec/unit/question/initialize_spec.rb +1 -6
- data/spec/unit/question/modify_spec.rb +25 -24
- data/spec/unit/question/required_spec.rb +31 -0
- data/spec/unit/question/validate_spec.rb +25 -17
- data/spec/unit/question/validation/call_spec.rb +22 -0
- data/spec/unit/response/read_bool_spec.rb +38 -27
- data/spec/unit/response/read_char_spec.rb +5 -8
- data/spec/unit/response/read_date_spec.rb +8 -12
- data/spec/unit/response/read_email_spec.rb +25 -22
- data/spec/unit/response/read_multiple_spec.rb +11 -13
- data/spec/unit/response/read_number_spec.rb +12 -16
- data/spec/unit/response/read_range_spec.rb +10 -13
- data/spec/unit/response/read_spec.rb +39 -38
- data/spec/unit/response/read_string_spec.rb +7 -12
- data/spec/unit/say_spec.rb +10 -14
- data/spec/unit/select_spec.rb +192 -0
- data/spec/unit/statement/initialize_spec.rb +0 -4
- data/spec/unit/suggest_spec.rb +6 -9
- data/spec/unit/warn_spec.rb +4 -8
- metadata +32 -8
- data/spec/unit/question/argument_spec.rb +0 -30
- data/spec/unit/question/valid_spec.rb +0 -46
- data/spec/unit/question/validation/valid_value_spec.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e24965d09c08a3bf136438bad66551d05f25a0f
|
4
|
+
data.tar.gz: 476702a67dd13fe4796c888d089107f4b6f7f18d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0645bb40ca7b847976e69d0d3c65e4e0a9441f4e3bade6ef1e0d38e7d9ef28e66132645aa30740c7a258939fe262664ed93306968eb76969bee768029d19c406
|
7
|
+
data.tar.gz: 70c03c2eb72010d0efe7d8a125c285dc32ec34117e29e2a44b17839c645a8b1650dd14d1184b7b8a871dc92b2c44121ab1e727aa9f5ca41c893184b678171fc8
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
0.2.0 (Nov 23, 2015)
|
2
|
+
|
3
|
+
* Add ability to select choice form list #select
|
4
|
+
* Add ability to select multiple options #multi_select
|
5
|
+
* Change #ask api to be similar to #select and #multi_select behaviour
|
6
|
+
* Change #ask :argument option to be :required
|
7
|
+
* Add :read option to #ask for reading specific type input
|
8
|
+
* Remove :valid option from #ask as #select is a better solution
|
9
|
+
|
10
|
+
0.1.0 (Nov 1, 2015)
|
11
|
+
|
12
|
+
* Initial implementation and release
|
data/README.md
CHANGED
@@ -17,8 +17,8 @@
|
|
17
17
|
|
18
18
|
## Features
|
19
19
|
|
20
|
+
* Number of prompt types for gathering user input
|
20
21
|
* A robust API for getting and validating complex inputs
|
21
|
-
* Number of coercion methods for converting response into Ruby types
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
@@ -41,10 +41,12 @@ Or install it yourself as:
|
|
41
41
|
* [1. Usage](#1-usage)
|
42
42
|
* [2. Interface](#2-interface)
|
43
43
|
* [2.1 ask](#21-ask)
|
44
|
-
|
45
|
-
|
46
|
-
* [2.
|
47
|
-
|
44
|
+
* [2.1.1 settings](#211-settings)
|
45
|
+
* [2.1.2 valid read keywords](#212-valid-read-keywords)
|
46
|
+
* [2.2 select](#22-select)
|
47
|
+
* [2.3 multi_select](#23-multi_select)
|
48
|
+
* [2.4 say](#25-say)
|
49
|
+
* [2.5 suggest](#26-suggest)
|
48
50
|
|
49
51
|
## 1. Usage
|
50
52
|
|
@@ -54,101 +56,263 @@ In order to start asking questions on the command line, create prompt:
|
|
54
56
|
prompt = TTY::Prompt.new
|
55
57
|
```
|
56
58
|
|
57
|
-
and then call `ask` with the question
|
59
|
+
and then call `ask` with the question for simple input:
|
58
60
|
|
59
61
|
```ruby
|
60
|
-
|
62
|
+
prompt.ask('Do you like Ruby?', type: :bool) # => true
|
61
63
|
```
|
62
64
|
|
63
|
-
|
65
|
+
Asking question with list of options couldn't be easier using `select` like so:
|
64
66
|
|
65
67
|
```ruby
|
66
|
-
|
68
|
+
prompt.select("Choose your destiny?", %w(Scorpion Kano Jax))
|
69
|
+
# =>
|
70
|
+
# Choose your destiny? (Use arrow keys, press Enter to select)
|
71
|
+
# ‣ Scorpion
|
72
|
+
# Kano
|
73
|
+
# Jax
|
74
|
+
```
|
75
|
+
|
76
|
+
Also, asking multiple choice questions is a breeze with `multi_select`:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
choices = %w(vodka beer wine whisky bourbon)
|
80
|
+
prompt.select("Select drinks?", choices)
|
81
|
+
# =>
|
82
|
+
#
|
83
|
+
# Select drinks? (Use arrow keys, press Space to select and Enter to finish)"
|
84
|
+
# ‣ ⬡ vodka
|
85
|
+
# ⬡ beer
|
86
|
+
# ⬡ wine
|
87
|
+
# ⬡ whisky
|
88
|
+
# ⬡ bourbon
|
67
89
|
```
|
68
90
|
|
69
91
|
## 2. Interface
|
70
92
|
|
71
93
|
### 2.1 ask
|
72
94
|
|
73
|
-
In order to ask a basic question
|
95
|
+
In order to ask a basic question with a string answer do:
|
74
96
|
|
75
97
|
```ruby
|
76
|
-
answer = prompt.ask("What is your name?")
|
98
|
+
answer = prompt.ask("What is your name?")
|
77
99
|
```
|
78
100
|
|
79
|
-
|
101
|
+
In order to prompt for more complex input you can use robust API by passing hash of properties or using block:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
prompt.ask("What is your name?") do |q|
|
105
|
+
q.required true
|
106
|
+
q.validate /\A\w+\Z/
|
107
|
+
q.modify :capitalize
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
#### 2.1.1 settings
|
112
|
+
|
113
|
+
Below is a list of the settings that may be used for customizing `ask` method behaviour:
|
80
114
|
|
81
115
|
```ruby
|
82
|
-
argument # :required or :optional
|
83
116
|
char # turn character based input, otherwise line (default: false)
|
84
|
-
clean # reset question
|
85
117
|
default # default value used if none is provided
|
86
118
|
echo # turn echo on and off (default: true)
|
119
|
+
in # specify range '0-9', '0..9', '0...9' or negative '-1..-9'
|
87
120
|
mask # mask characters i.e '****' (default: false)
|
88
121
|
modify # apply answer modification :upcase, :downcase, :trim, :chomp etc..
|
89
|
-
|
90
|
-
|
91
|
-
|
122
|
+
read # Specifies the type of input such as :bool, :string [see](#211-valid-read-keywords)
|
123
|
+
required # If true, value entered must be non-empty (default: false)
|
124
|
+
validate # regex, proc against which stdin input is checked
|
92
125
|
```
|
93
126
|
|
94
|
-
|
127
|
+
Validate setting can take `Regex`, `Proc` like so:
|
95
128
|
|
96
129
|
```ruby
|
97
|
-
prompt.ask(
|
130
|
+
prompt.ask('What is your username?') { |q|
|
131
|
+
q.validate { |input| input =~ (/^[^\.]+\.[^\.]+/) }
|
132
|
+
}
|
133
|
+
```
|
134
|
+
|
135
|
+
For example, if we wanted to ask a user for a single digit in given range
|
98
136
|
|
99
|
-
|
100
|
-
|
101
|
-
default 'Piotr'
|
102
|
-
validate /\w+\s\w+/
|
103
|
-
valid ['Piotr', 'Piotrek']
|
104
|
-
modify :capitalize
|
105
|
-
end.read_string
|
137
|
+
```ruby
|
138
|
+
ask("Provide number in range: 0-9") { |q| q.in('0-9') }
|
106
139
|
```
|
107
140
|
|
108
|
-
|
141
|
+
#### 2.1.2 valid read keywords
|
109
142
|
|
110
|
-
|
143
|
+
The most common thing to do is to cast the answer to specific type. The `read` property is used for that. By default `:string` answer is assumed but this can be changed using one of the following custom readers:
|
111
144
|
|
112
145
|
```ruby
|
113
|
-
|
146
|
+
:bool # true or false for strings such as "Yes", "No"
|
147
|
+
:char # first character
|
148
|
+
:date # date type
|
149
|
+
:datetime # datetime type
|
150
|
+
:email # validate answer against email regex
|
151
|
+
:file # a File object
|
152
|
+
:float # decimal or error if cannot convert
|
153
|
+
:int # integer or error if cannot convert
|
154
|
+
:multiline # multiple line string
|
155
|
+
:password # string with echo turned off
|
156
|
+
:range # range type
|
157
|
+
:regex # regex expression
|
158
|
+
:string # string
|
159
|
+
:symbol # symbol
|
160
|
+
:text # multiline string
|
161
|
+
:keypress # the key pressed
|
114
162
|
```
|
115
163
|
|
116
|
-
|
164
|
+
For example, if you are interested in range type as answer do the following:
|
117
165
|
|
118
166
|
```ruby
|
119
|
-
|
120
|
-
read_char # return first character
|
121
|
-
read_date # return date type
|
122
|
-
read_datetime # return datetime type
|
123
|
-
read_email # validate answer against email regex
|
124
|
-
read_file # return a File object
|
125
|
-
read_float # return decimal or error if cannot convert
|
126
|
-
read_int # return integer or error if cannot convert
|
127
|
-
read_multiple # return multiple line string
|
128
|
-
read_password # return string with echo turned off
|
129
|
-
read_range # return range type
|
130
|
-
read_regex # return regex expression
|
131
|
-
read_string # return string
|
132
|
-
read_symbol # return symbol
|
133
|
-
read_text # return multiline string
|
134
|
-
read_keypress # return the key pressed
|
167
|
+
ask("Provide range of numbers?", read: :range)
|
135
168
|
```
|
136
169
|
|
137
|
-
|
170
|
+
### 2.2 select
|
171
|
+
|
172
|
+
For asking questions involving list of options use `select` method by passing the question and possible choices:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
prompt.select("Choose your destiny?", %w(Scorpion Kano Jax))
|
176
|
+
# =>
|
177
|
+
# Choose your destiny? (Use arrow keys, press Enter to select)
|
178
|
+
# ‣ Scorpion
|
179
|
+
# Kano
|
180
|
+
# Jax
|
181
|
+
```
|
182
|
+
|
183
|
+
You can also provide options through DSL using the `choice` method for single entry and/or `choices` call for more than one choice:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
prompt.select("Choose your destiny?") do |menu|
|
187
|
+
menu.choice 'Scorpion'
|
188
|
+
menu.choice 'Kano'
|
189
|
+
menu.choice 'Jax'
|
190
|
+
end
|
191
|
+
# =>
|
192
|
+
# Choose your destiny? (Use arrow keys, press Enter to select)
|
193
|
+
# ‣ Scorpion
|
194
|
+
# Kano
|
195
|
+
# Jax
|
196
|
+
```
|
197
|
+
|
198
|
+
By default the choice name is used as return value, but you can provide your custom values:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
prompt.select("Choose your destiny?") do |menu|
|
202
|
+
menu.choice 'Scorpion', 1
|
203
|
+
menu.choice 'Kano', 2
|
204
|
+
menu.choice 'Jax', 3
|
205
|
+
end
|
206
|
+
# =>
|
207
|
+
# Choose your destiny? (Use arrow keys, press Enter to select)
|
208
|
+
# ‣ Scorpion
|
209
|
+
# Kano
|
210
|
+
# Jax
|
211
|
+
```
|
212
|
+
|
213
|
+
If you wish you can also provide a simple hash to denote choice name and its value like so:
|
138
214
|
|
139
215
|
```ruby
|
140
|
-
|
141
|
-
|
142
|
-
|
216
|
+
choices = {'Scorpion' => 1, 'Kano' => 2, 'Jax' => 3}
|
217
|
+
prompt.select("Choose your destiny?", choices)
|
218
|
+
```
|
219
|
+
|
220
|
+
To mark particular answer as selected use `default` with index of the option starting from `1`:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
prompt.select("Choose your destiny?") do |menu|
|
224
|
+
menu.default 3
|
225
|
+
|
226
|
+
menu.choice 'Scorpion', 1
|
227
|
+
menu.choice 'Kano', 2
|
228
|
+
menu.choice 'Jax', 3
|
229
|
+
end
|
230
|
+
# =>
|
231
|
+
# Choose your destiny? (Use arrow keys, press Enter to select)
|
232
|
+
# Scorpion
|
233
|
+
# Kano
|
234
|
+
# ‣ Jax
|
235
|
+
```
|
236
|
+
|
237
|
+
You can configure help message, marker like so
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
choices = %w(Scorpion Kano Jax)
|
241
|
+
prompt.select("Choose your destiny?", choices, help: "(Bash keyboard)")
|
242
|
+
# =>
|
243
|
+
# Choose your destiny? (Bash keyboard)
|
244
|
+
# ‣ Scorpion
|
245
|
+
# Kano
|
246
|
+
# Jax
|
247
|
+
```
|
248
|
+
|
249
|
+
### 2.3 multi_select
|
250
|
+
|
251
|
+
For asking questions involving multiple selection list use `multi_select` method by passing the question and possible choices:
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
choices = %w(vodka beer wine whisky bourbon)
|
255
|
+
prompt.select("Select drinks?", choices)
|
256
|
+
# =>
|
257
|
+
#
|
258
|
+
# Select drinks? (Use arrow keys, press Space to select and Enter to finish)"
|
259
|
+
# ‣ ⬡ vodka
|
260
|
+
# ⬡ beer
|
261
|
+
# ⬡ wine
|
262
|
+
# ⬡ whisky
|
263
|
+
# ⬡ bourbon
|
264
|
+
```
|
265
|
+
|
266
|
+
As a return value, the `multi_select` will always return an array by default populated with the names of the choices. If you wish to return custom values for the available choices do:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
|
270
|
+
prompt.select("Select drinks?", choices)
|
271
|
+
|
272
|
+
# Provided that vodka and beer have been selected, the function will return
|
273
|
+
# => [1, 2]
|
274
|
+
```
|
275
|
+
|
276
|
+
Similar to `select` method, you can also provide options through DSL using the `choice` method for single entry and/or `choices` call for more than one choice:
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
prompt.multi_select("Select drinks?") do |menu|
|
280
|
+
menu.choice :vodka, {score: 1}
|
281
|
+
menu.choice :beer, 2
|
282
|
+
menu.choice :wine, 3
|
283
|
+
menu.choices whisky: 4, bourbon: 5
|
284
|
+
end
|
285
|
+
```
|
286
|
+
|
287
|
+
To mark choice(s) as selected use the `default` option with index(s) of the option(s) starting from `1`:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
prompt.multi_select("Select drinks?") do |menu|
|
291
|
+
menu.default 2, 5
|
292
|
+
|
293
|
+
menu.choice :vodka, {score: 10}
|
294
|
+
menu.choice :beer, {score: 20}
|
295
|
+
menu.choice :wine, {score: 30}
|
296
|
+
menu.choice :whisky, {score: 40}
|
297
|
+
menu.choice :bourbon, {score: 50}
|
298
|
+
end
|
299
|
+
# =>
|
300
|
+
# Select drinks? beer, bourbon
|
301
|
+
# ⬡ vodka
|
302
|
+
# ⬢ beer
|
303
|
+
# ⬡ wine
|
304
|
+
# ⬡ whisky
|
305
|
+
# ‣ ⬢ bourbon
|
143
306
|
```
|
144
307
|
|
145
|
-
|
308
|
+
And when you press enter you will see the following selected:
|
146
309
|
|
147
310
|
```ruby
|
148
|
-
|
311
|
+
# Select drinks? beer, bourbon
|
312
|
+
# => [{score: 20}, {score: 50}]
|
149
313
|
```
|
150
314
|
|
151
|
-
### 2.
|
315
|
+
### 2.4 say
|
152
316
|
|
153
317
|
To simply print message out to stdout use `say` like so:
|
154
318
|
|
@@ -164,16 +328,16 @@ prompt.warn # print message(s) in yellow
|
|
164
328
|
prompt.error # print message(s) in red
|
165
329
|
```
|
166
330
|
|
167
|
-
### 2.
|
331
|
+
### 2.5 suggest
|
168
332
|
|
169
333
|
To suggest possible matches for the user input use `suggest` method like so:
|
170
334
|
|
171
335
|
```ruby
|
172
336
|
prompt.suggest('sta', ['stage', 'stash', 'commit', 'branch'])
|
173
337
|
# =>
|
174
|
-
Did you mean one of these?
|
175
|
-
|
176
|
-
|
338
|
+
# Did you mean one of these?
|
339
|
+
# stage
|
340
|
+
# stash
|
177
341
|
```
|
178
342
|
|
179
343
|
To cusomize query text presented pass `:single_text` and `:plural_text` options to respectively change the message when one match is found or many.
|
@@ -182,8 +346,8 @@ To cusomize query text presented pass `:single_text` and `:plural_text` options
|
|
182
346
|
possible = %w(status stage stash commit branch blame)
|
183
347
|
prompt.suggest('b', possible, indent: 4, single_text: 'Perhaps you meant?')
|
184
348
|
# =>
|
185
|
-
Perhaps you meant?
|
186
|
-
|
349
|
+
# Perhaps you meant?
|
350
|
+
# blame
|
187
351
|
```
|
188
352
|
|
189
353
|
## Contributing
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
# A single choice option
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
class Choice
|
9
|
+
# The label name
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# Create a Choice instance
|
15
|
+
#
|
16
|
+
# @api public
|
17
|
+
def initialize(name, value)
|
18
|
+
@name = name
|
19
|
+
@value = value
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create choice from value
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Choice.from(:option_1)
|
26
|
+
# Choice.from([:option_1, 1])
|
27
|
+
#
|
28
|
+
# @param [Object] val
|
29
|
+
# the value to be converted
|
30
|
+
#
|
31
|
+
# @raise [ArgumentError]
|
32
|
+
#
|
33
|
+
# @return [Choice]
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def self.from(val)
|
37
|
+
case val
|
38
|
+
when Choice
|
39
|
+
return val
|
40
|
+
when String, Symbol
|
41
|
+
new(val, val)
|
42
|
+
when Array
|
43
|
+
new("#{val.first}", val.last)
|
44
|
+
when Hash
|
45
|
+
new("#{val.keys.first}", val.values.first)
|
46
|
+
else
|
47
|
+
raise ArgumentError, "#{val} cannot be coerced into Choice"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Read value and evaluate
|
52
|
+
#
|
53
|
+
# @api public
|
54
|
+
def value
|
55
|
+
case @value
|
56
|
+
when Proc
|
57
|
+
@value.call
|
58
|
+
else
|
59
|
+
@value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Object equality comparison
|
64
|
+
#
|
65
|
+
# @return [Boolean]
|
66
|
+
#
|
67
|
+
# @api public
|
68
|
+
def ==(other)
|
69
|
+
return false unless other.is_a?(self.class)
|
70
|
+
name == other.name && value == other.value
|
71
|
+
end
|
72
|
+
|
73
|
+
# Object string representation
|
74
|
+
#
|
75
|
+
# @return [String]
|
76
|
+
#
|
77
|
+
# @api public
|
78
|
+
def to_s
|
79
|
+
"#{name}"
|
80
|
+
end
|
81
|
+
end # Choice
|
82
|
+
end # Prompt
|
83
|
+
end # TTY
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module TTY
|
6
|
+
class Prompt
|
7
|
+
# A class responsible for storing a collection of choices
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class Choices
|
11
|
+
include Enumerable
|
12
|
+
extend Forwardable
|
13
|
+
|
14
|
+
# The actual collection choices
|
15
|
+
#
|
16
|
+
# @return [Array[Choice]]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
attr_reader :choices
|
20
|
+
|
21
|
+
def_delegators :choices, :length, :size, :to_ary, :empty?, :values_at
|
22
|
+
|
23
|
+
# Convenience for creating choices
|
24
|
+
#
|
25
|
+
# @param [Array[Object]] choices
|
26
|
+
# the choice objects
|
27
|
+
#
|
28
|
+
# @return [Choices]
|
29
|
+
# the choices collection
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def self.[](*choices)
|
33
|
+
new(choices)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Create Choices collection
|
37
|
+
#
|
38
|
+
# @param [Array[Choice]] choices
|
39
|
+
# the choices to add to collection
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def initialize(choices = [])
|
43
|
+
@choices = choices.map do |choice|
|
44
|
+
Choice.from(choice)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Iterate over all choices in the collection
|
49
|
+
#
|
50
|
+
# @yield [Choice]
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
def each(&block)
|
54
|
+
return to_enum unless block_given?
|
55
|
+
choices.each(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Add choice to collection
|
59
|
+
#
|
60
|
+
# @param [Object] choice
|
61
|
+
# the choice to add
|
62
|
+
#
|
63
|
+
# @api public
|
64
|
+
def <<(choice)
|
65
|
+
choices << Choice.from(choice)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Access choice by index
|
69
|
+
#
|
70
|
+
# @param [Integer] index
|
71
|
+
#
|
72
|
+
# @return [Choice]
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
def [](index)
|
76
|
+
@choices[index]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Pluck a choice by its name from collection
|
80
|
+
#
|
81
|
+
# @param [String] name
|
82
|
+
# the label name for the choice
|
83
|
+
#
|
84
|
+
# @return [Choice]
|
85
|
+
#
|
86
|
+
# @api public
|
87
|
+
def pluck(name)
|
88
|
+
find { |choice| choice.name == name }
|
89
|
+
end
|
90
|
+
end # Choices
|
91
|
+
end # Prompt
|
92
|
+
end # TTY
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
module Codes
|
6
|
+
BACKSPACE = "\177"
|
7
|
+
DELETE = "\004"
|
8
|
+
ESCAPE = "\e"
|
9
|
+
LINEFEED = "\n"
|
10
|
+
RETURN = "\r"
|
11
|
+
SPACE = " "
|
12
|
+
TAB = "\t"
|
13
|
+
|
14
|
+
KEY_UP = "\e[A"
|
15
|
+
KEY_DOWN = "\e[B"
|
16
|
+
KEY_RIGHT = "\e[C"
|
17
|
+
KEY_LEFT = "\e[D"
|
18
|
+
KEY_DELETE = "\e[3"
|
19
|
+
|
20
|
+
CTRL_J = "\x0A"
|
21
|
+
CTRL_N = "\x0E"
|
22
|
+
CTRL_K = "\x0B"
|
23
|
+
CTRL_P = "\x10"
|
24
|
+
SIGINT = "\x03"
|
25
|
+
|
26
|
+
ITEM_SECURE = "•"
|
27
|
+
ITEM_SELECTED = "‣"
|
28
|
+
RADIO_CHECKED = "⬢"
|
29
|
+
RADIO_UNCHECKED = "⬡"
|
30
|
+
end # Codes
|
31
|
+
end # Prompt
|
32
|
+
end # TTY
|