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,121 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe Selector do
6
+
7
+ it "should be comparable to a string" do
8
+ Selector.new("@A:1..5").should be == "@A:1..5"
9
+ Selector.new("@A:1..5").should_not be == "@A:1..6"
10
+ end
11
+
12
+ context "given a subscript" do
13
+ before :each do
14
+ @it = Germinate::Selector.new("@A:1", "DEFAULT")
15
+ end
16
+
17
+ specify { @it.should be_slice }
18
+ specify { @it.should_not be_whole }
19
+ end
20
+
21
+ context "given no subscript" do
22
+ before :each do
23
+ @it = Germinate::Selector.new("@A", "DEFAULT")
24
+ end
25
+
26
+ specify { @it.should_not be_slice }
27
+ specify { @it.should be_whole }
28
+ end
29
+
30
+ context "given a post-pipeline subscript" do
31
+ before :each do
32
+ @it = Germinate::Selector.new("@A|foo:1", "DEFAULT")
33
+ end
34
+
35
+ specify { @it.should_not be_slice }
36
+ specify { @it.should be_whole }
37
+ end
38
+
39
+ context "given no type sigil or key" do
40
+ before :each do
41
+ @it = Selector.new(":2..5")
42
+ end
43
+
44
+ it "should have type code" do
45
+ @it.selector_type.should == :special
46
+ end
47
+
48
+ it "should have key SOURCE" do
49
+ @it.key.should == "SOURCE"
50
+ end
51
+ end
52
+
53
+ EXAMPLE_SELECTORS = [
54
+ # selector type key delim start end length pipeline excerpt_output?
55
+ [ "@A", :code, "A", '..', 1, -1, nil, %w[_transform] ,false],
56
+ [ "@A:1", :code, "A", nil, 1, 1, nil, %w[_transform] ,false],
57
+ [ "", :code, "DEFAULT", '..', 1, -1, nil, %w[_transform] ,false],
58
+ [ nil, :code, "DEFAULT", '..', 1, -1, nil, %w[_transform] ,false],
59
+ [ ":2..4", :code, "DEFAULT", '..', 2, 4, nil, %w[_transform] ,false],
60
+ [ ":2...4", :code, "DEFAULT", '...', 2, 4, nil, %w[_transform] ,false],
61
+ [ "@B:2,5", :code, "B", ',', 2, nil,5, %w[_transform] ,false],
62
+ [ "@B:/z/,6", :code, "B", ',', /z/, nil,6, %w[_transform] ,false],
63
+ [ "@_:/z/../x/", :code, "_", '..', /z/, /x/,nil, %w[_transform] ,false],
64
+ [ "@B:2,4|fnord",:code, "B", ',', 2, nil,4, %w[_transform fnord] ,false],
65
+ [ "$FOO", :special, "FOO", '..', 1, -1, nil, %w[_transform] ,false],
66
+ [ "@A|foo|bar", :code, "A", '..', 1, -1, nil, %w[_transform foo bar],false],
67
+ [ "@B|fnord:2,4",:code, "B", ',', 2, nil,4, %w[_transform fnord],true],
68
+ [ "@B|_transform",:code, "B", '..', 1, -1, nil, %w[_transform], false]
69
+ ]
70
+
71
+ EXAMPLE_SELECTORS.each do |selector_attributes|
72
+ selector_string = selector_attributes[0]
73
+ type = selector_attributes[1]
74
+ key = selector_attributes[2]
75
+ delimiter = selector_attributes[3]
76
+ start = selector_attributes[4]
77
+ end_offset = selector_attributes[5]
78
+ length = selector_attributes[6]
79
+ pipeline = selector_attributes[7]
80
+ excerpt_output = selector_attributes[8]
81
+
82
+ context "given selector '#{selector_attributes[0]}'" do
83
+ before :each do
84
+ @it = Germinate::Selector.new(selector_string, "DEFAULT")
85
+ end
86
+
87
+ it "should have string #{selector_string}" do
88
+ @it.string.should == selector_string
89
+ end
90
+
91
+ it "should have type #{type.inspect}" do
92
+ @it.selector_type.should == type
93
+ end
94
+ it "should have key #{key.inspect}" do
95
+ @it.key.should == key
96
+ end
97
+ it "should start at #{start.inspect}" do
98
+ @it.start_offset.should == start
99
+ end
100
+ it "should end at #{end_offset.inspect}" do
101
+ @it.end_offset.should == end_offset
102
+ end
103
+ it "should have length #{length.inspect}" do
104
+ @it.length.should == length
105
+ end
106
+ it "should have pipeline #{pipeline.inspect}" do
107
+ @it.pipeline.should == pipeline
108
+ end
109
+ it "should have delimiter #{delimiter.inspect}" do
110
+ @it.delimiter.should == delimiter
111
+ end
112
+
113
+ if excerpt_output
114
+ specify { @it.should be_excerpt_output }
115
+ else
116
+ specify { @it.should_not be_excerpt_output }
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe ShellPublisher do
6
+ before :each do
7
+ @name = "frank"
8
+ @pipeline_output = ["* line 1\n", "* line 2\n"]
9
+ @pipeline = stub("Pipeline", :call => @pipeline_output)
10
+ @variables = stub("Variables")
11
+ @librarian = stub("Librarian",
12
+ :make_pipeline => @pipeline,
13
+ :variables => @variables)
14
+ @command = "cat %f"
15
+ @options = {:command => @command}
16
+ @it = ShellPublisher.new(@name, @librarian, @options)
17
+ end
18
+
19
+ it "should have identifier 'shell'" do
20
+ ShellPublisher.identifier.should == "shell"
21
+ end
22
+
23
+ context "on publish" do
24
+ before :each do
25
+ @result = ["line 1\n", "line 2\n"]
26
+ @output = StringIO.new
27
+ @process = stub("ShellProcess", :call => @result).as_null_object
28
+ @source = stub("Source").as_null_object
29
+ @librarian.stub!(:[]).and_return(@source)
30
+ ShellProcess.stub!(:new).and_return(@process)
31
+ end
32
+
33
+ it "should create a new process" do
34
+ ShellProcess.should_receive(:new).with(@name, @command, @variables)
35
+ @it.publish!(@output)
36
+ end
37
+
38
+ it "should execute the created process" do
39
+ @process.should_receive(:call).with(anything).and_return(@result)
40
+ @it.publish!(@output)
41
+ end
42
+
43
+ it "should pass the pipeline output to the created process" do
44
+ @process.should_receive(:call).with(@pipeline_output).and_return(@result)
45
+ @it.publish!(@output)
46
+ end
47
+
48
+ it "should ask the librarian for the source file" do
49
+ @librarian.should_receive(:[]).with("$TEXT|_transform", anything)
50
+ @it.publish!(@output)
51
+ end
52
+
53
+ it "should write process output to given output stream" do
54
+ @it.publish!(@output)
55
+ @output.rewind
56
+ @output.read.should == "line 1\nline 2\n"
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,99 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe SourceFile do
6
+ before :each do
7
+ @it = SourceFile.new("DIR/SOURCE_PATH.EXT")
8
+ @file = stub("File", :flock => 0)
9
+ @lines = ["Line 1\n", "Line 2\n"]
10
+ File.stub!(:new).and_return(@file)
11
+ FileUtils.stub!(:cp)
12
+ end
13
+
14
+ it "should have a source path" do
15
+ @it.path.to_s.should == "DIR/SOURCE_PATH.EXT"
16
+ end
17
+
18
+ it "should append .germ.back for the backup path" do
19
+ @it.backup_path.to_s.should == "DIR/SOURCE_PATH.EXT.germ.bak"
20
+ end
21
+
22
+ context "when writing" do
23
+ before :each do
24
+ @open_file = stub("Open File", :write => nil)
25
+ @path = stub("Source Path", :read => "...")
26
+ @path.stub!(:open).and_yield(@open_file)
27
+ @backup_path = stub("BACKUP_PATH", :read => "...")
28
+ @it.backup_path = @backup_path
29
+ @it.path = @path
30
+ end
31
+
32
+ it "should lock and unlock the source path" do
33
+ File.should_receive(:new).with(@it.path).and_return(@file)
34
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(0)
35
+ @file.should_receive(:flock).with(File::LOCK_UN).ordered
36
+ @it.write!(@lines)
37
+ end
38
+
39
+ it "should raise error if locking fails" do
40
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(1)
41
+ @file.should_receive(:flock).with(File::LOCK_UN).ordered
42
+
43
+ lambda do
44
+ @it.write!(@lines)
45
+ end.should raise_error(RuntimeError)
46
+ end
47
+
48
+ it "should make a backup copy after locking the file" do
49
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(0)
50
+ FileUtils.should_receive(:cp).with(@it.path, @backup_path).ordered
51
+ @it.write!(@lines)
52
+ end
53
+
54
+ it "should make no backup if locking fails" do
55
+ @file.should_receive(:flock).with(File::LOCK_EX).ordered.and_return(1)
56
+ FileUtils.should_not_receive(:cp)
57
+ @it.write!(@lines) rescue nil
58
+ end
59
+
60
+ it "should unlock the file if backup fails" do
61
+ FileUtils.should_receive(:cp).and_raise("Some Error")
62
+ @file.should_receive(:flock).with(File::LOCK_UN)
63
+ @it.write!(@lines) rescue nil
64
+ end
65
+
66
+ it "should raise error if source file and backup are not equal" do
67
+ @path.should_receive(:read).and_return("...")
68
+ @backup_path.should_receive(:read).and_return("....")
69
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
70
+ end
71
+
72
+ it "should not open the source file if comparison fails" do
73
+ @path.should_receive(:read).and_return("...")
74
+ @backup_path.should_receive(:read).and_return("....")
75
+ @path.should_not_receive(:open)
76
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
77
+ end
78
+
79
+ it "should open the source file for overwriting after backing up" do
80
+ FileUtils.should_receive(:cp).ordered
81
+ @path.should_receive(:open).with('w+').ordered
82
+ @it.write!(@lines)
83
+ end
84
+
85
+ it "should write lines to the source file" do
86
+ @open_file.should_receive(:write).with("Line 1\n").ordered
87
+ @open_file.should_receive(:write).with("Line 2\n").ordered
88
+ @it.write!(@lines)
89
+ end
90
+
91
+ it "should restore backup if write fails" do
92
+ @open_file.should_receive(:write).and_raise("Some Failure")
93
+ FileUtils.should_receive(:cp).with(@backup_path, @path)
94
+ lambda do @it.write!(@lines) end.should raise_error(RuntimeError)
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe TextHunk do
6
+ before :each do
7
+ @it = TextHunk.new(["line 1", "line 2"])
8
+ end
9
+
10
+ it "should enable insertion expansion" do
11
+ @it.should be_expand_insertions
12
+ end
13
+
14
+ it "should enable line joining" do
15
+ @it.should be_join_lines
16
+ end
17
+
18
+ it "should enable blank stripping" do
19
+ @it.should be_strip_blanks
20
+ end
21
+
22
+ it "should disable comment erasure" do
23
+ @it.should_not be_erase_comments
24
+ end
25
+
26
+ it "should enable uncommenting" do
27
+ @it.should be_uncomment
28
+ end
29
+
30
+ it "should enable stripping right-side whitespace" do
31
+ @it.should be_rstrip_lines
32
+ end
33
+
34
+ it "should disable bracketing" do
35
+ @it.should_not be_bracket
36
+ end
37
+
38
+ it "should enable pipeline processing" do
39
+ @it.should be_pipeline
40
+ end
41
+
42
+ it "should enable insertion resolution" do
43
+ @it.should be_expand_insertions
44
+ end
45
+
46
+ it "should enable flattening nested hunks" do
47
+ @it.should be_flatten_nested
48
+ end
49
+
50
+
51
+ context "when visited by a formatter" do
52
+ before :each do
53
+ @comment_prefix = ">>"
54
+ contents = [
55
+ "foo",
56
+ "bar"
57
+ ]
58
+ @it = TextHunk.new(contents,
59
+ :comment_prefix => @comment_prefix)
60
+ @formatter = stub("Formatter")
61
+ end
62
+
63
+ it "should call #format_text! on self" do
64
+ @formatter.should_receive(:format_text!).with(@it, anything)
65
+ @it.format_with(@formatter)
66
+ end
67
+
68
+ it "should provide the comment prefix to the formatter" do
69
+ @formatter.should_receive(:format_text!).with(anything, @comment_prefix)
70
+ @it.format_with(@formatter)
71
+ end
72
+
73
+ end
74
+
75
+ describe "with a nested hunk" do
76
+ before :each do
77
+ @comment_prefix = ">>"
78
+ @formatter = stub("Formatter")
79
+ @nested_hunk = stub("Nested Hunk", :empty? => false)
80
+ contents = [
81
+ "foo",
82
+ "bar",
83
+ @nested_hunk,
84
+ "baz"
85
+ ]
86
+ @it = TextHunk.new(contents,
87
+ :comment_prefix => @comment_prefix)
88
+ end
89
+
90
+ it "should pass formatter on to nested hunks" do
91
+ @formatter.should_receive(:format_text!).with(["foo", "bar"], ">>").ordered
92
+ @nested_hunk.should_receive(:format_with).with(@formatter).ordered
93
+ @formatter.should_receive(:format_text!).with(["baz"], ">>").ordered
94
+ @it.format_with(@formatter)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,242 @@
1
+ require File.expand_path(
2
+ File.join(File.dirname(__FILE__), %w[.. .. lib germinate]))
3
+
4
+ module Germinate
5
+ describe TextTransforms do
6
+
7
+ Germinate::TextTransforms.methods(false).each do |transform|
8
+ describe "'#{transform}'" do
9
+ before :each do
10
+ @transform = Germinate::TextTransforms.send(transform)
11
+ end
12
+
13
+ it "should preserve hunk attributes from input to output" do
14
+ @pipeline = lambda {|h| h}
15
+ @input = Hunk.new([], :comment_prefix => "foo", :pipeline => @pipeline)
16
+ @output = @transform.call(@input)
17
+ @output.comment_prefix.should == @input.comment_prefix
18
+ end
19
+
20
+ unless transform == "flatten_nested"
21
+ context "given a lumpy hunk" do
22
+ before :each do
23
+ @nested_hunk = Hunk.new(["line 3", "line 4"])
24
+ @lumpy = Hunk.new([
25
+ "line 1",
26
+ @nested_hunk,
27
+ "line 2"
28
+ ],
29
+ :comment_prefix => "foo")
30
+ @output = @transform.call(@lumpy)
31
+ end
32
+
33
+ it "should pass nested hunks through untouched" do
34
+ @output[1].should == @nested_hunk
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "join_lines" do
42
+ before :each do
43
+ @it = TextTransforms.join_lines
44
+ end
45
+
46
+ context "given some line-broken paragraphs" do
47
+ before :each do
48
+ @input = [
49
+ "p1l1\n",
50
+ "p1l2\n",
51
+ "\n",
52
+ "p2l1",
53
+ "p2l2"
54
+ ]
55
+ end
56
+
57
+ it "should collapse the paragraphs into single lines" do
58
+ @it.call(@input).should == [
59
+ "p1l1 p1l2",
60
+ "\n",
61
+ "p2l1 p2l2"
62
+ ]
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "uncomment" do
68
+ context "with no comment prefix" do
69
+ before :each do
70
+ @it = TextTransforms.uncomment(nil)
71
+ end
72
+
73
+ it "should do nothing" do
74
+ @it.call(Hunk.new(["# foo", " bar"])).should == ["# foo", " bar"]
75
+ end
76
+ end
77
+
78
+ context "with a comment prefix of '# '" do
79
+ before :each do
80
+ @it = TextTransforms.uncomment('# ')
81
+ end
82
+
83
+ it "should strip matching comment prefixes" do
84
+ @it.call(["# foo", " bar"]).should == ["foo", " bar"]
85
+ end
86
+ end
87
+
88
+ context "given no explicit prefix" do
89
+ before :each do
90
+ @hunk = Hunk.new([" # foo", " bar"], :comment_prefix => " # ")
91
+ @it = TextTransforms.uncomment
92
+ end
93
+
94
+ it "should fall back on hunk's comment prefix" do
95
+ @it.call(@hunk).should == ["foo", " bar"]
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ describe "strip_blanks" do
102
+ context "given some leading and trailing blank lines" do
103
+ before :each do
104
+ @hunk = Hunk.new(
105
+ [
106
+ " \n ", "\t\t\t", "the good stuff",
107
+ " \n", "more good stuff\n", "\n"
108
+ ])
109
+ @it = TextTransforms.strip_blanks
110
+ end
111
+
112
+ it "should strip the blak lines" do
113
+ @it.call(@hunk).should == ["the good stuff", " \n", "more good stuff\n"]
114
+ end
115
+ end
116
+
117
+ context "given a nested hunk at the end" do
118
+ before :each do
119
+ @hunk = Hunk.new(
120
+ [
121
+ "not blank",
122
+ "the good stuff",
123
+ Hunk.new(["line 1"])
124
+ ])
125
+ @it = TextTransforms.strip_blanks
126
+ end
127
+
128
+ it "should not strip the hunk" do
129
+ @it.call(@hunk).should ==
130
+ ["not blank", "the good stuff", Hunk.new(["line 1"])]
131
+ end
132
+ end
133
+
134
+ end
135
+
136
+ describe "rstrip_lines" do
137
+ before :each do
138
+ @it = TextTransforms.rstrip_lines
139
+ end
140
+
141
+ it "should strip whitespace from the ends of lines" do
142
+ @it.call(["foo\n", "\n", "", "\tbar\t \n "]).should == ["foo", "", "", "\tbar"]
143
+ end
144
+ end
145
+
146
+ describe "bracket" do
147
+
148
+ context "given explicit brackets" do
149
+ before :each do
150
+ @it = TextTransforms.bracket("[", "]")
151
+ end
152
+
153
+ it "should bracket lines with the given brackets" do
154
+ @it.call(["line 1", "line 2"]).should == ["[", "line 1", "line 2", "]"]
155
+ end
156
+ end
157
+
158
+ context "given no arguments" do
159
+ before :each do
160
+ @hunk = Hunk.new(
161
+ ["line 1", "line 2"],
162
+ :code_open_bracket => "{{{",
163
+ :code_close_bracket => "}}}")
164
+ @it = TextTransforms.bracket
165
+ end
166
+
167
+ it "should use brackets specified on hunk" do
168
+ @it.call(@hunk).should == ["{{{", "line 1", "line 2", "}}}"]
169
+ end
170
+ end
171
+
172
+ context "given no no brackets" do
173
+ before :each do
174
+ @hunk = Hunk.new(
175
+ ["line 1", "line 2"])
176
+ @it = TextTransforms.bracket
177
+ end
178
+
179
+ it "should leave the hunk unchanged" do
180
+ @it.call(@hunk).should == ["line 1", "line 2"]
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "pipeline" do
186
+ before :each do
187
+ @output = stub("Output")
188
+ @pipeline = stub("Pipeline", :call => @output)
189
+ @hunk = stub("Hunk")
190
+ end
191
+
192
+ context "called on a hunk and a pipeline" do
193
+ before :each do
194
+ @it = TextTransforms.pipeline(@pipeline)
195
+ end
196
+
197
+ it "should invoke the pipeline on the hunk" do
198
+ @pipeline.should_receive(:call).with(@hunk).and_return(@output)
199
+ @it.call(@hunk).should == @output
200
+ end
201
+ end
202
+ end
203
+
204
+ describe "expand_insertions" do
205
+ before :each do
206
+ @output = stub("Output")
207
+ @hunk = stub("Hunk")
208
+ end
209
+
210
+ context "called on a hunk" do
211
+ before :each do
212
+ @it = TextTransforms.expand_insertions
213
+ end
214
+
215
+ it "should invoke expand_insertions on the hunk" do
216
+ @hunk.should_receive(:resolve_insertions).and_return(@output)
217
+ @it.call(@hunk).should == @output
218
+ end
219
+ end
220
+ end
221
+
222
+ describe "flatten" do
223
+ context "given a lumpy hunk" do
224
+ before :each do
225
+ @nested_hunk = Hunk.new(["line 3", "line 4"])
226
+ @lumpy = Hunk.new([
227
+ "line 1",
228
+ @nested_hunk,
229
+ "line 2"
230
+ ],
231
+ :comment_prefix => "foo")
232
+ @output = TextTransforms.flatten_nested.call(@lumpy)
233
+ end
234
+
235
+ it "should flatten the hunk into a single level" do
236
+ @output.should == ["line 1", "line 3", "line 4", "line 2"]
237
+ end
238
+ end
239
+
240
+ end
241
+ end
242
+ end