Module: SL::Searches

Defined in:
lib/searchlink/searches.rb

Class Method Summary collapse

Class Method Details

.all_possible_searchesObject



76
77
78
79
80
# File 'lib/searchlink/searches.rb', line 76

def all_possible_searches
  searches = []
  plugins[:search].each { |_, plugin| plugin[:searches].each { |s| searches.push(s[0]) } }
  searches.concat(SL.config['custom_site_searches'].keys)
end

.available_searchesString

Aligned list of available searches

Returns:

  • (String)

    Aligned list of searches



61
62
63
64
65
66
67
68
69
# File 'lib/searchlink/searches.rb', line 61

def available_searches
  searches = []
  plugins[:search].each { |_, plugin| searches.concat(plugin[:searches].delete_if { |s| s[1].nil? }) }
  out = []
  searches.each do |s|
    out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..].join(',')})" : s[0]}#{s[0].spacer}#{s[1]}"
  end
  out.join("\n")
end

.available_searches_htmlString

Output an HTML table of available searches

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/searchlink/searches.rb', line 41

def available_searches_html
  searches = plugins[:search]
             .flat_map { |_, plugin| plugin[:searches] }
             .reject { |s| s[1].nil? }
             .sort_by { |s| s[0].is_a?(Array) ? s[0][0] : s[0] }
  out = ['<table id="searches">',
         '<thead><td>Shortcut</td><td>Search Type</td></thead>',
         '<tbody>']

  searches.each do |s|
    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>"
  end
  out.concat(['</tbody>', '</table>']).join("\n")
end

.best_search_match(term) ⇒ Object



71
72
73
74
# File 'lib/searchlink/searches.rb', line 71

def best_search_match(term)
  searches = all_possible_searches.dup
  searches.flatten.select { |s| s.matches_score(term, separator: '', start_word: false) > 8 }
end

.description_for_search(search_type) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/searchlink/searches.rb', line 24

def description_for_search(search_type)
  description = "#{search_type} search"
  plugins[:search].each do |_, plugin|
    search = plugin[:searches].select { |s| s[0].is_a?(Array) ? s[0].include?(search_type) : s[0] == search_type }
    unless search.empty?
      description = search[0][1]
      break
    end
  end
  description
end

.did_you_mean(term) ⇒ Object



82
83
84
85
# File 'lib/searchlink/searches.rb', line 82

def did_you_mean(term)
  matches = best_search_match(term)
  matches.empty? ? '' : ", did you mean #{matches.map { |m| "!#{m}" }.join(', ')}?"
end

.do_search(search_type, search_terms, link_text, timeout: ) ⇒ Object



133
134
135
136
137
138
139
140
141
# File 'lib/searchlink/searches.rb', line 133

def do_search(search_type, search_terms, link_text, timeout: SL.config['timeout'])
  plugins[:search].each do |_title, plugin|
    trigger = plugin[:trigger].gsub(/(^\^|\$$)/, '')
    if search_type =~ /^#{trigger}$/
      search = proc { plugin[:class].search(search_type, search_terms, link_text) }
      return SL::Util.search_with_timeout(search, timeout)
    end
  end
end

.load_customObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/searchlink/searches.rb', line 116

def load_custom
  plugins_folder = File.expand_path('~/.local/searchlink/plugins')
  new_plugins_folder = File.expand_path('~/.config/searchlink/plugins')

  if File.directory?(plugins_folder) && !File.directory?(new_plugins_folder)
    Dir.glob(File.join(plugins_folder, '**/*.rb')).sort.each do |plugin|
      require plugin
    end
  end

  return unless File.directory?(new_plugins_folder)

  Dir.glob(File.join(new_plugins_folder, '**/*.rb')).sort.each do |plugin|
    require plugin
  end
end

.load_searchesObject



8
9
10
# File 'lib/searchlink/searches.rb', line 8

def load_searches
  Dir.glob(File.join(File.dirname(__FILE__), 'searches', '*.rb')).sort.each { |f| require f }
end

.pluginsObject



4
5
6
# File 'lib/searchlink/searches.rb', line 4

def plugins
  @plugins ||= {}
end

.register(title, type, klass) ⇒ Object

Register a plugin with the plugin manager

Parameters:

  • title (String, Array)

    title or array of titles

  • type (Symbol)

    plugin type (:search)

  • klass (Class)

    class that handles plugin actions. Search plugins must have a #settings and a #search method



20
21
22
# File 'lib/searchlink/searches.rb', line 20

def register(title, type, klass)
  Array(title).each { |t| register_plugin(t, type, klass) }
end

.register_plugin(title, type, klass) ⇒ Object

Raises:

  • (StandardError)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/searchlink/searches.rb', line 101

def register_plugin(title, type, klass)
  raise StandardError, "Plugin #{title} has no settings method" unless klass.respond_to? :settings

  settings = klass.settings

  raise StandardError, "Plugin #{title} has no search method" unless klass.respond_to? :search

  plugins[type] ||= {}
  plugins[type][title] = {
    trigger: settings.fetch(:trigger, title).normalize_trigger,
    searches: settings[:searches],
    class: klass
  }
end

.valid_search?(term) ⇒ Boolean

Returns:

  • (Boolean)


93
94
95
96
97
98
99
# File 'lib/searchlink/searches.rb', line 93

def valid_search?(term)
  valid = false
  valid = true if term =~ /^(#{valid_searches.join('|')})$/
  valid = true if SL.config['custom_site_searches'].keys.include? term
  # SL.notify("Invalid search#{did_you_mean(term)}", term) unless valid
  valid
end

.valid_searchesObject



87
88
89
90
91
# File 'lib/searchlink/searches.rb', line 87

def valid_searches
  searches = []
  plugins[:search].each { |_, plugin| searches.push(plugin[:trigger]) }
  searches
end