[DRE-commits] [ruby-org] 81/303: Big layering/refactoring

Jérémy Bobbio lunar at alioth.debian.org
Fri Aug 9 17:33:32 UTC 2013


This is an automated email from the git hooks/post-receive script.

lunar pushed a commit to branch master
in repository ruby-org.

commit a02d0fddf9f01b04b300eae26bf390718d61d0e4
Author: Brian Dewey <bdewey at gmail.com>
Date:   Wed Jan 6 00:59:29 2010 -0800

    Big layering/refactoring
---
 lib/org-ruby/headline.rb              |   44 ++++++--------------
 lib/org-ruby/html_output_buffer.rb    |   30 ++++++++++---
 lib/org-ruby/line.rb                  |   11 ++++-
 lib/org-ruby/output_buffer.rb         |   36 ++++++++++++++++
 lib/org-ruby/parser.rb                |   74 ++++++++++++++-------------------
 lib/org-ruby/textile_output_buffer.rb |    3 +-
 spec/output_buffer_spec.rb            |   19 +++++++++
 spec/parser_spec.rb                   |   18 +-------
 8 files changed, 137 insertions(+), 98 deletions(-)

diff --git a/lib/org-ruby/headline.rb b/lib/org-ruby/headline.rb
index deaaae1..8f33364 100644
--- a/lib/org-ruby/headline.rb
+++ b/lib/org-ruby/headline.rb
@@ -44,6 +44,7 @@ module Orgmode
     def initialize(line, parser = nil)
       super(line, parser)
       @body_lines = []
+      @body_lines << self       # Make @body_lines contain the headline?
       @tags = []
       @export_state = :exclude
       if (@line =~ LineRegexp) then
@@ -61,52 +62,33 @@ module Orgmode
       end
     end
 
+    # Override Line.output_text. For a heading, @headline_text
+    # is what we should output.
+    def output_text
+      return @headline_text
+    end
+
     # Determines if a line is an orgmode "headline":
     # A headline begins with one or more asterisks.
     def self.headline?(line)
       line =~ LineRegexp
     end
 
+    # Overrides Line.paragraph_type.
+    def paragraph_type
+      :"heading#{@level}"
+    end
+
     # Converts this headline and its body to textile.
     def to_textile
       output = "h#{@level}. #{@headline_text}\n"
-      output << Line.to_textile(@body_lines)
-      output
-    end
-
-    def to_html(opts = {})
-      return "" if @export_state == :exclude
-      if opts[:decorate_title]
-        decoration = " class=\"title\""
-        opts.delete(:decorate_title)
-      else
-        decoration = ""
-      end
-      output = "<h#{@level}#{decoration}>"
-      if @parser and @parser.export_heading_number? then
-        heading_number = @parser.get_next_headline_number(@level)
-        output << "<span class=\"heading-number heading-number-#{@level}\">#{heading_number} </span>"
-      end
-      if @parser and @parser.export_todo? and @keyword then
-        output << "<span class=\"todo-keyword #{@keyword}\">#{@keyword} </span>"
-      end
-      output << "#{escape(@headline_text)}</h#{@level}>\n"
-      return output if @export_state == :headline_only
-      output << Line.to_html(@body_lines, opts)
+      output << Line.to_textile(@body_lines[1..-1])
       output
     end
 
     ######################################################################
     private
 
-    # TODO 2009-12-29 This duplicates escape_buffer! in html_output_buffer. DRY.
-    def escape(str)
-      str = str.gsub(/&/, "&")
-      str = str.gsub(/</, "<")
-      str = str.gsub(/>/, ">")
-      str
-    end
-
     def parse_keywords
       re = @parser.custom_keyword_regexp if @parser
       re ||= KeywordsRegexp
diff --git a/lib/org-ruby/html_output_buffer.rb b/lib/org-ruby/html_output_buffer.rb
index e31c2b1..6199d7e 100644
--- a/lib/org-ruby/html_output_buffer.rb
+++ b/lib/org-ruby/html_output_buffer.rb
@@ -9,7 +9,13 @@ module Orgmode
       :ordered_list => "li",
       :unordered_list => "li",
       :table_row => "tr",
-      :table_header => "tr"
+      :table_header => "tr",
+      :heading1 => "h1",
+      :heading2 => "h2",
+      :heading3 => "h3",
+      :heading4 => "h4",
+      :heading5 => "h5",
+      :heading6 => "h6"
     }
 
     ModeTag = {
@@ -75,17 +81,29 @@ module Orgmode
           unless buffer_mode_is_table? and skip_tables?
             @logger.debug "FLUSH      ==========> #{@buffer_mode}"
             output_indentation
-            @output << "<#{HtmlBlockTag[@output_type]}#{@title_decoration}>" \
-            << inline_formatting(@buffer) \
-            << "</#{HtmlBlockTag[@output_type]}>\n"
+            @output << "<#{HtmlBlockTag[@output_type]}#{@title_decoration}>" 
+            if (@buffered_lines[0].kind_of?(Headline)) then
+              headline = @buffered_lines[0]
+              raise "Cannot be more than one headline!" if @buffered_lines.length > 1
+              if @options[:export_heading_number] then
+                level = headline.level
+                heading_number = get_next_headline_number(level)
+                output << "<span class=\"heading-number heading-number-#{level}\">#{heading_number} </span>"
+              end
+              if @options[:export_todo] and headline.keyword then
+                keyword = headline.keyword
+                output << "<span class=\"todo-keyword #{keyword}\">#{keyword} </span>"
+              end
+            end
+            @output << inline_formatting(@buffer) 
+            @output << "</#{HtmlBlockTag[@output_type]}>\n"
             @title_decoration = ""
           else
             @logger.debug "SKIP       ==========> #{@buffer_mode}"
           end
         end
       end
-      @buffer = ""
-      @buffer_mode = nil
+      clear_accumulation_buffer!
     end
 
     ######################################################################
diff --git a/lib/org-ruby/line.rb b/lib/org-ruby/line.rb
index 472dd1b..58e9525 100644
--- a/lib/org-ruby/line.rb
+++ b/lib/org-ruby/line.rb
@@ -76,6 +76,15 @@ module Orgmode
       @line.sub(OrderedListRegexp, "")
     end
 
+    # Extracts meaningful text and excludes org-mode markup,
+    # like identifiers for lists or headings.
+    def output_text
+      return strip_ordered_list_tag if ordered_list?
+      return strip_unordered_list_tag if unordered_list?
+      return @line.sub(InlineExampleRegexp, "") if inline_example?
+      return line
+    end
+
     def plain_text?
       not metadata? and not blank? and not plain_list?
     end
@@ -167,7 +176,7 @@ module Orgmode
     def self.to_textile(lines)
       output = ""
       output_buffer = TextileOutputBuffer.new(output)
-      translate(lines, output_buffer)
+      Parser.translate(lines, output_buffer)
     end
 
     ######################################################################
diff --git a/lib/org-ruby/output_buffer.rb b/lib/org-ruby/output_buffer.rb
index 4fbd114..4c704ba 100644
--- a/lib/org-ruby/output_buffer.rb
+++ b/lib/org-ruby/output_buffer.rb
@@ -13,6 +13,10 @@ module Orgmode
     # without intervening newlines.
     attr_reader :buffer
 
+    # These are the Line objects that are currently in the accumulation
+    # buffer.
+    attr_reader :buffered_lines
+
     # This is the output mode of the accumulation buffer.
     attr_reader :buffer_mode
 
@@ -22,17 +26,22 @@ module Orgmode
     # This is the current type of output being accumulated. 
     attr_accessor :output_type
 
+    # This stack is used to do proper outline numbering of headlines.
+    attr_accessor :headline_number_stack
+
     # Creates a new OutputBuffer object that is bound to an output object.
     # The output will get flushed to =output=.
     def initialize(output)
       @output = output
       @buffer = ""
+      @buffered_lines = []
       @buffer_mode = nil
       @output_type = :start
       @list_indent_stack = []
       @paragraph_modifier = nil
       @cancel_modifier = false
       @mode_stack = []
+      @headline_number_stack = []
 
       @logger = Logger.new(STDERR)
       if ENV['DEBUG']
@@ -79,6 +88,33 @@ module Orgmode
       pop_mode(:inline_example) if current_mode == :inline_example && !line.inline_example?
       push_mode(:table) if enter_table?
       pop_mode(:table) if exit_table?
+      @buffered_lines.push(line)
+    end
+
+    # Flushes everything currently in the accumulation buffer into the 
+    # output buffer. Derived classes must override this to actually move
+    # content into the output buffer with the appropriate markup. This
+    # method just does common bookkeeping cleanup.
+    def clear_accumulation_buffer!
+      @buffer = ""
+      @buffer_mode = nil
+      @buffered_lines = []
+    end
+
+    # Gets the next headline number for a given level. The intent is
+    # this function is called sequentially for each headline that
+    # needs to get numbered. It does standard outline numbering.
+    def get_next_headline_number(level)
+      raise "Headline level not valid: #{level}" if level <= 0
+      while level > @headline_number_stack.length do
+        @headline_number_stack.push 0
+      end
+      while level < @headline_number_stack.length do
+        @headline_number_stack.pop
+      end
+      raise "Oops, shouldn't happen" unless level == @headline_number_stack.length
+      @headline_number_stack[@headline_number_stack.length - 1] += 1
+      @headline_number_stack.join(".")
     end
 
     # Tests if we are entering a table mode.
diff --git a/lib/org-ruby/parser.rb b/lib/org-ruby/parser.rb
index 4b35d3e..86ba9a1 100644
--- a/lib/org-ruby/parser.rb
+++ b/lib/org-ruby/parser.rb
@@ -53,9 +53,6 @@ module Orgmode
       "t" == @options["todo"]
     end
 
-    # This stack is used to do proper outline numbering of headlines.
-    attr_accessor :headline_number_stack
-
     # Returns true if we are to export heading numbers.
     def export_heading_number?
       "t" == @options["num"]
@@ -72,22 +69,6 @@ module Orgmode
       "nil" != @options["|"]
     end
 
-    # Gets the next headline number for a given level. The intent is
-    # this function is called sequentially for each headline that
-    # needs to get numbered. It does standard outline numbering.
-    def get_next_headline_number(level)
-      raise "Headline level not valid: #{level}" if level <= 0
-      while level > @headline_number_stack.length do
-        @headline_number_stack.push 0
-      end
-      while level < @headline_number_stack.length do
-        @headline_number_stack.pop
-      end
-      raise "Oops, shouldn't happen" unless level == @headline_number_stack.length
-      @headline_number_stack[@headline_number_stack.length - 1] += 1
-      @headline_number_stack.join(".")
-    end
-
     # I can construct a parser object either with an array of lines
     # or with a single string that I will split along \n boundaries.
     def initialize(lines)
@@ -104,7 +85,6 @@ module Orgmode
       @current_headline = nil
       @header_lines = []
       @in_buffer_settings = { }
-      @headline_number_stack = []
       @options = { }
       mode = :normal
       previous_line = nil
@@ -136,7 +116,7 @@ module Orgmode
 
           # As long as we stay in code mode, force lines to be either blank or paragraphs.
           # Don't try to interpret structural items, like headings and tables.
-          line = Line.new line
+          line = Line.new line, self
           if line.end_block? and line.block_type == "EXAMPLE"
             mode = :normal
           else
@@ -171,23 +151,36 @@ module Orgmode
     # Converts the loaded org-mode file to HTML.
     def to_html
       mark_trees_for_export
-      @headline_number_stack = []
-      export_options = { }
+      export_options = {
+        :decorate_title => true,
+        :export_heading_number => export_heading_number?,
+        :export_todo => export_todo?
+      }
       export_options[:skip_tables] = true if not export_tables?
       output = ""
+      output_buffer = HtmlOutputBuffer.new(output, export_options)
+      
       if @in_buffer_settings["TITLE"] then
-        output << "<p class=\"title\">#{@in_buffer_settings["TITLE"]}</p>\n"
-      else
-        export_options[:decorate_title] = true
+
+        # If we're given a new title, then just create a new line
+        # for that title.
+        title = Line.new(@in_buffer_settings["TITLE"], self)
+        Parser.translate([title], output_buffer)
       end
-      output_buffer = HtmlOutputBuffer.new(output, export_options)
-      output << translate(@header_lines, output_buffer) unless skip_header_lines?
+      Parser.translate(@header_lines, output_buffer) unless skip_header_lines?
       
       # If we've output anything at all, remove the :decorate_title option.
       export_options.delete(:decorate_title) if (output.length > 0)
       @headlines.each do |headline|
-        output << headline.to_html(export_options)
-        export_options.delete(:decorate_title) if (output.length > 0)
+        next if headline.export_state == :exclude
+        case headline.export_state
+        when :exclude
+          # NOTHING
+        when :headline_only
+          Parser.translate(headline.body_lines[0, 1], output_buffer)
+        when :all
+          Parser.translate(headline.body_lines, output_buffer)
+        end
       end
       rp = RubyPants.new(output)
       rp.to_html
@@ -197,7 +190,8 @@ module Orgmode
     private
 
     # Converts an array of lines to the appropriate format.
-    def translate(lines, output_buffer)
+    # Writes the output to +output_buffer+.
+    def self.translate(lines, output_buffer)
       lines.each do |line|
 
         # See if we're carrying paragraph payload, and output
@@ -227,24 +221,20 @@ module Orgmode
 
           output_buffer << line.line.lstrip
 
-        when :ordered_list
-            
-          output_buffer << line.strip_ordered_list_tag << " "
-          
-        when :unordered_list
+        when :unordered_list, :ordered_list
           
-          output_buffer << line.strip_unordered_list_tag << " "
+          output_buffer << line.output_text << " "
 
         when :inline_example
 
-          output_buffer << line.line.sub(InlineExampleRegexp, "")
-          
-        when :paragraph
+          output_buffer << line.output_text
+
+        else
 
           if output_buffer.preserve_whitespace? then
-            output_buffer << line.line
+            output_buffer << line.output_text
           else
-            output_buffer << line.line.strip << " "
+            output_buffer << line.output_text.strip << " "
           end
         end
       end
diff --git a/lib/org-ruby/textile_output_buffer.rb b/lib/org-ruby/textile_output_buffer.rb
index d02bcd1..6fe85f5 100644
--- a/lib/org-ruby/textile_output_buffer.rb
+++ b/lib/org-ruby/textile_output_buffer.rb
@@ -59,8 +59,7 @@ module Orgmode
         @output << "*" * @list_indent_stack.length << " " if @output_type == :unordered_list
         @output << inline_formatting(@buffer) << "\n"
       end
-      @buffer = ""
-      @buffer_mode = nil
+      clear_accumulation_buffer!
     end
 
 
diff --git a/spec/output_buffer_spec.rb b/spec/output_buffer_spec.rb
new file mode 100644
index 0000000..533d359
--- /dev/null
+++ b/spec/output_buffer_spec.rb
@@ -0,0 +1,19 @@
+require File.join(File.dirname(__FILE__), %w[spec_helper])
+
+describe Orgmode::OutputBuffer do
+
+  it "computes outline level numbering" do
+    output_buffer = Orgmode::OutputBuffer.new ""
+    output_buffer.get_next_headline_number(1).should eql("1")
+    output_buffer.get_next_headline_number(1).should eql("2")
+    output_buffer.get_next_headline_number(1).should eql("3")
+    output_buffer.get_next_headline_number(1).should eql("4")
+    output_buffer.get_next_headline_number(2).should eql("4.1")
+    output_buffer.get_next_headline_number(2).should eql("4.2")
+    output_buffer.get_next_headline_number(1).should eql("5")
+    output_buffer.get_next_headline_number(2).should eql("5.1")
+    output_buffer.get_next_headline_number(2).should eql("5.2")
+    output_buffer.get_next_headline_number(4).should eql("5.2.0.1")
+  end
+
+end
diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb
index 6c5d3c7..a3b80e1 100644
--- a/spec/parser_spec.rb
+++ b/spec/parser_spec.rb
@@ -33,8 +33,8 @@ describe Orgmode::Parser do
 
   it "should put body lines in headlines" do
     parser = Orgmode::Parser.load(RememberFile)
-    parser.headlines[0].should have(0).body_lines
-    parser.headlines[1].should have(6).body_lines
+    parser.headlines[0].should have(1).body_lines
+    parser.headlines[1].should have(7).body_lines
   end
 
   it "should understand lines before the first headline" do
@@ -61,20 +61,6 @@ describe Orgmode::Parser do
     parser.export_todo?.should be_false
   end
 
-  it "computes outline level numbering" do
-    parser = Orgmode::Parser.new ""
-    parser.get_next_headline_number(1).should eql("1")
-    parser.get_next_headline_number(1).should eql("2")
-    parser.get_next_headline_number(1).should eql("3")
-    parser.get_next_headline_number(1).should eql("4")
-    parser.get_next_headline_number(2).should eql("4.1")
-    parser.get_next_headline_number(2).should eql("4.2")
-    parser.get_next_headline_number(1).should eql("5")
-    parser.get_next_headline_number(2).should eql("5.1")
-    parser.get_next_headline_number(2).should eql("5.2")
-    parser.get_next_headline_number(4).should eql("5.2.0.1")
-  end
-
   it "should skip in-buffer settings inside EXAMPLE blocks" do
     parser = Orgmode::Parser.load(FreeformExampleFile)
     parser.should have(0).in_buffer_settings

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-org.git



More information about the Pkg-ruby-extras-commits mailing list