inquirer 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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: