searchlink 2.3.69 → 2.3.70
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/searchlink/exceptions.rb +29 -0
- data/lib/searchlink/output.rb +7 -4
- data/lib/searchlink/parse.rb +214 -190
- data/lib/searchlink/script_plugin.rb +84 -0
- data/lib/searchlink/searches/helpers/chromium.rb +32 -31
- data/lib/searchlink/searches.rb +32 -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: 94434b4c63f4188ca00e93ad4c2be7765b61a2fdbccd3b7e706482bf1e09b618
|
4
|
+
data.tar.gz: 4af48f283d1a693bed323cdbbb91121ee5b4616225d4ecef46f80302016227ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fa2094dbbf341680baefae73f98aba890ace10c6f6d44198b7902c28810b9e3cc8121199b9ba26a1da0243dcf779c3f018ebaaa6f1e794456d72106fafe5ad6
|
7
|
+
data.tar.gz: 7a39a40fbc8e8466c3652e236eee03091b027dd83aebd481b31dcb3acaa3a53124d362887d4cbe33bc22699fadd4e7adfe40f4f40db48cb8f69754584d84ae70
|
@@ -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,56 @@ 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)
|
401
425
|
end
|
402
426
|
|
403
|
-
if url
|
404
|
-
title = SL::URL.title(url) if SL.titleize && title == ''
|
427
|
+
if @url
|
428
|
+
title = SL::URL.title(@url) if SL.titleize && title == ''
|
405
429
|
|
406
|
-
link_text = title if link_text == '' && title
|
430
|
+
@link_text = title if @link_text == '' && title
|
407
431
|
force_title = search_type =~ /def/ ? true : false
|
408
432
|
|
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)
|
433
|
+
if link_only || search_type =~ /sp(ell)?/ || @url == 'embed'
|
434
|
+
@url = title if @url == 'embed'
|
435
|
+
@cursor_difference += SL.match_length - @url.length
|
436
|
+
SL.match_length = @url.length
|
437
|
+
SL.add_report("#{@match_string} => #{@url}")
|
438
|
+
@url
|
439
|
+
elsif @ref_title
|
440
|
+
unless @links.key? @url
|
441
|
+
@links[@url] = @link_text
|
442
|
+
SL.add_footer SL.make_link(:ref_title, @link_text, @url, title: title, force_title: force_title)
|
419
443
|
end
|
420
|
-
delete_line = true
|
444
|
+
@delete_line = true
|
421
445
|
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
|
446
|
+
res = SL.make_link(:inline, @link_text, @url, title: title, force_title: force_title)
|
447
|
+
@cursor_difference += SL.match_length - res.length
|
424
448
|
SL.match_length = res.length
|
425
|
-
SL.add_report("#{match_string} => #{url}")
|
449
|
+
SL.add_report("#{@match_string} => #{@url}")
|
426
450
|
res
|
427
451
|
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)
|
452
|
+
unless @links.key? @url
|
453
|
+
@highest_marker += 1
|
454
|
+
@links[@url] = format('%<pre>s%<m>04d', pre: @prefix, m: @highest_marker)
|
455
|
+
SL.add_footer SL.make_link(:ref_title, @links[@url], @url, title: title, force_title: force_title)
|
432
456
|
end
|
433
457
|
|
434
458
|
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
|
459
|
+
res = SL.make_link(type, @link_text, @links[@url], title: false, force_title: force_title)
|
460
|
+
@cursor_difference += SL.match_length - res.length
|
437
461
|
SL.match_length = res.length
|
438
|
-
SL.add_report("#{match_string} => #{url}")
|
462
|
+
SL.add_report("#{@match_string} => #{@url}")
|
439
463
|
res
|
440
464
|
end
|
441
465
|
else
|
442
|
-
SL.add_error('No results', "#{search_terms} (#{match_string})")
|
466
|
+
SL.add_error('No results', "#{search_terms} (#{@match_string})")
|
443
467
|
counter_errors += 1
|
444
468
|
match
|
445
469
|
end
|
@@ -450,9 +474,9 @@ module SL
|
|
450
474
|
end
|
451
475
|
end
|
452
476
|
end
|
453
|
-
line_difference += 1 if delete_line
|
454
|
-
out.push(line) unless delete_line
|
455
|
-
delete_line = false
|
477
|
+
line_difference += 1 if @delete_line
|
478
|
+
out.push(line) unless @delete_line
|
479
|
+
@delete_line = false
|
456
480
|
end
|
457
481
|
warn "\n" unless SILENT
|
458
482
|
|
@@ -514,8 +538,8 @@ module SL
|
|
514
538
|
## using hostname as text without doing search
|
515
539
|
if SL::URL.only_url?(input.strip)
|
516
540
|
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)
|
541
|
+
@url, title = SL::URL.url_to_link(input.strip, type)
|
542
|
+
print SL.make_link(type, title, @url, title: false, force_title: false)
|
519
543
|
Process.exit
|
520
544
|
end
|
521
545
|
|
@@ -532,10 +556,10 @@ module SL
|
|
532
556
|
# input.sub!(/\+.*?$/, '').strip!
|
533
557
|
# end
|
534
558
|
|
535
|
-
link_text = false
|
559
|
+
@link_text = false
|
536
560
|
|
537
561
|
if input =~ /"(.*?)"/
|
538
|
-
link_text = Regexp.last_match(1)
|
562
|
+
@link_text = Regexp.last_match(1)
|
539
563
|
input.gsub!(/"(.*?)"/, '\1')
|
540
564
|
end
|
541
565
|
|
@@ -546,7 +570,7 @@ module SL
|
|
546
570
|
when /^!(\S+)\s+(.*)$/
|
547
571
|
type = Regexp.last_match(1)
|
548
572
|
link_info = Regexp.last_match(2).strip
|
549
|
-
link_text ||= link_info
|
573
|
+
@link_text ||= link_info
|
550
574
|
terms = link_info + additional_terms
|
551
575
|
terms.strip!
|
552
576
|
|
@@ -556,7 +580,7 @@ module SL
|
|
556
580
|
SL.config['custom_site_searches'].each do |k, v|
|
557
581
|
next unless type == k
|
558
582
|
|
559
|
-
link_text = terms if link_text == ''
|
583
|
+
@link_text = terms if @link_text == ''
|
560
584
|
v = parse_arguments(v, { no_restore: true })
|
561
585
|
if v =~ %r{^(/|http)}i
|
562
586
|
type = 'r'
|
@@ -614,10 +638,10 @@ module SL
|
|
614
638
|
terms = "site:#{type} #{terms}"
|
615
639
|
type = SL::GoogleSearch.api_key? ? 'gg' : 'g'
|
616
640
|
end
|
617
|
-
search_count ||= 0
|
618
|
-
search_count += 1
|
641
|
+
@search_count ||= 0
|
642
|
+
@search_count += 1
|
619
643
|
|
620
|
-
url, title, link_text = do_search(type, terms, link_text, search_count)
|
644
|
+
@url, title, @link_text = do_search(type, terms, @link_text, @search_count)
|
621
645
|
else
|
622
646
|
SL.add_error("Invalid search#{SL::Searches.did_you_mean(type)}", input)
|
623
647
|
counter_errors += 1
|
@@ -630,25 +654,25 @@ module SL
|
|
630
654
|
else
|
631
655
|
't'
|
632
656
|
end
|
633
|
-
link_text = input.sub(/^[tfilm]/, '')
|
634
|
-
url, title = SL::SocialSearch.social_handle(type, link_text)
|
635
|
-
link_text = title
|
657
|
+
@link_text = input.sub(/^[tfilm]/, '')
|
658
|
+
@url, title = SL::SocialSearch.social_handle(type, @link_text)
|
659
|
+
@link_text = title
|
636
660
|
else
|
637
|
-
link_text ||= input
|
638
|
-
url, title, link_text = SL.ddg(input, link_text)
|
661
|
+
@link_text ||= input
|
662
|
+
@url, title, @link_text = SL.ddg(input, @link_text)
|
639
663
|
end
|
640
664
|
|
641
|
-
if url
|
665
|
+
if @url
|
642
666
|
if type =~ /sp(ell)?/
|
643
|
-
SL.add_output(url)
|
667
|
+
SL.add_output(@url)
|
644
668
|
elsif link_only
|
645
|
-
SL.add_output(url)
|
646
|
-
elsif url == 'embed'
|
669
|
+
SL.add_output(@url)
|
670
|
+
elsif @url == 'embed'
|
647
671
|
SL.add_output(title)
|
648
672
|
else
|
649
673
|
type = reference_link ? :ref_title : :inline
|
650
674
|
|
651
|
-
SL.add_output SL.make_link(type, link_text, url, title: title, force_title: false)
|
675
|
+
SL.add_output SL.make_link(type, @link_text, @url, title: title, force_title: false)
|
652
676
|
SL.print_errors
|
653
677
|
end
|
654
678
|
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 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,24 @@ 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
|
+
cfg = case ext
|
149
|
+
when /^y/i
|
150
|
+
YAML.safe_load(config)
|
151
|
+
else
|
152
|
+
JSON.parse(config)
|
153
|
+
end
|
154
|
+
cfg['filename'] = File.basename(file)
|
155
|
+
cfg['path'] = file.shorten_path
|
156
|
+
SL::ScriptSearch.new(cfg)
|
157
|
+
end
|
133
158
|
end
|
134
159
|
|
135
160
|
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.70
|
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-10 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
|