vop 0.3.1 → 0.3.4

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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +34 -33
  5. data/README.md +184 -2
  6. data/bin/console +17 -0
  7. data/bin/setup +8 -0
  8. data/bin/vop.sh +6 -2
  9. data/exe/vop +3 -25
  10. data/lib/boot.rb +3 -0
  11. data/lib/core/meta/commands/new_command.rb +1 -0
  12. data/lib/core/meta/commands/new_plugin.rb +47 -0
  13. data/lib/core/meta/commands/search_gems_for_plugins.rb +38 -0
  14. data/lib/core/meta/commands/search_path.rb +6 -0
  15. data/lib/core/meta/commands/set.rb +12 -0
  16. data/lib/core/meta/commands/show.rb +6 -0
  17. data/lib/core/meta/commands/show_config.rb +9 -0
  18. data/lib/core/meta/commands/who_provides.rb +6 -0
  19. data/lib/core/meta/meta.plugin +1 -0
  20. data/lib/core/shell/commands/change_loglevel.rb +6 -0
  21. data/lib/{vop/plugins/core → core/shell}/commands/clear_context.rb +0 -0
  22. data/lib/core/shell/commands/edit.rb +12 -0
  23. data/lib/core/shell/commands/help.rb +49 -0
  24. data/lib/core/shell/commands/reset.rb +4 -0
  25. data/lib/{vop/plugins/core → core/shell}/commands/show_context.rb +0 -0
  26. data/lib/core/shell/commands/source.rb +21 -0
  27. data/lib/{vop/plugins/core/helpers/plugin_loader/plugin_syntax.rb → core/shell/shell.plugin} +0 -0
  28. data/lib/core/structure/commands/collect_contributions.rb +46 -0
  29. data/lib/core/structure/commands/disable_contributor.rb +16 -0
  30. data/lib/core/structure/commands/generate_entity_commands.rb +52 -0
  31. data/lib/core/structure/commands/generate_invalidation_commands.rb +26 -0
  32. data/lib/core/structure/commands/list_commands.rb +11 -0
  33. data/lib/core/structure/commands/list_contributors.rb +10 -0
  34. data/lib/core/structure/commands/list_entities.rb +3 -0
  35. data/lib/core/structure/commands/list_plugins.rb +3 -0
  36. data/lib/core/structure/commands/register_contributor.rb +14 -0
  37. data/lib/core/structure/structure.plugin +4 -0
  38. data/lib/vop/objects/chain.rb +25 -0
  39. data/lib/vop/objects/command.rb +86 -0
  40. data/lib/vop/objects/command_param.rb +39 -0
  41. data/lib/vop/objects/entities.rb +21 -0
  42. data/lib/vop/objects/entity.rb +75 -0
  43. data/lib/vop/objects/entity_definition.rb +33 -0
  44. data/lib/vop/objects/filter.rb +48 -0
  45. data/lib/vop/objects/plugin.rb +208 -0
  46. data/lib/vop/objects/request.rb +73 -0
  47. data/lib/vop/objects/response.rb +17 -0
  48. data/lib/vop/objects/thing_with_params.rb +17 -0
  49. data/lib/vop/{command_loader.rb → parts/command_loader.rb} +8 -12
  50. data/lib/vop/parts/dependency_resolver.rb +56 -0
  51. data/lib/vop/parts/entity_loader.rb +46 -0
  52. data/lib/vop/parts/executor.rb +155 -0
  53. data/lib/vop/parts/filter_loader.rb +41 -0
  54. data/lib/vop/parts/plugin_finder.rb +46 -0
  55. data/lib/vop/parts/plugin_loader.rb +72 -0
  56. data/lib/vop/shell/shell.rb +221 -0
  57. data/lib/vop/shell/shell_formatter.rb +110 -0
  58. data/lib/vop/shell/shell_input.rb +14 -0
  59. data/lib/vop/shell/shell_input_readline.rb +20 -0
  60. data/lib/vop/shell/shell_input_testable.rb +27 -0
  61. data/lib/vop/syntax/command_syntax.rb +90 -0
  62. data/lib/vop/syntax/entity_syntax.rb +35 -0
  63. data/lib/vop/syntax/filter_syntax.rb +11 -0
  64. data/lib/vop/syntax/plugin_syntax.rb +55 -0
  65. data/lib/vop/util/errors.rb +45 -0
  66. data/lib/vop/util/pluralizer.rb +26 -0
  67. data/lib/vop/util/worker.rb +24 -0
  68. data/lib/vop/version.rb +1 -1
  69. data/lib/vop/vop.rb +216 -0
  70. data/lib/vop.rb +16 -229
  71. data/vop.gemspec +18 -15
  72. metadata +95 -63
  73. data/bin/vop.rb +0 -28
  74. data/lib/vop/command.rb +0 -168
  75. data/lib/vop/entity.rb +0 -61
  76. data/lib/vop/loader.rb +0 -35
  77. data/lib/vop/plugin.rb +0 -141
  78. data/lib/vop/plugin_loader.rb +0 -88
  79. data/lib/vop/plugins/core/commands/collect_contributions.rb +0 -31
  80. data/lib/vop/plugins/core/commands/edit.rb +0 -12
  81. data/lib/vop/plugins/core/commands/help.rb +0 -38
  82. data/lib/vop/plugins/core/commands/identity.rb +0 -4
  83. data/lib/vop/plugins/core/commands/list_contributors.rb +0 -8
  84. data/lib/vop/plugins/core/commands/list_entities.rb +0 -3
  85. data/lib/vop/plugins/core/commands/pry.rb +0 -9
  86. data/lib/vop/plugins/core/commands/reset.rb +0 -5
  87. data/lib/vop/plugins/core/commands/source.rb +0 -5
  88. data/lib/vop/plugins/core/commands/system_call.rb +0 -5
  89. data/lib/vop/plugins/core/core.plugin +0 -4
  90. data/lib/vop/plugins/core/helpers/command_loader/command_syntax.rb +0 -45
  91. data/lib/vop/plugins/core/helpers/command_loader/contributions.rb +0 -28
  92. data/lib/vop/plugins/core/helpers/command_loader/entities.rb +0 -57
  93. data/lib/vop/plugins/core/helpers/helper.rb +0 -3
  94. data/lib/vop/plugins/meta/commands/add_search_path.rb +0 -6
  95. data/lib/vop/plugins/meta/commands/delete_plugin.rb +0 -13
  96. data/lib/vop/plugins/meta/commands/list_commands.rb +0 -17
  97. data/lib/vop/plugins/meta/commands/list_plugins.rb +0 -8
  98. data/lib/vop/plugins/meta/commands/new_command.rb +0 -14
  99. data/lib/vop/plugins/meta/commands/new_plugin.rb +0 -25
  100. data/lib/vop/plugins/meta/commands/show_search_path.rb +0 -3
  101. data/lib/vop/plugins/meta/commands/who_provides.rb +0 -5
  102. data/lib/vop/plugins/meta/meta.plugin +0 -1
  103. data/lib/vop/plugins/ssh/commands/scp.rb +0 -11
  104. data/lib/vop/plugins/ssh/commands/ssh.rb +0 -19
  105. data/lib/vop/plugins/ssh/ssh.plugin +0 -1
  106. data/lib/vop/shell/backend.rb +0 -28
  107. data/lib/vop/shell/base_shell.rb +0 -112
  108. data/lib/vop/shell/formatter.rb +0 -46
  109. data/lib/vop/shell/vop_shell_backend.rb +0 -257
  110. data/lib/vop/shell.rb +0 -52
@@ -0,0 +1,16 @@
1
+ param! "command_name", "command for which a contributor should be disabled"
2
+ param! "contributor", "name of the contributor to disable"
3
+
4
+ run do |plugin, command_name, contributor|
5
+ registry = plugin.state[:contributions] || {}
6
+ unless registry.has_key? command_name
7
+ raise "no contributors found for command #{command_name}"
8
+ end
9
+
10
+ contributors = registry[command_name]
11
+ unless contributors.include? contributor
12
+ raise "no contributor found with name #{contributor} for command #{command_name}"
13
+ end
14
+
15
+ contributors.delete(contributor)
16
+ end
@@ -0,0 +1,52 @@
1
+ description "each entity gets a command called <entities> automagically"
2
+
3
+ run do
4
+ result = []
5
+
6
+ @op.entities.each do |entity_name, definition|
7
+ list_command_name = definition.name.carefully_pluralize
8
+ $logger.debug "generating entity list command #{list_command_name} (#{definition.plugin.name})"
9
+
10
+ plugin = definition.plugin
11
+
12
+ list_command = Command.new(plugin, list_command_name)
13
+ # TODO list_command.read_only = true
14
+
15
+ if definition.on
16
+ list_command.add_param(definition.on.to_s, mandatory: true)
17
+ end
18
+
19
+ list_command.block = lambda do |params, request, context, plugin|
20
+ ex = Executor.new(@op)
21
+ block_param_names = definition.block.parameters.map { |x| x.last }
22
+ payload = ex.prepare_payload(request, context, block_param_names)
23
+
24
+ hash_array = definition.block.call(*payload)
25
+ if hash_array.nil?
26
+ $logger.warn "list block of entity '#{definition.name}' returned nil (?!)"
27
+ else
28
+ unless hash_array.is_a? Array
29
+ raise "unexpected data type : found #{hash_array.class}, expected Array"
30
+ end
31
+ entity_array = []
32
+ unless hash_array.empty?
33
+ first = hash_array.first
34
+ unless first.is_a? Hash
35
+ raise "entity '#{definition.name}' returned unexpected data type : found #{first.class}, expected Hash"
36
+ end
37
+ entity_array = hash_array.map do |row|
38
+ Entity.new(@op, definition.short_name, definition.key, row)
39
+ end
40
+ end
41
+
42
+ # wrap the resulting array of entities to add syntactic sugar
43
+ ::Vop::Entities.new(entity_array)
44
+ end
45
+ end
46
+ result << list_command
47
+ end
48
+
49
+ @op << result
50
+
51
+ result
52
+ end
@@ -0,0 +1,26 @@
1
+ description "all read-only commands get <command>! commands that invalidate automagically"
2
+
3
+ run do
4
+ count = 0
5
+ @op.commands.values.each do |command|
6
+ if command.read_only
7
+ invalidation_command_name = "#{command.short_name}!"
8
+ $logger.debug "generating invalidation command #{invalidation_command_name}"
9
+
10
+ invalidation_command = Command.new(command.plugin, invalidation_command_name)
11
+ invalidation_command.params = command.params
12
+
13
+ invalidation_command.block = lambda do |params|
14
+ @op.invalidate_cache(
15
+ "command" => command.short_name,
16
+ "raw_params" => params
17
+ )
18
+ @op.execute(command.short_name, params)
19
+ end
20
+
21
+ @op << invalidation_command
22
+ count += 1
23
+ end
24
+ end
25
+ count
26
+ end
@@ -0,0 +1,11 @@
1
+ param "plugin_filter", description: "name of a plugin by which commands should be filtered"
2
+
3
+ run do |plugin_filter|
4
+ result = @op.commands.values
5
+
6
+ unless plugin_filter.nil?
7
+ result.delete_if { |command| command.plugin.name != plugin_filter }
8
+ end
9
+
10
+ result.map { |command| command.name }.sort
11
+ end
@@ -0,0 +1,10 @@
1
+ param "command_name", description: "command for which contributors should be displayed"
2
+
3
+ run do |plugin, command_name|
4
+ registry = plugin.state[:contributions] || {}
5
+ if command_name
6
+ registry[command_name]
7
+ else
8
+ registry
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ run do |plugin|
2
+ @op.entities.keys
3
+ end
@@ -0,0 +1,3 @@
1
+ run do |plugin|
2
+ @op.plugins.map { |x| x.name }.sort
3
+ end
@@ -0,0 +1,14 @@
1
+ param! "command_name", description: "the target of the contribution"
2
+ param! "contributor", description: "the command that contributes"
3
+
4
+ run do |command_name, contributor, plugin|
5
+ # TODO verify that +command+ exists - cannot do it here because of
6
+ # 'machines.rails_machines' tries to contribute to unknown command 'machine'
7
+ # unless @op.commands.keys.include? command
8
+ # raise "'#{contributor}' tries to contribute to unknown command '#{command}'"
9
+ # end
10
+
11
+ # TODO initialize in init_hook (not here and in list_contributors)
12
+ registry = plugin.state[:contributions] ||= Hash.new { |h,k| h[k] = [] }
13
+ registry[command_name] << contributor
14
+ end
@@ -0,0 +1,4 @@
1
+ hook :loading_finished do
2
+ @op.generate_entity_commands
3
+ @op.generate_invalidation_commands
4
+ end
@@ -0,0 +1,25 @@
1
+ module Vop
2
+
3
+ class Chain
4
+
5
+ attr_reader :links
6
+
7
+ def initialize(op, links)
8
+ @op = op
9
+ @links = links
10
+ end
11
+
12
+ def next
13
+ @links.shift
14
+ end
15
+
16
+ def execute(request)
17
+ next_link = self.next
18
+ response = nil
19
+ response = next_link.execute(request) if next_link
20
+ response
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,86 @@
1
+ require_relative "command_param"
2
+
3
+ module Vop
4
+
5
+ class Command
6
+
7
+ attr_accessor :plugin
8
+ attr_accessor :name
9
+
10
+ attr_accessor :block
11
+ attr_accessor :params
12
+ attr_accessor :description
13
+
14
+ attr_accessor :show_options
15
+ attr_accessor :dont_register
16
+ attr_accessor :read_only
17
+ attr_accessor :allows_extra
18
+
19
+ def initialize(plugin, name)
20
+ @plugin = plugin
21
+ @name = name
22
+ @description = nil
23
+
24
+ @block = lambda { |params| $logger.warn "#{name} not yet implemented!" }
25
+
26
+ @params = []
27
+ @show_options = {}
28
+
29
+ @dont_register = false
30
+ @read_only = false
31
+ @allows_extra = false
32
+ end
33
+
34
+ def short_name
35
+ @name.split(".").last
36
+ end
37
+
38
+ def source
39
+ plugin.sources[:commands][name]
40
+ end
41
+
42
+ def param(name)
43
+ @params.select { |x| x.name == name }.first
44
+ end
45
+
46
+ def add_param(name, options = {})
47
+ @params << CommandParam.new(name, options)
48
+ end
49
+
50
+ def params_with(&filter)
51
+ params.select do |param|
52
+ filter.call(param)
53
+ end
54
+ end
55
+
56
+ def mandatory_params
57
+ params_with { |x| x.options[:mandatory] == true }
58
+ end
59
+
60
+ # The default param is the one used when a command is called with a single "scalar" param only, like
61
+ # @op.foo("zaphod")
62
+ # If a parameter is marked as default, it will be assigned the value "zaphod" in this case.
63
+ # If there is only a single param, it is the default param by default
64
+ # Also, if there is only one mandatory param, it is considered to be the default param
65
+ def default_param
66
+ if params.size == 1
67
+ params.first
68
+ else
69
+ result = params_with { |x| x.options[:default_param] == true }.first
70
+ if result.nil?
71
+ mandatory = mandatory_params
72
+ if mandatory_params.size == 1
73
+ result = mandatory.first
74
+ end
75
+ end
76
+ result
77
+ end
78
+ end
79
+
80
+ def execute(payload)
81
+ self.block.call(*payload)
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,39 @@
1
+ module Vop
2
+
3
+ class CommandParam
4
+
5
+ attr_reader :name, :options
6
+
7
+ def initialize(name, options = {})
8
+ @name = name
9
+
10
+ unless options.is_a? Hash
11
+ raise "[CommandParam] sanity check failed: unexpected options object class #{options.class}, expected Hash"
12
+ end
13
+
14
+ # auto-detect boolean parameters
15
+ if options.has_key? :default
16
+ if options[:default] == true || options[:default] == false
17
+ options[:boolean] = true
18
+ end
19
+ end
20
+
21
+ defaults = {
22
+ multi: false,
23
+ mandatory: false,
24
+ default_param: false
25
+ }
26
+ @options = defaults.merge(options)
27
+ end
28
+
29
+ # some params do not want to prefilled from the context
30
+ def wants_context
31
+ !(
32
+ options.has_key?(:use_context) &&
33
+ options[:use_context] == false
34
+ )
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,21 @@
1
+ module Vop
2
+
3
+ class Entities < Array
4
+
5
+ def [](key)
6
+ # if key.is_a? Numeric
7
+ # super(key)
8
+ # else
9
+ $logger.debug "accessing entity with key '#{key}'"
10
+ found = select { |x| x.id == key }.first
11
+ if found
12
+ found
13
+ else
14
+ raise "no element with key '#{key}'"
15
+ end
16
+ # end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,75 @@
1
+ module Vop
2
+
3
+ class Entity
4
+
5
+ attr_reader :type, :data, :key
6
+
7
+ def initialize(op, type, key, data)
8
+ @op = op
9
+ @type = type
10
+ @key = key
11
+ @data = data
12
+
13
+ unless @data.has_key? @key
14
+ raise "key #{key} not found in data : #{data.keys.sort}"
15
+ end
16
+
17
+ make_methods_for_commands
18
+ make_method_for_id
19
+ end
20
+
21
+ def id
22
+ @data[@key]
23
+ end
24
+
25
+ def [](key)
26
+ @data[key]
27
+ end
28
+
29
+ def plugin
30
+ if @data.has_key? "plugin_name"
31
+ @op.plugin(@data["plugin_name"])
32
+ end
33
+ end
34
+
35
+ # all commands that have a parameter with the same name as the entity
36
+ # are considered eligible for this entity (TODO that's too broad, isn't it?)
37
+ def entity_commands
38
+ result = @op.commands.values.select do |command|
39
+ command.params.select do |param|
40
+ param.name == @type
41
+ end.count > 0
42
+ end
43
+ @command_count = result.count
44
+ result
45
+ end
46
+
47
+ def make_methods_for_commands
48
+ entity_commands.each do |command|
49
+ # TODO this is very similar to code in Vop.<<
50
+ self.class.send(:define_method, command.short_name) do |*args, &block|
51
+ $logger.debug "[#{@type}:#{id}] #{command.short_name} (#{args.pretty_inspect}, block? #{block_given?})"
52
+ ruby_args = args.length > 0 ? args[0] : {}
53
+ # TODO we might want to do this only if there's a block param defined
54
+ # TODO this does not work if *args comes with a scalar default param
55
+ if block
56
+ ruby_args["block"] = block
57
+ end
58
+ @op.execute(command.short_name, ruby_args, { @type.to_s => id })
59
+ end
60
+ end
61
+ end
62
+
63
+ def make_method_for_id
64
+ self.class.send(:define_method, @key) do |*args|
65
+ id
66
+ end
67
+ end
68
+
69
+ def to_s
70
+ "Vop::Entity (#{@type})"
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,33 @@
1
+ module Vop
2
+
3
+ class EntityDefinition
4
+
5
+ attr_reader :plugin, :name
6
+ attr_accessor :key
7
+ attr_accessor :block
8
+ attr_accessor :on
9
+ attr_accessor :show_options
10
+
11
+ def initialize(plugin, name)
12
+ @plugin = plugin
13
+ @name = name
14
+ @key = "name"
15
+ @data = {}
16
+
17
+ @block = lambda { |params| $logger.warn "entity #{name} does not have a run block" }
18
+
19
+ @on = nil
20
+ @show_options = {}
21
+ end
22
+
23
+ def short_name
24
+ @name.split(".").last
25
+ end
26
+
27
+ def source
28
+ plugin.sources[:entities][name]
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,48 @@
1
+ module Vop
2
+
3
+ class Filter
4
+
5
+ attr_reader :name, :plugin
6
+
7
+ attr_accessor :description
8
+ attr_accessor :block
9
+
10
+ def initialize(plugin, name)
11
+ @plugin = plugin
12
+ @name = name
13
+ end
14
+
15
+ def short_name
16
+ @name.split(".").last
17
+ end
18
+
19
+ def execute(request)
20
+ # this executor is just to prepare payload
21
+ ex = Executor.new(@plugin.op)
22
+ context = {}
23
+ block_param_names = self.block.parameters.map { |x| x.last }
24
+ payload = ex.prepare_payload(request, context, block_param_names)
25
+
26
+ response = nil
27
+ begin
28
+ response = self.block.call(*payload)
29
+ rescue InterruptChain => ic
30
+ response = ic.response
31
+ end
32
+
33
+ response
34
+ end
35
+
36
+ end
37
+
38
+ class InterruptChain < Exception
39
+
40
+ attr_reader :response
41
+
42
+ def initialize(response)
43
+ @response = response
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,208 @@
1
+ require "json"
2
+ require_relative "../parts/entity_loader"
3
+ require_relative "../parts/command_loader"
4
+ require_relative "../parts/filter_loader"
5
+ require_relative "thing_with_params"
6
+
7
+ module Vop
8
+
9
+ class Plugin < ThingWithParams
10
+
11
+ attr_reader :op
12
+ attr_reader :name
13
+ attr_accessor :description
14
+ attr_reader :options
15
+ attr_reader :commands
16
+
17
+ attr_reader :sources
18
+ attr_reader :state
19
+ attr_reader :config
20
+ attr_accessor :dependencies
21
+
22
+ def initialize(op, plugin_name, plugin_path, options = {})
23
+ super()
24
+
25
+ @op = op
26
+ @name = plugin_name
27
+ @path = plugin_path
28
+
29
+ defaults = {
30
+ auto_load: true
31
+ }
32
+ @options = defaults.merge(options)
33
+
34
+ @description = nil
35
+
36
+ @state = {}
37
+
38
+ @config_file_name = File.join(op.plugin_config_path, plugin_name + ".json")
39
+ @config = {}
40
+
41
+ @dependencies = []
42
+
43
+ @hooks = {}
44
+ end
45
+
46
+ def to_s
47
+ "Vop::Plugin #{name}"
48
+ end
49
+
50
+ def init
51
+ $logger.debug "plugin init : #{@name}"
52
+
53
+ @sources = Hash.new { |h, k| h[k] = {} }
54
+
55
+ @config = {}
56
+
57
+ # call_hook :preload ?
58
+ load_helpers
59
+ load_default_config
60
+ load_config
61
+
62
+ # TODO proceed only if auto_load
63
+ call_hook :init
64
+ load_entities
65
+ load_commands
66
+ load_filters
67
+
68
+ #@op.call_global_hook :plugin_loaded, self
69
+ end
70
+
71
+ def plugin_dir(name)
72
+ File.join(@path, name.to_s)
73
+ end
74
+
75
+ def load_default_config
76
+ params.each do |param|
77
+ if param.options.has_key?(:default)
78
+ @config[param.name] = param.options[:default]
79
+ end
80
+ end
81
+ end
82
+
83
+ def load_config
84
+ $logger.debug "looking for config at #{@config_file_name}"
85
+ if File.exists? @config_file_name
86
+ raw = nil
87
+ begin
88
+ raw = IO.read(@config_file_name)
89
+ config_from_file = JSON.parse(raw)
90
+ @config.merge! config_from_file
91
+ $logger.debug "plugin config loaded from #{@config_file_name}"
92
+ rescue => e
93
+ $logger.error "could not read JSON config from #{@config_file_name} (#{e.message}), ignoring:\n#{raw}"
94
+ end
95
+ end
96
+ end
97
+
98
+ def write_config
99
+ $logger.info "writing config into #{@op.plugin_config_path}"
100
+ unless Dir.exists?(@op.plugin_config_path)
101
+ FileUtils.mkdir_p @op.plugin_config_path
102
+ end
103
+ File.open(@config_file_name, "w") do |file|
104
+ file.write @config.to_json()
105
+ end
106
+ end
107
+
108
+ def load_code_from_dir(type_name)
109
+ dir = plugin_dir(type_name)
110
+
111
+ if File.exists?(dir)
112
+ Dir.glob(File.join(dir, "*.rb")).each do |file_name|
113
+ name_from_file = /#{dir}\/(.+).rb$/.match(file_name).captures.first
114
+ full_name = [@name, name_from_file].join(".")
115
+ $logger.debug(" #{type_name} << #{full_name}")
116
+
117
+ @sources[type_name][full_name] = {
118
+ :file_name => file_name,
119
+ :code => File.read(file_name)
120
+ }
121
+ end
122
+ end
123
+ end
124
+
125
+ def load_entities
126
+ loader = EntityLoader.new(self)
127
+
128
+ load_code_from_dir :entities
129
+ @entities = loader.read_sources @sources[:entities]
130
+ @op << @entities unless @entities.empty?
131
+ end
132
+
133
+ def load_commands
134
+ loader = CommandLoader.new(self)
135
+
136
+ load_code_from_dir :commands
137
+ @commands = loader.read_sources @sources[:commands]
138
+ @op << @commands unless @commands.empty?
139
+ end
140
+
141
+ def load_filters
142
+ loader = FilterLoader.new(self)
143
+
144
+ load_code_from_dir :filters
145
+ @filters = loader.read_sources @sources[:filters]
146
+ @op << @filters unless @filters.empty?
147
+ end
148
+
149
+ def load_helpers
150
+ #load_code_from_dir :helpers
151
+ load_code_from_dir("helpers") # TODO unify (symbol vs. string) with load_commands above
152
+ end
153
+
154
+ def inject_helpers(target, sub_type_name = nil)
155
+ type_name = 'helpers'
156
+
157
+ plugins_to_load_helpers_from = [ self ]
158
+
159
+ self.dependencies.each do |name|
160
+ other = @op.plugin(name)
161
+ raise "can not resolve plugin dependency #{name}" unless other
162
+ plugins_to_load_helpers_from << other
163
+ end
164
+
165
+ plugins_to_load_helpers_from.each do |other_plugin|
166
+ helper_sources = other_plugin.sources[type_name]
167
+
168
+ next if helper_sources.size == 0
169
+
170
+ helper_module = Module.new()
171
+
172
+ helper_sources.each do |name, helper|
173
+ begin
174
+ helper_module.class_eval helper[:code]
175
+ rescue Exception => e
176
+ $stderr.puts("could not read helper #{name} : #{e.message}")
177
+ raise e
178
+ end
179
+ end
180
+
181
+ target.extend helper_module
182
+ end
183
+ end
184
+
185
+ def hook(name, &block)
186
+ @hooks[name.to_sym] = block
187
+ end
188
+
189
+ def call_hook(name, *args)
190
+ result = nil
191
+ if @hooks.has_key? name
192
+ result = @hooks[name].call(self, *args)
193
+ end
194
+ result
195
+ end
196
+
197
+ def template_path(name)
198
+ name += ".erb" unless name.end_with? ".erb"
199
+ File.join(plugin_dir(:templates), name)
200
+ end
201
+
202
+ def template(name)
203
+ @op.read_template(template_path(name))
204
+ end
205
+
206
+ end
207
+
208
+ end