]> git.cworth.org Git - sup/commitdiff
Merge branch 'hook-local-vars'
authorWilliam Morgan <wmorgan-sup@masanjin.net>
Tue, 8 Sep 2009 19:24:34 +0000 (15:24 -0400)
committerWilliam Morgan <wmorgan-sup@masanjin.net>
Tue, 8 Sep 2009 19:24:34 +0000 (15:24 -0400)
1  2 
lib/sup/hook.rb

diff --combined lib/sup/hook.rb
index 0c411626c43d1ad31e94493860f919b2ebf631e5,8a51cfebc14396d4dcd3c0f9cd1af1669479911f..2d6533d3b0c4eb85c46d12b262305d431bd3b3da
@@@ -1,33 -1,11 +1,11 @@@
  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 = {}
-     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
+       @__cache = {}
      end
  
      def say s
@@@ -40,7 -18,7 +18,7 @@@
      end
  
      def log s
 -      Redwood::log "hook[#@__name]: #{s}"
 +      info "hook[#@__name]: #{s}"
      end
  
      def ask_yes_or_no q
        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
  
@@@ -79,6 -69,8 +69,6 @@@
      @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
  
@@@ -127,15 -117,14 +115,14 @@@ privat
  
    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
+           log "read '#{name}' from #{fn_for(name)}"
          end
+       rescue SystemCallError => e
+         #log "disabled hook for '#{name}': #{e.message}"
+         nil
+       end
      end
  
      @hooks[name]
    end
  
    def log m
 -    Redwood::log("hook: " + m)
 +    info("hook: " + m)
    end
  end