Skip to content

Commit

Permalink
Adds support to change the top level directory for plugins
Browse files Browse the repository at this point in the history
  * Fixes #13 - use different plugin path
  * previously by default, pluginator would only look in the directory
    named plugins.  While this is a great notion, many existing plugin
    systems do not follow this path.
    This attempts to allow the user to change the default plugins
    directory to something different.

    Example: lib/plugins/my_group/plugin_name.rb  can now be
             lib/alt_plugins/my_group/plugin_name.rb.
  • Loading branch information
logicminds committed Jun 14, 2017
1 parent e205d0e commit ed71946
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*.gem
.bundle
/Gemfile.lock
/coverage
/doc
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ plugins.types => Array of types
- `type: "<type>"` - Load plugins only of given type, optional, makes `type` method accessible.
- `prefix: "/prefix"` - Load plugins only from this paths, optional, default `/lib`.
- `extends: %i[<extensions>]` - Extend pluginator with given extensions.
- `plugins_dir_name: 'plugins'` - the top level directory name to use when looking for plugins, defaults to "plugins"

## Extensions

Expand Down
5 changes: 3 additions & 2 deletions lib/pluginator/autodetect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ class Autodetect
# @option prefix [String] a prefix for finding plugins if forcing,
# by default only `/lib` is checked,
# regexp notation is allowed, for example `/(lib|local_lib)`

# @option plugins_dir_name [String] the top level directory name to use when looking for plugins
def initialize(group, options={})
super(group)
@force_prefix = options[:prefix]
@force_type = options[:type]
@plugins_dir_name = options[:plugins_dir_name] || 'plugins'
refresh
end

Expand All @@ -55,7 +56,7 @@ def initialize(group, options={})
#
# Use it after gem list change, for example after `Gem.install("new_gem")`
def refresh
plugin_lists = FormattedFinder.new(@force_prefix, @group, @force_type)
plugin_lists = FormattedFinder.new(@force_prefix, @group, @force_type, @plugins_dir_name)
register_plugins(plugin_lists.loaded_plugins_path)
load_plugins(plugin_lists.load_path_plugins_paths)
activate_plugins(plugin_lists.gem_plugins_paths)
Expand Down
15 changes: 9 additions & 6 deletions lib/pluginator/autodetect/finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class Autodetect
# Find plugins
class Finder

attr_reader :loaded_plugins_path, :load_path_plugins_paths, :gem_plugins_paths
attr_reader :loaded_plugins_path, :load_path_plugins_paths,
:gem_plugins_paths, :plugins_dir_name, :group, :force_type

# Automatically load plugins for given group (and type)
#
Expand All @@ -32,10 +33,12 @@ class Finder
# regexp notation is allowed, for example `/[lib|]`
# @param group [String] name of the plugins group
# @param force_type [String] name of the plugin type if forcing
def initialize(force_prefix, group, force_type)
# @option plugins_dir_name [String] the top level directory name to use when looking for plugins
def initialize(force_prefix, group, force_type, plugins_dir_name = 'plugins')
@force_prefix = force_prefix
@group = group
@force_type = force_type
@plugins_dir_name = plugins_dir_name || 'plugins'
@pattern = file_name_pattern
find_paths
end
Expand All @@ -44,7 +47,7 @@ def initialize(force_prefix, group, force_type)

# group => pattern
def file_name_pattern
"plugins/#{@group}/#{@force_type || "**"}/*.rb"
File.join(plugins_dir_name, group, (force_type || '**'), '*.rb' )
end

def find_paths
Expand Down Expand Up @@ -79,9 +82,9 @@ def split_file_names(file_names)

# file_name => [ path, full_name, type ]
def split_file_name(file_name)
prefix = @force_prefix || "/lib"
type = @force_type || ".*"
match = file_name.match(%r{.*#{prefix}/(plugins/(#{@group}/(#{type})/[^/]*)\.rb)$})
prefix = force_prefix || "/lib"
type = force_type || ".*"
match = file_name.match(%r{.*#{prefix}/(#{plugins_dir_name}/(#{group}/(#{type})/[^/]*)\.rb)$})
match[-3..-1] if match
end

Expand Down
2 changes: 1 addition & 1 deletion lib/pluginator/autodetect/formatted_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Autodetect
class FormattedFinder < Finder

# Reformat plugin lists
def initialize(force_prefix, group, force_type)
def initialize(force_prefix, group, force_type, plugins_dir_name)
super
map_loaded_plugins
map_gem_plugins
Expand Down
3 changes: 2 additions & 1 deletion lib/pluginator/extendable_autodetect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ class ExtendableAutodetect < Autodetect
# @param options [Hash] options to pass to creating Pluginator instance
# @option type [String] name of type to load
# @option extends [Array<Symbol>|Symbol] list of extension to extend into pluginator instance
# @option plugins_dir_name [String] the top level directory name to use when looking for plugins
def initialize(group, options={})
super(group, options)
super
extend_plugins(options[:extends] || [])
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
=begin
Copyright 2013 Michal Papis <[email protected]>
This file is part of pluginator.
pluginator is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pluginator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pluginator. If not, see <http://www.gnu.org/licenses/>.
=end

class Something::Math::Decrease
def self.type
"decrease"
end
def self.action(number)
number - 1
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
=begin
Copyright 2013 Michal Papis <[email protected]>
This file is part of pluginator.
pluginator is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pluginator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pluginator. If not, see <http://www.gnu.org/licenses/>.
=end

class Something::Math::Increase
def self.type
"increase"
end
def self.action(number)
number + 1
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
=begin
Copyright 2013 Michal Papis <[email protected]>
This file is part of pluginator.
pluginator is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pluginator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pluginator. If not, see <http://www.gnu.org/licenses/>.
=end

class Something::Nested::Structure::Test

def self.action
42
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
=begin
Copyright 2013 Michal Papis <[email protected]>
This file is part of pluginator.
pluginator is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pluginator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pluginator. If not, see <http://www.gnu.org/licenses/>.
=end

class Something::Stats::Max

def self.handles?(what)
%w{ max maximum }.include?(what)
end

def self.action
42
end
end
71 changes: 67 additions & 4 deletions test/pluginator/autodetect_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,81 @@ def gem_files(*paths)
end

describe Pluginator::Autodetect do
before do
@math_parsed = [
let(:math_files) do
gem_files(math_parsed.map(&:first))
end

let(:math_parsed) do
[
["plugins/something/math/increase.rb", "something/math/increase", "math"],
["plugins/something/math/decrease.rb", "something/math/decrease", "math"]
]
@math_files = gem_files(@math_parsed.map(&:first))
@all_files = gem_files(
end

let(:all_files) do
gem_files(
"plugins/something/math/increase.rb", "plugins/something/math/decrease.rb",
"plugins/something/nested/structure/test.rb", "plugins/something/stats/max.rb"
)
end

describe :alt_plugins_dir do
let(:math_parsed) do
[
["kitchen/something/math/increase.rb", "something/math/increase", "math"],
["kitchen/something/math/decrease.rb", "something/math/decrease", "math"]
]
end

let(:all_files) do
gem_files(
"kitchen/something/math/increase.rb", "kitchen/something/math/decrease.rb",
"kitchen/something/nested/structure/test.rb", "kitchen/something/stats/max.rb"
)
end

it :loads_plugins_automatically_for_group do
pluginator = Pluginator::Autodetect.new("something")
pluginator.types.must_include("stats")
pluginator.types.must_include("math")
pluginator.types.size.must_equal(3)
plugins = pluginator["math"].map(&:to_s)
plugins.size.must_equal(2)
plugins.must_include("Something::Math::Increase")
plugins.must_include("Something::Math::Decrease")
plugins.wont_include("Something::Math::Add")
end

it :loads_plugins_automatically_for_group_type do
pluginator = Pluginator::Autodetect.new("something", :type => "stats")
pluginator.types.sort.must_equal(["stats"])
end

it :makes_group_plugins_work do
pluginator = Pluginator::Autodetect.new("something")
pluginator.types.must_include("math")
pluginator["math"].detect{|plugin| plugin.type == "increase" }.action(2).must_equal(3)
pluginator["math"].detect{|plugin| plugin.type == "decrease" }.action(5).must_equal(4)
end

it :hides_methods do
pluginator = Pluginator::Autodetect.new("something")
pluginator.public_methods.map(&:to_sym).must_include(:register_plugin)
pluginator.public_methods.map(&:to_sym).wont_include(:split_file_name)
end

it :has_no_type_when_not_forced do
pluginator = Pluginator::Autodetect.new("something")
pluginator.type.must_be_nil
end

it :defines_type_method_dynamically do
pluginator = Pluginator::Autodetect.new("something", :type => "math")
pluginator.type.wont_be_nil
pluginator.type.must_equal(pluginator["math"])
end
end

it :loads_plugins_automatically_for_group do
pluginator = Pluginator::Autodetect.new("something")
pluginator.types.must_include("stats")
Expand Down

0 comments on commit ed71946

Please sign in to comment.