frog 1.0.1
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 +7 -0
- data/assets/last_updated.txt +1 -0
- data/assets/lists.js +4633 -0
- data/bin/console +14 -0
- data/bin/frog +4 -0
- data/bin/setup +8 -0
- data/lib/browser_launcher.rb +6 -0
- data/lib/constants.rb +5 -0
- data/lib/exact_searcher.rb +24 -0
- data/lib/exiter.rb +21 -0
- data/lib/frog.rb +32 -0
- data/lib/fuzzy_searcher.rb +77 -0
- data/lib/links_getter.rb +7 -0
- data/lib/links_updater.rb +49 -0
- data/lib/options_getter.rb +23 -0
- data/lib/search_router.rb +11 -0
- data/lib/search_term_getter.rb +12 -0
- metadata +203 -0
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "frog"
|
|
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
|
data/bin/frog
ADDED
data/bin/setup
ADDED
data/lib/constants.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class ExactSearcher
|
|
2
|
+
def initialize
|
|
3
|
+
@exiter = Exiter.new
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def search (search_term, links)
|
|
7
|
+
# Grep the links array to exactly match our search term
|
|
8
|
+
filtered_links = links.grep(/\/#{search_term}.html\"/i)
|
|
9
|
+
|
|
10
|
+
# Handle error and return if we don't find anything
|
|
11
|
+
if filtered_links.empty?
|
|
12
|
+
@exiter.exit_due_to_doc_not_found
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Get the relative URL of the required class
|
|
17
|
+
relative_url = filtered_links[0].partition("link:\"").last.partition("\"").first
|
|
18
|
+
|
|
19
|
+
# Append to base URL to form complete URL
|
|
20
|
+
target_link = "#{Constants::BASE_URL}/#{relative_url}"
|
|
21
|
+
|
|
22
|
+
return target_link
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/exiter.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class Exiter
|
|
2
|
+
def exit_due_to_no_search_term
|
|
3
|
+
abort "You need to provide something to search for".red
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def exit_due_to_doc_not_found
|
|
7
|
+
abort "Sorry. It looks like we couldn't find what you were looking for".red
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def exit_due_to_incorrect_index
|
|
11
|
+
abort "Sorry. It looks like you didn't enter the correct index".red
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def exit_due_to_net_http_fail_during_links_update
|
|
15
|
+
exit
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def exit_after_showing_help
|
|
19
|
+
exit
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/frog.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Get the project root
|
|
2
|
+
lib = File.expand_path('../../lib', __FILE__)
|
|
3
|
+
|
|
4
|
+
# Add project root to LOAD_PATH
|
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
|
+
|
|
7
|
+
# Require everything in lib so we don't have to require
|
|
8
|
+
# them in each file
|
|
9
|
+
Dir.glob(lib + '/*', &method(:require))
|
|
10
|
+
|
|
11
|
+
# Require external and third party libs
|
|
12
|
+
require 'optparse'
|
|
13
|
+
require 'launchy'
|
|
14
|
+
require 'time'
|
|
15
|
+
require 'net/http'
|
|
16
|
+
require 'colorize'
|
|
17
|
+
|
|
18
|
+
module Frog
|
|
19
|
+
def self.start
|
|
20
|
+
options = OptionsGetter.new.get_options
|
|
21
|
+
|
|
22
|
+
search_term = SearchTermGetter.new.get_search_term
|
|
23
|
+
|
|
24
|
+
links = LinksGetter.new.get_links_from_file
|
|
25
|
+
|
|
26
|
+
target_link = SearchRouter.new.delegate_to_appropriate_searcher(options[:exact], search_term, links)
|
|
27
|
+
|
|
28
|
+
BrowserLauncher.new.launch(target_link)
|
|
29
|
+
|
|
30
|
+
LinksUpdater.new.update_links_if_needed
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
class FuzzySearcher
|
|
2
|
+
def initialize
|
|
3
|
+
@exiter = Exiter.new
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def search (search_term, links)
|
|
7
|
+
|
|
8
|
+
# Grep the links array to fuzzily match our search term
|
|
9
|
+
filtered_links = links.grep(/#{search_term}/i)
|
|
10
|
+
|
|
11
|
+
# Error out and return if we don't find anything
|
|
12
|
+
if filtered_links.empty?
|
|
13
|
+
@exiter.exit_due_to_doc_not_found
|
|
14
|
+
return
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Create link and index hashes
|
|
18
|
+
# links_hash will map each class name to it's relative URL
|
|
19
|
+
# index_hash will match each selection index (that we show the user) to the class name
|
|
20
|
+
links_hash, index_hash = create_link_and_index_hashes(filtered_links)
|
|
21
|
+
|
|
22
|
+
# Show all the selection options to the user
|
|
23
|
+
show_selection_options(links_hash)
|
|
24
|
+
|
|
25
|
+
# Get the user selected index and verify if it's alright
|
|
26
|
+
index = get_verified_user_input(index_hash.size)
|
|
27
|
+
|
|
28
|
+
# Get the relative URL of the required class
|
|
29
|
+
relative_url = links_hash[index_hash[index]]
|
|
30
|
+
|
|
31
|
+
# Append to base URL to form complete URL
|
|
32
|
+
target_link = "#{Constants::BASE_URL}/#{relative_url}"
|
|
33
|
+
|
|
34
|
+
return target_link
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_link_and_index_hashes(filtered_links)
|
|
39
|
+
# Create 2 hashes
|
|
40
|
+
links_hash = Hash.new
|
|
41
|
+
index_hash = Hash.new
|
|
42
|
+
|
|
43
|
+
filtered_links.each_with_index do |link, i|
|
|
44
|
+
# Get class name
|
|
45
|
+
class_name = link.partition("label:\"").last.partition("\"").first
|
|
46
|
+
|
|
47
|
+
# Get relative URL
|
|
48
|
+
class_url = link.partition("link:\"").last.partition("\"").first
|
|
49
|
+
|
|
50
|
+
# Map class name to relative URL
|
|
51
|
+
links_hash[class_name] = class_url
|
|
52
|
+
|
|
53
|
+
# Map index to class name
|
|
54
|
+
index_hash[i] = class_name
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return links_hash, index_hash
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def show_selection_options(links_hash)
|
|
61
|
+
puts "Enter the index of the docs you want. ex: Enter 1 if you wish to select the first option.".green
|
|
62
|
+
links_hash.keys.each_with_index do |class_name, i|
|
|
63
|
+
puts "#{i+1}: #{class_name}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def get_verified_user_input(selection_options_size)
|
|
68
|
+
index = $stdin.gets.chomp.to_i - 1
|
|
69
|
+
if index < 0 || index >= selection_options_size
|
|
70
|
+
@exiter.exit_due_to_incorrect_index
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
return index
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
data/lib/links_getter.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class LinksUpdater
|
|
2
|
+
attr_reader :timestamp_file_path, :links_file_path
|
|
3
|
+
|
|
4
|
+
def initialize
|
|
5
|
+
@timestamp_file_path = File.expand_path("../assets/last_updated.txt", File.dirname(__FILE__))
|
|
6
|
+
@links_file_path = File.expand_path("../assets/lists.js", File.dirname(__FILE__))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def update_links_if_needed
|
|
10
|
+
if is_time_to_update?
|
|
11
|
+
update_links_from_website
|
|
12
|
+
update_timestamp
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
def is_time_to_update?
|
|
18
|
+
timestamp = File.read(@timestamp_file_path)
|
|
19
|
+
|
|
20
|
+
last_updated = DateTime.parse(timestamp)
|
|
21
|
+
|
|
22
|
+
one_week_from_last_updated = last_updated + 7
|
|
23
|
+
|
|
24
|
+
return DateTime.now > one_week_from_last_updated
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
def update_links_from_website
|
|
29
|
+
begin
|
|
30
|
+
# Get the latest links from the website
|
|
31
|
+
puts "Indexing the latest docs...".green
|
|
32
|
+
response = Net::HTTP.get_response(URI.parse(Constants::LINKS_URL))
|
|
33
|
+
rescue StandardError
|
|
34
|
+
# Exit if links update fails
|
|
35
|
+
puts "Looks like there's an internet connection problem. Will try again later.".red
|
|
36
|
+
Exiter.new.exit_due_to_net_http_fail_during_links_update
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Write them to file
|
|
41
|
+
File.write(@links_file_path, response.body)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
def update_timestamp
|
|
46
|
+
File.write(@timestamp_file_path, "#{DateTime.now}")
|
|
47
|
+
puts "Latest docs indexed!".green
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class OptionsGetter
|
|
2
|
+
def initialize
|
|
3
|
+
@exiter = Exiter.new
|
|
4
|
+
@options = {exact: false}
|
|
5
|
+
@options_parser = OptionParser.new do |opts|
|
|
6
|
+
opts.banner = 'Usage: droiddocs.rb [options] search_term'
|
|
7
|
+
|
|
8
|
+
opts.on('-e', '--exact', 'Search for the exact class') do |v|
|
|
9
|
+
@options[:exact] = true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
opts.on('-h', '--help', 'Displays Help') do
|
|
13
|
+
puts opts
|
|
14
|
+
@exiter.exit_after_showing_help
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_options
|
|
20
|
+
@options_parser.parse!
|
|
21
|
+
return @options
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class SearchRouter
|
|
2
|
+
def delegate_to_appropriate_searcher(exact, search_term, links)
|
|
3
|
+
if exact
|
|
4
|
+
# If it's an exact search
|
|
5
|
+
ExactSearcher.new.search(search_term, links)
|
|
6
|
+
else
|
|
7
|
+
# If it's a fuzzy search
|
|
8
|
+
FuzzySearcher.new.search(search_term, links)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: frog
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Anup Cowkur
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-06-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.12'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.12'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '5.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '5.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: minitest-reporters
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.1'
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: 1.1.9
|
|
65
|
+
type: :development
|
|
66
|
+
prerelease: false
|
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - "~>"
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '1.1'
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 1.1.9
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: byebug
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '9.0'
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: 9.0.5
|
|
85
|
+
type: :development
|
|
86
|
+
prerelease: false
|
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
88
|
+
requirements:
|
|
89
|
+
- - "~>"
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: '9.0'
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 9.0.5
|
|
95
|
+
- !ruby/object:Gem::Dependency
|
|
96
|
+
name: mocha
|
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - "~>"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '1.1'
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: 1.1.0
|
|
105
|
+
type: :development
|
|
106
|
+
prerelease: false
|
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - "~>"
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '1.1'
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: 1.1.0
|
|
115
|
+
- !ruby/object:Gem::Dependency
|
|
116
|
+
name: launchy
|
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - "~>"
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '2.4'
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 2.4.3
|
|
125
|
+
type: :runtime
|
|
126
|
+
prerelease: false
|
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '2.4'
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: 2.4.3
|
|
135
|
+
- !ruby/object:Gem::Dependency
|
|
136
|
+
name: colorize
|
|
137
|
+
requirement: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - "~>"
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '0.7'
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: 0.7.7
|
|
145
|
+
type: :runtime
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0.7'
|
|
152
|
+
- - ">="
|
|
153
|
+
- !ruby/object:Gem::Version
|
|
154
|
+
version: 0.7.7
|
|
155
|
+
description:
|
|
156
|
+
email:
|
|
157
|
+
- anupcowkur89@gmail.com
|
|
158
|
+
executables:
|
|
159
|
+
- frog
|
|
160
|
+
extensions: []
|
|
161
|
+
extra_rdoc_files: []
|
|
162
|
+
files:
|
|
163
|
+
- assets/last_updated.txt
|
|
164
|
+
- assets/lists.js
|
|
165
|
+
- bin/console
|
|
166
|
+
- bin/frog
|
|
167
|
+
- bin/setup
|
|
168
|
+
- lib/browser_launcher.rb
|
|
169
|
+
- lib/constants.rb
|
|
170
|
+
- lib/exact_searcher.rb
|
|
171
|
+
- lib/exiter.rb
|
|
172
|
+
- lib/frog.rb
|
|
173
|
+
- lib/fuzzy_searcher.rb
|
|
174
|
+
- lib/links_getter.rb
|
|
175
|
+
- lib/links_updater.rb
|
|
176
|
+
- lib/options_getter.rb
|
|
177
|
+
- lib/search_router.rb
|
|
178
|
+
- lib/search_term_getter.rb
|
|
179
|
+
homepage: https://github.com/anupcowkur/frog
|
|
180
|
+
licenses:
|
|
181
|
+
- MIT
|
|
182
|
+
metadata: {}
|
|
183
|
+
post_install_message:
|
|
184
|
+
rdoc_options: []
|
|
185
|
+
require_paths:
|
|
186
|
+
- lib
|
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
|
+
requirements:
|
|
189
|
+
- - ">="
|
|
190
|
+
- !ruby/object:Gem::Version
|
|
191
|
+
version: '0'
|
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
|
+
requirements:
|
|
194
|
+
- - ">="
|
|
195
|
+
- !ruby/object:Gem::Version
|
|
196
|
+
version: '0'
|
|
197
|
+
requirements: []
|
|
198
|
+
rubyforge_project:
|
|
199
|
+
rubygems_version: 2.6.4
|
|
200
|
+
signing_key:
|
|
201
|
+
specification_version: 4
|
|
202
|
+
summary: Frog helps you jump to the right Android dev docs from the command line
|
|
203
|
+
test_files: []
|