]> git.cworth.org Git - sup/blob - lib/sup/hook.rb
hook bugfix: status bar redraw
[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       @__locals[m] || super
23     end
24
25     def say s
26       @__say_id = BufferManager.say s, @__say_id
27       BufferManager.draw_screen
28     end
29
30     def log s
31       Redwood::log "hook[#@__name]: #{s}"
32     end
33
34     def ask_yes_or_no q
35       BufferManager.ask_yes_or_no q
36     end
37
38     def __binding 
39       binding
40     end
41
42     def __cleanup
43       BufferManager.clear @__say_id if @__say_id
44     end
45   end
46
47   include Singleton
48
49   def initialize dir
50     @dir = dir
51     @hooks = {}
52     @descs = {}
53     @contexts = {}
54     
55     Dir.mkdir dir unless File.exists? dir
56
57     self.class.i_am_the_instance self
58   end
59
60   def run name, locals={}
61     hook = hook_for(name) or return
62     context = @contexts[hook] ||= HookContext.new(name)
63     context.__locals = locals
64     
65     begin
66       result = context.instance_eval @hooks[name], fn_for(name)
67       if result.is_a? String
68         log "got return value: #{result.inspect}"
69         BufferManager.flash result 
70       end
71     rescue Exception => e
72       log "error running hook: #{e.message}"
73       log e.backtrace.join("\n")
74       BufferManager.flash "Error running hook: #{e.message}"
75     end
76     context.__cleanup
77   end
78
79   def register name, desc
80     @descs[name] = desc
81   end
82
83   def print_hooks f=$stdout
84 puts <<EOS
85 Have #{@descs.size} registered hooks:
86
87 EOS
88
89     @descs.sort.each do |name, desc|
90       f.puts <<EOS
91 #{name}
92 #{"-" * name.length}
93 File: #{fn_for name}
94 #{desc}
95 EOS
96     end
97   end
98
99 private
100
101   def hook_for name
102     unless @hooks.member? name
103       @hooks[name] =
104         begin
105           returning IO.readlines(fn_for(name)).join do
106             log "read '#{name}' from #{fn_for(name)}"
107           end
108         rescue SystemCallError => e
109           nil
110         end
111     end
112
113     @hooks[name]
114   end
115
116   def fn_for name
117     File.join @dir, "#{name}.rb"
118   end
119
120   def log m
121     Redwood::log("hook: " + m)
122   end
123 end
124
125 end