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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/searchlink/array.rb +6 -2
  3. data/lib/searchlink/config.rb +2 -0
  4. data/lib/searchlink/curl/html.rb +4 -4
  5. data/lib/searchlink/curl/json.rb +9 -7
  6. data/lib/searchlink/help.rb +3 -1
  7. data/lib/searchlink/output.rb +3 -1
  8. data/lib/searchlink/parse.rb +18 -15
  9. data/lib/searchlink/plist.rb +40 -44
  10. data/lib/searchlink/search.rb +2 -0
  11. data/lib/searchlink/searches/amazon.rb +2 -0
  12. data/lib/searchlink/searches/applemusic.rb +2 -0
  13. data/lib/searchlink/searches/bitly.rb +2 -0
  14. data/lib/searchlink/searches/definition.rb +2 -0
  15. data/lib/searchlink/searches/duckduckgo.rb +21 -21
  16. data/lib/searchlink/searches/github.rb +8 -1
  17. data/lib/searchlink/searches/google.rb +2 -0
  18. data/lib/searchlink/searches/helpers/chromium.rb +4 -2
  19. data/lib/searchlink/searches/helpers/firefox.rb +5 -4
  20. data/lib/searchlink/searches/helpers/safari.rb +2 -0
  21. data/lib/searchlink/searches/history.rb +6 -4
  22. data/lib/searchlink/searches/hook.rb +2 -0
  23. data/lib/searchlink/searches/itunes.rb +2 -0
  24. data/lib/searchlink/searches/lastfm.rb +2 -0
  25. data/lib/searchlink/searches/lyrics.rb +2 -0
  26. data/lib/searchlink/searches/pinboard.rb +2 -0
  27. data/lib/searchlink/searches/social.rb +2 -0
  28. data/lib/searchlink/searches/software.rb +2 -0
  29. data/lib/searchlink/searches/spelling.rb +2 -0
  30. data/lib/searchlink/searches/spotlight.rb +3 -1
  31. data/lib/searchlink/searches/stackoverflow.rb +2 -0
  32. data/lib/searchlink/searches/tmdb.rb +2 -0
  33. data/lib/searchlink/searches/twitter.rb +4 -2
  34. data/lib/searchlink/searches/wikipedia.rb +2 -0
  35. data/lib/searchlink/searches/youtube.rb +2 -0
  36. data/lib/searchlink/searches.rb +5 -3
  37. data/lib/searchlink/semver.rb +2 -0
  38. data/lib/searchlink/string.rb +16 -13
  39. data/lib/searchlink/url.rb +4 -0
  40. data/lib/searchlink/util.rb +3 -0
  41. data/lib/searchlink/version.rb +5 -2
  42. data/lib/searchlink/which.rb +145 -150
  43. data/lib/searchlink.rb +0 -1
  44. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd9142e4c8363dca0dbbc82c7bb4be3112ce335f908641b4184dbde9e1525960
4
- data.tar.gz: c8e7cf285e4de29c24a7fcb53014c2efa4da8a3c38a857f11747b97a8a653ba0
3
+ metadata.gz: 6074fd428fb2935f52c166ca6433e5a903b76dab894d21df2fe3d9867e0582fb
4
+ data.tar.gz: 7793308b2d133c13b227d2a63a22e71de6266050dca03ac4be465efa1c7183fb
5
5
  SHA512:
6
- metadata.gz: 6d2336776d6526804d9df51e180a9996a89cc9786ef4c0cefa5fede4e3ba2c9a931c4240c2116809f6fd928dc8155c7c3b26b0141add9bf1ed39000bdf73ca2e
7
- data.tar.gz: c7710d400e7346a79063604af305027a851f490ec055f7b762bc9d414db5f5ebf1d21504bff3acccb7e5832c42d5914ce844b324f483a7c0044ff72720b637dc
6
+ metadata.gz: f48c9a65f58b4b64a59621aa8b3a7b06e73735b0134d948936c3cea7c2afad71a442138cda7f30bb43c588f1557fc0c861c3323d3e7d3b49c48fa475a7f81590
7
+ data.tar.gz: 69fa9718827231021b9831eb3f260f34eaed2a2067e13ec7c712367c394800a75f424fc4b5878f3ce1c1d05e1e49ca5294523b9a19c89fbe5d49ab3d489b5467
@@ -1,11 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Array helpers
2
4
  class ::Array
3
- # Finds the longest element in an array of strings
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class << self
3
5
  attr_writer :config, :prev_config
@@ -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
- source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null` if source.nil? || source.empty?
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..].join("\n")
414
+ source = lines[idx..-1].join("\n")
415
415
  break
416
416
  end
417
417
  end
@@ -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
- target = target[key][int.to_i]
32
- else
33
- target = target[part]
34
- end
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
- source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null` if source.nil? || source.empty?
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..].join("\n")
76
+ source = lines[idx..-1].join("\n")
75
77
  break
76
78
  end
77
79
  end
@@ -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, s| l }.each { |label, site| text += "!#{label}#{label.spacer} #{site}\n" }
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
@@ -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!(/[ \t]+/, ' ')
100
+ title = title.gsub(/[ \t]+/, ' ')
99
101
 
100
102
  case type.to_sym
101
103
  when :ref_title
@@ -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 "" if input.nil?
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? ? (SL::GoogleSearch.test_for_key ? 'gg' : 'g') : m[1]
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
- if (!url)
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
- SL.add_error('No results', "#{search_terms} (#{match_string})")
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..].join(' ')
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
- unless type
623
- # If contains @ mid-handle, use Mastodon
624
- if Regexp.last_match(2) =~ /[a-z0-9_]@[a-z0-9_.]+/i
625
- type = 'm'
626
- else
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
@@ -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 ; end
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 Plist::parse_xml( filename_or_xml )
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 = Array.new
26
+ @open = []
25
27
  end
26
28
 
27
- def tag_start(name, attributes)
28
- @open.push PTag::mappings[name].new
29
+ def tag_start(name, _attributes)
30
+ @open.push PTag.mappings[name].new
29
31
  end
30
32
 
31
- def text( contents )
33
+ def text(contents)
32
34
  @open.last.text = contents if @open.last
33
35
  end
34
36
 
35
- def tag_end(name)
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( plist_data_or_file, listener )
47
- if plist_data_or_file.respond_to? :read
48
- @xml = plist_data_or_file.read
49
- elsif File.exists? plist_data_or_file
50
- @xml = File.read( plist_data_or_file )
51
- else
52
- @xml = plist_data_or_file
53
- end
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::mappings.keys.join('|')
67
+ plist_tags = PTag.mappings.keys.join('|')
66
68
  start_tag = /<(#{plist_tags})([^>]*)>/i
67
- end_tag = /<\/(#{plist_tags})[^>]*>/i
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 (@scanner[2] =~ /\/$/)
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 "Unimplemented element"
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 PTag::mappings
94
+ @@mappings = {}
95
+ def self.mappings
96
96
  @@mappings
97
97
  end
98
98
 
99
- def PTag::inherited( sub_class )
99
+ def self.inherited(sub_class)
100
100
  key = sub_class.to_s.downcase
101
- key.gsub!(/^plist::/, '' )
102
- key.gsub!(/^p/, '') unless key == "plist"
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 = Array.new
109
+ @children = []
110
110
  end
111
111
 
112
112
  def to_ruby
113
- raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
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.to_ruby if 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 = Hash.new
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::unescapeHTML(text || '')
143
+ CGI.unescapeHTML(text || '')
144
144
  end
145
145
  end
146
146
 
147
147
  class PString < PTag
148
148
  def to_ruby
149
- CGI::unescapeHTML(text || '')
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 do |c|
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
- return Marshal.load(data)
196
+ Marshal.load(data)
199
197
  rescue Exception
200
198
  io = StringIO.new
201
199
  io.write data
202
200
  io.rewind
203
- return io
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
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Main SearchLink class
2
4
  module SL
3
5
  include URL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Amazon Search
3
5
  class AmazonSearch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # title: Apple Music Search
2
4
  # description: Search Apple Music
3
5
  module SL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Bit.ly link shortening
3
5
  class BitlySearch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Dictionary Definition Search
3
5
  class DefinitionSearch
@@ -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
- begin
40
- terms = "%5C#{search_terms.url_encode}"
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
- locs = page.meta['refresh'].match(%r{/l/\?uddg=(.*?)$})
44
- locs = page.body.match(%r{/l/\?uddg=(.*?)'}) if locs.nil?
45
- locs = page.body.match(/url=(.*?)'/) if locs.nil?
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
- return false if locs.nil?
48
+ return false if locs.nil?
48
49
 
49
- url = locs[1].url_decode.sub(/&rut=\w+/, '')
50
+ url = locs[1].url_decode.sub(/&rut=\w+/, '')
50
51
 
51
- result = url.strip.url_decode || false
52
- return false unless result
52
+ result = url.strip.url_decode || false
53
+ return false unless result
53
54
 
54
- return false if result =~ /internal-search\.duckduckgo\.com/
55
+ return false if result =~ /internal-search\.duckduckgo\.com/
55
56
 
56
- # output_url = CGI.unescape(result)
57
- output_url = result
57
+ # output_url = CGI.unescape(result)
58
+ output_url = result
58
59
 
59
- output_title = if SL.config['include_titles'] || SL.titleize
60
- SL::URL.title(output_url) || ''
61
- else
62
- ''
63
- end
60
+ output_title = if SL.config['include_titles'] || SL.titleize
61
+ SL::URL.title(output_url) || ''
62
+ else
63
+ ''
64
+ end
64
65
 
65
- output_url = SL.first_image(output_url) if search_type =~ /img$/
66
+ output_url = SL.first_image(output_url) if search_type =~ /img$/
66
67
 
67
- [output_url, output_title, link_text]
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..].join(' '))
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
  module SL
2
4
  # Google Search
3
5
  class GoogleSearch
@@ -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 / 1000000 + (Time.new(1601, 01, 01).strftime('%s').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] && mark[:title].matches_exact(terms)
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class HistorySearch
3
5
  class << self
@@ -1,10 +1,12 @@
1
- #import
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 && str.length.positive?
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
  #
3
5
  # Hookmark String helpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # title: iTunes Search
2
4
  # description: Search iTunes
3
5
  module SL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class LastFMSearch
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Always start with module SL
2
4
  module SL
3
5
  # Give it a unique class name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class PinboardSearch
3
5
  PINBOARD_CACHE = SL::Util.cache_file_for('pinboard')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class SocialSearch
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Software Search
3
5
  class SoftwareSearch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Spelling Search
3
5
  class SpellSearch
@@ -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.sort_by { |r| File.basename(r).length }.first
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
  # Stack Overflow search
3
5
  class StackOverflowSearch
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # The Movie Database search
3
5
  class TMDBSearch
@@ -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(search_type, search_terms, link_text)
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
- return [url, title]
42
+ [url, title]
41
43
  end
42
44
  end
43
45
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  class WikipediaSearch
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # YouTube Search/Linking
3
5
  class YouTubeSearch
@@ -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..].join(',')})" : s[0]}</code></td><td>#{s[1]}</td></tr>"
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..].join(',')})" : s[0]}#{s[0].spacer}#{s[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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
4
  # Semantic versioning library
3
5
  class SemVer
@@ -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..].map { |s| Regexp.escape(s) }.join('')
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 = self.dup
401
+ s = dup
400
402
  m = s.length
401
403
  n = t.length
402
- return m if n == 0
403
- return n if m == 0
404
- d = Array.new(m+1) {Array.new(n+1)}
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] # adjust index into string
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
- [ d[i-1][j]+1, # deletion
414
- d[i][j-1]+1, # insertion
415
- d[i-1][j-1]+1, # substitution
416
- ].min
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
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Main module
1
4
  module SL
5
+ # URL module
2
6
  module URL
3
7
  class << self
4
8
  # Validates that a link exists and returns 200
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
4
+ # Utilities
2
5
  module Util
3
6
  class << self
4
7
  ## Execute system command with deadman's switch
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SL
2
- VERSION = '2.3.65'
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 %x{uname}.strip !~ /Darwin/
74
+ if `uname`.strip !~ /Darwin/
72
75
  add_output('Auto updating only available on macOS')
73
76
  return
74
77
  end
@@ -5,171 +5,166 @@
5
5
 
6
6
  module TTY
7
7
  module Which
8
- VERSION = "0.5.0"
9
- end # Which
10
- end # TTY
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
- # Find an executable in a platform independent way
16
- #
17
- # @param [String] cmd
18
- # the command to search for
19
- # @param [Array<String>] paths
20
- # the paths to look through
21
- #
22
- # @example
23
- # which("ruby") # => "/usr/local/bin/ruby"
24
- # which("/usr/local/bin/ruby") # => "/usr/local/bin/ruby"
25
- # which("foo") # => nil
26
- #
27
- # @example
28
- # which("ruby", paths: ["/usr/locale/bin", "/usr/bin", "/bin"])
29
- #
30
- # @return [String, nil]
31
- # the absolute path to executable if found, `nil` otherwise
32
- #
33
- # @api public
34
- def which(cmd, paths: search_paths)
35
- if file_with_path?(cmd)
36
- return cmd if executable_file?(cmd)
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
- extensions.each do |ext|
39
- exe = "#{cmd}#{ext}"
40
- return ::File.absolute_path(exe) if executable_file?(exe)
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
- paths.each do |path|
46
- if file_with_exec_ext?(cmd)
47
- exe = ::File.join(path, cmd)
48
- return ::File.absolute_path(exe) if executable_file?(exe)
49
- end
50
- extensions.each do |ext|
51
- exe = ::File.join(path, "#{cmd}#{ext}")
52
- return ::File.absolute_path(exe) if executable_file?(exe)
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
- # 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
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
- # Find default system paths
76
- #
77
- # @param [String] path
78
- # the path to search through
79
- #
80
- # @example
81
- # search_paths("/usr/local/bin:/bin")
82
- # # => ["/bin"]
83
- #
84
- # @return [Array<String>]
85
- # the array of paths to search
86
- #
87
- # @api private
88
- def search_paths(path = ENV["PATH"])
89
- paths = if path && !path.empty?
90
- path.split(::File::PATH_SEPARATOR)
91
- else
92
- %w[/usr/local/bin /usr/ucb /usr/bin /bin /opt/homebrew/bin]
93
- end
94
- paths.select(&Dir.method(:exist?))
95
- end
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
- # All possible file extensions
99
- #
100
- # @example
101
- # extensions(".exe;cmd;.bat")
102
- # # => [".exe", ".bat"]
103
- #
104
- # @param [String] path_ext
105
- # a string of semicolon separated filename extensions
106
- #
107
- # @return [Array<String>]
108
- # an array with valid file extensions
109
- #
110
- # @api private
111
- def extensions(path_ext = ENV["PATHEXT"])
112
- return [""] unless path_ext
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
- path_ext.split(::File::PATH_SEPARATOR).select { |part| part.include?(".") }
115
- end
116
- module_function :extensions
112
+ path_ext.split(::File::PATH_SEPARATOR).select { |part| part.include?('.') }
113
+ end
117
114
 
118
- # Determines if filename is an executable file
119
- #
120
- # @example Basic usage
121
- # executable_file?("/usr/bin/less") # => true
122
- #
123
- # @example Executable in directory
124
- # executable_file?("less", "/usr/bin") # => true
125
- # executable_file?("less", "/usr") # => false
126
- #
127
- # @param [String] filename
128
- # the path to file
129
- # @param [String] dir
130
- # the directory within which to search for filename
131
- #
132
- # @return [Boolean]
133
- #
134
- # @api private
135
- def executable_file?(filename, dir = nil)
136
- path = ::File.join(dir, filename) if dir
137
- path ||= filename
138
- ::File.file?(path) && ::File.executable?(path)
139
- end
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
- # Check if command itself has executable extension
143
- #
144
- # @param [String] filename
145
- # the path to executable file
146
- #
147
- # @example
148
- # file_with_exec_ext?("file.bat")
149
- # # => true
150
- #
151
- # @return [Boolean]
152
- #
153
- # @api private
154
- def file_with_exec_ext?(filename)
155
- extension = ::File.extname(filename)
156
- return false if extension.empty?
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
- extensions.any? { |ext| extension.casecmp(ext).zero? }
159
- end
160
- module_function :file_with_exec_ext?
154
+ extensions.any? { |ext| extension.casecmp(ext).zero? }
155
+ end
161
156
 
162
- # Check if executable file is part of absolute/relative path
163
- #
164
- # @param [String] cmd
165
- # the executable to check
166
- #
167
- # @return [Boolean]
168
- #
169
- # @api private
170
- def file_with_path?(cmd)
171
- ::File.expand_path(cmd) == cmd
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
- module_function :file_with_path?
174
- end # Which
175
- end # TTY
169
+ end
170
+ end
data/lib/searchlink.rb CHANGED
@@ -4,7 +4,6 @@
4
4
  # MIT License, please maintain attribution
5
5
  require 'net/https'
6
6
  require 'uri'
7
- require 'rexml/document'
8
7
  require 'shellwords'
9
8
  require 'yaml'
10
9
  require 'cgi'
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.65
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-01-16 00:00:00.000000000 Z
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.16
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.