Module: Doing::Plugins

Defined in:
lib/doing/plugin_manager.rb

Overview

Plugin handling

Class Method Summary collapse

Class Method Details

.available_plugins(type: :export) ⇒ Array

Return array of available plugin names

Parameters:

  • type (Symbol) (defaults to: :export)

    Plugin type (:import, :export)

Returns:

  • (Array)

    Array of plugin names (String)



182
183
184
185
# File 'lib/doing/plugin_manager.rb', line 182

def available_plugins(type: :export)
  type = valid_type(type)
  plugins[type].keys.sort
end

.list_plugins(options = {}) ⇒ Object

List available plugins to stdout

Parameters:

  • options (Hash) (defaults to: {})

    additional options

Options Hash (options):

  • :column (Boolean)

    display results in a single column

  • :type (String)

    Plugin type: all, import, or export



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/doing/plugin_manager.rb', line 158

def list_plugins(options = {})
  separator = options[:column] ? "\n" : "\t"
  type = options[:type].nil? || options[:type] =~ /all/i ? 'all' : valid_type(options[:type])

  case type
  when :import
    puts plugin_names(type: :import, separator: separator)
  when :export
    puts plugin_names(type: :export, separator: separator)
  else
    print 'Import plugins: '
    puts plugin_names(type: :import, separator: ', ')
    print 'Export plugins: '
    puts plugin_names(type: :export, separator: ', ')
  end
end

.load_plugins(add_dir = nil) ⇒ Object

Load plugins from plugins folder



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/doing/plugin_manager.rb', line 28

def load_plugins(add_dir = nil)
  plugins_path(add_dir).each do |plugin_search_path|
    Dir.glob(File.join(plugin_search_path, '**', '*.rb')).sort.each do |plugin|
      require plugin
    end
  end

  Gem.find_latest_files('doing-plugin-*', true).sort.each do |plugin|
    load plugin
  end

  # Gem.path.each do |path|
  #   $LOAD_PATH.unshift path
  #   Dir.glob(File.join(path, 'gems', 'doing-plugin-*', 'lib', '*.rb')).sort.each do |plugin|
  #     require plugin.sub(%r{#{path}/gems/(.*?)-[\d.]+$}, '\1')
  #   end
  # end

  plugins
end

.plugin_names(type: :export, separator: '|') ⇒ String

Return string version of plugin names

Parameters:

  • type (defaults to: :export)

    Plugin type (:import, :export)

  • separator (defaults to: '|')

    The separator to join names with

Returns:

  • (String)

    Plugin names joined with separator



195
196
197
198
# File 'lib/doing/plugin_manager.rb', line 195

def plugin_names(type: :export, separator: '|')
  type = valid_type(type)
  available_plugins(type: type).join(separator)
end

.plugin_regex(type: :export) ⇒ Regexp

Return a regular expression of all plugin triggers for type

Parameters:

  • type (Symbol) (defaults to: :export)

    The type :import or :export

Returns:

  • (Regexp)

    regular expression



209
210
211
212
213
214
215
216
# File 'lib/doing/plugin_manager.rb', line 209

def plugin_regex(type: :export)
  type = valid_type(type)
  pattern = []
  plugins[type].each do |_, options|
    pattern << options[:trigger].normalize_trigger
  end
  Regexp.new("^(?:#{pattern.sort.uniq.join('|')})$", true)
end

.plugin_templates(type: :export) ⇒ Array

Return array of available template names

Parameters:

  • type (Symbol) (defaults to: :export)

    Plugin type (:import, :export)

Returns:

  • (Array)

    Array of template names (String)



226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/doing/plugin_manager.rb', line 226

def plugin_templates(type: :export)
  type = valid_type(type)
  templates = []
  plugs = plugins[type].clone
  plugs.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
    options[:templates].each do |t|
      out = t[:name]
      out += " (#{t[:format]})" if t.key?(:format)
      templates << out
    end
  end

  templates.sort.uniq
end

.pluginsHash

Storage for registered plugins. Hash with :import and :export keys containing hashes of available plugins.

Returns:

  • (Hash)

    registered plugins



18
19
20
21
22
23
# File 'lib/doing/plugin_manager.rb', line 18

def plugins
  @plugins ||= {
    import: {},
    export: {}
  }
end

.plugins_path(add_dir = nil) ⇒ Array

Setup the plugin search path

Parameters:

  • add_dir (String) (defaults to: nil)

    optional additional path to include

Returns:

  • (Array)

    Returns an Array of plugin search paths



56
57
58
59
60
# File 'lib/doing/plugin_manager.rb', line 56

def plugins_path(add_dir = nil)
  paths = Array(File.join(File.dirname(__FILE__), 'plugins'))
  paths << File.join(add_dir) if add_dir
  paths.map { |d| File.expand_path(d) }
end

.register(title, type, klass) ⇒ Boolean

Register a plugin

Parameters:

  • title (String|Array)

    The name of the plugin (can be an array of names)

  • type (Symbol)

    The plugin type (:import, :export)

  • klass (Class)

    The class responding to :render or :import

Returns:

  • (Boolean)

    Success boolean



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/doing/plugin_manager.rb', line 74

def register(title, type, klass)
  type = validate_plugin(title, type, klass)
  return unless type

  if title.is_a?(Array)
    title.each { |t| register(t, type, klass) }
    return
  end

  settings = if klass.respond_to? :settings
               klass.settings
             else
               { trigger: title.normalize_trigger, config: {} }
             end

  plugins[type] ||= {}
  plugins[type][title] = {
    trigger: settings[:trigger].normalize_trigger || title.normalize_trigger,
    class: klass,
    templates: settings[:templates] || nil,
    config: settings[:config] || {}
  }

  return unless ENV['DOING_PLUGIN_DEBUG']

  Doing.logger.debug('Plugin Manager:', "Registered #{type} plugin \"#{title}\"")
end

.template_for_trigger(trigger, type: :export, save_to: nil) ⇒ String

Find and return the appropriate template for a trigger string. Outputs a string that can be written out to the terminal for redirection

Parameters:

  • trigger (String)

    The trigger to test

  • type (Symbol) (defaults to: :export)

    the plugin type (:import, :export)

  • save_to (String) (defaults to: nil)

    if a path is specified, write the template to that path. Nil for STDOUT

Returns:

  • (String)

    string content of template for trigger

Raises:



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/doing/plugin_manager.rb', line 276

def template_for_trigger(trigger, type: :export, save_to: nil)
  plugins[valid_type(type)].clone.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
    options[:templates].each do |t|
      next unless trigger =~ /^(?:#{t[:trigger].normalize_trigger})$/

      tpl = options[:class].template(trigger)
      return tpl unless save_to

      raise PluginException.new('No default filename defined', :export, t[:name]) unless t.key?(:filename)

      return save_template(tpl, save_to, t[:filename])
    end
  end
  raise Errors::InvalidArgument, "No template type matched \"#{trigger}\""
end

.template_regex(type: :export) ⇒ Regexp

Return a regular expression of all template triggers for type

Parameters:

  • type (Symbol) (defaults to: :export)

    The type :import or :export

Returns:

  • (Regexp)

    regular expression



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/doing/plugin_manager.rb', line 250

def template_regex(type: :export)
  type = valid_type(type)
  pattern = []
  plugs = plugins[type].clone
  plugs.delete_if { |_, o| o[:templates].nil? }.each do |_, options|
    options[:templates].each do |t|
      pattern << t[:trigger].normalize_trigger
    end
  end
  Regexp.new("^(?:#{pattern.join('|')})$", true)
end

.user_homeObject

Return the user's home directory



8
9
10
# File 'lib/doing/plugin_manager.rb', line 8

def user_home
  @user_home ||= Util.user_home
end

.valid_type(type, default: nil) ⇒ Symbol

Converts a partial symbol to a valid plugin type, e.g. :imp => :import

Parameters:

  • type (Symbol)

    the symbol to test

  • default (Symbol) (defaults to: nil)

    fallback value

Returns:

  • (Symbol)

    :import or :export



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/doing/plugin_manager.rb', line 135

def valid_type(type, default: nil)
  type ||= default

  t = type.to_s
  type = case t
         when /^i(m(p(o(r(t)?)?)?)?)?$/
           :import
         when /^e(x(p(o(r(t)?)?)?)?)?$/
           :export
         else
           raise Errors::InvalidPluginType.new('Invalid plugin type', 'unrecognized')
         end

  type.to_sym
end

.validate_plugin(title, type, klass) ⇒ Object

Verifies that a plugin is properly configured with necessary methods for its type. If the plugin fails validation, a PluginUncallable exception will be raised.

Parameters:

  • title (String)

    The title

  • type (Symbol)

    type, :import or :export

  • klass (Class)

    Plugin class



113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/doing/plugin_manager.rb', line 113

def validate_plugin(title, type, klass)
  type = valid_type(type)
  if type == :import && !klass.respond_to?(:import)
    raise Errors::PluginUncallable.new('Import plugins must respond to :import', type, title)
  end

  if type == :export && !klass.respond_to?(:render)
    raise Errors::PluginUncallable.new('Export plugins must respond to :render', type, title)
  end

  type
end