<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,13 +1,20 @@
-== Textmate Footnotes v3.1
-  * Added MySQL Query Analyzer
-  * Code refactoring (using modules, except backtracer)
-  * Ability to cherry pick notes
-  * Working on Rails 2.1
-
-== Textmate Footnotes v3.0
+TODO:
+  * Use YAML files to load configuration files
+  * Create a profiler tab
+  
+== Footnotes v3.2
 Author: Jos&#233; Valim (jose.valim@gmail.com)
 Site: http://www.pagestacker.com/
-Description:
+  * Added numbers to tabs;
+  * Added Queries note;
+  * Added MySQL Query Analyzer.
+
+== Footnotes v3.1
+  * Code refactoring (using modules, except backtracer);
+  * Ability to cherry pick notes;
+  * Working on Rails 2.1.
+
+== Footnotes v3.0
   * Some code refactoring;
   * Stylesheets bug fixed: was showing not only css in Stylesheets div;
   * Logtail fix: working with Rails 2.0 logger and in all OS, since it's Regexp based;
@@ -17,8 +24,8 @@ Description:
 
 == Textmate Footnotes v2.0
 Copyright (c) 2006 InquiryLabs, Inc.
-Site: http://inquirylabs.com/
 Author: Duane Johnson (duane.johnson@gmail.com)
+Site: http://inquirylabs.com/
 Description:
   Creates clickable footnotes on each rendered page, as well as clickable
   links in the backtrace should an error occur in your Rails app. Links take</diff>
      <filename>CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -33,7 +33,7 @@
 # In Footnotes 3.1, you also have the ability to cherry pick which notes do you
 # want to use, simply doing:
 #
-#   Footnotes::Filter.notes = [:session, :cookies, :params, :filters, :routes, :log, :general]
+#   Footnotes::Filter.notes = [:session, :cookies, :params, :filters, :routes, :queries, :log, :general]
 #
 if (ENV['RAILS_ENV'] == 'development')
   # Windows doesn't have 'uname', so rescue false</diff>
      <filename>init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,49 +1,56 @@
 module Footnotes
   module QueryAnalyzer
-    def self.columnized_row(fields, sized)
-      row = []
-      fields.each_with_index do |f, i|
-        row &lt;&lt; sprintf(&quot;%0-#{sized[i]}s&quot;, f.to_s)
-      end
-      row.join(' | ')
-    end
-
-    def self.columnized(array)
-      sized = {}
-      array.each do |row|
-        row.values.each_with_index do |value, i|
-          sized[i] = [sized[i].to_i, row.keys[i].length, value.to_s.length].max
-        end
-      end
-
+    def self.parse_explain(results)
       table = []
-      table &lt;&lt; columnized_row(array.first.keys, sized)
-      table &lt;&lt; '-' * table.first.length
-      array.each { |row| table &lt;&lt; columnized_row(row.values, sized) }
-      table.join(&quot;\n  &quot;) # Spaces added to work with format_log_entry
+      table &lt;&lt; results.fetch_fields.map(&amp;:name)
+      results.each{|row| table &lt;&lt; row}
+      table
     end
-    
+
     def self.included(base)
       base.class_eval do
-        alias_method :select_without_analyzer, :select
-        alias_method :select, :select_with_analyzer
+        alias_method_chain :execute, :analyzer
       end
     end
 
-    private
-    def select_with_analyzer(sql, name = nil)
-      query_results = select_without_analyzer(sql, name)
+    def execute_with_analyzer(sql, name = nil)
+      query_results = nil
+      time = Benchmark.realtime { query_results = execute_without_analyzer(sql, name) }
+
+      if sql =~ /^(select)|(create)|(update)|(delete)\b/i
+        operation = $&amp;.downcase.to_sym
+        explain = nil
 
-      if @logger &amp;&amp; @logger.level &lt;= Logger::INFO
-        @logger.debug(
-          @logger.silence do
-            &quot;\nAnalyzing #{name}\n  #{Footnotes::QueryAnalyzer.columnized(select_without_analyzer(&quot;explain #{sql}&quot;, name))}\n\n&quot;
+        if adapter_name == 'MySQL' &amp;&amp; operation == :select
+          log_silence do
+            explain = execute_without_analyzer(&quot;explain #{sql}&quot;, name)
           end
-        ) if sql =~ /^select/i
-      end          
+          explain = Footnotes::QueryAnalyzer.parse_explain(explain)
+        end
+        Footnotes::Filter.sql &lt;&lt; [operation, name, time, sql, explain]
+      end
+
       query_results
     end
   end
+
+  module AbstractAdapter
+    def log_silence
+      result = nil
+      if @logger
+        @logger.silence do
+          result = yield
+        end        
+      else
+        result = yield
+      end
+      result
+    end
+  end
 end
 
-ActiveRecord::ConnectionAdapters::MysqlAdapter.send :include, Footnotes::QueryAnalyzer
\ No newline at end of file
+ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Footnotes::AbstractAdapter
+ActiveRecord::ConnectionAdapters.local_constants.each do |adapter|
+  next unless adapter =~ /.*[^Abstract]Adapter$/
+  eval(&quot;ActiveRecord::ConnectionAdapters::#{adapter}&quot;).send :include, Footnotes::QueryAnalyzer
+end
\ No newline at end of file</diff>
      <filename>lib/textmate_analyzer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,17 +2,19 @@ require 'ostruct'
 
 module Footnotes
   class Filter
-    cattr_accessor :no_style, :notes
+    cattr_accessor :no_style, :notes, :sql
 
     self.no_style = false
-    self.notes = [:session, :cookies, :params, :filters, :routes, :log, :general]
+    self.notes = [:session, :cookies, :params, :filters, :routes, :queries, :log, :general]
+    self.sql = []
 
     #
     # Controller methods
     #
     def self.filter(controller)
       filter = Footnotes::Filter.new(controller)
-      filter.add_footnotes!   
+      filter.add_footnotes!
+      filter.reset!
     end
 
     def initialize(controller)
@@ -20,6 +22,7 @@ module Footnotes
       @template = controller.instance_variable_get('@template')
       @body = controller.response.body
       @extra_html = ''
+      @script = ''
     end
 
     def add_footnotes!
@@ -45,28 +48,48 @@ module Footnotes
     def content_type
       @controller.response.headers['Content-Type']
     end
+    
+    def reset!
+      self.sql = []
+    end
 
     #
     # Fieldset methods
     #
     def session_debug_info
-      escape(@controller.session.instance_variable_get(&quot;@data&quot;).inspect)
+      sessions = @controller.session.instance_variable_get(&quot;@data&quot;).symbolize_keys
+      [escape(sessions.inspect), sessions.length]
     end
 
     def cookies_debug_info
-      escape(@controller.send(:cookies).inspect)
+      cookies = @controller.send(:cookies).symbolize_keys
+      [escape(cookies.inspect), cookies.length]
     end
 
     def params_debug_info
-      escape(@controller.params.inspect)
+      params = @controller.params.symbolize_keys
+      [escape(params.inspect), params.length]
     end
 
     def filters_debug_info
-      &quot;&lt;pre&gt;#{mount_table(parsed_filters, :name, :type, :actions)}&lt;/pre&gt;&quot;
+      filters = parsed_filters.unshift([:name, :type, :actions])
+      [&quot;&lt;pre&gt;#{mount_table(filters)}&lt;/pre&gt;&quot;, filters.length]
     end
 
     def routes_debug_info
-      &quot;&lt;pre&gt;#{mount_table(parsed_routes, :path, :name, :options, :requirements)}&lt;/pre&gt;&quot;
+      routes = parsed_routes.unshift([:path, :name, :options, :requirements])
+      [&quot;&lt;pre&gt;#{mount_table(routes)}&lt;/pre&gt;&quot;, routes.length]
+    end
+
+    def queries_debug_info
+      html = ''
+      self.sql.collect do |item|
+        html &lt;&lt; &quot;&lt;b&gt;#{item[0].to_s.upcase}&lt;/b&gt;\n&quot;
+        html &lt;&lt; &quot;#{item[1] || 'SQL'} (#{sprintf('%f',item[2])}s)\n&quot;
+        html &lt;&lt; &quot;#{item[3].gsub(/(\s)+/,' ').gsub('`','')}\n&quot;
+        html &lt;&lt; mount_table(item[4])
+      end
+      [&quot;&lt;pre&gt;#{html}&lt;/pre&gt;&quot;, self.sql.length]
     end
 
     def log_debug_info
@@ -97,17 +120,15 @@ module Footnotes
 
     # Gets a bidimensional array with the labels of the &quot;second&quot; array (columns)
     #
-    def mount_table(array, *args)
-      return '' if args.empty?
-      header = '&lt;tr&gt;&lt;th&gt;' + args.collect{|i| escape(i.to_s.titlecase) }.join('&lt;/th&gt;&lt;th&gt;') + '&lt;/th&gt;&lt;/tr&gt;'
+    def mount_table(array)
+      return '' if array.empty?
+      header = '&lt;tr&gt;&lt;th&gt;' + array.shift.collect{|i| escape(i.to_s.humanize) }.join('&lt;/th&gt;&lt;th&gt;') + '&lt;/th&gt;&lt;/tr&gt;'
       lines = array.collect{|i| &quot;&lt;tr&gt;&lt;td&gt;#{i.join('&lt;/td&gt;&lt;td&gt;')}&lt;/td&gt;&lt;/tr&gt;&quot; }.join
 
       &lt;&lt;-TABLE
       &lt;table&gt;
         &lt;thead&gt;#{header}&lt;/thead&gt;
-        &lt;tbody style=&quot;text-align:left;&quot;&gt;
-          #{lines}
-        &lt;/tbody&gt;
+        &lt;tbody&gt;#{lines}&lt;/tbody&gt;
       &lt;/table&gt;
       TABLE
     end
@@ -158,9 +179,9 @@ module Footnotes
       &lt;div id=&quot;tm_footnotes_debug&quot;&gt;
         #{textmate_links if Footnotes::Filter.textmate_prefix}
         Show:
-        #{footnotes_links}
+        #{footnotes_content}
         #{@extra_html}
-        #{footnotes_fieldsets}
+        &lt;script type=&quot;text/javascript&quot;&gt;function untoogle(){#{@script}}&lt;/script&gt;
       &lt;/div&gt;
       &lt;!-- End Footnotes --&gt;
       HTML
@@ -173,59 +194,76 @@ module Footnotes
       end
     end
 
-    # Defines the title for each fieldset
+    # Generates footnotes script, links and content
     #
-    def footnotes_titles
-      return {
-        :session =&gt; &quot;Session&quot;,
-        :cookies =&gt; &quot;Cookies&quot;,
-        :params =&gt; &quot;Parameters&quot;,
-        :filters =&gt; &quot;Filter chain for #{@controller.class.to_s}&quot;,
-        :routes =&gt; &quot;Routes for #{@controller.class.to_s}&quot;,
-        :log =&gt; &quot;Log&quot;,
-        :general =&gt; &quot;General (id=\&quot;tm_debug\&quot;)&quot;
+    def footnotes_content
+      links = []
+      content = ''
+
+      self.notes.each{ |section|
+        next unless footnotes_info.key?(section)
+
+        # Call the method with the results
+        result, total = eval(&quot;#{section.to_s}_debug_info&quot;)
+        links &lt;&lt; footnote_link(section, total)
+        content &lt;&lt; footnote_fieldset(section, result)
       }
+
+      &quot;#{links.join(&quot; | \n&quot;)}#{content}&quot;
     end
 
-    # Generates links based on specified tabs
+    # Defines the title and link names for each note
     #
-    def footnotes_links
-      self.notes.collect{ |section|
-        next unless footnotes_titles.key?(section)
-        section_name = section.to_s
-        &quot;&lt;a href=\&quot;#\&quot; onclick=\&quot;#{footnotes_toggle(section_name+'_debug_info')};return false\&quot;&gt;#{section_name.titleize}&lt;/a&gt;&quot;
-      }.join(&quot; | \n&quot;)
+    def footnotes_info
+      return {
+        :session =&gt; { :title =&gt; &quot;Session&quot;, :link =&gt; &quot;Session&quot; },
+        :cookies =&gt; { :title =&gt; &quot;Cookies&quot;, :link =&gt; &quot;Cookies (%d)&quot; },
+        :params =&gt; { :title =&gt; &quot;Parameters&quot;, :link =&gt; &quot;Params (%d)&quot; },
+        :filters =&gt; { :title =&gt; &quot;Filter chain for #{@controller.class.to_s}&quot;, :link =&gt; &quot;Filters&quot; },
+        :routes =&gt; { :title =&gt; &quot;Routes for #{@controller.class.to_s}&quot;, :link =&gt; &quot;Routes&quot; },
+        :queries =&gt; { :title =&gt; &quot;Queries&quot;, :link =&gt; &quot;Queries (%d)&quot; },
+        :log =&gt; { :title =&gt; &quot;Log&quot;, :link =&gt; &quot;Log&quot; },
+        :general =&gt; { :title =&gt; &quot;General (id=\&quot;tm_debug\&quot;)&quot;, :link =&gt; &quot;General Debug&quot; },
+        :javascripts =&gt; { :title =&gt; &quot;Javascripts&quot;, :link =&gt; &quot;Javascripts (%d)&quot; },
+        :stylesheets =&gt; { :title =&gt; &quot;Stylesheets&quot;, :link =&gt; &quot;Stylesheets (%d)&quot; }
+      }
     end
 
-    # Generates fieldsets based on specified tabs
+    # Generate script that close notes when another is select
     #
-    def footnotes_fieldsets
-      self.notes.collect{ |section|
-        next unless footnotes_titles.key?(section)
-        section_name = section.to_s
-        &lt;&lt;-HTML
-        &lt;fieldset id=&quot;#{section_name}_debug_info&quot; class=&quot;tm_footnotes_debug_info&quot; style=&quot;display: none&quot;&gt;
-          &lt;legend&gt;#{footnotes_titles[section]}&lt;/legend&gt;
-          &lt;code&gt;#{eval(section_name+'_debug_info')}&lt;/code&gt;
-        &lt;/fieldset&gt;
-        HTML
-      }
+    def footnote_script(section)
+      @script &lt;&lt; &quot;document.getElementById('#{section.to_s}_debug_info').style.display = 'none'\n&quot;
     end
 
-    def footnotes_toggle(id)
-      &quot;s = document.getElementById('#{id}').style; if(s.display == 'none') { s.display = '' } else { s.display = 'none' }&quot;
+    def footnote_link(section, value = 0)
+      footnote_script(section)
+      name = section.to_s
+      &quot;&lt;a href=\&quot;#\&quot; onclick=\&quot;untoogle();document.getElementById('#{name}_debug_info').style.display = 'block';location.href ='##{name}_debug_info';return false;\&quot;&gt;#{(footnotes_info[section][:link] % value).humanize}&lt;/a&gt;&quot;
+    end
+
+    def footnote_fieldset(section, value)
+      name = section.to_s
+      &lt;&lt;-HTML
+      &lt;fieldset id=&quot;#{name}_debug_info&quot; class=&quot;tm_footnotes_debug_info&quot; style=&quot;display: none&quot;&gt;
+        &lt;legend&gt;#{footnotes_info[section][:title]}&lt;/legend&gt;
+        &lt;code&gt;#{value}&lt;/code&gt;
+      &lt;/fieldset&gt;
+      HTML
     end
 
     def insert_styles
       insert_text :before, /&lt;\/head&gt;/i, &lt;&lt;-HTML
       &lt;!-- Footnotes Style --&gt;
       &lt;style type=&quot;text/css&quot;&gt;
-        #tm_footnotes_debug {margin: 2em 0 1em 0; text-align: center; color: #777;}
-        #tm_footnotes_debug a {text-decoration: none; color: #777;}
+        #tm_footnotes_debug {margin: 2em 0 1em 0; text-align: center; color: #444; line-height: 16px;}
+        #tm_footnotes_debug a {text-decoration: none; color: #444;}
         #tm_footnotes_debug pre {overflow: scroll; margin: 0;}
-        #tm_footnotes_debug table td {padding: 0 4px;}
+        #tm_footnotes_debug thead {text-align: center;}
+        #tm_footnotes_debug table td {padding: 0 5px;}
+        #tm_footnotes_debug tbody {text-align: left;}
         #tm_footnotes_debug legend, #tm_footnotes_debug fieldset {background-color: #FFF;}
-        fieldset.tm_footnotes_debug_info {text-align: left; border: 1px dashed #aaa; padding: 0.5em 1em 1em 1em; margin: 1em 2em 1em 2em; color: #777;}
+        #queries_debug_info thead, #queries_debug_info tbody {text-align: center; color:#FF0000;}
+        fieldset.tm_footnotes_debug_info {text-align: left; border: 1px dashed #aaa; padding: 0.5em 1em 1em 1em; margin: 1em 2em 1em 2em; color: #444;}
       &lt;/style&gt;
       &lt;!-- End Footnotes Style --&gt;
       HTML</diff>
      <filename>lib/textmate_footnotes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -75,13 +75,13 @@ module Footnotes
         &lt;a href=&quot;#{view_url}&quot;&gt;View&lt;/a&gt; |
         &lt;a href=&quot;#{layout_url}&quot;&gt;Layout&lt;/a&gt;
       HTML
-      html += asset_file_links('Stylesheets', stylesheet_files) unless stylesheet_files.blank?
-      html += asset_file_links('Javascripts', javascript_files) unless javascript_files.blank?
+      html += asset_file_links(:stylesheets, stylesheet_files) unless stylesheet_files.blank?
+      html += asset_file_links(:javascripts, javascript_files) unless javascript_files.blank?
       html += '&lt;br/&gt;'
       return html
     end
 
-    def asset_file_links(link_text, files)
+    def asset_file_links(link_sym, files)
       return '' if files.size == 0
       links = files.map do |filename|
         if filename =~ %r{^/}
@@ -91,14 +91,10 @@ module Footnotes
           %{&lt;a href=&quot;#{filename}&quot;&gt;#{filename}&lt;/a&gt;}
         end
       end
-      @extra_html &lt;&lt; &lt;&lt;-HTML
-        &lt;fieldset id=&quot;tm_footnotes_#{link_text.underscore.gsub(' ', '_')}&quot; class=&quot;tm_footnotes_debug_info&quot; style=&quot;display: none&quot;&gt;
-          &lt;legend&gt;#{link_text}&lt;/legend&gt;
-          &lt;ul&gt;&lt;li&gt;#{links.join(&quot;&lt;/li&gt;&lt;li&gt;&quot;)}&lt;/li&gt;&lt;/ul&gt;
-        &lt;/fieldset&gt;
-      HTML
+      @extra_html &lt;&lt; footnote_fieldset(link_sym, &quot;&lt;ul&gt;&lt;li&gt;#{links.join(&quot;&lt;/li&gt;&lt;li&gt;&quot;)}&lt;/li&gt;&lt;/ul&gt;&quot;)
+
       # Return the link that will open the 'extra html' div
-      %{ | &lt;a href=&quot;#&quot; onclick=&quot;#{footnotes_toggle('tm_footnotes_' + link_text.underscore.gsub(' ', '_') )}; return false&quot;&gt;#{link_text}&lt;/a&gt;}
+      &quot; | #{footnote_link(link_sym, links.length)}&quot;
     end
     
     def lines_from_index(string, index)</diff>
      <filename>lib/textmate_links.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>014b1736b8572ec313c3135a68f49b31b2324a84</id>
    </parent>
  </parents>
  <author>
    <name>josevalim</name>
    <email>jose.valim@gmail.com</email>
  </author>
  <url>http://github.com/josevalim/rails-footnotes/commit/14dc5d1b2433fed070e6c10fdd652fa2f8df84ee</url>
  <id>14dc5d1b2433fed070e6c10fdd652fa2f8df84ee</id>
  <committed-date>2008-06-04T11:47:23-07:00</committed-date>
  <authored-date>2008-06-04T11:47:23-07:00</authored-date>
  <message>Added Queries notes, numbers and click in one note automatically close the others</message>
  <tree>d046158e47c039c1dd8dadbad451ce5c6d07b99b</tree>
  <committer>
    <name>josevalim</name>
    <email>jose.valim@gmail.com</email>
  </committer>
</commit>
