goodread 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5a293ce19c1885ff9c90422f79721f1f0842374
4
+ data.tar.gz: a2756e32cc34d605cfdd730ee39e2e08938b5276
5
+ SHA512:
6
+ metadata.gz: bfa940e289ac827d87c095f9ca4a3452ae458b5029d75d35a64e607982b3366ed0054022ec39b1f16cce961565f62c2a9042166fed0dd0fb3f258f6ee949fc7f
7
+ data.tar.gz: c0c93672822cb4b2579b63e2ae8f4066a5f3c20b2c6549b009ec185b1d9aac2b287a70d7249a22df542d69e9d771e18adac6023d34a60308a4f962534976baf3
data/.gitignore ADDED
@@ -0,0 +1,54 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ # Extra
53
+ Gemfile.lock
54
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ sudo:
2
+ false
3
+
4
+ language:
5
+ ruby
6
+
7
+ rvm:
8
+ - 2.1.2
9
+
10
+ before_install:
11
+ gem install bundler -v 1.14.6
12
+
13
+ deploy:
14
+ provider: rubygems
15
+ gem: goodread
16
+ on:
17
+ tags: true
18
+ api_key:
19
+ secure: 1Sip+AvVHYYcr+AwH8fysiDTm8a0E2jZZjk7raNGuX17vllz+q3vWLRIX+qsBcdLyY5nKwwn6UokXrWzEjtxFNJ7BO9j/lK9LFYeMDthfNQz0gZygJAmaJaAaPZ8saBe+SoLd+sTrXB26eNJQ8qkY1yz/uj03/f3FS+3S+Pwe5Gf95uMd3pAOxUJZaCVypKXiOpLq67pD8D6j+AbUUKr5VlQAw9+A6ddXFlLAVstJyApgxXlunaViHmCl396fFuE7CQIgKmcScJzl6wpQQ/KbqY4OyVXgB9relUxdiE7LRQeUGkwZ9R6UpPv7+LMTTZOMWXWc1gVLLRoWax4M8zQ7lhoK7Bsi6+0NqDJsg16q0+zBaFLQSRbI91ig8DaE4bQbC1BzlcZdw3bHE8YP6IjrP9v0EIEasgklKD4wwa3d+ltKFAtuoLM1jMNN7X85B5InQHGXl3Gf12QdKhBJDHJXF6elLj7q4S2yaGziHhtQukA8B6AtCt9efvnBJgQgLR1DFEnYbnbL42+fM3YKchfjWuk/el6Pz+ThiDPFGy3agDhaf9vV/ju5bBF1muok6XlKXs37sUcPAe5Kp7EU7IfqkJzAqG8ci3mJT3dxDSzxWa3kzL3UKZd6yh/ccukOLj4U38oySDYzlInBE76Apc2GTK7Vk9bAgGgOuCkFQCmAaY=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in goodread.gemspec
4
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Evgeny Karev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Goodread::Rb
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/goodread/rb`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'goodread'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install goodread
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/goodread-rb.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "goodread/rb"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/goodread-rb ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cli'
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/goodread.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "goodread"
7
+ spec.version = "0.1.0"
8
+ spec.authors = ["Evgeny Karev\n"]
9
+ spec.email = ["eskarev@gmail.com"]
10
+
11
+ spec.summary = %q{goodread}
12
+ spec.description = %q{goodread}
13
+ spec.homepage = "https://github.com/goodread/goodread-rb"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+
20
+ spec.bindir = "bin"
21
+ spec.executables = ["goodread-rb"]
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+
28
+ spec.add_dependency "colorize", "~> 0.8"
29
+ spec.add_dependency "gemoji", "~> 3.0"
30
+ end
data/lib/cli.rb ADDED
@@ -0,0 +1,416 @@
1
+ require 'json'
2
+ require 'yaml'
3
+ require 'emoji'
4
+ require 'colorize'
5
+
6
+
7
+ # Helpers
8
+
9
+ def parse_specs(path)
10
+
11
+ # Paths
12
+ paths = []
13
+ if !path
14
+ paths = Dir.glob('package.*')
15
+ if paths.empty?
16
+ path = 'packspec'
17
+ end
18
+ end
19
+ if File.file?(path)
20
+ paths = [path]
21
+ elsif File.directory?(path)
22
+ for path in Dir.glob("#{path}/*.*")
23
+ paths.push(path)
24
+ end
25
+ end
26
+
27
+ # Specs
28
+ specs = []
29
+ for path in paths
30
+ spec = parse_spec(path)
31
+ if spec
32
+ specs.push(spec)
33
+ end
34
+ end
35
+
36
+ return specs
37
+
38
+ end
39
+
40
+
41
+ def parse_spec(path)
42
+
43
+ # Documents
44
+ documents = []
45
+ if !path.end_with?('.yml')
46
+ return nil
47
+ end
48
+ contents = File.read(path)
49
+ YAML.load_stream(contents) do |document|
50
+ documents.push(document)
51
+ end
52
+
53
+ # Package
54
+ feature = parse_feature(documents[0][0])
55
+ if feature['skip']
56
+ return nil
57
+ end
58
+ package = feature['comment']
59
+
60
+ # Features
61
+ skip = false
62
+ features = []
63
+ for feature in documents[0]
64
+ feature = parse_feature(feature)
65
+ features.push(feature)
66
+ if feature['comment']
67
+ skip = feature['skip']
68
+ end
69
+ feature['skip'] = skip || feature['skip']
70
+ end
71
+
72
+ # Scope
73
+ scope = {}
74
+ scope['$import'] = BuiltinFunctions.new().public_method(:builtin_import)
75
+ if documents.length > 1 && documents[1]['rb']
76
+ eval(documents[1]['rb'])
77
+ hook_scope = Functions.new()
78
+ for name in hook_scope.public_methods
79
+ # TODO: filter ruby builtin methods
80
+ scope["$#{name}"] = hook_scope.public_method(name)
81
+ end
82
+ end
83
+
84
+ # Stats
85
+ stats = {'features' => 0, 'comments' => 0, 'skipped' => 0, 'tests' => 0}
86
+ for feature in features
87
+ stats['features'] += 1
88
+ if feature['comment']
89
+ stats['comments'] += 1
90
+ else
91
+ stats['tests'] += 1
92
+ if feature['skip']
93
+ stats['skipped'] += 1
94
+ end
95
+ end
96
+ end
97
+
98
+ return {
99
+ 'package' => package,
100
+ 'features' => features,
101
+ 'scope' => scope,
102
+ 'stats' => stats,
103
+ }
104
+
105
+ end
106
+
107
+
108
+ def parse_feature(feature)
109
+
110
+ # General
111
+ if feature.is_a?(String)
112
+ match = /^(?:\((.*)\))?(\w.*)$/.match(feature)
113
+ skip, comment = match[1], match[2]
114
+ if !!skip
115
+ skip = !skip.split(':').include?('rb')
116
+ end
117
+ return {'assign' => nil, 'comment' => comment, 'skip' => skip}
118
+ end
119
+ left, right = Array(feature.each_pair)[0]
120
+
121
+ # Left side
122
+ call = false
123
+ match = /^(?:\((.*)\))?(?:([^=]*)=)?([^=].*)?$/.match(left)
124
+ skip, assign, property = match[1], match[2], match[3]
125
+ if !!skip
126
+ skip = !skip.split(':').include?('rb')
127
+ end
128
+ if !assign && !property
129
+ raise Exception.new('Non-valid feature')
130
+ end
131
+ if !!property
132
+ call = true
133
+ if property.end_with?('==')
134
+ property = property[0..-3]
135
+ call = false
136
+ end
137
+ end
138
+
139
+ # Right side
140
+ args = []
141
+ kwargs = {}
142
+ result = right
143
+ if !!call
144
+ result = nil
145
+ for item in right
146
+ if item.is_a?(Hash) && item.length == 1
147
+ item_left, item_right = Array(item.each_pair)[0]
148
+ if item_left == '=='
149
+ result = item_right
150
+ next
151
+ end
152
+ if item_left.end_with?('=')
153
+ kwargs[item_left[0..-2]] = item_right
154
+ next
155
+ end
156
+ end
157
+ args.push(item)
158
+ end
159
+ end
160
+
161
+ # Text repr
162
+ text = property
163
+ if !!assign
164
+ text = "#{assign} = #{property || JSON.generate(result)}"
165
+ end
166
+ if !!call
167
+ items = []
168
+ for item in args
169
+ items.push(JSON.generate(item))
170
+ end
171
+ for name, item in kwargs.each_pair
172
+ items.push("#{name}=#{JSON.generate(item)}")
173
+ end
174
+ text = "#{text}(#{items.join(', ')})"
175
+ end
176
+ if !!result && !assign
177
+ text = "#{text} == #{result == 'ERROR' ? result : JSON.generate(result)}"
178
+ end
179
+ text = text.gsub(/{"([^{}]*?)": null}/, '\1')
180
+
181
+ return {
182
+ 'comment' => nil,
183
+ 'skip' => skip,
184
+ 'call' => call,
185
+ 'assign' => assign,
186
+ 'property' => property,
187
+ 'args' => args,
188
+ 'kwargs' => kwargs,
189
+ 'result' => result,
190
+ 'text' => text,
191
+ }
192
+
193
+ end
194
+
195
+
196
+ def test_specs(specs)
197
+
198
+ # Message
199
+ message = "\n # Ruby\n".bold
200
+ puts(message)
201
+
202
+ # Test specs
203
+ success = true
204
+ for spec in specs
205
+ spec_success = test_spec(spec)
206
+ success = success && spec_success
207
+ end
208
+
209
+ return success
210
+
211
+ end
212
+
213
+
214
+ def test_spec(spec)
215
+
216
+ # Message
217
+ message = Emoji.find_by_alias('heavy_minus_sign').raw * 3 + "\n\n"
218
+ puts(message)
219
+
220
+ # Test spec
221
+ passed = 0
222
+ for feature in spec['features']
223
+ result = test_feature(feature, spec['scope'])
224
+ if result
225
+ passed += 1
226
+ end
227
+ end
228
+ success = (passed == spec['stats']['features'])
229
+
230
+ # Message
231
+ color = 'green'
232
+ message = ("\n " + Emoji.find_by_alias('heavy_check_mark').raw + ' ').green.bold
233
+ if !success
234
+ color = 'red'
235
+ message = ("\n " + Emoji.find_by_alias('x').raw + ' ').red.bold
236
+ end
237
+ message += "#{spec['package']}: #{passed - spec['stats']['comments'] - spec['stats']['skipped']}/#{spec['stats']['tests'] - spec['stats']['skipped']}\n".colorize(color).bold
238
+ puts(message)
239
+
240
+ return success
241
+
242
+ end
243
+
244
+
245
+ def test_feature(feature, scope)
246
+
247
+ # Comment
248
+ if !!feature['comment']
249
+ message = "\n # #{feature['comment']}\n".bold
250
+ puts(message)
251
+ return true
252
+ end
253
+
254
+ # Skip
255
+ if !!feature['skip']
256
+ message = " #{Emoji.find_by_alias('heavy_minus_sign').raw} ".yellow
257
+ message += feature['text']
258
+ puts(message)
259
+ return true
260
+ end
261
+
262
+ # Dereference
263
+ # TODO: deepcopy feature
264
+ if !!feature['call']
265
+ feature['args'] = dereference_value(feature['args'], scope)
266
+ feature['kwargs'] = dereference_value(feature['kwargs'], scope)
267
+ end
268
+ feature['result'] = dereference_value(feature['result'], scope)
269
+
270
+ # Execute
271
+ exception = nil
272
+ result = feature['result']
273
+ if !!feature['property']
274
+ begin
275
+ property = scope
276
+ for name in feature['property'].split('.')
277
+ property = get_property(property, name)
278
+ end
279
+ if !!feature['call']
280
+ args = feature['args'].dup
281
+ if !feature['kwargs'].empty?
282
+ args.push(Hash[feature['kwargs'].map{|k, v| [k.to_sym, v]}])
283
+ end
284
+ if property.respond_to?('new')
285
+ result = property.new(*args)
286
+ else
287
+ result = property.call(*args)
288
+ end
289
+ else
290
+ result = property
291
+ if result.is_a?(Method)
292
+ result = result.call()
293
+ end
294
+ end
295
+ rescue Exception => exc
296
+ exception = exc
297
+ result = 'ERROR'
298
+ end
299
+ end
300
+
301
+ # Assign
302
+ if !!feature['assign']
303
+ owner = scope
304
+ names = feature['assign'].split('.')
305
+ for name in names[0..-2]
306
+ owner = get_property(owner, name)
307
+ end
308
+ # TODO: ensure constants are immutable
309
+ set_property(owner, names[-1], result)
310
+ end
311
+
312
+ # Compare
313
+ if feature['result'] != nil
314
+ success = result == feature['result']
315
+ else
316
+ success = result != 'ERROR'
317
+ end
318
+ if success
319
+ message = " #{Emoji.find_by_alias('heavy_check_mark').raw} ".green
320
+ message += feature['text']
321
+ puts(message)
322
+ else
323
+ begin
324
+ result_text = JSON.generate(result)
325
+ rescue Exception
326
+ result_text = result.to_s
327
+ end
328
+ message = " #{Emoji.find_by_alias('x').raw} ".red
329
+ message += "#{feature['text']}\n"
330
+ if exception
331
+ message += "Exception: #{exception}".red.bold
332
+ else
333
+ message += "Assertion: #{result_text} != #{JSON.generate(feature['result'])}".red.bold
334
+ end
335
+ puts(message)
336
+ end
337
+
338
+ return success
339
+
340
+ end
341
+
342
+
343
+ class BuiltinFunctions
344
+ def builtin_import(package)
345
+ attributes = {}
346
+ require(package)
347
+ for item in ObjectSpace.each_object
348
+ if package == String(item).downcase
349
+ begin
350
+ scope = Kernel.const_get(item)
351
+ rescue Exception
352
+ next
353
+ end
354
+ for name in scope.constants
355
+ attributes[String(name)] = scope.const_get(name)
356
+ end
357
+ end
358
+ end
359
+ return attributes
360
+ end
361
+ end
362
+
363
+
364
+ def dereference_value(value, scope)
365
+ if value.is_a?(Hash) && value.length == 1 && Array(value.each_value)[0] == nil
366
+ result = scope
367
+ for name in Array(value.each_key)[0].split('.')
368
+ result = get_property(result, name)
369
+ end
370
+ value = result
371
+ elsif value.is_a?(Hash)
372
+ for key, item in value
373
+ value[key] = dereference_value(item, scope)
374
+ end
375
+ elsif value.is_a?(Array)
376
+ for item, index in value.each_with_index
377
+ value[index] = dereference_value(item, scope)
378
+ end
379
+ end
380
+ return value
381
+ end
382
+
383
+
384
+ def get_property(owner, name)
385
+ if owner.is_a?(Method)
386
+ owner = owner.call()
387
+ end
388
+ if owner.class == Hash
389
+ return owner[name]
390
+ elsif owner.class == Array
391
+ return owner[name.to_i]
392
+ end
393
+ return owner.method(name)
394
+ end
395
+
396
+
397
+ def set_property(owner, name, value)
398
+ if owner.class == Hash
399
+ owner[name] = value
400
+ return
401
+ elsif owner.class == Array
402
+ owner[name.to_i] = value
403
+ return
404
+ end
405
+ return owner.const_set(name, value)
406
+ end
407
+
408
+
409
+ # Main program
410
+
411
+ path = ARGV[0] || nil
412
+ specs = parse_specs(path)
413
+ success = test_specs(specs)
414
+ if !success
415
+ exit(1)
416
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goodread
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 'Evgeny Karev
8
+
9
+ '
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2017-08-14 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.14'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.14'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '10.0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '10.0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '3.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: colorize
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '0.8'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '0.8'
71
+ - !ruby/object:Gem::Dependency
72
+ name: gemoji
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '3.0'
85
+ description: goodread
86
+ email:
87
+ - eskarev@gmail.com
88
+ executables:
89
+ - goodread-rb
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".rspec"
95
+ - ".travis.yml"
96
+ - Gemfile
97
+ - LICENSE.md
98
+ - README.md
99
+ - Rakefile
100
+ - bin/console
101
+ - bin/goodread-rb
102
+ - bin/setup
103
+ - goodread.gemspec
104
+ - lib/cli.rb
105
+ homepage: https://github.com/goodread/goodread-rb
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.6.12
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: goodread
129
+ test_files: []