gem-search 0.1.1 → 0.1.2
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +5 -0
- data/README.md +28 -18
- data/bin/gem-search +1 -3
- data/gem-search.gemspec +13 -13
- data/lib/gem_search.rb +9 -0
- data/lib/{gem-search → gem_search}/command.rb +39 -19
- data/lib/gem_search/executor.rb +79 -0
- data/lib/gem_search/rendering.rb +41 -0
- data/lib/{gem-search → gem_search}/version.rb +1 -1
- data/spec/bin/{gem-search_spec.rb → gem_search_spec.rb} +10 -5
- data/spec/command_spec.rb +11 -11
- data/spec/executor_spec.rb +97 -45
- data/spec/http_stubs/gems/git-trend.json +66 -0
- data/spec/http_stubs/gems/git-trend_no_homepage.json +65 -0
- data/spec/http_stubs/{cucumber-_1.json → search/cucumber-_1.json} +0 -0
- data/spec/http_stubs/{cucumber-_2.json → search/cucumber-_2.json} +0 -0
- data/spec/http_stubs/{cucumber-_3.json → search/cucumber-_3.json} +0 -0
- data/spec/spec_helper.rb +22 -19
- metadata +27 -23
- data/lib/gem-search.rb +0 -9
- data/lib/gem-search/executor.rb +0 -52
- data/lib/gem-search/rendering.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a1e1368ab020ee422a5df16ebed3581a5d1d295
|
4
|
+
data.tar.gz: bf0313e4e6bbc42fdbff3b5f51f781048531ceb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d95848032e753ecb45d4757ccb2a951e4da0a3dc2983822b533a8bc6a824a8d847dfa1f30e9221190c8a799e4c415a08775614b9733df301ce3e994d6f4cd421
|
7
|
+
data.tar.gz: 0e6b871fcc56fb661ae43db82a2812c01f506cc59b480d124778743ca8e48025008c0098e0406e3450ab6f915ff9dc04472285dbc64088f687e42080331d692a
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -19,8 +19,32 @@ install it yourself as:
|
|
19
19
|
|
20
20
|
Use the gem-search as follows:
|
21
21
|
|
22
|
-
|
22
|
+
|
23
|
+
### Sorted by DL(all)
|
24
|
+
|
23
25
|
gem-search `keyword'
|
26
|
+
or
|
27
|
+
gem-search `keyword' -s a
|
28
|
+
|
29
|
+
e.g.:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ gem-search webkit
|
33
|
+
NAME DL(ver) DL(all)
|
34
|
+
-------------------------------------------------- -------- ---------
|
35
|
+
capybara-webkit (0.12.1) 24863 185214
|
36
|
+
jasmine-headless-webkit (0.8.4) 19444 46147
|
37
|
+
guard-jasmine-headless-webkit (0.3.2) 11964 17872
|
38
|
+
rspec-formatter-webkit (2.2.0) 438 3549
|
39
|
+
webkit-rspec-formatter (2.0.2) 613 1573
|
40
|
+
intentmedia-capybara-webkit (0.7.2.4) 370 1362
|
41
|
+
capybara-webkit-remote (0.0.4) 209 838
|
42
|
+
otherinbox-capybara-webkit (0.12.0.1) 594 740
|
43
|
+
gtk-webkit-ruby (0.0.3) 289 289
|
44
|
+
```
|
45
|
+
|
46
|
+
### Sorted by gem name
|
47
|
+
gem-search `keyword' -s n
|
24
48
|
|
25
49
|
e.g.:
|
26
50
|
|
@@ -59,26 +83,12 @@ gtk-webkit-ruby (0.0.3) 289 289
|
|
59
83
|
capybara-webkit-remote (0.0.4) 209 838
|
60
84
|
```
|
61
85
|
|
62
|
-
###
|
86
|
+
### Browse
|
87
|
+
It open rubygem's homepage in the system's default web browser.
|
63
88
|
|
64
|
-
gem-search
|
89
|
+
gem-search browse 'gem_name'
|
65
90
|
|
66
|
-
e.g.:
|
67
91
|
|
68
|
-
```
|
69
|
-
$ gem-search webkit -s a
|
70
|
-
NAME DL(ver) DL(all)
|
71
|
-
-------------------------------------------------- -------- ---------
|
72
|
-
capybara-webkit (0.12.1) 24863 185214
|
73
|
-
jasmine-headless-webkit (0.8.4) 19444 46147
|
74
|
-
guard-jasmine-headless-webkit (0.3.2) 11964 17872
|
75
|
-
rspec-formatter-webkit (2.2.0) 438 3549
|
76
|
-
webkit-rspec-formatter (2.0.2) 613 1573
|
77
|
-
intentmedia-capybara-webkit (0.7.2.4) 370 1362
|
78
|
-
capybara-webkit-remote (0.0.4) 209 838
|
79
|
-
otherinbox-capybara-webkit (0.12.0.1) 594 740
|
80
|
-
gtk-webkit-ruby (0.0.3) 289 289
|
81
|
-
```
|
82
92
|
|
83
93
|
## Contributing
|
84
94
|
|
data/bin/gem-search
CHANGED
data/gem-search.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require File.expand_path('../lib/
|
1
|
+
require File.expand_path('../lib/gem_search/version', __FILE__)
|
2
2
|
|
3
3
|
def install_message
|
4
4
|
s = ''
|
5
5
|
s << "\xf0\x9f\x8d\xba " if or_over_mac_os_lion?
|
6
|
-
s <<
|
6
|
+
s << 'Thanks for installing!'
|
7
7
|
end
|
8
8
|
|
9
9
|
def or_over_mac_os_lion?
|
@@ -11,31 +11,31 @@ def or_over_mac_os_lion?
|
|
11
11
|
|
12
12
|
macos_full_version = `/usr/bin/sw_vers -productVersion`.chomp
|
13
13
|
macos_version = macos_full_version[/10\.\d+/]
|
14
|
-
|
14
|
+
macos_version >= '10.7' # 10.7 is lion
|
15
15
|
end
|
16
16
|
|
17
17
|
Gem::Specification.new do |gem|
|
18
|
-
gem.authors = [
|
19
|
-
gem.email = [
|
20
|
-
gem.homepage =
|
21
|
-
gem.summary =
|
18
|
+
gem.authors = ['rochefort']
|
19
|
+
gem.email = ['terasawan@gmail.com']
|
20
|
+
gem.homepage = 'https://github.com/rochefort/gem-search'
|
21
|
+
gem.summary = 'search gems with using rubygems.org API'
|
22
22
|
gem.description = gem.summary
|
23
23
|
|
24
24
|
gem.files = `git ls-files`.split($\)
|
25
25
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
26
26
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
27
|
-
gem.name =
|
28
|
-
gem.require_paths = [
|
27
|
+
gem.name = 'gem-search'
|
28
|
+
gem.require_paths = ['lib']
|
29
29
|
gem.version = Gem::Search::VERSION
|
30
30
|
|
31
31
|
gem.post_install_message = install_message
|
32
32
|
|
33
|
-
gem.add_dependency 'slop', '~>3.
|
33
|
+
gem.add_dependency 'slop', '~>3.6.0'
|
34
34
|
gem.add_dependency 'json', '~>1.8.1'
|
35
35
|
|
36
|
-
gem.add_development_dependency 'webmock', '~>1.
|
36
|
+
gem.add_development_dependency 'webmock', '~>1.18.0'
|
37
37
|
gem.add_development_dependency 'rake', '~>10.3.1'
|
38
38
|
|
39
|
-
gem.add_development_dependency 'rspec', '~>
|
40
|
-
gem.add_development_dependency 'simplecov', '~> 0.
|
39
|
+
gem.add_development_dependency 'rspec', '~> 3.0.0'
|
40
|
+
gem.add_development_dependency 'simplecov', '~> 0.9.0'
|
41
41
|
end
|
data/lib/gem_search.rb
ADDED
@@ -18,13 +18,32 @@ module Gem::Search
|
|
18
18
|
OPTS = Slop.parse(help: true) do
|
19
19
|
banner "Usage: gem-search gem_name [options]\n"
|
20
20
|
on :s, :sort, opt_description([
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
'Sort by the item.',
|
22
|
+
' default [a]ll',
|
23
|
+
' [a]ll :DL(all) eg. gem-search webkit -s a',
|
24
|
+
' [v]er :DL(ver) eg. gem-search webkit -s v',
|
25
|
+
' [n]ame : eg. gem-search webkit -s n',
|
26
|
+
]), argument: :optional
|
27
27
|
on :v, :version, 'Display the version.'
|
28
|
+
|
29
|
+
command 'browse' do
|
30
|
+
description "Open rubygem's homepage in the system's default web browser"
|
31
|
+
run do |_opts, args|
|
32
|
+
gem = args.first
|
33
|
+
executor = Executor.new
|
34
|
+
begin
|
35
|
+
executor.browse(gem)
|
36
|
+
rescue OpenURI::HTTPError
|
37
|
+
puts 'No such gem.'
|
38
|
+
abort
|
39
|
+
rescue => e
|
40
|
+
puts e.message
|
41
|
+
puts e.stacktrace
|
42
|
+
abort
|
43
|
+
end
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
end
|
28
47
|
end
|
29
48
|
|
30
49
|
def run
|
@@ -47,21 +66,22 @@ module Gem::Search
|
|
47
66
|
end
|
48
67
|
|
49
68
|
private
|
50
|
-
def version
|
51
|
-
puts "gem-search #{Gem::Search::VERSION}"
|
52
|
-
exit
|
53
|
-
end
|
54
69
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
70
|
+
def version
|
71
|
+
puts "gem-search #{Gem::Search::VERSION}"
|
72
|
+
exit
|
73
|
+
end
|
60
74
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
75
|
+
def validate
|
76
|
+
if (ARGV.size == 0)
|
77
|
+
puts OPTS
|
78
|
+
abort
|
65
79
|
end
|
80
|
+
|
81
|
+
if ARGV.any? { |arg| arg.match(/\A-/) }
|
82
|
+
puts OPTS
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
end
|
66
86
|
end
|
67
87
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Gem::Search
|
5
|
+
class Executor
|
6
|
+
include Gem::Search::Rendering
|
7
|
+
BASE_URL = 'https://rubygems.org'
|
8
|
+
SEARCH_API = "#{BASE_URL}/api/v1/search.json?query=%s&page=%d"
|
9
|
+
GEM_API = "#{BASE_URL}/api/v1/gems/%s.json"
|
10
|
+
GEM_URL = "#{BASE_URL}/%s"
|
11
|
+
|
12
|
+
MAX_REQUEST_COUNT = 20
|
13
|
+
|
14
|
+
def search(query, opt_sort = 'downloads')
|
15
|
+
return unless query
|
16
|
+
print 'Searching '
|
17
|
+
gems = []
|
18
|
+
(1..MAX_REQUEST_COUNT).each do |n|
|
19
|
+
print '.'
|
20
|
+
url = SEARCH_API % [query, n]
|
21
|
+
gems_by_page = open_rubygems_api(url)
|
22
|
+
break if gems_by_page.size.zero?
|
23
|
+
gems += gems_by_page
|
24
|
+
end
|
25
|
+
puts
|
26
|
+
|
27
|
+
fail Gem::Search::LibraryNotFound, 'We did not find results.' if gems.size.zero?
|
28
|
+
gems_sort!(gems, opt_sort)
|
29
|
+
Executor.render(gems)
|
30
|
+
end
|
31
|
+
|
32
|
+
def browse(gem)
|
33
|
+
return unless gem
|
34
|
+
api_url = GEM_API % gem
|
35
|
+
result = open_rubygems_api(api_url)
|
36
|
+
url = result['homepage_uri']
|
37
|
+
if url.nil? || url.empty?
|
38
|
+
url = GEM_URL % gem
|
39
|
+
end
|
40
|
+
browser_open(url)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# https://github.com/github/hub/blob/9c589396ae38f7b9f98319065ad491149954c152/lib/hub/context.rb#L517
|
46
|
+
def browser_open(url)
|
47
|
+
cmd = osx? ? 'open' :
|
48
|
+
%w[xdg-open cygstart x-www-browser firefox opera mozilla netscape].find { |comm| which comm }
|
49
|
+
system(cmd, url)
|
50
|
+
end
|
51
|
+
|
52
|
+
# refer to: https://github.com/github/hub/blob/9c589396ae38f7b9f98319065ad491149954c152/lib/hub/context.rb#L527
|
53
|
+
def osx?
|
54
|
+
require 'rbconfig'
|
55
|
+
RbConfig::CONFIG['host_os'].to_s.include?('darwin')
|
56
|
+
end
|
57
|
+
|
58
|
+
def open_rubygems_api(url)
|
59
|
+
option = {}
|
60
|
+
proxy = URI.parse(url).find_proxy
|
61
|
+
if proxy
|
62
|
+
if proxy.user && proxy.password
|
63
|
+
option[:proxy_http_basic_authentication] = [proxy, proxy.user, proxy.password]
|
64
|
+
else
|
65
|
+
option[:proxy] = proxy
|
66
|
+
end
|
67
|
+
end
|
68
|
+
JSON.parse(open(url, option).read)
|
69
|
+
end
|
70
|
+
|
71
|
+
def gems_sort!(gems, opt_sort)
|
72
|
+
if opt_sort == 'name'
|
73
|
+
gems.sort! { |x, y| x[opt_sort] <=> y[opt_sort] }
|
74
|
+
else
|
75
|
+
gems.sort! { |x, y| y[opt_sort] <=> x[opt_sort] }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Gem::Search
|
2
|
+
module Rendering
|
3
|
+
DEFAULT_RULED_LINE_SIZE = [50, 8, 9]
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(self)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render(gems)
|
10
|
+
ruled_line_size(gems)
|
11
|
+
render_to_header
|
12
|
+
render_to_body(gems)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def ruled_line_size(gems)
|
18
|
+
max_name_size = gems.map { |gem| "#{gem['name'] } (#{gem['version']})".size }.max
|
19
|
+
DEFAULT_RULED_LINE_SIZE[0] = max_name_size if max_name_size > DEFAULT_RULED_LINE_SIZE[0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_to_header
|
23
|
+
f = DEFAULT_RULED_LINE_SIZE
|
24
|
+
fmt = "%-#{f[0]}s %#{f[1]}s %#{f[2]}s"
|
25
|
+
puts fmt % ['NAME', 'DL(ver)', 'DL(all)']
|
26
|
+
puts fmt % ['-'*f[0], '-'*f[1], '-'*f[2]]
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_to_body(gems)
|
30
|
+
f = DEFAULT_RULED_LINE_SIZE
|
31
|
+
fmt = "%-#{f[0]}s %#{f[1]}d %#{f[2]}d"
|
32
|
+
gems.each do |gem|
|
33
|
+
puts fmt % [
|
34
|
+
"#{gem['name']} (#{gem['version']})",
|
35
|
+
gem['version_downloads'],
|
36
|
+
gem['downloads']
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -11,16 +11,21 @@ Usage: gem-search gem_name [options]
|
|
11
11
|
[n]ame : eg. gem-search webkit -s n
|
12
12
|
-v, --version Display the version.
|
13
13
|
-h, --help Display this help message.
|
14
|
-
EOS
|
15
14
|
|
15
|
+
Available commands:
|
16
|
+
|
17
|
+
browse Open rubygem's homepage in the system's default web browser
|
18
|
+
|
19
|
+
See `<command> --help` for more information on a specific command.
|
20
|
+
EOS
|
16
21
|
|
17
|
-
shared_examples 'display an usage' do
|
18
|
-
it '
|
22
|
+
RSpec.shared_examples 'display an usage' do
|
23
|
+
it 'display an usage' do
|
19
24
|
should == USAGE
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
|
-
describe 'bin/gem-search' do
|
28
|
+
RSpec.describe 'bin/gem-search' do
|
24
29
|
context 'with no argument' do
|
25
30
|
subject { `#{BIN}` }
|
26
31
|
it_behaves_like 'display an usage'
|
@@ -38,7 +43,7 @@ describe 'bin/gem-search' do
|
|
38
43
|
|
39
44
|
context 'with -v' do
|
40
45
|
subject { `#{BIN} -v` }
|
41
|
-
it '
|
46
|
+
it 'display an usage' do
|
42
47
|
should == "gem-search #{Gem::Search::VERSION}\n"
|
43
48
|
end
|
44
49
|
end
|
data/spec/command_spec.rb
CHANGED
@@ -2,34 +2,34 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
include Gem::Search
|
4
4
|
|
5
|
-
describe Command do
|
5
|
+
RSpec.describe Command do
|
6
6
|
describe '#run' do
|
7
7
|
before do
|
8
8
|
@executor = Executor.new
|
9
|
-
Executor.
|
10
|
-
ARGV.
|
11
|
-
stub_request_search(1, dummy_search_result)
|
12
|
-
|
9
|
+
allow(Executor).to receive(:new).and_return(@executor)
|
10
|
+
allow(ARGV).to receive(:[]).with(0).and_return(query)
|
11
|
+
stub_request_search(query, 1, dummy_search_result)
|
12
|
+
stub_request_search_no_result_with_page(query, 2)
|
13
13
|
end
|
14
|
-
let(:query) {'
|
14
|
+
let(:query) { 'factory_girl' }
|
15
15
|
|
16
16
|
context 'with no sort option' do
|
17
17
|
before do
|
18
|
-
Command::OPTS.
|
18
|
+
allow(Command::OPTS).to receive(:[]).and_return(nil)
|
19
19
|
end
|
20
20
|
it 'called with no sort option' do
|
21
|
-
@executor.
|
21
|
+
expect(@executor).to receive(:search).with(query).once
|
22
22
|
Command.new.run
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
context 'with sort option' do
|
27
27
|
before do
|
28
|
-
Command::OPTS.
|
29
|
-
Command::OPTS.
|
28
|
+
allow(Command::OPTS).to receive(:[]).and_return(nil)
|
29
|
+
allow(Command::OPTS).to receive(:[]).with('sort').and_return('a')
|
30
30
|
end
|
31
31
|
it 'called with sort option' do
|
32
|
-
@executor.
|
32
|
+
expect(@executor).to receive(:search).with(query, 'downloads').once
|
33
33
|
Command.new.run
|
34
34
|
end
|
35
35
|
end
|
data/spec/executor_spec.rb
CHANGED
@@ -2,37 +2,37 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
include Gem::Search
|
4
4
|
|
5
|
-
describe Executor do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
RSpec.describe Executor do
|
6
|
+
before do
|
7
|
+
@executor = Executor.new
|
8
|
+
end
|
10
9
|
|
10
|
+
describe '#search' do
|
11
11
|
context 'when a network error occurred' do
|
12
12
|
before do
|
13
|
-
stub_request(:get, build_search_uri(query, 1))
|
14
|
-
to_return(:
|
13
|
+
stub_request(:get, build_search_uri(query, 1))
|
14
|
+
.to_return(status: 500, body: '[]')
|
15
15
|
end
|
16
|
-
let(:query) {'network_error_orccurred'}
|
17
|
-
it { expect{ @executor.search(query) }.to raise_error(Exception) }
|
16
|
+
let(:query) { 'network_error_orccurred' }
|
17
|
+
it { expect { @executor.search(query) }.to raise_error(Exception) }
|
18
18
|
end
|
19
19
|
|
20
20
|
context 'when no matching gem' do
|
21
|
-
before {
|
22
|
-
let(:query) {'no_match_gem_name'}
|
23
|
-
it { expect{ @executor.search(query) }.to raise_error(LibraryNotFound) }
|
21
|
+
before { stub_request_search_no_result_with_page(query, 1) }
|
22
|
+
let(:query) { 'no_match_gem_name' }
|
23
|
+
it { expect { @executor.search(query) }.to raise_error(LibraryNotFound) }
|
24
24
|
end
|
25
25
|
|
26
26
|
describe 'sorting' do
|
27
27
|
before do
|
28
|
-
stub_request_search(1, dummy_search_result)
|
29
|
-
|
28
|
+
stub_request_search(query, 1, dummy_search_result)
|
29
|
+
stub_request_search_no_result_with_page(query, 2)
|
30
30
|
end
|
31
|
-
let(:query) {'factory_girl'}
|
31
|
+
let(:query) { 'factory_girl' }
|
32
32
|
|
33
33
|
context 'with no sort option' do
|
34
34
|
it 'display rubygems ordering by name' do
|
35
|
-
|
35
|
+
res = <<-'EOS'.unindent
|
36
36
|
|Searching ..
|
37
37
|
|NAME DL(ver) DL(all)
|
38
38
|
|-------------------------------------------------- -------- ---------
|
@@ -40,12 +40,13 @@ describe Executor do
|
|
40
40
|
|factory_girl_rails (3.5.0) 39724 1238780
|
41
41
|
|factory_girl_generator (0.0.3) 8015 15547
|
42
42
|
EOS
|
43
|
+
expect { @executor.search(query) }.to output(res).to_stdout
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
47
|
context 'with sort option: [a]download' do
|
47
48
|
it 'display rubygems ordering by name' do
|
48
|
-
|
49
|
+
res = <<-'EOS'.unindent
|
49
50
|
|Searching ..
|
50
51
|
|NAME DL(ver) DL(all)
|
51
52
|
|-------------------------------------------------- -------- ---------
|
@@ -53,12 +54,13 @@ describe Executor do
|
|
53
54
|
|factory_girl_rails (3.5.0) 39724 1238780
|
54
55
|
|factory_girl_generator (0.0.3) 8015 15547
|
55
56
|
EOS
|
57
|
+
expect { @executor.search(query, 'download') }.to output(res).to_stdout
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
context 'with sort option: [v]version_downloads' do
|
60
62
|
it 'display rubygems ordering by name' do
|
61
|
-
|
63
|
+
res = <<-'EOS'.unindent
|
62
64
|
|Searching ..
|
63
65
|
|NAME DL(ver) DL(all)
|
64
66
|
|-------------------------------------------------- -------- ---------
|
@@ -66,12 +68,13 @@ describe Executor do
|
|
66
68
|
|factory_girl_generator (0.0.3) 8015 15547
|
67
69
|
|factory_girl (3.6.0) 541 2042859
|
68
70
|
EOS
|
71
|
+
expect { @executor.search(query, 'version_downloads') }.to output(res).to_stdout
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
75
|
context 'with sort option: [n]ame' do
|
73
76
|
it 'display rubygems ordering by name' do
|
74
|
-
|
77
|
+
res = <<-'EOS'.unindent
|
75
78
|
|Searching ..
|
76
79
|
|NAME DL(ver) DL(all)
|
77
80
|
|-------------------------------------------------- -------- ---------
|
@@ -79,20 +82,21 @@ describe Executor do
|
|
79
82
|
|factory_girl_generator (0.0.3) 8015 15547
|
80
83
|
|factory_girl_rails (3.5.0) 39724 1238780
|
81
84
|
EOS
|
85
|
+
expect { @executor.search(query, 'name') }.to output(res).to_stdout
|
82
86
|
end
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
86
90
|
describe 'multiple page' do
|
87
91
|
before do
|
88
|
-
stub_request_search(1, load_http_stubs('cucumber-_1.json'))
|
89
|
-
stub_request_search(2, load_http_stubs('cucumber-_2.json'))
|
90
|
-
stub_request_search(3, load_http_stubs('cucumber-_3.json'))
|
91
|
-
|
92
|
+
stub_request_search(query, 1, load_http_stubs('search/cucumber-_1.json'))
|
93
|
+
stub_request_search(query, 2, load_http_stubs('search/cucumber-_2.json'))
|
94
|
+
stub_request_search(query, 3, load_http_stubs('search/cucumber-_3.json'))
|
95
|
+
stub_request_search_no_result_with_page(query, 4)
|
92
96
|
end
|
93
97
|
let(:query) { 'cucumber-' }
|
94
98
|
it 'display rubygems ordering by name' do
|
95
|
-
|
99
|
+
res = <<-'EOS'.unindent
|
96
100
|
|Searching ....
|
97
101
|
|NAME DL(ver) DL(all)
|
98
102
|
|-------------------------------------------------- -------- ---------
|
@@ -160,58 +164,106 @@ describe Executor do
|
|
160
164
|
|tasty-cucumber-client (0.1.10) 1504 11518
|
161
165
|
|vagrant-cucumber-host (0.1.14) 163 163
|
162
166
|
EOS
|
167
|
+
expect { @executor.search(query, 'name') }.to output(res).to_stdout
|
163
168
|
end
|
164
169
|
end
|
165
170
|
|
166
171
|
describe 'ruled NAME line' do
|
167
172
|
context 'NAME size is 42' do
|
168
173
|
before do
|
169
|
-
stub_request_search(1, dummy_search_result_name_size_is_42)
|
170
|
-
|
174
|
+
stub_request_search(query, 1, dummy_search_result_name_size_is_42)
|
175
|
+
stub_request_search_no_result_with_page(query, 2)
|
171
176
|
end
|
172
|
-
let(:query) {'size_is_42_2345678901234567890123456789012'}
|
177
|
+
let(:query) { 'size_is_42_2345678901234567890123456789012' }
|
173
178
|
it 'is 50 characters' do
|
174
|
-
|
179
|
+
res = <<-'EOS'.unindent
|
175
180
|
|Searching ..
|
176
181
|
|NAME DL(ver) DL(all)
|
177
182
|
|-------------------------------------------------- -------- ---------
|
178
183
|
|size_is_42_2345678901234567890123456789012 (0.0.1) 100 1000
|
179
184
|
EOS
|
185
|
+
expect { @executor.search(query) }.to output(res).to_stdout
|
180
186
|
end
|
181
187
|
end
|
182
188
|
|
183
189
|
context 'NAME size is 43' do
|
184
190
|
before do
|
185
|
-
stub_request_search(1, dummy_search_result_name_size_is_43)
|
186
|
-
|
191
|
+
stub_request_search(query, 1, dummy_search_result_name_size_is_43)
|
192
|
+
stub_request_search_no_result_with_page(query, 2)
|
187
193
|
end
|
188
|
-
let(:query) {'size_is_43_23456789012345678901234567890123'}
|
194
|
+
let(:query) { 'size_is_43_23456789012345678901234567890123' }
|
189
195
|
it 'is 51 characters' do
|
190
|
-
|
196
|
+
res = <<-'EOS'.unindent
|
191
197
|
|Searching ..
|
192
198
|
|NAME DL(ver) DL(all)
|
193
199
|
|--------------------------------------------------- -------- ---------
|
194
200
|
|size_is_43_23456789012345678901234567890123 (0.0.2) 200 2000
|
195
201
|
EOS
|
202
|
+
expect { @executor.search(query) }.to output(res).to_stdout
|
196
203
|
end
|
197
204
|
end
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
+
describe '#browse' do
|
209
|
+
context 'when a network error occurred' do
|
210
|
+
before do
|
211
|
+
stub_request(:get, build_gems_uri(query))
|
212
|
+
.to_return(status: 500, body: '[]')
|
213
|
+
end
|
214
|
+
let(:query) { 'network_error_orccurred' }
|
215
|
+
it { expect { @executor.browse(query) }.to raise_error(Exception) }
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'when no matching gem' do
|
219
|
+
before { stub_request_gems_no_result(query) }
|
220
|
+
let(:query) { 'no_match_gem_name' }
|
221
|
+
it { expect { @executor.browse(query) }.to raise_error(OpenURI::HTTPError) }
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'when no homepage_uri' do
|
225
|
+
before do
|
226
|
+
url = Executor::GEM_URL % query
|
227
|
+
allow(@executor).to receive(:system).with('open', url)
|
228
|
+
stub_request_gems(query, load_http_stubs("gems/#{query}.json"))
|
229
|
+
end
|
230
|
+
let(:query) { 'git-trend_no_homepage' }
|
231
|
+
|
232
|
+
it 'open a rubygems url' do
|
233
|
+
@executor.browse(query)
|
234
|
+
end
|
208
235
|
end
|
209
236
|
|
210
|
-
|
211
|
-
|
212
|
-
"
|
213
|
-
|
214
|
-
|
215
|
-
|
237
|
+
context 'when homepage_uri is existed' do
|
238
|
+
before do
|
239
|
+
http_stub = load_http_stubs("gems/#{query}.json")
|
240
|
+
url = JSON.parse(http_stub)['homepage_uri']
|
241
|
+
allow(@executor).to receive(:system).with('open', url)
|
242
|
+
stub_request_gems(query, http_stub)
|
243
|
+
end
|
244
|
+
let(:query) { 'git-trend' }
|
245
|
+
|
246
|
+
it 'open a homepage url' do
|
247
|
+
@executor.browse(query)
|
248
|
+
end
|
216
249
|
end
|
250
|
+
end
|
251
|
+
|
252
|
+
private
|
253
|
+
|
254
|
+
def dummy_search_result_name_size_is_42
|
255
|
+
[{"name"=>"size_is_42_2345678901234567890123456789012",
|
256
|
+
"downloads"=>1000,
|
257
|
+
"version"=>"0.0.1",
|
258
|
+
"version_downloads"=>100}
|
259
|
+
].to_json
|
260
|
+
end
|
261
|
+
|
262
|
+
def dummy_search_result_name_size_is_43
|
263
|
+
[{"name"=>"size_is_43_23456789012345678901234567890123",
|
264
|
+
"downloads"=>2000,
|
265
|
+
"version"=>"0.0.2",
|
266
|
+
"version_downloads"=>200}
|
267
|
+
].to_json
|
268
|
+
end
|
217
269
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
{
|
2
|
+
"name": "git-trend",
|
3
|
+
"downloads": 1106,
|
4
|
+
"version": "0.0.8",
|
5
|
+
"version_downloads": 36,
|
6
|
+
"platform": "ruby",
|
7
|
+
"authors": "rochefort",
|
8
|
+
"info": "cli based; show Trending repository on github",
|
9
|
+
"licenses": [
|
10
|
+
"MIT"
|
11
|
+
],
|
12
|
+
"project_uri": "http://rubygems.org/gems/git-trend",
|
13
|
+
"gem_uri": "http://rubygems.org/gems/git-trend-0.0.8.gem",
|
14
|
+
"homepage_uri": "https://github.com/rochefort/git-trend",
|
15
|
+
"wiki_uri": null,
|
16
|
+
"documentation_uri": null,
|
17
|
+
"mailing_list_uri": null,
|
18
|
+
"source_code_uri": null,
|
19
|
+
"bug_tracker_uri": null,
|
20
|
+
"dependencies": {
|
21
|
+
"development": [
|
22
|
+
{
|
23
|
+
"name": "bundler",
|
24
|
+
"requirements": "~> 1.6"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"name": "coveralls",
|
28
|
+
"requirements": ">= 0"
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"name": "rake",
|
32
|
+
"requirements": ">= 0"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"name": "rspec",
|
36
|
+
"requirements": "~> 3.0.0"
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"name": "rspec-its",
|
40
|
+
"requirements": "~> 1.0.1"
|
41
|
+
},
|
42
|
+
{
|
43
|
+
"name": "simplecov",
|
44
|
+
"requirements": "~> 0.9.0"
|
45
|
+
},
|
46
|
+
{
|
47
|
+
"name": "webmock",
|
48
|
+
"requirements": "~> 1.18.0"
|
49
|
+
}
|
50
|
+
],
|
51
|
+
"runtime": [
|
52
|
+
{
|
53
|
+
"name": "addressable",
|
54
|
+
"requirements": "~> 2.3.6"
|
55
|
+
},
|
56
|
+
{
|
57
|
+
"name": "mechanize",
|
58
|
+
"requirements": "~> 2.7.3"
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"name": "thor",
|
62
|
+
"requirements": "~> 0.19.1"
|
63
|
+
}
|
64
|
+
]
|
65
|
+
}
|
66
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
{
|
2
|
+
"name": "git-trend",
|
3
|
+
"downloads": 1106,
|
4
|
+
"version": "0.0.8",
|
5
|
+
"version_downloads": 36,
|
6
|
+
"platform": "ruby",
|
7
|
+
"authors": "rochefort",
|
8
|
+
"info": "cli based; show Trending repository on github",
|
9
|
+
"licenses": [
|
10
|
+
"MIT"
|
11
|
+
],
|
12
|
+
"project_uri": "http://rubygems.org/gems/git-trend",
|
13
|
+
"gem_uri": "http://rubygems.org/gems/git-trend-0.0.8.gem",
|
14
|
+
"wiki_uri": null,
|
15
|
+
"documentation_uri": null,
|
16
|
+
"mailing_list_uri": null,
|
17
|
+
"source_code_uri": null,
|
18
|
+
"bug_tracker_uri": null,
|
19
|
+
"dependencies": {
|
20
|
+
"development": [
|
21
|
+
{
|
22
|
+
"name": "bundler",
|
23
|
+
"requirements": "~> 1.6"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"name": "coveralls",
|
27
|
+
"requirements": ">= 0"
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"name": "rake",
|
31
|
+
"requirements": ">= 0"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"name": "rspec",
|
35
|
+
"requirements": "~> 3.0.0"
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"name": "rspec-its",
|
39
|
+
"requirements": "~> 1.0.1"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"name": "simplecov",
|
43
|
+
"requirements": "~> 0.9.0"
|
44
|
+
},
|
45
|
+
{
|
46
|
+
"name": "webmock",
|
47
|
+
"requirements": "~> 1.18.0"
|
48
|
+
}
|
49
|
+
],
|
50
|
+
"runtime": [
|
51
|
+
{
|
52
|
+
"name": "addressable",
|
53
|
+
"requirements": "~> 2.3.6"
|
54
|
+
},
|
55
|
+
{
|
56
|
+
"name": "mechanize",
|
57
|
+
"requirements": "~> 2.7.3"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"name": "thor",
|
61
|
+
"requirements": "~> 0.19.1"
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
}
|
File without changes
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -4,37 +4,40 @@ require 'simplecov'
|
|
4
4
|
SimpleCov.start
|
5
5
|
|
6
6
|
require 'webmock/rspec'
|
7
|
-
require '
|
7
|
+
require 'gem_search'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def capture(stream)
|
12
|
-
begin
|
13
|
-
stream = stream.to_s
|
14
|
-
eval "$#{stream} = StringIO.new"
|
15
|
-
yield
|
16
|
-
result = eval("$#{stream}").string
|
17
|
-
ensure
|
18
|
-
eval("$#{stream} = #{stream.upcase}")
|
19
|
-
end
|
20
|
-
|
21
|
-
result
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.expose_dsl_globally = false
|
22
11
|
end
|
23
12
|
|
24
13
|
def load_http_stubs(file_name)
|
25
14
|
open(File.join(File.dirname(__FILE__), 'http_stubs', file_name)).read
|
26
15
|
end
|
27
16
|
|
28
|
-
|
29
|
-
|
17
|
+
# stubs for search API
|
18
|
+
def stub_request_search(query, page, body)
|
19
|
+
stub_request(:get, build_search_uri(query, page)).to_return(status: 200, body: body)
|
30
20
|
end
|
31
21
|
|
32
|
-
def
|
33
|
-
stub_request(:get, build_search_uri(query, page)).to_return(:
|
22
|
+
def stub_request_search_no_result_with_page(query, page)
|
23
|
+
stub_request(:get, build_search_uri(query, page)).to_return(status: 200, body: '[]')
|
34
24
|
end
|
35
25
|
|
36
26
|
def build_search_uri(query, page)
|
37
|
-
Executor::
|
27
|
+
Executor::SEARCH_API % [query, page]
|
28
|
+
end
|
29
|
+
|
30
|
+
# stubs for gems API
|
31
|
+
def stub_request_gems(query, body)
|
32
|
+
stub_request(:get, build_gems_uri(query)).to_return(status: 200, body: body)
|
33
|
+
end
|
34
|
+
|
35
|
+
def stub_request_gems_no_result(query)
|
36
|
+
stub_request(:get, build_gems_uri(query)).to_return(status: 404, body: '[]')
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_gems_uri(query)
|
40
|
+
Executor::GEM_API % query
|
38
41
|
end
|
39
42
|
|
40
43
|
def dummy_search_result
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem-search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rochefort
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slop
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.
|
19
|
+
version: 3.6.0
|
20
20
|
type: :runtime
|
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: 3.
|
26
|
+
version: 3.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.
|
47
|
+
version: 1.18.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
54
|
+
version: 1.18.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,28 +72,28 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 3.0.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 3.0.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.
|
89
|
+
version: 0.9.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.
|
96
|
+
version: 0.9.0
|
97
97
|
description: search gems with using rubygems.org API
|
98
98
|
email:
|
99
99
|
- terasawan@gmail.com
|
@@ -111,17 +111,19 @@ files:
|
|
111
111
|
- Rakefile
|
112
112
|
- bin/gem-search
|
113
113
|
- gem-search.gemspec
|
114
|
-
- lib/
|
115
|
-
- lib/
|
116
|
-
- lib/
|
117
|
-
- lib/
|
118
|
-
- lib/
|
119
|
-
- spec/bin/
|
114
|
+
- lib/gem_search.rb
|
115
|
+
- lib/gem_search/command.rb
|
116
|
+
- lib/gem_search/executor.rb
|
117
|
+
- lib/gem_search/rendering.rb
|
118
|
+
- lib/gem_search/version.rb
|
119
|
+
- spec/bin/gem_search_spec.rb
|
120
120
|
- spec/command_spec.rb
|
121
121
|
- spec/executor_spec.rb
|
122
|
-
- spec/http_stubs/
|
123
|
-
- spec/http_stubs/
|
124
|
-
- spec/http_stubs/cucumber-
|
122
|
+
- spec/http_stubs/gems/git-trend.json
|
123
|
+
- spec/http_stubs/gems/git-trend_no_homepage.json
|
124
|
+
- spec/http_stubs/search/cucumber-_1.json
|
125
|
+
- spec/http_stubs/search/cucumber-_2.json
|
126
|
+
- spec/http_stubs/search/cucumber-_3.json
|
125
127
|
- spec/spec_helper.rb
|
126
128
|
homepage: https://github.com/rochefort/gem-search
|
127
129
|
licenses: []
|
@@ -147,10 +149,12 @@ signing_key:
|
|
147
149
|
specification_version: 4
|
148
150
|
summary: search gems with using rubygems.org API
|
149
151
|
test_files:
|
150
|
-
- spec/bin/
|
152
|
+
- spec/bin/gem_search_spec.rb
|
151
153
|
- spec/command_spec.rb
|
152
154
|
- spec/executor_spec.rb
|
153
|
-
- spec/http_stubs/
|
154
|
-
- spec/http_stubs/
|
155
|
-
- spec/http_stubs/cucumber-
|
155
|
+
- spec/http_stubs/gems/git-trend.json
|
156
|
+
- spec/http_stubs/gems/git-trend_no_homepage.json
|
157
|
+
- spec/http_stubs/search/cucumber-_1.json
|
158
|
+
- spec/http_stubs/search/cucumber-_2.json
|
159
|
+
- spec/http_stubs/search/cucumber-_3.json
|
156
160
|
- spec/spec_helper.rb
|
data/lib/gem-search.rb
DELETED
data/lib/gem-search/executor.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'open-uri'
|
3
|
-
|
4
|
-
module Gem::Search
|
5
|
-
class Executor
|
6
|
-
include Gem::Search::Rendering
|
7
|
-
BASE_URL = 'https://rubygems.org'
|
8
|
-
SEARCH_URL = "#{BASE_URL}/api/v1/search.json?query=%s&page=%d"
|
9
|
-
MAX_REQUEST_COUNT = 20
|
10
|
-
|
11
|
-
def search(query, opt_sort='downloads')
|
12
|
-
return unless query
|
13
|
-
print 'Searching '
|
14
|
-
gems = []
|
15
|
-
(1..MAX_REQUEST_COUNT).each do |n|
|
16
|
-
print '.'
|
17
|
-
url = SEARCH_URL % [query, n]
|
18
|
-
gems_by_page = search_rubygems(url)
|
19
|
-
break if gems_by_page.size.zero?
|
20
|
-
gems += gems_by_page
|
21
|
-
end
|
22
|
-
puts
|
23
|
-
|
24
|
-
raise Gem::Search::LibraryNotFound, 'We did not find results.' if gems.size.zero?
|
25
|
-
gems_sort!(gems, opt_sort)
|
26
|
-
Executor.render(gems)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
def search_rubygems(url)
|
31
|
-
option = {}
|
32
|
-
proxy = URI.parse(url).find_proxy
|
33
|
-
if proxy
|
34
|
-
if proxy.user && proxy.password
|
35
|
-
option[:proxy_http_basic_authentication] = [proxy, proxy.user, proxy.password]
|
36
|
-
else
|
37
|
-
option[:proxy] = proxy
|
38
|
-
end
|
39
|
-
end
|
40
|
-
JSON.parse(open(url, option).read)
|
41
|
-
end
|
42
|
-
|
43
|
-
def gems_sort!(gems, opt_sort)
|
44
|
-
if opt_sort == 'name'
|
45
|
-
gems.sort!{ |x,y| x[opt_sort] <=> y[opt_sort] }
|
46
|
-
else
|
47
|
-
gems.sort!{ |x,y| y[opt_sort] <=> x[opt_sort] }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
data/lib/gem-search/rendering.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
module Gem::Search
|
2
|
-
module Rendering
|
3
|
-
DEFAULT_RULED_LINE_SIZE = [50, 8, 9]
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.extend(self)
|
7
|
-
end
|
8
|
-
|
9
|
-
def render(gems)
|
10
|
-
set_ruled_line_size(gems)
|
11
|
-
render_to_header
|
12
|
-
render_to_body(gems)
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
def set_ruled_line_size(gems)
|
17
|
-
max_name_size = gems.map { |gem| "#{gem['name'] } (#{gem['version']})".size }.max
|
18
|
-
if max_name_size > DEFAULT_RULED_LINE_SIZE[0]
|
19
|
-
DEFAULT_RULED_LINE_SIZE[0] = max_name_size
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def render_to_header
|
24
|
-
f=DEFAULT_RULED_LINE_SIZE
|
25
|
-
fmt = "%-#{f[0]}s %#{f[1]}s %#{f[2]}s"
|
26
|
-
puts fmt % ['NAME', 'DL(ver)', 'DL(all)']
|
27
|
-
puts fmt % ['-'*f[0], '-'*f[1], '-'*f[2]]
|
28
|
-
end
|
29
|
-
|
30
|
-
def render_to_body(gems)
|
31
|
-
f=DEFAULT_RULED_LINE_SIZE
|
32
|
-
fmt = "%-#{f[0]}s %#{f[1]}d %#{f[2]}d"
|
33
|
-
gems.each do |gem|
|
34
|
-
puts fmt % [
|
35
|
-
"#{gem['name']} (#{gem['version']})",
|
36
|
-
gem['version_downloads'],
|
37
|
-
gem['downloads']
|
38
|
-
]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|