inquirer 0.1.2 → 0.2.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: 89669e4b2834eb47f0f7b2ba37267c25a47f9f79
4
- data.tar.gz: 057e9314a40673692bf52237a93277c31ceb00af
3
+ metadata.gz: 97119771a6f5d25b26a8c9e46d21833da7916364
4
+ data.tar.gz: 85d97425f2efb04f5a1cbd9b7029d0c1f41b1fe2
5
5
  SHA512:
6
- metadata.gz: 4f7a3fb070a89716e0a9ec572a88c94eff6341f1eb41c4d0555264645398834beb36734260eab862ea5cbeda291b03963bfa3bd100cd8aea86695ccbb33e234e
7
- data.tar.gz: 2d9ac726f146f2451cc207c3278046c8acdee9c9487883b5a714ad839e0b63db8febaab71d8e960b031dcf046af6abfcfd8a072e7cc0fea16a125cb1f64e58f5
6
+ metadata.gz: 8322479e68acb817daa91c465302a45e35ea2798386ba367f948ebd93dbd22ef7be33bf6410ff21e0fc82d5cd33d7b0e8ef07f57a54b49aed71859b6886ec3c0
7
+ data.tar.gz: 60ae3b63e8ebd9738b755d485294605c751979102026d0cd0e976c25a7989b2c41ee6c26ea0a1598891b0f2e743e3248286486c43a1be6875826fa502d16a276
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.2.0
2
+
3
+ * feature: add user input prompt with support for default values
4
+ * feature: add confirmation prompt with support for default values
5
+ * feature: render response for all prompts if desired
6
+ * improvement: hide the cursor in the list and checkbox prompts
7
+ * bugfix: fix the clear method not clearing every line on the way up
8
+
1
9
  ## 0.1.1
2
10
 
3
11
  * feature: add (and verify) rubinius 2.1 + 2.2 support
data/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  Interactive user prompts on CLI for ruby.
6
6
 
7
- ## Examples
7
+ ## Prompt types
8
+
9
+ ### List
8
10
 
9
11
  ```ruby
10
12
  idx = Ask.list "Look behind you...", [
@@ -17,6 +19,8 @@ idx = Ask.list "Look behind you...", [
17
19
 
18
20
  ![List example](example/list.png)
19
21
 
22
+ ### Checkbox
23
+
20
24
  ```ruby
21
25
  idx = Ask.checkbox "Monkey see, monkey...", [
22
26
  "don't",
@@ -28,6 +32,54 @@ idx = Ask.checkbox "Monkey see, monkey...", [
28
32
 
29
33
  ![Checkbox example](example/checkbox.png)
30
34
 
35
+ ### Input
36
+
37
+ Takes optional `default` property (`string`).
38
+
39
+ ```ruby
40
+ firstname = Ask.input "What's your name"
41
+ phone = Ask.input "What's your phone number", default: "123"
42
+ # name and phone are the responses for each question
43
+ ```
44
+
45
+ ![Input example](example/input.png)
46
+
47
+ ### Confirm
48
+
49
+ Takes optional `default` property (`true` or `false`). The default `default` value is true.
50
+
51
+ ```ruby
52
+ value = Ask.confirm "Are you sure?"
53
+ # value is a boolean
54
+
55
+ Ask.confirm "Are you sure?", default: false
56
+ # Default is false
57
+ ```
58
+
59
+ ![Input example](example/confirm.png)
60
+
61
+ ## Options
62
+
63
+ ### Method parameters
64
+
65
+ - question: `string` The text to your are going to ask
66
+ - elements: `array` Array of options to show. Only for `checkbox` and `list` types.
67
+
68
+ ### Rendering options
69
+
70
+ You can pass this options as the lastest parameter
71
+
72
+ - clear: `bool` [Default true] Clear the original question after pressing enter
73
+ - response: `bool` [Default true] Whether to show the selected response
74
+
75
+ ```ruby
76
+ # If you dont want any output use
77
+ Ask.input "What's your name", response: false
78
+
79
+ # If you don't want the response and you want to keep the question prompt
80
+ Ask.input "What's your name", clear: false, response: false
81
+ ```
82
+
31
83
  ## Installation
32
84
 
33
85
  gem install inquirer
@@ -42,6 +94,12 @@ idx = Ask.checkbox "Monkey see, monkey...", [
42
94
  | Rubinius 2.2.1 | ✔ | ✔ | ✘ |
43
95
  | JRuby 1.7.x | ✘ | ✘ | ✘ |
44
96
 
97
+ ## Contributors
98
+
99
+ **Thank you for contributing!**
100
+
101
+ * ![blackjid](https://avatars1.githubusercontent.com/u/228037?s=16) [blackjid](https://github.com/blackjid)
102
+
45
103
  ## Credit
46
104
 
47
105
  This is basically the wonderful [Inquirer.js](https://github.com/SBoudrias/Inquirer.js), just done for ruby. I was unable to find a good gem to handle user interaction in ruby as well as this module does in JS.
@@ -49,4 +107,4 @@ This is basically the wonderful [Inquirer.js](https://github.com/SBoudrias/Inqui
49
107
  ## License
50
108
 
51
109
  Apache v2
52
- Author: Dominik Richter
110
+ Author: Dominik Richter
data/example/checkbox.png CHANGED
Binary file
data/example/checkbox.rb CHANGED
@@ -4,4 +4,9 @@ idx = Ask.checkbox "Monkey see, monkey...", [
4
4
  "eats Banana",
5
5
  "do"
6
6
  ]
7
+ idx = Ask.checkbox "Monkey see, monkey...", [
8
+ "don't",
9
+ "eats Banana",
10
+ "do"
11
+ ]
7
12
  puts "you selected #{idx}"
Binary file
@@ -0,0 +1,5 @@
1
+ require_relative '../lib/inquirer'
2
+
3
+ value1 = Ask.confirm "Are you sure?"
4
+ value2 = Ask.confirm "Are you really sure?", default: false
5
+ puts "you chose #{value1} and #{value2}"
data/example/input.png ADDED
Binary file
data/example/input.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative '../lib/inquirer'
2
+
3
+ name = Ask.input "What's your name", default: "Monkey"
4
+ phone = Ask.input "What's your phone number"
5
+ puts "name: #{name}"
6
+ puts "phone: #{phone}"
data/example/list.png CHANGED
Binary file
data/example/list.rb CHANGED
@@ -4,4 +4,9 @@ idx = Ask.list "Look behind you...", [
4
4
  "a pink pony",
5
5
  "Godzilla"
6
6
  ]
7
+ idx = Ask.list "Look behind you...", [
8
+ "a three-headed monkey!",
9
+ "a pink pony",
10
+ "Godzilla"
11
+ ]
7
12
  puts "you selected #{idx}"
data/lib/inquirer.rb CHANGED
@@ -2,6 +2,8 @@ require 'inquirer/version'
2
2
  require 'inquirer/utils/iohelper'
3
3
  require 'inquirer/prompts/list'
4
4
  require 'inquirer/prompts/checkbox'
5
+ require 'inquirer/prompts/input'
6
+ require 'inquirer/prompts/confirm'
5
7
 
6
8
  module Ask
7
9
  extend self
@@ -12,4 +14,10 @@ module Ask
12
14
  def checkbox *args
13
15
  Checkbox.ask *args
14
16
  end
17
+ def input *args
18
+ Input.ask *args
19
+ end
20
+ def confirm *args
21
+ Confirm.ask *args
22
+ end
15
23
  end
@@ -14,6 +14,13 @@ module CheckboxRenderer
14
14
  ( footer.nil? ? "" : @footer % footer )
15
15
  end
16
16
 
17
+ def renderResponse heading = nil, response = nil
18
+ # render the heading
19
+ ( heading.nil? ? "" : @heading % heading ) +
20
+ # render the footer
21
+ ( response.nil? ? "" : @response % response )
22
+ end
23
+
17
24
  private
18
25
 
19
26
  def render_item x
@@ -40,14 +47,25 @@ class CheckboxDefault
40
47
  end
41
48
  end
42
49
 
50
+ # Default formatting for response
51
+ class CheckboxResponseDefault
52
+ include CheckboxRenderer
53
+ C = Term::ANSIColor
54
+ def initialize( style = nil )
55
+ @heading = "%s: "
56
+ @response = C.cyan("%s") + "\n"
57
+ end
58
+ end
59
+
43
60
  class Checkbox
44
- def initialize question = nil, elements = [], renderer = nil
61
+ def initialize question = nil, elements = [], renderer = nil, responseRenderer = nil
45
62
  @elements = elements
46
63
  @question = question
47
64
  @pos = 0
48
65
  @active = elements.map{|i| false}
49
66
  @prompt = ""
50
67
  @renderer = renderer || CheckboxDefault.new( Inquirer::Style::Default )
68
+ @responseRenderer = responseRenderer = CheckboxResponseDefault.new()
51
69
  end
52
70
 
53
71
  def update_prompt
@@ -63,35 +81,55 @@ class Checkbox
63
81
  @prompt = @renderer.render(@question, e)
64
82
  end
65
83
 
84
+ def update_response
85
+ e = @elements
86
+ .map.with_index(0)
87
+ .select {|f, pos| @active[pos] }
88
+ .map {|f, pos| f }
89
+ @prompt = @responseRenderer.renderResponse(@question, e.join(", "))
90
+ end
91
+
66
92
  # Run the list selection, wait for the user to select an item and return
67
93
  # the selected index
68
94
  # Params:
69
95
  # +clear+:: +Bool+ whether to clear the selection prompt once this is done
70
96
  # defaults to true; set it to false if you want the prompt to remain after
71
97
  # the user is done with selecting
72
- def run clear = true
98
+ # +response+:: +Bool+ whether show the rendered response when this is done
99
+ # defaults to true; set it to false if you want the prompt to remain after
100
+ # the user is done with selecting
101
+ def run clear, response
73
102
  # finish if there's nothing to do
74
103
  return @active if Array(@elements).empty?
75
- # render the
76
- IOHelper.render( update_prompt )
77
- # loop through user input
78
- IOHelper.read_key_while do |key|
79
- @pos = (@pos - 1) % @elements.length if key == "up"
80
- @pos = (@pos + 1) % @elements.length if key == "down"
81
- @active[@pos] = !@active[@pos] if key == "space"
82
- IOHelper.rerender( update_prompt )
83
- # we are done if the user hits return
84
- key != "return"
104
+
105
+ # hides the cursor while prompting
106
+ IOHelper.without_cursor do
107
+ # render the
108
+ IOHelper.render( update_prompt )
109
+ # loop through user input
110
+ IOHelper.read_key_while do |key|
111
+ @pos = (@pos - 1) % @elements.length if key == "up"
112
+ @pos = (@pos + 1) % @elements.length if key == "down"
113
+ @active[@pos] = !@active[@pos] if key == "space"
114
+ IOHelper.rerender( update_prompt )
115
+ # we are done if the user hits return
116
+ key != "return"
117
+ end
85
118
  end
119
+
86
120
  # clear the final prompt and the line
87
121
  IOHelper.clear if clear
122
+
123
+ # show the answer
124
+ IOHelper.render( update_response ) if response
125
+
88
126
  # return the index of the selected item
89
127
  @active
90
128
  end
91
129
 
92
- def self.ask question = nil, elements = [], opts = { clear: true }
93
- l = Checkbox.new question, elements, opts[:renderer]
94
- l.run opts[:clear]
130
+ def self.ask question = nil, elements = [], opts = {}
131
+ l = Checkbox.new question, elements, opts[:renderer], opts[:rendererResponse]
132
+ l.run opts.fetch(:clear, true), opts.fetch(:response, true)
95
133
  end
96
134
 
97
135
  end
@@ -0,0 +1,114 @@
1
+ require 'term/ansicolor'
2
+
3
+ # Base rendering for confirm
4
+ module ConfirmRenderer
5
+ def render heading = nil, default = nil, footer = nil
6
+ options = ['y','n']
7
+ options[0].capitalize! if default == true
8
+ options[1].capitalize! if default == false
9
+
10
+ # render the heading
11
+ ( heading.nil? ? "" : @heading % heading ) +
12
+ # render the defaults
13
+ @default % options +
14
+ # render the footer
15
+ ( footer.nil? ? "" : @footer % footer )
16
+ end
17
+
18
+ def renderResponse heading = nil, response = nil
19
+ # render the heading
20
+ ( heading.nil? ? "" : @heading % heading ) +
21
+ # render the footer
22
+ ( response.nil? ? "" : @response % response )
23
+ end
24
+ end
25
+
26
+ # Default formatting for confirm rendering
27
+ class ConfirmDefault
28
+ include ConfirmRenderer
29
+ C = Term::ANSIColor
30
+ def initialize( style )
31
+ @heading = "%s: "
32
+ @default = "(%s/%s)"
33
+ @footer = "%s"
34
+ end
35
+ end
36
+
37
+ # Default formatting for response
38
+ class ConfirmResponseDefault
39
+ include ConfirmRenderer
40
+ C = Term::ANSIColor
41
+ def initialize( style = nil )
42
+ @heading = "%s: "
43
+ @response = C.cyan("%s") + "\n"
44
+ end
45
+ end
46
+
47
+ class Confirm
48
+ def initialize question = nil, default = nil, renderer = nil, responseRenderer = nil
49
+ @question = question
50
+ @value = ""
51
+ @default = default
52
+ @prompt = ""
53
+ @renderer = renderer || ConfirmDefault.new( Inquirer::Style::Default )
54
+ @responseRenderer = responseRenderer = ConfirmResponseDefault.new()
55
+ end
56
+
57
+ def update_prompt
58
+ # call the renderer
59
+ @prompt = @renderer.render(@question, @default)
60
+ end
61
+
62
+ def update_response
63
+ @prompt = @responseRenderer.renderResponse(@question, (@value)? 'Yes' : 'No')
64
+ end
65
+
66
+ # Run the list selection, wait for the user to select an item and return
67
+ # the selected index
68
+ # Params:
69
+ # +clear+:: +Bool+ whether to clear the selection prompt once this is done
70
+ # defaults to true; set it to false if you want the prompt to remain after
71
+ # the user is done with selecting
72
+ # +response+:: +Bool+ whether show the rendered response when this is done
73
+ # defaults to true; set it to false if you want the prompt to remain after
74
+ # the user is done with selecting
75
+ def run clear, response
76
+ # render the
77
+ IOHelper.render( update_prompt )
78
+ # loop through user confirm
79
+ # IOHelper.read_char
80
+ IOHelper.read_key_while true do |key|
81
+ raw = IOHelper.char_to_raw(key)
82
+
83
+ case raw
84
+ when "y","Y"
85
+ @value = true
86
+ false
87
+ when "n","N"
88
+ @value = false
89
+ false
90
+ when "return"
91
+ @value = @default
92
+ false
93
+ else
94
+ true
95
+ end
96
+
97
+ end
98
+
99
+ # clear the final prompt and the line
100
+ IOHelper.clear if clear
101
+
102
+ # show the answer
103
+ IOHelper.render( update_response ) if response
104
+
105
+ # return the value
106
+ @value
107
+ end
108
+
109
+ def self.ask question = nil, opts = {}
110
+ l = Confirm.new question, opts.fetch(:default, true), opts[:renderer], opts[:rendererResponse]
111
+ l.run opts.fetch(:clear, true), opts.fetch(:response, true)
112
+ end
113
+
114
+ end
@@ -0,0 +1,130 @@
1
+ require 'term/ansicolor'
2
+
3
+ # Base rendering for input
4
+ module InputRenderer
5
+ def render heading = nil, value = nil, default = nil, footer = nil
6
+ # render the heading
7
+ ( heading.nil? ? "" : @heading % heading ) +
8
+ # render the defaults
9
+ ( default.nil? ? "" : @default % default ) +
10
+ # render the list
11
+ ( value.nil? ? "" : @value % value ) +
12
+ # render the footer
13
+ ( footer.nil? ? "" : @footer % footer )
14
+ end
15
+
16
+ def renderResponse heading = nil, response = nil
17
+ # render the heading
18
+ ( heading.nil? ? "" : @heading % heading ) +
19
+ # render the footer
20
+ ( response.nil? ? "" : @response % response )
21
+ end
22
+ end
23
+
24
+ # Default formatting for list rendering
25
+ class InputDefault
26
+ include InputRenderer
27
+ C = Term::ANSIColor
28
+ def initialize( style )
29
+ @heading = "%s: "
30
+ @default = "(%s) "
31
+ @value = "%s"
32
+ @footer = "%s"
33
+ end
34
+ end
35
+
36
+ # Default formatting for response
37
+ class InputResponseDefault
38
+ include InputRenderer
39
+ C = Term::ANSIColor
40
+ def initialize( style = nil )
41
+ @heading = "%s: "
42
+ @response = C.cyan("%s") + "\n"
43
+ end
44
+ end
45
+
46
+ class Input
47
+ def initialize question = nil, default = nil, renderer = nil, responseRenderer = nil
48
+ @question = question
49
+ @value = ""
50
+ @default = default
51
+ @prompt = ""
52
+ @pos = 0
53
+ @renderer = renderer || InputDefault.new( Inquirer::Style::Default )
54
+ @responseRenderer = responseRenderer = InputResponseDefault.new()
55
+ end
56
+
57
+ def update_prompt
58
+ # call the renderer
59
+ @prompt = @renderer.render(@question, @value, @default)
60
+ end
61
+
62
+ def update_response
63
+ @prompt = @responseRenderer.renderResponse(@question, @value)
64
+ end
65
+
66
+ def update_cursor
67
+ print IOHelper.char_left * @pos
68
+ end
69
+
70
+ # Run the list selection, wait for the user to select an item and return
71
+ # the selected index
72
+ # Params:
73
+ # +clear+:: +Bool+ whether to clear the selection prompt once this is done
74
+ # defaults to true; set it to false if you want the prompt to remain after
75
+ # the user is done with selecting
76
+ # +response+:: +Bool+ whether show the rendered response when this is done
77
+ # defaults to true; set it to false if you want the prompt to remain after
78
+ # the user is done with selecting
79
+ def run clear, response
80
+ # render the
81
+ IOHelper.render( update_prompt )
82
+ # loop through user input
83
+ # IOHelper.read_char
84
+ IOHelper.read_key_while true do |key|
85
+ raw = IOHelper.char_to_raw(key)
86
+
87
+ case raw
88
+ when "backspace"
89
+ @value = @value.chop
90
+ IOHelper.rerender( update_prompt )
91
+ update_cursor
92
+ when "left"
93
+ if @pos < @value.length
94
+ @pos = @pos + 1
95
+ print IOHelper.char_left
96
+ end
97
+ when "right"
98
+ if @pos > 0
99
+ @pos = @pos - 1
100
+ print IOHelper.char_right
101
+ end
102
+ when "return"
103
+ if not @default.nil? and @value == ""
104
+ @value = @default
105
+ end
106
+ else
107
+ unless ["up", "down"].include?(raw)
108
+ @value = @value.insert(@value.length - @pos, key)
109
+ IOHelper.rerender( update_prompt )
110
+ update_cursor
111
+ end
112
+ end
113
+ raw != "return"
114
+ end
115
+ # clear the final prompt and the line
116
+ IOHelper.clear if clear
117
+
118
+ # show the answer
119
+ IOHelper.render( update_response ) if response
120
+
121
+ # return the value
122
+ @value
123
+ end
124
+
125
+ def self.ask question = nil, opts = {}
126
+ l = Input.new question, opts[:default], opts[:renderer], opts[:rendererResponse]
127
+ l.run opts.fetch(:clear, true), opts.fetch(:response, true)
128
+ end
129
+
130
+ end
@@ -13,6 +13,13 @@ module ListRenderer
13
13
  ( footer.nil? ? "" : @footer % footer )
14
14
  end
15
15
 
16
+ def renderResponse heading = nil, response = nil
17
+ # render the heading
18
+ ( heading.nil? ? "" : @heading % heading ) +
19
+ # render the footer
20
+ ( response.nil? ? "" : @response % response )
21
+ end
22
+
16
23
  private
17
24
 
18
25
  def render_item x
@@ -34,13 +41,24 @@ class ListDefault
34
41
  end
35
42
  end
36
43
 
44
+ # Default formatting for response
45
+ class ListResponseDefault
46
+ include ListRenderer
47
+ C = Term::ANSIColor
48
+ def initialize( style = nil )
49
+ @heading = "%s: "
50
+ @response = C.cyan("%s") + "\n"
51
+ end
52
+ end
53
+
37
54
  class List
38
- def initialize question = nil, elements = [], renderer = nil
55
+ def initialize question = nil, elements = [], renderer = nil, responseRenderer = nil
39
56
  @elements = elements
40
57
  @question = question
41
58
  @pos = 0
42
59
  @prompt = ""
43
- @renderer = renderer || ListDefault.new( Inquirer::Style::Default )
60
+ @renderer = renderer = ListDefault.new( Inquirer::Style::Default )
61
+ @responseRenderer = responseRenderer = ListResponseDefault.new()
44
62
  end
45
63
 
46
64
  def update_prompt
@@ -56,34 +74,50 @@ class List
56
74
  @prompt = @renderer.render(@question, e)
57
75
  end
58
76
 
77
+ def update_response
78
+ @prompt = @responseRenderer.renderResponse(@question, @elements[@pos])
79
+ end
80
+
59
81
  # Run the list selection, wait for the user to select an item and return
60
82
  # the selected index
61
83
  # Params:
62
84
  # +clear+:: +Bool+ whether to clear the selection prompt once this is done
63
85
  # defaults to true; set it to false if you want the prompt to remain after
64
86
  # the user is done with selecting
65
- def run clear = true
87
+ # +response+:: +Bool+ whether show the rendered response when this is done
88
+ # defaults to true; set it to false if you want the prompt to remain after
89
+ # the user is done with selecting
90
+ def run clear, response
66
91
  # finish if there's nothing to do
67
92
  return nil if Array(@elements).empty?
68
- # render the
69
- IOHelper.render( update_prompt )
70
- # loop through user input
71
- IOHelper.read_key_while do |key|
72
- @pos = (@pos - 1) % @elements.length if key == "up"
73
- @pos = (@pos + 1) % @elements.length if key == "down"
74
- IOHelper.rerender( update_prompt )
75
- # we are done if the user hits return
76
- key != "return"
93
+
94
+ # hides the cursor while prompting
95
+ IOHelper.without_cursor do
96
+ # render the
97
+ IOHelper.render( update_prompt )
98
+ # loop through user input
99
+ IOHelper.read_key_while do |key|
100
+ @pos = (@pos - 1) % @elements.length if key == "up"
101
+ @pos = (@pos + 1) % @elements.length if key == "down"
102
+ IOHelper.rerender( update_prompt )
103
+ # we are done if the user hits return
104
+ key != "return"
105
+ end
77
106
  end
107
+
78
108
  # clear the final prompt and the line
79
109
  IOHelper.clear if clear
110
+
111
+ # show the answer
112
+ IOHelper.render( update_response ) if response
113
+
80
114
  # return the index of the selected item
81
115
  @pos
82
116
  end
83
117
 
84
- def self.ask question = nil, elements = [], opts = { clear: true }
85
- l = List.new question, elements, opts[:renderer]
86
- l.run opts[:clear]
118
+ def self.ask question = nil, elements = [], opts = {}
119
+ l = List.new question, elements, opts[:renderer], opts[:rendererResponse]
120
+ l.run opts.fetch(:clear, true), opts.fetch(:response, true)
87
121
  end
88
122
 
89
- end
123
+ end
@@ -56,21 +56,21 @@ module IOHelper
56
56
  # Params:
57
57
  # +with_exit_codes+:: +Bool+ whether to throw Interrupts when the user presses
58
58
  # ctrl-c and ctrl-d. (true by default)
59
- def read_key with_exit_codes = true
60
- raw = read_key_raw
61
- raise Interrupt if with_exit_codes and ( raw == "ctrl-c" or raw == "ctrl-d" )
62
- raw
59
+ def read_key with_exit_codes = true, return_char = false
60
+ char = read_char
61
+ raise Interrupt if with_exit_codes and ( char == "\003" or char == "\004" )
62
+ if return_char then char else char_to_raw char end
63
63
  end
64
64
 
65
65
  # Get each key the user presses and hand it one by one to the block. Do this
66
66
  # as long as the block returns truthy
67
67
  # Params:
68
68
  # +&block+:: +Proc+ a block that receives a user key and returns truthy or falsy
69
- def read_key_while &block
69
+ def read_key_while return_char = false, &block
70
70
  STDIN.noecho do
71
71
  # as long as the block doen't return falsy,
72
72
  # read the user input key and sned it to the block
73
- while block.( IOHelper.read_key )
73
+ while block.( IOHelper.read_key true, return_char )
74
74
  end
75
75
  end
76
76
  end
@@ -100,21 +100,30 @@ module IOHelper
100
100
  # determine how many lines to move up
101
101
  n = @rendered.scan(/\n/).length
102
102
  # jump back to the first position and clear the line
103
- print carriage_return + ( line_up * n ) + clear_line
103
+ print carriage_return + ( line_up + clear_line ) * n + clear_line
104
+ end
105
+
106
+ # hides the cursor and ensure the curso be visible at the end
107
+ def without_cursor
108
+ # tell the terminal to hide the cursor
109
+ print `tput civis`
110
+ begin
111
+ # run the block
112
+ yield
113
+ ensure
114
+ # tell the terminal to show the cursor
115
+ print `tput cnorm`
116
+ end
117
+ end
118
+
119
+ def char_to_raw char
120
+ KEYS.fetch char, char
104
121
  end
105
122
 
106
123
  def carriage_return; "\r" end
107
124
  def line_up; "\e[A" end
108
125
  def clear_line; "\e[0K" end
109
-
110
- private
111
-
112
- def read_key_raw
113
- c = read_char
114
- # try to get the key name from the character
115
- k = KEYS[c]
116
- # return either the character or key name
117
- ( k.nil? ) ? c : k
118
- end
126
+ def char_left; "\e[D" end
127
+ def char_right; "\e[C" end
119
128
 
120
129
  end
@@ -1,3 +1,3 @@
1
1
  module Inquirer
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -8,51 +8,61 @@ describe Checkbox do
8
8
  end
9
9
 
10
10
  it "finishes rendering with a clear" do
11
- Checkbox.ask "select", ["one","two","three"]
11
+ Checkbox.ask "select", ["one","two","three"], response: false
12
12
  IOHelper.output.must_equal ""
13
13
  end
14
14
 
15
15
  it "doesn't render the dialog with 0 items" do
16
- Checkbox.ask "select", [], clear: false
16
+ Checkbox.ask "select", [], clear: false, response: false
17
17
  IOHelper.output.must_equal ""
18
18
  end
19
19
 
20
20
  it "renders the dialog with 3 items" do
21
- Checkbox.ask "select", ["one","two","three"], clear: false
21
+ Checkbox.ask "select", ["one","two","three"], clear: false, response: false
22
22
  IOHelper.output.must_equal "select:\n\e[36m‣\e[0m⬡ one\n ⬡ two\n ⬡ three\n"
23
23
  end
24
24
 
25
25
  it "it finishes selection on pressing enter" do
26
26
  IOHelper.keys = "enter"
27
- Checkbox.ask( "select", ["one","two","three"], clear: false
27
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
28
28
  ).must_equal [false,false,false]
29
29
  end
30
30
 
31
31
  it "selects and renders other items correctly (press down, press up, space, cycle)" do
32
32
  IOHelper.keys = ["down","space","enter"]
33
- Checkbox.ask( "select", ["one","two","three"], clear: false
33
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
34
34
  ).must_equal [false,true,false]
35
35
  IOHelper.output.must_equal "select:\n ⬡ one\n\e[36m‣\e[0m\e[36m⬢\e[0m two\n ⬡ three\n"
36
36
 
37
37
  IOHelper.keys = ["space","down","space","enter"]
38
- Checkbox.ask( "select", ["one","two","three"], clear: false
38
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
39
39
  ).must_equal [true,true,false]
40
40
  IOHelper.output.must_equal "select:\n \e[36m⬢\e[0m one\n\e[36m‣\e[0m\e[36m⬢\e[0m two\n ⬡ three\n"
41
41
 
42
42
  IOHelper.keys = ["space","down","space","down","space","enter"]
43
- Checkbox.ask( "select", ["one","two","three"], clear: false
43
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
44
44
  ).must_equal [true,true,true]
45
45
  IOHelper.output.must_equal "select:\n \e[36m⬢\e[0m one\n \e[36m⬢\e[0m two\n\e[36m‣\e[0m\e[36m⬢\e[0m three\n"
46
46
 
47
47
  IOHelper.keys = ["down","down","down","space","enter"]
48
- Checkbox.ask( "select", ["one","two","three"], clear: false
48
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
49
49
  ).must_equal [true,false,false]
50
50
  IOHelper.output.must_equal "select:\n\e[36m‣\e[0m\e[36m⬢\e[0m one\n ⬡ two\n ⬡ three\n"
51
51
 
52
52
  IOHelper.keys = ["up","space","enter"]
53
- Checkbox.ask( "select", ["one","two","three"], clear: false
53
+ Checkbox.ask( "select", ["one","two","three"], clear: false, response: false
54
54
  ).must_equal [false,false,true]
55
55
  IOHelper.output.must_equal "select:\n ⬡ one\n ⬡ two\n\e[36m‣\e[0m\e[36m⬢\e[0m three\n"
56
56
  end
57
57
 
58
+ it "selects and renders response correctly" do
59
+ IOHelper.keys = ["down","space","enter"]
60
+ Checkbox.ask( "select", ["one","two","three"])
61
+ IOHelper.output.must_equal "select: \e[36mtwo\e[0m\n"
62
+
63
+ IOHelper.keys = ["space","down","space","enter"]
64
+ Checkbox.ask( "select", ["one","two","three"])
65
+ IOHelper.output.must_equal "select: \e[36mone, two\e[0m\n"
66
+ end
67
+
58
68
  end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+
4
+ describe Confirm do
5
+ before :each do
6
+ IOHelper.output = ""
7
+ end
8
+
9
+ it "should return true for y and Y and enter when default" do
10
+ IOHelper.keys = "y"
11
+ Confirm.ask("Are you sure?").must_equal true
12
+ IOHelper.keys = "Y"
13
+ Confirm.ask("Are you sure?").must_equal true
14
+ IOHelper.keys = "\r"
15
+ Confirm.ask("Are you sure?", default: true).must_equal true
16
+ end
17
+
18
+ it "should return false for n and N and enter when default" do
19
+ IOHelper.keys = "n"
20
+ Confirm.ask("Are you sure?").must_equal false
21
+ IOHelper.keys = "N"
22
+ Confirm.ask("Are you sure?").must_equal false
23
+ IOHelper.keys = "\r"
24
+ Confirm.ask("Are you sure?", default: false).must_equal false
25
+ end
26
+
27
+ it "should return true if not default given" do
28
+ IOHelper.keys = "\r"
29
+ Confirm.ask("Are you sure?").must_equal true
30
+ end
31
+
32
+ it "accepts and renders response correctly" do
33
+ IOHelper.keys = "n"
34
+ Confirm.ask("Are you sure?")
35
+ IOHelper.output.must_equal "Are you sure?: \e[36mNo\e[0m\n"
36
+
37
+ IOHelper.keys = "N"
38
+ Confirm.ask("Are you sure?")
39
+ IOHelper.output.must_equal "Are you sure?: \e[36mNo\e[0m\n"
40
+
41
+ IOHelper.keys = "y"
42
+ Confirm.ask("Are you sure?")
43
+ IOHelper.output.must_equal "Are you sure?: \e[36mYes\e[0m\n"
44
+
45
+ IOHelper.keys = "y"
46
+ Confirm.ask("Are you sure?")
47
+ IOHelper.output.must_equal "Are you sure?: \e[36mYes\e[0m\n"
48
+ end
49
+
50
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require 'minitest_helper'
3
+
4
+ describe Input do
5
+ before :each do
6
+ IOHelper.output = ""
7
+ IOHelper.keys = ['t','y','p','e','d',' ','i','n','p','u','t',"\r"]
8
+ end
9
+
10
+ it "should use chars value from the user" do
11
+ Input.ask("please type input").must_equal "typed input"
12
+ end
13
+
14
+ it "accepts and renders response correctly" do
15
+ Input.ask("please type input")
16
+ IOHelper.output.must_equal "please type input: \e[36mtyped input\e[0m\n"
17
+ end
18
+
19
+ it "should return default value if given and there is no input" do
20
+ IOHelper.keys = "\r"
21
+ Confirm.ask("Are you sure?", default: "I'm default").must_equal "I'm default"
22
+ end
23
+
24
+ end
@@ -8,51 +8,61 @@ describe List do
8
8
  end
9
9
 
10
10
  it "finishes rendering with a clear" do
11
- List.ask "select", ["one","two","three"]
11
+ List.ask "select", ["one","two","three"], response: false
12
12
  IOHelper.output.must_equal ""
13
13
  end
14
14
 
15
15
  it "doesn't render the dialog with 0 items" do
16
- List.ask "select", [], clear: false
16
+ List.ask "select", [], clear: false, response: false
17
17
  IOHelper.output.must_equal ""
18
18
  end
19
19
 
20
20
  it "renders the dialog with 3 items" do
21
- List.ask "select", ["one","two","three"], clear: false
21
+ List.ask "select", ["one","two","three"], clear: false, response: false
22
22
  IOHelper.output.must_equal "select:\n\e[36m‣\e[0m \e[36mone\e[0m\n two\n three\n"
23
23
  end
24
24
 
25
25
  it "it finishes selection on pressing enter" do
26
26
  IOHelper.keys = "enter"
27
- List.ask( "select", ["one","two","three"], clear: false
27
+ List.ask( "select", ["one","two","three"], clear: false, response: false
28
28
  ).must_equal 0
29
29
  end
30
30
 
31
31
  it "selects and renders other items correctly (press down, press up, cycle)" do
32
32
  IOHelper.keys = ["down","enter"]
33
- List.ask( "select", ["one","two","three"], clear: false
33
+ List.ask( "select", ["one","two","three"], clear: false, response: false
34
34
  ).must_equal 1
35
35
  IOHelper.output.must_equal "select:\n one\n\e[36m‣\e[0m \e[36mtwo\e[0m\n three\n"
36
36
 
37
37
  IOHelper.keys = ["down","down","enter"]
38
- List.ask( "select", ["one","two","three"], clear: false
38
+ List.ask( "select", ["one","two","three"], clear: false, response: false
39
39
  ).must_equal 2
40
40
  IOHelper.output.must_equal "select:\n one\n two\n\e[36m‣\e[0m \e[36mthree\e[0m\n"
41
41
 
42
42
  IOHelper.keys = ["down","down","down","enter"]
43
- List.ask( "select", ["one","two","three"], clear: false
43
+ List.ask( "select", ["one","two","three"], clear: false, response: false
44
44
  ).must_equal 0
45
45
  IOHelper.output.must_equal "select:\n\e[36m‣\e[0m \e[36mone\e[0m\n two\n three\n"
46
46
 
47
47
  IOHelper.keys = ["down","up","enter"]
48
- List.ask( "select", ["one","two","three"], clear: false
48
+ List.ask( "select", ["one","two","three"], clear: false, response: false
49
49
  ).must_equal 0
50
50
  IOHelper.output.must_equal "select:\n\e[36m‣\e[0m \e[36mone\e[0m\n two\n three\n"
51
51
 
52
52
  IOHelper.keys = ["up","enter"]
53
- List.ask( "select", ["one","two","three"], clear: false
53
+ List.ask( "select", ["one","two","three"], clear: false, response: false
54
54
  ).must_equal 2
55
55
  IOHelper.output.must_equal "select:\n one\n two\n\e[36m‣\e[0m \e[36mthree\e[0m\n"
56
56
  end
57
57
 
58
+ it "selects and renders response correctly" do
59
+ IOHelper.keys = ["down","enter"]
60
+ List.ask( "select", ["one","two","three"])
61
+ IOHelper.output.must_equal "select: \e[36mtwo\e[0m\n"
62
+
63
+ IOHelper.keys = ["down","down","enter"]
64
+ List.ask( "select", ["one","two","three"])
65
+ IOHelper.output.must_equal "select: \e[36mthree\e[0m\n"
66
+ end
67
+
58
68
  end
@@ -34,7 +34,9 @@ module IOHelper
34
34
  def rerender sth
35
35
  @output = sth
36
36
  end
37
- def read_key_while &block
38
- Array(@keys).each{|key| block.(key)}
37
+ def read_key_while return_char = false, &block
38
+ Array(@keys).each do |key|
39
+ break unless block.(key)
40
+ end
39
41
  end
40
- end
42
+ end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquirer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-24 00:00:00.000000000 Z
11
+ date: 2014-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: term-ansicolor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.2.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.2.2
27
27
  description: Interactive user prompts on CLI for ruby.
@@ -30,7 +30,7 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
- - .travis.yml
33
+ - ".travis.yml"
34
34
  - CHANGELOG.md
35
35
  - Gemfile
36
36
  - LICENSE
@@ -38,16 +38,24 @@ files:
38
38
  - Rakefile
39
39
  - example/checkbox.png
40
40
  - example/checkbox.rb
41
+ - example/confirm.png
42
+ - example/confirm.rb
43
+ - example/input.png
44
+ - example/input.rb
41
45
  - example/list.png
42
46
  - example/list.rb
43
47
  - inquirer.gemspec
44
48
  - lib/inquirer.rb
45
49
  - lib/inquirer/prompts/checkbox.rb
50
+ - lib/inquirer/prompts/confirm.rb
51
+ - lib/inquirer/prompts/input.rb
46
52
  - lib/inquirer/prompts/list.rb
47
53
  - lib/inquirer/style.rb
48
54
  - lib/inquirer/utils/iohelper.rb
49
55
  - lib/inquirer/version.rb
50
56
  - test/classes/checkbox_spec.rb
57
+ - test/classes/confirm_spec.rb
58
+ - test/classes/input_spec.rb
51
59
  - test/classes/list_spec.rb
52
60
  - test/minitest_helper.rb
53
61
  homepage: https://github.com/arlimus/inquirer.rb
@@ -60,19 +68,18 @@ require_paths:
60
68
  - lib
61
69
  required_ruby_version: !ruby/object:Gem::Requirement
62
70
  requirements:
63
- - - '>='
71
+ - - ">="
64
72
  - !ruby/object:Gem::Version
65
73
  version: '0'
66
74
  required_rubygems_version: !ruby/object:Gem::Requirement
67
75
  requirements:
68
- - - '>='
76
+ - - ">="
69
77
  - !ruby/object:Gem::Version
70
78
  version: '0'
71
79
  requirements: []
72
80
  rubyforge_project:
73
- rubygems_version: 2.0.14
81
+ rubygems_version: 2.2.0
74
82
  signing_key:
75
83
  specification_version: 4
76
84
  summary: Interactive user prompts on CLI for ruby.
77
85
  test_files: []
78
- has_rdoc: