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.
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