interactive 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.markdown +6 -0
- data/README.md +33 -18
- data/Rakefile +4 -0
- data/interactive.gemspec +3 -1
- data/lib/interactive.rb +2 -0
- data/lib/interactive/option.rb +45 -0
- data/lib/interactive/options.rb +40 -0
- data/lib/interactive/question.rb +9 -27
- data/lib/interactive/response.rb +33 -10
- data/lib/interactive/version.rb +1 -1
- metadata +39 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2c6959fba0126e77b3a9147f7f23435a19064cf
|
4
|
+
data.tar.gz: 7418c32a98aacddb6df983502f09abdf738f2d5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fe3a14aa9871323c85e1045d9eb0341422ec9489f49484d30756555e053eb1b7ec1c93a431c407b7294f87c9bd302936b7ddac18ef0a6cde98c816def50a0b1
|
7
|
+
data.tar.gz: a3144758369854cbf2790e558147f2a6bcd2f7f3269920e98c37cc08c67519b496fc3a3ff813cdb0534ee09709684eece520276616662b24cf4a9478f9b74d64
|
data/.travis.yml
CHANGED
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
v0.1.0 -- Mon Mar 16 07:17:53 EDT 2015
|
2
|
+
--------------------------------------
|
3
|
+
- Added support for handling ranges.
|
4
|
+
- Useful for processing responses of questions like "Which item do you want to
|
5
|
+
use?", where whole number responses such as "1", "2", etc. makes sense.
|
6
|
+
- Refactored, DRY'er.
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
# Interactive
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/interactive.svg)](http://badge.fury.io/rb/interactive)
|
3
|
+
[![Build Status](https://travis-ci.org/Edderic/interactive.svg)](https://travis-ci.org/Edderic/interactive)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/Edderic/interactive/badges/gpa.svg)](https://codeclimate.com/github/Edderic/interactive)
|
5
|
+
|
2
6
|
This is a helper module to assist in interactive question-answering events in the command line.
|
3
7
|
|
4
8
|
## Installation
|
@@ -6,7 +10,7 @@ This is a helper module to assist in interactive question-answering events in th
|
|
6
10
|
Add this line to your application's Gemfile:
|
7
11
|
|
8
12
|
```ruby
|
9
|
-
gem '
|
13
|
+
gem 'interactive'
|
10
14
|
```
|
11
15
|
|
12
16
|
And then execute:
|
@@ -15,7 +19,7 @@ And then execute:
|
|
15
19
|
|
16
20
|
Or install it yourself as:
|
17
21
|
|
18
|
-
$ gem install
|
22
|
+
$ gem install interactive
|
19
23
|
|
20
24
|
## Usage
|
21
25
|
|
@@ -23,21 +27,24 @@ If you want to ask a user a question expecting certain answers:
|
|
23
27
|
|
24
28
|
```ruby
|
25
29
|
question = Interactive::Question.new do |ques|
|
26
|
-
ques.question = "
|
27
|
-
ques.options = [
|
30
|
+
ques.question = "Which item do you want to use?"
|
31
|
+
ques.options = [1..3, :cancel, :quit]
|
28
32
|
end
|
29
33
|
```
|
30
34
|
|
31
|
-
You can run the loop and wait for a valid response
|
35
|
+
You can run the loop and wait for a valid response and do query methods on the
|
36
|
+
response:
|
32
37
|
|
33
38
|
```ruby
|
34
39
|
question.ask_and_wait_for_valid_response do |response|
|
35
|
-
if response.
|
36
|
-
#
|
37
|
-
elsif response.
|
38
|
-
#
|
39
|
-
elsif response.
|
40
|
-
# etc
|
40
|
+
if response.whole_num_1?
|
41
|
+
# do stuff if user responded with "1"
|
42
|
+
elsif response.whole_num?
|
43
|
+
# do stuff if user responded with "1", "2", or "3"
|
44
|
+
elsif response.cancel?
|
45
|
+
# do stuff if user responded with "c", etc.
|
46
|
+
elsif response.quit?
|
47
|
+
# do stuff if user responded with "q", etc.
|
41
48
|
end
|
42
49
|
end
|
43
50
|
```
|
@@ -45,7 +52,14 @@ end
|
|
45
52
|
That will ask the question appended by the shortcuts:
|
46
53
|
|
47
54
|
```ruby
|
48
|
-
# =>
|
55
|
+
# => "Which item do you want to use? [1/2/3/c/q]"
|
56
|
+
```
|
57
|
+
|
58
|
+
If the response is valid:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
$ a
|
62
|
+
# => response.add? will return true
|
49
63
|
```
|
50
64
|
|
51
65
|
If the response is invalid, it prints out the question and goes into detail as
|
@@ -53,11 +67,12 @@ to what the shortcuts stand for:
|
|
53
67
|
|
54
68
|
```ruby
|
55
69
|
$ bad-response
|
56
|
-
# =>
|
57
|
-
# =>
|
58
|
-
# =>
|
59
|
-
# =>
|
60
|
-
# =>
|
70
|
+
# => Which item do you want to use? [1/2/3/c/q]
|
71
|
+
# => 1 -- 1
|
72
|
+
# => 2 -- 2
|
73
|
+
# => 3 -- 3
|
74
|
+
# => c -- cancel
|
75
|
+
# => q -- quit
|
61
76
|
```
|
62
77
|
|
63
78
|
## Development
|
@@ -68,7 +83,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
68
83
|
|
69
84
|
## Contributing
|
70
85
|
|
71
|
-
1. Fork it ( https://github.com/
|
86
|
+
1. Fork it ( https://github.com/edderic/interactive/fork )
|
72
87
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
73
88
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
74
89
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
data/interactive.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_development_dependency "bundler", "~> 1.8"
|
21
20
|
spec.add_development_dependency "rake", "~> 10.0"
|
21
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
22
|
+
spec.add_development_dependency 'byebug', '~> 3.5'
|
23
|
+
spec.add_development_dependency 'bundler'
|
22
24
|
end
|
data/lib/interactive.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Interactive
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def Option(option)
|
7
|
+
if option.to_s.match(/^\d+$/)
|
8
|
+
@option = WholeNumberOption.new(option)
|
9
|
+
else
|
10
|
+
@option = WordOption.new(option)
|
11
|
+
end
|
12
|
+
|
13
|
+
@option
|
14
|
+
end
|
15
|
+
|
16
|
+
class WholeNumberOption < SimpleDelegator
|
17
|
+
def initialize(option)
|
18
|
+
@option = option
|
19
|
+
super(@option)
|
20
|
+
end
|
21
|
+
|
22
|
+
def shortcut_value
|
23
|
+
@option
|
24
|
+
end
|
25
|
+
|
26
|
+
def query_method_name
|
27
|
+
"whole_number_#{shortcut_value}?"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class WordOption < SimpleDelegator
|
32
|
+
def initialize(option)
|
33
|
+
@option = option
|
34
|
+
super(@option)
|
35
|
+
end
|
36
|
+
|
37
|
+
def shortcut_value
|
38
|
+
@option.to_s[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
def query_method_name
|
42
|
+
"#{@option}?"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Interactive
|
4
|
+
class Options < SimpleDelegator
|
5
|
+
include Interactive
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
flatten_ranges(options)
|
10
|
+
wrap_each_option
|
11
|
+
super(@options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def shortcuts_string
|
15
|
+
"[#{first_chars_without_last_slash(first_chars)}]"
|
16
|
+
end
|
17
|
+
|
18
|
+
def shortcuts_meanings
|
19
|
+
options.inject("") { |accum, opt| "#{accum} #{opt.shortcut_value} -- #{opt}\n"}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def flatten_ranges(options)
|
25
|
+
@options = options.inject([]) {|accum, opt| opt.respond_to?(:to_a) ? accum | opt.to_a : accum << opt}
|
26
|
+
end
|
27
|
+
|
28
|
+
def wrap_each_option
|
29
|
+
@options.map! {|option| Option(option) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def first_chars
|
33
|
+
options.inject("") { |accum, opt| "#{accum}#{ opt.shortcut_value}/" }
|
34
|
+
end
|
35
|
+
|
36
|
+
def first_chars_without_last_slash(first_chars)
|
37
|
+
first_chars[0..first_chars.length-2]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/interactive/question.rb
CHANGED
@@ -4,23 +4,21 @@ module Interactive
|
|
4
4
|
|
5
5
|
def initialize(&block)
|
6
6
|
yield self
|
7
|
+
|
8
|
+
@options = Interactive::Options.new(Array(@options))
|
9
|
+
|
10
|
+
raise ArgumentError, "question cannot be nil nor empty." if question.nil? || question.empty?
|
11
|
+
raise ArgumentError, "options cannot be empty." if options.empty?
|
7
12
|
end
|
8
13
|
|
9
14
|
def ask_and_wait_for_valid_response(&block)
|
10
|
-
|
11
|
-
|
12
|
-
while resp.invalid? do
|
13
|
-
puts "#{question} #{shortcuts_string}"
|
15
|
+
loop do
|
16
|
+
puts "#{question} #{options.shortcuts_string}"
|
14
17
|
resp = Interactive::Response.new(options)
|
15
|
-
puts shortcuts_meanings if resp.invalid?
|
18
|
+
puts options.shortcuts_meanings if resp.invalid?
|
16
19
|
|
17
20
|
yield resp
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
class NullResponse
|
22
|
-
def invalid?
|
23
|
-
true
|
21
|
+
break unless resp.invalid?
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
@@ -29,21 +27,5 @@ module Interactive
|
|
29
27
|
def response
|
30
28
|
STDIN.gets.chomp
|
31
29
|
end
|
32
|
-
|
33
|
-
def shortcuts_meanings
|
34
|
-
options.inject("") { |accum, opt| "#{accum} #{opt[0]} -- #{opt}\n"}
|
35
|
-
end
|
36
|
-
|
37
|
-
def options_first_chars
|
38
|
-
options.inject("") { |accum, opt| "#{accum}#{opt[0]}/" }
|
39
|
-
end
|
40
|
-
|
41
|
-
def shortcuts_string
|
42
|
-
"[#{options_first_chars_without_last_slash(options_first_chars)}]"
|
43
|
-
end
|
44
|
-
|
45
|
-
def options_first_chars_without_last_slash(options_first_chars)
|
46
|
-
options_first_chars[0..options_first_chars.length-2]
|
47
|
-
end
|
48
30
|
end
|
49
31
|
end
|
data/lib/interactive/response.rb
CHANGED
@@ -1,26 +1,49 @@
|
|
1
|
+
require 'interactive'
|
2
|
+
|
1
3
|
module Interactive
|
2
4
|
class Response
|
3
5
|
def initialize(*args)
|
4
|
-
|
5
|
-
|
6
|
-
else
|
7
|
-
@args = args
|
8
|
-
end
|
9
|
-
|
10
|
-
raise ArgumentError, "wrong number of arguments (need at least two arguments)" if @args.length == 1
|
11
|
-
raise ArgumentError, "may not use :invalid or 'invalid' as an argument. May not overwrite Interactive::Response#invalid" if @args.map(&:to_s).include?('invalid')
|
6
|
+
@args = Array(args).flatten
|
7
|
+
check_validity
|
12
8
|
|
13
9
|
@_response = STDIN.gets.chomp
|
14
10
|
|
11
|
+
define_methods
|
12
|
+
define_invalid
|
13
|
+
define_whole_number
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def check_validity
|
19
|
+
raise ArgumentError, "may not use :invalid or 'invalid' as an argument. Private method." if @args.map(&:to_s).include?('invalid')
|
20
|
+
raise ArgumentError, "may not use :whole_number or 'whole_number' as an argument. Private method." if @args.map(&:to_s).include?('whole_number')
|
21
|
+
raise ArgumentError, "may not have keyword options that have the same first letter." if first_chars_not_unique
|
22
|
+
raise ArgumentError, "wrong number of arguments (need at least two arguments)." if @args.length < 2
|
23
|
+
end
|
24
|
+
|
25
|
+
def define_methods
|
15
26
|
@args.each do |arg|
|
16
|
-
define_singleton_method
|
17
|
-
@_response.match(/^#{arg
|
27
|
+
define_singleton_method arg.query_method_name do
|
28
|
+
@_response.strip.match(/^#{arg.shortcut_value}$/i) ? true : false
|
18
29
|
end
|
19
30
|
end
|
31
|
+
end
|
20
32
|
|
33
|
+
def define_invalid
|
21
34
|
define_singleton_method "invalid?" do
|
22
35
|
methods(false).reject {|m| m == :invalid? }.none? {|m| send(m) }
|
23
36
|
end
|
24
37
|
end
|
38
|
+
|
39
|
+
def define_whole_number
|
40
|
+
define_singleton_method "whole_number?" do
|
41
|
+
methods(false).select {|m| m.to_s.match(/whole_number_\d+/)}.any? {|m| send(m) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def first_chars_not_unique
|
46
|
+
@args.map{|arg| arg.shortcut_value }.uniq.length != @args.length
|
47
|
+
end
|
25
48
|
end
|
26
49
|
end
|
data/lib/interactive/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interactive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edderic Ugaddan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '10.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: '
|
26
|
+
version: '10.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3.1'
|
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: '
|
40
|
+
version: '3.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
41
69
|
description:
|
42
70
|
email:
|
43
71
|
- edderic@gmail.com
|
@@ -48,6 +76,7 @@ files:
|
|
48
76
|
- ".gitignore"
|
49
77
|
- ".rspec"
|
50
78
|
- ".travis.yml"
|
79
|
+
- CHANGELOG.markdown
|
51
80
|
- CODE_OF_CONDUCT.md
|
52
81
|
- Gemfile
|
53
82
|
- LICENSE.txt
|
@@ -57,6 +86,8 @@ files:
|
|
57
86
|
- bin/setup
|
58
87
|
- interactive.gemspec
|
59
88
|
- lib/interactive.rb
|
89
|
+
- lib/interactive/option.rb
|
90
|
+
- lib/interactive/options.rb
|
60
91
|
- lib/interactive/question.rb
|
61
92
|
- lib/interactive/response.rb
|
62
93
|
- lib/interactive/version.rb
|