Module: SL::Searches

Defined in:
lib/searchlink/searches.rb

Overview

Searches and plugin registration

Class Method Summary collapse

Class Method Details

.all_possible_searchesObject



90
91
92
93
94
# File 'lib/searchlink/searches.rb', line 90

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

.available_searchesString

Aligned list of available searches

Returns:

  • (String)

    Aligned list of searches



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/searchlink/searches.rb', line 68

def available_searches
  searches = []
  plugins[:search].each_value { |plugin| searches.concat(plugin[:searches].delete_if { |s| s[1].nil? }) }
  out = []

  searches.each do |s|
    shortcut = if s[0].is_a?(Array)
                 "#{s[0][0]} (#{s[0][1..].join(',')})"
               else
                 s[0]
               end

    out << "!#{shortcut}#{shortcut.spacer}#{s[1]}"
  end
  out.join("\n")
end

.available_searches_htmlString

Output an HTML table of available searches

Returns:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/searchlink/searches.rb', line 44

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



85
86
87
88
# File 'lib/searchlink/searches.rb', line 85

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



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/searchlink/searches.rb', line 27

def description_for_search(search_type)
  description = "#{search_type} search"
  plugins[:search].each_value 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



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

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



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/searchlink/searches.rb', line 169

def do_search(search_type, search_terms, link_text, timeout: SL.config["timeout"])
  plugins[:search].each_value do |plugin|
    trigger = plugin[:trigger].gsub(/(^\^|\$$)/, "")
    next unless search_type =~ /^#{trigger}$/

    search = proc { plugin[:class].search(search_type, search_terms, link_text) }
    SL.config["skip_timeout"] = true if trigger =~ /^pop/

    return SL::Util.search_with_timeout(search, timeout)
  end
end

.load_customObject



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/searchlink/searches.rb', line 131

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

    load_custom_scripts(plugins_folder)
  end

  return unless File.directory?(new_plugins_folder)

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

  load_custom_scripts(new_plugins_folder)
end

.load_custom_scripts(plugins_folder) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/searchlink/searches.rb', line 152

def load_custom_scripts(plugins_folder)
  Dir.glob(File.join(plugins_folder, "**/*.{json,yml,yaml}")).each do |file|
    ext = File.extname(file).sub(/^\./, "")
    config = IO.read(file)

    cfg = case ext
          when /^y/i
            YAML.safe_load(config)
          else
            JSON.parse(config)
          end
    cfg["filename"] = File.basename(file)
    cfg["path"] = file.shorten_path
    SL::ScriptSearch.new(cfg)
  end
end

.load_searchesObject



11
12
13
# File 'lib/searchlink/searches.rb', line 11

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

.pluginsObject



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

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



23
24
25
# File 'lib/searchlink/searches.rb', line 23

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

.register_plugin(title, type, klass) ⇒ Object

Raises:



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

def register_plugin(title, type, klass)
  raise PluginError.new("Plugin has no settings method", plugin: title) unless klass.respond_to? :settings

  settings = klass.settings

  raise PluginError.new("Plugin has no search method", plugin: title) unless klass.respond_to? :search

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

.valid_search?(term) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
113
# File 'lib/searchlink/searches.rb', line 107

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



101
102
103
104
105
# File 'lib/searchlink/searches.rb', line 101

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