germinate 1.2.0
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/.gitignore +2 -0
- data/History.txt +26 -0
- data/README.rdoc +152 -0
- data/Rakefile +43 -0
- data/TODO +140 -0
- data/bin/germ +260 -0
- data/cucumber.yml +2 -0
- data/examples/basic.rb +123 -0
- data/examples/short.rb +19 -0
- data/features/author-formats-article.feature +111 -0
- data/features/author-lists-info.pending_feature +48 -0
- data/features/author-publishes-article-source.feature +5 -0
- data/features/author-publishes-article.feature +57 -0
- data/features/author-republishes-article.feature +5 -0
- data/features/author-selects-hunks.feature +26 -0
- data/features/author-sets-variables.feature +88 -0
- data/features/author-updates-article-source.feature +5 -0
- data/features/author-views-stuff.pending_feature +52 -0
- data/features/bin/quoter +6 -0
- data/features/bin/sorter +4 -0
- data/features/example_articles/bracketing.rb +27 -0
- data/features/example_articles/escaping.txt +13 -0
- data/features/example_articles/excerpt_output.rb +16 -0
- data/features/example_articles/hello.rb +9 -0
- data/features/example_articles/pipelines.txt +25 -0
- data/features/example_articles/regexen.rb +24 -0
- data/features/example_articles/sample_offsets.rb +18 -0
- data/features/example_articles/specials.rb +19 -0
- data/features/example_articles/stderr.rb +10 -0
- data/features/example_articles/wrapping.rb +8 -0
- data/features/example_output/bracketing.out +23 -0
- data/features/example_output/code_samples.txt +186 -0
- data/features/example_output/escaping.out +5 -0
- data/features/example_output/excerpt_output.out +6 -0
- data/features/example_output/hello.txt +1 -0
- data/features/example_output/pipelines.out +28 -0
- data/features/example_output/regexen.txt +22 -0
- data/features/example_output/sample_offsets.txt +15 -0
- data/features/example_output/specials.txt +40 -0
- data/features/example_output/stderr.out +3 -0
- data/features/example_output/wrapping.txt +3 -0
- data/features/step_definitions/germinate.rb +42 -0
- data/features/support/env.rb +20 -0
- data/germinate.gemspec +55 -0
- data/lib/germinate.rb +54 -0
- data/lib/germinate/application.rb +113 -0
- data/lib/germinate/article_editor.rb +20 -0
- data/lib/germinate/formatter.rb +119 -0
- data/lib/germinate/hunk.rb +183 -0
- data/lib/germinate/implicit_insertion.rb +9 -0
- data/lib/germinate/insertion.rb +29 -0
- data/lib/germinate/librarian.rb +293 -0
- data/lib/germinate/origin.rb +5 -0
- data/lib/germinate/pipeline.rb +13 -0
- data/lib/germinate/publisher.rb +57 -0
- data/lib/germinate/reader.rb +266 -0
- data/lib/germinate/selector.rb +136 -0
- data/lib/germinate/shared_style_attributes.rb +54 -0
- data/lib/germinate/shell_process.rb +94 -0
- data/lib/germinate/shell_publisher.rb +19 -0
- data/lib/germinate/simple_publisher.rb +7 -0
- data/lib/germinate/source_file.rb +41 -0
- data/lib/germinate/text_transforms.rb +119 -0
- data/lib/germinate/transform_process.rb +25 -0
- data/lib/germinate/variable.rb +23 -0
- data/sample.rb +14 -0
- data/spec/germinate/application_spec.rb +31 -0
- data/spec/germinate/article_editor_spec.rb +97 -0
- data/spec/germinate/code_hunk_spec.rb +73 -0
- data/spec/germinate/file_hunk_spec.rb +28 -0
- data/spec/germinate/formatter_spec.rb +160 -0
- data/spec/germinate/hunk_spec.rb +84 -0
- data/spec/germinate/implicit_insertion_spec.rb +33 -0
- data/spec/germinate/insertion_spec.rb +19 -0
- data/spec/germinate/librarian_spec.rb +555 -0
- data/spec/germinate/pipeline_spec.rb +34 -0
- data/spec/germinate/process_spec.rb +105 -0
- data/spec/germinate/publisher_spec.rb +130 -0
- data/spec/germinate/reader_spec.rb +385 -0
- data/spec/germinate/selector_spec.rb +121 -0
- data/spec/germinate/shell_publisher_spec.rb +61 -0
- data/spec/germinate/source_file_spec.rb +99 -0
- data/spec/germinate/text_hunk_spec.rb +98 -0
- data/spec/germinate/text_transforms_spec.rb +242 -0
- data/spec/germinate/transform_process_spec.rb +50 -0
- data/spec/germinate/variable_spec.rb +14 -0
- data/spec/germinate_spec.rb +8 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/cucumber.rake +5 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/test_germinate.rb +0 -0
- metadata +228 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe CodeHunk do
|
6
|
+
before :each do
|
7
|
+
@it = CodeHunk.new(["foo", "bar"])
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should disable line joining" do
|
11
|
+
@it.should_not be_join_lines
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should enable blank stripping" do
|
15
|
+
@it.should be_strip_blanks
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should disable comment erasure" do
|
19
|
+
@it.should_not be_erase_comments
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should disable uncommenting" do
|
23
|
+
@it.should_not be_uncomment
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should disable stripping right-side whitespace" do
|
27
|
+
@it.should_not be_rstrip_lines
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should enable bracketing" do
|
31
|
+
@it.should be_bracket
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should enable pipeline processing" do
|
35
|
+
@it.should be_pipeline
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when visited by a formatter" do
|
39
|
+
before :each do
|
40
|
+
@formatter = stub("Formatter")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should call #formate_code! for self" do
|
44
|
+
@formatter.should_receive(:format_code!).with(@it, anything)
|
45
|
+
@it.format_with(@formatter)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with a nested hunk" do
|
50
|
+
before :each do
|
51
|
+
@formatter = stub("Formatter")
|
52
|
+
@comment_prefix = ">>"
|
53
|
+
@nested_hunk = stub("Nested Hunk", :empty? => false)
|
54
|
+
contents = [
|
55
|
+
"foo",
|
56
|
+
"bar",
|
57
|
+
@nested_hunk,
|
58
|
+
"baz"
|
59
|
+
]
|
60
|
+
@it = CodeHunk.new(contents,
|
61
|
+
:comment_prefix => @comment_prefix)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should pass formatter on to nested hunks" do
|
65
|
+
@formatter.should_receive(:format_code!).with(["foo", "bar"], ">>").ordered
|
66
|
+
@nested_hunk.should_receive(:format_with).with(@formatter).ordered
|
67
|
+
@formatter.should_receive(:format_code!).with(["baz"], ">>").ordered
|
68
|
+
@it.format_with(@formatter)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe FileHunk do
|
6
|
+
before :each do
|
7
|
+
@it = FileHunk.new(["foo", "bar"], {:source_path => "SOURCE_PATH"})
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should know its source path" do
|
11
|
+
@it.source_path.to_s.should == "SOURCE_PATH"
|
12
|
+
end
|
13
|
+
|
14
|
+
specify { @it.should be_whole_file }
|
15
|
+
|
16
|
+
context "when visited by a formatter" do
|
17
|
+
before :each do
|
18
|
+
@formatter = stub("Formatter")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should call #formate_code! for self" do
|
22
|
+
@formatter.should_receive(:format_code!).with(@it, anything)
|
23
|
+
@it.format_with(@formatter)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe Formatter do
|
6
|
+
before :each do
|
7
|
+
@output = StringIO.new
|
8
|
+
@it = Formatter.new(@output)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should start in the :initial state" do
|
12
|
+
@it.state.should == :initial
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def output_string
|
17
|
+
@output.rewind
|
18
|
+
@output.string
|
19
|
+
end
|
20
|
+
|
21
|
+
context "which has been started" do
|
22
|
+
before :each do
|
23
|
+
@it.start!
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be in the :code state" do
|
27
|
+
@it.state.should == :code
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should ignore initial lines" do
|
31
|
+
@it.add_line!("TEST")
|
32
|
+
output_string.should == ""
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
context "after the :TEXT: keyword" do
|
38
|
+
before :each do
|
39
|
+
@it.start!
|
40
|
+
@it.add_line!(":TEXT:\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be in the :paragraph state" do
|
44
|
+
@it.state.should == :paragraph
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should start outputting text" do
|
48
|
+
@it.add_line!("check 1 2 3\n")
|
49
|
+
@it.add_line!("\n")
|
50
|
+
output_string.should == "check 1 2 3\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "after the :TEXT: keyword followed by :CUT:" do
|
55
|
+
before :each do
|
56
|
+
@it.start!
|
57
|
+
@it.add_line!(":TEXT:\n")
|
58
|
+
@it.add_line!(":CUT:\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should be in the :code state" do
|
62
|
+
@it.state.should == :code
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should stop outputting text" do
|
66
|
+
@it.add_line!("check 1 2 3\n")
|
67
|
+
output_string.should == ""
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "after a :TEXT: keyword prefixed with '#'" do
|
72
|
+
before :each do
|
73
|
+
@it.start!
|
74
|
+
@it.add_line!("# :TEXT:\n")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should be in the :paragraph state" do
|
78
|
+
@it.state.should == :paragraph
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a comment prefix of '#'" do
|
82
|
+
@it.comment_prefix.should == '#'
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should strip '#' prefixes from text" do
|
86
|
+
@it.add_line!("# Line 1\n")
|
87
|
+
@it.add_line!(" ## Line 2\n")
|
88
|
+
@it.add_line!("\n")
|
89
|
+
output_string.should == "Line 1 Line 2\n"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should ignore uncommented lines" do
|
93
|
+
@it.add_line!("; Not a comment #")
|
94
|
+
output_string.should == ""
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should ignore blank lines" do
|
98
|
+
@it.add_line!(" \t\n")
|
99
|
+
output_string.should == ""
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should ignore commented blank lines" do
|
103
|
+
@it.add_line!("# \t\n")
|
104
|
+
output_string.should == ""
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "after a :TEXT: keyword prefixed with ';'" do
|
109
|
+
before :each do
|
110
|
+
@it.start!
|
111
|
+
@it.add_line!(" ; :TEXT:\n")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should have a comment prefix of ';'" do
|
115
|
+
@it.comment_prefix.should == ';'
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should strip ';' prefixes from text" do
|
119
|
+
@it.add_line!("; Line 1\n")
|
120
|
+
@it.add_line!(" ;; Line 2\n")
|
121
|
+
@it.add_line!(";\n")
|
122
|
+
output_string.should == "Line 1 Line 2\n"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should ignore lines with '#' prefixes" do
|
126
|
+
@it.add_line!("# Line 1\n")
|
127
|
+
output_string.should == ""
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "in a text section " do
|
132
|
+
before :each do
|
133
|
+
@it.start!
|
134
|
+
@it.add_line!("# :TEXT:\n")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should join adjacent lines" do
|
138
|
+
@it.add_line!("# foo\n")
|
139
|
+
@it.add_line!("# bar\n")
|
140
|
+
@it.add_line!("\n")
|
141
|
+
output_string.should == "foo bar\n"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "in a linebreak section" do
|
146
|
+
before :each do
|
147
|
+
@it.start!
|
148
|
+
@it.add_line!("# :TEXT:\n")
|
149
|
+
@it.add_line!("# P1\n")
|
150
|
+
@it.add_line!("\n")
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should finish the section with a double newline" do
|
154
|
+
@it.add_line!("# P2\n")
|
155
|
+
@it.add_line!("\n")
|
156
|
+
output_string.should == "P1\n\nP2\n"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe Hunk, "(attributes)" do
|
6
|
+
Germinate::SharedStyleAttributes.fattrs.each do |attribute|
|
7
|
+
it "should support the #{attribute} style attribute" do
|
8
|
+
@it = Germinate::Hunk.new([], attribute => "test")
|
9
|
+
@it.send(attribute).should == "test"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should pass the #{attribute} attribute on to duplicates" do
|
13
|
+
@it = Germinate::Hunk.new([], attribute => "test")
|
14
|
+
@it.dup.send(attribute).should == "test"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should pass the #{attribute} attribute on to clones" do
|
18
|
+
@it = Germinate::Hunk.new([], attribute => "test")
|
19
|
+
@it.clone.send(attribute).should == "test"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should pass the #{attribute} attribute on to slices" do
|
23
|
+
@it = Germinate::Hunk.new([], attribute => "test")
|
24
|
+
@it[0..-1].send(attribute).should == "test"
|
25
|
+
@it.slice(0..-1).send(attribute).should == "test"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should copy #{attribute} from given template" do
|
29
|
+
@template = Object.new
|
30
|
+
@template.extend SharedStyleAttributes
|
31
|
+
@template.send(attribute, "test")
|
32
|
+
@it = Germinate::Hunk.new([], @template)
|
33
|
+
@it.send(attribute).should == "test"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Hunk do
|
40
|
+
before :each do
|
41
|
+
@it = Hunk.new
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not have a source path" do
|
45
|
+
@it.source_path.should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
specify { @it.should_not be_whole_file }
|
49
|
+
|
50
|
+
context "with an insertion" do
|
51
|
+
before :each do
|
52
|
+
@nested_hunk = stub("Nested Hunk")
|
53
|
+
@insertion = stub("Insertion", :resolve => @nested_hunk)
|
54
|
+
@it << "line 1"
|
55
|
+
@it << @insertion
|
56
|
+
@it << "line 2"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be able to resolve the insertion" do
|
60
|
+
@it.resolve_insertions.should == [
|
61
|
+
"line 1",
|
62
|
+
@nested_hunk,
|
63
|
+
"line 2"
|
64
|
+
]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "with some content" do
|
69
|
+
before :each do
|
70
|
+
@it.push("foo", "bar", "foo", "baz")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be able to find indexes of elements matching a regex" do
|
74
|
+
@it.index_matching(/ba/).should == 1
|
75
|
+
@it.index_matching(/fo/).should == 0
|
76
|
+
@it.index_matching(/fo/, 1).should == 2
|
77
|
+
@it.index_matching(/fo/, 2).should == 2
|
78
|
+
@it.index_matching(/fo/, 3).should be_nil
|
79
|
+
@it.index_matching(/za/, 3).should be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe ImplicitInsertion do
|
6
|
+
before :each do
|
7
|
+
@hunk = stub("Hunk").as_null_object
|
8
|
+
@library = stub("Library")
|
9
|
+
@selector = stub("Selector")
|
10
|
+
@it = Germinate::ImplicitInsertion.new(@selector, @library)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when the librarian can find the selection" do
|
14
|
+
before :each do
|
15
|
+
@library.stub!(:[]).and_return(@hunk)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should resolve to the hunk the librarian returns" do
|
19
|
+
@it.resolve.should equal(@hunk)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when the librarian cannot find the selection" do
|
24
|
+
before :each do
|
25
|
+
@library.stub!(:[]).and_raise(IndexError.new)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should resolve to a null hunk" do
|
29
|
+
@it.resolve.should be_a_kind_of(NullHunk)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(
|
2
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
3
|
+
|
4
|
+
module Germinate
|
5
|
+
describe Insertion, "given a library and a selector" do
|
6
|
+
before :each do
|
7
|
+
@hunk = stub("Hunk").as_null_object
|
8
|
+
@library = stub("Library", :[] => @hunk)
|
9
|
+
@selector = stub("Selector")
|
10
|
+
@it = Germinate::Insertion.new(@selector, @library, {})
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should use the library to resolve itself" do
|
14
|
+
@library.should_receive(:[]).
|
15
|
+
with(@selector, anything, anything).and_return(@hunk)
|
16
|
+
@it.resolve.should == @hunk
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,555 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'arrayfields'
|
3
|
+
|
4
|
+
require File.expand_path(
|
5
|
+
File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
|
6
|
+
|
7
|
+
|
8
|
+
module Germinate
|
9
|
+
describe Librarian do
|
10
|
+
before :each do
|
11
|
+
@it = Librarian.new
|
12
|
+
@it.source_path = "SOURCE_PATH"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should know its source path if given" do
|
16
|
+
@it.source_path.should == "SOURCE_PATH"
|
17
|
+
end
|
18
|
+
|
19
|
+
context "by default" do
|
20
|
+
it "should have access to the special _transform process" do
|
21
|
+
@it.process('_transform').should be_a_kind_of(TransformProcess)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not have a comment prefix" do
|
25
|
+
@it.comment_prefix.should == nil
|
26
|
+
@it.comment_prefix_known?.should be_false
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not have code brackets" do
|
30
|
+
@it.code_open_bracket.should be_nil
|
31
|
+
@it.code_close_bracket.should be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Germinate::SharedStyleAttributes.fattrs.each do |attribute|
|
36
|
+
it "should pass the #{attribute} attribute on to text hunks" do
|
37
|
+
@it.send(attribute, "#{attribute}_test")
|
38
|
+
@it.add_text!("first", "hello")
|
39
|
+
@it.section("first").send(attribute).should == "#{attribute}_test"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should pass the #{attribute} attribute on to code hunks" do
|
43
|
+
@it.send(attribute, "#{attribute}_test")
|
44
|
+
@it.add_code!("first", "hello")
|
45
|
+
@it.sample("first").send(attribute).should == "#{attribute}_test"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "given a comment prefix" do
|
50
|
+
before :each do
|
51
|
+
@it.comment_prefix = "||"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should remember the comment prefix" do
|
55
|
+
@it.comment_prefix.should == "||"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should know it has a comment prefix" do
|
59
|
+
@it.comment_prefix_known?.should be_true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "given code brackets" do
|
64
|
+
before :each do
|
65
|
+
@it.code_open_bracket = "{"
|
66
|
+
@it.code_close_bracket = "}"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should remember the open bracket" do
|
70
|
+
@it.code_open_bracket.should == "{"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should remember the close bracket" do
|
74
|
+
@it.code_close_bracket.should == "}"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context "given custom code attributes" do
|
80
|
+
before :each do
|
81
|
+
@it.set_code_attributes!(
|
82
|
+
"sample1",
|
83
|
+
:code_open_bracket => "<<",
|
84
|
+
:code_close_bracket => ">>")
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should create the sample (if needed) and assign the attributes" do
|
88
|
+
@it.sample("sample1").code_open_bracket.should == "<<"
|
89
|
+
@it.sample("sample1").code_close_bracket.should == ">>"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "given an insertion in my_section with selector @my_selector" do
|
94
|
+
before :each do
|
95
|
+
@it.disable_all_transforms!
|
96
|
+
@it.add_code!("my_sample", "line 1\n")
|
97
|
+
@it.add_insertion!("my_section", "@my_sample", { :comment_prefix => "@" })
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should add an Insertion to the named section" do
|
101
|
+
@it.section("my_section").last.should be_a_kind_of(Insertion)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should give the insertion the selector @my_selector" do
|
105
|
+
@it.section("my_section").last.selector.to_s.should == "@my_sample"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should give the insertion a reference to the library" do
|
109
|
+
@it.section("my_section").last.library.should == @it
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should apply any passed attributes to the insertion" do
|
113
|
+
@it.section("my_section").last.comment_prefix.should == "@"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should include the insertion in the $TEXT hunk" do
|
117
|
+
@it['$TEXT'].first.should be_a_kind_of(Insertion)
|
118
|
+
@it['$TEXT'].first.selector.should == "@my_sample"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "given a process to file" do
|
123
|
+
before :each do
|
124
|
+
@it.add_process!("myproc", "cowsay")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should make the process available as a ShellProcess object" do
|
128
|
+
@it.process("myproc").should be_a_kind_of(Germinate::ShellProcess)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should store the process name" do
|
132
|
+
@it.process("myproc").name.should == "myproc"
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should store the process command" do
|
136
|
+
@it.process("myproc").command.should == "cowsay"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should include the process when listing known processes" do
|
140
|
+
@it.process_names.should include("myproc")
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should give the process a reference to the librarians variables" do
|
144
|
+
@it.process("myproc").variables.should equal(@it.variables)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "given a code sample and some processes" do
|
149
|
+
before :each do
|
150
|
+
@output_a = Hunk.new(["line 1a", "line 2a"])
|
151
|
+
@output_b = Hunk.new(["line 1b", "line 2b"])
|
152
|
+
@process_a = stub("ShellProcess A",
|
153
|
+
:call => @output_a,
|
154
|
+
:name => "foo",
|
155
|
+
:command => "aaa")
|
156
|
+
@process_b = stub("ShellProcess B",
|
157
|
+
:call => @output_b,
|
158
|
+
:name => "bar",
|
159
|
+
:command => "bbb")
|
160
|
+
Germinate::ShellProcess.stub!(:new).
|
161
|
+
with("foo", "aaa", {}).
|
162
|
+
and_return(@process_a)
|
163
|
+
Germinate::ShellProcess.stub!(:new).
|
164
|
+
with("bar", "bbb", {}).
|
165
|
+
and_return(@process_b)
|
166
|
+
|
167
|
+
@it.add_code!("A", "line 1")
|
168
|
+
@it.add_code!("A", "line 2")
|
169
|
+
@it.add_process!("foo", "aaa")
|
170
|
+
@it.add_process!("bar", "bbb")
|
171
|
+
end
|
172
|
+
|
173
|
+
context "when the processes are included in a selection" do
|
174
|
+
before :each do
|
175
|
+
@selector = "@A|foo|bar"
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should call the processes on the selected text" do
|
179
|
+
@process_a.should_receive(:call).with(["line 1\n", "line 2\n"]).
|
180
|
+
and_return(@output_a)
|
181
|
+
@process_b.should_receive(:call).with(@output_a).
|
182
|
+
and_return(@output_b)
|
183
|
+
|
184
|
+
@it[@selector].should == ["line 1b", "line 2b"]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "when asked to make a pipeline of the two processes" do
|
189
|
+
before :each do
|
190
|
+
@pipeline = @it.make_pipeline("bar|foo")
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should return a Pipeline object" do
|
194
|
+
@pipeline.should be_a_kind_of(Germinate::Pipeline)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should return a two-process pipeline" do
|
198
|
+
@pipeline.should have(2).processes
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should include the named processes in the pipeline" do
|
202
|
+
@pipeline.processes[0].name.should == "bar"
|
203
|
+
@pipeline.processes[0].command.should == "bbb"
|
204
|
+
@pipeline.processes[1].name.should == "foo"
|
205
|
+
@pipeline.processes[1].command.should == "aaa"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "when asked to make an empty pipeline" do
|
210
|
+
before :each do
|
211
|
+
@pipeline = @it.make_pipeline("")
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should return an empty pipeline" do
|
215
|
+
@pipeline.should have(0).processes
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "given a new publisher" do
|
221
|
+
before :each do
|
222
|
+
@publisher_name = "MyPub"
|
223
|
+
@publisher_type = "shell"
|
224
|
+
@publisher_options = {'foo' => 'bar'}
|
225
|
+
@publisher = stub("Publisher")
|
226
|
+
Germinate::Publisher.stub!(:make).and_return(@publisher)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should construct a new publisher object" do
|
230
|
+
Germinate::Publisher.should_receive(:make).
|
231
|
+
with(@publisher_name, @publisher_type, @it, @publisher_options).
|
232
|
+
and_return(@publisher)
|
233
|
+
@it.add_publisher!(@publisher_name, @publisher_type, @publisher_options)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should make the new publisher available by name" do
|
237
|
+
@it.add_publisher!(@publisher_name, @publisher_type, @publisher_options)
|
238
|
+
@it.publisher(@publisher_name).should equal(@publisher)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should raise an error when an unknown publisher is requested" do
|
242
|
+
@it.add_publisher!(@publisher_name, @publisher_type, @publisher_options)
|
243
|
+
lambda do
|
244
|
+
@it.publisher("foo")
|
245
|
+
end.should raise_error(IndexError)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context "given a variable directive" do
|
250
|
+
before :each do
|
251
|
+
@line = " :SET: FOO, 123"
|
252
|
+
@it.set_variable!(@line, 111, "FOO", "123")
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should add a variable with the given name and value" do
|
256
|
+
@it.variables["FOO"].should == "123"
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should set the variables line to the given value" do
|
260
|
+
@it.variables["FOO"].line.should equal(@line)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should set the variables line_number to the given value" do
|
264
|
+
@it.variables["FOO"].origin.line_number.should == 111
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should set the variables source path to its own source path" do
|
268
|
+
@it.variables["FOO"].origin.source_path.to_s.should == "SOURCE_PATH"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "given a variable setting when the variable already has a value" do
|
273
|
+
before :each do
|
274
|
+
@it.set_variable!(" :SET: FOO, 123", 1, "FOO", "123")
|
275
|
+
@it.set_variable!(" :SET: FOO, 456", 1, "FOO", "456")
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should replace the old variable value with the new one" do
|
279
|
+
@it.variables["FOO"].should == "456"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "setting a new variable" do
|
284
|
+
before :each do
|
285
|
+
@it.add_text!("a", " # some text")
|
286
|
+
@it.comment_prefix = " # "
|
287
|
+
@it.variables["FOO"] = 123
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should add a new line" do
|
291
|
+
@it.lines.last.should == " # :SET: 'FOO', '123'\n"
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should set the variable to reference the new line" do
|
295
|
+
@it.variables["FOO"].line.should equal(@it.lines.last)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should set the line number for the new line" do
|
299
|
+
@it.variables["FOO"].origin.line_number.should == 2
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should set the variable's source file to its own" do
|
303
|
+
@it.variables["FOO"].origin.source_path.should == "SOURCE_PATH"
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should set the variable's value as a string" do
|
307
|
+
@it.variables["FOO"].should == "123"
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should set the updatad flag" do
|
311
|
+
@it.should be_updated
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "setting an existing variable" do
|
316
|
+
before :each do
|
317
|
+
@it.comment_prefix = " # "
|
318
|
+
@it.variables["FOO"] = 123
|
319
|
+
@it.add_text!("a", " # some text")
|
320
|
+
@it.updated = false
|
321
|
+
@it.variables["FOO"] = 456
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should not add a new line" do
|
325
|
+
@it.should have(2).lines
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should point to an already existing line" do
|
329
|
+
@it.variables["FOO"].line.should equal(@it.lines.first)
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should keep variable line number" do
|
333
|
+
@it.variables["FOO"].origin.line_number.should == 1
|
334
|
+
end
|
335
|
+
|
336
|
+
it "should keep variable source path" do
|
337
|
+
@it.variables["FOO"].origin.source_path.should == "SOURCE_PATH"
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should update the variable's value" do
|
341
|
+
@it.variables["FOO"].should == "456"
|
342
|
+
end
|
343
|
+
|
344
|
+
it "should set the updatad flag" do
|
345
|
+
@it.should be_updated
|
346
|
+
end
|
347
|
+
|
348
|
+
it "should update the source line with a new directive" do
|
349
|
+
@it.lines.first.should == " # :SET: 'FOO', '456'\n"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "storing changes" do
|
354
|
+
before :each do
|
355
|
+
@it.add_text!("A", "Line 1")
|
356
|
+
@it.add_text!("B", "Line 2")
|
357
|
+
@source_file = stub("Source File")
|
358
|
+
@it.source_file = @source_file
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should send all lines to the source file object to be written" do
|
362
|
+
@source_file.should_receive(:write!).with(["Line 1\n", "Line 2\n"])
|
363
|
+
@it.store_changes!
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
context "given an assortment of lines" do
|
368
|
+
before :each do
|
369
|
+
@it.add_front_matter!("FM 1")
|
370
|
+
@it.add_front_matter!("FM 2")
|
371
|
+
@it.add_control!("CONTROL 1")
|
372
|
+
@it.add_text!("SECTION1", "TEXT 1")
|
373
|
+
@it.add_text!("SECTION1", "TEXT 2")
|
374
|
+
@it.add_control!("CONTROL 2")
|
375
|
+
@it.add_code!("SECTION1", "CODE 1")
|
376
|
+
@it.add_control!("CONTROL 3")
|
377
|
+
@it.add_text!("SECTION2", "TEXT 3")
|
378
|
+
@it.add_text!("SECTION2", "TEXT 4")
|
379
|
+
@it.add_code!("SECTION2", "CODE 2")
|
380
|
+
@it.add_code!("SECTION2", "CODE 2l2")
|
381
|
+
@it.add_code!("SECTION2", "CODE 2l3")
|
382
|
+
@it.add_code!("SECTION2", "CODE 2l4")
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should be able to retrieve all the lines in order" do
|
386
|
+
@it.lines.should == [
|
387
|
+
"FM 1\n",
|
388
|
+
"FM 2\n",
|
389
|
+
"CONTROL 1\n",
|
390
|
+
"TEXT 1\n",
|
391
|
+
"TEXT 2\n",
|
392
|
+
"CONTROL 2\n",
|
393
|
+
"CODE 1\n",
|
394
|
+
"CONTROL 3\n",
|
395
|
+
"TEXT 3\n",
|
396
|
+
"TEXT 4\n",
|
397
|
+
"CODE 2\n",
|
398
|
+
"CODE 2l2\n",
|
399
|
+
"CODE 2l3\n",
|
400
|
+
"CODE 2l4\n",
|
401
|
+
]
|
402
|
+
end
|
403
|
+
|
404
|
+
it "should be able to retrieve text lines" do
|
405
|
+
@it.text_lines.should == [
|
406
|
+
"TEXT 1\n",
|
407
|
+
"TEXT 2\n",
|
408
|
+
"TEXT 3\n",
|
409
|
+
"TEXT 4\n"
|
410
|
+
]
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should be able to retrieve code lines" do
|
414
|
+
@it.code_lines.should == [
|
415
|
+
"CODE 1\n",
|
416
|
+
"CODE 2\n",
|
417
|
+
"CODE 2l2\n",
|
418
|
+
"CODE 2l3\n",
|
419
|
+
"CODE 2l4\n",
|
420
|
+
]
|
421
|
+
end
|
422
|
+
|
423
|
+
it "should be able to retrieve front matter" do
|
424
|
+
@it.front_matter_lines.should == [
|
425
|
+
"FM 1\n",
|
426
|
+
"FM 2\n",
|
427
|
+
]
|
428
|
+
end
|
429
|
+
|
430
|
+
it "should be able to retrieve text by section" do
|
431
|
+
@it.section("SECTION1").should == [
|
432
|
+
"TEXT 1\n",
|
433
|
+
"TEXT 2\n"
|
434
|
+
]
|
435
|
+
@it.section("SECTION2").should == [
|
436
|
+
"TEXT 3\n",
|
437
|
+
"TEXT 4\n"
|
438
|
+
]
|
439
|
+
end
|
440
|
+
|
441
|
+
it "should be able to retrieve code by sample name" do
|
442
|
+
@it.sample("SECTION1").should == [
|
443
|
+
"CODE 1\n"
|
444
|
+
]
|
445
|
+
@it.sample("SECTION2").should == [
|
446
|
+
"CODE 2\n",
|
447
|
+
"CODE 2l2\n",
|
448
|
+
"CODE 2l3\n",
|
449
|
+
"CODE 2l4\n",
|
450
|
+
]
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should be able to return a list of section names" do
|
454
|
+
@it.section_names.should == [
|
455
|
+
"SECTION1",
|
456
|
+
"SECTION2"
|
457
|
+
]
|
458
|
+
end
|
459
|
+
|
460
|
+
it "should be able to return a list of sample names" do
|
461
|
+
@it.sample_names.should == [
|
462
|
+
"SECTION1",
|
463
|
+
"SECTION2"
|
464
|
+
]
|
465
|
+
end
|
466
|
+
|
467
|
+
it "should be able to tell if a section exists" do
|
468
|
+
@it.should have_section("SECTION1")
|
469
|
+
@it.should_not have_section("SECTION5")
|
470
|
+
end
|
471
|
+
|
472
|
+
it "should be able to tell if a sample exists" do
|
473
|
+
@it.should have_sample("SECTION1")
|
474
|
+
@it.should_not have_sample("SECTION5")
|
475
|
+
end
|
476
|
+
|
477
|
+
it "should be able to retrieve lines using a selector" do
|
478
|
+
@it[Selector.new("@SECTION1", nil)].should == ["CODE 1\n"]
|
479
|
+
@it["@SECTION1"].should == ["CODE 1\n"]
|
480
|
+
end
|
481
|
+
|
482
|
+
context "given the $SOURCE selector with no subscripts" do
|
483
|
+
before :each do
|
484
|
+
@hunk = @it["$SOURCE"]
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should return a FileHunk" do
|
488
|
+
@hunk.should be_a_kind_of(FileHunk)
|
489
|
+
end
|
490
|
+
|
491
|
+
it "should return a FileHunk with the source file path set" do
|
492
|
+
@hunk.source_path.should == "SOURCE_PATH"
|
493
|
+
end
|
494
|
+
|
495
|
+
end
|
496
|
+
|
497
|
+
SELECTOR_EXAMPLES = [
|
498
|
+
# Selector Expected Excerpt Expected Type
|
499
|
+
[ "@SECTION1", ["CODE 1\n"], CodeHunk ],
|
500
|
+
[ "@SECTION2:1", ["CODE 2\n"], CodeHunk ],
|
501
|
+
[ "@SECTION2:2..3", ["CODE 2l2\n", "CODE 2l3\n"], CodeHunk ],
|
502
|
+
[ "@SECTION2:2,2", ["CODE 2l2\n", "CODE 2l3\n"], CodeHunk ],
|
503
|
+
[ "@SECTION2:/l2/../l3/", ["CODE 2l2\n", "CODE 2l3\n"], CodeHunk ],
|
504
|
+
[ "@SECTION2:/l2/.../l3/", ["CODE 2l2\n"], CodeHunk ],
|
505
|
+
[ "@SECTION2:/2/,3", [
|
506
|
+
"CODE 2\n",
|
507
|
+
"CODE 2l2\n",
|
508
|
+
"CODE 2l3\n"], CodeHunk ],
|
509
|
+
[ "@SECTION2:/l2/..-1", [
|
510
|
+
"CODE 2l2\n",
|
511
|
+
"CODE 2l3\n",
|
512
|
+
"CODE 2l4\n"], CodeHunk ],
|
513
|
+
[ "$CODE", [
|
514
|
+
"CODE 1\n",
|
515
|
+
"CODE 2\n",
|
516
|
+
"CODE 2l2\n",
|
517
|
+
"CODE 2l3\n",
|
518
|
+
"CODE 2l4\n", ], CodeHunk
|
519
|
+
],
|
520
|
+
[ "$SOURCE", [
|
521
|
+
"FM 1\n",
|
522
|
+
"FM 2\n",
|
523
|
+
"CONTROL 1\n",
|
524
|
+
"TEXT 1\n",
|
525
|
+
"TEXT 2\n",
|
526
|
+
"CONTROL 2\n",
|
527
|
+
"CODE 1\n",
|
528
|
+
"CONTROL 3\n",
|
529
|
+
"TEXT 3\n",
|
530
|
+
"TEXT 4\n",
|
531
|
+
"CODE 2\n",
|
532
|
+
"CODE 2l2\n",
|
533
|
+
"CODE 2l3\n",
|
534
|
+
"CODE 2l4\n",
|
535
|
+
], FileHunk
|
536
|
+
],
|
537
|
+
[ "$TEXT", [
|
538
|
+
"TEXT 1 TEXT 2 TEXT 3 TEXT 4" ], TextHunk
|
539
|
+
],
|
540
|
+
|
541
|
+
]
|
542
|
+
|
543
|
+
SELECTOR_EXAMPLES.each do |example|
|
544
|
+
example.fields = [:selector, :hunk, :type]
|
545
|
+
it "should be able to locate #{example[:selector]}" do
|
546
|
+
@it[example[:selector]].should == example[:hunk]
|
547
|
+
end
|
548
|
+
|
549
|
+
it "should return #{example[:selector]} as #{example[:type]}" do
|
550
|
+
@it[example[:selector]].should be_a_kind_of(example[:type])
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|