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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ff5d5591031e2228dd4f07ed37081474cb1fb92
4
- data.tar.gz: 0ef086b79a0b7d5cbf3c3053b3239a443a8c9414
3
+ metadata.gz: f2c6959fba0126e77b3a9147f7f23435a19064cf
4
+ data.tar.gz: 7418c32a98aacddb6df983502f09abdf738f2d5c
5
5
  SHA512:
6
- metadata.gz: 7d838a2550a4560dc1e63543a8bcb58108ebca75ea3c9b8c38f10bf5cf8cc3fdbde9979c555db23b398034aa5d92b369c87fceefeb2b21b7b2e83500ecc70a5f
7
- data.tar.gz: 15c8b7095256e042bd2d882f7f2f1ad43165e590cb1fe60dd1eaaa6f40789e49db849d78b16b99a3f6b5b264dbee0578555c9cb08dbddb28ed1780828a681917
6
+ metadata.gz: 4fe3a14aa9871323c85e1045d9eb0341422ec9489f49484d30756555e053eb1b7ec1c93a431c407b7294f87c9bd302936b7ddac18ef0a6cde98c816def50a0b1
7
+ data.tar.gz: a3144758369854cbf2790e558147f2a6bcd2f7f3269920e98c37cc08c67519b496fc3a3ff813cdb0534ee09709684eece520276616662b24cf4a9478f9b74d64
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.0.0
4
+ - 2.1.0
3
5
  - 2.2.0
@@ -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 'interactive_question'
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 interactive_question
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 = "What do you want to do?"
27
- ques.options = [:add, :edit, :update, :remove]
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.add?
36
- # add the thingymajigger
37
- elsif response.edit?
38
- # edit the thingymajigger
39
- elsif response.update?
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
- # => What do you want to do? [a/e/u/r]
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
- # => What do you want to do? [a/e/u/r]
57
- # => a -- add
58
- # => e -- edit
59
- # => u -- update
60
- # => r -- remove
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/[my-github-username]/interactive_question/fork )
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
@@ -1,2 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
+ desc 'Run specs'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+ task :default => [:spec]
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
@@ -1,4 +1,6 @@
1
1
  require "interactive/version"
2
+ require "interactive/option"
3
+ require "interactive/options"
2
4
  require 'interactive/question'
3
5
  require 'interactive/response'
4
6
 
@@ -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
@@ -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
- resp = NullResponse.new
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
- end
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
@@ -1,26 +1,49 @@
1
+ require 'interactive'
2
+
1
3
  module Interactive
2
4
  class Response
3
5
  def initialize(*args)
4
- if args.first.class.ancestors.include?(Enumerable)
5
- @args = args.first
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 "#{arg}?" do
17
- @_response.match(/^#{arg[0]}$/i) ? true : false
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
@@ -1,3 +1,3 @@
1
1
  module Interactive
2
- VERSION = "0.0.0"
2
+ VERSION = "0.1.0"
3
3
  end
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.0.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-14 00:00:00.000000000 Z
11
+ date: 2015-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.8'
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: '1.8'
26
+ version: '10.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
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: '10.0'
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