clive 0.8.1 → 1.0.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 (52) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +328 -227
  3. data/lib/clive.rb +130 -50
  4. data/lib/clive/argument.rb +170 -0
  5. data/lib/clive/arguments.rb +139 -0
  6. data/lib/clive/arguments/parser.rb +210 -0
  7. data/lib/clive/base.rb +189 -0
  8. data/lib/clive/command.rb +342 -444
  9. data/lib/clive/error.rb +66 -0
  10. data/lib/clive/formatter.rb +57 -141
  11. data/lib/clive/formatter/colour.rb +37 -0
  12. data/lib/clive/formatter/plain.rb +172 -0
  13. data/lib/clive/option.rb +185 -75
  14. data/lib/clive/option/runner.rb +163 -0
  15. data/lib/clive/output.rb +141 -16
  16. data/lib/clive/parser.rb +180 -87
  17. data/lib/clive/struct_hash.rb +109 -0
  18. data/lib/clive/type.rb +117 -0
  19. data/lib/clive/type/definitions.rb +170 -0
  20. data/lib/clive/type/lookup.rb +23 -0
  21. data/lib/clive/version.rb +3 -3
  22. data/spec/clive/a_cli_spec.rb +245 -0
  23. data/spec/clive/argument_spec.rb +148 -0
  24. data/spec/clive/arguments/parser_spec.rb +35 -0
  25. data/spec/clive/arguments_spec.rb +191 -0
  26. data/spec/clive/command_spec.rb +276 -209
  27. data/spec/clive/formatter/colour_spec.rb +129 -0
  28. data/spec/clive/formatter/plain_spec.rb +129 -0
  29. data/spec/clive/option/runner_spec.rb +92 -0
  30. data/spec/clive/option_spec.rb +149 -23
  31. data/spec/clive/output_spec.rb +86 -2
  32. data/spec/clive/parser_spec.rb +201 -81
  33. data/spec/clive/struct_hash_spec.rb +82 -0
  34. data/spec/clive/type/definitions_spec.rb +312 -0
  35. data/spec/clive/type_spec.rb +107 -0
  36. data/spec/clive_spec.rb +60 -0
  37. data/spec/extras/expectations.rb +86 -0
  38. data/spec/extras/focus.rb +22 -0
  39. data/spec/helper.rb +35 -0
  40. metadata +56 -36
  41. data/lib/clive/bool.rb +0 -67
  42. data/lib/clive/exceptions.rb +0 -54
  43. data/lib/clive/flag.rb +0 -199
  44. data/lib/clive/switch.rb +0 -31
  45. data/lib/clive/tokens.rb +0 -141
  46. data/spec/clive/bool_spec.rb +0 -54
  47. data/spec/clive/flag_spec.rb +0 -117
  48. data/spec/clive/formatter_spec.rb +0 -108
  49. data/spec/clive/switch_spec.rb +0 -14
  50. data/spec/clive/tokens_spec.rb +0 -38
  51. data/spec/shared_specs.rb +0 -16
  52. data/spec/spec_helper.rb +0 -12
@@ -0,0 +1,35 @@
1
+ $: << File.dirname(__FILE__) + '/../..'
2
+ require 'helper'
3
+
4
+ class Clive::Arguments::ParserSubject < Clive::Arguments::Parser
5
+ attr_reader :opts
6
+ end
7
+
8
+ describe Clive::Arguments::Parser do
9
+
10
+ subject { Clive::Arguments::ParserSubject }
11
+
12
+ describe '#initialize' do
13
+ it 'normalises key names' do
14
+ subject.new(:kind => String, :in => %w(a b c)).opts.keys.must_include :type, :within
15
+ end
16
+ end
17
+
18
+ describe '#to_a' do
19
+ it 'returns an array of hashes' do
20
+ subject.new(:type => [Integer, Time]).to_a.must_equal [{:type => Integer, :name => 'arg'},
21
+ {:type => Time, :name => 'arg'}]
22
+ end
23
+ end
24
+
25
+ describe '#to_args' do
26
+ it 'returns an array of Argument instances' do
27
+ args = subject.new(:args => '<a> <b> [<c>]', :type => [Integer, Time]).to_args
28
+ args.size.must_equal 3
29
+ args[0].must_be_argument :name => :a, :type => Clive::Type::Integer
30
+ args[1].must_be_argument :name => :b, :type => Clive::Type::Time
31
+ args[2].must_be_argument :name => :c, :optional => true
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,191 @@
1
+ $: << File.dirname(__FILE__) + '/..'
2
+ require 'helper'
3
+
4
+ describe Clive::Arguments do
5
+
6
+ subject {
7
+ Clive::Arguments.create :args => '[<a>] <b> <c> [<d>]',
8
+ :type => [Integer] * 4,
9
+ :constraint => [:even?, :odd?] * 2
10
+ }
11
+
12
+ describe '.create' do
13
+ it 'parses the options passed using Parser' do
14
+ parser, opts = mock, stub
15
+ parser.expects(:to_args).returns([])
16
+ Clive::Arguments::Parser.expects(:new).with(opts).returns(parser)
17
+ Clive::Arguments.create opts
18
+ end
19
+ it 'returns a list of Argument instances' do
20
+ a = Clive::Arguments.create :args => '[<a>] <b>', :as => [Integer, nil], :in => [1..5, nil]
21
+ a[0].must_be_argument :name => :a, :optional => true, :within => 1..5,
22
+ :type => Clive::Type::Integer
23
+ a[1].must_be_argument :name => :b, :optional => false
24
+ end
25
+ end
26
+
27
+ describe '#zip' do
28
+ it 'zips arguments properly' do
29
+ def subject.simple_zip(other); zip(other).map(&:last); end
30
+
31
+ # These behaviours are definitely what should happen
32
+ subject.simple_zip(%w(1 4)).must_equal [nil, '1', '4', nil]
33
+ subject.simple_zip(%w(1 4 3)).must_equal [nil, '1', '4', '3']
34
+ subject.simple_zip(%w(2 1 4 3)).must_equal ['2', '1', '4', '3']
35
+ subject.simple_zip(%w(2 1 4)).must_equal ['2', '1', '4', nil]
36
+
37
+ # These behaviours may change
38
+ subject.simple_zip(%w(2)).must_equal [nil, nil, '2', nil]
39
+ subject.simple_zip(%w(1)).must_equal [nil, '1', nil, nil]
40
+ subject.simple_zip(%w(2 1)).must_equal [nil, nil, '2', nil]
41
+ end
42
+ end
43
+
44
+ describe '#to_s' do
45
+ subject {
46
+ Clive::Arguments.new( [
47
+ Clive::Argument.new(:a),
48
+ Clive::Argument.new(:b, :optional => true),
49
+ Clive::Argument.new(:c, :optional => true),
50
+ Clive::Argument.new(:d)
51
+ ])
52
+ }
53
+
54
+ it 'removes extra square brackets' do
55
+ subject.to_s.must_equal "<a> [<b> <c>] <d>"
56
+ end
57
+ end
58
+
59
+ describe '#min' do
60
+ it 'returns the number of non-optional arguments' do
61
+ subject.min.must_equal 2
62
+ end
63
+ end
64
+
65
+ describe '#max' do
66
+ it 'returns the total number of arguments' do
67
+ subject.max.must_equal 4
68
+ end
69
+ end
70
+
71
+ describe '#possible?' do
72
+ it 'is true if each argument is possible and list is not too long' do
73
+ subject.must_be :possible?, [2]
74
+ subject.must_be :possible?, [2, 3]
75
+ subject.must_be :possible?, [2, 3, 4]
76
+ subject.must_be :possible?, [2, 3, 4, 5]
77
+ end
78
+
79
+ it 'is false if the list is too long' do
80
+ subject.wont_be :possible?, [2, 3, 4, 5, 6]
81
+ end
82
+
83
+ it 'is true even if an argument is not possible' do
84
+ subject.must_be :possible?, ['hello']
85
+ end
86
+
87
+ it 'single' do
88
+ subject = Clive::Arguments.create :arg => '<name>'
89
+ subject.must_be :possible?, []
90
+ subject.must_be :possible?, %w(John)
91
+ subject.wont_be :possible?, %w(John Doe)
92
+ end
93
+
94
+ it 'single optional' do
95
+ subject = Clive::Arguments.create :arg => '[<name>]'
96
+ subject.must_be :possible?, []
97
+ subject.must_be :possible?, %w(John)
98
+ subject.wont_be :possible?, %w(John Doe)
99
+ end
100
+
101
+ it 'single with constraint' do
102
+ subject = Clive::Arguments.create :arg => '<name>', :constraint => proc {|i| i.size == 4 }
103
+ subject.must_be :possible?, []
104
+ subject.must_be :possible?, %w(John)
105
+ subject.wont_be :possible?, %w(James)
106
+ subject.wont_be :possible?, %w(John Doe)
107
+ end
108
+
109
+ it 'single optional with constraint' do
110
+ subject = Clive::Arguments.create :arg => '[<name>]', :constraint => proc {|i| i.size == 4 }
111
+ subject.must_be :possible?, []
112
+ subject.must_be :possible?, %w(John)
113
+ subject.wont_be :possible?, %w(James)
114
+ subject.wont_be :possible?, %w(John Doe)
115
+ end
116
+
117
+ it 'multiple surrounding' do
118
+ subject = Clive::Arguments.create :args => '<first> [<middle>] <last>'
119
+ subject.must_be :possible?, []
120
+ subject.must_be :possible?, %w(John)
121
+ subject.must_be :possible?, %w(John Doe)
122
+ subject.must_be :possible?, %w(John David Doe)
123
+ subject.wont_be :possible?, %w(John David James Doe)
124
+ end
125
+
126
+ it 'multiple middle' do
127
+ subject = Clive::Arguments.create :args => '[<first>] <middle> [<last>]'
128
+ subject.must_be :possible?, []
129
+ subject.must_be :possible?, %w(John)
130
+ subject.must_be :possible?, %w(John Doe)
131
+ subject.must_be :possible?, %w(John David Doe)
132
+ subject.wont_be :possible?, %w(John David James Doe)
133
+ end
134
+
135
+ it 'multiple surrounding with constraints' do
136
+ subject = Clive::Arguments.create :args => '<first> [<middle>] <last>',
137
+ :constraint => [proc {|i| i.size == 3 }, proc {|i| i.size == 4 }, proc {|i| i.size == 5 }]
138
+ subject.must_be :possible?, []
139
+
140
+ subject.must_be :possible?, %w(Joe) # [Joe, ..., ...]
141
+ subject.wont_be :possible?, %w(Gary) # [!!!, Gary, ...]
142
+ subject.wont_be :possible?, %w(David) # [!!!, nil, David]
143
+
144
+ subject.must_be :possible?, %w(Joe Gary) # [Joe, Gary, ...]
145
+ subject.must_be :possible?, %w(Joe David) # [Joe, ..., David]
146
+ subject.wont_be :possible?, %w(Gary David) # [!!!, Gary, David]
147
+
148
+ subject.must_be :possible?, %w(Joe Gary David) # [Joe, Gary, David]
149
+ subject.wont_be :possible?, %w(Joe Gary David Doe) # [Joe, Gary, David] Doe
150
+ end
151
+ end
152
+
153
+ describe '#valid?' do
154
+ it 'is false if the list is not #possible' do
155
+ subject.stubs(:possible?).returns(false)
156
+ subject.wont_be :valid?, [1, 2]
157
+ end
158
+
159
+ it 'is false if the list is too short' do
160
+ subject.stubs(:possible?).returns(true)
161
+ subject.wont_be :valid?, [1]
162
+ end
163
+
164
+ it 'is true if the list is #possible? and not too short' do
165
+ subject.stubs(:possible?).returns(true)
166
+ subject.must_be :valid?, [1, 2]
167
+ subject.must_be :valid?, [1, 2, 3]
168
+ subject.must_be :valid?, [0, 1, 2, 3]
169
+ end
170
+ end
171
+
172
+ describe '#create_valid' do
173
+ it 'returns the correct arguments' do
174
+ a = Clive::Arguments.create :args => '[<a>] <b> [<c>]'
175
+ a.create_valid(%w(a b c)).must_equal ['a', 'b', 'c']
176
+ a.create_valid(%w(a b)).must_equal ['a', 'b', nil]
177
+ a.create_valid(%w(a)).must_equal [nil, 'a', nil]
178
+ end
179
+
180
+ it 'coerces the arguments' do
181
+ a = Clive::Arguments.create :args => '<a> <b>', :as => [Integer, Float]
182
+ a.create_valid(%w(50.55 50.55)).must_equal [50, 50.55]
183
+ end
184
+
185
+ it 'uses defaults where needed' do
186
+ a = Clive::Arguments.create :args => '[<a>] <b> [<c>]', :defaults => ['y', nil, 'y']
187
+ a.create_valid(%w(n)).must_equal %w(y n y)
188
+ end
189
+ end
190
+
191
+ end
@@ -1,240 +1,307 @@
1
- require 'spec_helper'
1
+ $: << File.dirname(__FILE__) + '/..'
2
+ require 'helper'
2
3
 
3
4
  describe Clive::Command do
4
5
 
5
- context "when creating a base command" do
6
- subject { Clive::Command.setup(Class.new) {} }
7
- end
8
-
9
- subject {
10
- Clive::Command.new([:co, :comm], "A command", Class.new) do
11
- bool(:boo) {}
12
- switch(:swi) {}
13
- flag(:fla) {}
14
- command(:com) {}
15
- end
16
- }
17
-
18
- it_behaves_like "an option"
19
-
20
- describe "#initialize" do
21
- subject {
22
- Clive::Command.new([:com], "A command", Class.new) do
23
- flag(:test)
24
- end
6
+ it 'can take arguments' do
7
+ command = Clive::Command.create([:test], '', :arg => '<dir>')
8
+
9
+ state = {:test => {}}
10
+ command.run(state, ['~/somewhere'])
11
+ state[:test][:args].must_equal '~/somewhere'
12
+ end
13
+
14
+ it 'can run a block with arguments' do
15
+ command = Clive::Command.create [], '', :arg => '<dir>' do
16
+ action { puts dir }
17
+ end
18
+
19
+ this { command.run({}, ['~/somewhere']) }.must_output "~/somewhere\n"
20
+ end
21
+
22
+ describe '#initialize' do
23
+ subject {
24
+ Clive::Command.new([:c,:b,:a],
25
+ 'A command',
26
+ :head => true,
27
+ :args => '<a> [<b>]',
28
+ :as => [Integer, nil],
29
+ :group => 'Cool commands',
30
+ :help => true,
31
+ :name => 'file.rb')
25
32
  }
26
-
27
- it "generates a help header" do
28
- File.stub!(:basename).and_return("test")
29
- subject.instance_variable_get("@header").should == "Usage: test com [options]"
30
- end
31
-
32
- it "generates an option missing proc" do
33
- proc = subject.instance_variable_get("@option_missing")
34
- expect {
35
- proc.call("hey")
36
- }.should raise_error Clive::NoOptionError
37
- end
38
-
39
- it "doesn't run the block given" do
40
- subject.flags.size.should == 0
41
- end
42
-
43
- it "generates a help switch" do
44
- subject.switches.map {|i| i.names}.should include ["h", "help"]
45
- end
46
- end
47
-
48
- describe "#bools" do
49
- it "returns an array of bools" do
50
- subject.find
51
- subject.bools.each do |i|
52
- i.should be_kind_of Clive::Bool
53
- end
33
+
34
+ it 'sets the names' do
35
+ subject.names.must_equal [:c,:b,:a]
36
+ end
37
+
38
+ it 'sets the description' do
39
+ subject.description.must_equal 'A command'
40
+ end
41
+
42
+ it 'sets the options' do
43
+ subject.config[:head].must_be_true
44
+ subject.config[:group].must_equal 'Cool commands'
45
+ end
46
+
47
+ it 'sets the arguments' do
48
+ subject.args.size.must_equal 2
49
+ subject.args.map(&:name).must_equal [:a, :b]
50
+ end
51
+
52
+ it 'sets a default header' do
53
+ subject.instance_variable_get(:@header).call.must_equal 'Usage: file.rb c,b,a [options]'
54
+ end
55
+
56
+ it 'sets a default footer' do
57
+ subject.instance_variable_get(:@footer).must_equal ''
58
+ end
59
+
60
+ it 'adds the help option' do
61
+ subject.must_be :has?, '--help'
62
+ subject.must_be :has?, '-h'
63
+ end
64
+
65
+ it 'resets the current description' do
66
+ subject.instance_variable_get(:@_last_desc).must_equal ''
54
67
  end
55
68
  end
56
-
57
- describe "#switches" do
58
- it "returns an array of switches" do
59
- subject.find
60
- subject.switches.each do |i|
61
- i.should be_kind_of Clive::Switch
62
- end
69
+
70
+ describe '#name' do
71
+ it 'returns the first, in order when defined, name' do
72
+ command = Clive::Command.new [:efg, :abc, :zxy]
73
+ command.name.must_equal :efg
63
74
  end
64
75
  end
65
-
66
- describe "#flags" do
67
- it "returns an array of flags" do
68
- subject.find
69
- subject.flags.each do |i|
70
- i.should be_kind_of Clive::Flag
71
- end
76
+
77
+ describe '#to_s' do
78
+ it 'returns the names joined' do
79
+ command = Clive::Command.new [:a, :b, :c]
80
+ command.to_s.must_equal 'a,b,c'
72
81
  end
73
82
  end
74
-
75
- describe "#find" do
76
- it "runs the block for the command" do
77
- subject.flags.size.should == 0
78
- subject.find
79
- subject.flags.size.should == 1
80
- end
81
-
82
- it "sets the block to nil" do
83
- subject.find
84
- subject.block.should be_nil
85
- end
86
- end
87
-
88
- describe "#run" do
89
- it "returns an array of unused arguments" do
90
- subject.find
91
- subject.run(%w(--swi what)).should == ['what']
92
- end
93
- end
94
-
95
- describe "#to_h" do
96
- it "returns a hash of data for help formatting" do
97
- hsh = {'names' => subject.names, 'desc' => subject.desc}
98
- subject.to_h.should == hsh
99
- end
100
- end
101
-
102
- describe "#command" do
103
- it "creates a new command" do
104
- expect {
105
- subject.command(:comm)
106
- }.should change {subject.commands.size}.by(1)
107
- end
108
-
109
- it "resets the current description" do
110
- subject.desc 'A command'
111
- subject.command(:comm)
112
- subject.current_desc.should == ""
113
- end
114
- end
115
-
116
- describe "#switch" do
117
- it "creates a new switch" do
118
- expect {
119
- subject.switch(:s, :switch)
120
- }.should change {subject.switches.size}.by(1)
121
- end
122
-
123
- it "resets the current description" do
124
- subject.desc 'A switch'
125
- subject.switch(:s, :switch)
126
- subject.current_desc.should == ""
127
- end
128
- end
129
-
130
- describe "#flag" do
131
- it "creates a new flag" do
132
- expect {
133
- subject.flag(:f, :flag)
134
- }.should change {subject.flags.size}.by(1)
135
- end
136
-
137
- it "resets the current description" do
138
- subject.desc 'A flag'
139
- subject.flag(:f, :flag)
140
- subject.current_desc.should == ""
141
- end
142
- end
143
-
144
- describe "#bool" do
145
- it "creates two bool switches" do
146
- expect {
147
- subject.bool(:b, :bool)
148
- }.should change {subject.bools.size}.by(2)
149
- end
150
-
151
- it "resets the current description" do
152
- subject.desc 'A bool'
153
- subject.bool(:b, :bool)
154
- subject.current_desc.should == ""
155
- end
156
- end
157
-
158
- describe "#desc" do
159
- context "when called with no arguments" do
160
- it "returns the description for the command" do
161
- subject.desc.should == "A command"
83
+
84
+ describe '#run_block' do
85
+ it 'runs the block passed to command' do
86
+ command = Clive::Command.new do
87
+ print 'Hey I was ran'
162
88
  end
89
+ this { command.run_block({}) }.must_output 'Hey I was ran'
163
90
  end
164
-
165
- context "when called with an argument" do
166
- it "sets the current description" do
167
- subject.desc "A new desc"
168
- subject.instance_variable_get("@current_desc").should == "A new desc"
169
- end
91
+
92
+ it 'returns a possibly modified state' do
93
+ state = {}
94
+ command = Clive::Command.new { set :a, true }
95
+ state.wont_have :key?, :a
96
+ command.run_block(state)
97
+ state.must_have :key?, :a
98
+ end
99
+ end
100
+
101
+ describe '#header' do
102
+ it 'sets the header' do
103
+ command = Clive::Command.new
104
+ command.header 'A header'
105
+ command.instance_variable_get(:@header).must_equal 'A header'
106
+ end
107
+ end
108
+
109
+ describe '#footer' do
110
+ it 'sets the footer' do
111
+ command = Clive::Command.new
112
+ command.footer 'A footer'
113
+ command.instance_variable_get(:@footer).must_equal 'A footer'
114
+ end
115
+ end
116
+
117
+ describe '#config' do
118
+ it 'sets options' do
119
+ command = Clive::Command.new
120
+ command.config :name => 'my cool app'
121
+ command.config[:name].must_equal 'my cool app'
122
+ end
123
+ end
124
+
125
+ describe '#set' do
126
+ it 'sets a value to the state hash' do
127
+ command = Clive::Command.new
128
+ command.instance_variable_set :@state, {}
129
+ command.set :a, true
130
+ command.instance_variable_get(:@state).must_equal :a => true
131
+ end
132
+ end
133
+
134
+ describe '#option' do
135
+ it 'creates an option' do
136
+ command = Clive::Command.new
137
+ command.option :O, :opt, 'An option', :tail => true
138
+
139
+ opt = command.find('-O')
140
+ opt.name.must_equal :opt
141
+ opt.description.must_equal 'An option'
142
+ opt.config.must_contain :tail => true
143
+ end
144
+ end
145
+
146
+ describe '#boolean' do
147
+ it 'creates a new boolean option' do
148
+ command = Clive::Command.new
149
+ command.boolean :auto, 'Auto build', :head => true
150
+
151
+ bool = command.find('--auto')
152
+ bool.name.must_equal :auto
153
+ bool.description.must_equal 'Auto build'
154
+ bool.config.must_contain :head => true
155
+ bool.config[:boolean].must_be_true
156
+ end
157
+ end
158
+
159
+ describe '#action' do
160
+ it 'stores a block' do
161
+ command = Clive::Command.new
162
+ block = proc {}
163
+ command.action &block
164
+ command.instance_variable_get(:@block).to_s.must_equal block.to_s
170
165
  end
171
166
  end
172
-
173
- describe "#option_missing" do
174
- it "sets the option missing proc" do
175
- proc = lambda {|n| puts "What? #{name} doesn't exist" }
176
- subject.option_missing(&proc)
177
- subject.instance_variable_get("@option_missing").should == proc
167
+
168
+ describe '#description' do
169
+ it 'sets the description' do
170
+ command = Clive::Command.new
171
+ command.description 'Some description'
172
+ command.instance_variable_get(:@_last_desc).must_equal 'Some description'
173
+ end
174
+
175
+ it 'gets the description' do
176
+ command = Clive::Command.new [], 'A command'
177
+ command.description.must_equal 'A command'
178
178
  end
179
179
  end
180
-
181
- describe "#header" do
182
- it "sets the header" do
183
- subject.header "A header"
184
- subject.instance_variable_get("@header").should == "A header"
180
+
181
+ describe '#find' do
182
+ subject {
183
+ Clive::Command.create [:command] do
184
+ bool :F, :force
185
+ opt :auto_build
186
+ end
187
+ }
188
+
189
+ it 'finds boolean options' do
190
+ subject.find('--force').name.must_equal :force
191
+ end
192
+
193
+ it 'finds short options' do
194
+ subject.find('-F').name.must_equal :force
195
+ end
196
+
197
+ it 'does not find short negative boolean options' do
198
+ subject.find('--no-F').must_be_nil
199
+ end
200
+
201
+ it 'does not find negative boolean options' do
202
+ subject.find('--no-force').must_be_nil
203
+ end
204
+
205
+ it 'finds options with multiple words in name' do
206
+ subject.find('--auto_build').name.must_equal :auto_build
207
+ end
208
+
209
+ it 'finds options with dashes in name' do
210
+ subject.find('--auto-build').name.must_equal :auto_build
211
+ end
212
+
213
+ it 'does not find non existent options' do
214
+ subject.find('--no-auto-build').must_be_nil
215
+ subject.find('--unreal').must_be_nil
185
216
  end
186
217
  end
187
-
188
- describe "#footer" do
189
- it "sets the footer" do
190
- subject.footer "A footer"
191
- subject.instance_variable_get("@footer").should == "A footer"
218
+
219
+ describe '#find_option' do
220
+ subject {
221
+ Clive::Command.create do
222
+ bool :F, :force
223
+ opt :auto_build
224
+ end
225
+ }
226
+
227
+ it 'finds boolean options' do
228
+ subject.find_option(:force).name.must_equal :force
229
+ end
230
+
231
+ it 'finds short options' do
232
+ subject.find_option(:F).name.must_equal :force
233
+ end
234
+
235
+ it 'does not find short negative boolean options' do
236
+ subject.find_option(:no_F).must_be_nil
237
+ end
238
+
239
+ it 'does not find negative boolean options' do
240
+ subject.find_option(:no_force).must_be_nil
241
+ end
242
+
243
+ it 'finds options with multiple words in name' do
244
+ subject.find_option(:auto_build).name.must_equal :auto_build
245
+ end
246
+
247
+ it 'does not find non existent options' do
248
+ subject.find_option(:no_auto_build).must_be_nil
249
+ subject.find_option(:unreal).must_be_nil
192
250
  end
193
251
  end
194
-
195
- describe "#build_help" do
196
- it "adds a switch for help" do
197
- subject.options = []
198
- subject.options.should be_empty
199
- subject.build_help
200
- subject.options.map(&:names).should include ['h', 'help']
252
+
253
+ describe '#has?' do
254
+ it 'tries to find the option' do
255
+ command = Clive::Command.new
256
+ command.expects(:find).with('--option').returns(Clive::Option.new)
257
+ command.has?('--option').must_be_true
201
258
  end
202
259
  end
203
-
204
- describe "#help" do
205
- it "returns a string of help" do
206
- help = <<EOS
207
- Usage: rspec co, comm [options]
208
260
 
209
- Options:
210
- -h, --help \e[90mDisplay help\e[0m
211
- EOS
212
-
213
- subject.help.should == help
261
+ describe '#group' do
262
+ it 'sets the group for options created' do
263
+ command = Clive::Command.create do
264
+ group 'Testing'
265
+ opt :test
266
+ group 'Changed'
267
+ opt :change
268
+ opt :manual, :group => 'Set'
269
+ end
270
+
271
+ command.find_option(:test).config[:group].must_equal 'Testing'
272
+ command.find_option(:change).config[:group].must_equal 'Changed'
273
+ command.find_option(:manual).config[:group].must_equal 'Set'
214
274
  end
215
275
  end
216
-
217
- describe "#help_formatter" do
218
- context "when called with a symbol" do
219
- it "uses the named formatter" do
220
- before = subject.instance_variable_get("@formatter")
221
- subject.help_formatter(:white)
222
- subject.instance_variable_get("@formatter").should_not == before
276
+
277
+ describe '#end_group' do
278
+ it 'calls #group with nil' do
279
+ command = Clive::Command.create do
280
+ group 'Testing'
281
+ option :test
282
+ end_group
283
+ option :none
223
284
  end
285
+
286
+ command.find_option(:none).config[:group].must_be_nil
224
287
  end
225
-
226
- context "when called with argumentss and a block" do
227
- it "creates a new help formatter" do
228
- subject.help_formatter :width => 40, :prepend => 5 do |h|
229
- h.switch "switch"
230
- h.bool "bool"
231
- h.flag "flag"
232
- h.command "command"
233
- end
234
- formatter = subject.instance_variable_get("@formatter")
235
- formatter.width.should == 40
288
+ end
289
+
290
+ describe '#help' do
291
+ it 'builds a help string using the defined formatter' do
292
+ f = mock
293
+ command = Clive::Command.create [], "", :formatter => f, :help => true do
294
+ header 'Top'
295
+ footer 'Bottom'
236
296
  end
297
+
298
+ f.expects(:header=).with('Top')
299
+ f.expects(:footer=).with('Bottom')
300
+ f.expects(:options=).with([command.find_option(:help)])
301
+ f.expects(:to_s).with()
302
+
303
+ command.help
237
304
  end
238
305
  end
239
306
 
240
- end
307
+ end