|
Revision 6580, 2.1 kB
(checked in by cho45, 5 years ago)
|
|
lang/ruby/chokan/branches/citrus:
chokan と同じようにリロードできるようにした。
スペックをいろいろ追加
|
-
Property svn:executable set to
*
|
| Line | |
|---|
| 1 | #!/usr/bin/env ruby |
|---|
| 2 | |
|---|
| 3 | require "pathname" |
|---|
| 4 | |
|---|
| 5 | module Citrus |
|---|
| 6 | class Plugins |
|---|
| 7 | class PluginsError < StandardError; end |
|---|
| 8 | class UnknownPlugin < PluginsError; end |
|---|
| 9 | |
|---|
| 10 | def initialize(path) |
|---|
| 11 | @path = Pathname.new(path) |
|---|
| 12 | @instances = {} |
|---|
| 13 | update |
|---|
| 14 | end |
|---|
| 15 | |
|---|
| 16 | def plugin_names |
|---|
| 17 | @plugins.keys |
|---|
| 18 | end |
|---|
| 19 | |
|---|
| 20 | def loaded_plugin_names |
|---|
| 21 | @instances.keys |
|---|
| 22 | end |
|---|
| 23 | |
|---|
| 24 | def loaded_plugins |
|---|
| 25 | @instances |
|---|
| 26 | end |
|---|
| 27 | |
|---|
| 28 | def [](key) |
|---|
| 29 | @instances[key] |
|---|
| 30 | end |
|---|
| 31 | |
|---|
| 32 | def each(&block) |
|---|
| 33 | @instances.each(&block) |
|---|
| 34 | end |
|---|
| 35 | |
|---|
| 36 | def load(class_name, *args) |
|---|
| 37 | raise UnknownPlugin, "UnknownPlugin: #{class_name}" unless @plugins.key?(class_name) |
|---|
| 38 | |
|---|
| 39 | info = @plugins[class_name] |
|---|
| 40 | @instances[class_name] = info[:class].new(*args) |
|---|
| 41 | @instances[class_name].on_load if @instances[class_name].respond_to? :on_load |
|---|
| 42 | |
|---|
| 43 | @instances[class_name] |
|---|
| 44 | end |
|---|
| 45 | |
|---|
| 46 | def unload(class_name) |
|---|
| 47 | raise UnknownPlugin, "UnknownPlugin: #{class_name}" unless @plugins.key?(class_name) |
|---|
| 48 | @instances[class_name].on_unload if @instances[class_name].respond_to? :on_unload |
|---|
| 49 | |
|---|
| 50 | @instances.delete class_name |
|---|
| 51 | end |
|---|
| 52 | |
|---|
| 53 | def reload(class_name, *args) |
|---|
| 54 | if class_name == :all |
|---|
| 55 | ret = {} |
|---|
| 56 | plugins = search(@path) |
|---|
| 57 | plugins.each do |k, v| |
|---|
| 58 | if @instances.key?(k) |
|---|
| 59 | # Re-instanciate |
|---|
| 60 | if @plugins[k][:time] < v[:time] |
|---|
| 61 | @plugins[k] = v |
|---|
| 62 | self.unload(k) |
|---|
| 63 | ret[k] = self.load(k, *args) |
|---|
| 64 | end |
|---|
| 65 | end |
|---|
| 66 | end |
|---|
| 67 | ret |
|---|
| 68 | else |
|---|
| 69 | plugins = search(@path) |
|---|
| 70 | raise UnknownPlugin, "UnknownPlugin: #{class_name}" unless plugins.key?(class_name) |
|---|
| 71 | file = plugins[class_name][:file] |
|---|
| 72 | @plugins.update load_file(file) |
|---|
| 73 | self.unload(class_name) |
|---|
| 74 | self.load(class_name, *args) |
|---|
| 75 | end |
|---|
| 76 | end |
|---|
| 77 | |
|---|
| 78 | def update |
|---|
| 79 | @plugins = search(@path) |
|---|
| 80 | end |
|---|
| 81 | |
|---|
| 82 | protected |
|---|
| 83 | def search(path) |
|---|
| 84 | class_table = {} |
|---|
| 85 | |
|---|
| 86 | Pathname.glob("#{path}/*.rb") do |f| |
|---|
| 87 | class_table.update(load_file(f)) |
|---|
| 88 | end |
|---|
| 89 | |
|---|
| 90 | class_table |
|---|
| 91 | end |
|---|
| 92 | |
|---|
| 93 | def load_file(f) |
|---|
| 94 | ret = {} |
|---|
| 95 | m = Module.new |
|---|
| 96 | m.module_eval(f.read) |
|---|
| 97 | m.constants.each do |name| |
|---|
| 98 | const = m.const_get(name) |
|---|
| 99 | if const.is_a? Class |
|---|
| 100 | ret[name] = { |
|---|
| 101 | :class => const, |
|---|
| 102 | :file => f, |
|---|
| 103 | :time => f.mtime, |
|---|
| 104 | } |
|---|
| 105 | end |
|---|
| 106 | end |
|---|
| 107 | ret |
|---|
| 108 | end |
|---|
| 109 | end |
|---|
| 110 | end |
|---|
| 111 | |
|---|