frog 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'frog'
4
+ Frog.start
@@ -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
@@ -0,0 +1,6 @@
1
+ class BrowserLauncher
2
+ def launch(target_link)
3
+ puts "Boom! Launching #{target_link}".green
4
+ Launchy.open(target_link)
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Constants
2
+ VERSION = "1.0.1"
3
+ BASE_URL = "https://developer.android.com"
4
+ LINKS_URL = "https://developer.android.com/reference/lists.js"
5
+ end
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ class LinksGetter
2
+ def get_links_from_file
3
+ contents = File.read(File.expand_path("../assets/lists.js", File.dirname(__FILE__)))
4
+
5
+ return contents.partition("[").last.partition("]").first.split("\n")
6
+ end
7
+ end
@@ -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
@@ -0,0 +1,12 @@
1
+ class SearchTermGetter
2
+ def get_search_term
3
+ search_term = ARGV[0]
4
+
5
+ if search_term.nil?
6
+ Exiter.new.exit_due_to_no_search_term
7
+ return
8
+ end
9
+
10
+ return search_term
11
+ end
12
+ 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: []