devver-germinate 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/.gitignore +2 -0
  2. data/History.txt +4 -0
  3. data/README.rdoc +132 -0
  4. data/Rakefile +43 -0
  5. data/bin/germ +133 -0
  6. data/cucumber.yml +2 -0
  7. data/examples/basic.rb +118 -0
  8. data/examples/short.rb +17 -0
  9. data/features/author-formats-article.feature +108 -0
  10. data/features/author-lists-info.feature +45 -0
  11. data/features/author-publishes-article-source.feature +5 -0
  12. data/features/author-publishes-article.feature +5 -0
  13. data/features/author-republishes-article.feature +5 -0
  14. data/features/author-selects-hunks.feature +26 -0
  15. data/features/author-updates-article-source.feature +5 -0
  16. data/features/author-views-stuff.feature +48 -0
  17. data/features/bin/quoter +6 -0
  18. data/features/bin/sorter +4 -0
  19. data/features/example_articles/code_samples.rb +89 -0
  20. data/features/example_articles/escaping.txt +12 -0
  21. data/features/example_articles/hello.rb +9 -0
  22. data/features/example_articles/pipelines.txt +25 -0
  23. data/features/example_articles/regexen.rb +24 -0
  24. data/features/example_articles/sample_offsets.rb +18 -0
  25. data/features/example_articles/specials.rb +19 -0
  26. data/features/example_articles/wrapping.rb +8 -0
  27. data/features/example_output/code_samples.txt +186 -0
  28. data/features/example_output/escaping.out +5 -0
  29. data/features/example_output/hello.txt +1 -0
  30. data/features/example_output/pipelines.out +28 -0
  31. data/features/example_output/regexen.txt +22 -0
  32. data/features/example_output/sample_offsets.txt +15 -0
  33. data/features/example_output/specials.txt +36 -0
  34. data/features/example_output/wrapping.txt +3 -0
  35. data/features/step_definitions/germinate.rb +30 -0
  36. data/features/support/env.rb +18 -0
  37. data/germinate.gemspec +55 -0
  38. data/lib/germinate.rb +54 -0
  39. data/lib/germinate/application.rb +62 -0
  40. data/lib/germinate/article_editor.rb +20 -0
  41. data/lib/germinate/article_formatter.rb +75 -0
  42. data/lib/germinate/formatter.rb +119 -0
  43. data/lib/germinate/hunk.rb +149 -0
  44. data/lib/germinate/implicit_insertion.rb +9 -0
  45. data/lib/germinate/insertion.rb +15 -0
  46. data/lib/germinate/librarian.rb +179 -0
  47. data/lib/germinate/pipeline.rb +11 -0
  48. data/lib/germinate/process.rb +67 -0
  49. data/lib/germinate/reader.rb +212 -0
  50. data/lib/germinate/selector.rb +95 -0
  51. data/lib/germinate/shared_style_attributes.rb +23 -0
  52. data/lib/germinate/text_transforms.rb +90 -0
  53. data/spec/germinate/application_spec.rb +14 -0
  54. data/spec/germinate/article_editor_spec.rb +97 -0
  55. data/spec/germinate/article_formatter_spec.rb +153 -0
  56. data/spec/germinate/code_hunk_spec.rb +45 -0
  57. data/spec/germinate/formatter_spec.rb +160 -0
  58. data/spec/germinate/hunk_spec.rb +77 -0
  59. data/spec/germinate/implicit_insertion_spec.rb +33 -0
  60. data/spec/germinate/insertion_spec.rb +18 -0
  61. data/spec/germinate/librarian_spec.rb +336 -0
  62. data/spec/germinate/pipeline_spec.rb +24 -0
  63. data/spec/germinate/process_spec.rb +64 -0
  64. data/spec/germinate/reader_spec.rb +306 -0
  65. data/spec/germinate/selector_spec.rb +65 -0
  66. data/spec/germinate/text_hunk_spec.rb +53 -0
  67. data/spec/germinate/text_transforms_spec.rb +154 -0
  68. data/spec/germinate_spec.rb +8 -0
  69. data/spec/spec.opts +1 -0
  70. data/spec/spec_helper.rb +16 -0
  71. data/tasks/ann.rake +80 -0
  72. data/tasks/bones.rake +20 -0
  73. data/tasks/cucumber.rake +5 -0
  74. data/tasks/gem.rake +201 -0
  75. data/tasks/git.rake +40 -0
  76. data/tasks/notes.rake +27 -0
  77. data/tasks/post_load.rake +34 -0
  78. data/tasks/rdoc.rake +51 -0
  79. data/tasks/rubyforge.rake +55 -0
  80. data/tasks/setup.rb +292 -0
  81. data/tasks/spec.rake +54 -0
  82. data/tasks/svn.rake +47 -0
  83. data/tasks/test.rake +40 -0
  84. data/tasks/zentest.rake +36 -0
  85. data/test/test_germinate.rb +0 -0
  86. metadata +209 -0
@@ -0,0 +1,24 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Pipeline, "given a set of processes" do
6
+ before :each do
7
+ @intput = stub("Input")
8
+ @output1 = stub("Output 1")
9
+ @output2 = stub("Output 2")
10
+ @output3 = stub("Output 3")
11
+ @process1 = stub("Process 1", :call => @output1)
12
+ @process2 = stub("Process 2", :call => @output2)
13
+ @process3 = stub("Process 3", :call => @output3)
14
+ @it = Germinate::Pipeline.new([@process1, @process2, @process3])
15
+ end
16
+
17
+ it "should compose the processes into a pipeline" do
18
+ @process1.should_receive(:call).with(@input).and_return(@output1)
19
+ @process2.should_receive(:call).with(@output1).and_return(@output2)
20
+ @process3.should_receive(:call).with(@output2).and_return(@output3)
21
+ @it.call(@input).should == @output3
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Process do
6
+ before :each do
7
+ @input = Germinate::Hunk.new(
8
+ ["line 1\n", "line 2\n"],
9
+ :comment_prefix => "//")
10
+ @output = ["1 enil\n", "2 enil\n"]
11
+ @command = stub("Command", :readlines => @output).as_null_object
12
+ IO.stub!(:popen).and_yield(@command)
13
+ end
14
+
15
+ context "given a command 'mycommand'" do
16
+ before :each do
17
+ @it = Germinate::Process.new("myproc", "mycommand")
18
+ end
19
+
20
+ context "when called on a hunk of text" do
21
+ it "should pipe the input through the command" do
22
+ @command.should_receive(:<<).with("line 1\n").ordered
23
+ @command.should_receive(:<<).with("line 2\n").ordered
24
+ @command.should_receive(:close_write).ordered
25
+ @command.should_receive(:readlines).ordered.
26
+ and_return(["a\n", "b\n"])
27
+ IO.should_receive(:popen).with("mycommand", "r+").and_yield(@command)
28
+ output = @it.call(@input)
29
+ output.should == ["a\n", "b\n"]
30
+ end
31
+
32
+ it "should preserve hunk attributes" do
33
+ output = @it.call(@input)
34
+ output.comment_prefix.should == "//"
35
+ end
36
+ end
37
+ end
38
+
39
+ context "given a command 'mycommand %f' and called on some text" do
40
+ before :each do
41
+ @it = Germinate::Process.new("myproc", "mycommand %f")
42
+ end
43
+
44
+ it "should create a temporary file and pass the name to the command" do
45
+ @tempfile = stub("Temp File", :path => "TEMP_PATH")
46
+ Tempfile.should_receive(:open).with("germinate_hunk").and_yield(@tempfile)
47
+ @tempfile.should_receive(:<<).with("line 1\n").ordered
48
+ @tempfile.should_receive(:<<).with("line 2\n").ordered
49
+ @tempfile.should_receive(:close).ordered
50
+ IO.should_receive(:popen).
51
+ with("mycommand 'TEMP_PATH'", "r").
52
+ and_yield(@command)
53
+
54
+ @it.call(@input).should == @output
55
+ end
56
+
57
+ it "should preserve hunk attributes" do
58
+ output = @it.call(@input)
59
+ output.comment_prefix.should == "//"
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,306 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Reader do
6
+ before :each do
7
+ @librarian = stub("Librarian", :comment_prefix_known? => false).
8
+ as_null_object
9
+ @it = Reader.new(@librarian)
10
+ end
11
+
12
+ it "should start in the :initial state" do
13
+ @it.state.should == :initial
14
+ end
15
+
16
+ it "should start out with a section count of 0" do
17
+ @it.section_count.should == 0
18
+ end
19
+
20
+ it "should start out with current section SECTION0" do
21
+ @it.current_section.should == "SECTION0"
22
+ end
23
+
24
+ context "when section count is incremented" do
25
+
26
+ before :each do
27
+ @it.increment_section_count!
28
+ end
29
+
30
+ it "should increment section count by one" do
31
+ @it.section_count.should == 1
32
+ end
33
+
34
+ it "should update current section" do
35
+ @it.current_section.should == "SECTION1"
36
+ end
37
+
38
+ end
39
+
40
+ CONTROL_LINES = [
41
+ # Line Comment Args
42
+ [":TEXT:\n", nil, []],
43
+ ["# :CUT: \n", "#", []],
44
+ [" ; :TEXT: foo\n", ";", ["foo"]],
45
+ ["//:SAMPLE:\n", "//", []],
46
+ ["$>:END: ", "$>", []],
47
+ [":SAMPLE: bar, { a: 1, b: 2 }", nil, ["bar", {"a"=>1, "b"=>2}]],
48
+ [':BRACKET_CODE:', nil, []],
49
+ [':INSERT: @sel', nil, ["@sel"]],
50
+ [':PROCESS: foo, bar', nil, ["foo", "bar"]],
51
+ ]
52
+
53
+ CONTROL_LINES.each do |(line, comment, args)|
54
+ context "when given the line #{line}" do
55
+ if comment
56
+ it "should set the comment character to '#{comment}'" do
57
+ @librarian.should_receive(:comment_prefix=).with(comment)
58
+ @it << line
59
+ end
60
+ else
61
+ it "should not set a comment prefix" do
62
+ @librarian.should_not_receive(:comment_prefix=)
63
+ @it << line
64
+ end
65
+ end
66
+
67
+ it "should store the line as a control line" do
68
+ @librarian.should_receive(:add_control!).with(line)
69
+ @it << line
70
+ end
71
+ end
72
+ end
73
+
74
+ context "given a BRACKET_CODE control line" do
75
+ before :each do
76
+ @line = ':BRACKET_CODE: "<<<", ">>>"'
77
+ end
78
+
79
+ it "should store the brackets" do
80
+ @librarian.should_receive(:code_open_bracket=).with("<<<")
81
+ @librarian.should_receive(:code_close_bracket=).with(">>>")
82
+ @it << @line
83
+ end
84
+
85
+ end
86
+
87
+ context "before the first line of text" do
88
+ it "should treat non-keyword lines as front matter" do
89
+ @librarian.should_receive(:add_front_matter!, "TEST")
90
+ @it << "TEST"
91
+ end
92
+ end
93
+
94
+ context "after an initial line of text" do
95
+ before :each do
96
+ @it << "\n"
97
+ end
98
+
99
+ it "should be in the :front_matter state" do
100
+ @it.state.should == :front_matter
101
+ end
102
+
103
+ it "should record non-keyword lines as more front matter" do
104
+ @librarian.should_receive(:add_front_matter!, "TEST")
105
+ @it << "TEST"
106
+ end
107
+ end
108
+
109
+ context "after the :TEXT: keyword" do
110
+ before :each do
111
+ @it << ":TEXT:\n"
112
+ end
113
+
114
+ it "should be in the :text state" do
115
+ @it.state.should == :text
116
+ end
117
+
118
+ it "should place following text lines into a section" do
119
+ @librarian.should_receive(:add_text!).with("SECTION1", "blah blah blah")
120
+ @it << "blah blah blah"
121
+ end
122
+
123
+ context "given an escaped directive" do
124
+ it "should add the directive line as text" do
125
+ @librarian.should_receive(:add_text!).with("SECTION1", ":TEXT: abc")
126
+ @it << "\\:TEXT: abc"
127
+ end
128
+ end
129
+ end
130
+
131
+ context "after two anonymous :TEXT: sections" do
132
+ before :each do
133
+ @it << ":TEXT:\n"
134
+ @it << ":TEXT:\n"
135
+ end
136
+
137
+ it "should be in SECTION2" do
138
+ @it.current_section.should == "SECTION2"
139
+ end
140
+ end
141
+
142
+ context "after a named :TEXT: keyword" do
143
+ before :each do
144
+ @it << ":TEXT: foo\n"
145
+ end
146
+
147
+ it "should be in the :text state" do
148
+ @it.state.should == :text
149
+ end
150
+
151
+ it "should place following text lines into the named section" do
152
+ @librarian.should_receive(:add_text!).with("foo", "yadda yadda")
153
+ @it << "yadda yadda"
154
+ end
155
+
156
+ it "should name following code lines after the section" do
157
+ @librarian.should_receive(:add_code!).with("foo", "this is code")
158
+ @it << "yadda yadda\n"
159
+ @it << ":SAMPLE:\n"
160
+ @it << "this is code"
161
+ end
162
+ end
163
+
164
+ context "after text is ended by a :CUT:" do
165
+ before :each do
166
+ @it << ":TEXT:\n"
167
+ @it << ":CUT:\n"
168
+ end
169
+
170
+ it "should be in the :code state" do
171
+ @it.state.should == :code
172
+ end
173
+
174
+ it "should add following lines to a code sample" do
175
+ @librarian.should_receive(:add_code!).with("SECTION2", "this is code")
176
+ @it << "this is code"
177
+ end
178
+ end
179
+
180
+ context "after a :TEXT: keyword prefixed with '#'" do
181
+ before :each do
182
+ @it << "# :TEXT:\n"
183
+ end
184
+
185
+ it "should be in the :text state" do
186
+ @it.state.should == :text
187
+ end
188
+
189
+ end
190
+
191
+ context "after a :TEXT: keyword prefixed with ';'" do
192
+ before :each do
193
+ @it << " ; :TEXT:\n"
194
+ end
195
+
196
+ it "should be in the :text state" do
197
+ @it.state.should == :text
198
+ end
199
+
200
+ end
201
+
202
+ context "given a :SAMPLE: keyword with a name" do
203
+ before :each do
204
+ @it << ":SAMPLE: foobar"
205
+ end
206
+
207
+ it "should file following code lines under the given name" do
208
+ @librarian.should_receive(:add_code!).with("foobar", "line 1")
209
+ @librarian.should_receive(:add_code!).with("foobar", "line 2")
210
+
211
+ @it << "line 1"
212
+ @it << "line 2"
213
+ end
214
+
215
+ context "given an escaped directive" do
216
+ it "should add the directive line as code" do
217
+ @librarian.should_receive(:add_code!).with("foobar", " # :TEXT: abc")
218
+ @it << " # \\:TEXT: abc"
219
+ end
220
+ end
221
+ end
222
+
223
+ context "given a :SAMPLE: keyword with custom brackets" do
224
+ before :each do
225
+ @line = ':SAMPLE: foobar, { brackets: ["<<", ">>"] }'
226
+ end
227
+
228
+ it "should assign custom bracket attributes to the sample" do
229
+ @librarian.should_receive(:set_code_attributes!).
230
+ with("foobar",
231
+ {
232
+ :code_open_bracket => "<<",
233
+ :code_close_bracket => ">>"
234
+ })
235
+
236
+ @it << @line
237
+ end
238
+ end
239
+
240
+ context "in text section with comment set" do
241
+ before :each do
242
+ @librarian.stub!(:comment_prefix_known?).and_return(true)
243
+ @librarian.stub!(:comment_prefix).and_return("#")
244
+ @it << "# :TEXT:\n"
245
+ @section = @it.current_section
246
+ end
247
+
248
+ it "should treat a commented line as more of the same section" do
249
+ @librarian.should_receive(:add_text!).
250
+ with(@section, "# commented text\n")
251
+ @it << "# commented text\n"
252
+ end
253
+
254
+ it "should treat a commented blank line as more of the same section" do
255
+ @librarian.should_receive(:add_text!).
256
+ with(@section, "# \n")
257
+ @it << "# \n"
258
+ end
259
+
260
+ it "should treat an uncommented blank line as more of the same section" do
261
+ @librarian.should_receive(:add_text!).
262
+ with(@section, " \n")
263
+ @it << " \n"
264
+ end
265
+
266
+ it "should treat an uncommented line as the start of code" do
267
+ @librarian.should_receive(:add_code!).
268
+ with(@section, "uncommented text\n")
269
+ @it << "uncommented text\n"
270
+ end
271
+ end
272
+
273
+ context "given an insertion with an explicit selector" do
274
+ before :each do
275
+ @it << ":TEXT: mysection"
276
+ @line = ":INSERT: foo"
277
+ end
278
+
279
+ it "should add an insertion to the current section" do
280
+ @librarian.should_receive(:add_insertion!).with("mysection", anything)
281
+ @it << @line
282
+ end
283
+
284
+ it "should pass a selector object to the librarian" do
285
+ @librarian.should_receive(:add_insertion!) do |section, selector|
286
+ selector.should be_a_kind_of(Selector)
287
+ selector.string.should == "foo"
288
+ selector.default_key.should == "mysection"
289
+ end
290
+ @it << @line
291
+ end
292
+ end
293
+
294
+ context "given a process directive" do
295
+ before :each do
296
+ @line = ' # :PROCESS: sortail, "sort | tail"'
297
+ end
298
+
299
+ it "should add the process to the library" do
300
+ @librarian.should_receive(:add_process!).with("sortail", "sort | tail")
301
+ @it << @line
302
+ end
303
+ end
304
+
305
+ end
306
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Selector do
6
+ EXAMPLE_SELECTORS = [
7
+ # selector type key delim start end length pipeline
8
+ [ "@A", :code, "A", '..', 1, -1, nil, [] ],
9
+ [ "@A:1", :code, "A", nil, 1, 1, nil, [] ],
10
+ [ "", :code, "DEFAULT", '..', 1, -1, nil, [] ],
11
+ [ nil, :code, "DEFAULT", '..', 1, -1, nil, [] ],
12
+ [ ":2..4", :code, "DEFAULT", '..', 2, 4, nil, [] ],
13
+ [ ":2...4", :code, "DEFAULT", '...', 2, 4, nil, [] ],
14
+ [ "@B:2,5", :code, "B", ',', 2, nil,5, [] ],
15
+ [ "@B:/z/,6", :code, "B", ',', /z/, nil,6, [] ],
16
+ [ "@_:/z/../x/", :code, "_", '..', /z/, /x/,nil, [] ],
17
+ [ "@B:2,4|fnord",:code, "B", ',', 2, nil,4, ["fnord"]],
18
+ [ "$FOO", :special, "FOO", '..', 1, -1, nil, [] ],
19
+ [ "@A|foo|bar", :code, "A", '..', 1, -1, nil, ["foo", "bar"]],
20
+ ]
21
+
22
+ EXAMPLE_SELECTORS.each do |selector_attributes|
23
+ selector_string = selector_attributes[0]
24
+ type = selector_attributes[1]
25
+ key = selector_attributes[2]
26
+ delimiter = selector_attributes[3]
27
+ start = selector_attributes[4]
28
+ end_offset = selector_attributes[5]
29
+ length = selector_attributes[6]
30
+ pipeline = selector_attributes[7]
31
+
32
+ context "given selector '#{selector_attributes[0]}'" do
33
+ before :each do
34
+ @it = Germinate::Selector.new(selector_string, "DEFAULT")
35
+ end
36
+
37
+ it "should have string #{selector_string}" do
38
+ @it.string.should == selector_string
39
+ end
40
+
41
+ it "should have type #{type.inspect}" do
42
+ @it.selector_type.should == type
43
+ end
44
+ it "should have key #{key.inspect}" do
45
+ @it.key.should == key
46
+ end
47
+ it "should start at #{start.inspect}" do
48
+ @it.start_offset.should == start
49
+ end
50
+ it "should end at #{end_offset.inspect}" do
51
+ @it.end_offset.should == end_offset
52
+ end
53
+ it "should have length #{length.inspect}" do
54
+ @it.length.should == length
55
+ end
56
+ it "should have pipeline #{pipeline.inspect}" do
57
+ @it.pipeline.should == pipeline
58
+ end
59
+ it "should have delimiter #{delimiter.inspect}" do
60
+ @it.delimiter.should == delimiter
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end