Ok, I've now done a bit more investigation and now understand what
Haml is doing under the covers.

The reason why my hack manipulating the tabulation didn't work is
because of the way templates are nested in Rails with Haml.

Basically, let's say you suppress the tabulation in your "show"
template using the hack shown above. I've found that it's only
necessary to set @real_tabs to 0, as in the end what's going to get
called is push_script() and that only cares about @real_tabs, not
@tabulation.

But what happens next is that your application layout gets rendered,
and inside it is a yield call that gets the output of the precompiled
"show" template. This means that the output goes through push_script()
a second time and you get unwanted indentation again.

This is a tricky issue: you need some way for nested templates to
communicate upwards to the templates that enclose them, and advise
them not to meddle with the tabulation.

I've got a new hack that works, but it is terribly ugly. Here it is:

Here's a snippet of my "show" template:

  -preserving do
    [EMAIL PROTECTED]

And here's the updated preserving helper:

  def preserving &block
    real_tabs = buffer.instance_variable_get :@real_tabs
    buffer.instance_variable_set :@real_tabs, 0
    buffer.buffer << "<!-- Haml: start pre -->\n"
    yield
    buffer.buffer << "<!-- Haml: end pre -->\n"
    buffer.instance_variable_set :@real_tabs, real_tabs
  end

Notice how it not only suppresses indentation; it is also inserting
HTML comments into the buffer which will be visible to any higher-
level template which encloses it.

And finally, here is the patch to the push_script method that scans
for these HTML comments and acts accordingly:

diff --git a/vendor/plugins/haml/lib/haml/buffer.rb b/vendor/plugins/
haml/lib/haml/buffer.rb
index 4bdac1d..5e8638c 100644
--- a/vendor/plugins/haml/lib/haml/buffer.rb
+++ b/vendor/plugins/haml/lib/haml/buffer.rb
@@ -78,8 +78,22 @@ module Haml
           @buffer << "\n"
         end

-        result = result.gsub(/^/m, tabs(tabulation))
-        @buffer << "#{result}\n"
+        tab = tabs(tabulation)
+        pre = false
+        result.each do |line|
+          case line
+          when /<!-- Haml: start pre -->/
+            pre = true
+          when /<!-- Haml: end pre -->/
+            pre = false
+          else
+            if pre
+              @buffer << "#{line}"
+            else
+              @buffer << "#{tab}#{line}"
+            end
+          end
+        end

         if close_tag
           @buffer << "#{tabs(tabulation-1)}</#{close_tag}>\n"

Yes, it is a horrible hack, and probably quite slow, but it works. I'd
still like to find a more elegant solution though. I can't think of a
way to communicate this stuff back up into enclosing templates without
embedding some kind of marker like that in the text.

And on a side note, a minor bug found while inspect the code in that
file:

diff --git a/vendor/plugins/haml/lib/haml/buffer.rb b/vendor/plugins/
haml/lib/haml/buffer.rb
index 4bdac1d..5e8638c 100644
--- a/vendor/plugins/haml/lib/haml/buffer.rb
+++ b/vendor/plugins/haml/lib/haml/buffer.rb
@@ -152,7 +166,7 @@ module Haml
     # Gets <tt>count</tt> tabs. Mostly for internal use.
     def tabs(count)
       tabs = count + @tabulation
-      '  ' * tabs
+      '  ' * tabs # BUG: <-- this line has no effect
       @@tab_cache[tabs] ||= '  ' * tabs
     end

Note how the second line has no side effects so is really just wasting
time. It effectively renders the optimization that that method tries
to implement (avoiding the recalculation of the tab text) ineffective,
because it recalculates it anyway and just throws it away.

Cheers,
Wincent


--~--~---------~--~----~------------~-------~--~----~
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