org_mode 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/Gemfile +26 -0
- data/README.mkd +30 -0
- data/Rakefile +1 -0
- data/bin/org-mode +32 -0
- data/features/cmdline_agenda.feature +34 -0
- data/features/cmdline_handles_errors_cracefully.feature +10 -0
- data/features/cmdline_noparams.feature +11 -0
- data/features/cmdline_todos.feature +5 -0
- data/features/steps.rb +35 -0
- data/features/support/env.rb +0 -0
- data/features/support/org_mode_script.rb +53 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/org_mode/commands/agenda.rb +39 -0
- data/lib/org_mode/commands/update.rb +4 -0
- data/lib/org_mode/commands.rb +7 -0
- data/lib/org_mode/loader.rb +17 -0
- data/lib/org_mode/parser.rb +137 -0
- data/lib/org_mode/reporters/agenda.rb +44 -0
- data/lib/org_mode/version.rb +3 -0
- data/lib/org_mode.rb +87 -0
- data/org_mode.gemspec +28 -0
- data/spec/data/org-file-01-simple-node-structure.org +12 -0
- data/spec/lib/org_mode/commands/agenda_spec.rb +55 -0
- data/spec/lib/org_mode/parser_spec.rb +323 -0
- data/spec/lib/org_mode/reporters/agenda_spec.rb +74 -0
- data/spec/lib/org_mode_spec.rb +52 -0
- data/spec/support/blueprints.rb +27 -0
- data/spec/support/capture_stdout.rb +12 -0
- data/spec/support/include_hash.rb +7 -0
- data/spec/support/write_into_tempfile.rb +6 -0
- metadata +166 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'org_mode/commands/agenda'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'core_ext/string'
|
4
|
+
require 'support/capture_stdout'
|
5
|
+
require 'support/write_into_tempfile'
|
6
|
+
require 'timecop'
|
7
|
+
|
8
|
+
# Helper to execute agenda and compare the output
|
9
|
+
def execute_and_compare_stdout_with args, options, expected_output
|
10
|
+
output = capture_stdout do
|
11
|
+
@org_mode_commands_agenda.execute(args, options)
|
12
|
+
end
|
13
|
+
output.should == expected_output
|
14
|
+
end
|
15
|
+
|
16
|
+
describe OrgMode::Commands::Agenda do
|
17
|
+
before do
|
18
|
+
Timecop.freeze('2012-01-01 15:00')
|
19
|
+
|
20
|
+
@org_mode_commands_agenda = OrgMode::Commands::Agenda.new
|
21
|
+
end
|
22
|
+
|
23
|
+
context '#execute' do
|
24
|
+
context 'when loaded with one file' do
|
25
|
+
it 'extracts and displays scheduled tasks correctly' do
|
26
|
+
org_file = write_into_tempfile <<-eos.strip_indent(10)
|
27
|
+
* TODO Scheduled task <1-1-2012 Wed 15:15>
|
28
|
+
eos
|
29
|
+
execute_and_compare_stdout_with [org_file.path], stub, <<-eos.strip_indent(10)
|
30
|
+
Agenda ()
|
31
|
+
2012-01-01
|
32
|
+
TODO Scheduled task
|
33
|
+
eos
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context 'when loaded with two files' do
|
37
|
+
it 'displays both in expected format and sorted correctly' do
|
38
|
+
org_file = write_into_tempfile <<-eos.strip_indent(10)
|
39
|
+
* TODO Scheduled task on the 5th <5-1-2012 Wed 15:15>
|
40
|
+
eos
|
41
|
+
org_file2 = write_into_tempfile <<-eos.strip_indent(10)
|
42
|
+
* TODO Scheduled task on the 1th <1-1-2012 Wed 15:15>
|
43
|
+
eos
|
44
|
+
execute_and_compare_stdout_with [org_file, org_file2].map(&:path), stub,
|
45
|
+
<<-eos.strip_indent(10)
|
46
|
+
Agenda ()
|
47
|
+
2012-01-01
|
48
|
+
TODO Scheduled task on the 1th
|
49
|
+
2012-01-05
|
50
|
+
TODO Scheduled task on the 5th
|
51
|
+
eos
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,323 @@
|
|
1
|
+
require 'org_mode'
|
2
|
+
require 'org_mode/parser'
|
3
|
+
|
4
|
+
# Parser
|
5
|
+
# ------
|
6
|
+
#
|
7
|
+
# Two way parser:
|
8
|
+
# First pass
|
9
|
+
# Find file settings
|
10
|
+
# Find all nodes
|
11
|
+
# Title and content tree structure
|
12
|
+
# Second pass
|
13
|
+
# Parse all nodes
|
14
|
+
# (using information from file, ak TODO keywords)
|
15
|
+
# Parse title
|
16
|
+
# Parse content
|
17
|
+
#
|
18
|
+
# Node
|
19
|
+
# Title
|
20
|
+
# TodoStateKeyword
|
21
|
+
# Date
|
22
|
+
# Content
|
23
|
+
# CodeBlockParser
|
24
|
+
# PlainTextParser
|
25
|
+
#
|
26
|
+
# Nodes
|
27
|
+
# SettingsNode
|
28
|
+
# settings_hash
|
29
|
+
# SettingsAttachment
|
30
|
+
# PlainTextNode
|
31
|
+
# content
|
32
|
+
# CodeBlockNode
|
33
|
+
# language
|
34
|
+
# content
|
35
|
+
|
36
|
+
|
37
|
+
# Private: Loads org example
|
38
|
+
#
|
39
|
+
# name - takes part of filename
|
40
|
+
#
|
41
|
+
# Returns the contents of the file
|
42
|
+
def load_org_example name
|
43
|
+
File.open("spec/data/org-file-#{name}.org").read
|
44
|
+
end
|
45
|
+
|
46
|
+
describe OrgMode::FileParser do
|
47
|
+
context ".parse_into_tokens" do
|
48
|
+
it "should pars only one" do
|
49
|
+
org_data = <<-org.gsub(/^\s{8}/,'')
|
50
|
+
* First
|
51
|
+
org
|
52
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
53
|
+
b.should be_empty
|
54
|
+
n.should == [["* First", ""]]
|
55
|
+
e.should be_empty
|
56
|
+
end
|
57
|
+
it "should pars only one without enter" do
|
58
|
+
org_data = "* First"
|
59
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
60
|
+
b.should be_empty
|
61
|
+
n.should == [["* First", ""]]
|
62
|
+
e.should be_empty
|
63
|
+
end
|
64
|
+
it "should divide data up correctly" do
|
65
|
+
org_data = <<-org.gsub(/^\s{8}/,'')
|
66
|
+
* First
|
67
|
+
** Second
|
68
|
+
org
|
69
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
70
|
+
b.should be_empty
|
71
|
+
n.should == [["* First", ""], ["** Second", ""]]
|
72
|
+
e.should be_empty
|
73
|
+
end
|
74
|
+
it "should handle nodes with content" do
|
75
|
+
org_data = <<-org.gsub(/^\s{8}/,'')
|
76
|
+
* First
|
77
|
+
Content for first node
|
78
|
+
** Second
|
79
|
+
Content for nested node
|
80
|
+
org
|
81
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
82
|
+
b.should be_empty
|
83
|
+
n.should == [["* First", " Content for first node"], ["** Second", " Content for nested node"]]
|
84
|
+
e.should be_empty
|
85
|
+
end
|
86
|
+
it "should handle content with no nodes" do
|
87
|
+
org_data = <<-org.gsub(/^\s{8}/,'')
|
88
|
+
Just some textfile without any nodes
|
89
|
+
org
|
90
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
91
|
+
b.should == 'Just some textfile without any nodes'
|
92
|
+
n.should == []
|
93
|
+
e.should be_empty
|
94
|
+
end
|
95
|
+
it "should take an empty string" do
|
96
|
+
org_data = <<-org.gsub(/^\s{8}/,'')
|
97
|
+
org
|
98
|
+
b,n,e = OrgMode::FileParser.parse_into_tokens(org_data)
|
99
|
+
b.should be_empty
|
100
|
+
n.should == []
|
101
|
+
e.should be_empty
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context ".parse" do
|
106
|
+
let(:org_data) { load_org_example '01-simple-node-structure' }
|
107
|
+
it "should just parse the file" do
|
108
|
+
parsed = OrgMode::FileParser.parse(org_data)
|
109
|
+
end
|
110
|
+
context 'with a parsed org_file' do
|
111
|
+
let(:org_file) { OrgMode::FileParser.parse(org_data) }
|
112
|
+
|
113
|
+
it "should return an OrgMode::File" do
|
114
|
+
org_file.should be_an_instance_of( OrgMode::File )
|
115
|
+
end
|
116
|
+
|
117
|
+
it "parses the tree correctly" do
|
118
|
+
org_file.nodes.length.should == 12
|
119
|
+
end
|
120
|
+
|
121
|
+
it "has an empty beginning" do
|
122
|
+
org_file.header.should be_empty
|
123
|
+
end
|
124
|
+
it "has an empty ending" do
|
125
|
+
org_file.footer.should be_empty
|
126
|
+
end
|
127
|
+
context 'parent_child relations' do
|
128
|
+
it "root node has no parent" do
|
129
|
+
org_file.nodes[0].parent.should be_nil
|
130
|
+
end
|
131
|
+
it "root node has 2 children" do
|
132
|
+
org_file.nodes[0].children.length.should == 2
|
133
|
+
org_file.nodes[0].children[0].title.should == 'FirstChildMain'
|
134
|
+
org_file.nodes[0].children[1].title.should == 'SecondChildMain'
|
135
|
+
end
|
136
|
+
it "ThirdMain should be in business" do
|
137
|
+
org_file.nodes[8].children[0].children[0].children[0].title.should ==
|
138
|
+
'FirstChildFirstChildFirstChildMain'
|
139
|
+
end
|
140
|
+
it "destilled the correct root nodes" do
|
141
|
+
org_file.root_nodes.map(&:title).should == %w[Main SecondMain ThirdMain]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe OrgMode::NodeParser do
|
149
|
+
context ".parse" do
|
150
|
+
context "title" do
|
151
|
+
context "standard node title" do
|
152
|
+
let(:node) {OrgMode::NodeParser.parse('** Standard node title', nil)}
|
153
|
+
it "parses the title correctly" do
|
154
|
+
node.title.should == 'Standard node title'
|
155
|
+
end
|
156
|
+
it "determines the correct stars" do
|
157
|
+
node.stars.should == 2
|
158
|
+
end
|
159
|
+
it "determines the correct indent" do
|
160
|
+
node.indent.should == 3
|
161
|
+
end
|
162
|
+
end
|
163
|
+
context "level deeper node title" do
|
164
|
+
let(:node) {OrgMode::NodeParser.parse('*** Standard node title one level deeper', nil)}
|
165
|
+
it "parses the title correctly" do
|
166
|
+
node.title.should == 'Standard node title one level deeper'
|
167
|
+
end
|
168
|
+
it "determines the correct stars" do
|
169
|
+
node.stars.should == 3
|
170
|
+
end
|
171
|
+
it "determines the correct indent" do
|
172
|
+
node.indent.should == 4
|
173
|
+
end
|
174
|
+
end
|
175
|
+
context "node title with date" do
|
176
|
+
let(:node) {OrgMode::NodeParser.parse('** Date node title <2012-02-02 Wed>', nil) }
|
177
|
+
it "parses the date from the title correcty" do
|
178
|
+
node.date.strftime('%Y-%m-%d').should == '2012-02-02'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
context "node title with date time" do
|
182
|
+
let(:node) {OrgMode::NodeParser.parse('** Date node title <2012-02-03 Wed 15:15>', nil)}
|
183
|
+
it "parses the date-time from the title correcty" do
|
184
|
+
node.date.strftime('%Y-%m-%d %H:%M').should == '2012-02-03 15:15'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
context "node title with date-range" do
|
188
|
+
let(:node) {OrgMode::NodeParser.parse('** Date node title <2012-02-03 Wed 15:15-16:15>', nil)}
|
189
|
+
it "parses the date from the title correcty" do
|
190
|
+
node.date.strftime('%Y-%m-%d %H:%M').should == '2012-02-03 15:15'
|
191
|
+
end
|
192
|
+
it "parses the start_tiem correctly" do
|
193
|
+
node.date_start_time.strftime('%Y-%m-%d %H:%M').should == '2012-02-03 15:15'
|
194
|
+
end
|
195
|
+
it "parses the end_time correctly" do
|
196
|
+
node.date_end_time.strftime('%Y-%m-%d %H:%M').should == '2012-02-03 16:15'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
context "parses TODO states correctly" do
|
200
|
+
let(:node) {OrgMode::NodeParser.parse('** TODO Date node title', nil)}
|
201
|
+
it "parses the TODO keyword correctly" do
|
202
|
+
node.todo_state.should == 'TODO'
|
203
|
+
end
|
204
|
+
context "parses DONE state correctly" do
|
205
|
+
let(:node) {OrgMode::NodeParser.parse('** DONE Date node title', nil)}
|
206
|
+
it "parses the TODO keyword correctly" do
|
207
|
+
node.todo_state.should == 'DONE'
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
context "content indentation" do
|
213
|
+
context "correctly indented" do
|
214
|
+
before do
|
215
|
+
org_title, *org_content = <<-eos.gsub(/^\s{10}/,'').lines.to_a
|
216
|
+
*** Title
|
217
|
+
Content belonging
|
218
|
+
at a certain indent
|
219
|
+
should be parsed correctly
|
220
|
+
eos
|
221
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
222
|
+
end
|
223
|
+
it "parses content and removes indent" do
|
224
|
+
@node.content.should == <<-eos.gsub(/^\s{10}/,'')
|
225
|
+
Content belonging
|
226
|
+
at a certain indent
|
227
|
+
should be parsed correctly
|
228
|
+
eos
|
229
|
+
end
|
230
|
+
end
|
231
|
+
context "too far" do
|
232
|
+
before do
|
233
|
+
org_title, *org_content = <<-eos.gsub(/^\s{10}/,'').lines.to_a
|
234
|
+
*** Title
|
235
|
+
Content belonging
|
236
|
+
at a certain indent
|
237
|
+
should be parsed correctly
|
238
|
+
eos
|
239
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
240
|
+
end
|
241
|
+
it "parses content and removes indent" do
|
242
|
+
@node.content.should == <<-eos.gsub(/^\s{10}/,'')
|
243
|
+
Content belonging
|
244
|
+
at a certain indent
|
245
|
+
should be parsed correctly
|
246
|
+
eos
|
247
|
+
end
|
248
|
+
end
|
249
|
+
context "indented in content block" do
|
250
|
+
before do
|
251
|
+
org_title, *org_content = <<-eos.gsub(/^\s{10}/,'').lines.to_a
|
252
|
+
*** Title
|
253
|
+
Content belonging
|
254
|
+
at a certain indent
|
255
|
+
should be parsed correctly
|
256
|
+
eos
|
257
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
258
|
+
end
|
259
|
+
it "parses content and removes indent" do
|
260
|
+
@node.content.should == <<-eos.gsub(/^\s{10}/,'')
|
261
|
+
Content belonging
|
262
|
+
at a certain indent
|
263
|
+
should be parsed correctly
|
264
|
+
eos
|
265
|
+
end
|
266
|
+
end
|
267
|
+
context "one row outdented" do
|
268
|
+
before do
|
269
|
+
org_title, *org_content = <<-eos.gsub(/^\s{10}/,'').lines.to_a
|
270
|
+
*** Title
|
271
|
+
Content belonging
|
272
|
+
at a certain indent
|
273
|
+
should be parsed correctly
|
274
|
+
eos
|
275
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
276
|
+
end
|
277
|
+
it "parses content and removes indent" do
|
278
|
+
@node.content.should == <<-eos.gsub(/^\s{10}/,'')
|
279
|
+
Content belonging
|
280
|
+
at a certain indent
|
281
|
+
should be parsed correctly
|
282
|
+
eos
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
context "content whitespace" do
|
287
|
+
it "removes whitespace at beginning" do
|
288
|
+
org_title, *org_content = <<-eos.gsub(/^\s{8}/,'').lines.to_a
|
289
|
+
*** Title
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
Content belonging
|
294
|
+
at a certain indent
|
295
|
+
should be parsed correctly
|
296
|
+
eos
|
297
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
298
|
+
@node.content.should == <<-eos.gsub(/^\s{8}/,'')
|
299
|
+
Content belonging
|
300
|
+
at a certain indent
|
301
|
+
should be parsed correctly
|
302
|
+
eos
|
303
|
+
end
|
304
|
+
it "removes whitespace at ending" do
|
305
|
+
org_title, *org_content = <<-eos.gsub(/^\s{8}/,'').lines.to_a
|
306
|
+
*** Title
|
307
|
+
Content belonging
|
308
|
+
at a certain indent
|
309
|
+
should be parsed correctly
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
eos
|
314
|
+
@node = OrgMode::NodeParser.parse(org_title, org_content.join)
|
315
|
+
@node.content.should == <<-eos.gsub(/^\s{8}/,'')
|
316
|
+
Content belonging
|
317
|
+
at a certain indent
|
318
|
+
should be parsed correctly
|
319
|
+
eos
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'org_mode/reporters/agenda'
|
2
|
+
require 'support/blueprints'
|
3
|
+
require 'support/include_hash'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
describe OrgMode::Reporters::Agenda do
|
7
|
+
before do
|
8
|
+
Timecop.freeze('2012-02-02')
|
9
|
+
end
|
10
|
+
let(:file_collection) do
|
11
|
+
nodes = []
|
12
|
+
files = []
|
13
|
+
nodes << OrgMode::Node.make(:stars => 1, :date=>Date.parse('2012-02-01'))
|
14
|
+
nodes << OrgMode::Node.make(:stars => 2, :date=>Date.parse('2012-02-05'))
|
15
|
+
files << OrgMode::File.make(:nodes => nodes)
|
16
|
+
nodes = []
|
17
|
+
nodes << OrgMode::Node.make(:stars => 1,
|
18
|
+
:todo_state => 'DONE',
|
19
|
+
:date => Date.parse('2012-06-01'))
|
20
|
+
nodes << OrgMode::Node.make(:stars => 2, :date=>Date.parse('2012-02-03'))
|
21
|
+
nodes << OrgMode::Node.make(:stars => 3, :date=>DateTime.parse('2012-02-01 15:00'))
|
22
|
+
files << OrgMode::File.make(:nodes => nodes)
|
23
|
+
OrgMode::FileCollection.make(:files => files)
|
24
|
+
end
|
25
|
+
let(:reporter) { OrgMode::Reporters::Agenda.new(file_collection) }
|
26
|
+
|
27
|
+
context '#open_nodes_grouped_by_day' do
|
28
|
+
|
29
|
+
let (:reported) { reporter.open_nodes_grouped_by_day }
|
30
|
+
|
31
|
+
it "extracts the correct dates and in the correct order" do
|
32
|
+
dates = reported.map {|e| e[:date] }
|
33
|
+
dates.should == ["2012-02-01", "2012-02-03", "2012-02-05"]
|
34
|
+
end
|
35
|
+
it "should group the nodecounts correctly" do
|
36
|
+
nodecount_per_date = reported.map { |e| [e[:date], e[:nodes].length] }
|
37
|
+
nodecount_per_date.should == [["2012-02-01", 2], ["2012-02-03", 1], ["2012-02-05", 1]]
|
38
|
+
end
|
39
|
+
it "should result in the following subhashes" do
|
40
|
+
reported.should ==
|
41
|
+
[{:date=>"2012-02-01",
|
42
|
+
:nodes=>
|
43
|
+
[{:title=>"org-node",
|
44
|
+
:content=>"org-node content",
|
45
|
+
:todo_state=>"TODO",
|
46
|
+
:date=>"2012-02-01 00:00",
|
47
|
+
:stars=>1},
|
48
|
+
{:title=>"org-node",
|
49
|
+
:content=>"org-node content",
|
50
|
+
:todo_state=>"TODO",
|
51
|
+
:date=>"2012-02-01 15:00",
|
52
|
+
:stars=>3}]},
|
53
|
+
{:date=>"2012-02-03",
|
54
|
+
:nodes=>
|
55
|
+
[{:title=>"org-node",
|
56
|
+
:content=>"org-node content",
|
57
|
+
:todo_state=>"TODO",
|
58
|
+
:date=>"2012-02-03 00:00",
|
59
|
+
:stars=>2}]},
|
60
|
+
{:date=>"2012-02-05",
|
61
|
+
:nodes=>
|
62
|
+
[{:title=>"org-node",
|
63
|
+
:content=>"org-node content",
|
64
|
+
:todo_state=>"TODO",
|
65
|
+
:date=>"2012-02-05 00:00",
|
66
|
+
:stars=>2}]}]
|
67
|
+
end
|
68
|
+
it "it ignores the DONE task" do
|
69
|
+
dates = reported.map {|e| e[:date] }
|
70
|
+
dates.should_not include("2012-06-01")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'org_mode'
|
2
|
+
require 'support/blueprints'
|
3
|
+
|
4
|
+
describe OrgMode::File do
|
5
|
+
let(:file) do
|
6
|
+
nodes = []
|
7
|
+
files = []
|
8
|
+
nodes << OrgMode::Node.make(:stars => 1)
|
9
|
+
nodes << OrgMode::Node.make(:stars => 2, :date=>Time.now)
|
10
|
+
nodes << OrgMode::Node.make(:stars => 3)
|
11
|
+
nodes << OrgMode::Node.make(:stars => 1)
|
12
|
+
OrgMode::File.make(:nodes => nodes)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "accumulates correctly" do
|
16
|
+
file.nodes.length.should == 4
|
17
|
+
end
|
18
|
+
|
19
|
+
it "detects all rootnodes correctly" do
|
20
|
+
file.root_nodes.length.should == 2
|
21
|
+
end
|
22
|
+
|
23
|
+
it "detects all scheduled nodes correctly" do
|
24
|
+
file.scheduled_nodes.length.should == 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe OrgMode::FileCollection do
|
29
|
+
let(:file_collection) do
|
30
|
+
nodes = []
|
31
|
+
files = []
|
32
|
+
nodes << OrgMode::Node.make(:stars => 1)
|
33
|
+
nodes << OrgMode::Node.make(:stars => 2)
|
34
|
+
files << OrgMode::File.make(:nodes => nodes)
|
35
|
+
nodes = []
|
36
|
+
nodes << OrgMode::Node.make(:stars => 1)
|
37
|
+
nodes << OrgMode::Node.make(:stars => 2, :date=>Time.now)
|
38
|
+
nodes << OrgMode::Node.make(:stars => 3)
|
39
|
+
files << OrgMode::File.make(:nodes => nodes)
|
40
|
+
OrgMode::FileCollection.make(:files => files)
|
41
|
+
end
|
42
|
+
it "accumulates correctly" do
|
43
|
+
file_collection.nodes.length.should == 5
|
44
|
+
end
|
45
|
+
|
46
|
+
it "detects all rootnodes correctly" do
|
47
|
+
file_collection.root_nodes.length.should == 2
|
48
|
+
end
|
49
|
+
it "detects all scheduled nodes correctly" do
|
50
|
+
file_collection.scheduled_nodes.length.should == 1
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'org_mode'
|
2
|
+
|
3
|
+
class OrgMode::Node
|
4
|
+
def self.make(attrs={})
|
5
|
+
self.new.tap do |n|
|
6
|
+
n.title = attrs[:title] || "org-node"
|
7
|
+
n.stars = attrs[:stars] || rand(4)
|
8
|
+
n.content = attrs[:content] || "org-node content"
|
9
|
+
n.date = attrs[:date]
|
10
|
+
n.todo_state = attrs[:todo_state] || 'TODO'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class OrgMode::File
|
16
|
+
def self.make(attrs={})
|
17
|
+
nodes = attrs[:nodes] || Array.new(2) { OrgMode::Node.make }
|
18
|
+
self.new("aheader", nodes , "afooter")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class OrgMode::FileCollection
|
23
|
+
def self.make(attrs={})
|
24
|
+
files = attrs[:files] || Array.new(2) { OrgMode::File.make }
|
25
|
+
self.new( files )
|
26
|
+
end
|
27
|
+
end
|