command_kit 0.1.0.pre1

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 (98) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +29 -0
  4. data/.gitignore +7 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +29 -0
  8. data/Gemfile +14 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +283 -0
  11. data/Rakefile +23 -0
  12. data/command_kit.gemspec +60 -0
  13. data/gemspec.yml +14 -0
  14. data/lib/command_kit.rb +1 -0
  15. data/lib/command_kit/arguments.rb +161 -0
  16. data/lib/command_kit/arguments/argument.rb +111 -0
  17. data/lib/command_kit/arguments/argument_value.rb +81 -0
  18. data/lib/command_kit/arguments/usage.rb +6 -0
  19. data/lib/command_kit/colors.rb +355 -0
  20. data/lib/command_kit/command.rb +42 -0
  21. data/lib/command_kit/command_name.rb +95 -0
  22. data/lib/command_kit/commands.rb +299 -0
  23. data/lib/command_kit/commands/auto_load.rb +153 -0
  24. data/lib/command_kit/commands/auto_load/subcommand.rb +90 -0
  25. data/lib/command_kit/commands/auto_require.rb +138 -0
  26. data/lib/command_kit/commands/command.rb +12 -0
  27. data/lib/command_kit/commands/help.rb +43 -0
  28. data/lib/command_kit/commands/parent_command.rb +21 -0
  29. data/lib/command_kit/commands/subcommand.rb +51 -0
  30. data/lib/command_kit/console.rb +141 -0
  31. data/lib/command_kit/description.rb +89 -0
  32. data/lib/command_kit/env.rb +43 -0
  33. data/lib/command_kit/env/home.rb +71 -0
  34. data/lib/command_kit/env/path.rb +71 -0
  35. data/lib/command_kit/examples.rb +99 -0
  36. data/lib/command_kit/exception_handler.rb +55 -0
  37. data/lib/command_kit/help.rb +62 -0
  38. data/lib/command_kit/help/man.rb +125 -0
  39. data/lib/command_kit/inflector.rb +84 -0
  40. data/lib/command_kit/main.rb +103 -0
  41. data/lib/command_kit/options.rb +179 -0
  42. data/lib/command_kit/options/option.rb +171 -0
  43. data/lib/command_kit/options/option_value.rb +90 -0
  44. data/lib/command_kit/options/parser.rb +227 -0
  45. data/lib/command_kit/options/quiet.rb +53 -0
  46. data/lib/command_kit/options/usage.rb +6 -0
  47. data/lib/command_kit/options/verbose.rb +55 -0
  48. data/lib/command_kit/options/version.rb +62 -0
  49. data/lib/command_kit/os.rb +47 -0
  50. data/lib/command_kit/pager.rb +115 -0
  51. data/lib/command_kit/printing.rb +32 -0
  52. data/lib/command_kit/printing/indent.rb +78 -0
  53. data/lib/command_kit/program_name.rb +57 -0
  54. data/lib/command_kit/stdio.rb +138 -0
  55. data/lib/command_kit/usage.rb +102 -0
  56. data/lib/command_kit/version.rb +4 -0
  57. data/lib/command_kit/xdg.rb +138 -0
  58. data/spec/arguments/argument_spec.rb +169 -0
  59. data/spec/arguments/argument_value_spec.rb +126 -0
  60. data/spec/arguments_spec.rb +213 -0
  61. data/spec/colors_spec.rb +470 -0
  62. data/spec/command_kit_spec.rb +8 -0
  63. data/spec/command_name_spec.rb +130 -0
  64. data/spec/command_spec.rb +49 -0
  65. data/spec/commands/auto_load/subcommand_spec.rb +82 -0
  66. data/spec/commands/auto_load_spec.rb +128 -0
  67. data/spec/commands/auto_require_spec.rb +142 -0
  68. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +10 -0
  69. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +10 -0
  70. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +10 -0
  71. data/spec/commands/help_spec.rb +66 -0
  72. data/spec/commands/parent_command_spec.rb +40 -0
  73. data/spec/commands/subcommand_spec.rb +99 -0
  74. data/spec/commands_spec.rb +767 -0
  75. data/spec/console_spec.rb +201 -0
  76. data/spec/description_spec.rb +203 -0
  77. data/spec/env/home_spec.rb +46 -0
  78. data/spec/env/path_spec.rb +78 -0
  79. data/spec/env_spec.rb +123 -0
  80. data/spec/examples_spec.rb +235 -0
  81. data/spec/exception_handler_spec.rb +103 -0
  82. data/spec/help_spec.rb +119 -0
  83. data/spec/inflector_spec.rb +104 -0
  84. data/spec/main_spec.rb +179 -0
  85. data/spec/options/option_spec.rb +258 -0
  86. data/spec/options/option_value_spec.rb +67 -0
  87. data/spec/options/parser_spec.rb +265 -0
  88. data/spec/options_spec.rb +137 -0
  89. data/spec/os_spec.rb +46 -0
  90. data/spec/pager_spec.rb +154 -0
  91. data/spec/printing/indent_spec.rb +130 -0
  92. data/spec/printing_spec.rb +76 -0
  93. data/spec/program_name_spec.rb +62 -0
  94. data/spec/spec_helper.rb +6 -0
  95. data/spec/stdio_spec.rb +264 -0
  96. data/spec/usage_spec.rb +237 -0
  97. data/spec/xdg_spec.rb +191 -0
  98. metadata +156 -0
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/arguments/argument_value'
3
+
4
+ describe CommandKit::Arguments::ArgumentValue do
5
+ let(:type) { String }
6
+ let(:required) { false }
7
+ let(:default) { "foo" }
8
+ let(:usage) { 'FOO' }
9
+
10
+ subject do
11
+ described_class.new(
12
+ type: type,
13
+ required: required,
14
+ default: default,
15
+ usage: usage
16
+ )
17
+ end
18
+
19
+ describe "#initialize" do
20
+ it "must require a usage: keyword"do
21
+ expect {
22
+ described_class.new(type: type, required: required, default: default)
23
+ }.to raise_error(ArgumentError)
24
+ end
25
+
26
+ context "when type: is given" do
27
+ subject { described_class.new(type: type, usage: usage) }
28
+
29
+ it "must set #type" do
30
+ expect(subject.type).to eq(type)
31
+ end
32
+ end
33
+
34
+ context "when type: is not given" do
35
+ subject { described_class.new(usage: usage) }
36
+
37
+ it "must default to nil" do
38
+ expect(subject.type).to be_nil
39
+ end
40
+ end
41
+
42
+ context "when required: is given" do
43
+ subject { described_class.new(required: required, usage: usage) }
44
+
45
+ it "must set #required" do
46
+ expect(subject.required).to eq(required)
47
+ end
48
+ end
49
+
50
+ context "when required: is not given" do
51
+ subject { described_class.new(usage: usage) }
52
+
53
+ it "must default to true" do
54
+ expect(subject.required).to be(true)
55
+ end
56
+ end
57
+
58
+ context "when default: is given" do
59
+ subject { described_class.new(default: default, usage: usage) }
60
+
61
+ it "must set #default" do
62
+ expect(subject.default).to eq(default)
63
+ end
64
+ end
65
+
66
+ context "when default: is not given" do
67
+ subject { described_class.new(usage: usage) }
68
+
69
+ it "must default to nil" do
70
+ expect(subject.default).to be_nil
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#required?" do
76
+ context "when required: is initialized with true" do
77
+ let(:required) { true }
78
+
79
+ it { expect(subject.required?).to be(true) }
80
+ end
81
+
82
+ context "when required: is initialized with false" do
83
+ let(:required) { false }
84
+
85
+ it { expect(subject.required?).to be(false) }
86
+ end
87
+ end
88
+
89
+ describe "#optional?" do
90
+ context "when required: is initialized with true" do
91
+ let(:required) { true }
92
+
93
+ it { expect(subject.optional?).to be(false) }
94
+ end
95
+
96
+ context "when required: is initialized with false" do
97
+ let(:required) { false }
98
+
99
+ it { expect(subject.optional?).to be(true) }
100
+ end
101
+ end
102
+
103
+ describe "#default_value" do
104
+ context "when initialized with a default: that responded to #call" do
105
+ let(:default) do
106
+ ->{ [] }
107
+ end
108
+
109
+ it "must call the default #call method" do
110
+ expect(subject.default_value).to eq(default.call)
111
+ end
112
+ end
113
+
114
+ context "when initialized with a default: that it's an Object" do
115
+ let(:default) { "" }
116
+
117
+ it "must return the default: object" do
118
+ expect(subject.default_value).to eq(default)
119
+ end
120
+
121
+ it "must duplicate the default: object each time" do
122
+ expect(subject.default_value).to_not be(subject.default_value)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,213 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/arguments'
3
+
4
+ describe Arguments do
5
+ module TestArguments
6
+ class ImplicitCmd
7
+ include CommandKit::Arguments
8
+ end
9
+ end
10
+
11
+ let(:command_class) { TestArguments::ImplicitCmd }
12
+
13
+ describe ".arguments" do
14
+ subject { TestArguments::ImplicitCmd }
15
+
16
+ context "when no arguments have been defined" do
17
+ it "should default to {}" do
18
+ expect(subject.arguments).to eq({})
19
+ end
20
+ end
21
+
22
+ context "when a arguments is explicitly set" do
23
+ module TestArguments
24
+ class ExplicitCmd
25
+ include CommandKit::Arguments
26
+ argument :foo, desc: 'Foo option'
27
+ argument :bar, desc: 'Bar option'
28
+ end
29
+ end
30
+
31
+ subject { TestArguments::ExplicitCmd }
32
+
33
+ it "must return the explicitly set arguments" do
34
+ expect(subject.arguments.keys).to eq([:foo, :bar])
35
+ end
36
+ end
37
+
38
+ context "when the command class inherites from another class" do
39
+ context "but no arguments are defined" do
40
+ module TestArguments
41
+ class BaseCmd
42
+ include CommandKit::Arguments
43
+ end
44
+
45
+ class InheritedCmd < BaseCmd
46
+ end
47
+ end
48
+
49
+ subject { TestArguments::InheritedCmd }
50
+
51
+ it "must search each class then return {}"do
52
+ expect(subject.arguments).to eq({})
53
+ end
54
+ end
55
+
56
+ module TestArguments
57
+ class ExplicitBaseCmd
58
+ include CommandKit::Arguments
59
+ argument :foo, desc: 'Foo option'
60
+ argument :bar, desc: 'Bar option'
61
+ end
62
+ end
63
+
64
+ context "when the superclass defines arguments" do
65
+ module TestArguments
66
+ class ImplicitInheritedCmd < ExplicitBaseCmd
67
+ end
68
+ end
69
+
70
+ let(:super_subject) { TestArguments::ExplicitBaseCmd }
71
+ subject { TestArguments::ImplicitInheritedCmd }
72
+
73
+ it "must inherit the superclass'es arguments" do
74
+ expect(subject.arguments).to eq(super_subject.arguments)
75
+ end
76
+
77
+ it "must not change the superclass'es arguments" do
78
+ expect(super_subject.arguments.keys).to eq([:foo, :bar])
79
+ end
80
+ end
81
+
82
+ context "when the subclass defines arguments" do
83
+ module TestArguments
84
+ class ImplicitBaseCmd
85
+ include CommandKit::Arguments
86
+ end
87
+
88
+ class ExplicitInheritedCmd < ImplicitBaseCmd
89
+ argument :baz, desc: 'Baz option'
90
+ argument :qux, desc: 'Qux option'
91
+ end
92
+ end
93
+
94
+ let(:super_subject) { TestArguments::ImplicitBaseCmd }
95
+ subject { TestArguments::ExplicitInheritedCmd }
96
+
97
+ it "must return the subclass'es arguments" do
98
+ expect(subject.arguments.keys).to eq([:baz, :qux])
99
+ end
100
+
101
+ it "must not change the superclass'es arguments" do
102
+ expect(super_subject.arguments).to eq({})
103
+ end
104
+ end
105
+
106
+ context "when subclass overrides the superclass's argumentss" do
107
+ module TestArguments
108
+ class ExplicitOverridingInheritedCmd < ExplicitBaseCmd
109
+ argument :foo, desc: "Overriden foo option"
110
+ end
111
+ end
112
+
113
+ let(:super_subject) { TestArguments::ExplicitBaseCmd }
114
+ subject { TestArguments::ExplicitOverridingInheritedCmd }
115
+
116
+ it "must combine the superclass'es arguments with the subclass'es" do
117
+ expect(subject.arguments.keys).to eq([:foo, :bar])
118
+ expect(subject.arguments[:foo].desc).to eq("Overriden foo option")
119
+ expect(subject.arguments[:bar].desc).to eq("Bar option")
120
+ end
121
+
122
+ it "must not change the superclass'es arguments" do
123
+ expect(super_subject.arguments.keys).to eq([:foo, :bar])
124
+ expect(super_subject.arguments[:foo].desc).to eq("Foo option")
125
+ expect(super_subject.arguments[:bar].desc).to eq("Bar option")
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ subject { command_class.new }
132
+
133
+ describe "#help_arguments" do
134
+ context "when #arguments returns {}" do
135
+ module TestArguments
136
+ class NoArguments
137
+ include CommandKit::Arguments
138
+ end
139
+ end
140
+
141
+ let(:command_class) { TestArguments::NoArguments }
142
+ subject { command_class.new }
143
+
144
+ it "must print out the arguments" do
145
+ expect { subject.help_arguments }.to_not output.to_stdout
146
+ end
147
+ end
148
+
149
+ context "when #arguments returns an Array" do
150
+ module TestArguments
151
+ class MultipleArguments
152
+ include CommandKit::Arguments
153
+
154
+ argument :foo, desc: "Foo option"
155
+ argument :bar, desc: "Bar option"
156
+ argument :baz, desc: "Baz option"
157
+ end
158
+ end
159
+
160
+ let(:command_class) { TestArguments::MultipleArguments }
161
+ subject { command_class.new }
162
+
163
+ let(:foo_argument) { command_class.arguments[:foo] }
164
+ let(:bar_argument) { command_class.arguments[:bar] }
165
+ let(:baz_argument) { command_class.arguments[:baz] }
166
+
167
+ it "must print out the 'Arguments:' section header and the arguments" do
168
+ expect { subject.help_arguments }.to output(
169
+ [
170
+ '',
171
+ "Arguments:",
172
+ " #{foo_argument.usage.ljust(33)}#{foo_argument.desc}",
173
+ " #{bar_argument.usage.ljust(33)}#{bar_argument.desc}",
174
+ " #{baz_argument.usage.ljust(33)}#{baz_argument.desc}",
175
+ ''
176
+ ].join($/)
177
+ ).to_stdout
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "#help" do
183
+ it "must call #help_arguments" do
184
+ expect(subject).to receive(:help_arguments)
185
+
186
+ subject.help
187
+ end
188
+
189
+ context "when the superclass defines it's own #help method" do
190
+ module TestDescription
191
+ class SuperclassHelpMethod
192
+ def help
193
+ puts 'superclass'
194
+ end
195
+ end
196
+
197
+ class InheritedHelpMethod < SuperclassHelpMethod
198
+ include CommandKit::Arguments
199
+ end
200
+ end
201
+
202
+ let(:super_command_class) { TestDescription::SuperclassHelpMethod }
203
+ let(:command_class) { TestDescription::InheritedHelpMethod }
204
+
205
+ it "must call the superclass'es #help method first" do
206
+ expect_any_instance_of(super_command_class).to receive(:help)
207
+ expect(subject).to receive(:help_arguments)
208
+
209
+ subject.help
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,470 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/colors'
3
+
4
+ describe Colors do
5
+ module TestColors
6
+ class TestCommand
7
+ include CommandKit::Colors
8
+ end
9
+ end
10
+
11
+ let(:command_class) { TestColors::TestCommand }
12
+ subject { command_class.new }
13
+
14
+ it { expect(described_class).to include(Stdio) }
15
+ it { expect(described_class).to include(Env) }
16
+
17
+ describe Colors::ANSI do
18
+ subject { described_class }
19
+
20
+ describe "RESET" do
21
+ it { expect(subject::RESET).to eq("\e[0m") }
22
+ end
23
+
24
+ describe "CLEAR" do
25
+ it { expect(subject::CLEAR).to eq("\e[0m") }
26
+ end
27
+
28
+ describe "BOLD" do
29
+ it { expect(subject::BOLD).to eq("\e[1m") }
30
+ end
31
+
32
+ describe "RESET_INTENSITY" do
33
+ it { expect(subject::RESET_INTENSITY).to eq("\e[22m") }
34
+ end
35
+
36
+ describe "BLACK" do
37
+ it { expect(subject::BLACK).to eq("\e[30m") }
38
+ end
39
+
40
+ describe "RED" do
41
+ it { expect(subject::RED).to eq("\e[31m") }
42
+ end
43
+
44
+ describe "GREEN" do
45
+ it { expect(subject::GREEN).to eq("\e[32m") }
46
+ end
47
+
48
+ describe "YELLOW" do
49
+ it { expect(subject::YELLOW).to eq("\e[33m") }
50
+ end
51
+
52
+ describe "BLUE" do
53
+ it { expect(subject::BLUE).to eq("\e[34m") }
54
+ end
55
+
56
+ describe "MAGENTA" do
57
+ it { expect(subject::MAGENTA).to eq("\e[35m") }
58
+ end
59
+
60
+ describe "CYAN" do
61
+ it { expect(subject::CYAN).to eq("\e[36m") }
62
+ end
63
+
64
+ describe "WHITE" do
65
+ it { expect(subject::WHITE).to eq("\e[37m") }
66
+ end
67
+
68
+ describe "RESET_COLOR" do
69
+ it { expect(subject::RESET_COLOR).to eq("\e[39m") }
70
+ end
71
+
72
+ let(:str) { 'foo' }
73
+
74
+ describe ".reset" do
75
+ it { expect(subject.reset).to eq(described_class::RESET) }
76
+ end
77
+
78
+ describe ".clear" do
79
+ it { expect(subject.clear).to eq(described_class::CLEAR) }
80
+ end
81
+
82
+ describe ".bold" do
83
+ context "when given a string" do
84
+ it "must wrap the string with \\e[1m and \\e[22m" do
85
+ expect(subject.bold(str)).to eq("\e[1m#{str}\e[22m")
86
+ end
87
+ end
88
+
89
+ context "when given no arguments" do
90
+ it { expect(subject.bold).to eq("\e[1m") }
91
+ end
92
+ end
93
+
94
+ describe ".black" do
95
+ context "when given a string" do
96
+ it "must wrap the string with \\e[30m and \\e[39m" do
97
+ expect(subject.black(str)).to eq("\e[30m#{str}\e[39m")
98
+ end
99
+ end
100
+
101
+ context "when given no arguments" do
102
+ it { expect(subject.black).to eq("\e[30m") }
103
+ end
104
+ end
105
+
106
+ describe ".red" do
107
+ context "when given a string" do
108
+ it "must wrap the string with \\e[31m and \\e[39m" do
109
+ expect(subject.red(str)).to eq("\e[31m#{str}\e[39m")
110
+ end
111
+ end
112
+
113
+ context "when given no arguments" do
114
+ it { expect(subject.red).to eq("\e[31m") }
115
+ end
116
+ end
117
+
118
+ describe ".green" do
119
+ context "when given a string" do
120
+ it "must wrap the string with \\e[32m and \\e[39m" do
121
+ expect(subject.green(str)).to eq("\e[32m#{str}\e[39m")
122
+ end
123
+ end
124
+
125
+ context "when given no arguments" do
126
+ it { expect(subject.green).to eq("\e[32m") }
127
+ end
128
+ end
129
+
130
+ describe ".yellow" do
131
+ context "when given a string" do
132
+ it "must wrap the string with \\e[33m and \\e[39m" do
133
+ expect(subject.yellow(str)).to eq("\e[33m#{str}\e[39m")
134
+ end
135
+ end
136
+
137
+ context "when given no arguments" do
138
+ it { expect(subject.yellow).to eq("\e[33m") }
139
+ end
140
+ end
141
+
142
+ describe ".blue" do
143
+ context "when given a string" do
144
+ it "must wrap the string with \\e[34m and \\e[39m" do
145
+ expect(subject.blue(str)).to eq("\e[34m#{str}\e[39m")
146
+ end
147
+ end
148
+
149
+ context "when given no arguments" do
150
+ it { expect(subject.blue).to eq("\e[34m") }
151
+ end
152
+ end
153
+
154
+ describe ".magenta" do
155
+ context "when given a string" do
156
+ it "must wrap the string with \\e[35m and \\e[39m" do
157
+ expect(subject.magenta(str)).to eq("\e[35m#{str}\e[39m")
158
+ end
159
+ end
160
+
161
+ context "when given no arguments" do
162
+ it { expect(subject.magenta).to eq("\e[35m") }
163
+ end
164
+ end
165
+
166
+ describe ".cyan" do
167
+ context "when given a string" do
168
+ it "must wrap the string with \\e[36m and \\e[39m" do
169
+ expect(subject.cyan(str)).to eq("\e[36m#{str}\e[39m")
170
+ end
171
+ end
172
+
173
+ context "when given no arguments" do
174
+ it { expect(subject.cyan).to eq("\e[36m") }
175
+ end
176
+ end
177
+
178
+ describe ".white" do
179
+ context "when given a string" do
180
+ it "must wrap the string with \\e[37m and \\e[39m" do
181
+ expect(subject.white(str)).to eq("\e[37m#{str}\e[39m")
182
+ end
183
+ end
184
+
185
+ context "when given no arguments" do
186
+ it { expect(subject.white).to eq("\e[37m") }
187
+ end
188
+ end
189
+ end
190
+
191
+ describe Colors::PlainText do
192
+ subject { described_class }
193
+
194
+ let(:str) { 'foo' }
195
+
196
+ describe "RESET" do
197
+ it { expect(subject::RESET).to eq('') }
198
+ end
199
+
200
+ describe "CLEAR" do
201
+ it { expect(subject::CLEAR).to eq('') }
202
+ end
203
+
204
+ describe "BOLD" do
205
+ it { expect(subject::BOLD).to eq('') }
206
+ end
207
+
208
+ describe "RESET_INTENSITY" do
209
+ it { expect(subject::RESET_INTENSITY).to eq('') }
210
+ end
211
+
212
+ describe "BLACK" do
213
+ it { expect(subject::BLACK).to eq('') }
214
+ end
215
+
216
+ describe "RED" do
217
+ it { expect(subject::RED).to eq('') }
218
+ end
219
+
220
+ describe "GREEN" do
221
+ it { expect(subject::GREEN).to eq('') }
222
+ end
223
+
224
+ describe "YELLOW" do
225
+ it { expect(subject::YELLOW).to eq('') }
226
+ end
227
+
228
+ describe "BLUE" do
229
+ it { expect(subject::BLUE).to eq('') }
230
+ end
231
+
232
+ describe "MAGENTA" do
233
+ it { expect(subject::MAGENTA).to eq('') }
234
+ end
235
+
236
+ describe "CYAN" do
237
+ it { expect(subject::CYAN).to eq('') }
238
+ end
239
+
240
+ describe "WHITE" do
241
+ it { expect(subject::WHITE).to eq('') }
242
+ end
243
+
244
+ describe "RESET_COLOR" do
245
+ it { expect(subject::RESET_COLOR).to eq('') }
246
+ end
247
+
248
+ describe ".reset" do
249
+ it { expect(subject.reset).to eq('') }
250
+ end
251
+
252
+ describe ".clear" do
253
+ it { expect(subject.clear).to eq('') }
254
+ end
255
+
256
+ describe ".bold" do
257
+ context "when given a string" do
258
+ it "must return that string" do
259
+ expect(subject.bold(str)).to eq(str)
260
+ end
261
+ end
262
+
263
+ context "when given no arguments" do
264
+ it { expect(subject.bold).to eq('') }
265
+ end
266
+ end
267
+
268
+ describe ".black" do
269
+ context "when given a string" do
270
+ it "must return that string" do
271
+ expect(subject.black(str)).to eq(str)
272
+ end
273
+ end
274
+
275
+ context "when given no arguments" do
276
+ it { expect(subject.black).to eq('') }
277
+ end
278
+ end
279
+
280
+ describe ".red" do
281
+ context "when given a string" do
282
+ it "must return that string" do
283
+ expect(subject.red(str)).to eq(str)
284
+ end
285
+ end
286
+
287
+ context "when given no arguments" do
288
+ it { expect(subject.red).to eq('') }
289
+ end
290
+ end
291
+
292
+ describe ".green" do
293
+ context "when given a string" do
294
+ it "must return that string" do
295
+ expect(subject.green(str)).to eq(str)
296
+ end
297
+ end
298
+
299
+ context "when given no arguments" do
300
+ it { expect(subject.green).to eq('') }
301
+ end
302
+ end
303
+
304
+ describe ".yellow" do
305
+ context "when given a string" do
306
+ it "must return that string" do
307
+ expect(subject.yellow(str)).to eq(str)
308
+ end
309
+ end
310
+
311
+ context "when given no arguments" do
312
+ it { expect(subject.yellow).to eq('') }
313
+ end
314
+ end
315
+
316
+ describe ".blue" do
317
+ context "when given a string" do
318
+ it "must return that string" do
319
+ expect(subject.blue(str)).to eq(str)
320
+ end
321
+ end
322
+
323
+ context "when given no arguments" do
324
+ it { expect(subject.blue).to eq('') }
325
+ end
326
+ end
327
+
328
+ describe ".magenta" do
329
+ context "when given a string" do
330
+ it "must return that string" do
331
+ expect(subject.magenta(str)).to eq(str)
332
+ end
333
+ end
334
+
335
+ context "when given no arguments" do
336
+ it { expect(subject.magenta).to eq('') }
337
+ end
338
+ end
339
+
340
+ describe ".cyan" do
341
+ context "when given a string" do
342
+ it "must return that string" do
343
+ expect(subject.cyan(str)).to eq(str)
344
+ end
345
+ end
346
+
347
+ context "when given no arguments" do
348
+ it { expect(subject.cyan).to eq('') }
349
+ end
350
+ end
351
+
352
+ describe ".white" do
353
+ context "when given a string" do
354
+ it "must return that string" do
355
+ expect(subject.white(str)).to eq(str)
356
+ end
357
+ end
358
+
359
+ context "when given no arguments" do
360
+ it { expect(subject.white).to eq('') }
361
+ end
362
+ end
363
+ end
364
+
365
+ describe "#ansi?" do
366
+ context "when TERM='dumb'" do
367
+ subject { command_class.new(env: {'TERM' => 'dumb'}) }
368
+
369
+ it { expect(subject.ansi?).to be(false) }
370
+ end
371
+
372
+ context "when stdout is a TTY" do
373
+ let(:stdout) { StringIO.new }
374
+ subject { command_class.new(stdout: stdout) }
375
+
376
+ before { allow(stdout).to receive(:tty?).and_return(true) }
377
+
378
+ it { expect(subject.ansi?).to be(true) }
379
+ end
380
+
381
+ context "when stdout is not a TTY" do
382
+ let(:stdout) { StringIO.new }
383
+ subject { command_class.new(stdout: stdout) }
384
+
385
+ it { expect(subject.ansi?).to be(false) }
386
+ end
387
+
388
+ context "when given an alternate stream" do
389
+ context "and the alternate stream is a TTY" do
390
+ let(:stream) { StringIO.new }
391
+
392
+ before { allow(stream).to receive(:tty?).and_return(true) }
393
+
394
+ it { expect(subject.ansi?(stream)).to be(true) }
395
+ end
396
+
397
+ context "but the alternate stream is not a TTY" do
398
+ let(:stream) { StringIO.new }
399
+
400
+ it { expect(subject.ansi?(stream)).to be(false) }
401
+ end
402
+ end
403
+ end
404
+
405
+ describe "#colors" do
406
+ context "when stdout supports ANSI" do
407
+ let(:stdout) { StringIO.new }
408
+ subject { command_class.new(stdout: stdout) }
409
+
410
+ before { allow(stdout).to receive(:tty?).and_return(true) }
411
+
412
+ it { expect(subject.colors).to be(Colors::ANSI) }
413
+
414
+ context "when a block is given" do
415
+ it do
416
+ expect { |b|
417
+ subject.colors(&b)
418
+ }.to yield_with_args(Colors::ANSI)
419
+ end
420
+ end
421
+ end
422
+
423
+ context "when stdout does not support ANSI" do
424
+ let(:stdout) { StringIO.new }
425
+ subject { command_class.new(stdout: stdout) }
426
+
427
+ it { expect(subject.colors).to be(Colors::PlainText) }
428
+
429
+ context "when a block is given" do
430
+ it do
431
+ expect { |b|
432
+ subject.colors(&b)
433
+ }.to yield_with_args(Colors::PlainText)
434
+ end
435
+ end
436
+ end
437
+
438
+ context "when given an alternate stream" do
439
+ context "and the alternate stream supports ANSI" do
440
+ let(:stream) { StringIO.new }
441
+
442
+ before { allow(stream).to receive(:tty?).and_return(true) }
443
+
444
+ it { expect(subject.colors(stream)).to be(Colors::ANSI) }
445
+
446
+ context "when a block is given" do
447
+ it do
448
+ expect { |b|
449
+ subject.colors(stream,&b)
450
+ }.to yield_with_args(Colors::ANSI)
451
+ end
452
+ end
453
+ end
454
+
455
+ context "but the alternate stream does not support ANSI" do
456
+ let(:stream) { StringIO.new }
457
+
458
+ it { expect(subject.colors(stream)).to be(Colors::PlainText) }
459
+
460
+ context "when a block is given" do
461
+ it do
462
+ expect { |b|
463
+ subject.colors(stream,&b)
464
+ }.to yield_with_args(Colors::PlainText)
465
+ end
466
+ end
467
+ end
468
+ end
469
+ end
470
+ end