searchlink 2.3.69 → 2.3.71
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/lib/searchlink/exceptions.rb +29 -0
- data/lib/searchlink/output.rb +7 -4
- data/lib/searchlink/parse.rb +222 -190
- data/lib/searchlink/script_plugin.rb +84 -0
- data/lib/searchlink/searches/helpers/chromium.rb +32 -31
- data/lib/searchlink/searches.rb +33 -7
- data/lib/searchlink/semver.rb +7 -7
- data/lib/searchlink/string.rb +8 -0
- data/lib/searchlink/version.rb +1 -1
- data/lib/searchlink.rb +7 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55880b0891d029bf3dde58968a5b55c4cb302b14ceecd8e5f279338abc070895
|
|
4
|
+
data.tar.gz: 7ea4da442f494ce7c956d9510f7eb20f295de133d91d7abe538c380bfd7b4d79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 61efe73ac610acaea6d949186358bb863df9ff10d9fd0698f6b5510c3128c4833e2904347deccdb335573e1dcc4793739ae801150e97ba4bbf1e0ade8544d979
|
|
7
|
+
data.tar.gz: 0dc5b9f05b691833a8a515f186513a4ee7c281d8358e81f1abdaf1f7412d855480ce8d34f4bbfd383682d811eeb016fbb1868cd6ff165b5cca36afd50eaea87b
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SL
|
|
4
|
+
# Custom Semantic Versioning error
|
|
5
|
+
class VersionError < StandardError
|
|
6
|
+
def initialize(msg)
|
|
7
|
+
msg = msg ? ": #{msg}" : ''
|
|
8
|
+
puts "Versioning error#{msg}"
|
|
9
|
+
|
|
10
|
+
super()
|
|
11
|
+
|
|
12
|
+
Process.exit 1
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Custom plugin error
|
|
17
|
+
class PluginError < StandardError
|
|
18
|
+
def initialize(msg = nil, plugin: nil)
|
|
19
|
+
plugin = %("#{plugin}") if plugin
|
|
20
|
+
plugin ||= 'plugin'
|
|
21
|
+
msg = ": #{msg}" if msg
|
|
22
|
+
puts "Error in #{plugin}#{msg}"
|
|
23
|
+
|
|
24
|
+
super()
|
|
25
|
+
|
|
26
|
+
Process.exit 1
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/searchlink/output.rb
CHANGED
|
@@ -62,13 +62,16 @@ module SL
|
|
|
62
62
|
|
|
63
63
|
# Posts macOS notifications
|
|
64
64
|
#
|
|
65
|
-
# @param
|
|
66
|
-
# @param
|
|
65
|
+
# @param title [String] The title of the notification
|
|
66
|
+
# @param subtitle [String] The text of the notification
|
|
67
67
|
#
|
|
68
|
-
def notify(
|
|
68
|
+
def notify(title, subtitle)
|
|
69
69
|
return unless SL.config['notifications']
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
title = title.gsub(/"/, '\\"')
|
|
72
|
+
subtitle = subtitle.gsub(/"/, '\\"')
|
|
73
|
+
|
|
74
|
+
`osascript -e 'display notification "SearchLink" with title "#{title}" subtitle "#{subtitle}"'`
|
|
72
75
|
end
|
|
73
76
|
end
|
|
74
77
|
end
|
data/lib/searchlink/parse.rb
CHANGED
|
@@ -20,14 +20,14 @@ module SL
|
|
|
20
20
|
|
|
21
21
|
input.parse_flags! unless skip_flags
|
|
22
22
|
|
|
23
|
-
options = %w[debug country_code inline prefix_random include_titles remove_seo validate_links]
|
|
23
|
+
options = %w[debug country_code inline prefix_random include_titles remove_seo validate_links complete_bare]
|
|
24
24
|
options.each do |o|
|
|
25
25
|
if input =~ /^ *#{o}:\s+(\S+)$/
|
|
26
26
|
val = Regexp.last_match(1).strip
|
|
27
27
|
val = true if val =~ /true/i
|
|
28
28
|
val = false if val =~ /false/i
|
|
29
29
|
SL.config[o] = val
|
|
30
|
-
|
|
30
|
+
warn "\r\033[0KGlobal config: #{o} = #{SL.config[o]}\n" unless SILENT
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
next if skip_flags
|
|
@@ -57,7 +57,7 @@ module SL
|
|
|
57
57
|
case input.strip
|
|
58
58
|
when /^!?help$/i
|
|
59
59
|
if SILENT
|
|
60
|
-
help_dialog
|
|
60
|
+
help_dialog
|
|
61
61
|
else
|
|
62
62
|
$stdout.puts SL.version_check.to_s
|
|
63
63
|
$stdout.puts 'See https://github.com/ttscoff/searchlink/wiki for help'
|
|
@@ -75,6 +75,117 @@ module SL
|
|
|
75
75
|
Process.exit 0
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
def create_footnote(mtch)
|
|
79
|
+
if mtch[1].nil? || mtch[1] == ''
|
|
80
|
+
match
|
|
81
|
+
else
|
|
82
|
+
note = mtch[1].strip
|
|
83
|
+
@footnote_counter += 1
|
|
84
|
+
ref = if !@link_text.empty? && @link_text.scan(/\s/).empty?
|
|
85
|
+
@link_text
|
|
86
|
+
else
|
|
87
|
+
format('%<p>sfn%<c>04d', p: @prefix, c: @footnote_counter)
|
|
88
|
+
end
|
|
89
|
+
SL.add_footer "[^#{ref}]: #{note}"
|
|
90
|
+
res = "[^#{ref}]"
|
|
91
|
+
@cursor_difference += (SL.match_length - res.length)
|
|
92
|
+
SL.match_length = res.length
|
|
93
|
+
SL.add_report("#{@match_string} => Footnote #{ref}")
|
|
94
|
+
res
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def add_title(link_info)
|
|
99
|
+
@url = link_info
|
|
100
|
+
title = SL::URL.title(@url)
|
|
101
|
+
@link_text = title
|
|
102
|
+
|
|
103
|
+
if @ref_title
|
|
104
|
+
unless @links.key? @url
|
|
105
|
+
@links[@url] = @link_text
|
|
106
|
+
SL.add_footer SL.make_link(:ref_title, @link_text, @url, title: title, force_title: false)
|
|
107
|
+
end
|
|
108
|
+
@delete_line = true
|
|
109
|
+
elsif SL.config['inline']
|
|
110
|
+
res = SL.make_link(:inline, @link_text, @url, title: title, force_title: false)
|
|
111
|
+
@cursor_difference += SL.match_length - res.length
|
|
112
|
+
SL.match_length = res.length
|
|
113
|
+
SL.add_report("#{@match_string} => #{@url}")
|
|
114
|
+
res
|
|
115
|
+
else
|
|
116
|
+
unless @links.key? @url
|
|
117
|
+
@highest_marker += 1
|
|
118
|
+
@links[@url] = format('%<pre>s%<m>04d', pre: @prefix, m: @highest_marker)
|
|
119
|
+
SL.add_footer SL.make_link(:ref_title, @links[@url], @url, title: title, force_title: false)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
type = SL.config['inline'] ? :inline : :ref_link
|
|
123
|
+
res = SL.make_link(type, @link_text, @links[@url], title: false, force_title: false)
|
|
124
|
+
@cursor_difference += SL.match_length - res.length
|
|
125
|
+
SL.match_length = res.length
|
|
126
|
+
SL.add_report("#{@match_string} => #{@url}")
|
|
127
|
+
res
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def custom_search(search_type, search_terms)
|
|
132
|
+
SL.config['custom_site_searches'].each do |k, v|
|
|
133
|
+
next unless search_type == k
|
|
134
|
+
|
|
135
|
+
@link_text = search_terms if !SL.titleize && @link_text == ''
|
|
136
|
+
v = parse_arguments(v, { no_restore: true })
|
|
137
|
+
if v =~ %r{^(/|http)}i
|
|
138
|
+
search_type = 'r'
|
|
139
|
+
tokens = v.scan(/\$term\d+[ds]?/).sort.uniq
|
|
140
|
+
|
|
141
|
+
if !tokens.empty?
|
|
142
|
+
highest_token = 0
|
|
143
|
+
tokens.each do |token|
|
|
144
|
+
if token =~ /(\d+)[ds]?$/ && Regexp.last_match(1).to_i > highest_token
|
|
145
|
+
highest_token = Regexp.last_match(1).to_i
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
terms_p = search_terms.split(/ +/)
|
|
149
|
+
if terms_p.length > highest_token
|
|
150
|
+
remainder = terms_p[highest_token - 1..-1].join(' ')
|
|
151
|
+
terms_p = terms_p[0..highest_token - 2]
|
|
152
|
+
terms_p.push(remainder)
|
|
153
|
+
end
|
|
154
|
+
tokens.each do |t|
|
|
155
|
+
next unless t =~ /(\d+)[ds]?$/
|
|
156
|
+
|
|
157
|
+
int = Regexp.last_match(1).to_i - 1
|
|
158
|
+
replacement = terms_p[int]
|
|
159
|
+
case t
|
|
160
|
+
when /d$/
|
|
161
|
+
replacement.downcase!
|
|
162
|
+
re_down = ''
|
|
163
|
+
when /s$/
|
|
164
|
+
replacement.slugify!
|
|
165
|
+
re_down = ''
|
|
166
|
+
else
|
|
167
|
+
re_down = '(?!d|s)'
|
|
168
|
+
end
|
|
169
|
+
v.gsub!(/#{Regexp.escape(t) + re_down}/, replacement.url_encode)
|
|
170
|
+
end
|
|
171
|
+
search_terms = v
|
|
172
|
+
else
|
|
173
|
+
search_terms = v.gsub(/\$term[ds]?/i) do |mtch|
|
|
174
|
+
search_terms.downcase! if mtch =~ /d$/i
|
|
175
|
+
search_terms.slugify! if mtch =~ /s$/i
|
|
176
|
+
search_terms.url_encode
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
else
|
|
180
|
+
search_type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
181
|
+
search_terms = "site:#{v} #{search_terms}"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
break
|
|
185
|
+
end
|
|
186
|
+
[search_type, search_terms]
|
|
187
|
+
end
|
|
188
|
+
|
|
78
189
|
def parse(input)
|
|
79
190
|
SL.output = []
|
|
80
191
|
return false if input.empty?
|
|
@@ -94,7 +205,7 @@ module SL
|
|
|
94
205
|
SL.add_output("<!-- v#{latest_version} available, run SearchLink on the word 'update' to install. -->")
|
|
95
206
|
end
|
|
96
207
|
|
|
97
|
-
links = {}
|
|
208
|
+
@links = {}
|
|
98
209
|
SL.footer = []
|
|
99
210
|
counter_links = 0
|
|
100
211
|
counter_errors = 0
|
|
@@ -102,9 +213,9 @@ module SL
|
|
|
102
213
|
input.sub!(/\n?<!-- Report:.*?-->\n?/m, '')
|
|
103
214
|
input.sub!(/\n?<!-- Errors:.*?-->\n?/m, '')
|
|
104
215
|
|
|
105
|
-
input.scan(/\[(.*?)\]:\s+(.*?)\n/).each { |match| links[match[1].strip] = match[0] }
|
|
216
|
+
input.scan(/\[(.*?)\]:\s+(.*?)\n/).each { |match| @links[match[1].strip] = match[0] }
|
|
106
217
|
|
|
107
|
-
prefix = if SL.config['prefix_random']
|
|
218
|
+
@prefix = if SL.config['prefix_random']
|
|
108
219
|
if input =~ /\[(\d{4}-)\d+\]: \S+/
|
|
109
220
|
Regexp.last_match(1)
|
|
110
221
|
else
|
|
@@ -114,16 +225,27 @@ module SL
|
|
|
114
225
|
''
|
|
115
226
|
end
|
|
116
227
|
|
|
117
|
-
highest_marker = 0
|
|
118
|
-
input.scan(/^\s{,3}\[(?:#{prefix})?(\d+)\]: /).each do
|
|
228
|
+
@highest_marker = 0
|
|
229
|
+
input.scan(/^\s{,3}\[(?:#{@prefix})?(\d+)\]: /).each do
|
|
119
230
|
m = Regexp.last_match
|
|
120
|
-
highest_marker = m[1].to_i if m[1].to_i > highest_marker
|
|
231
|
+
@highest_marker = m[1].to_i if m[1].to_i > @highest_marker
|
|
121
232
|
end
|
|
122
233
|
|
|
123
|
-
footnote_counter = 0
|
|
124
|
-
input.scan(/^\s{,3}\[\^(?:#{prefix})?fn(\d+)\]: /).each do
|
|
234
|
+
@footnote_counter = 0
|
|
235
|
+
input.scan(/^\s{,3}\[\^(?:#{@prefix})?fn(\d+)\]: /).each do
|
|
125
236
|
m = Regexp.last_match
|
|
126
|
-
footnote_counter = m[1].to_i if m[1].to_i > footnote_counter
|
|
237
|
+
@footnote_counter = m[1].to_i if m[1].to_i > @footnote_counter
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
if SL.config['complete_bare']
|
|
241
|
+
rx = %r{(?ix-m)(?<!\(|:\s|<)(?:
|
|
242
|
+
(?:https?://)(?:[\da-z.-]+)\.(?:[a-z.]{2,6})
|
|
243
|
+
(?:[/\w\d.\-()_/+=?&%]*?(?=[\s\n]|$))
|
|
244
|
+
)}
|
|
245
|
+
input.gsub!(rx) do
|
|
246
|
+
url_match = Regexp.last_match
|
|
247
|
+
url_match.pre_match =~ /!\S+ +$/ ? url_match[0] : "[%](#{url_match[0]})"
|
|
248
|
+
end
|
|
127
249
|
end
|
|
128
250
|
|
|
129
251
|
if input =~ /\[(.*?)\]\((.*?)\)/
|
|
@@ -135,7 +257,7 @@ module SL
|
|
|
135
257
|
line_difference = 0
|
|
136
258
|
lines.each_with_index do |line, num|
|
|
137
259
|
SL.line_num = num - line_difference
|
|
138
|
-
cursor_difference = 0
|
|
260
|
+
@cursor_difference = 0
|
|
139
261
|
# ignore links in code blocks
|
|
140
262
|
if line =~ /^( {4,}|\t+)[^*+\-]/
|
|
141
263
|
out.push(line)
|
|
@@ -155,22 +277,22 @@ module SL
|
|
|
155
277
|
next
|
|
156
278
|
end
|
|
157
279
|
|
|
158
|
-
delete_line = false
|
|
280
|
+
@delete_line = false
|
|
159
281
|
|
|
160
|
-
search_count = 0
|
|
282
|
+
@search_count = 0
|
|
161
283
|
|
|
162
284
|
line.gsub!(/\[(.*?)\]\((.*?)\)/) do |match|
|
|
163
285
|
this_match = Regexp.last_match
|
|
164
|
-
SL.match_column = this_match.begin(0) - cursor_difference
|
|
165
|
-
match_string = this_match.to_s
|
|
166
|
-
SL.match_length = match_string.length
|
|
286
|
+
SL.match_column = this_match.begin(0) - @cursor_difference
|
|
287
|
+
@match_string = this_match.to_s
|
|
288
|
+
SL.match_length = @match_string.length
|
|
167
289
|
match_before = this_match.pre_match
|
|
168
290
|
|
|
169
291
|
invalid_search = false
|
|
170
|
-
ref_title = false
|
|
292
|
+
@ref_title = false
|
|
171
293
|
|
|
172
294
|
if match_before.scan(/(^|[^\\])`/).length.odd?
|
|
173
|
-
SL.add_report("Match '#{match_string}' within an inline code block")
|
|
295
|
+
SL.add_report("Match '#{@match_string}' within an inline code block")
|
|
174
296
|
invalid_search = true
|
|
175
297
|
end
|
|
176
298
|
|
|
@@ -179,14 +301,14 @@ module SL
|
|
|
179
301
|
$stderr.print("\033[0K\rProcessed: #{counter_links} of #{total_links}, #{counter_errors} errors. ")
|
|
180
302
|
end
|
|
181
303
|
|
|
182
|
-
link_text = this_match[1] || ''
|
|
304
|
+
@link_text = this_match[1] || ''
|
|
183
305
|
link_info = parse_arguments(this_match[2].strip).strip || ''
|
|
184
306
|
|
|
185
|
-
if link_text.strip == '' && link_info =~ /".*?"/
|
|
307
|
+
if @link_text.strip == '' && link_info =~ /".*?"/
|
|
186
308
|
link_info.gsub!(/"(.*?)"/) do
|
|
187
|
-
m = Regexp.last_match
|
|
188
|
-
link_text = m if link_text == ''
|
|
189
|
-
|
|
309
|
+
m = Regexp.last_match
|
|
310
|
+
@link_text = m[1] if @link_text == ''
|
|
311
|
+
m[0]
|
|
190
312
|
end
|
|
191
313
|
end
|
|
192
314
|
|
|
@@ -195,11 +317,11 @@ module SL
|
|
|
195
317
|
end
|
|
196
318
|
|
|
197
319
|
if link_info.strip =~ /:$/ && line.strip == match
|
|
198
|
-
ref_title = true
|
|
320
|
+
@ref_title = true
|
|
199
321
|
link_info.sub!(/\s*:\s*$/, '')
|
|
200
322
|
end
|
|
201
323
|
|
|
202
|
-
unless
|
|
324
|
+
unless !@link_text.empty? || !link_info.sub(/^[!\^]\S+/, '').strip.empty?
|
|
203
325
|
SL.add_error('No input', match)
|
|
204
326
|
counter_errors += 1
|
|
205
327
|
invalid_search = true
|
|
@@ -217,60 +339,15 @@ module SL
|
|
|
217
339
|
match
|
|
218
340
|
elsif link_info =~ /^\^(.+)/
|
|
219
341
|
m = Regexp.last_match
|
|
220
|
-
|
|
221
|
-
match
|
|
222
|
-
else
|
|
223
|
-
note = m[1].strip
|
|
224
|
-
footnote_counter += 1
|
|
225
|
-
ref = if !link_text.empty? && link_text.scan(/\s/).empty?
|
|
226
|
-
link_text
|
|
227
|
-
else
|
|
228
|
-
format('%<p>sfn%<c>04d', p: prefix, c: footnote_counter)
|
|
229
|
-
end
|
|
230
|
-
SL.add_footer "[^#{ref}]: #{note}"
|
|
231
|
-
res = "[^#{ref}]"
|
|
232
|
-
cursor_difference += (SL.match_length - res.length)
|
|
233
|
-
SL.match_length = res.length
|
|
234
|
-
SL.add_report("#{match_string} => Footnote #{ref}")
|
|
235
|
-
res
|
|
236
|
-
end
|
|
342
|
+
create_footnote(m)
|
|
237
343
|
# Handle [](URL) and [%](URL), filling in title
|
|
238
|
-
elsif (link_text == '' || link_text == '%') && SL::URL.url?(link_info)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
link_text = title
|
|
242
|
-
|
|
243
|
-
if ref_title
|
|
244
|
-
unless links.key? url
|
|
245
|
-
links[url] = link_text
|
|
246
|
-
SL.add_footer SL.make_link(:ref_title, link_text, url, title: title, force_title: false)
|
|
247
|
-
end
|
|
248
|
-
delete_line = true
|
|
249
|
-
elsif SL.config['inline']
|
|
250
|
-
res = SL.make_link(:inline, link_text, url, title: title, force_title: false)
|
|
251
|
-
cursor_difference += SL.match_length - res.length
|
|
252
|
-
SL.match_length = res.length
|
|
253
|
-
SL.add_report("#{match_string} => #{url}")
|
|
254
|
-
res
|
|
255
|
-
else
|
|
256
|
-
unless links.key? url
|
|
257
|
-
highest_marker += 1
|
|
258
|
-
links[url] = format('%<pre>s%<m>04d', pre: prefix, m: highest_marker)
|
|
259
|
-
SL.add_footer SL.make_link(:ref_title, links[url], url, title: title, force_title: false)
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
type = SL.config['inline'] ? :inline : :ref_link
|
|
263
|
-
res = SL.make_link(type, link_text, links[url], title: false, force_title: false)
|
|
264
|
-
cursor_difference += SL.match_length - res.length
|
|
265
|
-
SL.match_length = res.length
|
|
266
|
-
SL.add_report("#{match_string} => #{url}")
|
|
267
|
-
res
|
|
268
|
-
end
|
|
269
|
-
elsif (link_text == '' && link_info == '') || SL::URL.url?(link_info)
|
|
344
|
+
elsif (@link_text == '' || @link_text == '%') && SL::URL.url?(link_info)
|
|
345
|
+
add_title(link_info)
|
|
346
|
+
elsif (@link_text == '' && link_info == '') || SL::URL.url?(link_info)
|
|
270
347
|
SL.add_error('Invalid search', match) unless SL::URL.url?(link_info)
|
|
271
348
|
match
|
|
272
349
|
else
|
|
273
|
-
link_info = link_text if
|
|
350
|
+
link_info = @link_text if !@link_text.empty? && link_info == ''
|
|
274
351
|
|
|
275
352
|
search_type = ''
|
|
276
353
|
search_terms = ''
|
|
@@ -291,15 +368,15 @@ module SL
|
|
|
291
368
|
search_terms.strip!
|
|
292
369
|
|
|
293
370
|
# if the link text is just '%' replace with title regardless of config settings
|
|
294
|
-
if link_text == '%' && search_terms && !search_terms.empty?
|
|
371
|
+
if @link_text == '%' && search_terms && !search_terms.empty?
|
|
295
372
|
SL.titleize = true
|
|
296
|
-
link_text = ''
|
|
373
|
+
@link_text = ''
|
|
297
374
|
end
|
|
298
375
|
|
|
299
|
-
search_terms = link_text if search_terms == ''
|
|
376
|
+
search_terms = @link_text if search_terms == ''
|
|
300
377
|
|
|
301
378
|
# if the input starts with a +, append it to the link text as the search terms
|
|
302
|
-
search_terms = "#{link_text} #{search_terms.strip.sub(/^\+\s*/, '')}" if search_terms.strip =~ /^\+[^+]/
|
|
379
|
+
search_terms = "#{@link_text} #{search_terms.strip.sub(/^\+\s*/, '')}" if search_terms.strip =~ /^\+[^+]/
|
|
303
380
|
|
|
304
381
|
# if the end of input contain "^", copy to clipboard instead of STDOUT
|
|
305
382
|
SL.clipboard = true if search_terms =~ /(!!)?\^(!!)?$/
|
|
@@ -314,19 +391,19 @@ module SL
|
|
|
314
391
|
|
|
315
392
|
if search_word && SL::Searches.valid_search?(search_word[1])
|
|
316
393
|
search_type = search_word[1] unless search_word.nil?
|
|
317
|
-
search_terms = link_text
|
|
394
|
+
search_terms = @link_text
|
|
318
395
|
elsif search_word && search_word[1] =~ /^(\S+\.)+\S+$/
|
|
319
396
|
search_type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
320
397
|
puts SL::GoogleSearch.api_key?
|
|
321
|
-
search_terms = "site:#{search_word[1]} #{link_text}"
|
|
398
|
+
search_terms = "site:#{search_word[1]} #{@link_text}"
|
|
322
399
|
else
|
|
323
400
|
SL.add_error("Invalid search#{SL::Searches.did_you_mean(search_word[1])}", match)
|
|
324
401
|
search_type = false
|
|
325
402
|
search_terms = false
|
|
326
403
|
end
|
|
327
|
-
elsif link_text &&
|
|
404
|
+
elsif @link_text && !@link_text.empty? && (!link_info || link_info.empty?)
|
|
328
405
|
search_type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
329
|
-
search_terms = link_text
|
|
406
|
+
search_terms = @link_text
|
|
330
407
|
elsif link_info && !link_info.empty?
|
|
331
408
|
search_type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
332
409
|
search_terms = link_info
|
|
@@ -337,109 +414,64 @@ module SL
|
|
|
337
414
|
end
|
|
338
415
|
|
|
339
416
|
if search_type && !search_terms.empty?
|
|
340
|
-
|
|
341
|
-
next unless search_type == k
|
|
342
|
-
|
|
343
|
-
link_text = search_terms if !SL.titleize && link_text == ''
|
|
344
|
-
v = parse_arguments(v, { no_restore: true })
|
|
345
|
-
if v =~ %r{^(/|http)}i
|
|
346
|
-
search_type = 'r'
|
|
347
|
-
tokens = v.scan(/\$term\d+[ds]?/).sort.uniq
|
|
348
|
-
|
|
349
|
-
if !tokens.empty?
|
|
350
|
-
highest_token = 0
|
|
351
|
-
tokens.each do |token|
|
|
352
|
-
if token =~ /(\d+)[ds]?$/ && Regexp.last_match(1).to_i > highest_token
|
|
353
|
-
highest_token = Regexp.last_match(1).to_i
|
|
354
|
-
end
|
|
355
|
-
end
|
|
356
|
-
terms_p = search_terms.split(/ +/)
|
|
357
|
-
if terms_p.length > highest_token
|
|
358
|
-
remainder = terms_p[highest_token - 1..-1].join(' ')
|
|
359
|
-
terms_p = terms_p[0..highest_token - 2]
|
|
360
|
-
terms_p.push(remainder)
|
|
361
|
-
end
|
|
362
|
-
tokens.each do |t|
|
|
363
|
-
next unless t =~ /(\d+)[ds]?$/
|
|
364
|
-
|
|
365
|
-
int = Regexp.last_match(1).to_i - 1
|
|
366
|
-
replacement = terms_p[int]
|
|
367
|
-
case t
|
|
368
|
-
when /d$/
|
|
369
|
-
replacement.downcase!
|
|
370
|
-
re_down = ''
|
|
371
|
-
when /s$/
|
|
372
|
-
replacement.slugify!
|
|
373
|
-
re_down = ''
|
|
374
|
-
else
|
|
375
|
-
re_down = '(?!d|s)'
|
|
376
|
-
end
|
|
377
|
-
v.gsub!(/#{Regexp.escape(t) + re_down}/, replacement.url_encode)
|
|
378
|
-
end
|
|
379
|
-
search_terms = v
|
|
380
|
-
else
|
|
381
|
-
search_terms = v.gsub(/\$term[ds]?/i) do |mtch|
|
|
382
|
-
search_terms.downcase! if mtch =~ /d$/i
|
|
383
|
-
search_terms.slugify! if mtch =~ /s$/i
|
|
384
|
-
search_terms.url_encode
|
|
385
|
-
end
|
|
386
|
-
end
|
|
387
|
-
else
|
|
388
|
-
search_type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
389
|
-
search_terms = "site:#{v} #{search_terms}"
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
break
|
|
393
|
-
end
|
|
417
|
+
search_type, search_terms = custom_search(search_type, search_terms)
|
|
394
418
|
end
|
|
395
419
|
|
|
396
|
-
if (search_type && search_terms) || url
|
|
420
|
+
if (search_type && search_terms) || @url
|
|
397
421
|
# warn "Searching #{search_type} for #{search_terms}"
|
|
398
|
-
unless url
|
|
399
|
-
search_count += 1
|
|
400
|
-
url, title, link_text = do_search(search_type, search_terms, link_text, search_count)
|
|
422
|
+
unless @url
|
|
423
|
+
@search_count += 1
|
|
424
|
+
@url, title, @link_text = do_search(search_type, search_terms, @link_text, @search_count)
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
if (@link_text == '' || @link_text == '%') && @url
|
|
428
|
+
if title
|
|
429
|
+
@link_text = title
|
|
430
|
+
else
|
|
431
|
+
add_title(@url)
|
|
432
|
+
end
|
|
401
433
|
end
|
|
402
434
|
|
|
403
|
-
if url
|
|
404
|
-
title = SL::URL.title(url) if SL.titleize && title == ''
|
|
435
|
+
if @url
|
|
436
|
+
title = SL::URL.title(@url) if SL.titleize && title == ''
|
|
405
437
|
|
|
406
|
-
link_text = title if link_text == '' && title
|
|
438
|
+
@link_text = title if @link_text == '' && title
|
|
407
439
|
force_title = search_type =~ /def/ ? true : false
|
|
408
440
|
|
|
409
|
-
if link_only || search_type =~ /sp(ell)?/ || url == 'embed'
|
|
410
|
-
url = title if url == 'embed'
|
|
411
|
-
cursor_difference += SL.match_length - url.length
|
|
412
|
-
SL.match_length = url.length
|
|
413
|
-
SL.add_report("#{match_string} => #{url}")
|
|
414
|
-
url
|
|
415
|
-
elsif ref_title
|
|
416
|
-
unless links.key? url
|
|
417
|
-
links[url] = link_text
|
|
418
|
-
SL.add_footer SL.make_link(:ref_title, link_text, url, title: title, force_title: force_title)
|
|
441
|
+
if link_only || search_type =~ /sp(ell)?/ || @url == 'embed'
|
|
442
|
+
@url = title if @url == 'embed'
|
|
443
|
+
@cursor_difference += SL.match_length - @url.length
|
|
444
|
+
SL.match_length = @url.length
|
|
445
|
+
SL.add_report("#{@match_string} => #{@url}")
|
|
446
|
+
@url
|
|
447
|
+
elsif @ref_title
|
|
448
|
+
unless @links.key? @url
|
|
449
|
+
@links[@url] = @link_text
|
|
450
|
+
SL.add_footer SL.make_link(:ref_title, @link_text, @url, title: title, force_title: force_title)
|
|
419
451
|
end
|
|
420
|
-
delete_line = true
|
|
452
|
+
@delete_line = true
|
|
421
453
|
elsif SL.config['inline']
|
|
422
|
-
res = SL.make_link(:inline, link_text, url, title: title, force_title: force_title)
|
|
423
|
-
cursor_difference += SL.match_length - res.length
|
|
454
|
+
res = SL.make_link(:inline, @link_text, @url, title: title, force_title: force_title)
|
|
455
|
+
@cursor_difference += SL.match_length - res.length
|
|
424
456
|
SL.match_length = res.length
|
|
425
|
-
SL.add_report("#{match_string} => #{url}")
|
|
457
|
+
SL.add_report("#{@match_string} => #{@url}")
|
|
426
458
|
res
|
|
427
459
|
else
|
|
428
|
-
unless links.key? url
|
|
429
|
-
highest_marker += 1
|
|
430
|
-
links[url] = format('%<pre>s%<m>04d', pre: prefix, m: highest_marker)
|
|
431
|
-
SL.add_footer SL.make_link(:ref_title, links[url], url, title: title, force_title: force_title)
|
|
460
|
+
unless @links.key? @url
|
|
461
|
+
@highest_marker += 1
|
|
462
|
+
@links[@url] = format('%<pre>s%<m>04d', pre: @prefix, m: @highest_marker)
|
|
463
|
+
SL.add_footer SL.make_link(:ref_title, @links[@url], @url, title: title, force_title: force_title)
|
|
432
464
|
end
|
|
433
465
|
|
|
434
466
|
type = SL.config['inline'] ? :inline : :ref_link
|
|
435
|
-
res = SL.make_link(type, link_text, links[url], title: false, force_title: force_title)
|
|
436
|
-
cursor_difference += SL.match_length - res.length
|
|
467
|
+
res = SL.make_link(type, @link_text, @links[@url], title: false, force_title: force_title)
|
|
468
|
+
@cursor_difference += SL.match_length - res.length
|
|
437
469
|
SL.match_length = res.length
|
|
438
|
-
SL.add_report("#{match_string} => #{url}")
|
|
470
|
+
SL.add_report("#{@match_string} => #{@url}")
|
|
439
471
|
res
|
|
440
472
|
end
|
|
441
473
|
else
|
|
442
|
-
SL.add_error('No results', "#{search_terms} (#{match_string})")
|
|
474
|
+
SL.add_error('No results', "#{search_terms} (#{@match_string})")
|
|
443
475
|
counter_errors += 1
|
|
444
476
|
match
|
|
445
477
|
end
|
|
@@ -450,9 +482,9 @@ module SL
|
|
|
450
482
|
end
|
|
451
483
|
end
|
|
452
484
|
end
|
|
453
|
-
line_difference += 1 if delete_line
|
|
454
|
-
out.push(line) unless delete_line
|
|
455
|
-
delete_line = false
|
|
485
|
+
line_difference += 1 if @delete_line
|
|
486
|
+
out.push(line) unless @delete_line
|
|
487
|
+
@delete_line = false
|
|
456
488
|
end
|
|
457
489
|
warn "\n" unless SILENT
|
|
458
490
|
|
|
@@ -514,8 +546,8 @@ module SL
|
|
|
514
546
|
## using hostname as text without doing search
|
|
515
547
|
if SL::URL.only_url?(input.strip)
|
|
516
548
|
type = reference_link ? :ref_title : :inline
|
|
517
|
-
url, title = SL::URL.url_to_link(input.strip, type)
|
|
518
|
-
print SL.make_link(type, title, url, title: false, force_title: false)
|
|
549
|
+
@url, title = SL::URL.url_to_link(input.strip, type)
|
|
550
|
+
print SL.make_link(type, title, @url, title: false, force_title: false)
|
|
519
551
|
Process.exit
|
|
520
552
|
end
|
|
521
553
|
|
|
@@ -532,10 +564,10 @@ module SL
|
|
|
532
564
|
# input.sub!(/\+.*?$/, '').strip!
|
|
533
565
|
# end
|
|
534
566
|
|
|
535
|
-
link_text = false
|
|
567
|
+
@link_text = false
|
|
536
568
|
|
|
537
569
|
if input =~ /"(.*?)"/
|
|
538
|
-
link_text = Regexp.last_match(1)
|
|
570
|
+
@link_text = Regexp.last_match(1)
|
|
539
571
|
input.gsub!(/"(.*?)"/, '\1')
|
|
540
572
|
end
|
|
541
573
|
|
|
@@ -546,7 +578,7 @@ module SL
|
|
|
546
578
|
when /^!(\S+)\s+(.*)$/
|
|
547
579
|
type = Regexp.last_match(1)
|
|
548
580
|
link_info = Regexp.last_match(2).strip
|
|
549
|
-
link_text ||= link_info
|
|
581
|
+
@link_text ||= link_info
|
|
550
582
|
terms = link_info + additional_terms
|
|
551
583
|
terms.strip!
|
|
552
584
|
|
|
@@ -556,7 +588,7 @@ module SL
|
|
|
556
588
|
SL.config['custom_site_searches'].each do |k, v|
|
|
557
589
|
next unless type == k
|
|
558
590
|
|
|
559
|
-
link_text = terms if link_text == ''
|
|
591
|
+
@link_text = terms if @link_text == ''
|
|
560
592
|
v = parse_arguments(v, { no_restore: true })
|
|
561
593
|
if v =~ %r{^(/|http)}i
|
|
562
594
|
type = 'r'
|
|
@@ -614,10 +646,10 @@ module SL
|
|
|
614
646
|
terms = "site:#{type} #{terms}"
|
|
615
647
|
type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
|
616
648
|
end
|
|
617
|
-
search_count ||= 0
|
|
618
|
-
search_count += 1
|
|
649
|
+
@search_count ||= 0
|
|
650
|
+
@search_count += 1
|
|
619
651
|
|
|
620
|
-
url, title, link_text = do_search(type, terms, link_text, search_count)
|
|
652
|
+
@url, title, @link_text = do_search(type, terms, @link_text, @search_count)
|
|
621
653
|
else
|
|
622
654
|
SL.add_error("Invalid search#{SL::Searches.did_you_mean(type)}", input)
|
|
623
655
|
counter_errors += 1
|
|
@@ -630,25 +662,25 @@ module SL
|
|
|
630
662
|
else
|
|
631
663
|
't'
|
|
632
664
|
end
|
|
633
|
-
link_text = input.sub(/^[tfilm]/, '')
|
|
634
|
-
url, title = SL::SocialSearch.social_handle(type, link_text)
|
|
635
|
-
link_text = title
|
|
665
|
+
@link_text = input.sub(/^[tfilm]/, '')
|
|
666
|
+
@url, title = SL::SocialSearch.social_handle(type, @link_text)
|
|
667
|
+
@link_text = title
|
|
636
668
|
else
|
|
637
|
-
link_text ||= input
|
|
638
|
-
url, title, link_text = SL.ddg(input, link_text)
|
|
669
|
+
@link_text ||= input
|
|
670
|
+
@url, title, @link_text = SL.ddg(input, @link_text)
|
|
639
671
|
end
|
|
640
672
|
|
|
641
|
-
if url
|
|
673
|
+
if @url
|
|
642
674
|
if type =~ /sp(ell)?/
|
|
643
|
-
SL.add_output(url)
|
|
675
|
+
SL.add_output(@url)
|
|
644
676
|
elsif link_only
|
|
645
|
-
SL.add_output(url)
|
|
646
|
-
elsif url == 'embed'
|
|
677
|
+
SL.add_output(@url)
|
|
678
|
+
elsif @url == 'embed'
|
|
647
679
|
SL.add_output(title)
|
|
648
680
|
else
|
|
649
681
|
type = reference_link ? :ref_title : :inline
|
|
650
682
|
|
|
651
|
-
SL.add_output SL.make_link(type, link_text, url, title: title, force_title: false)
|
|
683
|
+
SL.add_output SL.make_link(type, @link_text, @url, title: title, force_title: false)
|
|
652
684
|
SL.print_errors
|
|
653
685
|
end
|
|
654
686
|
else
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# title: Script plugin
|
|
4
|
+
# description: Load custom searches from non-ruby scripts
|
|
5
|
+
module SL
|
|
6
|
+
# Script Search
|
|
7
|
+
class ScriptSearch
|
|
8
|
+
def initialize(config)
|
|
9
|
+
@filename = config['filename']
|
|
10
|
+
@path = config['path']
|
|
11
|
+
|
|
12
|
+
%w[trigger searches name script].each do |key|
|
|
13
|
+
raise PluginError.new(%(configuration missing key "#{key}"), plugin: @filename) unless config.key?(key)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@trigger = config['trigger']
|
|
17
|
+
@searches = config['searches']
|
|
18
|
+
@name = config['name']
|
|
19
|
+
@script = find_script(config['script'])
|
|
20
|
+
|
|
21
|
+
unless File.executable?(@script)
|
|
22
|
+
raise PluginError.new(%(script "#{File.basename(@script)}" not executable\nrun `chmod a+x #{@script.shorten_path}` to correct),
|
|
23
|
+
plugin: @filename)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def settings
|
|
28
|
+
{
|
|
29
|
+
trigger: @trigger,
|
|
30
|
+
searches: @searches
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def search(search_type, search_terms, link_text)
|
|
35
|
+
type = Shellwords.escape(search_type)
|
|
36
|
+
terms = Shellwords.escape(search_terms)
|
|
37
|
+
text = Shellwords.escape(link_text)
|
|
38
|
+
|
|
39
|
+
stdout = `#{[@script, type, terms, text].join(' ')} 2>&1`
|
|
40
|
+
|
|
41
|
+
unless $CHILD_STATUS.success?
|
|
42
|
+
raise PluginError.new(%("#{File.basename(@script)}" returned error #{$CHILD_STATUS.exitstatus}\n#{stdout}),
|
|
43
|
+
plugin: @filename)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
res = JSON.parse(stdout)
|
|
48
|
+
rescue JSON::ParserError
|
|
49
|
+
res = YAML.safe_load(stdout)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
unless res.is_a?(Hash)
|
|
53
|
+
raise PluginError.new(%(invalid results from "#{File.basename(@script)}", must be YAML or JSON string),
|
|
54
|
+
plugin: @filename)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
%w[url title link_text].each do |key|
|
|
58
|
+
unless res.key?(key)
|
|
59
|
+
raise PluginError.new(%("#{File.basename(@script)}" output missing key "#{key}"), plugin: @filename)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
[res['url'], res['title'], res['link_text']]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
SL::Searches.register @name, :search, self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def find_script(script)
|
|
71
|
+
return File.expand_path(script) if File.exist?(File.expand_path(script))
|
|
72
|
+
|
|
73
|
+
base = File.expand_path('~/.config/searchlink/plugins')
|
|
74
|
+
first = File.join(base, script)
|
|
75
|
+
return first if File.exist?(first)
|
|
76
|
+
|
|
77
|
+
base = File.expand_path('~/.config/searchlink')
|
|
78
|
+
second = File.join(base, script)
|
|
79
|
+
return second if File.exist?(second)
|
|
80
|
+
|
|
81
|
+
raise PluginError.new(%(Script plugin script "#{script}" not found), plugin: @filename)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -31,14 +31,25 @@ module SL
|
|
|
31
31
|
## @return [Array] Single bookmark, [url, title, date]
|
|
32
32
|
##
|
|
33
33
|
def search_brave_history(term)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
base = File.expand_path('~/Library/Application Support/BraveSoftware/Brave-Browser/')
|
|
35
|
+
profiles = Dir.glob('**/History', base: base)
|
|
36
|
+
profiles.delete_if { |p| p =~ /^Snapshots/ }
|
|
37
|
+
profiles.map! { |f| File.join(base, f) }
|
|
38
|
+
|
|
39
|
+
res = false
|
|
40
|
+
|
|
41
|
+
profiles.each do |bookmarks|
|
|
42
|
+
next unless File.exist?(bookmarks)
|
|
43
|
+
|
|
44
|
+
profile = bookmarks.match(%r{Browser/([^/]+)/})[1]
|
|
45
|
+
|
|
46
|
+
SL.notify("Searching Brave History for profile #{profile}", term)
|
|
47
|
+
res = search_chromium_history(bookmarks, term)
|
|
48
|
+
|
|
49
|
+
break if res
|
|
41
50
|
end
|
|
51
|
+
|
|
52
|
+
res
|
|
42
53
|
end
|
|
43
54
|
|
|
44
55
|
## Search Edge history
|
|
@@ -66,9 +77,7 @@ module SL
|
|
|
66
77
|
break if res
|
|
67
78
|
end
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
false
|
|
80
|
+
res
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
## Search Chrome history
|
|
@@ -99,9 +108,7 @@ module SL
|
|
|
99
108
|
break if res
|
|
100
109
|
end
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
false
|
|
111
|
+
res
|
|
105
112
|
end
|
|
106
113
|
|
|
107
114
|
##
|
|
@@ -172,7 +179,7 @@ module SL
|
|
|
172
179
|
|
|
173
180
|
if File.exist?(bookmarks_file)
|
|
174
181
|
SL.notify('Searching Arc Bookmarks', term)
|
|
175
|
-
return
|
|
182
|
+
return search_arc_json(bookmarks_file, term)
|
|
176
183
|
end
|
|
177
184
|
|
|
178
185
|
false
|
|
@@ -204,9 +211,7 @@ module SL
|
|
|
204
211
|
break if res
|
|
205
212
|
end
|
|
206
213
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
false
|
|
214
|
+
res
|
|
210
215
|
end
|
|
211
216
|
|
|
212
217
|
##
|
|
@@ -225,18 +230,16 @@ module SL
|
|
|
225
230
|
res = false
|
|
226
231
|
|
|
227
232
|
profiles.each do |bookmarks|
|
|
228
|
-
|
|
229
|
-
profile = bookmarks.match(%r{Edge/([^/]+)/})[1]
|
|
233
|
+
next unless File.exist?(bookmarks)
|
|
230
234
|
|
|
231
|
-
|
|
232
|
-
res = search_chromium_bookmarks(bookmarks, term)
|
|
233
|
-
break if res
|
|
234
|
-
end
|
|
235
|
-
end
|
|
235
|
+
profile = bookmarks.match(%r{Edge/([^/]+)/})[1]
|
|
236
236
|
|
|
237
|
-
|
|
237
|
+
SL.notify("Searching Edge Bookmarks for profile #{profile}", term)
|
|
238
|
+
res = search_chromium_bookmarks(bookmarks, term)
|
|
239
|
+
break if res
|
|
240
|
+
end
|
|
238
241
|
|
|
239
|
-
|
|
242
|
+
res
|
|
240
243
|
end
|
|
241
244
|
|
|
242
245
|
##
|
|
@@ -264,9 +267,7 @@ module SL
|
|
|
264
267
|
end
|
|
265
268
|
end
|
|
266
269
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
false
|
|
270
|
+
res
|
|
270
271
|
end
|
|
271
272
|
|
|
272
273
|
##
|
|
@@ -277,7 +278,7 @@ module SL
|
|
|
277
278
|
##
|
|
278
279
|
## @return [Array] single bookmark [url, title, date]
|
|
279
280
|
##
|
|
280
|
-
def
|
|
281
|
+
def search_arc_json(bookmarks_file, term)
|
|
281
282
|
arc_bookmarks = JSON.parse(IO.read(bookmarks_file))
|
|
282
283
|
|
|
283
284
|
exact_match = false
|
|
@@ -341,7 +342,7 @@ module SL
|
|
|
341
342
|
|
|
342
343
|
return false if bookmarks.empty?
|
|
343
344
|
|
|
344
|
-
lastest_bookmark = bookmarks.
|
|
345
|
+
lastest_bookmark = bookmarks.min_by { |u| u[:created] }
|
|
345
346
|
|
|
346
347
|
return [lastest_bookmark[:url], lastest_bookmark[:title], lastest_bookmark[:date]]
|
|
347
348
|
end
|
data/lib/searchlink/searches.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SL
|
|
4
|
+
# Searches and plugin registration
|
|
4
5
|
module Searches
|
|
5
6
|
class << self
|
|
6
7
|
def plugins
|
|
@@ -25,7 +26,7 @@ module SL
|
|
|
25
26
|
|
|
26
27
|
def description_for_search(search_type)
|
|
27
28
|
description = "#{search_type} search"
|
|
28
|
-
plugins[:search].
|
|
29
|
+
plugins[:search].each_value do |plugin|
|
|
29
30
|
search = plugin[:searches].select { |s| s[0].is_a?(Array) ? s[0].include?(search_type) : s[0] == search_type }
|
|
30
31
|
unless search.empty?
|
|
31
32
|
description = search[0][1]
|
|
@@ -50,7 +51,11 @@ module SL
|
|
|
50
51
|
'<tbody>']
|
|
51
52
|
|
|
52
53
|
searches.each do |s|
|
|
53
|
-
out << "<tr
|
|
54
|
+
out << "<tr>
|
|
55
|
+
<td>
|
|
56
|
+
<code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(',')})" : s[0]}
|
|
57
|
+
</code>
|
|
58
|
+
</td><td>#{s[1]}</td></tr>"
|
|
54
59
|
end
|
|
55
60
|
out.concat(['</tbody>', '</table>']).join("\n")
|
|
56
61
|
end
|
|
@@ -62,7 +67,7 @@ module SL
|
|
|
62
67
|
#
|
|
63
68
|
def available_searches
|
|
64
69
|
searches = []
|
|
65
|
-
plugins[:search].
|
|
70
|
+
plugins[:search].each_value { |plugin| searches.concat(plugin[:searches].delete_if { |s| s[1].nil? }) }
|
|
66
71
|
out = []
|
|
67
72
|
searches.each do |s|
|
|
68
73
|
out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(',')})" : s[0]}#{s[0].spacer}#{s[1]}"
|
|
@@ -77,8 +82,8 @@ module SL
|
|
|
77
82
|
|
|
78
83
|
def all_possible_searches
|
|
79
84
|
searches = []
|
|
80
|
-
plugins[:search].
|
|
81
|
-
searches.concat(SL.config['custom_site_searches'].keys)
|
|
85
|
+
plugins[:search].each_value { |plugin| plugin[:searches].each { |s| searches.push(s[0]) } }
|
|
86
|
+
searches.concat(SL.config['custom_site_searches'].keys.sort)
|
|
82
87
|
end
|
|
83
88
|
|
|
84
89
|
def did_you_mean(term)
|
|
@@ -101,11 +106,11 @@ module SL
|
|
|
101
106
|
end
|
|
102
107
|
|
|
103
108
|
def register_plugin(title, type, klass)
|
|
104
|
-
raise
|
|
109
|
+
raise PluginError.new("Plugin has no settings method", plugin: title) unless klass.respond_to? :settings
|
|
105
110
|
|
|
106
111
|
settings = klass.settings
|
|
107
112
|
|
|
108
|
-
raise
|
|
113
|
+
raise PluginError.new("Plugin has no search method", plugin: title) unless klass.respond_to? :search
|
|
109
114
|
|
|
110
115
|
plugins[type] ||= {}
|
|
111
116
|
plugins[type][title] = {
|
|
@@ -123,6 +128,8 @@ module SL
|
|
|
123
128
|
Dir.glob(File.join(plugins_folder, '**/*.rb')).sort.each do |plugin|
|
|
124
129
|
require plugin
|
|
125
130
|
end
|
|
131
|
+
|
|
132
|
+
load_custom_scripts(plugins_folder)
|
|
126
133
|
end
|
|
127
134
|
|
|
128
135
|
return unless File.directory?(new_plugins_folder)
|
|
@@ -130,6 +137,25 @@ module SL
|
|
|
130
137
|
Dir.glob(File.join(new_plugins_folder, '**/*.rb')).sort.each do |plugin|
|
|
131
138
|
require plugin
|
|
132
139
|
end
|
|
140
|
+
|
|
141
|
+
load_custom_scripts(new_plugins_folder)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def load_custom_scripts(plugins_folder)
|
|
145
|
+
Dir.glob(File.join(plugins_folder, '**/*.{json,yml,yaml}')).each do |file|
|
|
146
|
+
ext = File.extname(file).sub(/^\./, '')
|
|
147
|
+
config = IO.read(file)
|
|
148
|
+
|
|
149
|
+
cfg = case ext
|
|
150
|
+
when /^y/i
|
|
151
|
+
YAML.safe_load(config)
|
|
152
|
+
else
|
|
153
|
+
JSON.parse(config)
|
|
154
|
+
end
|
|
155
|
+
cfg['filename'] = File.basename(file)
|
|
156
|
+
cfg['path'] = file.shorten_path
|
|
157
|
+
SL::ScriptSearch.new(cfg)
|
|
158
|
+
end
|
|
133
159
|
end
|
|
134
160
|
|
|
135
161
|
def do_search(search_type, search_terms, link_text, timeout: SL.config['timeout'])
|
data/lib/searchlink/semver.rb
CHANGED
|
@@ -5,14 +5,14 @@ module SL
|
|
|
5
5
|
class SemVer
|
|
6
6
|
attr_accessor :maj, :min, :patch, :pre
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
## Initialize a Semantic Version object
|
|
9
|
+
##
|
|
10
|
+
## @param version_string [String] a semantic version number
|
|
11
|
+
##
|
|
12
|
+
## @return [SemVer] SemVer object
|
|
13
|
+
##
|
|
14
14
|
def initialize(version_string)
|
|
15
|
-
raise "Invalid semantic version number: #{version_string}" unless version_string.valid_version?
|
|
15
|
+
raise VersionError.new("Invalid semantic version number: #{version_string}") unless version_string.valid_version?
|
|
16
16
|
|
|
17
17
|
@maj, @min, @patch = version_string.split(/\./)
|
|
18
18
|
@pre = nil
|
data/lib/searchlink/string.rb
CHANGED
|
@@ -488,5 +488,13 @@ module SL
|
|
|
488
488
|
def code_indent
|
|
489
489
|
split(/\n/).map { |l| " #{l}" }.join("\n")
|
|
490
490
|
end
|
|
491
|
+
|
|
492
|
+
##
|
|
493
|
+
## Shorten path by adding ~ for home directory
|
|
494
|
+
##
|
|
495
|
+
def shorten_path
|
|
496
|
+
home_directory = ENV['HOME']
|
|
497
|
+
sub(home_directory, '~')
|
|
498
|
+
end
|
|
491
499
|
end
|
|
492
500
|
end
|
data/lib/searchlink/version.rb
CHANGED
data/lib/searchlink.rb
CHANGED
|
@@ -13,10 +13,14 @@ require 'zlib'
|
|
|
13
13
|
require 'time'
|
|
14
14
|
require 'json'
|
|
15
15
|
require 'erb'
|
|
16
|
+
require 'english'
|
|
16
17
|
|
|
17
18
|
# import
|
|
18
19
|
require 'tokens' if File.exist?('lib/tokens.rb')
|
|
19
20
|
|
|
21
|
+
# import
|
|
22
|
+
require 'searchlink/exceptions'
|
|
23
|
+
|
|
20
24
|
# import
|
|
21
25
|
require 'searchlink/number'
|
|
22
26
|
|
|
@@ -65,4 +69,7 @@ require 'searchlink/output'
|
|
|
65
69
|
# import
|
|
66
70
|
require 'searchlink/which'
|
|
67
71
|
|
|
72
|
+
# import
|
|
73
|
+
require 'searchlink/script_plugin'
|
|
74
|
+
|
|
68
75
|
module Secrets; end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: searchlink
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.71
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brett Terpstra
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-08-
|
|
11
|
+
date: 2024-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -235,11 +235,13 @@ files:
|
|
|
235
235
|
- lib/searchlink/curl.rb
|
|
236
236
|
- lib/searchlink/curl/html.rb
|
|
237
237
|
- lib/searchlink/curl/json.rb
|
|
238
|
+
- lib/searchlink/exceptions.rb
|
|
238
239
|
- lib/searchlink/help.rb
|
|
239
240
|
- lib/searchlink/number.rb
|
|
240
241
|
- lib/searchlink/output.rb
|
|
241
242
|
- lib/searchlink/parse.rb
|
|
242
243
|
- lib/searchlink/plist.rb
|
|
244
|
+
- lib/searchlink/script_plugin.rb
|
|
243
245
|
- lib/searchlink/search.rb
|
|
244
246
|
- lib/searchlink/searches.rb
|
|
245
247
|
- lib/searchlink/searches/amazon.rb
|