tty-prompt 0.8.0 → 0.9.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/CHANGELOG.md +12 -0
- data/README.md +66 -6
- data/appveyor.yml +23 -0
- data/examples/enum_paged.rb +9 -0
- data/examples/select_paginated.rb +9 -0
- data/lib/tty-prompt.rb +2 -0
- data/lib/tty/prompt/enum_list.rb +127 -28
- data/lib/tty/prompt/enum_paginator.rb +54 -0
- data/lib/tty/prompt/list.rb +55 -9
- data/lib/tty/prompt/multi_list.rb +3 -3
- data/lib/tty/prompt/paginator.rb +88 -0
- data/lib/tty/prompt/reader.rb +15 -35
- data/lib/tty/prompt/version.rb +1 -1
- data/spec/unit/enum_paginator_spec.rb +49 -0
- data/spec/unit/enum_select_spec.rb +161 -7
- data/spec/unit/multi_select_spec.rb +41 -0
- data/spec/unit/paginator_spec.rb +47 -0
- data/spec/unit/reader/read_keypress_spec.rb +10 -0
- data/spec/unit/reader/read_line_spec.rb +9 -2
- data/spec/unit/reader/read_multiline_spec.rb +8 -0
- data/spec/unit/select_spec.rb +43 -2
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ef2f5ff49f413f853a8cb33f8894189fb36f728
|
4
|
+
data.tar.gz: cbcd8a42cfefbfbaad8d2028fc5847ce55a20443
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6e8c1ef4460ce0e6ac1ce17d018bd737d98290163293b5d229b7d65cc38c8656784ffbd2b3e13c275f672f145ba22cbe31e74302de0dc0f757d7605f6d22971
|
7
|
+
data.tar.gz: 029244b6acd770bc6ba0836bf85f01f12d3ec80523bd43a5532826516a80ee44937292408f5e12a7657058db8466a0ec29aed9c5054adf9afd65d09e63816dd5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.9.0] - 2016-12-20
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add ability to paginate choices list for #select, #multi_select & #enum_select
|
7
|
+
with :per_page, :page_info and :default options
|
8
|
+
* Add ability to switch through options in #select & #multi_select using the tab key
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
* Fix readers to accept multibyte characters reported by Jaehyun Shin(@keepcosmos)
|
12
|
+
|
3
13
|
## [v0.8.0] - 2016-11-29
|
4
14
|
|
5
15
|
### Added
|
@@ -114,6 +124,8 @@
|
|
114
124
|
|
115
125
|
* Initial implementation and release
|
116
126
|
|
127
|
+
[v0.9.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.8.0...v0.9.0
|
128
|
+
[v0.8.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.7.1...v0.8.0
|
117
129
|
[v0.7.1]: https://github.com/piotrmurach/tty-prompt/compare/v0.7.0...v0.7.1
|
118
130
|
[v0.7.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.6.0...v0.7.0
|
119
131
|
[v0.6.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.5.0...v0.6.0
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# TTY::Prompt [][gitter]
|
2
2
|
[][gem]
|
3
3
|
[][travis]
|
4
|
+
[][appveyor]
|
4
5
|
[][codeclimate]
|
5
6
|
[][coverage]
|
6
7
|
[][inchpages]
|
@@ -8,6 +9,7 @@
|
|
8
9
|
[gitter]: https://gitter.im/piotrmurach/tty
|
9
10
|
[gem]: http://badge.fury.io/rb/tty-prompt
|
10
11
|
[travis]: http://travis-ci.org/piotrmurach/tty-prompt
|
12
|
+
[appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-prompt
|
11
13
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/tty-prompt
|
12
14
|
[coverage]: https://coveralls.io/github/piotrmurach/tty-prompt
|
13
15
|
[inchpages]: http://inch-ci.org/github/piotrmurach/tty-prompt
|
@@ -21,6 +23,8 @@
|
|
21
23
|
* Number of prompt types for gathering user input
|
22
24
|
* A robust API for validating complex inputs
|
23
25
|
* User friendly error feedback
|
26
|
+
* Intuitive DSL for creating complex menus
|
27
|
+
* Ability to page long menus
|
24
28
|
|
25
29
|
## Installation
|
26
30
|
|
@@ -60,9 +64,10 @@ Or install it yourself as:
|
|
60
64
|
* [2.4 multiline](#24-multiline)
|
61
65
|
* [2.5 mask](#25-mask)
|
62
66
|
* [2.6 yes?/no?](#26-yesno)
|
63
|
-
* [2.7
|
64
|
-
* [2.7.1
|
65
|
-
* [2.7.2
|
67
|
+
* [2.7 menu](#27-menu)
|
68
|
+
* [2.7.1 select](#271-select)
|
69
|
+
* [2.7.2 multi_select](#272-multi_select)
|
70
|
+
* [2.7.3 enum_select](#273-enum_select)
|
66
71
|
* [2.8 expand](#28-expand)
|
67
72
|
* [2.9 collect](#29-collect)
|
68
73
|
* [2.10 suggest](#210-suggest)
|
@@ -488,7 +493,9 @@ prompt.no?('Do you hate Ruby?')
|
|
488
493
|
|
489
494
|
Similarly to `yes?` method, you can supply the same options to customize the question.
|
490
495
|
|
491
|
-
### 2.7
|
496
|
+
### 2.7 menu
|
497
|
+
|
498
|
+
### 2.7.1 select
|
492
499
|
|
493
500
|
For asking questions involving list of options use `select` method by passing the question and possible choices:
|
494
501
|
|
@@ -584,7 +591,31 @@ prompt.select("Choose your destiny?", choices, help: "(Bash keyboard)", marker:
|
|
584
591
|
# Jax
|
585
592
|
```
|
586
593
|
|
587
|
-
|
594
|
+
By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
|
595
|
+
|
596
|
+
```ruby
|
597
|
+
letters = ('A'..'Z').to_a
|
598
|
+
prompt.select("Choose your letter?", letters, per_page: 4)
|
599
|
+
# =>
|
600
|
+
# Which letter? (Use arrow keys, press Enter to select)
|
601
|
+
# ‣ A
|
602
|
+
# B
|
603
|
+
# C
|
604
|
+
# D
|
605
|
+
# (Move up or down to reveal more choices)
|
606
|
+
```
|
607
|
+
|
608
|
+
You can also customise page navigation text using `:page_help` option:
|
609
|
+
```ruby
|
610
|
+
letters = ('A'..'Z').to_a
|
611
|
+
prompt.select("Choose your letter?") do |menu|
|
612
|
+
menu.per_page 4
|
613
|
+
menu.page_help '(Wiggle thy finger up or down to see more)'
|
614
|
+
menu.choices letters, per_page: 4)
|
615
|
+
end
|
616
|
+
```
|
617
|
+
|
618
|
+
### 2.7.2 multi_select
|
588
619
|
|
589
620
|
For asking questions involving multiple selection list use `multi_select` method by passing the question and possible choices:
|
590
621
|
|
@@ -685,7 +716,21 @@ prompt.multi_select("Select drinks?", choices, help: 'Press beer can against key
|
|
685
716
|
# ⬡ bourbon
|
686
717
|
```
|
687
718
|
|
688
|
-
|
719
|
+
By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
|
720
|
+
|
721
|
+
```ruby
|
722
|
+
letters = ('A'..'Z').to_a
|
723
|
+
prompt.multi_select("Choose your letter?", letters, per_page: 4)
|
724
|
+
# =>
|
725
|
+
# Which letter? (Use arrow keys, press Space to select and Enter to finish)
|
726
|
+
# ‣ ⬡ A
|
727
|
+
# ⬡ B
|
728
|
+
# ⬡ C
|
729
|
+
# ⬡ D
|
730
|
+
# (Move up or down to reveal more choices)
|
731
|
+
```
|
732
|
+
|
733
|
+
### 2.7.3 enum_select
|
689
734
|
|
690
735
|
In order to ask for standard selection from indexed list you can use `enum_select` and pass question together with possible choices:
|
691
736
|
|
@@ -744,6 +789,21 @@ end
|
|
744
789
|
# Select an editor? /usr/bin/vim
|
745
790
|
```
|
746
791
|
|
792
|
+
By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
|
793
|
+
|
794
|
+
```ruby
|
795
|
+
letters = ('A'..'Z').to_a
|
796
|
+
prompt.enum_select("Choose your letter?", letters, per_page: 4)
|
797
|
+
# =>
|
798
|
+
# Which letter?
|
799
|
+
# 1) A
|
800
|
+
# 2) B
|
801
|
+
# 3) C
|
802
|
+
# 4) D
|
803
|
+
# Choose 1-26 [1]:
|
804
|
+
# (Press tab/right or left to reveal more choices)
|
805
|
+
```
|
806
|
+
|
747
807
|
### 2.8 expand
|
748
808
|
|
749
809
|
The `expand` provides a compact way to ask a question with many options.
|
data/appveyor.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
install:
|
3
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
4
|
+
- ruby --version
|
5
|
+
- gem --version
|
6
|
+
- bundle install
|
7
|
+
build: off
|
8
|
+
test_script:
|
9
|
+
- bundle exec rake ci
|
10
|
+
environment:
|
11
|
+
matrix:
|
12
|
+
- ruby_version: "193"
|
13
|
+
- ruby_version: "200"
|
14
|
+
- ruby_version: "200-x64"
|
15
|
+
- ruby_version: "21"
|
16
|
+
- ruby_version: "21-x64"
|
17
|
+
- ruby_version: "22"
|
18
|
+
- ruby_version: "22-x64"
|
19
|
+
- ruby_version: "23"
|
20
|
+
- ruby_version: "23-x64"
|
21
|
+
matrix:
|
22
|
+
allow_failures:
|
23
|
+
- ruby_version: "193"
|
data/lib/tty-prompt.rb
CHANGED
@@ -20,6 +20,8 @@ require 'tty/prompt/slider'
|
|
20
20
|
require 'tty/prompt/statement'
|
21
21
|
require 'tty/prompt/suggestion'
|
22
22
|
require 'tty/prompt/answers_collector'
|
23
|
+
require 'tty/prompt/paginator'
|
24
|
+
require 'tty/prompt/enum_paginator'
|
23
25
|
require 'tty/prompt/symbols'
|
24
26
|
require 'tty/prompt/test'
|
25
27
|
require 'tty/prompt/utils'
|
data/lib/tty/prompt/enum_list.rb
CHANGED
@@ -7,6 +7,8 @@ module TTY
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class EnumList
|
10
|
+
PAGE_HELP = '(Press tab/right or left to reveal more choices)'.freeze
|
11
|
+
|
10
12
|
# Create instance of EnumList menu.
|
11
13
|
#
|
12
14
|
# @api public
|
@@ -18,10 +20,16 @@ module TTY
|
|
18
20
|
@active_color = options.fetch(:active_color) { @prompt.active_color }
|
19
21
|
@help_color = options.fetch(:help_color) { @prompt.help_color }
|
20
22
|
@error_color = options.fetch(:error_color) { @prompt.error_color }
|
23
|
+
@input = nil
|
21
24
|
@done = false
|
25
|
+
@first_render = true
|
22
26
|
@failure = false
|
23
27
|
@active = @default
|
24
28
|
@choices = Choices.new
|
29
|
+
@per_page = options[:per_page]
|
30
|
+
@page_help = options[:page_help] || PAGE_HELP
|
31
|
+
@paginator = EnumPaginator.new
|
32
|
+
@page_active = @default
|
25
33
|
|
26
34
|
@prompt.subscribe(self)
|
27
35
|
end
|
@@ -33,6 +41,33 @@ module TTY
|
|
33
41
|
@default = default
|
34
42
|
end
|
35
43
|
|
44
|
+
# Set number of items per page
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def per_page(value)
|
48
|
+
@per_page = value
|
49
|
+
end
|
50
|
+
|
51
|
+
def page_size
|
52
|
+
(@per_page || Paginator::DEFAULT_PAGE_SIZE)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Check if list is paginated
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
def paginated?
|
61
|
+
@choices.size >= page_size
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param [String] text
|
65
|
+
# the help text to display per page
|
66
|
+
# @api pbulic
|
67
|
+
def page_help(text)
|
68
|
+
@page_help = text
|
69
|
+
end
|
70
|
+
|
36
71
|
# Set selecting active index using number pad
|
37
72
|
#
|
38
73
|
# @api public
|
@@ -70,14 +105,15 @@ module TTY
|
|
70
105
|
def call(question, possibilities, &block)
|
71
106
|
choices(possibilities)
|
72
107
|
@question = question
|
73
|
-
block
|
108
|
+
block[self] if block
|
74
109
|
setup_defaults
|
75
110
|
render
|
76
111
|
end
|
77
112
|
|
78
113
|
def keypress(event)
|
79
114
|
if [:backspace, :delete].include?(event.key.name)
|
80
|
-
|
115
|
+
return if @input.empty?
|
116
|
+
@input.chop!
|
81
117
|
mark_choice_as_active
|
82
118
|
elsif event.value =~ /^\d+$/
|
83
119
|
@input += event.value
|
@@ -94,24 +130,39 @@ module TTY
|
|
94
130
|
@failure = true
|
95
131
|
end
|
96
132
|
end
|
97
|
-
|
133
|
+
alias keyenter keyreturn
|
98
134
|
|
99
|
-
|
135
|
+
def keyright(*)
|
136
|
+
if (@page_active + page_size) <= @choices.size
|
137
|
+
@page_active += page_size
|
138
|
+
else
|
139
|
+
@page_active = 1
|
140
|
+
end
|
141
|
+
end
|
142
|
+
alias keytab keyright
|
100
143
|
|
101
|
-
def
|
102
|
-
if
|
103
|
-
@
|
144
|
+
def keyleft(*)
|
145
|
+
if (@page_active - page_size) >= 0
|
146
|
+
@page_active -= page_size
|
104
147
|
else
|
105
|
-
@
|
148
|
+
@page_active = @choices.size - 1
|
106
149
|
end
|
107
150
|
end
|
108
151
|
|
109
|
-
|
152
|
+
private
|
153
|
+
|
154
|
+
# Find active choice or set to default
|
155
|
+
#
|
156
|
+
# @return [nil]
|
110
157
|
#
|
111
158
|
# @api private
|
112
|
-
def
|
113
|
-
|
114
|
-
|
159
|
+
def mark_choice_as_active
|
160
|
+
if (@input.to_i > 1) && !@choices[@input.to_i - 1].nil?
|
161
|
+
@active = @input.to_i
|
162
|
+
else
|
163
|
+
@active = @default
|
164
|
+
end
|
165
|
+
@page_active = @active
|
115
166
|
end
|
116
167
|
|
117
168
|
# Validate default indexes to be within range
|
@@ -119,8 +170,16 @@ module TTY
|
|
119
170
|
# @api private
|
120
171
|
def validate_defaults
|
121
172
|
return if @default >= 1 && @default <= @choices.size
|
122
|
-
|
123
|
-
|
173
|
+
raise PromptConfigurationError,
|
174
|
+
"default index `#{d}` out of range (1 - #{@choices.size})"
|
175
|
+
end
|
176
|
+
|
177
|
+
# Setup default option and active selection
|
178
|
+
#
|
179
|
+
# @api private
|
180
|
+
def setup_defaults
|
181
|
+
validate_defaults
|
182
|
+
mark_choice_as_active
|
124
183
|
end
|
125
184
|
|
126
185
|
# Render a selection list.
|
@@ -134,9 +193,9 @@ module TTY
|
|
134
193
|
def render
|
135
194
|
@input = ''
|
136
195
|
until @done
|
137
|
-
render_question
|
196
|
+
lines = render_question
|
138
197
|
@prompt.read_keypress
|
139
|
-
refresh
|
198
|
+
refresh(lines)
|
140
199
|
end
|
141
200
|
render_question
|
142
201
|
render_answer
|
@@ -153,9 +212,11 @@ module TTY
|
|
153
212
|
|
154
213
|
# Determine area of the screen to clear
|
155
214
|
#
|
215
|
+
# @param [Integer] lines
|
216
|
+
# the lines to clear
|
217
|
+
#
|
156
218
|
# @api private
|
157
|
-
def refresh
|
158
|
-
lines = @question.scan("\n").length + @choices.length + 2
|
219
|
+
def refresh(lines)
|
159
220
|
@prompt.print(@prompt.clear_lines(lines))
|
160
221
|
@prompt.print(@prompt.cursor.clear_screen_down)
|
161
222
|
end
|
@@ -166,18 +227,34 @@ module TTY
|
|
166
227
|
def render_question
|
167
228
|
header = "#{@prefix}#{@question} #{render_header}"
|
168
229
|
@prompt.puts(header)
|
169
|
-
|
170
|
-
@
|
171
|
-
|
230
|
+
lines = header.lines.count
|
231
|
+
unless @done
|
232
|
+
menu = render_menu + render_footer
|
233
|
+
lines += menu.lines.count
|
234
|
+
@prompt.print(menu)
|
235
|
+
end
|
172
236
|
render_error if @failure
|
237
|
+
render_page_help if paginated? && !@done
|
238
|
+
lines
|
173
239
|
end
|
174
240
|
|
241
|
+
# Error message when incorrect index chosen
|
242
|
+
#
|
243
|
+
# @api private
|
244
|
+
def error_message
|
245
|
+
error = 'Please enter a valid number'
|
246
|
+
"\n" + @prompt.decorate('>>', @error_color) + ' ' + error
|
247
|
+
end
|
248
|
+
|
249
|
+
# Render error message and return cursor to position of input
|
250
|
+
#
|
175
251
|
# @api private
|
176
252
|
def render_error
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
253
|
+
@prompt.print(error_message)
|
254
|
+
if !paginated?
|
255
|
+
@prompt.print(@prompt.cursor.prev_line)
|
256
|
+
@prompt.print(@prompt.cursor.forward(render_footer.size))
|
257
|
+
end
|
181
258
|
end
|
182
259
|
|
183
260
|
# Render chosen option
|
@@ -188,7 +265,7 @@ module TTY
|
|
188
265
|
def render_header
|
189
266
|
return '' unless @done
|
190
267
|
return '' unless @active
|
191
|
-
selected_item =
|
268
|
+
selected_item = @choices[@active - 1].name.to_s
|
192
269
|
@prompt.decorate(selected_item, @active_color)
|
193
270
|
end
|
194
271
|
|
@@ -201,6 +278,28 @@ module TTY
|
|
201
278
|
" Choose 1-#{@choices.size} [#{@default}]: #{@input}"
|
202
279
|
end
|
203
280
|
|
281
|
+
# Pagination help message
|
282
|
+
#
|
283
|
+
# @return [String]
|
284
|
+
#
|
285
|
+
# @api private
|
286
|
+
def page_help_message
|
287
|
+
return '' unless paginated?
|
288
|
+
"\n" + @prompt.decorate(@page_help, @help_color)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Render page help
|
292
|
+
#
|
293
|
+
# @api private
|
294
|
+
def render_page_help
|
295
|
+
@prompt.print(page_help_message)
|
296
|
+
if @failure
|
297
|
+
@prompt.print(@prompt.cursor.prev_line)
|
298
|
+
end
|
299
|
+
@prompt.print(@prompt.cursor.prev_line)
|
300
|
+
@prompt.print(@prompt.cursor.forward(render_footer.size))
|
301
|
+
end
|
302
|
+
|
204
303
|
# Render menu with indexed choices to select from
|
205
304
|
#
|
206
305
|
# @return [String]
|
@@ -208,11 +307,11 @@ module TTY
|
|
208
307
|
# @api private
|
209
308
|
def render_menu
|
210
309
|
output = ''
|
211
|
-
@choices
|
310
|
+
@paginator.paginate(@choices, @page_active, @per_page) do |choice, index|
|
212
311
|
num = (index + 1).to_s + @enum + Symbols::SPACE
|
213
312
|
selected = Symbols::SPACE * 2 + num + choice.name
|
214
313
|
output << if index + 1 == @active
|
215
|
-
@prompt.decorate(
|
314
|
+
@prompt.decorate(selected.to_s, @active_color)
|
216
315
|
else
|
217
316
|
selected
|
218
317
|
end
|