interactive 0.5.0 → 0.6.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: 9b4efce0bf189c7b0a8adc60366457b50510cbe1
4
- data.tar.gz: 3e19e3f985a2b18722dc99ade99a3ef970feafa2
3
+ metadata.gz: 9619d284dc3cc786e129bd08d223793905f26e7a
4
+ data.tar.gz: df6b8e044710d93f821081f7f40abdeb9ce8c213
5
5
  SHA512:
6
- metadata.gz: d6f3f4fc0e3b08451d43c5fa562999199ab2e890fcdb30fccf243da1269bf434abe8643936fcd01c34ba42ae6dab571be97945c5ca4f54e9811d6c781458094f
7
- data.tar.gz: 50b82f8817f6706fae656063f65a66c1af98c2391c009552d351ca585eb369a8dd71c33d04335a62b7b43335f18c171011f9c40369557a1e45c3862f0a5113f1
6
+ metadata.gz: e71708a64f3f61a9be18cb8757f0ec0c25fbc9600b74fc676803d60bf558150767f50381b50d1e27223b586a726c892fffd06e7baf96189db8af98cd0f047186
7
+ data.tar.gz: 55e31021ea77758ba04dd25b81551b9f974f8b6763b2ad240c56dbb806a2b8b7ec163a6f22ac7433d80eca41557efcab8377f5e1194afdef446441815114506d
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ v0.6.0 -- Sat Mar 28 22:32:12 EDT 2015
2
+ --------------------------------------
3
+ - added support for displaying tabular data
4
+
1
5
  v0.5.0 -- Fri Mar 20 20:01:26 EDT 2015
2
6
  --------------------------------------
3
7
  - added `Question#reask`.
data/README.md CHANGED
@@ -154,6 +154,46 @@ Which path do you want to use? [0/1/c]
154
154
  c -- cancel
155
155
  ```
156
156
 
157
+ You could also present tabular data:
158
+
159
+ ```ruby
160
+ character_1 = OpenStruct.new(name: 'Frank Underwood', job: 'Vice President')
161
+ character_2 = OpenStruct.new(name: 'Zoe Barnes', job: 'Reporter')
162
+ characters_list = [character_1, character_2]
163
+
164
+ iq = Question.new do |q|
165
+ q.question = "Which House of Cards character are you interested in?"
166
+ q.options = [characters_list, :cancel]
167
+ q.columns = [:index, :name, :job]
168
+ end
169
+
170
+ iq.ask do |response|
171
+ if response.whole_number?
172
+ # response.to_i will convert the response string to an integer.
173
+ # useful for getting the index (i.e. options_list[response.to_i])
174
+ elsif response.cancel?
175
+ # do stuff to cancel...
176
+ end
177
+ end
178
+ ```
179
+
180
+ This will ask the question with a table:
181
+
182
+ ```
183
+ Which House of Cards character are you interested in? [0/1/c]
184
+ c -- cancel
185
+ +-------+-----------------+----------------+
186
+ | index | name | job |
187
+ +-------+-----------------+----------------+
188
+ | 0 | Frank Underwood | Vice President |
189
+ | 1 | Zoe Barnes | Reporter |
190
+ +-------+-----------------+----------------+
191
+ ```
192
+
193
+ Note that the second, and up to the last, value of the `columns` list are the
194
+ messages that get sent to each object in the `objects` list of the `options`
195
+ array.
196
+
157
197
  ### Question#reask
158
198
  ```ruby
159
199
 
data/interactive.gemspec CHANGED
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency 'rspec', '~> 3.1'
22
22
  spec.add_development_dependency 'byebug', '~> 3.5'
23
23
  spec.add_development_dependency 'bundler'
24
+ spec.add_runtime_dependency 'terminal-table', '~> 1.4', '>= 1.4.5'
24
25
  end
data/lib/interactive.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "interactive/version"
2
2
  require "delegate"
3
+ require "terminal-table"
3
4
  require "interactive/option"
4
5
  require "interactive/options"
5
6
  require "interactive/question_with_eager_full_explanation"
@@ -3,8 +3,14 @@ require 'interactive'
3
3
 
4
4
  module Interactive
5
5
  module_function
6
- def Options(options=[])
7
- options.empty? ? EmptyOptions.new([]) : NonEmptyOptions.new(options)
6
+ def Options(options=[], columns=[])
7
+ if options.empty?
8
+ EmptyOptions.new([])
9
+ elsif Array(columns).any?
10
+ TabularOptions.new(options, columns)
11
+ else
12
+ NonEmptyOptions.new(options)
13
+ end
8
14
  end
9
15
 
10
16
  class NonEmptyOptions < SimpleDelegator
@@ -55,6 +61,57 @@ module Interactive
55
61
  end
56
62
  end
57
63
 
64
+ class TabularOptions < NonEmptyOptions
65
+ def initialize(options, columns)
66
+ @options = options
67
+ @headings = columns.clone
68
+ columns.shift
69
+ @table_columns = columns
70
+ super(@options)
71
+ end
72
+
73
+ def shortcuts_meanings
74
+ non_table_shortcuts_meanings + table_shortcuts_meanings
75
+ end
76
+
77
+ private
78
+
79
+ def non_table_shortcuts_meanings
80
+ non_table_options.inject("") {|accum, opt| "#{accum} #{opt[0]} -- #{opt}\n"}
81
+ end
82
+
83
+ def table_shortcuts_meanings
84
+ @table = Terminal::Table.new(headings: @headings)
85
+ @table.align_column(0, :right)
86
+ rows.each {|row| @table << row}
87
+ @table.to_s
88
+ end
89
+
90
+ def non_table_options
91
+ @options.reject do |opt|
92
+ @table_columns.inject(true) {|accum, col| accum && opt.value.respond_to?(col) }
93
+ end
94
+ end
95
+
96
+ def table_options
97
+ @options.select do |opt|
98
+ opt_responds_to_each_column?(opt)
99
+ end
100
+ end
101
+
102
+ def rows
103
+ table_options.map.with_index do |opt, index|
104
+ @table_columns.inject([]) do |accum, col|
105
+ accum << opt.value.send(col)
106
+ end.insert(0, index)
107
+ end
108
+ end
109
+
110
+ def opt_responds_to_each_column?(opt)
111
+ @table_columns.inject(true) {|accum, col| accum && opt.value.respond_to?(col) }
112
+ end
113
+ end
114
+
58
115
 
59
116
  class EmptyOptions < SimpleDelegator
60
117
  def initialize(options)
@@ -3,16 +3,20 @@ require 'forwardable'
3
3
  module Interactive
4
4
  class Question
5
5
  extend Forwardable
6
- attr_accessor :question, :options
6
+ attr_accessor :question, :options, :columns
7
7
  def_delegators :@question_type, :reask!
8
8
 
9
9
  def initialize(&block)
10
10
  yield self
11
11
 
12
- @options = Interactive::Options(Array(@options))
12
+ @options = Interactive::Options(Array(@options), @columns)
13
13
 
14
14
  raise ArgumentError, "question cannot be nil nor empty." if question.nil? || question.empty?
15
- @question_type = @options.has_hash? ? QuestionWithEagerFullExplanation.new(self) : QuestionWithLazyFullExplanation.new(self)
15
+ if @columns || @options.has_hash?
16
+ @question_type = QuestionWithEagerFullExplanation.new(self)
17
+ else
18
+ @question_type = QuestionWithLazyFullExplanation.new(self)
19
+ end
16
20
  end
17
21
 
18
22
  def ask_and_wait_for_valid_response(&block)
@@ -1,3 +1,3 @@
1
1
  module Interactive
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.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-21 00:00:00.000000000 Z
11
+ date: 2015-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,26 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: terminal-table
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.4'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 1.4.5
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '1.4'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.4.5
69
89
  description:
70
90
  email:
71
91
  - edderic@gmail.com