interactive 0.0.0 → 0.1.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: 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