escort 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +8 -8
  2. data/.irbrc +2 -0
  3. data/.travis.yml +1 -1
  4. data/README.md +272 -3
  5. data/TODO.md +118 -71
  6. data/examples/.my_apprc +24 -0
  7. data/examples/basic_config_file +16 -0
  8. data/examples/basic_conflicts +1 -1
  9. data/examples/basic_with_everything +30 -0
  10. data/examples/suite_complex +65 -0
  11. data/examples/{command → suite_simple} +0 -0
  12. data/examples/suite_with_sub_commands +94 -0
  13. data/lib/escort.rb +6 -4
  14. data/lib/escort/action_command/base.rb +7 -5
  15. data/lib/escort/app.rb +2 -8
  16. data/lib/escort/auto_options.rb +5 -3
  17. data/lib/escort/formatter/cursor_position.rb +29 -0
  18. data/lib/escort/formatter/default_help_formatter.rb +37 -32
  19. data/lib/escort/formatter/option.rb +1 -1
  20. data/lib/escort/formatter/stream_output_formatter.rb +88 -0
  21. data/lib/escort/formatter/{borderless_table.rb → string_grid.rb} +21 -19
  22. data/lib/escort/formatter/string_splitter.rb +24 -4
  23. data/lib/escort/setup/configuration/loader.rb +8 -2
  24. data/lib/escort/setup/configuration/locator/chaining.rb +29 -0
  25. data/lib/escort/setup/configuration/locator/executing_script_directory.rb +15 -0
  26. data/lib/escort/setup/configuration/locator/specified_directory.rb +21 -0
  27. data/lib/escort/setup/configuration/reader.rb +4 -2
  28. data/lib/escort/setup/configuration/writer.rb +6 -2
  29. data/lib/escort/setup/dsl/command.rb +7 -8
  30. data/lib/escort/setup/dsl/global.rb +3 -51
  31. data/lib/escort/version.rb +1 -1
  32. data/spec/integration/basic_config_file_spec.rb +82 -0
  33. data/spec/integration/suite_simple_spec.rb +45 -0
  34. data/spec/integration/suite_sub_command_spec.rb +51 -0
  35. data/spec/lib/escort/action_command/base_spec.rb +200 -0
  36. data/spec/lib/escort/formatter/option_spec.rb +2 -2
  37. data/spec/lib/escort/formatter/stream_output_formatter_spec.rb +214 -0
  38. data/spec/lib/escort/formatter/string_grid_spec.rb +59 -0
  39. data/spec/lib/escort/setup/configuration/generator_spec.rb +101 -0
  40. data/spec/lib/escort/setup/configuration/loader_spec.rb +79 -0
  41. data/spec/lib/escort/setup/configuration/locator/chaining_spec.rb +81 -0
  42. data/spec/lib/escort/setup/configuration/locator/descending_to_home_spec.rb +57 -0
  43. data/spec/lib/escort/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
  44. data/spec/lib/escort/setup/configuration/locator/specified_directory_spec.rb +33 -0
  45. data/spec/lib/escort/setup/configuration/merge_tool_spec.rb +41 -0
  46. data/spec/lib/escort/setup/configuration/reader_spec.rb +41 -0
  47. data/spec/lib/escort/setup/configuration/writer_spec.rb +75 -0
  48. data/spec/spec_helper.rb +2 -1
  49. metadata +44 -24
  50. data/examples/attic/1_1_basic.rb +0 -15
  51. data/examples/attic/1_2_basic_requires_arguments.rb +0 -15
  52. data/examples/attic/2_2_command.rb +0 -18
  53. data/examples/attic/2_2_command_requires_arguments.rb +0 -20
  54. data/examples/attic/2_3_nested_commands.rb +0 -26
  55. data/examples/attic/3_validations.rb +0 -31
  56. data/examples/attic/4_1_config_file.rb +0 -42
  57. data/examples/attic/argument_handling/basic.rb +0 -12
  58. data/examples/attic/argument_handling/basic_command.rb +0 -18
  59. data/examples/attic/argument_handling/no_arguments.rb +0 -14
  60. data/examples/attic/argument_handling/no_arguments_command.rb +0 -20
  61. data/examples/attic/command_aliases/app.rb +0 -31
  62. data/examples/attic/config_file/.apprc2 +0 -16
  63. data/examples/attic/config_file/app.rb +0 -78
  64. data/examples/attic/config_file/sub_commands.rb +0 -35
  65. data/examples/attic/default_command/app.rb +0 -20
  66. data/examples/attic/sub_commands/app.rb +0 -18
  67. data/examples/attic/validation_basic/app.rb +0 -31
  68. data/lib/escort/formatter/terminal_formatter.rb +0 -58
  69. data/lib/escort/setup/dsl/validations.rb +0 -25
@@ -1,3 +1,3 @@
1
1
  module Escort
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,82 @@
1
+ describe "Escort basic app with config file defined", :integration => true do
2
+ include FakeFS::SpecHelpers
3
+
4
+ subject { Escort::App.create(option_string, &app_configuration) }
5
+
6
+ let(:path) {File.join(File.expand_path('~'), '.test_apprc')}
7
+ let(:app_configuration) do
8
+ lambda do |app|
9
+ app.config_file ".test_apprc", :autocreate => autocreate
10
+
11
+ app.options do |opts|
12
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
13
+ end
14
+
15
+ app.action do |options, arguments|
16
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
17
+ end
18
+ end
19
+ end
20
+
21
+ context "when config file is autocreatable" do
22
+ context "and config file does not yet exist" do
23
+ before do
24
+ begin
25
+ subject
26
+ rescue SystemExit => e
27
+ end
28
+ end
29
+ let(:autocreate) {true}
30
+ let(:option_string) { "" }
31
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
32
+ it("should have created a config file in default location") { File.should exist path }
33
+ end
34
+
35
+ context "and config file already exists" do
36
+ before do
37
+ FileUtils.mkdir_p(File.dirname path)
38
+ File.open(path, 'w') {|f| f.write(JSON.pretty_generate({:global => {:commands => {}, :options => {:option1 => 'hello'}}, :user => {}})) }
39
+
40
+ begin
41
+ subject
42
+ rescue SystemExit => e
43
+ end
44
+ end
45
+ let(:autocreate) {true}
46
+ let(:option_string) { "" }
47
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
48
+ it("should have picked up the existing config file") { result[:command_options][:option1].should == 'hello' }
49
+ end
50
+ end
51
+
52
+ context "when config file is not autocreatable" do
53
+ context "and config file already exists" do
54
+ let(:autocreate) {false}
55
+ let(:option_string) { "" }
56
+ before do
57
+ FileUtils.mkdir_p(File.dirname path)
58
+ File.open(path, 'w') {|f| f.write(JSON.pretty_generate({:global => {:commands => {}, :options => {:option1 => 'hello'}}, :user => {}})) }
59
+
60
+ begin
61
+ subject
62
+ rescue SystemExit => e
63
+ end
64
+ end
65
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
66
+ it("should have picked up the existing config file") { result[:command_options][:option1].should == 'hello' }
67
+ end
68
+
69
+ context "and config file does not yet exist" do
70
+ let(:autocreate) {false}
71
+ let(:option_string) { "" }
72
+ before do
73
+ begin
74
+ subject
75
+ rescue SystemExit => e
76
+ end
77
+ end
78
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
79
+ it("should not have created a config file in default location") { File.should_not exist path }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,45 @@
1
+ describe "Escort suite app with one level of commands", :integration => true do
2
+ subject { Escort::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
8
+ end
9
+
10
+ app.command :command1, :aliases => [:c1] do |command|
11
+ command.options do |opts|
12
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string
13
+ end
14
+
15
+ command.action do |options, arguments|
16
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
17
+ end
18
+ end
19
+
20
+ app.action do |options, arguments|
21
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
22
+ end
23
+ end
24
+ end
25
+
26
+ context "when calling command with option and global option" do
27
+ let(:option_string) { "-o hello command1 --option2 world" }
28
+
29
+ before do
30
+ begin
31
+ subject
32
+ rescue SystemExit => e
33
+ end
34
+ end
35
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
36
+ it("should have the right command name") { result[:command_name].should == :command1 }
37
+ it("should have have global option set") { result[:options][:global][:options][:option1].should == 'hello' }
38
+ it("should have have command option set") { result[:command_options][:option2].should == 'world' }
39
+ end
40
+
41
+ context "when using command alias" do
42
+ let(:option_string) { "-o hello c1 --option2 world" }
43
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ describe "Escort suite app with sub commands", :integration => true do
2
+ subject { Escort::App.create(option_string, &app_configuration) }
3
+
4
+ let(:app_configuration) do
5
+ lambda do |app|
6
+ app.options do |opts|
7
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
8
+ end
9
+
10
+ app.command :command1, :aliases => [:c1] do |command|
11
+ command.options do |opts|
12
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string
13
+ end
14
+
15
+ command.command :sub_command1 do |command|
16
+ command.options do |opts|
17
+ opts.opt :option3, "Option3", :short => :none, :long => '--option3', :type => :string
18
+ end
19
+
20
+ command.action do |options, arguments|
21
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
22
+ end
23
+ end
24
+
25
+ command.action do |options, arguments|
26
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
27
+ end
28
+ end
29
+
30
+ app.action do |options, arguments|
31
+ Escort::IntegrationTestCommand.new(options, arguments).execute(result)
32
+ end
33
+ end
34
+ end
35
+
36
+ context "when calling sub command with option and command option and global option" do
37
+ let(:option_string) { "-o hello command1 --option2=world sub_command1 --option3=foo" }
38
+
39
+ before do
40
+ begin
41
+ subject
42
+ rescue SystemExit => e
43
+ end
44
+ end
45
+ it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
46
+ it("should have the right command name") { result[:command_name].should == :sub_command1 }
47
+ it("should have have sub command option set") { result[:command_options][:option3].should == 'foo' }
48
+ it("should have have global option set") { result[:options][:global][:options][:option1].should == 'hello' }
49
+ it("should have have command option set") { result[:options][:global][:commands][:command1][:options][:option2].should == 'world' }
50
+ end
51
+ end
@@ -0,0 +1,200 @@
1
+ describe Escort::SetupAccessor do
2
+ let(:command) { Escort::TestCommand.new(options, arguments, config) }
3
+ let(:options) { {} }
4
+ let(:arguments) { [] }
5
+ let(:config) { {} }
6
+
7
+ describe "#command_context" do
8
+ subject {command.send(:command_context)}
9
+
10
+ context "when command context already set" do
11
+ before do
12
+ command.instance_variable_set(:"@command_context", [:hello])
13
+ end
14
+
15
+ it {subject.should == [:hello]}
16
+ end
17
+
18
+ context "when command context not yet set" do
19
+ context "and options hash is empty" do
20
+ it {subject.should == []}
21
+ end
22
+
23
+ context "and options hash is of valid structure" do
24
+ context "and command is global" do
25
+ let(:options) { {:global => {:commands => {}}} }
26
+ it {subject.should == []}
27
+ end
28
+
29
+ context "and command is child of global" do
30
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}}} }
31
+ it {subject.should == [:command1]}
32
+
33
+ context "and no commands hash for sub command in options" do
34
+ let(:options) { {:global => {:commands => {:command1 => {}}}} }
35
+ it {subject.should == [:command1]}
36
+ end
37
+ end
38
+
39
+ context "and command is grandchild of global" do
40
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}}} }
41
+ it {subject.should == [:command1, :sub_command1]}
42
+ end
43
+
44
+ context "and command is great grandchild of global" do
45
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {:sub_sub_command1 => {:commands => {}}}}}}}}} }
46
+ it {subject.should == [:command1, :sub_command1, :sub_sub_command1]}
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "#command_name" do
53
+ subject {command.send(:command_name)}
54
+
55
+ context "when context is global" do
56
+ let(:options) { {:global => {:commands => {}}} }
57
+ it {subject.should == :global}
58
+ end
59
+
60
+ context "when context is of size 1" do
61
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}}} }
62
+ it {subject.should == :command1}
63
+ end
64
+
65
+ context "when context is of size 2" do
66
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}}} }
67
+ it {subject.should == :sub_command1}
68
+ end
69
+ end
70
+
71
+ describe "#command_options" do
72
+ subject {command.send(:command_options)}
73
+
74
+ context "when context is global" do
75
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
76
+ it {subject.should == {:hello => :world}}
77
+ end
78
+
79
+ context "when context is of size 1" do
80
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}, :options => {:hello => :world}}}}} }
81
+ it {subject.should == {:hello => :world}}
82
+ end
83
+
84
+ context "when context is of size 2" do
85
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}, :options => {:hello => :world}}}}}}} }
86
+ it {subject.should == {:hello => :world}}
87
+ end
88
+ end
89
+
90
+ describe "#global_options" do
91
+ subject {command.send(:global_options)}
92
+
93
+ context "when context is global" do
94
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
95
+ it {subject.should == {:hello => :world}}
96
+ end
97
+
98
+ context "when context is of size 1" do
99
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
100
+ it {subject.should == {:hello => :world}}
101
+ end
102
+ end
103
+
104
+ describe "#parent_options" do
105
+ subject {command.send(:parent_options)}
106
+
107
+ context "when context is global" do
108
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
109
+ it {subject.should == {}}
110
+ end
111
+
112
+ context "when context is of size 1" do
113
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
114
+ it {subject.should == {:hello => :world}}
115
+ end
116
+
117
+ context "when context is of size 2" do
118
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}, :options => {:hello => :world}}}}} }
119
+ it {subject.should == {:hello => :world}}
120
+ end
121
+ end
122
+
123
+ describe "#grandparent_options" do
124
+ subject {command.send(:grandparent_options)}
125
+
126
+ context "when context is global" do
127
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
128
+ it {subject.should == {}}
129
+ end
130
+
131
+ context "when context is of size 1" do
132
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}}}, :options => {:hello => :world}}} }
133
+ it {subject.should == {}}
134
+ end
135
+
136
+ context "when context is of size 2" do
137
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {:sub_command1 => {:commands => {}}}}}, :options => {:hello => :world}}} }
138
+ it {subject.should == {:hello => :world}}
139
+ end
140
+ end
141
+
142
+ describe "#ancestor_options" do
143
+ subject {command.send(:ancestor_options, generation_number)}
144
+
145
+ context "when context is global" do
146
+ let(:options) { {:global => {:commands => {}, :options => {:hello => :world}}} }
147
+
148
+ context "and generation number is 0" do
149
+ let(:generation_number) {0}
150
+ it {subject.should == {:hello => :world}}
151
+ end
152
+
153
+ context "and generation number is 1" do
154
+ let(:generation_number) {1}
155
+ it {subject.should == {}}
156
+ end
157
+
158
+ context "and generation number is 2" do
159
+ let(:generation_number) {2}
160
+ it {subject.should == {}}
161
+ end
162
+
163
+ context "and generation number is 3" do
164
+ let(:generation_number) {3}
165
+ it {subject.should == {}}
166
+ end
167
+ end
168
+
169
+ context "when context is of size 1" do
170
+ let(:options) { {:global => {:commands => {:command1 => {:commands => {}, :options => {:foo => :bar}}}, :options => {:hello => :world}}} }
171
+
172
+ context "and generation number is 0" do
173
+ let(:generation_number) {0}
174
+ it {subject.should == {:foo => :bar}}
175
+ end
176
+
177
+ context "and generation number is 1" do
178
+ let(:generation_number) {1}
179
+ it {subject.should == {:hello => :world}}
180
+ end
181
+
182
+ context "and generation number is 2" do
183
+ let(:generation_number) {2}
184
+ it {subject.should == {}}
185
+ end
186
+
187
+ context "and generation number is 3" do
188
+ let(:generation_number) {3}
189
+ it {subject.should == {}}
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ module Escort
196
+ class TestCommand < ::Escort::ActionCommand::Base
197
+ def execute
198
+ end
199
+ end
200
+ end
@@ -276,7 +276,7 @@ describe Escort::Formatter::Option do
276
276
  end
277
277
  end
278
278
  end
279
- it {subject.should == ''}
279
+ it {subject.should == []}
280
280
  end
281
281
 
282
282
  context "when validations is defined" do
@@ -294,7 +294,7 @@ describe Escort::Formatter::Option do
294
294
  end
295
295
  end
296
296
  end
297
- it {subject.should == "must be 'foo'\n- must not be 'bar'"}
297
+ it {subject.should == ["must be 'foo'", "must not be 'bar'"]}
298
298
  end
299
299
  end
300
300
  end
@@ -0,0 +1,214 @@
1
+ describe Escort::Formatter::StreamOutputFormatter do
2
+ let(:formatter) {Escort::Formatter::StreamOutputFormatter.new(stream, :max_output_width => output_width)}
3
+ let(:stream) { StringIO.new }
4
+ let(:output_width) { 10 }
5
+ let(:output) {stream.readlines}
6
+
7
+ describe "#print" do
8
+ subject {formatter.print(string)}
9
+
10
+ before { subject; stream.rewind }
11
+
12
+ context "when string is less than output_width" do
13
+ let(:string) {'12345'}
14
+ it("stream should have one line") {output.first.should == string}
15
+ end
16
+
17
+ context "when string is greater than output width" do
18
+ let(:string) {'123456789abcd'}
19
+ it("stream should have two lines") {output.should == ["123456789a\n", "bcd"]}
20
+ end
21
+
22
+ context "when string is has newlines in it" do
23
+ context "and both lines less than output width" do
24
+ let(:string) {"1234567\n89abcd"}
25
+ it("stream should have two lines") {output.should == ["1234567\n", "89abcd"]}
26
+ end
27
+
28
+ context "and first line greater than output width" do
29
+ let(:string) {"123456789abcd\nefg"}
30
+ it("stream should have three lines") {output.should == ["123456789a\n", "bcd\n", "efg"]}
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#puts" do
36
+ subject {formatter.puts(string, options)}
37
+ let(:string) {'hello'}
38
+ let(:options) { {:newlines => newlines} }
39
+ let(:newlines) {1}
40
+
41
+ before { subject; stream.rewind }
42
+
43
+ context "when newlines" do
44
+ context "is zero" do
45
+ let(:newlines) {0}
46
+ let(:string) {"123456789abcd\nefg"}
47
+ it("stream should have three lines") {output.should == ["123456789a\n", "bcd\n", "efg"]}
48
+ end
49
+
50
+ context "not specified" do
51
+ subject {formatter.puts(string)}
52
+ let(:string) {"123"}
53
+ it("stream should have one newline") {output.should == ["123\n"]}
54
+ end
55
+
56
+ context "is two" do
57
+ let(:string) {"123"}
58
+ let(:newlines) {2}
59
+ it("stream should have two newlines") {output.should == ["123\n", "\n"]}
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#newline" do
65
+ subject {formatter.newline(newline_count)}
66
+ let(:newline_count) {1}
67
+
68
+ before { subject; stream.rewind }
69
+
70
+ context "when newline count not specified" do
71
+ subject {formatter.newline}
72
+ it("stream should have one newline") {output.should == ["\n"]}
73
+ end
74
+
75
+ context "when newline count is 2" do
76
+ let(:newline_count) {2}
77
+ it("stream should have two newlines") {output.should == ["\n", "\n"]}
78
+ end
79
+ end
80
+
81
+ describe "#indent" do
82
+ subject {formatter.indent(indent_width, &indented_block)}
83
+
84
+ let(:indented_block) do
85
+ lambda {|f| f.print string}
86
+ end
87
+
88
+ before { subject; stream.rewind }
89
+
90
+ context "when indent is 0" do
91
+ let(:indent_width) {0}
92
+
93
+ context "and we print a string less than output_width" do
94
+ let(:string) {'12345'}
95
+ it("stream should have one line") {output.should == ['12345']}
96
+ end
97
+
98
+ context "and we print a string greater than output width" do
99
+ let(:string) {'123456789abcd'}
100
+ it("stream should have two lines") {output.should == ["123456789a\n", "bcd"]}
101
+ end
102
+
103
+ context "and we print a string that has newlines in it" do
104
+ context "and both lines are less than output width" do
105
+ let(:string) {"1234567\n89abcd"}
106
+ it("stream should have two lines") {output.should == ["1234567\n", "89abcd"]}
107
+ end
108
+
109
+ context "and first line is greater than output width" do
110
+ let(:string) {"123456789abcd\nefg"}
111
+ it("stream should have three lines") {output.should == ["123456789a\n", "bcd\n", "efg"]}
112
+ end
113
+ end
114
+ end
115
+
116
+ context "when indent is 1" do
117
+ let(:indent_width) {1}
118
+
119
+ context "and we print a string less than output_width" do
120
+ let(:string) {'12345'}
121
+ it("stream should have one line") {output.should == [' 12345']}
122
+ end
123
+
124
+ context "and we print a string greater than output width" do
125
+ let(:string) {'123456789abcd'}
126
+ it("stream should have two lines") {output.should == [" 123456789\n", " abcd"]}
127
+ end
128
+
129
+ context "and we print a string that has newlines in it" do
130
+ context "and both lines are less than output width" do
131
+ let(:string) {"1234567\n89abcd"}
132
+ it("stream should have two lines") {output.should == [" 1234567\n", " 89abcd"]}
133
+ end
134
+
135
+ context "and first line is greater than output width" do
136
+ let(:string) {"123456789abcd\nefg"}
137
+ it("stream should have three lines") {output.should == [" 123456789\n", " abcd\n", " efg"]}
138
+ end
139
+ end
140
+ end
141
+
142
+ context "when indent is 3" do
143
+ let(:indent_width) {3}
144
+
145
+ context "and we print a string less than output_width" do
146
+ let(:string) {'12345'}
147
+ it("stream should have one line") {output.should == [' 12345']}
148
+ end
149
+
150
+ context "and we print a string greater than output width" do
151
+ let(:string) {'123456789abcd'}
152
+ it("stream should have two lines") {output.should == [" 1234567\n", " 89abcd"]}
153
+ end
154
+
155
+ context "and we print a string that has newlines in it" do
156
+ context "and both lines are less than output width" do
157
+ let(:string) {"1234567\n89abcd"}
158
+ it("stream should have two lines") {output.should == [" 1234567\n", " 89abcd"]}
159
+ end
160
+
161
+ context "and first line is greater than output width" do
162
+ let(:string) {"123456789abcd\nefg"}
163
+ it("stream should have three lines") {output.should == [" 1234567\n", " 89abcd\n", " efg"]}
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ context "output combinations" do
170
+ subject do
171
+ Escort::Formatter::StreamOutputFormatter.new(stream, :max_output_width => output_width) do |f|
172
+ f.print "the quick"
173
+ f.newline
174
+ f.print "brown fox"
175
+ f.print "jumped over the"
176
+ f.print "lazy dog"
177
+ f.newline
178
+ f.puts 'rainbow suspenders'
179
+ f.indent(3) do |f|
180
+ f.puts "blah blah blah blah"
181
+ f.newline(2)
182
+ f.indent(2) do |f|
183
+ f.puts "indent me good"
184
+ f.print "foo"
185
+ f.print "foo"
186
+ f.print "foo"
187
+ f.newline
188
+ f.puts "exit", :newlines => 4
189
+ end
190
+ end
191
+ end
192
+ end
193
+ let(:stream) { StringIO.new }
194
+ let(:output_width) { 10 }
195
+
196
+ let(:output) {stream.readlines}
197
+
198
+ before { subject; stream.rewind }
199
+
200
+ context "lines should not be greater than output width" do
201
+ it do
202
+ output.each do |line|
203
+ line.strip.length.should be <= output_width
204
+ end
205
+ end
206
+ end
207
+
208
+ context "stream should contain" do
209
+ it do
210
+ output.should == ["the quick\n", "brown foxj\n", "umped over\n", " thelazy d\n", "og\n", "rainbow su\n", "spenders\n", " blah bl\n", " ah blah\n", " blah\n", "\n", "\n", " inden\n", " t me \n", " good\n", " foofo\n", " ofoo\n", " exit\n", "\n", "\n", "\n"]
211
+ end
212
+ end
213
+ end
214
+ end