escort 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.irbrc +2 -0
- data/.travis.yml +1 -1
- data/README.md +272 -3
- data/TODO.md +118 -71
- data/examples/.my_apprc +24 -0
- data/examples/basic_config_file +16 -0
- data/examples/basic_conflicts +1 -1
- data/examples/basic_with_everything +30 -0
- data/examples/suite_complex +65 -0
- data/examples/{command → suite_simple} +0 -0
- data/examples/suite_with_sub_commands +94 -0
- data/lib/escort.rb +6 -4
- data/lib/escort/action_command/base.rb +7 -5
- data/lib/escort/app.rb +2 -8
- data/lib/escort/auto_options.rb +5 -3
- data/lib/escort/formatter/cursor_position.rb +29 -0
- data/lib/escort/formatter/default_help_formatter.rb +37 -32
- data/lib/escort/formatter/option.rb +1 -1
- data/lib/escort/formatter/stream_output_formatter.rb +88 -0
- data/lib/escort/formatter/{borderless_table.rb → string_grid.rb} +21 -19
- data/lib/escort/formatter/string_splitter.rb +24 -4
- data/lib/escort/setup/configuration/loader.rb +8 -2
- data/lib/escort/setup/configuration/locator/chaining.rb +29 -0
- data/lib/escort/setup/configuration/locator/executing_script_directory.rb +15 -0
- data/lib/escort/setup/configuration/locator/specified_directory.rb +21 -0
- data/lib/escort/setup/configuration/reader.rb +4 -2
- data/lib/escort/setup/configuration/writer.rb +6 -2
- data/lib/escort/setup/dsl/command.rb +7 -8
- data/lib/escort/setup/dsl/global.rb +3 -51
- data/lib/escort/version.rb +1 -1
- data/spec/integration/basic_config_file_spec.rb +82 -0
- data/spec/integration/suite_simple_spec.rb +45 -0
- data/spec/integration/suite_sub_command_spec.rb +51 -0
- data/spec/lib/escort/action_command/base_spec.rb +200 -0
- data/spec/lib/escort/formatter/option_spec.rb +2 -2
- data/spec/lib/escort/formatter/stream_output_formatter_spec.rb +214 -0
- data/spec/lib/escort/formatter/string_grid_spec.rb +59 -0
- data/spec/lib/escort/setup/configuration/generator_spec.rb +101 -0
- data/spec/lib/escort/setup/configuration/loader_spec.rb +79 -0
- data/spec/lib/escort/setup/configuration/locator/chaining_spec.rb +81 -0
- data/spec/lib/escort/setup/configuration/locator/descending_to_home_spec.rb +57 -0
- data/spec/lib/escort/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
- data/spec/lib/escort/setup/configuration/locator/specified_directory_spec.rb +33 -0
- data/spec/lib/escort/setup/configuration/merge_tool_spec.rb +41 -0
- data/spec/lib/escort/setup/configuration/reader_spec.rb +41 -0
- data/spec/lib/escort/setup/configuration/writer_spec.rb +75 -0
- data/spec/spec_helper.rb +2 -1
- metadata +44 -24
- data/examples/attic/1_1_basic.rb +0 -15
- data/examples/attic/1_2_basic_requires_arguments.rb +0 -15
- data/examples/attic/2_2_command.rb +0 -18
- data/examples/attic/2_2_command_requires_arguments.rb +0 -20
- data/examples/attic/2_3_nested_commands.rb +0 -26
- data/examples/attic/3_validations.rb +0 -31
- data/examples/attic/4_1_config_file.rb +0 -42
- data/examples/attic/argument_handling/basic.rb +0 -12
- data/examples/attic/argument_handling/basic_command.rb +0 -18
- data/examples/attic/argument_handling/no_arguments.rb +0 -14
- data/examples/attic/argument_handling/no_arguments_command.rb +0 -20
- data/examples/attic/command_aliases/app.rb +0 -31
- data/examples/attic/config_file/.apprc2 +0 -16
- data/examples/attic/config_file/app.rb +0 -78
- data/examples/attic/config_file/sub_commands.rb +0 -35
- data/examples/attic/default_command/app.rb +0 -20
- data/examples/attic/sub_commands/app.rb +0 -18
- data/examples/attic/validation_basic/app.rb +0 -31
- data/lib/escort/formatter/terminal_formatter.rb +0 -58
- data/lib/escort/setup/dsl/validations.rb +0 -25
data/lib/escort/version.rb
CHANGED
@@ -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'
|
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
|