plugin-loader 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ # command.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The command format takes '$' to be a command, executes it, and
21
+ #returns an array of lines of standard output.
22
+ # {
23
+ # "format" => "command",
24
+ # "$" => "COMMAND"
25
+ # }
26
+ require 'plugin/format'
27
+
28
+ #Depends: libescape-ruby
29
+ require 'escape'
30
+
31
+ Plugin::Format.add 'command' do |exec, args, opts|
32
+ IO.popen Escape.shell_command([exec.to_s, *args]).to_s do |handle|
33
+ return handle.read.split("\n")
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ # data.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #data is a very simple plugin format that just returns the data structure
21
+ #referred to by the '$' key in the plugin metadata file:
22
+ # {
23
+ # "format" : "data",
24
+ # "$" : ...
25
+ # }
26
+ #The data can be any type supported by JSON, including number, string, array,
27
+ #hash(object) and boolean.
28
+ require 'plugin/format'
29
+
30
+ Plugin::Format.add 'data' do |exec, args, opts|
31
+ exec
32
+ end
@@ -0,0 +1,67 @@
1
+ # dbus.rb
2
+ #
3
+ # Defines a plugin format that works by connecting to a dbus service.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+ #
22
+ #
23
+ #A plugin in dbus format has a general metadata file format of:
24
+ # {
25
+ # 'format' : 'dbus',
26
+ # '$' : [service, object, interface, method]
27
+ # }
28
+ #For example:
29
+ # {
30
+ # "format" : "dbus",
31
+ # "$" : [
32
+ # "org.gnome.Rhythmbox",
33
+ # "/org/gnome/Rhythmbox/Player",
34
+ # "org.gnome.Rhythmbox.Player",
35
+ # "getPlayingUri"
36
+ # ]
37
+ # }
38
+ #describes a plugin that gets the current playing song in Rhythmbox.
39
+ #
40
+ #The dbus format uses the dbus session bus.
41
+ #It only works with dbus services that can be introspected (which is almost all of them).
42
+ require 'plugin/format'
43
+
44
+ #Depends: libdbus-ruby
45
+ require 'dbus'
46
+
47
+ module Plugin
48
+
49
+ Format.add 'dbus' do |exec, args, opts|
50
+ service = exec[0]
51
+ object = exec[1]
52
+ iface = exec[2]
53
+ method = exec[3]
54
+
55
+ obj = DBus::SessionBus.
56
+ instance.
57
+ service(service).
58
+ object(object)
59
+
60
+ obj.introspect
61
+
62
+ obj[iface].
63
+ method(method).
64
+ call(*args)
65
+ end
66
+
67
+ end
@@ -0,0 +1,48 @@
1
+ # ruby.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The ruby format allows plugins to be written in ruby.
21
+ #The '$' key refers to the ruby file that should be loaded.
22
+ #The metadata file has the following format:
23
+ # {
24
+ # "format" : "ruby",
25
+ # "$" : "ruby_lib"
26
+ # }
27
+ #The ruby file should look something like:
28
+ # Plugin.new do |*args|
29
+ # #some code
30
+ # end
31
+ require 'plugin/format'
32
+
33
+ module Plugin
34
+
35
+ _ruby_plugin = lambda do |*args|
36
+ args
37
+ end
38
+
39
+ def self.new &b
40
+ _ruby_plugin = b
41
+ end
42
+
43
+ Format.add 'ruby' do |exec, args, opts|
44
+ load exec
45
+ _ruby_plugin.call *args
46
+ end
47
+
48
+ end
@@ -0,0 +1,35 @@
1
+ # script.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The script format takes '$' to be an executable in the @script_dir folder.
21
+ #The script is executed and an array of lines of standard output is returned.
22
+ # {
23
+ # "format" => "command",
24
+ # "$" => "COMMAND"
25
+ # }
26
+ require 'plugin/format'
27
+
28
+ #Depends: libescape-ruby
29
+ require 'escape'
30
+
31
+ Plugin::Format.add 'script' do |exec, args, opts|
32
+ IO.popen Escape.shell_command(["#{opts[:dir] || '/usr/bin'}/#{exec}", *args]).to_s do |handle|
33
+ return handle.read.split("\n")
34
+ end
35
+ end
@@ -0,0 +1,68 @@
1
+ # format.rb
2
+ #
3
+ # Defines a class allowing new plugin formats to be added.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+
22
+
23
+ module Plugin
24
+
25
+ #An instance of this class represents a plugin format.
26
+ class Format
27
+ @@formats = {}
28
+ #To create a new annonymous plugin format:
29
+ # Plugin::Format.new do |exec, args, opts|
30
+ # ...
31
+ # return return_data
32
+ # end
33
+ #Argument 'exec' provides the data in the '$' key of the plugin metadata file.
34
+ #Argument 'args' is an array of arguments passed to this format by a Plugin::Loader instance when its run method is called.
35
+ #Argument 'opts' is a hash of options from Plugin::Loader that may be required by a plugin format. At present opts conatins the following keys:
36
+ # :plugin_dir
37
+ # :data_dir
38
+ # :script_dir
39
+ #These are the same as the options given when the Plugin::Loader was initialized.
40
+ #
41
+ #Plugin::Format.add should be used to create a new plugin format because the format is given a name.
42
+ def initialize &b
43
+ @block = b
44
+ end
45
+ #Creates a lambda function from the exec value and opts hash.
46
+ #When the lambda function is called, its arguments become 'args' and
47
+ #the block given at initialize is executed.
48
+ def new exec, opts={}
49
+ lambda do |*args|
50
+ @block.call exec, args, opts
51
+ end
52
+ end
53
+ #Creates a named plugin format using the same rules as Plugin::Format.new:
54
+ # Plugin::Format.add "name" do |exec, args, opts|
55
+ # ...
56
+ # return return_data
57
+ # end
58
+ def self.add name, &b
59
+ @@formats[name] = self.new &b
60
+ end
61
+ #Returns the format called 'name':
62
+ # Plugin::Format['name']
63
+ def self.[] name
64
+ @@formats[name]
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,130 @@
1
+ # loader.rb
2
+ #
3
+ # Provides a class for loading plugins into a program.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+ require 'plugin/format'
22
+
23
+ #Depends: libjson-ruby
24
+ require 'json'
25
+
26
+ module Plugin
27
+
28
+ #Using an instance of this class, you can control what plugins are
29
+ #loaded into your program.
30
+ class Loader
31
+ #OPTIONS:
32
+ #
33
+ # :allowed_formats => [...] #optional; default is an array of all available plugin formats
34
+ #- Defines an array of names (strings) of formats that plugins for this instance can be written in.
35
+ #
36
+ # :data_dir => '/usr/share/appname' #required
37
+ #- Defines the directory in which the data for this instance is stored in the file system.
38
+ #
39
+ # :plugin_dir => '' #optional; default is "#{@data_dir}/plugins"
40
+ #- Defines the directory in which the plugin metadata files are stored
41
+ #
42
+ # :script_dir => '' #optional; default is "#{@data_dir}/scripts"
43
+ #- Defines the directory in which excecutables (potentially used by plugins) are stored.
44
+ def initialize opts={}
45
+ @available_formats = $:.map do |path|
46
+ Dir.glob("#{path}/plugin/format/*.rb").map! do |rbfile|
47
+ File.basename(rbfile).sub!(/\.rb$/, '')
48
+ end
49
+ end
50
+ @available_formats.flatten!
51
+ @allowed_formats = opts[:allowed_formats] ? (opts[:allowed_formats] & available_formats) : available_formats
52
+ @allowed_formats.each do |fmt|
53
+ require "plugin/format/#{fmt}"
54
+ end
55
+ @data_dir = opts[:data_dir]
56
+ @plugin_dir = opts[:plugin_dir] || "#{@data_dir}/plugins"
57
+ @script_dir = opts[:script_dir] || "#{@data_dir}/scripts"
58
+ @plugins = {}
59
+ end
60
+ #Loads a plugin called 'name' of type 'type'.
61
+ #It does this by reading the metadata file: "#{@plugin_dir}/name.type".
62
+ #Plugin types should be considered namespaces for one or more plugins.
63
+ #Plugin names are the unique identification of a plugin within a particular type.
64
+ #Plugins are similar to functions - they are excecuted with arguments a value (which can be a complex data structure such as hash or array if needed).
65
+ #load does not excecute a plugin but it once loaded
66
+ #a plugin can be excecuted with the run method.
67
+ #
68
+ #The metadata files are in a JSON format:
69
+ # {
70
+ # "format" => "FORMAT_NAME",
71
+ # "$" => ...
72
+ # }
73
+ #The 'format' key is a string that defines the name of the format of the plugin. If load loads a plugin without the 'format' key, an exception is raised.
74
+ #If the format is not available or is not allowed (see: initailize), an exception is raised.
75
+ #See Plugin::Format for more details on plugin formats.
76
+ #The '$' key can be any data structure (most commonly a string) and is used by the format declaration to excecute a plugin. See the individual format declarations in plugin/format/*.rb for details of individual formats. If the '$' key is missing, an exception is raised.
77
+ def load name, type
78
+ File.open "#{@plugin_dir}/#{name}.#{type}" do |f|
79
+ data = JSON.parse(f.read)
80
+ unless data.has_key? '$'
81
+ raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required '$' key!"
82
+ end
83
+ unless data.has_key? 'format'
84
+ raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required 'format' key!"
85
+ end
86
+ unless @plugins.has_key? type
87
+ @plugins[type] = {}
88
+ end
89
+ format = Format[data['format']]
90
+ if format.nil?
91
+ raise "Plugin format #{data['format']} does not exist or is disabled!"
92
+ end
93
+ @plugins[type][name] = format.new data['$'],
94
+ :script_dir => @script_dir,
95
+ :data_dir => @data_dir,
96
+ :plugin_dir => @plugin_dir
97
+ end
98
+ end
99
+ #Unloads a plugin of name 'name' and type 'type'.
100
+ def unload name, type
101
+ @plugins[type].delete name
102
+ end
103
+ #Loads all plugins of type 'type'.
104
+ def load_type type
105
+ Dir.glob("#{@plugin_dir}/*.#{type}").each do |file|
106
+ self.load file
107
+ end
108
+ end
109
+ #Unloads all plugins of type 'type'.
110
+ def unload_type type
111
+ @plugins.delete type
112
+ end
113
+ #Loads all plugins.
114
+ def load_all
115
+ Dir.glob("#{@plugin_dir}/*").each do |file|
116
+ self.load file
117
+ end
118
+ end
119
+ #Unloads all plugins.
120
+ def unload_all
121
+ @plugins.clear
122
+ end
123
+ #Excecutes the plugin of type 'type' called 'name', passing in any other arguments.
124
+ #The return value of the plugin is returned.
125
+ def run name, type, *args
126
+ @plugins[type][name].call *args
127
+ end
128
+ end
129
+
130
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: plugin-loader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Green
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-09-25 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dbus
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: escape
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: |-
46
+ plugin-loader can be used to extend a program written in ruby by using plugins.
47
+ Plugins can be written in ruby or can be external resources.
48
+ email: david4dev@gmail.com
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - lib/plugin/format/dbus.rb
57
+ - lib/plugin/format/script.rb
58
+ - lib/plugin/format/ruby.rb
59
+ - lib/plugin/format/data.rb
60
+ - lib/plugin/format/command.rb
61
+ - lib/plugin/format.rb
62
+ - lib/plugin/loader.rb
63
+ has_rdoc: true
64
+ homepage: https://launchpad.net/libplugin-loader-ruby
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 1.8.1
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Library for creating extensible ruby applications
91
+ test_files: []
92
+