org-ruby 0.5.1 → 0.5.2

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 (89) hide show
  1. data/History.txt +81 -77
  2. data/README.rdoc +66 -66
  3. data/Rakefile +28 -28
  4. data/bin/org-ruby +40 -40
  5. data/lib/org-ruby.rb +50 -50
  6. data/lib/org-ruby/headline.rb +102 -120
  7. data/lib/org-ruby/html_output_buffer.rb +174 -156
  8. data/lib/org-ruby/line.rb +206 -260
  9. data/lib/org-ruby/output_buffer.rb +227 -191
  10. data/lib/org-ruby/parser.rb +320 -272
  11. data/lib/org-ruby/regexp_helper.rb +156 -156
  12. data/lib/org-ruby/textile_output_buffer.rb +67 -68
  13. data/spec/data/freeform-example.org +113 -113
  14. data/spec/data/freeform.org +111 -111
  15. data/spec/data/hyp-planning.org +335 -335
  16. data/spec/data/remember.org +53 -53
  17. data/spec/headline_spec.rb +55 -55
  18. data/spec/html_examples/advanced-code.html +36 -36
  19. data/spec/html_examples/advanced-code.org +53 -53
  20. data/spec/html_examples/advanced-lists.html +31 -31
  21. data/spec/html_examples/advanced-lists.org +31 -31
  22. data/spec/html_examples/block_code.html +28 -28
  23. data/spec/html_examples/block_code.org +35 -35
  24. data/spec/html_examples/blockquote.html +7 -7
  25. data/spec/html_examples/blockquote.org +13 -13
  26. data/spec/html_examples/code-comment.html +18 -18
  27. data/spec/html_examples/code-comment.org +22 -22
  28. data/spec/html_examples/custom-seq-todo.html +15 -15
  29. data/spec/html_examples/custom-seq-todo.org +24 -24
  30. data/spec/html_examples/custom-todo.html +15 -15
  31. data/spec/html_examples/custom-todo.org +24 -24
  32. data/spec/html_examples/custom-typ-todo.html +15 -15
  33. data/spec/html_examples/custom-typ-todo.org +24 -24
  34. data/spec/html_examples/entities.html +4 -4
  35. data/spec/html_examples/entities.org +11 -11
  36. data/spec/html_examples/escape-pre.html +6 -6
  37. data/spec/html_examples/escape-pre.org +6 -6
  38. data/spec/html_examples/export-exclude-only.html +13 -13
  39. data/spec/html_examples/export-exclude-only.org +81 -81
  40. data/spec/html_examples/export-keywords.html +4 -4
  41. data/spec/html_examples/export-keywords.org +18 -18
  42. data/spec/html_examples/export-tags.html +8 -8
  43. data/spec/html_examples/export-tags.org +82 -82
  44. data/spec/html_examples/export-title.html +2 -2
  45. data/spec/html_examples/export-title.org +4 -4
  46. data/spec/html_examples/html-literal.html +2 -2
  47. data/spec/html_examples/html-literal.org +6 -6
  48. data/spec/html_examples/inline-formatting.html +10 -10
  49. data/spec/html_examples/inline-formatting.org +17 -17
  50. data/spec/html_examples/link-features.html +8 -8
  51. data/spec/html_examples/link-features.org +19 -19
  52. data/spec/html_examples/lists.html +19 -19
  53. data/spec/html_examples/lists.org +36 -36
  54. data/spec/html_examples/metadata-comment.html +27 -27
  55. data/spec/html_examples/metadata-comment.org +30 -30
  56. data/spec/html_examples/only-list.html +5 -5
  57. data/spec/html_examples/only-list.org +3 -3
  58. data/spec/html_examples/only-table.html +6 -6
  59. data/spec/html_examples/only-table.org +5 -5
  60. data/spec/html_examples/skip-header.html +3 -3
  61. data/spec/html_examples/skip-header.org +28 -28
  62. data/spec/html_examples/skip-table.html +4 -4
  63. data/spec/html_examples/skip-table.org +19 -19
  64. data/spec/html_examples/tables.html +20 -20
  65. data/spec/html_examples/tables.org +26 -26
  66. data/spec/html_examples/text.html +2 -2
  67. data/spec/html_examples/text.org +16 -16
  68. data/spec/line_spec.rb +151 -151
  69. data/spec/output_buffer_spec.rb +19 -0
  70. data/spec/parser_spec.rb +152 -166
  71. data/spec/regexp_helper_spec.rb +57 -57
  72. data/spec/spec_helper.rb +21 -21
  73. data/spec/textile_examples/block_code.org +35 -35
  74. data/spec/textile_examples/block_code.textile +29 -29
  75. data/spec/textile_examples/blockquote.org +13 -13
  76. data/spec/textile_examples/blockquote.textile +11 -11
  77. data/spec/textile_examples/keywords.org +13 -13
  78. data/spec/textile_examples/keywords.textile +11 -11
  79. data/spec/textile_examples/links.org +11 -11
  80. data/spec/textile_examples/links.textile +10 -10
  81. data/spec/textile_examples/lists.org +36 -36
  82. data/spec/textile_examples/lists.textile +20 -20
  83. data/spec/textile_examples/single-space-plain-list.org +13 -13
  84. data/spec/textile_examples/single-space-plain-list.textile +10 -10
  85. data/spec/textile_examples/tables.org +26 -26
  86. data/spec/textile_examples/tables.textile +23 -23
  87. data/spec/textile_output_buffer_spec.rb +21 -21
  88. data/tasks/test_case.rake +49 -49
  89. metadata +3 -2
data/lib/org-ruby/line.rb CHANGED
@@ -1,260 +1,206 @@
1
- module Orgmode
2
-
3
- # Represents a single line of an orgmode file.
4
- class Line
5
-
6
- # This is the line itself.
7
- attr_reader :line
8
-
9
- # The indent level of this line. this is important to properly translate
10
- # nested lists from orgmode to textile.
11
- # TODO 2009-12-20 bdewey: Handle tabs
12
- attr_reader :indent
13
-
14
- # Backpointer to the parser that owns this line.
15
- attr_reader :parser
16
-
17
- # A line can have its type assigned instead of inferred from its
18
- # content. For example, something that parses as a "table" on its
19
- # own ("| one | two|\n") may just be a paragraph if it's inside
20
- # #+BEGIN_EXAMPLE. Set this property on the line to assign its
21
- # type. This will then affect the value of +paragraph_type+.
22
- attr_accessor :assigned_paragraph_type
23
-
24
- def initialize(line, parser = nil)
25
- @parser = parser
26
- @line = line
27
- @indent = 0
28
- @line =~ /\s*/
29
- @assigned_paragraph_type = nil
30
- @indent = $&.length unless blank?
31
- end
32
-
33
- def to_s
34
- return @line
35
- end
36
-
37
- # Tests if a line is a comment.
38
- def comment?
39
- check_assignment_or_regexp(:comment, /^\s*#/)
40
- end
41
-
42
- # Tests if a line contains metadata instead of actual content.
43
- def metadata?
44
- check_assignment_or_regexp(:metadata, /^\s*(CLOCK|DEADLINE|START|CLOSED|SCHEDULED):/)
45
- end
46
-
47
- def nonprinting?
48
- comment? || metadata?
49
- end
50
-
51
- def blank?
52
- check_assignment_or_regexp(:blank, /^\s*$/)
53
- end
54
-
55
- def plain_list?
56
- ordered_list? or unordered_list?
57
- end
58
-
59
- UnorderedListRegexp = /^\s*(-|\+)\s*/
60
-
61
- def unordered_list?
62
- check_assignment_or_regexp(:unordered_list, UnorderedListRegexp)
63
- end
64
-
65
- def strip_unordered_list_tag
66
- @line.sub(UnorderedListRegexp, "")
67
- end
68
-
69
- OrderedListRegexp = /^\s*\d+(\.|\))\s*/
70
-
71
- def ordered_list?
72
- check_assignment_or_regexp(:ordered_list, OrderedListRegexp)
73
- end
74
-
75
- def strip_ordered_list_tag
76
- @line.sub(OrderedListRegexp, "")
77
- end
78
-
79
- def plain_text?
80
- not metadata? and not blank? and not plain_list?
81
- end
82
-
83
- def table_row?
84
- # for an org-mode table, the first non-whitespace character is a
85
- # | (pipe).
86
- check_assignment_or_regexp(:table_row, /^\s*\|/)
87
- end
88
-
89
- def table_separator?
90
- # an org-mode table separator has the first non-whitespace
91
- # character as a | (pipe), then consists of nothing else other
92
- # than pipes, hyphens, and pluses.
93
-
94
- check_assignment_or_regexp(:table_separator, /^\s*\|[-\|\+]*\s*$/)
95
- end
96
-
97
- # Checks if this line is a table header.
98
- def table_header?
99
- @assigned_paragraph_type == :table_header
100
- end
101
-
102
- def table?
103
- table_row? or table_separator? or table_header?
104
- end
105
-
106
- BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)/
107
-
108
- def begin_block?
109
- @line =~ BlockRegexp && $1 == "BEGIN"
110
- end
111
-
112
- def end_block?
113
- @line =~ BlockRegexp && $1 == "END"
114
- end
115
-
116
- def block_type
117
- $2 if @line =~ BlockRegexp
118
- end
119
-
120
- def code_block_type?
121
- block_type =~ /^(EXAMPLE|SRC)$/
122
- end
123
-
124
- InlineExampleRegexp = /^\s*:/
125
-
126
- # Test if the line matches the "inline example" case:
127
- # the first character on the line is a colon.
128
- def inline_example?
129
- check_assignment_or_regexp(:inline_example, InlineExampleRegexp)
130
- end
131
-
132
- InBufferSettingRegexp = /^#\+(\w+):\s*(.*)$/
133
-
134
- # call-seq:
135
- # line.in_buffer_setting? => boolean
136
- # line.in_buffer_setting? { |key, value| ... }
137
- #
138
- # Called without a block, this method determines if the line
139
- # contains an in-buffer setting. Called with a block, the block
140
- # will get called if the line contains an in-buffer setting with
141
- # the key and value for the setting.
142
- def in_buffer_setting?
143
- return false if @assigned_paragraph_type && @assigned_paragraph_type != :comment
144
- if block_given? then
145
- if @line =~ InBufferSettingRegexp
146
- yield $1, $2
147
- end
148
- else
149
- @line =~ InBufferSettingRegexp
150
- end
151
- end
152
-
153
- # Determines the paragraph type of the current line.
154
- def paragraph_type
155
- return :blank if blank?
156
- return :ordered_list if ordered_list?
157
- return :unordered_list if unordered_list?
158
- return :metadata if metadata?
159
- return :comment if comment?
160
- return :table_separator if table_separator?
161
- return :table_row if table_row?
162
- return :table_header if table_header?
163
- return :inline_example if inline_example?
164
- return :paragraph
165
- end
166
-
167
- def self.to_textile(lines)
168
- output = ""
169
- output_buffer = TextileOutputBuffer.new(output)
170
- translate(lines, output_buffer)
171
- end
172
-
173
- def self.to_html(lines, opts = { })
174
- output = ""
175
- output_buffer = HtmlOutputBuffer.new(output, opts)
176
- translate(lines, output_buffer)
177
- end
178
-
179
- # Converts an array of lines to textile format.
180
- def self.translate(lines, output_buffer)
181
- lines.each do |line|
182
-
183
- # See if we're carrying paragraph payload, and output
184
- # it if we're about to switch to some other output type.
185
- output_buffer.prepare(line)
186
-
187
- case line.paragraph_type
188
- when :metadata, :table_separator, :blank
189
-
190
- output_buffer << line.line if output_buffer.preserve_whitespace?
191
-
192
- when :comment
193
-
194
- if line.begin_block?
195
- output_buffer.push_mode(:blockquote) if line.block_type == "QUOTE"
196
- output_buffer.push_mode(:src) if line.block_type == "SRC"
197
- output_buffer.push_mode(:example) if line.block_type == "EXAMPLE"
198
- elsif line.end_block?
199
- output_buffer.pop_mode(:blockquote) if line.block_type == "QUOTE"
200
- output_buffer.pop_mode(:src) if line.block_type == "SRC"
201
- output_buffer.pop_mode(:example) if line.block_type == "EXAMPLE"
202
- else
203
- output_buffer << line.line if output_buffer.preserve_whitespace?
204
- end
205
-
206
- when :table_row, :table_header
207
-
208
- output_buffer << line.line.lstrip
209
-
210
- when :ordered_list
211
-
212
- output_buffer << line.strip_ordered_list_tag << " "
213
-
214
- when :unordered_list
215
-
216
- output_buffer << line.strip_unordered_list_tag << " "
217
-
218
- when :inline_example
219
-
220
- output_buffer << line.line.sub(InlineExampleRegexp, "")
221
-
222
- when :paragraph
223
-
224
- if output_buffer.preserve_whitespace? then
225
- output_buffer << line.line
226
- else
227
- output_buffer << line.line.strip << " "
228
- end
229
- end
230
- end
231
- output_buffer.flush!
232
- output_buffer.pop_mode until output_buffer.current_mode == :normal
233
- output_buffer.output
234
- end
235
-
236
- ######################################################################
237
- private
238
-
239
- # This function is an internal helper for determining the paragraph
240
- # type of a line... for instance, if the line is a comment or contains
241
- # metadata. It's used in routines like blank?, plain_list?, etc.
242
- #
243
- # What's tricky is lines can have assigned types, so you need to check
244
- # the assigned type, if present, or see if the characteristic regexp
245
- # for the paragraph type matches if not present.
246
- #
247
- # call-seq:
248
- # check_assignment_or_regexp(assignment, regexp) => boolean
249
- #
250
- # assignment:: if the paragraph has an assigned type, it will be
251
- # checked to see if it equals +assignment+.
252
- # regexp:: If the paragraph does not have an assigned type,
253
- # the contents of the paragraph will be checked against
254
- # this regexp.
255
- def check_assignment_or_regexp(assignment, regexp)
256
- return @assigned_paragraph_type == assignment if @assigned_paragraph_type
257
- return @line =~ regexp
258
- end
259
- end # class Line
260
- end # module Orgmode
1
+ module Orgmode
2
+
3
+ # Represents a single line of an orgmode file.
4
+ class Line
5
+
6
+ # This is the line itself.
7
+ attr_reader :line
8
+
9
+ # The indent level of this line. this is important to properly translate
10
+ # nested lists from orgmode to textile.
11
+ # TODO 2009-12-20 bdewey: Handle tabs
12
+ attr_reader :indent
13
+
14
+ # Backpointer to the parser that owns this line.
15
+ attr_reader :parser
16
+
17
+ # A line can have its type assigned instead of inferred from its
18
+ # content. For example, something that parses as a "table" on its
19
+ # own ("| one | two|\n") may just be a paragraph if it's inside
20
+ # #+BEGIN_EXAMPLE. Set this property on the line to assign its
21
+ # type. This will then affect the value of +paragraph_type+.
22
+ attr_accessor :assigned_paragraph_type
23
+
24
+ def initialize(line, parser = nil)
25
+ @parser = parser
26
+ @line = line
27
+ @indent = 0
28
+ @line =~ /\s*/
29
+ @assigned_paragraph_type = nil
30
+ @indent = $&.length unless blank?
31
+ end
32
+
33
+ def to_s
34
+ return @line
35
+ end
36
+
37
+ # Tests if a line is a comment.
38
+ def comment?
39
+ check_assignment_or_regexp(:comment, /^\s*#/)
40
+ end
41
+
42
+ # Tests if a line contains metadata instead of actual content.
43
+ def metadata?
44
+ check_assignment_or_regexp(:metadata, /^\s*(CLOCK|DEADLINE|START|CLOSED|SCHEDULED):/)
45
+ end
46
+
47
+ def nonprinting?
48
+ comment? || metadata?
49
+ end
50
+
51
+ def blank?
52
+ check_assignment_or_regexp(:blank, /^\s*$/)
53
+ end
54
+
55
+ def plain_list?
56
+ ordered_list? or unordered_list?
57
+ end
58
+
59
+ UnorderedListRegexp = /^\s*(-|\+)\s*/
60
+
61
+ def unordered_list?
62
+ check_assignment_or_regexp(:unordered_list, UnorderedListRegexp)
63
+ end
64
+
65
+ def strip_unordered_list_tag
66
+ @line.sub(UnorderedListRegexp, "")
67
+ end
68
+
69
+ OrderedListRegexp = /^\s*\d+(\.|\))\s*/
70
+
71
+ def ordered_list?
72
+ check_assignment_or_regexp(:ordered_list, OrderedListRegexp)
73
+ end
74
+
75
+ def strip_ordered_list_tag
76
+ @line.sub(OrderedListRegexp, "")
77
+ end
78
+
79
+ # Extracts meaningful text and excludes org-mode markup,
80
+ # like identifiers for lists or headings.
81
+ def output_text
82
+ return strip_ordered_list_tag if ordered_list?
83
+ return strip_unordered_list_tag if unordered_list?
84
+ return @line.sub(InlineExampleRegexp, "") if inline_example?
85
+ return line
86
+ end
87
+
88
+ def plain_text?
89
+ not metadata? and not blank? and not plain_list?
90
+ end
91
+
92
+ def table_row?
93
+ # for an org-mode table, the first non-whitespace character is a
94
+ # | (pipe).
95
+ check_assignment_or_regexp(:table_row, /^\s*\|/)
96
+ end
97
+
98
+ def table_separator?
99
+ # an org-mode table separator has the first non-whitespace
100
+ # character as a | (pipe), then consists of nothing else other
101
+ # than pipes, hyphens, and pluses.
102
+
103
+ check_assignment_or_regexp(:table_separator, /^\s*\|[-\|\+]*\s*$/)
104
+ end
105
+
106
+ # Checks if this line is a table header.
107
+ def table_header?
108
+ @assigned_paragraph_type == :table_header
109
+ end
110
+
111
+ def table?
112
+ table_row? or table_separator? or table_header?
113
+ end
114
+
115
+ BlockRegexp = /^\s*#\+(BEGIN|END)_(\w*)/
116
+
117
+ def begin_block?
118
+ @line =~ BlockRegexp && $1 == "BEGIN"
119
+ end
120
+
121
+ def end_block?
122
+ @line =~ BlockRegexp && $1 == "END"
123
+ end
124
+
125
+ def block_type
126
+ $2 if @line =~ BlockRegexp
127
+ end
128
+
129
+ def code_block_type?
130
+ block_type =~ /^(EXAMPLE|SRC)$/
131
+ end
132
+
133
+ InlineExampleRegexp = /^\s*:/
134
+
135
+ # Test if the line matches the "inline example" case:
136
+ # the first character on the line is a colon.
137
+ def inline_example?
138
+ check_assignment_or_regexp(:inline_example, InlineExampleRegexp)
139
+ end
140
+
141
+ InBufferSettingRegexp = /^#\+(\w+):\s*(.*)$/
142
+
143
+ # call-seq:
144
+ # line.in_buffer_setting? => boolean
145
+ # line.in_buffer_setting? { |key, value| ... }
146
+ #
147
+ # Called without a block, this method determines if the line
148
+ # contains an in-buffer setting. Called with a block, the block
149
+ # will get called if the line contains an in-buffer setting with
150
+ # the key and value for the setting.
151
+ def in_buffer_setting?
152
+ return false if @assigned_paragraph_type && @assigned_paragraph_type != :comment
153
+ if block_given? then
154
+ if @line =~ InBufferSettingRegexp
155
+ yield $1, $2
156
+ end
157
+ else
158
+ @line =~ InBufferSettingRegexp
159
+ end
160
+ end
161
+
162
+ # Determines the paragraph type of the current line.
163
+ def paragraph_type
164
+ return :blank if blank?
165
+ return :ordered_list if ordered_list?
166
+ return :unordered_list if unordered_list?
167
+ return :metadata if metadata?
168
+ return :comment if comment?
169
+ return :table_separator if table_separator?
170
+ return :table_row if table_row?
171
+ return :table_header if table_header?
172
+ return :inline_example if inline_example?
173
+ return :paragraph
174
+ end
175
+
176
+ def self.to_textile(lines)
177
+ output = ""
178
+ output_buffer = TextileOutputBuffer.new(output)
179
+ Parser.translate(lines, output_buffer)
180
+ end
181
+
182
+ ######################################################################
183
+ private
184
+
185
+ # This function is an internal helper for determining the paragraph
186
+ # type of a line... for instance, if the line is a comment or contains
187
+ # metadata. It's used in routines like blank?, plain_list?, etc.
188
+ #
189
+ # What's tricky is lines can have assigned types, so you need to check
190
+ # the assigned type, if present, or see if the characteristic regexp
191
+ # for the paragraph type matches if not present.
192
+ #
193
+ # call-seq:
194
+ # check_assignment_or_regexp(assignment, regexp) => boolean
195
+ #
196
+ # assignment:: if the paragraph has an assigned type, it will be
197
+ # checked to see if it equals +assignment+.
198
+ # regexp:: If the paragraph does not have an assigned type,
199
+ # the contents of the paragraph will be checked against
200
+ # this regexp.
201
+ def check_assignment_or_regexp(assignment, regexp)
202
+ return @assigned_paragraph_type == assignment if @assigned_paragraph_type
203
+ return @line =~ regexp
204
+ end
205
+ end # class Line
206
+ end # module Orgmode