Index: lib/haml/engine.rb
===================================================================
--- lib/haml/engine.rb  (revision 606)
+++ lib/haml/engine.rb  (working copy)
@@ -1,10 +1,111 @@
 require 'haml/helpers'
 require 'haml/buffer'
+require 'haml/context'
 require 'haml/filters'
 require 'haml/error'
 require 'haml/util'

+# NOTE: SVN's diff won't add new files.  This should go in
'context.rb'.
 module Haml
+  # +Context+ objects are throw-away objects designed to be the
target of
+  # a +Proc+ binding.  They can wrap an arbitrary object, to which
all
+  # undefined messages will be sent.  Typically, +Context+ objects
will have
+  # several singleton methods defined on them.  Additionally, +Context
+
+  # objects capture the output generated within the +Proc+ that is
bound to
+  # them.
+  class Context
+    # Remove any methods that would interfere with relaying messages
to
+    # the wrapped object.
+    instance_methods.each do |name|
+      if !(["__id__", "__send__", "ancestors", "class", "class_eval",
+          "class_variables", "const_defined?", "const_get",
"const_missing",
+          "const_set", "constants", "extend", "freeze", "frozen?",
"id",
+          "include", "include?", "included_modules", "inspect",
+          "instance_eval", "instance_method", "instance_methods",
+          "instance_of?", "instance_variable_get",
"instance_variable_set",
+          "instance_variables", "is_a?", "kind_of?", "local_methods",
+          "method", "method_defined?", "methods", "module_eval",
"new",
+          "object_id", "private_class_method",
"private_instance_methods",
+          "private_method_defined?", "private_methods",
+          "protected_instance_methods", "protected_method_defined?",
+          "protected_methods", "public_class_method",
+          "public_instance_methods", "public_method_defined?",
+          "public_methods", "require", "require_gem", "send",
+          "singleton_methods", "superclass", "taint", "tainted?",
"type",
+          "untaint"].include?(name))
+        undef_method(name)
+      end
+    end
+
+    # Creates a context object, and optionally wraps an arbitrary
object to
+    # which any missing methods will be relayed.
+    def initialize(wrapped_object=nil)
+      @wrapped_object = wrapped_object
+    end
+
+    # An arbitrary object wrapped by the +Context+.  If this is set
to
+    # anything other than +nil+, any missing methods will be relayed
to this
+    # object.
+    attr_reader :wrapped_object
+
+    # Returns the execution context for the Context object.
+    def binding
+      # Kind of a hack to get around the fact that we're overriding
the
+      # private Kernel version of the binding method.
+      return (lambda {}).binding
+    end
+
+    # Returns the +StringIO+ output buffer for whatever output was
generated
+    # within the +Proc+ that was bound to the +Context+ instance.
+    def output_buffer
+      if !defined?(@output_buffer) || @output_buffer == nil
+        require 'stringio'
+        @output_buffer = StringIO.new
+      end
+      return @output_buffer
+    end
+
+    # Output is redirected to the output buffer.
+    def print(*params)
+      self.output_buffer.print(*params)
+    end
+
+    # Output is redirected to the output buffer.
+    def printf(*params)
+      self.output_buffer.printf(*params)
+    end
+
+    # Output is redirected to the output buffer.
+    def puts(*params)
+      self.output_buffer.puts(*params)
+    end
+
+    # Output is redirected to the output buffer.
+    def putc(*params)
+      self.output_buffer.putc(*params)
+    end
+
+    # Output is redirected to the output buffer.
+    def write(*params)
+      self.output_buffer.write(*params)
+    end
+
+    # Relays any missing methods to the wrapped object, or raises an
error if
+    # there is no wrapped object.
+    def method_missing(message, *params, &block)
+      if @wrapped_object != nil
+        return @wrapped_object.send(message, *params, &block)
+      else
+        raise NoMethodError,
+          "undefined method `#{message.to_s}' for " +
+          "#{self.inspect}:#{self.class}"
+      end
+    end
+  end
+end
+
+
+module Haml
   # This is the class where all the parsing and processing of the
Haml
   # template is done. It can be directly used by the user by creating
a
   # new instance and calling <tt>to_html</tt> to render the template.
For example:
@@ -156,7 +257,7 @@

     # Processes the template and returns the result as a string.
     def render(scope = Object.new, &block)
-      @scope_object = scope
+      @scope_object = Haml::Context.new(scope)
       @buffer = Haml::Buffer.new(@options)

       # Run the compiled evaluator function


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Haml" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/haml?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to