]> git.cworth.org Git - sup/blob - lib/sup/hook.rb
turn off hook disable log message
[sup] / lib / sup / hook.rb
1 module Redwood
2
3 class HookManager
4   ## there's probably a better way to do this, but to evaluate a hook
5   ## with a bunch of pre-set "local variables" i define a function
6   ## per variable and then instance_evaluate the code.
7   ##
8   ## how does rails do it, when you pass :locals into a partial?
9   ##
10   ## i don't bother providing setters, since i'm pretty sure the
11   ## charade will fall apart pretty quickly with respect to scoping.
12   ## this is basically fail-fast.
13   class HookContext
14     def initialize name
15       @__name = name
16       @__locals = {}
17     end
18
19     attr_writer :__locals
20
21     def method_missing m, *a
22       case @__locals[m]
23       when Proc
24         @__locals[m].call(*a)
25       when nil
26         super
27       else
28         @__locals[m]
29       end
30     end
31
32     def say s
33       @__say_id = BufferManager.say s, @__say_id
34       BufferManager.draw_screen
35     end
36
37     def log s
38       Redwood::log "hook[#@__name]: #{s}"
39     end
40
41     def ask_yes_or_no q
42       BufferManager.ask_yes_or_no q
43     end
44
45     def __binding 
46       binding
47     end
48
49     def __cleanup
50       BufferManager.clear @__say_id if @__say_id
51     end
52   end
53
54   include Singleton
55
56   def initialize dir
57     @dir = dir
58     @hooks = {}
59     @descs = {}
60     @contexts = {}
61     
62     Dir.mkdir dir unless File.exists? dir
63
64     self.class.i_am_the_instance self
65   end
66
67   def run name, locals={}
68     hook = hook_for(name) or return
69     context = @contexts[hook] ||= HookContext.new(name)
70     context.__locals = locals
71
72     result = nil
73     begin
74       result = context.instance_eval @hooks[name], fn_for(name)
75     rescue Exception => e
76       log "error running hook: #{e.message}"
77       log e.backtrace.join("\n")
78       BufferManager.flash "Error running hook: #{e.message}"
79     end
80     context.__cleanup
81     result
82   end
83
84   def register name, desc
85     @descs[name] = desc
86   end
87
88   def print_hooks f=$stdout
89 puts <<EOS
90 Have #{@descs.size} registered hooks:
91
92 EOS
93
94     @descs.sort.each do |name, desc|
95       f.puts <<EOS
96 #{name}
97 #{"-" * name.length}
98 File: #{fn_for name}
99 #{desc}
100 EOS
101     end
102   end
103
104 private
105
106   def hook_for name
107     unless @hooks.member? name
108       @hooks[name] =
109         begin
110           returning IO.readlines(fn_for(name)).join do
111             log "read '#{name}' from #{fn_for(name)}"
112           end
113         rescue SystemCallError => e
114           #log "disabled hook for '#{name}': #{e.message}"
115           nil
116         end
117     end
118
119     @hooks[name]
120   end
121
122   def fn_for name
123     File.join @dir, "#{name}.rb"
124   end
125
126   def log m
127     Redwood::log("hook: " + m)
128   end
129 end
130
131 end