searchlink 2.3.65 → 2.3.67

Sign up to get free protection for your applications and to get access to all the features.
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.