germinate 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/.gitignore +2 -0
  2. data/History.txt +26 -0
  3. data/README.rdoc +152 -0
  4. data/Rakefile +43 -0
  5. data/TODO +140 -0
  6. data/bin/germ +260 -0
  7. data/cucumber.yml +2 -0
  8. data/examples/basic.rb +123 -0
  9. data/examples/short.rb +19 -0
  10. data/features/author-formats-article.feature +111 -0
  11. data/features/author-lists-info.pending_feature +48 -0
  12. data/features/author-publishes-article-source.feature +5 -0
  13. data/features/author-publishes-article.feature +57 -0
  14. data/features/author-republishes-article.feature +5 -0
  15. data/features/author-selects-hunks.feature +26 -0
  16. data/features/author-sets-variables.feature +88 -0
  17. data/features/author-updates-article-source.feature +5 -0
  18. data/features/author-views-stuff.pending_feature +52 -0
  19. data/features/bin/quoter +6 -0
  20. data/features/bin/sorter +4 -0
  21. data/features/example_articles/bracketing.rb +27 -0
  22. data/features/example_articles/escaping.txt +13 -0
  23. data/features/example_articles/excerpt_output.rb +16 -0
  24. data/features/example_articles/hello.rb +9 -0
  25. data/features/example_articles/pipelines.txt +25 -0
  26. data/features/example_articles/regexen.rb +24 -0
  27. data/features/example_articles/sample_offsets.rb +18 -0
  28. data/features/example_articles/specials.rb +19 -0
  29. data/features/example_articles/stderr.rb +10 -0
  30. data/features/example_articles/wrapping.rb +8 -0
  31. data/features/example_output/bracketing.out +23 -0
  32. data/features/example_output/code_samples.txt +186 -0
  33. data/features/example_output/escaping.out +5 -0
  34. data/features/example_output/excerpt_output.out +6 -0
  35. data/features/example_output/hello.txt +1 -0
  36. data/features/example_output/pipelines.out +28 -0
  37. data/features/example_output/regexen.txt +22 -0
  38. data/features/example_output/sample_offsets.txt +15 -0
  39. data/features/example_output/specials.txt +40 -0
  40. data/features/example_output/stderr.out +3 -0
  41. data/features/example_output/wrapping.txt +3 -0
  42. data/features/step_definitions/germinate.rb +42 -0
  43. data/features/support/env.rb +20 -0
  44. data/germinate.gemspec +55 -0
  45. data/lib/germinate.rb +54 -0
  46. data/lib/germinate/application.rb +113 -0
  47. data/lib/germinate/article_editor.rb +20 -0
  48. data/lib/germinate/formatter.rb +119 -0
  49. data/lib/germinate/hunk.rb +183 -0
  50. data/lib/germinate/implicit_insertion.rb +9 -0
  51. data/lib/germinate/insertion.rb +29 -0
  52. data/lib/germinate/librarian.rb +293 -0
  53. data/lib/germinate/origin.rb +5 -0
  54. data/lib/germinate/pipeline.rb +13 -0
  55. data/lib/germinate/publisher.rb +57 -0
  56. data/lib/germinate/reader.rb +266 -0
  57. data/lib/germinate/selector.rb +136 -0
  58. data/lib/germinate/shared_style_attributes.rb +54 -0
  59. data/lib/germinate/shell_process.rb +94 -0
  60. data/lib/germinate/shell_publisher.rb +19 -0
  61. data/lib/germinate/simple_publisher.rb +7 -0
  62. data/lib/germinate/source_file.rb +41 -0
  63. data/lib/germinate/text_transforms.rb +119 -0
  64. data/lib/germinate/transform_process.rb +25 -0
  65. data/lib/germinate/variable.rb +23 -0
  66. data/sample.rb +14 -0
  67. data/spec/germinate/application_spec.rb +31 -0
  68. data/spec/germinate/article_editor_spec.rb +97 -0
  69. data/spec/germinate/code_hunk_spec.rb +73 -0
  70. data/spec/germinate/file_hunk_spec.rb +28 -0
  71. data/spec/germinate/formatter_spec.rb +160 -0
  72. data/spec/germinate/hunk_spec.rb +84 -0
  73. data/spec/germinate/implicit_insertion_spec.rb +33 -0
  74. data/spec/germinate/insertion_spec.rb +19 -0
  75. data/spec/germinate/librarian_spec.rb +555 -0
  76. data/spec/germinate/pipeline_spec.rb +34 -0
  77. data/spec/germinate/process_spec.rb +105 -0
  78. data/spec/germinate/publisher_spec.rb +130 -0
  79. data/spec/germinate/reader_spec.rb +385 -0
  80. data/spec/germinate/selector_spec.rb +121 -0
  81. data/spec/germinate/shell_publisher_spec.rb +61 -0
  82. data/spec/germinate/source_file_spec.rb +99 -0
  83. data/spec/germinate/text_hunk_spec.rb +98 -0
  84. data/spec/germinate/text_transforms_spec.rb +242 -0
  85. data/spec/germinate/transform_process_spec.rb +50 -0
  86. data/spec/germinate/variable_spec.rb +14 -0
  87. data/spec/germinate_spec.rb +8 -0
  88. data/spec/spec.opts +1 -0
  89. data/spec/spec_helper.rb +16 -0
  90. data/tasks/ann.rake +80 -0
  91. data/tasks/bones.rake +20 -0
  92. data/tasks/cucumber.rake +5 -0
  93. data/tasks/gem.rake +201 -0
  94. data/tasks/git.rake +40 -0
  95. data/tasks/notes.rake +27 -0
  96. data/tasks/post_load.rake +34 -0
  97. data/tasks/rdoc.rake +51 -0
  98. data/tasks/rubyforge.rake +55 -0
  99. data/tasks/setup.rb +292 -0
  100. data/tasks/spec.rake +54 -0
  101. data/tasks/svn.rake +47 -0
  102. data/tasks/test.rake +40 -0
  103. data/tasks/zentest.rake +36 -0
  104. data/test/test_germinate.rb +0 -0
  105. 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