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<String>

Return array of available plugin names

Parameters:

  • type (defaults to: :export)

    Plugin type (:import, :export)

Returns:



151
152
153
154
# File 'lib/doing/plugin_manager.rb', line 151

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 (type, separator) (defaults to: {})


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/doing/plugin_manager.rb', line 127

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



21
22
23
24
25
26
27
28
29
# File 'lib/doing/plugin_manager.rb', line 21

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

  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:



164
165
166
167
# File 'lib/doing/plugin_manager.rb', line 164

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



178
179
180
181
182
183
184
185
# File 'lib/doing/plugin_manager.rb', line 178

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

.plugin_templates(type: :export) ⇒ Array<String>

Return array of available template names

Parameters:

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

    Plugin type (:import, :export)

Returns:



195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/doing/plugin_manager.rb', line 195

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

.pluginsObject



11
12
13
14
15
16
# File 'lib/doing/plugin_manager.rb', line 11

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



38
39
40
41
42
# File 'lib/doing/plugin_manager.rb', line 38

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



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/doing/plugin_manager.rb', line 56

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

.save_template(tpl, dir, filename) ⇒ Object

Raises:

  • (DoingRuntimeError)


258
259
260
261
262
263
264
265
266
267
268
# File 'lib/doing/plugin_manager.rb', line 258

def save_template(tpl, dir, filename)
  dir = File.expand_path(dir)
  FileUtils.mkdir_p(dir) unless File.exist?(dir)
  raise DoingRuntimeError, "Path #{dir} exists but is not a directory" unless File.directory?(dir)

  file = File.join(dir, filename)
  File.open(file, 'w') do |f|
    f.puts(tpl)
    Doing.logger.warn('File update:', "Template written to #{file}")
  end
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)

Returns:

  • (String)

    string content of template for trigger

Raises:



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/doing/plugin_manager.rb', line 242

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



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/doing/plugin_manager.rb', line 219

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



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

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



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/doing/plugin_manager.rb', line 106

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, 'Invalid plugin type'
         end

  type.to_sym
end

.validate_plugin(title, type, klass) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/doing/plugin_manager.rb', line 84

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: type, plugin: title)
  end

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

  type
end