org-ruby 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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