austb-tty-prompt 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +25 -0
  5. data/CHANGELOG.md +218 -0
  6. data/CODE_OF_CONDUCT.md +49 -0
  7. data/Gemfile +19 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +1132 -0
  10. data/Rakefile +8 -0
  11. data/appveyor.yml +23 -0
  12. data/benchmarks/speed.rb +27 -0
  13. data/examples/ask.rb +15 -0
  14. data/examples/collect.rb +19 -0
  15. data/examples/echo.rb +11 -0
  16. data/examples/enum.rb +8 -0
  17. data/examples/enum_paged.rb +9 -0
  18. data/examples/enum_select.rb +7 -0
  19. data/examples/expand.rb +29 -0
  20. data/examples/in.rb +9 -0
  21. data/examples/inputs.rb +10 -0
  22. data/examples/key_events.rb +11 -0
  23. data/examples/keypress.rb +9 -0
  24. data/examples/mask.rb +13 -0
  25. data/examples/multi_select.rb +8 -0
  26. data/examples/multi_select_paged.rb +9 -0
  27. data/examples/multiline.rb +9 -0
  28. data/examples/pause.rb +7 -0
  29. data/examples/select.rb +18 -0
  30. data/examples/select_paginated.rb +9 -0
  31. data/examples/slider.rb +6 -0
  32. data/examples/validation.rb +9 -0
  33. data/examples/yes_no.rb +7 -0
  34. data/lib/tty-prompt.rb +4 -0
  35. data/lib/tty/prompt.rb +535 -0
  36. data/lib/tty/prompt/answers_collector.rb +59 -0
  37. data/lib/tty/prompt/choice.rb +90 -0
  38. data/lib/tty/prompt/choices.rb +110 -0
  39. data/lib/tty/prompt/confirm_question.rb +129 -0
  40. data/lib/tty/prompt/converter_dsl.rb +22 -0
  41. data/lib/tty/prompt/converter_registry.rb +64 -0
  42. data/lib/tty/prompt/converters.rb +77 -0
  43. data/lib/tty/prompt/distance.rb +49 -0
  44. data/lib/tty/prompt/enum_list.rb +337 -0
  45. data/lib/tty/prompt/enum_paginator.rb +56 -0
  46. data/lib/tty/prompt/evaluator.rb +29 -0
  47. data/lib/tty/prompt/expander.rb +292 -0
  48. data/lib/tty/prompt/keypress.rb +94 -0
  49. data/lib/tty/prompt/list.rb +317 -0
  50. data/lib/tty/prompt/mask_question.rb +91 -0
  51. data/lib/tty/prompt/multi_list.rb +108 -0
  52. data/lib/tty/prompt/multiline.rb +71 -0
  53. data/lib/tty/prompt/paginator.rb +88 -0
  54. data/lib/tty/prompt/question.rb +333 -0
  55. data/lib/tty/prompt/question/checks.rb +87 -0
  56. data/lib/tty/prompt/question/modifier.rb +94 -0
  57. data/lib/tty/prompt/question/validation.rb +72 -0
  58. data/lib/tty/prompt/reader.rb +352 -0
  59. data/lib/tty/prompt/reader/codes.rb +121 -0
  60. data/lib/tty/prompt/reader/console.rb +57 -0
  61. data/lib/tty/prompt/reader/history.rb +145 -0
  62. data/lib/tty/prompt/reader/key_event.rb +91 -0
  63. data/lib/tty/prompt/reader/line.rb +162 -0
  64. data/lib/tty/prompt/reader/mode.rb +44 -0
  65. data/lib/tty/prompt/reader/win_api.rb +29 -0
  66. data/lib/tty/prompt/reader/win_console.rb +53 -0
  67. data/lib/tty/prompt/result.rb +42 -0
  68. data/lib/tty/prompt/slider.rb +182 -0
  69. data/lib/tty/prompt/statement.rb +55 -0
  70. data/lib/tty/prompt/suggestion.rb +115 -0
  71. data/lib/tty/prompt/symbols.rb +61 -0
  72. data/lib/tty/prompt/timeout.rb +69 -0
  73. data/lib/tty/prompt/utils.rb +44 -0
  74. data/lib/tty/prompt/version.rb +7 -0
  75. data/lib/tty/test_prompt.rb +20 -0
  76. data/tasks/console.rake +11 -0
  77. data/tasks/coverage.rake +11 -0
  78. data/tasks/spec.rake +29 -0
  79. data/tty-prompt.gemspec +32 -0
  80. metadata +243 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 00d9b66e9648c7cbead34f0012a6120d5789b476
4
+ data.tar.gz: 0effaa17428ccaee0ede5627c0857cb1d1d58823
5
+ SHA512:
6
+ metadata.gz: 2f07c871bce4d4dc2e6797d586b518616c7ceb3836402de240d6b631b049b58caa09444d9b20f9bf973a02e5a24ddc789f75d423edc560b972dafecb01405c1e
7
+ data.tar.gz: 3d092541ec166c171f9cb473b9e35cb6d532c29bdfd204ff9982c5afe13ef14620b97eca569771b585bb1fbdba4f6ecd37cd42a38ef11864441af056ecc84ddd
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --warnings
@@ -0,0 +1,25 @@
1
+ ---
2
+ language: ruby
3
+ sudo: false
4
+ cache: bundler
5
+ bundler_args: --without tools
6
+ script: "bundle exec rake ci"
7
+ rvm:
8
+ - 1.9.3
9
+ - 2.0.0
10
+ - 2.1.10
11
+ - 2.2.6
12
+ - 2.3.3
13
+ - 2.4.1
14
+ - ruby-head
15
+ - jruby-9000
16
+ - jruby-head
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: ruby-head
20
+ - rvm: jruby-head
21
+ fast_finish: true
22
+ branches:
23
+ only: master
24
+ notifications:
25
+ email: false
@@ -0,0 +1,218 @@
1
+ # Change log
2
+
3
+ ## [v0.13.0] _ 2017-xx-xx
4
+
5
+ ### Added
6
+
7
+ ### Changed
8
+ * Change Timeout to use clock time instead of sleep to measure interval
9
+
10
+ ### Fixed
11
+ * Fix keypress with timeout option to cleanly stop timeout thread
12
+ * Fix Reader to treat git-bash & cygwin emulators as unix like
13
+
14
+ ## [v0.12.0] - 2017-03-19
15
+
16
+ ### Added
17
+ * Add Multiline question type
18
+ * Add Keypress question type
19
+ * Add Reader::History for storing buffered lines
20
+ * Add Reader::Line for line abstraction
21
+
22
+ ### Changed
23
+ * Remove :read option from Question
24
+ * Chnage Reader#read_line to handle raw mode for processing special
25
+ characters such as Ctrl+x, navigate through history buffer
26
+ using up/down arrows, allow editing current line by moving left/right
27
+ with arrow keys and inserting content
28
+ * Change Reader#read_multiline to gather multi line input correctly,
29
+ skip empty lines and terminate when Ctrl+d and Ctrl+z are pressed
30
+ * Change Reader::Mode to check if tty is available by Matt Martyn (@MMartyn)
31
+ * Change #keypress prompt to correctly refresh line and accept :keys & :timeout options
32
+
33
+ ### Fixed
34
+ * Fix issue with #select, #multi_selct, #enum_select when choices are
35
+ provided as hash object together with prompt options.
36
+ * Fix issue with default parameter for yes?/no? prompt by Carlos Fonseca (@carlosefonseca)
37
+ * Fix List#help to allow setting help text through DSL
38
+
39
+ ## [v0.11.0] - 2017-02-26
40
+
41
+ ### Added
42
+ * Add Console for reading input characters on Unix systems
43
+ * Add WinConsole for reading input characters on Windows systems
44
+ * Add WindowsApi to allow for calls to external Windows api
45
+ * Add echo support to multilist by Keith Keith T. Garner(@ktgeek)
46
+
47
+ ### Changed
48
+ * Change Reader to use Console for input reading
49
+ * Change Codes to use codepoints instead of strings
50
+ * Change Reader#read_line to match #gets behaviour
51
+ * Change Symbols to provide Unicode support on windows
52
+ * Change Slider to display Unicode when possible
53
+ * Change ConverterRegistry to be immutable
54
+ * Change Reader to expose #trigger in place of #publish for events firing
55
+
56
+ ### Fixed
57
+ * Fix `modify` throwing exception, when user enters empty input by Igor Rzegocki(@ajgon)
58
+ * Fix #clear_line behaviour by using tty-cursor 0.4.0 to work in all terminals
59
+ * Fix paging issue for lists shorter than :per_page value repeating title
60
+ * Fix #mask prompt to correctly match input on Windows
61
+ * Fix @mask to use default error messages
62
+ * Fix #select & #multi_select prompts to allow changing options with arrow keys on Windows
63
+ * Fix #echo to work correctly in zsh shell by štef(@d4be4st)
64
+ * Fix Slider#keyright event accepting max value outside of range
65
+ * Fix 2.4.0 conversion errors by using necromancer 0.4.0
66
+ * Fix #enum_select preventing selection of first item
67
+
68
+ ## [v0.10.1] - 2017-02-06
69
+
70
+ ### Fixed
71
+ * Fix File namespacing
72
+
73
+ ## [v0.10.0] - 2017-01-01
74
+
75
+ ### Added
76
+ * Add :enable_color option for toggling colors support
77
+
78
+ ### Changed
79
+ * Update pastel dependency version
80
+
81
+ ## [v0.9.0] - 2016-12-20
82
+
83
+ ### Added
84
+ * Add ability to paginate choices list for #select, #multi_select & #enum_select
85
+ with :per_page, :page_info and :default options
86
+ * Add ability to switch through options in #select & #multi_select using the tab key
87
+
88
+ ### Fixed
89
+ * Fix readers to accept multibyte characters reported by Jaehyun Shin(@keepcosmos)
90
+
91
+ ## [v0.8.0] - 2016-11-29
92
+
93
+ ### Added
94
+ * Add ability to publish custom key events for VIM keybindings customisations etc...
95
+
96
+ ### Fixed
97
+ * Fix Reader#read_char to use Ruby internal buffers instead of direct system call by @kke(Kimmo Lehto)
98
+ * Fix issue with #ask required & validate checks to take into account required when validating values
99
+ * Fix bug with #read_keypress to handle function keys and meta navigation keys
100
+ * Fix issue with default messages not displaying for `range`, `required` and `validate`
101
+
102
+ ## [v0.7.1] - 2016-08-07
103
+
104
+ ### Fixed
105
+ * Fix Reader::Mode to include standard io library
106
+
107
+ ## [v0.7.0] - 2016-07-17
108
+
109
+ ### Added
110
+ * Add :interrupt_handler option to customise keyboard interrupt behaviour
111
+
112
+ ### Changed
113
+ * Remove tty-platform dependency
114
+
115
+ ### Fixed
116
+ * Fix Reader#read_keypress issue when handling interrupt signal by Ondrej Moravcik(@ondra-m)
117
+ * Fix raw & echo modes to use standard library support by Kim Burgestrand(@Burgestrand)
118
+
119
+ ## [v0.6.0] - 2016-05-21
120
+
121
+ ### Changed
122
+ * Upgrade tty-cursor dependency
123
+
124
+ ### Fixed
125
+ * Fix issue with reader trapping signals by @kylekyle
126
+ * Fix expand to use new prev_line implementation
127
+
128
+ ## [v0.5.0] - 2016-03-28
129
+
130
+ ### Added
131
+ * Add ConfirmQuestion for #yes? & #no? calls
132
+ * Add ability to collect more than one answer through #collect call
133
+ * Add Choices#find_by for selecting choice based on attribute
134
+ * Add Prompt#expand for expanding key options
135
+ * Add :active_color, :help_color, :prefix options for customizing prompts display
136
+
137
+ ### Changed
138
+ * Change Choice#from to allow for coersion of complex objects with keys
139
+ * Change Choices#pluck to search through object attributes
140
+ * Change #select :enum option help text to display actual numbers range
141
+
142
+ ### Fixed
143
+ * Fix #no? to correctly ask negative question by @ondra-m
144
+ * Fix #ask :default option to handle nil or empty string
145
+ * Fix #multi_select :default option and color changing
146
+
147
+ ## [v0.4.0] - 2016-02-08
148
+
149
+ ### Added
150
+ * Add :enum option for #select & #multi_select to allow for numerical selection by @rtoshiro
151
+ * Add new key event types to KeyEvent
152
+ * Add #slider for picking values from range of numbers
153
+ * Add #enum_select for selecting option from enumerated list
154
+ * Add ability to configure error messages for #ask call
155
+ * Add new ConversionError type
156
+
157
+ ### Changed
158
+ * Move #blank? to Utils
159
+ * Update pastel dependency
160
+
161
+ ## [v0.3.0] - 2015-12-28
162
+
163
+ ### Added
164
+ * Add prefix option to prompt to customize #ask, #select, #multi_select
165
+ * Add default printing to #ask
166
+ * Add #yes?/#no? boolean queries
167
+ * Add Evaluator and Result for validation checking to Question
168
+ * Add ability for #ask to display error messages on failed validation
169
+ * Add ability to specify in-built names for validation e.i. :email
170
+ * Add KeyEvent for keyboard events publishing to Reader
171
+ * Add #read_multiline to Reader
172
+ * Add :convert option for ask configuration
173
+ * Add ability to specify custom proc converters
174
+ * Add #ask_keypress to gather character input
175
+ * Add #ask_multiline to gather multiline input
176
+ * Add MaskedQuestion & #mask method for masking input stream characters
177
+
178
+ ### Changed
179
+ * Change Reader#read_keypress to be robust and read correctly byte sequences
180
+ * Change Reader#getc to #read_line and extend arguments with echo option
181
+ * Extract cursor movement to dependency tty-cursor
182
+ * Change List & MultiList to subscribe to keyboard events
183
+ * Change to move mode inside reader namespace
184
+ * Remove Response & Error objects
185
+ * Remove :char option from #ask
186
+ * Change :read option to specify mode of reading out of :line, :multiline, :keypress
187
+ * Rename #confirm to #ok
188
+
189
+ ## [v0.2.0] - 2015-11-23
190
+
191
+ ### Added
192
+ * Add ability to select choice form list #select
193
+ * Add ability to select multiple options #multi_select
194
+ * Add :read option to #ask for reading specific type input
195
+
196
+ ### Changed
197
+ * Change #ask api to be similar to #select and #multi_select behaviour
198
+ * Change #ask :argument option to be :required
199
+ * Remove :valid option from #ask as #select is a better solution
200
+
201
+ ## [v0.1.0] - 2015-11-01
202
+
203
+ * Initial implementation and release
204
+
205
+ [v0.12.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.11.0...v0.12.0
206
+ [v0.11.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.10.1...v0.11.0
207
+ [v0.10.1]: https://github.com/piotrmurach/tty-prompt/compare/v0.10.0...v0.10.1
208
+ [v0.10.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.9.0...v0.10.0
209
+ [v0.9.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.8.0...v0.9.0
210
+ [v0.8.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.7.1...v0.8.0
211
+ [v0.7.1]: https://github.com/piotrmurach/tty-prompt/compare/v0.7.0...v0.7.1
212
+ [v0.7.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.6.0...v0.7.0
213
+ [v0.6.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.5.0...v0.6.0
214
+ [v0.5.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.4.0...v0.5.0
215
+ [v0.4.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.3.0...v0.4.0
216
+ [v0.3.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.2.0...v0.3.0
217
+ [v0.2.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.1.0...v0.2.0
218
+ [v0.1.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.1.0
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at [email]. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'benchmark-ips', '~> 2.0.0'
7
+ gem 'simplecov', '~> 0.10.0'
8
+ gem 'coveralls', '~> 0.8.2'
9
+ gem 'term-ansicolor', '=1.3.2'
10
+ end
11
+
12
+ group :tools do
13
+ gem 'byebug', platform: :mri
14
+ end
15
+
16
+ group :metrics do
17
+ gem 'yard', '~> 0.8.7'
18
+ gem 'yardstick', '~> 0.9.9'
19
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Piotr Murach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,1132 @@
1
+ # TTY::Prompt [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]
2
+ [![Gem Version](https://badge.fury.io/rb/tty-prompt.svg)][gem]
3
+ [![Build Status](https://secure.travis-ci.org/piotrmurach/tty-prompt.svg?branch=master)][travis]
4
+ [![Build status](https://ci.appveyor.com/api/projects/status/4cguoiah5dprbq7n?svg=true)][appveyor]
5
+ [![Code Climate](https://codeclimate.com/github/piotrmurach/tty-prompt/badges/gpa.svg)][codeclimate]
6
+ [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/tty-prompt/badge.svg)][coverage]
7
+ [![Inline docs](http://inch-ci.org/github/piotrmurach/tty-prompt.svg?branch=master)][inchpages]
8
+
9
+ [gitter]: https://gitter.im/piotrmurach/tty
10
+ [gem]: http://badge.fury.io/rb/tty-prompt
11
+ [travis]: http://travis-ci.org/piotrmurach/tty-prompt
12
+ [appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-prompt
13
+ [codeclimate]: https://codeclimate.com/github/piotrmurach/tty-prompt
14
+ [coverage]: https://coveralls.io/github/piotrmurach/tty-prompt
15
+ [inchpages]: http://inch-ci.org/github/piotrmurach/tty-prompt
16
+
17
+ > A beautiful and powerful interactive command line prompt.
18
+
19
+ **TTY::Prompt** provides independent prompt component for [TTY](https://github.com/piotrmurach/tty) toolkit.
20
+
21
+ ## Features
22
+
23
+ * Number of prompt types for gathering user input
24
+ * A robust API for validating complex inputs
25
+ * User friendly error feedback
26
+ * Intuitive DSL for creating complex menus
27
+ * Ability to page long menus
28
+
29
+ ## Installation
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ ```ruby
34
+ gem 'tty-prompt'
35
+ ```
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install tty-prompt
44
+
45
+ ## Contents
46
+
47
+ * [1. Usage](#1-usage)
48
+ * [2. Interface](#2-interface)
49
+ * [2.1 ask](#21-ask)
50
+ * [2.1.1 convert](#211-convert)
51
+ * [2.1.2 default](#212-default)
52
+ * [2.1.3 echo](#213-echo)
53
+ * [2.1.4 error messages](#214-error-messages)
54
+ * [2.1.5 in](#215-in)
55
+ * [2.1.6 modify](#216-modify)
56
+ * [2.1.7 required](#217-required)
57
+ * [2.1.8 validate](#218-validate)
58
+ * [2.2 keypress](#22-keypress)
59
+ * [2.2.1 timeout](#221-timeout)
60
+ * [2.3 multiline](#23-multiline)
61
+ * [2.4 mask](#24-mask)
62
+ * [2.5 yes?/no?](#25-yesno)
63
+ * [2.6 menu](#26-menu)
64
+ * [2.6.1 select](#261-select)
65
+ * [2.6.2 multi_select](#262-multi_select)
66
+ * [2.6.2.1 echo](#2621-echo)
67
+ * [2.6.3 enum_select](#263-enum_select)
68
+ * [2.7 expand](#27-expand)
69
+ * [2.8 collect](#28-collect)
70
+ * [2.9 suggest](#29-suggest)
71
+ * [2.10 slider](#210-slider)
72
+ * [2.11 say](#211-say)
73
+ * [2.11.1 ok](#2111-ok)
74
+ * [2.11.2 warn](#2112-warn)
75
+ * [2.11.3 error](#2113-error)
76
+ * [2.12 keyboard events](#212-keyboard-events)
77
+ * [3. settings](#3-settings)
78
+ * [3.1 active_color](#31-active_color)
79
+ * [3.2 enable_color](#32-enable-color)
80
+ * [3.3 help_color](#33-help_color)
81
+ * [3.4 interrupt](#34-interrupt)
82
+ * [3.5 prefix](#35-prefix)
83
+ * [3.6 trakc_history](#36-track_history)
84
+
85
+ ## 1. Usage
86
+
87
+ In order to start asking questions on the command line, create prompt:
88
+
89
+ ```ruby
90
+ prompt = TTY::Prompt.new
91
+ ```
92
+
93
+ and then call `ask` with the question for simple input:
94
+
95
+ ```ruby
96
+ prompt.ask('What is your name?', default: ENV['USER'])
97
+ # => What is your name? (piotr)
98
+ ```
99
+
100
+ To confirm input use `yes?`:
101
+
102
+ ```ruby
103
+ prompt.yes?('Do you like Ruby?')
104
+ # => Do you like Ruby? (Y/n)
105
+ ```
106
+
107
+ If you want to input password or secret information use `mask`:
108
+
109
+ ```ruby
110
+ prompt.mask("What is your secret?")
111
+ # => What is your secret? ••••
112
+ ```
113
+
114
+ Asking question with list of options couldn't be easier using `select` like so:
115
+
116
+ ```ruby
117
+ prompt.select("Choose your destiny?", %w(Scorpion Kano Jax))
118
+ # =>
119
+ # Choose your destiny? (Use arrow keys, press Enter to select)
120
+ # ‣ Scorpion
121
+ # Kano
122
+ # Jax
123
+ ```
124
+
125
+ Also, asking multiple choice questions is a breeze with `multi_select`:
126
+
127
+ ```ruby
128
+ choices = %w(vodka beer wine whisky bourbon)
129
+ prompt.multi_select("Select drinks?", choices)
130
+ # =>
131
+ #
132
+ # Select drinks? (Use arrow keys, press Space to select and Enter to finish)"
133
+ # ‣ ⬡ vodka
134
+ # ⬡ beer
135
+ # ⬡ wine
136
+ # ⬡ whisky
137
+ # ⬡ bourbon
138
+ ```
139
+
140
+ To ask for a selection from enumerated list you can use `enum_select`:
141
+
142
+ ```ruby
143
+ choices = %w(emacs nano vim)
144
+ prompt.enum_select("Select an editor?", choices)
145
+ # =>
146
+ #
147
+ # Select an editor?
148
+ # 1) emacs
149
+ # 2) nano
150
+ # 3) vim
151
+ # Choose 1-3 [1]:
152
+ ```
153
+
154
+ However, if you have a lot of options to choose from you may want to use `expand`:
155
+
156
+ ```ruby
157
+ choices = [
158
+ { key: 'y', name: 'overwrite this file', value: :yes },
159
+ { key: 'n', name: 'do not overwrite this file', value: :no },
160
+ { key: 'a', name: 'overwrite this file and all later files', value: :all },
161
+ { key: 'd', name: 'show diff', value: :diff },
162
+ { key: 'q', name: 'quit; do not overwrite this file ', value: :quit }
163
+ ]
164
+ prompt.expand('Overwrite Gemfile?', choices)
165
+ # =>
166
+ # Overwrite Gemfile? (enter "h" for help) [y,n,a,d,q,h]
167
+ ```
168
+
169
+ If you wish to collect more than one answer use `collect`:
170
+
171
+ ```ruby
172
+ result = prompt.collect do
173
+ key(:name).ask('Name?')
174
+
175
+ key(:age).ask('Age?', convert: :int)
176
+
177
+ key(:address) do
178
+ key(:street).ask('Street?', required: true)
179
+ key(:city).ask('City?')
180
+ key(:zip).ask('Zip?', validate: /\A\d{3}\Z/)
181
+ end
182
+ end
183
+ # =>
184
+ # {:name => "Piotr", :age => 30, :address => {:street => "Street", :city => "City", :zip => "123"}}
185
+ ```
186
+
187
+ ## 2. Interface
188
+
189
+ ### 2.1 ask
190
+
191
+ In order to ask a basic question do:
192
+
193
+ ```ruby
194
+ prompt.ask("What is your name?")
195
+ ```
196
+
197
+ However, to prompt for more complex input you can use robust API by passing hash of properties or using a block like so:
198
+
199
+ ```ruby
200
+ prompt.ask("What is your name?") do |q|
201
+ q.required true
202
+ q.validate /\A\w+\Z/
203
+ q.modify :capitalize
204
+ end
205
+ ```
206
+
207
+ #### 2.1.1 convert
208
+
209
+ The `convert` property is used to convert input to a required type.
210
+
211
+ By default no conversion is performed. The following conversions are provided:
212
+
213
+ ```ruby
214
+ :bool # true or false for strings such as "Yes", "No"
215
+ :date # date type
216
+ :datetime # datetime type
217
+ :file # File object
218
+ :float # decimal or error if cannot convert
219
+ :int # integer or error if cannot convert
220
+ :path # Pathname object
221
+ :range # range type
222
+ :regexp # regex expression
223
+ :string # string
224
+ :symbol # symbol
225
+ ```
226
+
227
+ For example, if you are interested in range type as answer do the following:
228
+
229
+ ```ruby
230
+ prompt.ask("Provide range of numbers?", convert: :range)
231
+ # Provide range of numbers? 1-10
232
+ # => 1..10
233
+ ```
234
+
235
+ You can also provide a custom conversion like so:
236
+
237
+ ```ruby
238
+ prompt.ask('Ingredients? (comma sep list)') do |q|
239
+ q.convert -> (input) { input.split(/,\s*/) }
240
+ end
241
+ # Ingredients? (comma sep list) milk, eggs, flour
242
+ # => ['milk', 'eggs', 'flour']
243
+ ```
244
+
245
+ #### 2.1.2 default
246
+
247
+ The `:default` option is used if the user presses return key:
248
+
249
+ ```ruby
250
+ prompt.ask('What is your name?', default: 'Anonymous')
251
+ # =>
252
+ # What is your name? (Anonymous)
253
+ ```
254
+
255
+ #### 2.1.3 echo
256
+
257
+ To control whether the input is shown back in terminal or not use `:echo` option like so:
258
+
259
+ ```ruby
260
+ prompt.ask('password:', echo: false)
261
+ ```
262
+
263
+ #### 2.1.4 error messages
264
+
265
+ By default `tty-prompt` comes with predefined error messages for `required`, `in`, `validate` options.
266
+
267
+ You can change these and configure to your liking either by inling them with the option:
268
+
269
+ ```ruby
270
+ prompt.ask('What is your email?') do |q|
271
+ q.validate(/\A\w+@\w+\.\w+\Z/, 'Invalid email address')
272
+ end
273
+ ```
274
+
275
+ or change the `messages` key entry out of `:required?`, `:valid?`, `:range?`:
276
+
277
+ ```ruby
278
+ prompt.ask('What is your email?') do |q|
279
+ q.validate(/\A\w+@\w+\.\w+\Z/)
280
+ q.messages[:valid?] = 'Invalid email address'
281
+ end
282
+ ```
283
+
284
+ to change default range validation error message do:
285
+
286
+ ```ruby
287
+ prompt.ask('How spicy on scale (1-5)? ') do |q|
288
+ q.in '1-5'
289
+ q.messages[:range?] = '%{value} out of expected range #{in}'
290
+ end
291
+ ```
292
+
293
+ #### 2.1.5 in
294
+
295
+ In order to check that provided input falls inside a range of inputs use the `in` option. For example, if we wanted to ask a user for a single digit in given range we may do following:
296
+
297
+ ```ruby
298
+ ask("Provide number in range: 0-9?") { |q| q.in('0-9') }
299
+ ```
300
+
301
+ #### 2.1.6 modify
302
+
303
+ Set the `:modify` option if you want to handle whitespace or letter capitalization.
304
+
305
+ ```ruby
306
+ prompt.ask('Enter text:') do |q|
307
+ q.modify :strip, :collapse
308
+ end
309
+ ```
310
+
311
+ Available letter casing settings are:
312
+ ```ruby
313
+ :up # change to upper case
314
+ :down # change to small case
315
+ :capitalize # capitalize each word
316
+ ```
317
+
318
+ Available whitespace settings are:
319
+ ```ruby
320
+ :trim # remove whitespace from both ends of the input
321
+ :chomp # remove whitespace at the end of input
322
+ :collapse # reduce all whitespace to single character
323
+ :remove # remove all whitespace
324
+ ```
325
+
326
+ #### 2.1.7 required
327
+
328
+ To ensure that input is provided use `:required` option:
329
+
330
+ ```ruby
331
+ prompt.ask("What's your phone number?", required: true)
332
+ # What's your phone number?
333
+ # >> Value must be provided
334
+ ```
335
+
336
+ #### 2.1.8 validate
337
+
338
+ In order to validate that input matches a given patter you can pass the `validate` option. Validate setting accepts `Regex`, `Proc` or `Symbol`.
339
+
340
+ ```ruby
341
+ prompt.ask('What is your username?') do |q|
342
+ q.validate /^[^\.]+\.[^\.]+/
343
+ end
344
+ ```
345
+
346
+ The **TTY::Prompt** comes with bult-in validations for `:email` and you can use them directly like so:
347
+
348
+ ```prompt
349
+ prompt.ask('What is your email?') { |q| q.validate :email }
350
+ ```
351
+
352
+ ### 2.2. keypress
353
+
354
+ In order to ask question that awaits a single character answer use `keypress` prompt like so:
355
+
356
+ ```ruby
357
+ prompt.keypress("Press key ?")
358
+ # Press key?
359
+ # => a
360
+ ```
361
+
362
+ By default any key is accepted but you can limit keys by using `:keys` option. Any key event names such as `:space` or `:ctrl_k` are valid:
363
+
364
+ ```ruby
365
+ prompt.keypress("Press space or enter to continue, keys: [:space, :return])
366
+ ```
367
+
368
+ #### 2.2.1 timeout
369
+
370
+ Timeout can be set using `:timeout` option to expire prompt and allow the script to continue automatically:
371
+
372
+ ```ruby
373
+ prompt.keypress("Press any key to continue, resumes automatically in 3 seconds ...", timeout: 3)
374
+ ```
375
+
376
+ In addition the `keypress` recognises `:countdown` token when inserted inside the question. It will automatically countdown the time in seconds:
377
+
378
+ ```ruby
379
+ prompt.keypress("Press any key to continue, resumes automatically in :countdown ...", timeout: 3)
380
+ ```
381
+
382
+ ### 2.3 multiline
383
+
384
+ Asking for multiline input can be done with `multiline` method. The reading of input will terminate when `Ctrl+d` or `Ctrl+z` is pressed. Empty lines will not be included in the returned array.
385
+
386
+ ```ruby
387
+ prompt.multiline("Description?")
388
+ # Description? (Press CTRL-D or CTRL-Z to finish)
389
+ # I know not all that may be coming,
390
+ # but be it what it will,
391
+ # I'll go to it laughing.
392
+ # => ["I know not all that may be coming,\n", "but be it what it will,\n", "I'll go to it laughing.\n"]
393
+ ```
394
+
395
+ The `multiline` uses similar options to those supported by `ask` prompt. For example, to provide default description:
396
+
397
+ ```ruby
398
+ prompt.multiline("Description?", default: 'A super sweet prompt.')
399
+ ```
400
+
401
+ or using DSL:
402
+
403
+ ```ruby
404
+ prompt.multiline("Description?") do |q|
405
+ q.default 'A super sweet prompt.'
406
+ q.help 'Press thy ctrl+d to end'
407
+ end
408
+ ```
409
+
410
+ ### 2.4 mask
411
+
412
+ If you require input of confidential information use `mask` method. By default each character that is printed is replaced by `•` symbol. All configuration options applicable to `ask` method can be used with `mask` as well.
413
+
414
+ ```ruby
415
+ prompt.mask('What is your secret?')
416
+ # => What is your secret? ••••
417
+ ```
418
+
419
+ The masking character can be changed by passing `:mask` option:
420
+
421
+ ```ruby
422
+ heart = prompt.decorate('❤ ', :magenta)
423
+ prompt.mask('What is your secret?', mask: heart)
424
+ # => What is your secret? ❤ ❤ ❤ ❤ ❤
425
+ ```
426
+
427
+ If you don't wish to show any output use `:echo` option like so:
428
+
429
+ ```ruby
430
+ prompt.mask('What is your secret?', echo: false)
431
+ ```
432
+
433
+ You can also provide validation for your mask to enforce for instance strong passwords:
434
+
435
+ ```ruby
436
+ prompt.mask('What is your secret?', mask: heart) do |q|
437
+ q.validate(/[a-z\ ]{5,15}/)
438
+ end
439
+ ```
440
+
441
+ ### 2.5 yes?/no?
442
+
443
+ In order to display a query asking for boolean input from user use `yes?` like so:
444
+
445
+ ```ruby
446
+ prompt.yes?('Do you like Ruby?')
447
+ # =>
448
+ # Do you like Ruby? (Y/n)
449
+ ```
450
+
451
+ You can further customize question by passing `suffix`, `positive`, `negative` and `convert` options. The `suffix` changes text of available options, the `positive` specifies display string for successful answer and `negative` changes display string for negative answer. The final value is a boolean provided the `convert` option evaluates to boolean.
452
+
453
+ It's enough to provide the `suffix` option for the prompt to accept matching answers with correct labels:
454
+
455
+ ```ruby
456
+ prompt.yes?("Are you a human?") do |q|
457
+ q.suffix 'Yup/nope'
458
+ end
459
+ # =>
460
+ # Are you a human? (Yup/nope)
461
+ ```
462
+
463
+ Alternatively, instead of `suffix` option provide the `positive` and `negative` labels:
464
+
465
+ ```ruby
466
+ prompt.yes?("Are you a human?") do |q|
467
+ q.default false
468
+ q.positive 'Yup'
469
+ q.negative 'Nope'
470
+ end
471
+ # =>
472
+ # Are you a human? (yup/Nope)
473
+ ```
474
+
475
+ Finally, providing all available options you can ask fully customized question:
476
+
477
+ ```ruby
478
+ prompt.yes?('Are you a human?') do |q|
479
+ q.suffix 'Agree/Disagree'
480
+ q.positive 'Agree'
481
+ q.negative 'Disagree'
482
+ q.convert -> (input) { !input.match(/^agree$/i).nil? }
483
+ end
484
+ # =>
485
+ # Are you a human? (Agree/Disagree)
486
+ ```
487
+
488
+ There is also the opposite for asking confirmation of negative question:
489
+
490
+ ```ruby
491
+ prompt.no?('Do you hate Ruby?')
492
+ # =>
493
+ # Do you hate Ruby? (y/N)
494
+ ```
495
+
496
+ Similarly to `yes?` method, you can supply the same options to customize the question.
497
+
498
+ ### 2.6 menu
499
+
500
+ ### 2.6.1 select
501
+
502
+ For asking questions involving list of options use `select` method by passing the question and possible choices:
503
+
504
+ ```ruby
505
+ prompt.select("Choose your destiny?", %w(Scorpion Kano Jax))
506
+ # =>
507
+ # Choose your destiny? (Use arrow keys, press Enter to select)
508
+ # ‣ Scorpion
509
+ # Kano
510
+ # Jax
511
+ ```
512
+
513
+ You can also provide options through DSL using the `choice` method for single entry and/or `choices` for more than one choice:
514
+
515
+ ```ruby
516
+ prompt.select("Choose your destiny?") do |menu|
517
+ menu.choice 'Scorpion'
518
+ menu.choice 'Kano'
519
+ menu.choice 'Jax'
520
+ end
521
+ # =>
522
+ # Choose your destiny? (Use arrow keys, press Enter to select)
523
+ # ‣ Scorpion
524
+ # Kano
525
+ # Jax
526
+ ```
527
+
528
+ By default the choice name is used as return value, but you can provide your custom values including a `Proc` object:
529
+
530
+ ```ruby
531
+ prompt.select("Choose your destiny?") do |menu|
532
+ menu.choice 'Scorpion', 1
533
+ menu.choice 'Kano', 2
534
+ menu.choice 'Jax', -> { 'Nice choice captain!' }
535
+ end
536
+ # =>
537
+ # Choose your destiny? (Use arrow keys, press Enter to select)
538
+ # ‣ Scorpion
539
+ # Kano
540
+ # Jax
541
+ ```
542
+
543
+ If you wish you can also provide a simple hash to denote choice name and its value like so:
544
+
545
+ ```ruby
546
+ choices = {'Scorpion' => 1, 'Kano' => 2, 'Jax' => 3}
547
+ prompt.select("Choose your destiny?", choices)
548
+ ```
549
+
550
+ To mark particular answer as selected use `default` with index of the option starting from `1`:
551
+
552
+ ```ruby
553
+ prompt.select("Choose your destiny?") do |menu|
554
+ menu.default 3
555
+
556
+ menu.choice 'Scorpion', 1
557
+ menu.choice 'Kano', 2
558
+ menu.choice 'Jax', 3
559
+ end
560
+ # =>
561
+ # Choose your destiny? (Use arrow keys, press Enter to select)
562
+ # Scorpion
563
+ # Kano
564
+ # ‣ Jax
565
+ ```
566
+
567
+ For ordered choices set `enum` to any delimiter String. In that way, you can use arrows keys and numbers (0-9) to select the item.
568
+
569
+ ```ruby
570
+ prompt.select("Choose your destiny?") do |menu|
571
+ menu.enum '.'
572
+
573
+ menu.choice 'Scorpion', 1
574
+ menu.choice 'Kano', 2
575
+ menu.choice 'Jax', 3
576
+ end
577
+ # =>
578
+ # Choose your destiny? (Use arrow or number (0-9) keys, press Enter to select)
579
+ # 1. Scorpion
580
+ # 2. Kano
581
+ # ‣ 3. Jax
582
+ ```
583
+
584
+ You can configure help message and/or marker like so
585
+
586
+ ```ruby
587
+ choices = %w(Scorpion Kano Jax)
588
+ prompt.select("Choose your destiny?", choices, help: "(Bash keyboard)", marker: '>')
589
+ # =>
590
+ # Choose your destiny? (Bash keyboard)
591
+ # > Scorpion
592
+ # Kano
593
+ # Jax
594
+ ```
595
+
596
+ By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
597
+
598
+ ```ruby
599
+ letters = ('A'..'Z').to_a
600
+ prompt.select("Choose your letter?", letters, per_page: 4)
601
+ # =>
602
+ # Which letter? (Use arrow keys, press Enter to select)
603
+ # ‣ A
604
+ # B
605
+ # C
606
+ # D
607
+ # (Move up or down to reveal more choices)
608
+ ```
609
+
610
+ You can also customise page navigation text using `:page_help` option:
611
+ ```ruby
612
+ letters = ('A'..'Z').to_a
613
+ prompt.select("Choose your letter?") do |menu|
614
+ menu.per_page 4
615
+ menu.page_help '(Wiggle thy finger up or down to see more)'
616
+ menu.choices letters
617
+ end
618
+ ```
619
+
620
+ ### 2.6.2 multi_select
621
+
622
+ For asking questions involving multiple selection list use `multi_select` method by passing the question and possible choices:
623
+
624
+ ```ruby
625
+ choices = %w(vodka beer wine whisky bourbon)
626
+ prompt.multi_select("Select drinks?", choices)
627
+ # =>
628
+ #
629
+ # Select drinks? (Use arrow keys, press Space to select and Enter to finish)"
630
+ # ‣ ⬡ vodka
631
+ # ⬡ beer
632
+ # ⬡ wine
633
+ # ⬡ whisky
634
+ # ⬡ bourbon
635
+ ```
636
+
637
+ 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:
638
+
639
+ ```ruby
640
+ choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
641
+ prompt.multi_select("Select drinks?", choices)
642
+
643
+ # Provided that vodka and beer have been selected, the function will return
644
+ # => [1, 2]
645
+ ```
646
+
647
+ 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:
648
+
649
+ ```ruby
650
+ prompt.multi_select("Select drinks?") do |menu|
651
+ menu.choice :vodka, {score: 1}
652
+ menu.choice :beer, 2
653
+ menu.choice :wine, 3
654
+ menu.choices whisky: 4, bourbon: 5
655
+ end
656
+ ```
657
+
658
+ To mark choice(s) as selected use the `default` option with index(s) of the option(s) starting from `1`:
659
+
660
+ ```ruby
661
+ prompt.multi_select("Select drinks?") do |menu|
662
+ menu.default 2, 5
663
+
664
+ menu.choice :vodka, {score: 10}
665
+ menu.choice :beer, {score: 20}
666
+ menu.choice :wine, {score: 30}
667
+ menu.choice :whisky, {score: 40}
668
+ menu.choice :bourbon, {score: 50}
669
+ end
670
+ # =>
671
+ # Select drinks? beer, bourbon
672
+ # ⬡ vodka
673
+ # ⬢ beer
674
+ # ⬡ wine
675
+ # ⬡ whisky
676
+ # ‣ ⬢ bourbon
677
+ ```
678
+
679
+ Like `select`, for ordered choices set `enum` to any delimiter String. In that way, you can use arrows keys and numbers (0-9) to select the item.
680
+
681
+ ```ruby
682
+ prompt.multi_select("Select drinks?") do |menu|
683
+ menu.enum ')'
684
+
685
+ menu.choice :vodka, {score: 10}
686
+ menu.choice :beer, {score: 20}
687
+ menu.choice :wine, {score: 30}
688
+ menu.choice :whisky, {score: 40}
689
+ menu.choice :bourbon, {score: 50}
690
+ end
691
+ # =>
692
+ # Select drinks? beer, bourbon
693
+ # ⬡ 1) vodka
694
+ # ⬢ 2) beer
695
+ # ⬡ 3) wine
696
+ # ⬡ 4) whisky
697
+ # ‣ ⬢ 5) bourbon
698
+ ```
699
+
700
+ And when you press enter you will see the following selected:
701
+
702
+ ```ruby
703
+ # Select drinks? beer, bourbon
704
+ # => [{score: 20}, {score: 50}]
705
+ ```
706
+
707
+ You can configure help message and/or marker like so
708
+
709
+ ```ruby
710
+ choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
711
+ prompt.multi_select("Select drinks?", choices, help: 'Press beer can against keyboard')
712
+ # =>
713
+ # Select drinks? (Press beer can against keyboard)"
714
+ # ‣ ⬡ vodka
715
+ # ⬡ beer
716
+ # ⬡ wine
717
+ # ⬡ whisky
718
+ # ⬡ bourbon
719
+ ```
720
+
721
+ By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
722
+
723
+ ```ruby
724
+ letters = ('A'..'Z').to_a
725
+ prompt.multi_select("Choose your letter?", letters, per_page: 4)
726
+ # =>
727
+ # Which letter? (Use arrow keys, press Space to select and Enter to finish)
728
+ # ‣ ⬡ A
729
+ # ⬡ B
730
+ # ⬡ C
731
+ # ⬡ D
732
+ # (Move up or down to reveal more choices)
733
+ ```
734
+
735
+ ### 2.6.2.1 echo
736
+
737
+ To control whether the selected items are shown on the question
738
+ header use the :echo option:
739
+
740
+ ```ruby
741
+ choices = %w(vodka beer wine whisky bourbon)
742
+ prompt.multi_select("Select drinks?", choices, echo: false)
743
+ # =>
744
+ # Select drinks?
745
+ # ⬡ vodka
746
+ # ⬢ 2) beer
747
+ # ⬡ 3) wine
748
+ # ⬡ 4) whisky
749
+ # ‣ ⬢ 5) bourbon
750
+ ```
751
+
752
+ ### 2.6.3 enum_select
753
+
754
+ In order to ask for standard selection from indexed list you can use `enum_select` and pass question together with possible choices:
755
+
756
+ ```ruby
757
+ choices = %w(emacs nano vim)
758
+ prompt.enum_select("Select an editor?")
759
+ # =>
760
+ #
761
+ # Select an editor?
762
+ # 1) nano
763
+ # 2) vim
764
+ # 3) emacs
765
+ # Choose 1-3 [1]:
766
+ ```
767
+
768
+ Similar to `select` and `multi_select`, you can provide question options through DSL using `choice` method and/or `choices` like so:
769
+
770
+ ```ruby
771
+ choices = %w(nano vim emacs)
772
+ prompt.enum_select("Select an editor?") do |menu|
773
+ menu.choice :nano, '/bin/nano'
774
+ menu.choice :vim, '/usr/bin/vim'
775
+ menu.choice :emacs, '/usr/bin/emacs'
776
+ end
777
+ # =>
778
+ #
779
+ # Select an editor?
780
+ # 1) nano
781
+ # 2) vim
782
+ # 3) emacs
783
+ # Choose 1-3 [1]:
784
+ #
785
+ # Select an editor? /bin/nano
786
+ ```
787
+
788
+ You can change the indexed numbers by passing `enum` option and the default option by using `default` like so
789
+
790
+ ```ruby
791
+ choices = %w(nano vim emacs)
792
+ prompt.enum_select("Select an editor?") do |menu|
793
+ menu.default 2
794
+ menu.enum '.'
795
+
796
+ menu.choice :nano, '/bin/nano'
797
+ menu.choice :vim, '/usr/bin/vim'
798
+ menu.choice :emacs, '/usr/bin/emacs'
799
+ end
800
+ # =>
801
+ #
802
+ # Select an editor?
803
+ # 1. nano
804
+ # 2. vim
805
+ # 3. emacs
806
+ # Choose 1-3 [2]:
807
+ #
808
+ # Select an editor? /usr/bin/vim
809
+ ```
810
+
811
+ By default the menu is paginated if selection grows beyond `6` items. To change this setting use `:per_page` configuration.
812
+
813
+ ```ruby
814
+ letters = ('A'..'Z').to_a
815
+ prompt.enum_select("Choose your letter?", letters, per_page: 4)
816
+ # =>
817
+ # Which letter?
818
+ # 1) A
819
+ # 2) B
820
+ # 3) C
821
+ # 4) D
822
+ # Choose 1-26 [1]:
823
+ # (Press tab/right or left to reveal more choices)
824
+ ```
825
+
826
+ ### 2.7 expand
827
+
828
+ The `expand` provides a compact way to ask a question with many options.
829
+
830
+ As first argument `expand` takes the message to display and as a second an array of choices. Compared to the `select`, `multi_select` and `enum_select`, the choices need to be objects that include `:key`, `:name` and `:value` keys. The `:key` must be a single character. The help choice is added automatically as the last option and the key `h`.
831
+
832
+ ```ruby
833
+ choices = [
834
+ {
835
+ key: 'y',
836
+ name: 'overwrite this file',
837
+ value: :yes
838
+ }, {
839
+ key: 'n',
840
+ name: 'do not overwrite this file',
841
+ value: :no
842
+ }, {
843
+ key: 'q',
844
+ name: 'quit; do not overwrite this file ',
845
+ value: :quit
846
+ }
847
+ ]
848
+ ```
849
+
850
+ The choices can also be provided through DSL using the `choice` method. The `:value` can be a primitive value or `Proc` instance that gets executed and whose value is used as returned type. For example:
851
+
852
+ ```ruby
853
+ prompt.expand('Overwrite Gemfile?') do |q|
854
+ q.choice key: 'y', name: 'Overwrite' do :ok end
855
+ q.choice key: 'n', name: 'Skip', value: :no
856
+ q.choice key: 'a', name: 'Overwrite all', value: :all
857
+ q.choice key: 'd', name: 'Show diff', value: :diff
858
+ q.choice key: 'q', name: 'Quit', value: :quit
859
+ end
860
+ ```
861
+
862
+ The first element in the array of choices or provided via `choice` DSL will be the default choice, you can change that by passing `default` option.
863
+
864
+ ```ruby
865
+ prompt.expand('Overwrite Gemfile?', choices)
866
+ # =>
867
+ # Overwrite Gemfile? (enter "h" for help) [y,n,q,h]
868
+ ```
869
+
870
+ Each time user types an option a hint will be displayed:
871
+
872
+ ```ruby
873
+ # Overwrite Gemfile? (enter "h" for help) [y,n,a,d,q,h] y
874
+ # >> overwrite this file
875
+ ```
876
+
877
+ If user types `h` and presses enter, an expanded view will be shown which further allows to refine the choice:
878
+
879
+ ```ruby
880
+ # Overwrite Gemfile?
881
+ # y - overwrite this file
882
+ # n - do not overwrite this file
883
+ # q - quit; do not overwrite this file
884
+ # h - print help
885
+ # Choice [y]:
886
+ ```
887
+
888
+ Run `examples/expand.rb` to see the prompt in action.
889
+
890
+ ### 2.8 collect
891
+
892
+ In order to collect more than one answer use `collect` method. Using the `key` you can describe the answers key name. All the methods for asking user input such as `ask`, `mask`, `select` can be directly invoked on the key. The key composition is very flexible by allowing nested keys. If you want the value to be automatically converted to required type use [convert](#221-convert).
893
+
894
+ For example to gather some contact information do:
895
+
896
+ ```ruby
897
+ prompt.collect do
898
+ key(:name).ask('Name?')
899
+
900
+ key(:age).ask('Age?', convert: :int)
901
+
902
+ key(:address) do
903
+ key(:street).ask('Street?', required: true)
904
+ key(:city).ask('City?')
905
+ key(:zip).ask('Zip?', validate: /\A\d{3}\Z/)
906
+ end
907
+ end
908
+ # =>
909
+ # {:name => "Piotr", :age => 30, :address => {:street => "Street", :city => "City", :zip => "123"}}
910
+ ```
911
+
912
+ ### 2.9 suggest
913
+
914
+ To suggest possible matches for the user input use `suggest` method like so:
915
+
916
+ ```ruby
917
+ prompt.suggest('sta', ['stage', 'stash', 'commit', 'branch'])
918
+ # =>
919
+ # Did you mean one of these?
920
+ # stage
921
+ # stash
922
+ ```
923
+
924
+ To customize query text presented pass `:single_text` and `:plural_text` options to respectively change the message when one match is found or many.
925
+
926
+ ```ruby
927
+ possible = %w(status stage stash commit branch blame)
928
+ prompt.suggest('b', possible, indent: 4, single_text: 'Perhaps you meant?')
929
+ # =>
930
+ # Perhaps you meant?
931
+ # blame
932
+ ```
933
+
934
+ ### 2.10 slider
935
+
936
+ If you have constrained range of numbers for user to choose from you may consider using `slider`. The slider provides easy visual way of picking a value marked by `O` marker.
937
+
938
+ ```ruby
939
+ prompt.slider('What size?', min: 32, max: 54, step: 2)
940
+ # =>
941
+ #
942
+ # What size? (User arrow keys, press Enter to select)
943
+ # |------O-----| 44
944
+ ```
945
+
946
+ Slider can be configured through DSL as well:
947
+
948
+ ```ruby
949
+ prompt.slider('What size?') do |range|
950
+ range.default 4
951
+ range.min 0
952
+ range.max 20
953
+ range.step 2
954
+ end
955
+ # =>
956
+ #
957
+ # What size? (User arrow keys, press Enter to select)
958
+ # |--O-------| 4
959
+ ```
960
+
961
+ ### 2.11 say
962
+
963
+ To simply print message out to stdout use `say` like so:
964
+
965
+ ```ruby
966
+ prompt.say(...)
967
+ ```
968
+
969
+ The `say` method also accepts option `:color` which supports all the colors provided by [pastel](https://github.com/piotrmurach/pastel#3-supported-colors)
970
+
971
+ **TTY::Prompt** provides more specific versions of `say` method to better express intenation behind the message such as `ok`, `warn` and `error`.
972
+
973
+ #### 2.11.1 ok
974
+
975
+ Print message(s) in green do:
976
+
977
+ ```ruby
978
+ prompt.ok(...)
979
+ ```
980
+
981
+ #### 2.12.2 warn
982
+
983
+ Print message(s) in yellow do:
984
+
985
+ ```ruby
986
+ prompt.warn(...)
987
+ ```
988
+
989
+ #### 2.11.3 error
990
+
991
+ Print message(s) in red do:
992
+
993
+ ```ruby
994
+ prompt.error(...)
995
+ ```
996
+
997
+ #### 2.12 keyboard events
998
+
999
+ All the prompt types, when a key is pressed, fire key press events. You can subscribe to listen to this events by calling `on` with type of event name.
1000
+
1001
+ ```ruby
1002
+ prompt.on(:keypress) { |event| ... }
1003
+ ```
1004
+
1005
+ The event object is yielded to a block whenever particular event fires. The event has `key` and `value` methods. Further, the `key` responds to following messages:
1006
+
1007
+ * `name` - the name of the event such as :up, :down, letter or digit
1008
+ * `meta` - true if event is non-standard key associated
1009
+ * `shift` - true if shift has been pressed with the key
1010
+ * `ctrl` - true if ctrl has been pressed with the key
1011
+
1012
+ For example, to add vim like key navigation to `select` prompt one would do the following:
1013
+
1014
+ ```ruby
1015
+ prompt.on(:keypress) do |event|
1016
+ if event.value == 'j'
1017
+ prompt.trigger(:keydown)
1018
+ end
1019
+
1020
+ if event.value == 'k'
1021
+ prompt.trigger(:keyup)
1022
+ end
1023
+ end
1024
+ ```
1025
+
1026
+ You can subscribe to more than one event:
1027
+
1028
+ ```ruby
1029
+ prompt.on(:keypress) { |key| ... }
1030
+ .on(:keydown) { |key| ... }
1031
+ ```
1032
+
1033
+ The available events are:
1034
+
1035
+ * `:keypress`
1036
+ * `:keydown`
1037
+ * `:keyup`
1038
+ * `:keyleft`
1039
+ * `:keyright`
1040
+ * `:keynum`
1041
+ * `:keytab`
1042
+ * `:keyenter`
1043
+ * `:keyreturn`
1044
+ * `:keyspace`
1045
+ * `:keyescape`
1046
+ * `:keydelete`
1047
+ * `:keybackspace`
1048
+
1049
+ ## 3 settings
1050
+
1051
+ ### 3.1 active_color
1052
+
1053
+ All prompt types support `:active_color` option. In case of `select`, `multi_select`, `enum_select` or `expand` this color is used to highlight the currently selected choice. All the resulted inputs provided by user that are read in by the prompt as answer are highlighted with this color. This option can be applied either globablly for all prompts or individually.
1054
+
1055
+ ```ruby
1056
+ prompt = TTY::Prompt.new(active_color: :cyan)
1057
+ ```
1058
+
1059
+ or per individual input do:
1060
+
1061
+ ```ruby
1062
+ prompt.select('What size?', %w(Large Medium Small), active_color: :cyan)
1063
+ ```
1064
+
1065
+ Please [see pastel](https://github.com/piotrmurach/pastel#3-supported-colors) for all supported colors.
1066
+
1067
+ ### 3.2 enable_color
1068
+
1069
+ If you wish to disable coloring for a prompt simply pass `:enable_color` option
1070
+
1071
+ ```
1072
+ prompt = TTY::Prompt.new(enable_color: true)
1073
+ ```
1074
+
1075
+ ### 3.3 help_color
1076
+
1077
+ Prompts such as `select`, `multi_select`, `expand` support `:help_color` which is used to customize the help text. This option can be applied either globablly for all prompts or individually.
1078
+
1079
+ ```ruby
1080
+ prompt = TTY::Prompt.new(help_color: :cyan)
1081
+ ```
1082
+
1083
+ or per individual input do:
1084
+
1085
+ ```ruby
1086
+ prompt.select('What size?', %w(Large Medium Small), help_color: :cyan)
1087
+ ```
1088
+
1089
+ ### 3.4 interrupt
1090
+
1091
+ By default `InputInterrupt` error will be raised when the user hits the interrupt key(Control-C). However, you can customise this behaviour by passing the `:interrupt` option. The available options are:
1092
+
1093
+ * `:signal` - sends interrupt signal
1094
+ * `:exit` - exists with status code
1095
+ * `:noop` - skips handler
1096
+ * custom proc
1097
+
1098
+ For example, to send interrupt signal do:
1099
+
1100
+ ```ruby
1101
+ prompt = TTY::Prompt.new(interrupt: :signal)
1102
+ ```
1103
+
1104
+ ### 3.5 prefix
1105
+
1106
+ You can prefix each question asked using the `:prefix` option. This option can be applied either globally for all prompts or individual for each one:
1107
+
1108
+ ```ruby
1109
+ prompt = TTY::Prompt.new(prefix: '[?] ')
1110
+ ```
1111
+
1112
+ ### 3.6 track_history
1113
+
1114
+ The prompts that accept line input such as `multiline` or `ask` provide history buffer that tracks all the lines entered during `TTY::Prompt.new` interactions. The history buffer provides previoius or next lines when user presses up/down arrows respectively. However, if you wish to disable this behaviour use `:track_history` option like so:
1115
+
1116
+ ```ruby
1117
+ prompt = TTY::Prompt.new(track_history: false)
1118
+ ```
1119
+
1120
+ ## Contributing
1121
+
1122
+ 1. Fork it ( https://github.com/piotrmurach/tty-prompt/fork )
1123
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
1124
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
1125
+ 4. Push to the branch (`git push origin my-new-feature`)
1126
+ 5. Create a new Pull Request
1127
+
1128
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
1129
+
1130
+ ## Copyright
1131
+
1132
+ Copyright (c) 2015-2017 Piotr Murach. See LICENSE for further details.