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.
- 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
|