lib/sup/hook.rb in sup-0.8.1 vs lib/sup/hook.rb in sup-0.9

- old
+ new

@@ -1,48 +1,26 @@ module Redwood class HookManager - ## there's probably a better way to do this, but to evaluate a hook - ## with a bunch of pre-set "local variables" i define a function - ## per variable and then instance_evaluate the code. - ## - ## how does rails do it, when you pass :locals into a partial? - ## - ## i don't bother providing setters, since i'm pretty sure the - ## charade will fall apart pretty quickly with respect to scoping. - ## "fail-fast", we'll call it. class HookContext def initialize name @__say_id = nil @__name = name - @__locals = {} + @__cache = {} end - attr_writer :__locals - - def method_missing m, *a - case @__locals[m] - when Proc - @__locals[m] = @__locals[m].call(*a) # only call the proc once - when nil - super - else - @__locals[m] - end - end - def say s if BufferManager.instantiated? @__say_id = BufferManager.say s, @__say_id BufferManager.draw_screen else log s end end def log s - Redwood::log "hook[#@__name]: #{s}" + info "hook[#@__name]: #{s}" end def ask_yes_or_no q if BufferManager.instantiated? BufferManager.ask_yes_or_no q @@ -58,16 +36,28 @@ def set tag, value HookManager.tags[tag] = value end - def __binding - binding - end - - def __cleanup + def __run __hook, __filename, __locals + __binding = binding + __lprocs, __lvars = __locals.partition { |k, v| v.is_a?(Proc) } + eval __lvars.map { |k, v| "#{k} = __locals[#{k.inspect}];" }.join, __binding + ## we also support closures for delays evaluation. unfortunately + ## we have to do this via method calls, so you don't get all the + ## semantics of a regular variable. not ideal. + __lprocs.each do |k, v| + self.class.instance_eval do + define_method k do + @__cache[k] ||= v.call + end + end + end + ret = eval __hook, __binding, __filename BufferManager.clear @__say_id if @__say_id + @__cache = {} + ret end end include Singleton @@ -77,31 +67,27 @@ @descs = {} @contexts = {} @tags = {} Dir.mkdir dir unless File.exists? dir - - self.class.i_am_the_instance self end attr_reader :tags def run name, locals={} hook = hook_for(name) or return context = @contexts[hook] ||= HookContext.new(name) - context.__locals = locals result = nil begin - result = context.instance_eval @hooks[name], fn_for(name) + result = context.__run hook, fn_for(name), locals rescue Exception => e log "error running hook: #{e.message}" log e.backtrace.join("\n") @hooks[name] = nil # disable it BufferManager.flash "Error running hook: #{e.message}" if BufferManager.instantiated? end - context.__cleanup result end def register name, desc @descs[name] = desc @@ -123,33 +109,34 @@ end end def enabled? name; !hook_for(name).nil? end + def clear; @hooks.clear; end + private def hook_for name unless @hooks.member? name - @hooks[name] = - begin - returning IO.read(fn_for(name)) do - log "read '#{name}' from #{fn_for(name)}" - end - rescue SystemCallError => e - #log "disabled hook for '#{name}': #{e.message}" - nil + @hooks[name] = begin + returning IO.read(fn_for(name)) do + debug "read '#{name}' from #{fn_for(name)}" end + rescue SystemCallError => e + #debug "disabled hook for '#{name}': #{e.message}" + nil + end end @hooks[name] end def fn_for name File.join @dir, "#{name}.rb" end def log m - Redwood::log("hook: " + m) + info("hook: " + m) end end end