wallyqs-org-ruby 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. data/History.txt +41 -11
  2. data/README.rdoc +55 -50
  3. data/bin/org-ruby +11 -5
  4. data/lib/org-ruby.rb +20 -27
  5. data/lib/org-ruby/headline.rb +0 -10
  6. data/lib/org-ruby/html_output_buffer.rb +224 -143
  7. data/lib/org-ruby/html_symbol_replace.rb +359 -340
  8. data/lib/org-ruby/line.rb +91 -30
  9. data/lib/org-ruby/output_buffer.rb +147 -139
  10. data/lib/org-ruby/parser.rb +45 -111
  11. data/lib/org-ruby/regexp_helper.rb +52 -57
  12. data/lib/org-ruby/textile_output_buffer.rb +90 -37
  13. data/lib/org-ruby/textile_symbol_replace.rb +360 -341
  14. metadata +39 -200
  15. data/.bnsignore +0 -18
  16. data/.gitignore +0 -2
  17. data/Gemfile +0 -7
  18. data/Gemfile.lock +0 -36
  19. data/Rakefile +0 -33
  20. data/TAGS +0 -167
  21. data/announcement.txt +0 -24
  22. data/org-ruby.gemspec +0 -40
  23. data/spec/data/freeform-example.org +0 -113
  24. data/spec/data/freeform.org +0 -111
  25. data/spec/data/hyp-planning.org +0 -335
  26. data/spec/data/remember.org +0 -53
  27. data/spec/headline_spec.rb +0 -65
  28. data/spec/html_examples/advanced-code.html +0 -81
  29. data/spec/html_examples/advanced-code.org +0 -106
  30. data/spec/html_examples/advanced-lists.html +0 -31
  31. data/spec/html_examples/advanced-lists.org +0 -31
  32. data/spec/html_examples/block_code.html +0 -28
  33. data/spec/html_examples/block_code.org +0 -35
  34. data/spec/html_examples/blockcomment.html +0 -3
  35. data/spec/html_examples/blockcomment.org +0 -15
  36. data/spec/html_examples/blockquote.html +0 -7
  37. data/spec/html_examples/blockquote.org +0 -13
  38. data/spec/html_examples/center.html +0 -6
  39. data/spec/html_examples/center.org +0 -7
  40. data/spec/html_examples/code-comment.html +0 -18
  41. data/spec/html_examples/code-comment.org +0 -22
  42. data/spec/html_examples/code-syntax.html +0 -98
  43. data/spec/html_examples/code-syntax.org +0 -99
  44. data/spec/html_examples/comment-trees.html +0 -4
  45. data/spec/html_examples/comment-trees.org +0 -13
  46. data/spec/html_examples/custom-seq-todo.html +0 -15
  47. data/spec/html_examples/custom-seq-todo.org +0 -24
  48. data/spec/html_examples/custom-todo.html +0 -15
  49. data/spec/html_examples/custom-todo.org +0 -24
  50. data/spec/html_examples/custom-typ-todo.html +0 -15
  51. data/spec/html_examples/custom-typ-todo.org +0 -24
  52. data/spec/html_examples/deflist.html +0 -6
  53. data/spec/html_examples/deflist.org +0 -6
  54. data/spec/html_examples/entities.html +0 -4
  55. data/spec/html_examples/entities.org +0 -11
  56. data/spec/html_examples/escape-pre.html +0 -6
  57. data/spec/html_examples/escape-pre.org +0 -6
  58. data/spec/html_examples/export-exclude-only.html +0 -13
  59. data/spec/html_examples/export-exclude-only.org +0 -81
  60. data/spec/html_examples/export-keywords.html +0 -4
  61. data/spec/html_examples/export-keywords.org +0 -18
  62. data/spec/html_examples/export-tags.html +0 -8
  63. data/spec/html_examples/export-tags.org +0 -82
  64. data/spec/html_examples/export-title.html +0 -2
  65. data/spec/html_examples/export-title.org +0 -4
  66. data/spec/html_examples/footnotes.html +0 -10
  67. data/spec/html_examples/footnotes.org +0 -7
  68. data/spec/html_examples/html-literal.html +0 -2
  69. data/spec/html_examples/html-literal.org +0 -6
  70. data/spec/html_examples/inline-formatting.html +0 -20
  71. data/spec/html_examples/inline-formatting.org +0 -33
  72. data/spec/html_examples/inline-images.html +0 -10
  73. data/spec/html_examples/inline-images.org +0 -15
  74. data/spec/html_examples/link-features.html +0 -8
  75. data/spec/html_examples/link-features.org +0 -19
  76. data/spec/html_examples/lists.html +0 -23
  77. data/spec/html_examples/lists.org +0 -47
  78. data/spec/html_examples/metadata-comment.html +0 -27
  79. data/spec/html_examples/metadata-comment.org +0 -30
  80. data/spec/html_examples/only-list.html +0 -5
  81. data/spec/html_examples/only-list.org +0 -3
  82. data/spec/html_examples/only-table.html +0 -6
  83. data/spec/html_examples/only-table.org +0 -5
  84. data/spec/html_examples/skip-header.html +0 -3
  85. data/spec/html_examples/skip-header.org +0 -28
  86. data/spec/html_examples/skip-table.html +0 -4
  87. data/spec/html_examples/skip-table.org +0 -19
  88. data/spec/html_examples/subsupscript-nil.html +0 -3
  89. data/spec/html_examples/subsupscript-nil.org +0 -6
  90. data/spec/html_examples/subsupscript.html +0 -3
  91. data/spec/html_examples/subsupscript.org +0 -5
  92. data/spec/html_examples/tables.html +0 -35
  93. data/spec/html_examples/tables.org +0 -50
  94. data/spec/html_examples/text.html +0 -2
  95. data/spec/html_examples/text.org +0 -16
  96. data/spec/line_spec.rb +0 -155
  97. data/spec/output_buffer_spec.rb +0 -19
  98. data/spec/parser_spec.rb +0 -152
  99. data/spec/regexp_helper_spec.rb +0 -57
  100. data/spec/spec_helper.rb +0 -20
  101. data/spec/textile_examples/block_code.org +0 -35
  102. data/spec/textile_examples/block_code.textile +0 -29
  103. data/spec/textile_examples/blockquote.org +0 -13
  104. data/spec/textile_examples/blockquote.textile +0 -11
  105. data/spec/textile_examples/center.org +0 -7
  106. data/spec/textile_examples/center.textile +0 -6
  107. data/spec/textile_examples/footnotes.org +0 -7
  108. data/spec/textile_examples/footnotes.textile +0 -8
  109. data/spec/textile_examples/keywords.org +0 -13
  110. data/spec/textile_examples/keywords.textile +0 -11
  111. data/spec/textile_examples/links.org +0 -11
  112. data/spec/textile_examples/links.textile +0 -10
  113. data/spec/textile_examples/lists.org +0 -36
  114. data/spec/textile_examples/lists.textile +0 -20
  115. data/spec/textile_examples/single-space-plain-list.org +0 -13
  116. data/spec/textile_examples/single-space-plain-list.textile +0 -10
  117. data/spec/textile_examples/tables.org +0 -50
  118. data/spec/textile_examples/tables.textile +0 -40
  119. data/spec/textile_output_buffer_spec.rb +0 -21
  120. data/tasks/test_case.rake +0 -49
  121. data/test/test_orgmode_parser.rb +0 -0
  122. data/util/gen-special-replace.el +0 -37
@@ -14,6 +14,12 @@ module Orgmode
14
14
  # Backpointer to the parser that owns this line.
15
15
  attr_reader :parser
16
16
 
17
+ # Paragraph type determined for the line.
18
+ attr_reader :paragraph_type
19
+
20
+ # Major modes associate paragraphs with a table, list and so on.
21
+ attr_reader :major_mode
22
+
17
23
  # A line can have its type assigned instead of inferred from its
18
24
  # content. For example, something that parses as a "table" on its
19
25
  # own ("| one | two|\n") may just be a paragraph if it's inside
@@ -26,6 +32,8 @@ module Orgmode
26
32
  @line = line
27
33
  @indent = 0
28
34
  @line =~ /\s*/
35
+ determine_paragraph_type
36
+ determine_major_mode
29
37
  @assigned_paragraph_type = nil
30
38
  @indent = $&.length unless blank?
31
39
  end
@@ -55,7 +63,7 @@ module Orgmode
55
63
  check_assignment_or_regexp(:property_drawer, PropertyDrawerRegexp)
56
64
  end
57
65
 
58
- PropertyDrawerItemRegexp = /^\s*:(\w+):\s*(.*)$/i
66
+ PropertyDrawerItemRegexp = /^\s*:([0-9A-Za-z_\-]+):\s*(.*)$/i
59
67
 
60
68
  def property_drawer_item?
61
69
  @line =~ PropertyDrawerItemRegexp
@@ -78,7 +86,7 @@ module Orgmode
78
86
  ordered_list? or unordered_list? or definition_list?
79
87
  end
80
88
 
81
- UnorderedListRegexp = /^\s*(-|\+)\s+/
89
+ UnorderedListRegexp = /^\s*(-|\+|\s+[*])\s+/
82
90
 
83
91
  def unordered_list?
84
92
  check_assignment_or_regexp(:unordered_list, UnorderedListRegexp)
@@ -88,7 +96,7 @@ module Orgmode
88
96
  @line.sub(UnorderedListRegexp, "")
89
97
  end
90
98
 
91
- DefinitionListRegexp = /^\s*(-|\+)\s*(.*?)::/
99
+ DefinitionListRegexp = /^\s*(-|\+|\s+[*])\s+(.*\s+|)::($|\s+)/
92
100
 
93
101
  def definition_list?
94
102
  check_assignment_or_regexp(:definition_list, DefinitionListRegexp)
@@ -104,12 +112,19 @@ module Orgmode
104
112
  @line.sub(OrderedListRegexp, "")
105
113
  end
106
114
 
115
+ HorizontalRuleRegexp = /^\s*-{5,}\s*$/
116
+
117
+ def horizontal_rule?
118
+ check_assignment_or_regexp(:horizontal_rule, HorizontalRuleRegexp)
119
+ end
120
+
107
121
  # Extracts meaningful text and excludes org-mode markup,
108
122
  # like identifiers for lists or headings.
109
123
  def output_text
110
124
  return strip_ordered_list_tag if ordered_list?
111
125
  return strip_unordered_list_tag if unordered_list?
112
126
  return @line.sub(InlineExampleRegexp, "") if inline_example?
127
+ return strip_raw_text_tag if raw_text?
113
128
  return line
114
129
  end
115
130
 
@@ -131,7 +146,7 @@ module Orgmode
131
146
  check_assignment_or_regexp(:table_separator, /^\s*\|[-\|\+]*\s*$/)
132
147
  end
133
148
 
134
- # Checks if this line is a table header.
149
+ # Checks if this line is a table header.
135
150
  def table_header?
136
151
  @assigned_paragraph_type == :table_header
137
152
  end
@@ -140,7 +155,7 @@ module Orgmode
140
155
  table_row? or table_separator? or table_header?
141
156
  end
142
157
 
143
- BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)\s*(\w*)?/i
158
+ BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)\s*([0-9A-Za-z_\-]*)?/i
144
159
 
145
160
  def begin_block?
146
161
  @line =~ BlockRegexp && $1 =~ /BEGIN/i
@@ -158,7 +173,7 @@ module Orgmode
158
173
  $3 if @line =~ BlockRegexp
159
174
  end
160
175
 
161
- def code_block_type?
176
+ def code_block?
162
177
  block_type =~ /^(EXAMPLE|SRC)$/i
163
178
  end
164
179
 
@@ -170,6 +185,21 @@ module Orgmode
170
185
  check_assignment_or_regexp(:inline_example, InlineExampleRegexp)
171
186
  end
172
187
 
188
+ RawTextRegexp = /^(\s*)#\+(\w+):\s*/
189
+
190
+ # Checks if this line is raw text.
191
+ def raw_text?
192
+ check_assignment_or_regexp(:raw_text, RawTextRegexp)
193
+ end
194
+
195
+ def raw_text_tag
196
+ $2.upcase if @line =~ RawTextRegexp
197
+ end
198
+
199
+ def strip_raw_text_tag
200
+ @line.sub(RawTextRegexp) { |match| $1 }
201
+ end
202
+
173
203
  InBufferSettingRegexp = /^#\+(\w+):\s*(.*)$/
174
204
 
175
205
  # call-seq:
@@ -192,29 +222,60 @@ module Orgmode
192
222
  end
193
223
 
194
224
  # Determines the paragraph type of the current line.
195
- def paragraph_type
196
- return :blank if blank?
197
- return :definition_list if definition_list? # order is important! A definition_list is also an unordered_list!
198
- return :ordered_list if ordered_list?
199
- return :unordered_list if unordered_list?
200
- return :property_drawer_begin_block if property_drawer_begin_block?
201
- return :property_drawer_end_block if property_drawer_end_block?
202
- return :property_drawer_item if property_drawer_item?
203
- return :metadata if metadata?
204
- return :begin_block if begin_block?
205
- return :end_block if end_block?
206
- return :comment if comment?
207
- return :table_separator if table_separator?
208
- return :table_row if table_row?
209
- return :table_header if table_header?
210
- return :inline_example if inline_example?
211
- return :paragraph
212
- end
213
-
214
- def self.to_textile(lines)
215
- output = ""
216
- output_buffer = TextileOutputBuffer.new(output)
217
- Parser.translate(lines, output_buffer)
225
+ def determine_paragraph_type
226
+ @paragraph_type = \
227
+ case
228
+ when blank?
229
+ :blank
230
+ when definition_list? # order is important! A definition_list is also an unordered_list!
231
+ :definition_term
232
+ when (ordered_list? or unordered_list?)
233
+ :list_item
234
+ when property_drawer_begin_block?
235
+ :property_drawer_begin_block
236
+ when property_drawer_end_block?
237
+ :property_drawer_end_block
238
+ when property_drawer_item?
239
+ :property_drawer_item
240
+ when metadata?
241
+ :metadata
242
+ when block_type
243
+ case block_type.downcase.to_sym
244
+ when :center, :comment, :example, :html, :quote, :src
245
+ block_type.downcase.to_sym
246
+ else
247
+ :comment
248
+ end
249
+ when raw_text? # order is important! Raw text can be also a comment
250
+ :raw_text
251
+ when comment?
252
+ :comment
253
+ when table_separator?
254
+ :table_separator
255
+ when table_row?
256
+ :table_row
257
+ when table_header?
258
+ :table_header
259
+ when inline_example?
260
+ :inline_example
261
+ when horizontal_rule?
262
+ :horizontal_rule
263
+ else :paragraph
264
+ end
265
+ end
266
+
267
+ def determine_major_mode
268
+ @major_mode = \
269
+ case
270
+ when definition_list? # order is important! A definition_list is also an unordered_list!
271
+ :definition_list
272
+ when ordered_list?
273
+ :ordered_list
274
+ when unordered_list?
275
+ :unordered_list
276
+ when table?
277
+ :table
278
+ end
218
279
  end
219
280
 
220
281
  ######################################################################
@@ -227,7 +288,7 @@ module Orgmode
227
288
  # What's tricky is lines can have assigned types, so you need to check
228
289
  # the assigned type, if present, or see if the characteristic regexp
229
290
  # for the paragraph type matches if not present.
230
- #
291
+ #
231
292
  # call-seq:
232
293
  # check_assignment_or_regexp(assignment, regexp) => boolean
233
294
  #
@@ -8,40 +8,29 @@ module Orgmode
8
8
  # add a newline character prior emitting the output.
9
9
  class OutputBuffer
10
10
 
11
- # This is the accumulation buffer. It's a holding pen so
12
- # consecutive lines of the right type can get stuck together
13
- # without intervening newlines.
14
- attr_reader :buffer
15
-
16
- # These are the Line objects that are currently in the accumulation
17
- # buffer.
18
- attr_reader :buffered_lines
19
-
20
- # This is the output mode of the accumulation buffer.
21
- attr_reader :buffer_mode
22
-
23
11
  # This is the overall output buffer
24
12
  attr_reader :output
25
13
 
26
- # This is the current type of output being accumulated.
14
+ # This is the current type of output being accumulated.
27
15
  attr_accessor :output_type
28
16
 
29
- # This stack is used to do proper outline numbering of headlines.
30
- attr_accessor :headline_number_stack
31
-
32
17
  # Creates a new OutputBuffer object that is bound to an output object.
33
18
  # The output will get flushed to =output=.
34
19
  def initialize(output)
35
- @output = output
20
+ # This is the accumulation buffer. It's a holding pen so
21
+ # consecutive lines of the right type can get stuck together
22
+ # without intervening newlines.
36
23
  @buffer = ""
37
- @buffered_lines = []
38
- @buffer_mode = nil
24
+
25
+ # This stack is used to do proper outline numbering of
26
+ # headlines.
27
+ @headline_number_stack = []
28
+
29
+ @output = output
39
30
  @output_type = :start
40
31
  @list_indent_stack = []
41
- @paragraph_modifier = nil
42
- @cancel_modifier = false
43
32
  @mode_stack = []
44
- @headline_number_stack = []
33
+ @code_block_indent = nil
45
34
 
46
35
  @logger = Logger.new(STDERR)
47
36
  if ENV['DEBUG'] or $DEBUG
@@ -51,21 +40,13 @@ module Orgmode
51
40
  end
52
41
 
53
42
  @re_help = RegexpHelper.new
54
- push_mode(:normal)
55
43
  end
56
44
 
57
- Modes = [:normal, :ordered_list, :unordered_list, :definition_list, :blockquote, :src, :example, :table, :inline_example, :center, :property_drawer]
58
-
59
45
  def current_mode
60
46
  @mode_stack.last
61
47
  end
62
48
 
63
- def current_mode_list?
64
- (current_mode == :ordered_list) or (current_mode == :unordered_list)
65
- end
66
-
67
49
  def push_mode(mode)
68
- raise "Not a recognized mode: #{mode}" unless Modes.include?(mode)
69
50
  @mode_stack.push(mode)
70
51
  end
71
52
 
@@ -75,33 +56,49 @@ module Orgmode
75
56
  m
76
57
  end
77
58
 
78
- # Prepares the output buffer to receive content from a line.
79
- # As a side effect, this may flush the current accumulated text.
80
- def prepare(line)
81
- @logger.debug "Looking at #{line.paragraph_type}: #{line.to_s}"
82
- if not should_accumulate_output?(line) then
83
- @block_lang = line.block_lang if line.begin_block? and line.code_block_type?
59
+ def insert(line)
60
+ # Prepares the output buffer to receive content from a line.
61
+ # As a side effect, this may flush the current accumulated text.
62
+ @logger.debug "Looking at #{line.paragraph_type}(#{current_mode}) : #{line.to_s}"
63
+ # We try to get the lang from #+BEGIN_SRC blocks
64
+ @block_lang = line.block_lang if line.begin_block?
65
+ unless should_accumulate_output?(line)
84
66
  flush!
85
- maintain_list_indent_stack(line)
86
- @output_type = line.paragraph_type
67
+ maintain_mode_stack(line)
87
68
  end
88
- push_mode(:inline_example) if line.inline_example? and current_mode != :inline_example and not line.property_drawer?
89
- pop_mode(:inline_example) if current_mode == :inline_example and !line.inline_example?
90
- push_mode(:property_drawer) if line.property_drawer? and current_mode != :property_drawer
91
- pop_mode(:property_drawer) if current_mode == :property_drawer and line.property_drawer_end_block?
92
- push_mode(:table) if enter_table?
93
- pop_mode(:table) if exit_table?
94
- @buffered_lines.push(line)
95
- end
96
-
97
- # Flushes everything currently in the accumulation buffer into the
98
- # output buffer. Derived classes must override this to actually move
99
- # content into the output buffer with the appropriate markup. This
100
- # method just does common bookkeeping cleanup.
101
- def clear_accumulation_buffer!
102
- @buffer = ""
103
- @buffer_mode = nil
104
- @buffered_lines = []
69
+
70
+ # Adds the current line to the output buffer
71
+ case
72
+ when line.raw_text?
73
+ @buffer << "\n" << line.output_text if line.raw_text_tag == @buffer_tag
74
+ when preserve_whitespace?
75
+ @buffer << "\n" << line.output_text unless line.block_type
76
+ when line.assigned_paragraph_type == :code
77
+ # If the line is contained within a code block but we should
78
+ # not preserve whitespaces, then we do nothing.
79
+ when (line.kind_of? Headline)
80
+ add_line_attributes line
81
+ @buffer << "\n" << line.output_text.strip
82
+ when ([:definition_term, :list_item, :table_row, :table_header,
83
+ :horizontal_rule].include? line.paragraph_type)
84
+ @buffer << "\n" << line.output_text.strip
85
+ when line.paragraph_type == :paragraph
86
+ @buffer << "\n"
87
+ buffer_indentation
88
+ @buffer << line.output_text.strip
89
+ end
90
+
91
+ if mode_is_code? current_mode and not line.block_type
92
+ # Determines the amount of whitespaces to be stripped at the
93
+ # beginning of each line in code block.
94
+ if @code_block_indent
95
+ @code_block_indent = [@code_block_indent, line.indent].min
96
+ else
97
+ @code_block_indent = line.indent
98
+ end
99
+ end
100
+
101
+ @output_type = line.assigned_paragraph_type || line.paragraph_type
105
102
  end
106
103
 
107
104
  # Gets the next headline number for a given level. The intent is
@@ -120,79 +117,83 @@ module Orgmode
120
117
  @headline_number_stack.join(".")
121
118
  end
122
119
 
123
- # Tests if we are entering a table mode.
124
- def enter_table?
125
- ((@output_type == :table_row) || (@output_type == :table_header) || (@output_type == :table_separator)) &&
126
- (current_mode != :table)
127
- end
128
-
129
- # Tests if we are existing a table mode.
130
- def exit_table?
131
- ((@output_type != :table_row) && (@output_type != :table_header) && (@output_type != :table_separator)) &&
132
- (current_mode == :table)
133
- end
134
-
135
- # Accumulate the string @str@.
136
- def << (str)
137
- if @buffer_mode && @buffer_mode != current_mode then
138
- raise "Accumulation buffer is mixing modes: @buffer_mode == #{@buffer_mode}, current_mode == #{current_mode}"
139
- else
140
- @buffer_mode = current_mode
141
- end
142
- @buffer << str
143
- end
144
-
145
- # Gets the current list indent level.
120
+ # Gets the current list indent level.
146
121
  def list_indent_level
147
122
  @list_indent_stack.length
148
123
  end
149
124
 
150
125
  # Test if we're in an output mode in which whitespace is significant.
151
126
  def preserve_whitespace?
152
- mode_is_code current_mode
127
+ [:example, :inline_example, :raw_text, :src].include? current_mode
153
128
  end
154
129
 
155
130
  ######################################################################
156
131
  private
157
132
 
158
- def mode_is_code(mode)
159
- case mode
160
- when :src, :inline_example, :example
161
- true
162
- else
163
- false
164
- end
133
+ def mode_is_heading?(mode)
134
+ [:heading1, :heading2, :heading3,
135
+ :heading4, :heading5, :heading6].include? mode
165
136
  end
166
137
 
167
- def maintain_list_indent_stack(line)
168
- if (line.plain_list?) then
169
- while (not @list_indent_stack.empty? \
170
- and (@list_indent_stack.last > line.indent))
171
- @list_indent_stack.pop
172
- pop_mode
173
- end
174
- if (@list_indent_stack.empty? \
175
- or @list_indent_stack.last < line.indent)
176
- @list_indent_stack.push(line.indent)
177
- push_mode line.paragraph_type
178
- end
179
- elsif line.blank? then
138
+ def mode_is_block?(mode)
139
+ [:quote, :center, :example, :src].include? mode
140
+ end
180
141
 
181
- # Nothing
142
+ def mode_is_code?(mode)
143
+ [:example, :src].include? mode
144
+ end
182
145
 
183
- elsif ((line.paragraph_type == :paragraph) and
184
- (not @list_indent_stack.empty? and
185
- line.indent > @list_indent_stack.last))
146
+ def boundary_of_block?(line)
147
+ # Boundary of inline example
148
+ return true if ((line.paragraph_type == :inline_example) ^
149
+ (@output_type == :inline_example))
150
+ # Boundary of begin...end block
151
+ return true if mode_is_block? @output_type
152
+ end
186
153
 
187
- # Nothing -- output this paragraph inside
188
- # the list block (ul/ol)
154
+ def maintain_mode_stack(line)
155
+ # Always close the following lines
156
+ pop_mode if (mode_is_heading? current_mode or
157
+ current_mode == :paragraph or
158
+ current_mode == :horizontal_rule or
159
+ current_mode == :inline_example or
160
+ current_mode == :raw_text)
189
161
 
190
- else
191
- @list_indent_stack = []
192
- while ((current_mode == :ordered_list) or
193
- (current_mode == :definition_list) or
194
- (current_mode == :unordered_list))
195
- pop_mode
162
+ # End-block line closes every mode within block
163
+ if line.end_block? and @mode_stack.include? line.paragraph_type
164
+ pop_mode until current_mode == line.paragraph_type
165
+ end
166
+
167
+ if ((not line.paragraph_type == :blank) or
168
+ @output_type == :blank)
169
+ # Close previous tags on demand. Two blank lines close all tags.
170
+ while ((not @list_indent_stack.empty?) and
171
+ @list_indent_stack.last >= line.indent and
172
+ # Don't allow an arbitrary line to close block
173
+ (not mode_is_block? current_mode))
174
+ # Item can't close its major mode
175
+ if (@list_indent_stack.last == line.indent and
176
+ line.major_mode == current_mode)
177
+ break
178
+ else
179
+ pop_mode
180
+ end
181
+ end
182
+ end
183
+
184
+ # Special case: Only end-block line closes block
185
+ pop_mode if line.end_block? and line.paragraph_type == current_mode
186
+
187
+ unless line.paragraph_type == :blank
188
+ if (@list_indent_stack.empty? or
189
+ @list_indent_stack.last <= line.indent or
190
+ mode_is_block? current_mode)
191
+ # Opens the major mode of line if it exists
192
+ if @list_indent_stack.last != line.indent or mode_is_block? current_mode
193
+ push_mode(line.major_mode, line.indent) if line.major_mode
194
+ end
195
+ # Opens tag that precedes text immediately
196
+ push_mode(line.paragraph_type, line.indent) unless line.end_block?
196
197
  end
197
198
  end
198
199
  end
@@ -202,36 +203,43 @@ module Orgmode
202
203
  end
203
204
 
204
205
  # Tests if the current line should be accumulated in the current
205
- # output buffer. (Extraneous line breaks in the orgmode buffer
206
- # are removed by accumulating lines in the output buffer without
207
- # line breaks.)
208
- def should_accumulate_output?(line)
209
-
210
- # Special case: Preserve line breaks in block code mode.
211
- return false if preserve_whitespace?
212
-
213
- # Special case: Multiple blank lines get accumulated.
214
- return true if line.paragraph_type == :blank and @output_type == :blank
215
-
216
- # Currently only "paragraphs" get accumulated with previous output.
217
- return false unless line.paragraph_type == :paragraph
218
- if ((@output_type == :ordered_list) or
219
- (@output_type == :definition_list) or
220
- (@output_type == :unordered_list)) then
221
-
222
- # If the previous output type was a list item, then we only put a paragraph in it
223
- # if its indent level is greater than the list indent level.
224
-
225
- return false unless line.indent > @list_indent_stack.last
206
+ # output buffer.
207
+ def should_accumulate_output? line
208
+ # Special case: Assign mode if not yet done.
209
+ return false unless current_mode
210
+
211
+ # Special case: Handles accumulating block content and example lines
212
+ if mode_is_code? current_mode
213
+ return true unless (line.end_block? and
214
+ line.paragraph_type == current_mode)
215
+ end
216
+ return false if boundary_of_block? line
217
+ return true if current_mode == :inline_example
218
+
219
+ # Special case: Don't accumulate the following lines.
220
+ return false if (mode_is_heading? @output_type or
221
+ @output_type == :comment or
222
+ @output_type == :horizontal_rule or
223
+ @output_type == :raw_text)
224
+
225
+ # Special case: Blank line at least splits paragraphs
226
+ return false if @output_type == :blank
227
+
228
+ if line.paragraph_type == :paragraph
229
+ # Paragraph gets accumulated only if its indent level is
230
+ # greater than the indent level of the previous mode.
231
+ if @mode_stack[-2] and not mode_is_block? @mode_stack[-2]
232
+ return false if line.indent <= @list_indent_stack[-2]
233
+ end
234
+ # Special case: Multiple "paragraphs" get accumulated.
235
+ return true
226
236
  end
227
237
 
228
- # Only accumulate paragraphs with lists & paragraphs.
229
- return false unless
230
- ((@output_type == :paragraph) or
231
- (@output_type == :ordered_list) or
232
- (@output_type == :definition_list) or
233
- (@output_type == :unordered_list))
234
- true
238
+ false
239
+ end
240
+
241
+ def buffer_indentation
242
+ return false
235
243
  end
236
244
  end # class OutputBuffer
237
245
  end # module Orgmode