Module: SL::Searches

Defined in:
lib/searchlink/searches.rb

Overview

Searches and plugin registration

Class Method Summary collapse

Class Method Details

.all_possible_searchesObject



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

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
# 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|
    out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-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:



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..-1].join(',')})" : s[0]}
    </code>
    </td><td>#{s[1]}</td></tr>"
  end
  out.concat(['</tbody>', '</table>']).join("\n")
end

.best_search_match(term) ⇒ Object



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

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



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

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



161
162
163
164
165
166
167
168
169
# File 'lib/searchlink/searches.rb', line 161

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



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/searchlink/searches.rb', line 123

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



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/searchlink/searches.rb', line 144

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:



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/searchlink/searches.rb', line 108

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],
    class: klass
  }
end

.valid_search?(term) ⇒ Boolean

Returns:

  • (Boolean)


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

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



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

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