userinput 1.0.1 → 1.0.2

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: fa7fa580b2919ec587477758892ba2dcd9f0edee
4
- data.tar.gz: 05400265239b2bd76e85f59b5ebf34700df15fcb
3
+ metadata.gz: fecaf095e207d7b834db8f0de396d80af8d87ff6
4
+ data.tar.gz: 9d4c5839e4836859e16ce401c913e408f70caa0d
5
5
  SHA512:
6
- metadata.gz: 47f23a9a9d8d4c28cdb752f9d2ad854310ed2212a4e9a1792038f13b271192bbb2f31faaf81f459b5dedb1a850ef37785247f849fa930cff26c2429c05c57634
7
- data.tar.gz: a8db81aebdeac9512fb7f4326bfeb3345c28c75ed0e6168175e654bfbfad0058b51a42b0b514d9eb0d5b3f4d1ef2d80aaf276d78adf0509b47550c94ca6286b8
6
+ metadata.gz: e0beb2540cbf3a317db9ebb5f4f292a7e8e39316acc20862cafed1349143bc97e1c22a2432a22dd048875613c3a82ea9fbf657d6fd34b790a246022bd3e0fd40
7
+ data.tar.gz: 1e27c605e1890342f2f795bc1674020e2d371757497db1b70243878cf356570ab43a9b4684d837de98dadbd12f92c4535596223bd9642e5231370df2fa19ea31
@@ -0,0 +1,4 @@
1
+ 2.4.0
2
+ 2.3.3
3
+ 2.2.6
4
+ 2.1.10
@@ -1,2 +1,7 @@
1
1
  Encoding:
2
2
  Enabled: false
3
+ Metrics/BlockLength:
4
+ Exclude:
5
+ - spec/**/*
6
+ Style/FormatString:
7
+ EnforcedStyle: percent
@@ -1,3 +1,13 @@
1
+ # 1.0.3 / 2016-04-10
2
+
3
+ * [ENHANCEMENT] Clean up module layout
4
+ * [FEATURE] Add Boolean helper for yes/no questions
5
+
6
+ # 1.0.2 / 2016-04-08
7
+
8
+ * [FEATURE] Add support for Enumerables in :validation parameter
9
+ * [ENHANCEMENT] Refactor validation support to be more extensible
10
+
1
11
  # 1.0.1 / 2016-02-13
2
12
 
3
13
  * [FEATURE] Support setting custom IO object as file descriptor for output
data/README.md CHANGED
@@ -3,7 +3,7 @@ userinput
3
3
 
4
4
  [![Gem Version](https://img.shields.io/gem/v/userinput.svg)](https://rubygems.org/gems/userinput)
5
5
  [![Dependency Status](https://img.shields.io/gemnasium/akerl/userinput.svg)](https://gemnasium.com/akerl/userinput)
6
- [![Build Status](https://img.shields.io/circleci/project/akerl/userinput.svg)](https://circleci.com/gh/akerl/userinput)
6
+ [![Build Status](https://img.shields.io/circleci/project/akerl/userinput/master.svg)](https://circleci.com/gh/akerl/userinput)
7
7
  [![Coverage Status](https://img.shields.io/codecov/c/github/akerl/userinput.svg)](https://codecov.io/github/akerl/userinput)
8
8
  [![Code Quality](https://img.shields.io/codacy/fbda4046154e4ac38a47f2c6627d57c8.svg)](https://www.codacy.com/app/akerl/userinput)
9
9
  [![MIT Licensed](https://img.shields.io/badge/license-MIT-green.svg)](https://tldrlegal.com/license/mit-license)
@@ -39,7 +39,7 @@ You can optionally provide a default:
39
39
  => "_other"
40
40
  ```
41
41
 
42
- If you provide a validation Regexp or a code block, the input will be validated using that:
42
+ If you provide a validation Regexp, Enumerable, or a code block, the input will be validated using that:
43
43
 
44
44
  ```
45
45
  > require 'userinput'
@@ -97,6 +97,19 @@ Password?
97
97
  => "_password"
98
98
  ```
99
99
 
100
+ ### Boolean helper
101
+
102
+ UserInput::Boolean is a subclass of Prompt that is designed for asking yes/no questions.
103
+
104
+ It valiates that answers match /(y|yes|n|no)/i, and returns the response as a boolean true/false rather than a string.
105
+
106
+ To use it:
107
+
108
+ ```
109
+ a = UserInput::Boolean.new(message: 'Do you like cats')
110
+ response = a.ask
111
+ ```
112
+
100
113
  ## Installation
101
114
 
102
115
  gem install userinput
data/circle.yml CHANGED
@@ -1,12 +1,7 @@
1
1
  dependencies:
2
2
  override:
3
- - 'rvm-exec 1.9.3-p551 bundle install'
4
- - 'rvm-exec 2.0.0-p645 bundle install'
5
- - 'rvm-exec 2.1.6 bundle install'
6
- - 'rvm-exec 2.2.2 bundle install'
3
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i gem update --system --no-doc || exit 1 ; done'
4
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle install || exit 1 ; done'
7
5
  test:
8
6
  override:
9
- - 'rvm-exec 1.9.3-p551 bundle exec rake'
10
- - 'rvm-exec 2.0.0-p645 bundle exec rake'
11
- - 'rvm-exec 2.1.6 bundle exec rake'
12
- - 'rvm-exec 2.2.2 bundle exec rake'
7
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle exec rake || exit 1 ; done'
@@ -1,6 +1,13 @@
1
1
  ##
2
2
  # User input library
3
3
  module UserInput
4
+ # Hash of validation strategies
5
+ VALIDATIONS = {
6
+ Proc => :call,
7
+ Regexp => :match,
8
+ Enumerable => :include?
9
+ }.freeze
10
+
4
11
  class << self
5
12
  ##
6
13
  # Insert a helper .new() method for creating a new Prompt object
@@ -9,89 +16,7 @@ module UserInput
9
16
  self::Prompt.new(*args, &block)
10
17
  end
11
18
  end
12
-
13
- ##
14
- # Prompt object
15
- class Prompt
16
- ##
17
- # Build new prompt object and set defaults
18
- def initialize(params = {}, &block)
19
- @attempts = params[:attempts]
20
- @message = params[:message] || ''
21
- @default = params[:default]
22
- @secret = params[:secret] || false
23
- @fd = params[:fd] || STDOUT
24
- @validation = block || params[:validation]
25
- end
26
-
27
- ##
28
- # Request user input
29
- def ask
30
- @fd.print "#{@message}? #{@default.nil? ? '' : "[#{@default}] "}"
31
- disable_echo if @secret
32
-
33
- input = _ask
34
- return input if valid(input)
35
-
36
- check_counter
37
- ask
38
- ensure
39
- enable_echo if @secret
40
- end
41
-
42
- private
43
-
44
- ##
45
- # Validate user input
46
- def valid(input)
47
- case @validation
48
- when Proc
49
- return @validation.call input
50
- when Regexp
51
- return @validation.match input
52
- when NilClass
53
- return true
54
- else
55
- raise "Supported validation type not provided #{@validation.class}"
56
- end
57
- end
58
-
59
- ##
60
- # Parse user input
61
- def _ask
62
- input = STDIN.gets.chomp
63
- input = @default if input.empty? && @default
64
- @fd.puts if @secret
65
- input
66
- end
67
-
68
- ##
69
- # Track attempt counter
70
- def check_counter
71
- return if @attempts.nil?
72
- @attempts -= 1
73
- raise ArgumentError, 'No valid input provided' if @attempts == 0
74
- end
75
-
76
- ##
77
- # Disable terminal display of user input
78
- def disable_echo
79
- toggle_echo false
80
- end
81
-
82
- ##
83
- # Enable terminal display of user input
84
- def enable_echo
85
- toggle_echo true
86
- end
87
-
88
- ##
89
- # Toggle terminal display of user input
90
- def toggle_echo(state)
91
- setting = state ? '' : '-'
92
- `stty #{setting}echo`
93
- rescue
94
- nil
95
- end
96
- end
97
19
  end
20
+
21
+ require 'userinput/prompt'
22
+ require 'userinput/boolean'
@@ -0,0 +1,15 @@
1
+ module UserInput
2
+ ##
3
+ # Helper class for asking yes/no questions
4
+ class Boolean < Prompt
5
+ def initialize(params = {})
6
+ super
7
+ @validation = /(y|yes|n|no)/i
8
+ @separator = ' [y/n]?' if @separator == '?'
9
+ end
10
+
11
+ def ask
12
+ super =~ /y/i ? true : false
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ module UserInput
2
+ MESSAGE_TEMPLATE = '%{message}%{separator} %{default}'.freeze
3
+
4
+ ##
5
+ # Prompt object
6
+ class Prompt
7
+ ##
8
+ # Build new prompt object and set defaults
9
+ def initialize(params = {}, &block)
10
+ @attempts = params[:attempts]
11
+ @message = params[:message] || ''
12
+ @separator = params[:separator] || '?'
13
+ @default = params[:default]
14
+ @secret = params[:secret] || false
15
+ @fd = params[:fd] || STDOUT
16
+ @validation = block || params[:validation]
17
+ end
18
+
19
+ ##
20
+ # Request user input
21
+ def ask
22
+ @fd.print full_message
23
+ disable_echo if @secret
24
+
25
+ input = _ask
26
+ return input if valid(input)
27
+
28
+ check_counter
29
+ ask
30
+ ensure
31
+ enable_echo if @secret
32
+ end
33
+
34
+ private
35
+
36
+ def full_message
37
+ MESSAGE_TEMPLATE % {
38
+ message: @message,
39
+ separator: @separator,
40
+ default: @default.nil? ? '' : "[#{@default}] "
41
+ }
42
+ end
43
+
44
+ ##
45
+ # Validate user input
46
+ def valid(input)
47
+ return true unless @validation
48
+ _, method = VALIDATIONS.find { |klass, _| @validation.is_a? klass }
49
+ return @validation.send(method, input) if method
50
+ raise "Supported validation type not provided #{@validation.class}"
51
+ end
52
+
53
+ ##
54
+ # Parse user input
55
+ def _ask
56
+ input = STDIN.gets.chomp
57
+ input = @default if input.empty? && @default
58
+ @fd.puts if @secret
59
+ input
60
+ end
61
+
62
+ ##
63
+ # Track attempt counter
64
+ def check_counter
65
+ return if @attempts.nil?
66
+ @attempts -= 1
67
+ raise ArgumentError, 'No valid input provided' if @attempts.zero?
68
+ end
69
+
70
+ ##
71
+ # Disable terminal display of user input
72
+ def disable_echo
73
+ toggle_echo false
74
+ end
75
+
76
+ ##
77
+ # Enable terminal display of user input
78
+ def enable_echo
79
+ toggle_echo true
80
+ end
81
+
82
+ ##
83
+ # Toggle terminal display of user input
84
+ def toggle_echo(state)
85
+ setting = state ? '' : '-'
86
+ `stty #{setting}echo`
87
+ rescue
88
+ nil
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe UserInput do
4
+ describe UserInput::Prompt do
5
+ let(:subject) do
6
+ UserInput::Prompt.new(
7
+ attempts: 2,
8
+ message: '_msg',
9
+ default: '_default'
10
+ )
11
+ end
12
+
13
+ describe '#new' do
14
+ it 'makes a new Prompt object' do
15
+ expect(subject).to be_an_instance_of UserInput::Prompt
16
+ end
17
+ end
18
+
19
+ describe '#ask' do
20
+ it 'prompts for user input' do
21
+ allow(STDIN).to receive(:gets) { "_answer\n" }
22
+ expect(STDOUT).to receive(:print).with('_msg? [_default] ')
23
+ expect(subject.ask).to eql '_answer'
24
+ end
25
+
26
+ it 'returns the default if available' do
27
+ allow(STDIN).to receive(:gets) { "\n" }
28
+ expect(STDOUT).to receive(:print).with('_msg? [_default] ')
29
+ expect(subject.ask).to eql '_default'
30
+ end
31
+
32
+ context 'when provided a Regexp' do
33
+ it 'validates input' do
34
+ prompt = UserInput::Prompt.new(
35
+ message: '_msg',
36
+ validation: /[0-9]+/
37
+ )
38
+ allow(STDIN).to receive(:gets).and_return("_str\n", "29\n")
39
+ expect(STDOUT).to receive(:print).with('_msg? ').twice
40
+ expect(prompt.ask).to eql '29'
41
+ end
42
+ end
43
+ context 'when provided a code block' do
44
+ it 'validates input' do
45
+ prompt = UserInput::Prompt.new { |x| x == 'correct' }
46
+ allow(STDIN).to receive(:gets).and_return("_str\n", "correct\n")
47
+ expect(STDOUT).to receive(:print).with('? ').twice
48
+ expect(prompt.ask).to eql 'correct'
49
+ end
50
+ end
51
+ context 'when provided an Enumerable' do
52
+ it 'validates input' do
53
+ prompt = UserInput::Prompt.new(
54
+ message: '_msg',
55
+ validation: %w(a b c)
56
+ )
57
+ allow(STDIN).to receive(:gets).and_return("_str\n", "a\n")
58
+ expect(STDOUT).to receive(:print).with('_msg? ').twice
59
+ expect(prompt.ask).to eql 'a'
60
+ end
61
+ end
62
+ context 'when provided an unsupported validation method' do
63
+ it 'raises a RuntimeError' do
64
+ prompt = UserInput::Prompt.new(validation: 28)
65
+ allow(STDIN).to receive(:gets).and_return("_str\n")
66
+ expect(STDOUT).to receive(:print).with('? ')
67
+ expect { prompt.ask }.to raise_error RuntimeError
68
+ end
69
+ end
70
+
71
+ it 'raises an error if max attempts is reached' do
72
+ prompt = UserInput::Prompt.new(attempts: 2) { false }
73
+ allow(STDIN).to receive(:gets).and_return("_str\n", "_foo\n")
74
+ expect(STDOUT).to receive(:print).with('? ').twice
75
+ expect { prompt.ask }.to raise_error ArgumentError
76
+ end
77
+ end
78
+
79
+ it 'disables echo for secret input' do
80
+ prompt = UserInput::Prompt.new(secret: true)
81
+ allow(STDIN).to receive(:gets).and_return("_str\n")
82
+ expect(STDOUT).to receive(:print).with('? ')
83
+ expect(prompt.ask).to eql '_str'
84
+ end
85
+
86
+ it 'accepts an alternate file descriptor for output' do
87
+ target = StringIO.new
88
+ prompt = UserInput::Prompt.new(fd: target)
89
+ allow(STDIN).to receive(:gets).and_return("_str\n")
90
+ expect(target).to receive(:print).with('? ')
91
+ expect(prompt.ask).to eql '_str'
92
+ end
93
+ end
94
+ end
@@ -6,84 +6,4 @@ describe UserInput do
6
6
  expect(UserInput.new).to be_an_instance_of UserInput::Prompt
7
7
  end
8
8
  end
9
-
10
- describe UserInput::Prompt do
11
- let(:subject) do
12
- UserInput::Prompt.new(
13
- attempts: 2,
14
- message: '_msg',
15
- default: '_default'
16
- )
17
- end
18
-
19
- describe '#new' do
20
- it 'makes a new Prompt object' do
21
- expect(subject).to be_an_instance_of UserInput::Prompt
22
- end
23
- end
24
-
25
- describe '#ask' do
26
- it 'prompts for user input' do
27
- allow(STDIN).to receive(:gets) { "_answer\n" }
28
- expect(STDOUT).to receive(:print).with('_msg? [_default] ')
29
- expect(subject.ask).to eql '_answer'
30
- end
31
-
32
- it 'returns the default if available' do
33
- allow(STDIN).to receive(:gets) { "\n" }
34
- expect(STDOUT).to receive(:print).with('_msg? [_default] ')
35
- expect(subject.ask).to eql '_default'
36
- end
37
-
38
- context 'when provided a Regexp' do
39
- it 'validates input' do
40
- prompt = UserInput::Prompt.new(
41
- message: '_msg',
42
- validation: /[0-9]+/
43
- )
44
- allow(STDIN).to receive(:gets).and_return("_str\n", "29\n")
45
- expect(STDOUT).to receive(:print).with('_msg? ').twice
46
- expect(prompt.ask).to eql '29'
47
- end
48
- end
49
- context 'when provided a code block' do
50
- it 'validates input' do
51
- prompt = UserInput::Prompt.new { |x| x == 'correct' }
52
- allow(STDIN).to receive(:gets).and_return("_str\n", "correct\n")
53
- expect(STDOUT).to receive(:print).with('? ').twice
54
- expect(prompt.ask).to eql 'correct'
55
- end
56
- end
57
- context 'when provided an unsupported validation method' do
58
- it 'raises a RuntimeError' do
59
- prompt = UserInput::Prompt.new(validation: 28)
60
- allow(STDIN).to receive(:gets).and_return("_str\n")
61
- expect(STDOUT).to receive(:print).with('? ')
62
- expect { prompt.ask }.to raise_error RuntimeError
63
- end
64
- end
65
-
66
- it 'raises an error if max attempts is reached' do
67
- prompt = UserInput::Prompt.new(attempts: 2) { false }
68
- allow(STDIN).to receive(:gets).and_return("_str\n", "_foo\n")
69
- expect(STDOUT).to receive(:print).with('? ').twice
70
- expect { prompt.ask }.to raise_error ArgumentError
71
- end
72
- end
73
-
74
- it 'disables echo for secret input' do
75
- prompt = UserInput::Prompt.new(secret: true)
76
- allow(STDIN).to receive(:gets).and_return("_str\n")
77
- expect(STDOUT).to receive(:print).with('? ')
78
- expect(prompt.ask).to eql '_str'
79
- end
80
-
81
- it 'accepts an alternate file descriptor for output' do
82
- target = StringIO.new
83
- prompt = UserInput::Prompt.new(fd: target)
84
- allow(STDIN).to receive(:gets).and_return("_str\n")
85
- expect(target).to receive(:print).with('? ')
86
- expect(prompt.ask).to eql '_str'
87
- end
88
- end
89
9
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'userinput'
3
- s.version = '1.0.1'
3
+ s.version = '1.0.2'
4
4
  s.date = Time.now.strftime("%Y-%m-%d")
5
5
 
6
6
  s.summary = 'Simple user input library'
@@ -13,9 +13,9 @@ Gem::Specification.new do |s|
13
13
  s.files = `git ls-files`.split
14
14
  s.test_files = `git ls-files spec/*`.split
15
15
 
16
- s.add_development_dependency 'rubocop', '~> 0.37.0'
17
- s.add_development_dependency 'rake', '~> 10.5.0'
16
+ s.add_development_dependency 'rubocop', '~> 0.47.0'
17
+ s.add_development_dependency 'rake', '~> 12.0.0'
18
18
  s.add_development_dependency 'codecov', '~> 0.1.1'
19
- s.add_development_dependency 'rspec', '~> 3.4.0'
20
- s.add_development_dependency 'fuubar', '~> 2.0.0'
19
+ s.add_development_dependency 'rspec', '~> 3.5.0'
20
+ s.add_development_dependency 'fuubar', '~> 2.2.0'
21
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: userinput
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Les Aker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-13 00:00:00.000000000 Z
11
+ date: 2017-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.37.0
19
+ version: 0.47.0
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.37.0
26
+ version: 0.47.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 10.5.0
33
+ version: 12.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 10.5.0
40
+ version: 12.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: codecov
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,34 +58,35 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.4.0
61
+ version: 3.5.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.4.0
68
+ version: 3.5.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: fuubar
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 2.0.0
75
+ version: 2.2.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 2.0.0
82
+ version: 2.2.0
83
83
  description: Provides a prompt object for requesting user input
84
84
  email: me@lesaker.org
85
85
  executables: []
86
86
  extensions: []
87
87
  extra_rdoc_files: []
88
88
  files:
89
+ - ".circle-ruby"
89
90
  - ".gitignore"
90
91
  - ".prospectus"
91
92
  - ".rspec"
@@ -97,7 +98,10 @@ files:
97
98
  - Rakefile
98
99
  - circle.yml
99
100
  - lib/userinput.rb
101
+ - lib/userinput/boolean.rb
102
+ - lib/userinput/prompt.rb
100
103
  - spec/spec_helper.rb
104
+ - spec/userinput/prompt_spec.rb
101
105
  - spec/userinput_spec.rb
102
106
  - userinput.gemspec
103
107
  homepage: https://github.com/akerl/userinput
@@ -120,10 +124,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
124
  version: '0'
121
125
  requirements: []
122
126
  rubyforge_project:
123
- rubygems_version: 2.5.1
127
+ rubygems_version: 2.5.2
124
128
  signing_key:
125
129
  specification_version: 4
126
130
  summary: Simple user input library
127
131
  test_files:
128
132
  - spec/spec_helper.rb
133
+ - spec/userinput/prompt_spec.rb
129
134
  - spec/userinput_spec.rb