cli-ui 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 257914b1c561094bd1e2a466a251b8e44055d806
4
- data.tar.gz: 4a0e814e44663e4740090ecb556056e4f224e0fd
3
+ metadata.gz: 367667f90cce34fe2ac10fffbd13a24a8b7a90e3
4
+ data.tar.gz: fdc151c1343bc037c8f03c3308ec3646795e9dbd
5
5
  SHA512:
6
- metadata.gz: 8a887458aa8446824c92682f32eeb995a7d002a6a1b787b68694873c7e52706de368233415f13d85b399f72e36a7c4d7cb493950d4b2773c0b6dd159b2e500fb
7
- data.tar.gz: bd0dc80707861825a752de6c325f6faf8c2f404c174446d2fa760a4224a2b7e3894c493aa0f5859a5ac947b9ba871c9c8cf2e832c59b239b6bd124fda8bf5c32
6
+ metadata.gz: 51e249672f6214028aebf3ab31b2d90cde511da996118b50607522318528c57ae0bfe40edc4b447593fb5faf2712b964fdfafdc26e1b092ce96e8ee92366e759
7
+ data.tar.gz: 58e27c5790e1bb0f35581953467a8c5a38d7ca647f3cca7042e42d347c9708dc44e9007cb326fa563b241daaaaa480662de7dfdaa2ad5a3084ecf68dc4158cf6
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ Gemfile.lock
1
2
  *.gem
2
3
  build
3
4
  .vagrant
data/README.md CHANGED
@@ -49,6 +49,19 @@ Prompt user with options and ask them to choose. Can answer using arrow keys, nu
49
49
  CLI::UI.ask('What language/framework do you use?', options: %w(rails go ruby python))
50
50
  ```
51
51
 
52
+ Can also assign callbacks to each option
53
+
54
+ ```ruby
55
+ CLI::UI.ask('What language/framework do you use?') do |handler|
56
+ handler.option('rails') { |selection| selection }
57
+ handler.option('go') { |selection| selection }
58
+ handler.option('ruby') { |selection| selection }
59
+ handler.option('python') { |selection| selection }
60
+ end
61
+ ```
62
+
63
+ * Note that the two examples provided above are identical in functionality
64
+
52
65
  ![Interactive Prompt](https://user-images.githubusercontent.com/3074765/33797984-0ebb5e64-dcdf-11e7-9e7e-7204f279cece.gif)
53
66
 
54
67
  ---
data/lib/cli/ui/prompt.rb CHANGED
@@ -5,12 +5,13 @@ module CLI
5
5
  module UI
6
6
  module Prompt
7
7
  autoload :InteractiveOptions, 'cli/ui/prompt/interactive_options'
8
- private_constant :InteractiveOptions
8
+ autoload :OptionsHandler, 'cli/ui/prompt/options_handler'
9
+ private_constant :InteractiveOptions, :OptionsHandler
9
10
 
10
11
  class << self
11
- # Ask a user a question with either free form answer or a set of answers
12
+ # Ask a user a question with either free form answer or a set of answers (multiple choice)
13
+ # Can use arrows, y/n, numbers (1/2), and vim bindings to control multiple choice selection
12
14
  # Do not use this method for yes/no questions. Use +confirm+
13
- # Can use arrows, y/n, numbers, and vim bindings to control
14
15
  #
15
16
  # * Handles free form answers (options are nil)
16
17
  # * Handles default answers for free form text
@@ -25,14 +26,25 @@ module CLI
25
26
  #
26
27
  # ==== Options
27
28
  #
28
- # * +:options+ - Options to ask the user. Will use +InteractiveOptions+ to do so
29
+ # * +:options+ - Options that the user may select from. Will use +InteractiveOptions+ to do so.
29
30
  # * +:default+ - The default answer to the question (e.g. they just press enter and don't input anything)
30
31
  # * +:is_file+ - Tells the input to use file auto-completion (tab completion)
31
32
  # * +:allow_empty+ - Allows the answer to be empty
32
33
  #
33
34
  # Note:
34
- # * +:options+ conflicts with +:default+ and +:is_file+, you cannot set options with either of these keywords
35
+ # * +:options+ or providing a +Block+ conflicts with +:default+ and +:is_file+, you cannot set options with either of these keywords
35
36
  # * +:default+ conflicts with +:allow_empty:, you cannot set these together
37
+ # * +:options+ conflicts with providing a +Block+ , you may only set one
38
+ #
39
+ # ==== Block (optional)
40
+ #
41
+ # * A Proc that provides a +OptionsHandler+ and uses the public +:option+ method to add options and their
42
+ # respective handlers
43
+ #
44
+ # ==== Return Value
45
+ #
46
+ # * If a +Block+ was not provided, the selected option or response to the free form question will be returned
47
+ # * If a +Block+ was provided, the evaluted value of the +Block+ will be returned
36
48
  #
37
49
  # ==== Example Usage:
38
50
  #
@@ -48,35 +60,50 @@ module CLI
48
60
  # Free form question when the answer can be empty
49
61
  # CLI::UI::Prompt.ask('What is your opinion on this question?', allow_empty: true)
50
62
  #
51
- # Question with answers
63
+ # Interactive (multiple choice) question
52
64
  # CLI::UI::Prompt.ask('What kind of project is this?', options: %w(rails go ruby python))
53
65
  #
54
- #
55
- def ask(question, options: nil, default: nil, is_file: nil, allow_empty: true)
56
- if (default && !allow_empty) || (options && (default || is_file))
57
- raise(ArgumentError, 'conflicting arguments')
66
+ # Interactive (multiple choice) question with defined handlers
67
+ # CLI::UI::Prompt.ask('What kind of project is this?') do |handler|
68
+ # handler.option('rails') { |selection| selection }
69
+ # handler.option('go') { |selection| selection }
70
+ # handler.option('ruby') { |selection| selection }
71
+ # handler.option('python') { |selection| selection }
72
+ # end
73
+ #
74
+ def ask(question, options: nil, default: nil, is_file: nil, allow_empty: true, &options_proc)
75
+ if ((options || block_given?) && (default || is_file))
76
+ raise(ArgumentError, 'conflicting arguments: options provided with default or is_file')
58
77
  end
59
78
 
60
- if default
61
- puts_question("#{question} (empty = #{default})")
62
- elsif options
63
- puts_question("#{question} {{yellow:(choose with ↑ ↓ ⏎)}}")
79
+ if options || block_given?
80
+ ask_interactive(question, options, &options_proc)
64
81
  else
65
- puts_question(question)
82
+ ask_free_form(question, default, is_file, allow_empty)
66
83
  end
84
+ end
67
85
 
68
- # Present the user with options
69
- if options
70
- resp = InteractiveOptions.call(options)
86
+ # Asks the user a yes/no question.
87
+ # Can use arrows, y/n, numbers (1/2), and vim bindings to control
88
+ #
89
+ # ==== Example Usage:
90
+ #
91
+ # Confirmation question
92
+ # CLI::UI::Prompt.confirm('Is the sky blue?')
93
+ #
94
+ def confirm(question)
95
+ ask_interactive(question, %w(yes no)) == 'yes'
96
+ end
97
+
98
+ private
71
99
 
72
- # Clear the line, and reset the question to include the answer
73
- print(ANSI.previous_line + ANSI.end_of_line + ' ')
74
- print(ANSI.cursor_save)
75
- print(' ' * CLI::UI::Terminal.width)
76
- print(ANSI.cursor_restore)
77
- puts_question("#{question} (You chose: {{italic:#{resp}}})")
100
+ def ask_free_form(question, default, is_file, allow_empty)
101
+ raise(ArgumentError, 'conflicting arguments: default enabled but allow_empty is false') if (default && !allow_empty)
78
102
 
79
- return resp
103
+ if default
104
+ puts_question("#{question} (empty = #{default})")
105
+ else
106
+ puts_question(question)
80
107
  end
81
108
 
82
109
  # Ask a free form question
@@ -94,19 +121,34 @@ module CLI
94
121
  end
95
122
  end
96
123
 
97
- # Asks the user a yes/no question.
98
- # Can use arrows, y/n, numbers (1/2), and vim bindings to control
99
- #
100
- # ==== Example Usage:
101
- #
102
- # Confirmation question
103
- # CLI::UI::Prompt.confirm('Is the sky blue?')
104
- #
105
- def confirm(question)
106
- ask(question, options: %w(yes no)) == 'yes'
124
+ def ask_interactive(question, options = nil)
125
+ raise(ArgumentError, 'conflicting arguments: options and block given') if options && block_given?
126
+
127
+ options ||= if block_given?
128
+ handler = OptionsHandler.new
129
+ yield handler
130
+ handler.options
131
+ end
132
+
133
+ raise(ArgumentError, 'insufficient options') if options.nil? || options.size < 2
134
+ puts_question("#{question} {{yellow:(choose with ↑ ↓ ⏎)}}")
135
+ resp = interactive_prompt(options)
136
+
137
+ # Clear the line, and reset the question to include the answer
138
+ print(ANSI.previous_line + ANSI.end_of_line + ' ')
139
+ print(ANSI.cursor_save)
140
+ print(' ' * CLI::UI::Terminal.width)
141
+ print(ANSI.cursor_restore)
142
+ puts_question("#{question} (You chose: {{italic:#{resp}}})")
143
+
144
+ return handler.call(resp) if block_given?
145
+ resp
107
146
  end
108
147
 
109
- private
148
+ # Useful for stubbing in tests
149
+ def interactive_prompt(options)
150
+ InteractiveOptions.call(options)
151
+ end
110
152
 
111
153
  def write_default_over_empty_input(default)
112
154
  CLI::UI.raw do
@@ -0,0 +1,24 @@
1
+ module CLI
2
+ module UI
3
+ module Prompt
4
+ # A class that handles the various options of an InteractivePrompt and their callbacks
5
+ class OptionsHandler
6
+ def initialize
7
+ @options = {}
8
+ end
9
+
10
+ def options
11
+ @options.keys
12
+ end
13
+
14
+ def option(option, &handler)
15
+ @options[option] = handler
16
+ end
17
+
18
+ def call(option)
19
+ @options[option].call(option)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module CLI
2
2
  module UI
3
- VERSION = "1.0.0"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cli-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2017-12-15 00:00:00.000000000 Z
13
+ date: 2018-02-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -67,7 +67,6 @@ files:
67
67
  - ".rubocop.yml"
68
68
  - ".travis.yml"
69
69
  - Gemfile
70
- - Gemfile.lock
71
70
  - LICENSE.txt
72
71
  - README.md
73
72
  - Rakefile
@@ -84,6 +83,7 @@ files:
84
83
  - lib/cli/ui/progress.rb
85
84
  - lib/cli/ui/prompt.rb
86
85
  - lib/cli/ui/prompt/interactive_options.rb
86
+ - lib/cli/ui/prompt/options_handler.rb
87
87
  - lib/cli/ui/spinner.rb
88
88
  - lib/cli/ui/spinner/async.rb
89
89
  - lib/cli/ui/spinner/spin_group.rb
data/Gemfile.lock DELETED
@@ -1,54 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cli-ui (0.1.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ansi (1.5.0)
10
- ast (2.3.0)
11
- builder (3.2.3)
12
- byebug (9.0.6)
13
- metaclass (0.0.4)
14
- method_source (0.8.2)
15
- minitest (5.10.2)
16
- minitest-reporters (1.1.14)
17
- ansi
18
- builder
19
- minitest (>= 5.0)
20
- ruby-progressbar
21
- mocha (1.2.1)
22
- metaclass (~> 0.0.1)
23
- parallel (1.12.0)
24
- parser (2.4.0.2)
25
- ast (~> 2.3)
26
- powerpack (0.1.1)
27
- rainbow (3.0.0)
28
- rake (10.5.0)
29
- rubocop (0.52.0)
30
- parallel (~> 1.10)
31
- parser (>= 2.4.0.2, < 3.0)
32
- powerpack (~> 0.1)
33
- rainbow (>= 2.2.2, < 4.0)
34
- ruby-progressbar (~> 1.7)
35
- unicode-display_width (~> 1.0, >= 1.0.1)
36
- ruby-progressbar (1.9.0)
37
- unicode-display_width (1.3.0)
38
-
39
- PLATFORMS
40
- ruby
41
-
42
- DEPENDENCIES
43
- bundler (~> 1.15)
44
- byebug
45
- cli-ui!
46
- method_source
47
- minitest (>= 5.0.0)
48
- minitest-reporters
49
- mocha
50
- rake (~> 10.0)
51
- rubocop
52
-
53
- BUNDLED WITH
54
- 1.16.0