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.
- data/History.txt +81 -77
- data/README.rdoc +66 -66
- data/Rakefile +28 -28
- data/bin/org-ruby +40 -40
- data/lib/org-ruby.rb +50 -50
- data/lib/org-ruby/headline.rb +102 -120
- data/lib/org-ruby/html_output_buffer.rb +174 -156
- data/lib/org-ruby/line.rb +206 -260
- data/lib/org-ruby/output_buffer.rb +227 -191
- data/lib/org-ruby/parser.rb +320 -272
- data/lib/org-ruby/regexp_helper.rb +156 -156
- data/lib/org-ruby/textile_output_buffer.rb +67 -68
- data/spec/data/freeform-example.org +113 -113
- data/spec/data/freeform.org +111 -111
- data/spec/data/hyp-planning.org +335 -335
- data/spec/data/remember.org +53 -53
- data/spec/headline_spec.rb +55 -55
- data/spec/html_examples/advanced-code.html +36 -36
- data/spec/html_examples/advanced-code.org +53 -53
- data/spec/html_examples/advanced-lists.html +31 -31
- data/spec/html_examples/advanced-lists.org +31 -31
- data/spec/html_examples/block_code.html +28 -28
- data/spec/html_examples/block_code.org +35 -35
- data/spec/html_examples/blockquote.html +7 -7
- data/spec/html_examples/blockquote.org +13 -13
- data/spec/html_examples/code-comment.html +18 -18
- data/spec/html_examples/code-comment.org +22 -22
- data/spec/html_examples/custom-seq-todo.html +15 -15
- data/spec/html_examples/custom-seq-todo.org +24 -24
- data/spec/html_examples/custom-todo.html +15 -15
- data/spec/html_examples/custom-todo.org +24 -24
- data/spec/html_examples/custom-typ-todo.html +15 -15
- data/spec/html_examples/custom-typ-todo.org +24 -24
- data/spec/html_examples/entities.html +4 -4
- data/spec/html_examples/entities.org +11 -11
- data/spec/html_examples/escape-pre.html +6 -6
- data/spec/html_examples/escape-pre.org +6 -6
- data/spec/html_examples/export-exclude-only.html +13 -13
- data/spec/html_examples/export-exclude-only.org +81 -81
- data/spec/html_examples/export-keywords.html +4 -4
- data/spec/html_examples/export-keywords.org +18 -18
- data/spec/html_examples/export-tags.html +8 -8
- data/spec/html_examples/export-tags.org +82 -82
- data/spec/html_examples/export-title.html +2 -2
- data/spec/html_examples/export-title.org +4 -4
- data/spec/html_examples/html-literal.html +2 -2
- data/spec/html_examples/html-literal.org +6 -6
- data/spec/html_examples/inline-formatting.html +10 -10
- data/spec/html_examples/inline-formatting.org +17 -17
- data/spec/html_examples/link-features.html +8 -8
- data/spec/html_examples/link-features.org +19 -19
- data/spec/html_examples/lists.html +19 -19
- data/spec/html_examples/lists.org +36 -36
- data/spec/html_examples/metadata-comment.html +27 -27
- data/spec/html_examples/metadata-comment.org +30 -30
- data/spec/html_examples/only-list.html +5 -5
- data/spec/html_examples/only-list.org +3 -3
- data/spec/html_examples/only-table.html +6 -6
- data/spec/html_examples/only-table.org +5 -5
- data/spec/html_examples/skip-header.html +3 -3
- data/spec/html_examples/skip-header.org +28 -28
- data/spec/html_examples/skip-table.html +4 -4
- data/spec/html_examples/skip-table.org +19 -19
- data/spec/html_examples/tables.html +20 -20
- data/spec/html_examples/tables.org +26 -26
- data/spec/html_examples/text.html +2 -2
- data/spec/html_examples/text.org +16 -16
- data/spec/line_spec.rb +151 -151
- data/spec/output_buffer_spec.rb +19 -0
- data/spec/parser_spec.rb +152 -166
- data/spec/regexp_helper_spec.rb +57 -57
- data/spec/spec_helper.rb +21 -21
- data/spec/textile_examples/block_code.org +35 -35
- data/spec/textile_examples/block_code.textile +29 -29
- data/spec/textile_examples/blockquote.org +13 -13
- data/spec/textile_examples/blockquote.textile +11 -11
- data/spec/textile_examples/keywords.org +13 -13
- data/spec/textile_examples/keywords.textile +11 -11
- data/spec/textile_examples/links.org +11 -11
- data/spec/textile_examples/links.textile +10 -10
- data/spec/textile_examples/lists.org +36 -36
- data/spec/textile_examples/lists.textile +20 -20
- data/spec/textile_examples/single-space-plain-list.org +13 -13
- data/spec/textile_examples/single-space-plain-list.textile +10 -10
- data/spec/textile_examples/tables.org +26 -26
- data/spec/textile_examples/tables.textile +23 -23
- data/spec/textile_output_buffer_spec.rb +21 -21
- data/tasks/test_case.rake +49 -49
- 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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
return :
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
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
|