userinput 1.0.1 → 1.0.2

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: 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