escort 0.2.1 → 0.3.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 (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