searchlink 2.3.65 → 2.3.67
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/array.rb +6 -2
- data/lib/searchlink/config.rb +2 -0
- data/lib/searchlink/curl/html.rb +4 -4
- data/lib/searchlink/curl/json.rb +9 -7
- data/lib/searchlink/help.rb +3 -1
- data/lib/searchlink/output.rb +3 -1
- data/lib/searchlink/parse.rb +18 -15
- data/lib/searchlink/plist.rb +40 -44
- data/lib/searchlink/search.rb +2 -0
- data/lib/searchlink/searches/amazon.rb +2 -0
- data/lib/searchlink/searches/applemusic.rb +2 -0
- data/lib/searchlink/searches/bitly.rb +2 -0
- data/lib/searchlink/searches/definition.rb +2 -0
- data/lib/searchlink/searches/duckduckgo.rb +21 -21
- data/lib/searchlink/searches/github.rb +8 -1
- data/lib/searchlink/searches/google.rb +2 -0
- data/lib/searchlink/searches/helpers/chromium.rb +4 -2
- data/lib/searchlink/searches/helpers/firefox.rb +5 -4
- data/lib/searchlink/searches/helpers/safari.rb +2 -0
- data/lib/searchlink/searches/history.rb +6 -4
- data/lib/searchlink/searches/hook.rb +2 -0
- data/lib/searchlink/searches/itunes.rb +2 -0
- data/lib/searchlink/searches/lastfm.rb +2 -0
- data/lib/searchlink/searches/lyrics.rb +2 -0
- data/lib/searchlink/searches/pinboard.rb +2 -0
- data/lib/searchlink/searches/social.rb +2 -0
- data/lib/searchlink/searches/software.rb +2 -0
- data/lib/searchlink/searches/spelling.rb +2 -0
- data/lib/searchlink/searches/spotlight.rb +3 -1
- data/lib/searchlink/searches/stackoverflow.rb +2 -0
- data/lib/searchlink/searches/tmdb.rb +2 -0
- data/lib/searchlink/searches/twitter.rb +4 -2
- data/lib/searchlink/searches/wikipedia.rb +2 -0
- data/lib/searchlink/searches/youtube.rb +2 -0
- data/lib/searchlink/searches.rb +5 -3
- data/lib/searchlink/semver.rb +2 -0
- data/lib/searchlink/string.rb +16 -13
- data/lib/searchlink/url.rb +4 -0
- data/lib/searchlink/util.rb +3 -0
- data/lib/searchlink/version.rb +5 -2
- data/lib/searchlink/which.rb +145 -150
- data/lib/searchlink.rb +0 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6074fd428fb2935f52c166ca6433e5a903b76dab894d21df2fe3d9867e0582fb
|
|
4
|
+
data.tar.gz: 7793308b2d133c13b227d2a63a22e71de6266050dca03ac4be465efa1c7183fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f48c9a65f58b4b64a59621aa8b3a7b06e73735b0134d948936c3cea7c2afad71a442138cda7f30bb43c588f1557fc0c861c3323d3e7d3b49c48fa475a7f81590
|
|
7
|
+
data.tar.gz: 69fa9718827231021b9831eb3f260f34eaed2a2067e13ec7c712367c394800a75f424fc4b5878f3ce1c1d05e1e49ca5294523b9a19c89fbe5d49ab3d489b5467
|
data/lib/searchlink/array.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Array helpers
|
|
2
4
|
class ::Array
|
|
3
|
-
#
|
|
5
|
+
# This method takes an array and returns the longest element of that array.
|
|
6
|
+
#
|
|
7
|
+
# @return [String] Longest string in array
|
|
4
8
|
#
|
|
5
|
-
# @return [String] first element among longest elements
|
|
6
9
|
def longest_element
|
|
7
10
|
longest_elements[0]
|
|
8
11
|
end
|
|
12
|
+
|
|
9
13
|
# Finds the longest elements and returns an Array
|
|
10
14
|
#
|
|
11
15
|
# @return [Array] array of longest elements
|
data/lib/searchlink/config.rb
CHANGED
data/lib/searchlink/curl/html.rb
CHANGED
|
@@ -375,8 +375,6 @@ module Curl
|
|
|
375
375
|
images
|
|
376
376
|
end
|
|
377
377
|
|
|
378
|
-
|
|
379
|
-
|
|
380
378
|
##
|
|
381
379
|
## Curls the html for the page
|
|
382
380
|
##
|
|
@@ -396,7 +394,9 @@ module Curl
|
|
|
396
394
|
headers = headers.nil? ? '' : headers.map { |h, v| %(-H "#{h}: #{v}") }.join(' ')
|
|
397
395
|
compress = compressed ? '--compressed' : ''
|
|
398
396
|
source = `#{@curl} -#{flags} #{compress} #{headers} '#{url}' 2>/dev/null`
|
|
399
|
-
|
|
397
|
+
if source.nil? || source.empty?
|
|
398
|
+
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null`
|
|
399
|
+
end
|
|
400
400
|
|
|
401
401
|
return false if source.nil? || source.empty?
|
|
402
402
|
|
|
@@ -411,7 +411,7 @@ module Curl
|
|
|
411
411
|
m = Regexp.last_match
|
|
412
412
|
headers[m[1]] = m[2]
|
|
413
413
|
else
|
|
414
|
-
source = lines[idx
|
|
414
|
+
source = lines[idx..-1].join("\n")
|
|
415
415
|
break
|
|
416
416
|
end
|
|
417
417
|
end
|
data/lib/searchlink/curl/json.rb
CHANGED
|
@@ -27,11 +27,11 @@ module Curl
|
|
|
27
27
|
parts = path.split(/./)
|
|
28
28
|
target = json
|
|
29
29
|
parts.each do |part|
|
|
30
|
-
if part =~ /(?<key>[^\[]+)\[(?<int>\d+)\]/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
target = if part =~ /(?<key>[^\[]+)\[(?<int>\d+)\]/
|
|
31
|
+
target[key][int.to_i]
|
|
32
|
+
else
|
|
33
|
+
target[part]
|
|
34
|
+
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
target
|
|
@@ -56,7 +56,9 @@ module Curl
|
|
|
56
56
|
headers = headers.nil? ? '' : headers.map { |h, v| %(-H "#{h}: #{v}") }.join(' ')
|
|
57
57
|
compress = compressed ? '--compressed' : ''
|
|
58
58
|
source = `#{@curl} -#{flags} #{compress} #{headers} '#{url}' 2>/dev/null`
|
|
59
|
-
|
|
59
|
+
if source.nil? || source.empty?
|
|
60
|
+
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null`
|
|
61
|
+
end
|
|
60
62
|
|
|
61
63
|
return false if source.nil? || source.empty?
|
|
62
64
|
|
|
@@ -71,7 +73,7 @@ module Curl
|
|
|
71
73
|
m = Regexp.last_match
|
|
72
74
|
headers[m[1]] = m[2]
|
|
73
75
|
else
|
|
74
|
-
source = lines[idx
|
|
76
|
+
source = lines[idx..-1].join("\n")
|
|
75
77
|
break
|
|
76
78
|
end
|
|
77
79
|
end
|
data/lib/searchlink/help.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
class SearchLink
|
|
3
5
|
def help_css
|
|
@@ -65,7 +67,7 @@ module SL
|
|
|
65
67
|
|
|
66
68
|
if SL.config['custom_site_searches']
|
|
67
69
|
text += "\n-- [Custom Searches] ----------------------\n"
|
|
68
|
-
SL.config['custom_site_searches'].sort_by { |l,
|
|
70
|
+
SL.config['custom_site_searches'].sort_by { |l, _s| l }.each { |label, site| text += "!#{label}#{label.spacer} #{site}\n" }
|
|
69
71
|
end
|
|
70
72
|
text
|
|
71
73
|
end
|
data/lib/searchlink/output.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
class << self
|
|
3
5
|
attr_writer :titleize, :clipboard, :output, :footer, :line_num,
|
|
@@ -95,7 +97,7 @@ module SL
|
|
|
95
97
|
text = text ? text.strip : title
|
|
96
98
|
title = title && (SL.config['include_titles'] || force_title) ? %( "#{title.clean}") : ''
|
|
97
99
|
|
|
98
|
-
title.gsub
|
|
100
|
+
title = title.gsub(/[ \t]+/, ' ')
|
|
99
101
|
|
|
100
102
|
case type.to_sym
|
|
101
103
|
when :ref_title
|
data/lib/searchlink/parse.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
class SearchLink
|
|
3
5
|
# Parse arguments in the input string
|
|
@@ -8,9 +10,9 @@ module SL
|
|
|
8
10
|
# @option opt [Boolean] :no_restore (false) whether to restore previous config
|
|
9
11
|
# @return [String] the parsed string
|
|
10
12
|
#
|
|
11
|
-
def parse_arguments(string, opt={})
|
|
13
|
+
def parse_arguments(string, opt = {})
|
|
12
14
|
input = string.dup
|
|
13
|
-
return
|
|
15
|
+
return '' if input.nil?
|
|
14
16
|
|
|
15
17
|
skip_flags = opt[:only_meta] || false
|
|
16
18
|
no_restore = opt[:no_restore] || false
|
|
@@ -279,7 +281,11 @@ module SL
|
|
|
279
281
|
if link_info =~ /^(?:[!\^](\S+))\s*(.*)$/
|
|
280
282
|
m = Regexp.last_match
|
|
281
283
|
|
|
282
|
-
search_type = m[1].nil?
|
|
284
|
+
search_type = if m[1].nil?
|
|
285
|
+
SL::GoogleSearch.test_for_key ? 'gg' : 'g'
|
|
286
|
+
else
|
|
287
|
+
m[1]
|
|
288
|
+
end
|
|
283
289
|
|
|
284
290
|
search_terms = m[2].gsub(/(^["']|["']$)/, '')
|
|
285
291
|
search_terms.strip!
|
|
@@ -301,7 +307,7 @@ module SL
|
|
|
301
307
|
# if the end of input contains "!!", only print the url
|
|
302
308
|
link_only = true if search_terms =~ /!!\^?$/
|
|
303
309
|
|
|
304
|
-
search_terms.sub!(/(!!)?\^?(!!)?$/,
|
|
310
|
+
search_terms.sub!(/(!!)?\^?(!!)?$/, '')
|
|
305
311
|
|
|
306
312
|
elsif link_info =~ /^!/
|
|
307
313
|
search_word = link_info.match(/^!(\S+)/)
|
|
@@ -389,7 +395,7 @@ module SL
|
|
|
389
395
|
|
|
390
396
|
if (search_type && search_terms) || url
|
|
391
397
|
# warn "Searching #{search_type} for #{search_terms}"
|
|
392
|
-
|
|
398
|
+
unless url
|
|
393
399
|
search_count += 1
|
|
394
400
|
url, title, link_text = do_search(search_type, search_terms, link_text, search_count)
|
|
395
401
|
end
|
|
@@ -433,7 +439,7 @@ module SL
|
|
|
433
439
|
res
|
|
434
440
|
end
|
|
435
441
|
else
|
|
436
|
-
|
|
442
|
+
SL.add_error('No results', "#{search_terms} (#{match_string})")
|
|
437
443
|
counter_errors += 1
|
|
438
444
|
match
|
|
439
445
|
end
|
|
@@ -564,7 +570,7 @@ module SL
|
|
|
564
570
|
end
|
|
565
571
|
terms_p = terms.split(/ +/)
|
|
566
572
|
if terms_p.length > highest_token
|
|
567
|
-
remainder = terms_p[highest_token - 1
|
|
573
|
+
remainder = terms_p[highest_token - 1..-1].join(' ')
|
|
568
574
|
terms_p = terms_p[0..highest_token - 2]
|
|
569
575
|
terms_p.push(remainder)
|
|
570
576
|
end
|
|
@@ -619,14 +625,11 @@ module SL
|
|
|
619
625
|
# Social handle expansion
|
|
620
626
|
when /^([tfilm])?@(\S+)\s*$/
|
|
621
627
|
type = Regexp.last_match(1)
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
type = 't'
|
|
628
|
-
end
|
|
629
|
-
end
|
|
628
|
+
type ||= if Regexp.last_match(2) =~ /[a-z0-9_]@[a-z0-9_.]+/i
|
|
629
|
+
'm'
|
|
630
|
+
else
|
|
631
|
+
't'
|
|
632
|
+
end
|
|
630
633
|
link_text = input.sub(/^[tfilm]/, '')
|
|
631
634
|
url, title = SL::SocialSearch.social_handle(type, link_text)
|
|
632
635
|
link_text = title
|
data/lib/searchlink/plist.rb
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# = plist
|
|
2
4
|
#
|
|
3
5
|
# Copyright 2006-2010 Ben Bleything and Patrick May
|
|
4
6
|
# Distributed under the MIT License
|
|
5
|
-
module Plist
|
|
7
|
+
module Plist; end
|
|
6
8
|
|
|
7
9
|
# === Load a plist file
|
|
8
10
|
# This is the main point of the library:
|
|
9
11
|
#
|
|
10
12
|
# r = Plist::parse_xml( filename_or_xml )
|
|
11
13
|
module Plist
|
|
12
|
-
def
|
|
14
|
+
def self.parse_xml(filename_or_xml)
|
|
13
15
|
listener = Listener.new
|
|
14
16
|
parser = StreamParser.new(filename_or_xml, listener)
|
|
15
17
|
parser.parse
|
|
@@ -21,18 +23,18 @@ module Plist
|
|
|
21
23
|
|
|
22
24
|
def initialize
|
|
23
25
|
@result = nil
|
|
24
|
-
@open =
|
|
26
|
+
@open = []
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
def tag_start(name,
|
|
28
|
-
@open.push PTag
|
|
29
|
+
def tag_start(name, _attributes)
|
|
30
|
+
@open.push PTag.mappings[name].new
|
|
29
31
|
end
|
|
30
32
|
|
|
31
|
-
def text(
|
|
33
|
+
def text(contents)
|
|
32
34
|
@open.last.text = contents if @open.last
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
def tag_end(
|
|
37
|
+
def tag_end(_name)
|
|
36
38
|
last = @open.pop
|
|
37
39
|
if @open.empty?
|
|
38
40
|
@result = last.to_ruby
|
|
@@ -43,28 +45,28 @@ module Plist
|
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
class StreamParser
|
|
46
|
-
def initialize(
|
|
47
|
-
if plist_data_or_file.respond_to? :read
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
def initialize(plist_data_or_file, listener)
|
|
49
|
+
@xml = if plist_data_or_file.respond_to? :read
|
|
50
|
+
plist_data_or_file.read
|
|
51
|
+
elsif File.exist? plist_data_or_file
|
|
52
|
+
File.read(plist_data_or_file)
|
|
53
|
+
else
|
|
54
|
+
plist_data_or_file
|
|
55
|
+
end
|
|
54
56
|
|
|
55
57
|
@listener = listener
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
TEXT
|
|
59
|
-
XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
|
|
60
|
-
DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
|
|
61
|
-
COMMENT_START = /\A<!--/u
|
|
62
|
-
COMMENT_END = /.*?-->/um
|
|
60
|
+
TEXT = /([^<]+)/.freeze
|
|
61
|
+
XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um.freeze
|
|
62
|
+
DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um.freeze
|
|
63
|
+
COMMENT_START = /\A<!--/u.freeze
|
|
64
|
+
COMMENT_END = /.*?-->/um.freeze
|
|
63
65
|
|
|
64
66
|
def parse
|
|
65
|
-
plist_tags = PTag
|
|
67
|
+
plist_tags = PTag.mappings.keys.join('|')
|
|
66
68
|
start_tag = /<(#{plist_tags})([^>]*)>/i
|
|
67
|
-
end_tag =
|
|
69
|
+
end_tag = %r{</(#{plist_tags})[^>]*>}i
|
|
68
70
|
|
|
69
71
|
require 'strscan'
|
|
70
72
|
|
|
@@ -76,53 +78,51 @@ module Plist
|
|
|
76
78
|
elsif @scanner.scan(DOCTYPE_PATTERN)
|
|
77
79
|
elsif @scanner.scan(start_tag)
|
|
78
80
|
@listener.tag_start(@scanner[1], nil)
|
|
79
|
-
if
|
|
80
|
-
@listener.tag_end(@scanner[1])
|
|
81
|
-
end
|
|
81
|
+
@listener.tag_end(@scanner[1]) if @scanner[2] =~ %r{/$}
|
|
82
82
|
elsif @scanner.scan(TEXT)
|
|
83
83
|
@listener.text(@scanner[1])
|
|
84
84
|
elsif @scanner.scan(end_tag)
|
|
85
85
|
@listener.tag_end(@scanner[1])
|
|
86
86
|
else
|
|
87
|
-
raise
|
|
87
|
+
raise 'Unimplemented element'
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
class PTag
|
|
94
|
-
@@mappings = {
|
|
95
|
-
def
|
|
94
|
+
@@mappings = {}
|
|
95
|
+
def self.mappings
|
|
96
96
|
@@mappings
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
def
|
|
99
|
+
def self.inherited(sub_class)
|
|
100
100
|
key = sub_class.to_s.downcase
|
|
101
|
-
key.gsub!(/^plist::/, ''
|
|
102
|
-
key.gsub!(/^p/, '')
|
|
101
|
+
key.gsub!(/^plist::/, '')
|
|
102
|
+
key.gsub!(/^p/, '') unless key == 'plist'
|
|
103
103
|
|
|
104
104
|
@@mappings[key] = sub_class
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
attr_accessor :text, :children
|
|
108
108
|
def initialize
|
|
109
|
-
@children =
|
|
109
|
+
@children = []
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
def to_ruby
|
|
113
|
-
raise
|
|
113
|
+
raise 'Unimplemented: ' + self.class.to_s + "#to_ruby on #{inspect}"
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
class PList < PTag
|
|
118
118
|
def to_ruby
|
|
119
|
-
children.first
|
|
119
|
+
children.first&.to_ruby
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
class PDict < PTag
|
|
124
124
|
def to_ruby
|
|
125
|
-
dict =
|
|
125
|
+
dict = {}
|
|
126
126
|
key = nil
|
|
127
127
|
|
|
128
128
|
children.each do |c|
|
|
@@ -140,21 +140,19 @@ module Plist
|
|
|
140
140
|
|
|
141
141
|
class PKey < PTag
|
|
142
142
|
def to_ruby
|
|
143
|
-
CGI
|
|
143
|
+
CGI.unescapeHTML(text || '')
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
class PString < PTag
|
|
148
148
|
def to_ruby
|
|
149
|
-
CGI
|
|
149
|
+
CGI.unescapeHTML(text || '')
|
|
150
150
|
end
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
class PArray < PTag
|
|
154
154
|
def to_ruby
|
|
155
|
-
children.collect
|
|
156
|
-
c.to_ruby
|
|
157
|
-
end
|
|
155
|
+
children.collect(&:to_ruby)
|
|
158
156
|
end
|
|
159
157
|
end
|
|
160
158
|
|
|
@@ -195,19 +193,17 @@ module Plist
|
|
|
195
193
|
data = Base64.decode64(text.gsub(/\s+/, ''))
|
|
196
194
|
|
|
197
195
|
begin
|
|
198
|
-
|
|
196
|
+
Marshal.load(data)
|
|
199
197
|
rescue Exception
|
|
200
198
|
io = StringIO.new
|
|
201
199
|
io.write data
|
|
202
200
|
io.rewind
|
|
203
|
-
|
|
201
|
+
io
|
|
204
202
|
end
|
|
205
203
|
end
|
|
206
204
|
end
|
|
207
205
|
end
|
|
208
206
|
|
|
209
|
-
|
|
210
207
|
# module Plist
|
|
211
208
|
# VERSION = '3.1.0'
|
|
212
209
|
# end
|
|
213
|
-
|
data/lib/searchlink/search.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
# DuckDuckGo Search
|
|
3
5
|
class DuckDuckGoSearch
|
|
@@ -36,36 +38,34 @@ module SL
|
|
|
36
38
|
|
|
37
39
|
# return SL.ddg(search_terms, link_text) if search_type == 'g' && SL::GoogleSearch.test_for_key
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
page = Curl::Html.new("https://duckduckgo.com/?q=#{terms}", compressed: true)
|
|
41
|
+
terms = "%5C#{search_terms.url_encode}"
|
|
42
|
+
page = Curl::Html.new("https://duckduckgo.com/?q=#{terms}", compressed: true)
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
locs = page.meta['refresh'].match(%r{/l/\?uddg=(.*?)$})
|
|
45
|
+
locs = page.body.match(%r{/l/\?uddg=(.*?)'}) if locs.nil?
|
|
46
|
+
locs = page.body.match(/url=(.*?)'/) if locs.nil?
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
return false if locs.nil?
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
url = locs[1].url_decode.sub(/&rut=\w+/, '')
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
result = url.strip.url_decode || false
|
|
53
|
+
return false unless result
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
return false if result =~ /internal-search\.duckduckgo\.com/
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
# output_url = CGI.unescape(result)
|
|
58
|
+
output_url = result
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
output_title = if SL.config['include_titles'] || SL.titleize
|
|
61
|
+
SL::URL.title(output_url) || ''
|
|
62
|
+
else
|
|
63
|
+
''
|
|
64
|
+
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
output_url = SL.first_image(output_url) if search_type =~ /img$/
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
end
|
|
68
|
+
[output_url, output_title, link_text]
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Searches DuckDuckGo for the given search terms and
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
# GitHub search
|
|
3
5
|
class GitHubSearch
|
|
@@ -59,6 +61,11 @@ module SL
|
|
|
59
61
|
|
|
60
62
|
res = Curl::Json.new(url, headers: headers).json
|
|
61
63
|
|
|
64
|
+
if res.is_a?(Hash) && res['status'].to_i == 401
|
|
65
|
+
SL.notify('Error', 'Bad GitHub credentials')
|
|
66
|
+
return nil
|
|
67
|
+
end
|
|
68
|
+
|
|
62
69
|
best = nil
|
|
63
70
|
best = filter_gists(res, search_terms) if res
|
|
64
71
|
|
|
@@ -209,7 +216,7 @@ module SL
|
|
|
209
216
|
else
|
|
210
217
|
if terms.split(/ +/).count > 1
|
|
211
218
|
parts = terms.split(/ +/)
|
|
212
|
-
gist = search_user_gists(parts[0], parts[1
|
|
219
|
+
gist = search_user_gists(parts[0], parts[1..-1].join(' '))
|
|
213
220
|
|
|
214
221
|
if gist
|
|
215
222
|
url = gist[:url]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
##
|
|
2
4
|
## Chromium (Chrome, Arc, Brave, Edge) search methods
|
|
3
5
|
##
|
|
@@ -273,7 +275,7 @@ module SL
|
|
|
273
275
|
if json.key? 'children'
|
|
274
276
|
urls = extract_chrome_bookmarks(json['children'], urls, term)
|
|
275
277
|
elsif json['type'] == 'url'
|
|
276
|
-
date = Time.at(json['date_added'].to_i /
|
|
278
|
+
date = Time.at(json['date_added'].to_i / 1_000_000 + Time.new(1601, 0o1, 0o1).strftime('%s').to_i)
|
|
277
279
|
url = { url: json['url'], title: json['name'], date: date }
|
|
278
280
|
score = score_mark(url, term)
|
|
279
281
|
|
|
@@ -299,7 +301,7 @@ module SL
|
|
|
299
301
|
def score_mark(mark, terms)
|
|
300
302
|
return 0 unless mark[:url]
|
|
301
303
|
|
|
302
|
-
score = if mark[:title]
|
|
304
|
+
score = if mark[:title]&.matches_exact(terms)
|
|
303
305
|
12 + mark[:url].matches_score(terms, start_word: false)
|
|
304
306
|
elsif mark[:url].matches_exact(terms)
|
|
305
307
|
11
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
class HistorySearch
|
|
3
5
|
class << self
|
|
@@ -56,12 +58,11 @@ module SL
|
|
|
56
58
|
|
|
57
59
|
marks.map! do |bm|
|
|
58
60
|
date = Time.parse(bm['datum'])
|
|
59
|
-
score = score_mark({url: bm['url'], title: bm['title']}, term)
|
|
61
|
+
score = score_mark({ url: bm['url'], title: bm['title'] }, term)
|
|
60
62
|
{ url: bm['url'], title: bm['title'], date: date, score: score }
|
|
61
63
|
end
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
m = marks.sort_by { |m| [m[:url].length * -1, m[:score]] }.last
|
|
65
|
+
m = marks.max_by { |m| [m[:url].length * -1, m[:score]] }
|
|
65
66
|
|
|
66
67
|
[m[:url], m[:title], m[:date]]
|
|
67
68
|
else
|
|
@@ -124,7 +125,7 @@ module SL
|
|
|
124
125
|
bm = JSON.parse(most_recent)[0]
|
|
125
126
|
|
|
126
127
|
date = Time.parse(bm['datum'])
|
|
127
|
-
score = score_mark({url: bm['url'], title: bm['title']}, term)
|
|
128
|
+
score = score_mark({ url: bm['url'], title: bm['title'] }, term)
|
|
128
129
|
[bm['url'], bm['title'], date, score]
|
|
129
130
|
else
|
|
130
131
|
false
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# import
|
|
2
4
|
require_relative 'helpers/chromium'
|
|
3
5
|
|
|
4
|
-
#import
|
|
6
|
+
# import
|
|
5
7
|
require_relative 'helpers/firefox'
|
|
6
8
|
|
|
7
|
-
#import
|
|
9
|
+
# import
|
|
8
10
|
require_relative 'helpers/safari'
|
|
9
11
|
|
|
10
12
|
module SL
|
|
@@ -48,7 +50,7 @@ module SL
|
|
|
48
50
|
str = search_type.match(/^h(([scfabe])([hb])?)*$/)[1]
|
|
49
51
|
|
|
50
52
|
types = []
|
|
51
|
-
while str
|
|
53
|
+
while str&.length&.positive?
|
|
52
54
|
if str =~ /^s([hb]*)/
|
|
53
55
|
t = Regexp.last_match(1)
|
|
54
56
|
if t.length > 1 || t.empty?
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
# Spotlight file search
|
|
3
5
|
class SpotlightSearch
|
|
@@ -14,7 +16,7 @@ module SL
|
|
|
14
16
|
def search(_, search_terms, link_text)
|
|
15
17
|
query = search_terms.gsub(/%22/, '"')
|
|
16
18
|
matches = `mdfind '#{query}' 2>/dev/null`.strip.split(/\n/)
|
|
17
|
-
res = matches.
|
|
19
|
+
res = matches.min_by { |r| File.basename(r).length }
|
|
18
20
|
return [false, query, link_text] if res.strip.empty?
|
|
19
21
|
|
|
20
22
|
title = File.basename(res)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
class TwitterSearch
|
|
3
5
|
class << self
|
|
@@ -10,7 +12,7 @@ module SL
|
|
|
10
12
|
}
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def search(
|
|
15
|
+
def search(_search_type, search_terms, link_text)
|
|
14
16
|
if SL::URL.url?(search_terms) && search_terms =~ %r{^https://twitter.com/}
|
|
15
17
|
url, title = twitter_embed(search_terms)
|
|
16
18
|
else
|
|
@@ -37,7 +39,7 @@ module SL
|
|
|
37
39
|
else
|
|
38
40
|
return [false, 'Error retrieving tweet']
|
|
39
41
|
end
|
|
40
|
-
|
|
42
|
+
[url, title]
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
|
data/lib/searchlink/searches.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
module Searches
|
|
3
5
|
class << self
|
|
@@ -14,7 +16,7 @@ module SL
|
|
|
14
16
|
#
|
|
15
17
|
# @param [String, Array] title title or array of titles
|
|
16
18
|
# @param [Symbol] type plugin type (:search)
|
|
17
|
-
# @param [Class] klass class that handles plugin actions. Search plugins
|
|
19
|
+
# @param [Class] klass class that handles plugin actions. Search plugins
|
|
18
20
|
# must have a #settings and a #search method
|
|
19
21
|
#
|
|
20
22
|
def register(title, type, klass)
|
|
@@ -48,7 +50,7 @@ module SL
|
|
|
48
50
|
'<tbody>']
|
|
49
51
|
|
|
50
52
|
searches.each do |s|
|
|
51
|
-
out << "<tr><td><code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1
|
|
53
|
+
out << "<tr><td><code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(',')})" : s[0]}</code></td><td>#{s[1]}</td></tr>"
|
|
52
54
|
end
|
|
53
55
|
out.concat(['</tbody>', '</table>']).join("\n")
|
|
54
56
|
end
|
|
@@ -63,7 +65,7 @@ module SL
|
|
|
63
65
|
plugins[:search].each { |_, plugin| searches.concat(plugin[:searches].delete_if { |s| s[1].nil? }) }
|
|
64
66
|
out = []
|
|
65
67
|
searches.each do |s|
|
|
66
|
-
out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1
|
|
68
|
+
out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(',')})" : s[0]}#{s[0].spacer}#{s[1]}"
|
|
67
69
|
end
|
|
68
70
|
out.join("\n")
|
|
69
71
|
end
|
data/lib/searchlink/semver.rb
CHANGED
data/lib/searchlink/string.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
4
|
# String helpers
|
|
3
5
|
class ::String
|
|
@@ -275,7 +277,7 @@ module SL
|
|
|
275
277
|
|
|
276
278
|
next if parts.length == 1
|
|
277
279
|
|
|
278
|
-
remaining_separators = seo_title_separators[i
|
|
280
|
+
remaining_separators = seo_title_separators[i..-1].map { |s| Regexp.escape(s) }.join('')
|
|
279
281
|
seps = Regexp.new("^[^#{remaining_separators}]+$")
|
|
280
282
|
|
|
281
283
|
longest = parts.longest_element.strip
|
|
@@ -396,24 +398,25 @@ module SL
|
|
|
396
398
|
end
|
|
397
399
|
|
|
398
400
|
def distance(t)
|
|
399
|
-
s =
|
|
401
|
+
s = dup
|
|
400
402
|
m = s.length
|
|
401
403
|
n = t.length
|
|
402
|
-
return m if n
|
|
403
|
-
return n if m
|
|
404
|
-
|
|
404
|
+
return m if n.zero?
|
|
405
|
+
return n if m.zero?
|
|
406
|
+
|
|
407
|
+
d = Array.new(m + 1) { Array.new(n + 1) }
|
|
405
408
|
|
|
406
|
-
(0..m).each {|i| d[i][0] = i}
|
|
407
|
-
(0..n).each {|j| d[0][j] = j}
|
|
409
|
+
(0..m).each { |i| d[i][0] = i }
|
|
410
|
+
(0..n).each { |j| d[0][j] = j }
|
|
408
411
|
(1..n).each do |j|
|
|
409
412
|
(1..m).each do |i|
|
|
410
|
-
d[i][j] = if s[i-1] == t[j-1]
|
|
411
|
-
d[i-1][j-1] # no operation required
|
|
413
|
+
d[i][j] = if s[i - 1] == t[j - 1] # adjust index into string
|
|
414
|
+
d[i - 1][j - 1] # no operation required
|
|
412
415
|
else
|
|
413
|
-
[
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
416
|
+
[d[i - 1][j] + 1, # deletion
|
|
417
|
+
d[i][j - 1] + 1, # insertion
|
|
418
|
+
d[i - 1][j - 1] + 1 # substitution
|
|
419
|
+
].min
|
|
417
420
|
end
|
|
418
421
|
end
|
|
419
422
|
end
|
data/lib/searchlink/url.rb
CHANGED
data/lib/searchlink/util.rb
CHANGED
data/lib/searchlink/version.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SL
|
|
2
|
-
VERSION = '2.3.
|
|
4
|
+
VERSION = '2.3.67'
|
|
3
5
|
end
|
|
4
6
|
|
|
7
|
+
# Main module
|
|
5
8
|
module SL
|
|
6
9
|
class << self
|
|
7
10
|
def version_check
|
|
@@ -68,7 +71,7 @@ module SL
|
|
|
68
71
|
end
|
|
69
72
|
|
|
70
73
|
def update_searchlink
|
|
71
|
-
if
|
|
74
|
+
if `uname`.strip !~ /Darwin/
|
|
72
75
|
add_output('Auto updating only available on macOS')
|
|
73
76
|
return
|
|
74
77
|
end
|
data/lib/searchlink/which.rb
CHANGED
|
@@ -5,171 +5,166 @@
|
|
|
5
5
|
|
|
6
6
|
module TTY
|
|
7
7
|
module Which
|
|
8
|
-
VERSION =
|
|
9
|
-
end
|
|
10
|
-
end
|
|
8
|
+
VERSION = '0.5.0'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
11
|
|
|
12
12
|
module TTY
|
|
13
13
|
# A class responsible for finding an executable in the PATH
|
|
14
14
|
module Which
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
15
|
+
class << self
|
|
16
|
+
# Find an executable in a platform independent way
|
|
17
|
+
#
|
|
18
|
+
# @param [String] cmd
|
|
19
|
+
# the command to search for
|
|
20
|
+
# @param [Array<String>] paths
|
|
21
|
+
# the paths to look through
|
|
22
|
+
#
|
|
23
|
+
# @example
|
|
24
|
+
# which("ruby") # => "/usr/local/bin/ruby"
|
|
25
|
+
# which("/usr/local/bin/ruby") # => "/usr/local/bin/ruby"
|
|
26
|
+
# which("foo") # => nil
|
|
27
|
+
#
|
|
28
|
+
# @example
|
|
29
|
+
# which("ruby", paths: ["/usr/locale/bin", "/usr/bin", "/bin"])
|
|
30
|
+
#
|
|
31
|
+
# @return [String, nil]
|
|
32
|
+
# the absolute path to executable if found, `nil` otherwise
|
|
33
|
+
#
|
|
34
|
+
# @api public
|
|
35
|
+
def which(cmd, paths: search_paths)
|
|
36
|
+
if file_with_path?(cmd)
|
|
37
|
+
return cmd if executable_file?(cmd)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
extensions.each do |ext|
|
|
40
|
+
exe = "#{cmd}#{ext}"
|
|
41
|
+
return ::File.absolute_path(exe) if executable_file?(exe)
|
|
42
|
+
end
|
|
43
|
+
return nil
|
|
41
44
|
end
|
|
42
|
-
return nil
|
|
43
|
-
end
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
paths.each do |path|
|
|
47
|
+
if file_with_exec_ext?(cmd)
|
|
48
|
+
exe = ::File.join(path, cmd)
|
|
49
|
+
return ::File.absolute_path(exe) if executable_file?(exe)
|
|
50
|
+
end
|
|
51
|
+
extensions.each do |ext|
|
|
52
|
+
exe = ::File.join(path, "#{cmd}#{ext}")
|
|
53
|
+
return ::File.absolute_path(exe) if executable_file?(exe)
|
|
54
|
+
end
|
|
53
55
|
end
|
|
56
|
+
nil
|
|
54
57
|
end
|
|
55
|
-
nil
|
|
56
|
-
end
|
|
57
|
-
module_function :which
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
module_function :exist?
|
|
59
|
+
# Check if executable exists in the path
|
|
60
|
+
#
|
|
61
|
+
# @param [String] cmd
|
|
62
|
+
# the executable to check
|
|
63
|
+
#
|
|
64
|
+
# @param [Array<String>] paths
|
|
65
|
+
# paths to check
|
|
66
|
+
#
|
|
67
|
+
# @return [Boolean]
|
|
68
|
+
#
|
|
69
|
+
# @api public
|
|
70
|
+
def exist?(cmd, paths: search_paths)
|
|
71
|
+
!which(cmd, paths: paths).nil?
|
|
72
|
+
end
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
module_function :search_paths
|
|
74
|
+
# Find default system paths
|
|
75
|
+
#
|
|
76
|
+
# @param [String] path
|
|
77
|
+
# the path to search through
|
|
78
|
+
#
|
|
79
|
+
# @example
|
|
80
|
+
# search_paths("/usr/local/bin:/bin")
|
|
81
|
+
# # => ["/bin"]
|
|
82
|
+
#
|
|
83
|
+
# @return [Array<String>]
|
|
84
|
+
# the array of paths to search
|
|
85
|
+
#
|
|
86
|
+
# @api private
|
|
87
|
+
def search_paths(path = ENV['PATH'])
|
|
88
|
+
paths = if path && !path.empty?
|
|
89
|
+
path.split(::File::PATH_SEPARATOR)
|
|
90
|
+
else
|
|
91
|
+
%w[/usr/local/bin /usr/ucb /usr/bin /bin /opt/homebrew/bin]
|
|
92
|
+
end
|
|
93
|
+
paths.select(&Dir.method(:exist?))
|
|
94
|
+
end
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
# All possible file extensions
|
|
97
|
+
#
|
|
98
|
+
# @example
|
|
99
|
+
# extensions(".exe;cmd;.bat")
|
|
100
|
+
# # => [".exe", ".bat"]
|
|
101
|
+
#
|
|
102
|
+
# @param [String] path_ext
|
|
103
|
+
# a string of semicolon separated filename extensions
|
|
104
|
+
#
|
|
105
|
+
# @return [Array<String>]
|
|
106
|
+
# an array with valid file extensions
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
def extensions(path_ext = ENV['PATHEXT'])
|
|
110
|
+
return [''] unless path_ext
|
|
113
111
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
module_function :extensions
|
|
112
|
+
path_ext.split(::File::PATH_SEPARATOR).select { |part| part.include?('.') }
|
|
113
|
+
end
|
|
117
114
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
module_function :executable_file?
|
|
115
|
+
# Determines if filename is an executable file
|
|
116
|
+
#
|
|
117
|
+
# @example Basic usage
|
|
118
|
+
# executable_file?("/usr/bin/less") # => true
|
|
119
|
+
#
|
|
120
|
+
# @example Executable in directory
|
|
121
|
+
# executable_file?("less", "/usr/bin") # => true
|
|
122
|
+
# executable_file?("less", "/usr") # => false
|
|
123
|
+
#
|
|
124
|
+
# @param [String] filename
|
|
125
|
+
# the path to file
|
|
126
|
+
# @param [String] dir
|
|
127
|
+
# the directory within which to search for filename
|
|
128
|
+
#
|
|
129
|
+
# @return [Boolean]
|
|
130
|
+
#
|
|
131
|
+
# @api private
|
|
132
|
+
def executable_file?(filename, dir = nil)
|
|
133
|
+
path = ::File.join(dir, filename) if dir
|
|
134
|
+
path ||= filename
|
|
135
|
+
::File.file?(path) && ::File.executable?(path)
|
|
136
|
+
end
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
138
|
+
# Check if command itself has executable extension
|
|
139
|
+
#
|
|
140
|
+
# @param [String] filename
|
|
141
|
+
# the path to executable file
|
|
142
|
+
#
|
|
143
|
+
# @example
|
|
144
|
+
# file_with_exec_ext?("file.bat")
|
|
145
|
+
# # => true
|
|
146
|
+
#
|
|
147
|
+
# @return [Boolean]
|
|
148
|
+
#
|
|
149
|
+
# @api private
|
|
150
|
+
def file_with_exec_ext?(filename)
|
|
151
|
+
extension = ::File.extname(filename)
|
|
152
|
+
return false if extension.empty?
|
|
157
153
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
module_function :file_with_exec_ext?
|
|
154
|
+
extensions.any? { |ext| extension.casecmp(ext).zero? }
|
|
155
|
+
end
|
|
161
156
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
157
|
+
# Check if executable file is part of absolute/relative path
|
|
158
|
+
#
|
|
159
|
+
# @param [String] cmd
|
|
160
|
+
# the executable to check
|
|
161
|
+
#
|
|
162
|
+
# @return [Boolean]
|
|
163
|
+
#
|
|
164
|
+
# @api private
|
|
165
|
+
def file_with_path?(cmd)
|
|
166
|
+
::File.expand_path(cmd) == cmd
|
|
167
|
+
end
|
|
172
168
|
end
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
end # TTY
|
|
169
|
+
end
|
|
170
|
+
end
|
data/lib/searchlink.rb
CHANGED
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.67
|
|
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-
|
|
11
|
+
date: 2024-08-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -292,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
292
292
|
- !ruby/object:Gem::Version
|
|
293
293
|
version: '0'
|
|
294
294
|
requirements: []
|
|
295
|
-
rubygems_version: 3.2.
|
|
295
|
+
rubygems_version: 3.2.15
|
|
296
296
|
signing_key:
|
|
297
297
|
specification_version: 4
|
|
298
298
|
summary: Create Markdown links from web searches without leaving your editor.
|