choosy 0.1.0 → 0.2.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 (45) hide show
  1. data/README.markdown +229 -221
  2. data/Rakefile +21 -3
  3. data/examples/bar.rb +44 -0
  4. data/examples/foo.rb +198 -0
  5. data/examples/superfoo.rb +125 -0
  6. data/lib/VERSION +1 -1
  7. data/lib/choosy/argument.rb +51 -0
  8. data/lib/choosy/base_command.rb +22 -7
  9. data/lib/choosy/command.rb +12 -4
  10. data/lib/choosy/dsl/argument_builder.rb +88 -0
  11. data/lib/choosy/dsl/base_command_builder.rb +71 -56
  12. data/lib/choosy/dsl/command_builder.rb +14 -2
  13. data/lib/choosy/dsl/option_builder.rb +43 -83
  14. data/lib/choosy/dsl/super_command_builder.rb +37 -9
  15. data/lib/choosy/option.rb +13 -11
  16. data/lib/choosy/parse_result.rb +8 -27
  17. data/lib/choosy/parser.rb +20 -16
  18. data/lib/choosy/printing/color.rb +39 -21
  19. data/lib/choosy/printing/erb_printer.rb +12 -3
  20. data/lib/choosy/printing/formatting_element.rb +17 -0
  21. data/lib/choosy/printing/help_printer.rb +204 -117
  22. data/lib/choosy/printing/terminal.rb +53 -0
  23. data/lib/choosy/super_command.rb +6 -6
  24. data/lib/choosy/super_parser.rb +26 -15
  25. data/lib/choosy/verifier.rb +61 -6
  26. data/spec/choosy/base_command_spec.rb +27 -2
  27. data/spec/choosy/command_spec.rb +31 -9
  28. data/spec/choosy/dsl/argument_builder_spec.rb +180 -0
  29. data/spec/choosy/dsl/base_command_builder_spec.rb +87 -44
  30. data/spec/choosy/dsl/commmand_builder_spec.rb +15 -4
  31. data/spec/choosy/dsl/option_builder_spec.rb +101 -191
  32. data/spec/choosy/dsl/super_command_builder_spec.rb +34 -9
  33. data/spec/choosy/parser_spec.rb +30 -8
  34. data/spec/choosy/printing/color_spec.rb +19 -5
  35. data/spec/choosy/printing/help_printer_spec.rb +152 -73
  36. data/spec/choosy/printing/terminal_spec.rb +27 -0
  37. data/spec/choosy/super_command_spec.rb +17 -17
  38. data/spec/choosy/super_parser_spec.rb +20 -10
  39. data/spec/choosy/verifier_spec.rb +137 -47
  40. data/spec/integration/command-A_spec.rb +6 -6
  41. data/spec/integration/command-B_spec.rb +45 -0
  42. data/spec/integration/supercommand-A_spec.rb +33 -27
  43. data/spec/integration/supercommand-B_spec.rb +32 -0
  44. data/spec/spec_helpers.rb +8 -5
  45. metadata +95 -54
@@ -0,0 +1,27 @@
1
+ require 'spec_helpers'
2
+ require 'choosy/printing/terminal'
3
+
4
+ module Choosy::Printing
5
+ class TerminalTest
6
+ include Terminal
7
+ end
8
+
9
+ describe Terminal do
10
+ before :each do
11
+ @t = TerminalTest.new
12
+ end
13
+
14
+ it "should know the width of the screen, if possible, or set a default [COULD BREAK ON YOUR MACHINE]" do
15
+ @t.columns.should satisfy {|c| c >= Terminal::DEFAULT_COLUMN_COUNT }
16
+ end
17
+
18
+ it "should know the lenght the screen, if possible, or set a default [COULD BREAK ON YOUR MACHINE]" do
19
+ @t.lines.should satisfy {|l| l >= Terminal::DEFAULT_LINE_COUNT }
20
+ end
21
+
22
+ it "should allow for setting the column width" do
23
+ @t.columns = 40
24
+ @t.columns.should eql(40)
25
+ end
26
+ end
27
+ end
@@ -9,8 +9,8 @@ module Choosy
9
9
 
10
10
  describe :parse! do
11
11
  it "should be able to print out the version number" do
12
- @c.alter do |c|
13
- c.version "superblah"
12
+ @c.alter do
13
+ version "superblah"
14
14
  end
15
15
 
16
16
  o = capture :stdout do
@@ -21,27 +21,27 @@ module Choosy
21
21
  end
22
22
 
23
23
  it "should print out the supercommand help message" do
24
- @c.alter do |c|
25
- c.help
24
+ @c.alter do
25
+ help
26
26
  end
27
27
 
28
28
  o = capture :stdout do
29
29
  @c.parse!([])
30
30
  end
31
31
 
32
- o.should match(/USAGE:/)
32
+ o.should match(/Usage:/)
33
33
  end
34
34
 
35
35
  it "should print out a subcommand help message" do
36
- @c.alter do |c|
37
- c.help
38
- c.command :bar do |bar|
39
- bar.boolean :count, "The count"
36
+ @c.alter do
37
+ help
38
+ command :bar do
39
+ boolean :count, "The count"
40
40
  end
41
41
  end
42
42
 
43
43
  o = capture :stdout do
44
- @c.parse!(['help', 'bar'])
44
+ @c.parse! ['help', 'bar']
45
45
  end
46
46
 
47
47
  o.should match(/--count/)
@@ -50,9 +50,9 @@ module Choosy
50
50
 
51
51
  describe :execute! do
52
52
  it "should fail when no executor is present" do
53
- @c.alter do |c|
54
- c.command :bar do |bar|
55
- bar.boolean :count, "The count"
53
+ @c.alter do
54
+ command :bar do
55
+ boolean :count, "The count"
56
56
  end
57
57
  end
58
58
 
@@ -63,10 +63,10 @@ module Choosy
63
63
 
64
64
  it "should call the executors" do
65
65
  count = 0
66
- @c.alter do |c|
67
- c.command :bar do |bar|
68
- bar.integer :count, "The count"
69
- bar.executor do |opts, args|
66
+ @c.alter do
67
+ command :bar do
68
+ integer :count, "The count"
69
+ executor do |opts, args|
70
70
  count = opts[:count]
71
71
  end
72
72
  end
@@ -1,6 +1,7 @@
1
1
  require 'spec_helpers'
2
2
  require 'choosy/super_parser'
3
3
  require 'choosy/super_command'
4
+ require 'choosy/dsl/super_command_builder'
4
5
 
5
6
  module Choosy
6
7
  class SuperParserBuilder
@@ -8,12 +9,11 @@ module Choosy
8
9
 
9
10
  def initialize
10
11
  @super = Choosy::SuperCommand.new :super
11
- @parsimonious = false
12
12
  end
13
13
 
14
14
  def command(name)
15
- @super.alter do |a|
16
- a.command name do |c|
15
+ @super.alter do
16
+ command name do |c|
17
17
  yield c if block_given?
18
18
  end
19
19
  end
@@ -21,8 +21,8 @@ module Choosy
21
21
  end
22
22
 
23
23
  def single(name)
24
- @super.alter do |a|
25
- a.single name, name.to_s
24
+ @super.alter do
25
+ single name, name.to_s
26
26
  end
27
27
  self
28
28
  end
@@ -33,11 +33,13 @@ module Choosy
33
33
  end
34
34
 
35
35
  def parsimonious!
36
- @parsimonious = true
37
- end
36
+ @super.alter do
37
+ parsimonious
38
+ end
39
+ end
38
40
 
39
41
  def build
40
- SuperParser.new(@super, @parsimonious)
42
+ SuperParser.new(@super)
41
43
  end
42
44
  end
43
45
 
@@ -69,7 +71,7 @@ module Choosy
69
71
  @p.super.builder.help
70
72
  attempting {
71
73
  @p.parse!()
72
- }.should raise_error(Choosy::HelpCalled, :super)
74
+ }.should raise_error(Choosy::HelpCalled, Choosy::DSL::SuperCommandBuilder::SUPER)
73
75
  end
74
76
  end
75
77
 
@@ -88,7 +90,15 @@ module Choosy
88
90
  end
89
91
 
90
92
  it "should collect other names of commands as arguments" do
91
- @p.command(:bar).command(:baz).parse!('bar', 'baz').subresults.should have(1).item
93
+ @p.command(:bar) do |c|
94
+ c.arguments
95
+ end.command(:baz).parse!('bar', 'baz').subresults.should have(1).item
96
+ end
97
+
98
+ it "should fail when the first command doesn't take arguments" do
99
+ attempting {
100
+ @p.command(:bar).command(:baz).parse!('bar', 'baz')
101
+ }.should raise_error(Choosy::ValidationError, /bar: no arguments allowed: baz/)
92
102
  end
93
103
  end
94
104
 
@@ -26,30 +26,40 @@ module Choosy
26
26
 
27
27
  before :each do
28
28
  reset!
29
- @res = ParseResult.new(@c)
29
+ @res = ParseResult.new(@c, false)
30
30
  end
31
31
 
32
- describe :verify_options! do
32
+ describe :verify! do
33
33
  it "should not try to validate arguments if not set" do
34
34
  b.boolean :debug, "Debug"
35
+ b.arguments do
36
+ count 0..10
37
+ end
38
+
35
39
  @res.args << "a"
36
40
  attempting {
37
- v.verify_options!(@res)
41
+ v.verify!(@res)
38
42
  }.should_not raise_error
39
43
  end
40
44
  end
41
45
 
42
- describe :verify_arguments! do
43
- it "should validate arguments if asked" do
44
- b.arguments do |args|
45
- raise RuntimeError.new('Called!')
46
+ describe :required? do
47
+ it "should fail when an option is required but not provided" do
48
+ o = b.string :str, "String" do
49
+ required
46
50
  end
51
+ attempting {
52
+ v.required?(o, @res)
53
+ }.should raise_error(Choosy::ValidationError, /required/)
54
+ end
47
55
 
56
+ it "should succeed when nothing is required" do
57
+ o = b.string :str, "String"
48
58
  attempting {
49
- v.verify_arguments!(@res)
50
- }.should raise_error(RuntimeError, 'Called!')
59
+ v.required?(o, @res)
60
+ }.should_not raise_error
51
61
  end
52
- end
62
+ end#required?
53
63
 
54
64
  describe :populate! do
55
65
  it "should fill in default boolean values to false if unset" do
@@ -93,13 +103,66 @@ module Choosy
93
103
  v.populate!(o, @res)
94
104
  @res.options.should be_empty
95
105
  end
96
- end#populate_defaults!
106
+ end#populate!
107
+
108
+ describe :convert! do
109
+ it "should convert files" do
110
+ o = b.file :afile, "A File"
111
+ @res[:afile] = __FILE__
112
+ v.convert!(o, @res)
113
+ @res[:afile].path.should eql(__FILE__)
114
+ end
115
+
116
+ class CustomConverter
117
+ def convert(value)
118
+ value.to_i
119
+ end
120
+ end
121
+
122
+ it "should convert a custom type" do
123
+ o = b.single :an_int, "An int" do
124
+ cast CustomConverter.new
125
+ end
126
+ @res[:an_int] = "1"
127
+
128
+ v.convert!(o, @res)
129
+ @res[:an_int].should eql(1)
130
+ end
131
+ end#convert!
132
+
133
+ describe :restricted? do
134
+ it "should verify that arguments are restricted to a certain subset for a single valued option" do
135
+ o = b.option :value do
136
+ flags '-v', '--value', 'VALUE'
137
+ desc "Description"
138
+ cast :symbol
139
+ only :a, :b, :c
140
+ end
141
+
142
+ @res[:value] = :d
143
+ attempting {
144
+ v.restricted?(o, @res)
145
+ }.should raise_error(Choosy::ValidationError, "unrecognized value (only 'a', 'b', 'c' allowed): 'd'")
146
+ end
147
+
148
+ it "should verify that all arguments are restricted for a muli-valued option" do
149
+ o = b.option :value do
150
+ long '--value', 'VALUES+'
151
+ only :a, :b, :c
152
+ end
153
+
154
+ @res[:value] = [:a, :b, :c, :d]
155
+ attempting {
156
+ v.restricted?(o, @res)
157
+ }.should raise_error(Choosy::ValidationError, "unrecognized value (only 'a', 'b', 'c' allowed): 'd'")
158
+ end
159
+ end
97
160
 
98
161
  describe :validate! do
99
162
  it "should call the validate proc associated with each option" do
100
- o = b.string :line, "Line" do |l|
101
- l.validate do |arg|
102
- l.fail "Validated!"
163
+ o = b.string :line, "Line" do
164
+ validate do |arg, options|
165
+ die "Validated!"
103
166
  end
104
167
  end
105
168
  @res[:line] = "line"
@@ -110,9 +173,9 @@ module Choosy
110
173
  end
111
174
 
112
175
  it "should not call the proc on empty arguments" do
113
- o = b.strings :line, "Line" do |l|
114
- l.validate do |arg|
115
- l.fail "Validated!"
176
+ o = b.strings :line, "Line" do
177
+ validate do |arg|
178
+ die "Validated!"
116
179
  end
117
180
  end
118
181
  @res[:line] = []
@@ -124,7 +187,7 @@ module Choosy
124
187
  it "should not call the proc when the arguments are null" do
125
188
  o = b.string :line, "Line" do |l|
126
189
  l.validate do |arg|
127
- l.fail "Validated!"
190
+ die "Validated!"
128
191
  end
129
192
  end
130
193
  @res[:line] = nil
@@ -132,49 +195,76 @@ module Choosy
132
195
  v.validate!(o, @res)
133
196
  @res[:line].should be(nil)
134
197
  end
135
- end#validate!
136
198
 
137
- describe :required? do
138
- it "should fail when an option is required but not provided" do
139
- o = b.string :str, "String" do |s|
140
- s.required
199
+ it "should call the proc with the additional option param" do
200
+ o = b.string :line, "Line" do
201
+ validate do |arg, options|
202
+ options[:populated] = arg
203
+ options[:line] = "this"
204
+ end
141
205
  end
142
- attempting {
143
- v.required?(o, @res)
144
- }.should raise_error(Choosy::ValidationError, /Required/)
206
+ @res[:line] = 'blah'
207
+
208
+ v.validate!(o, @res)
209
+ @res[:populated].should eql('blah')
210
+ @res[:line].should eql("this")
145
211
  end
212
+ end#validate!
213
+
214
+ describe :verify_arguments! do
215
+ it "should validate arguments if asked" do
216
+ b.arguments do
217
+ validate do |args, option|
218
+ raise RuntimeError.new('Called!')
219
+ end
220
+ end
221
+ @res.args << 'a'
146
222
 
147
- it "should succeed when nothing is required" do
148
- o = b.string :str, "String"
149
223
  attempting {
150
- v.required?(o, @res)
151
- }.should_not raise_error
224
+ v.verify_arguments!(@res)
225
+ }.should raise_error(RuntimeError, 'Called!')
152
226
  end
153
- end
154
227
 
155
- describe :convert! do
156
- it "should convert files" do
157
- o = b.file :afile, "A File"
158
- @res[:afile] = __FILE__
159
- v.convert!(o, @res)
160
- @res[:afile].path.should eql(__FILE__)
228
+ it "should validate that the argument count isn't too few" do
229
+ b.arguments do
230
+ count 2
231
+ end
232
+ @res.args << "a"
233
+
234
+ attempting {
235
+ v.verify_arguments!(@res)
236
+ }.should raise_error(Choosy::ValidationError, /too few arguments/)
161
237
  end
162
238
 
163
- class CustomConverter
164
- def convert(value)
165
- value.to_i
239
+ it "should validate that the argument count isn't too many" do
240
+ b.arguments do
241
+ count 1
166
242
  end
243
+ @res.args << "a"
244
+ @res.args << "b"
245
+
246
+ attempting {
247
+ v.verify_arguments!(@res)
248
+ }.should raise_error(Choosy::ValidationError, /too many arguments/)
167
249
  end
168
250
 
169
- it "should convert a custom type" do
170
- o = b.single :an_int, "An int" do |i|
171
- i.cast CustomConverter.new
251
+ it "should succed when the argument count is in an acceptable range" do
252
+ b.arguments do
253
+ count 1..3
172
254
  end
173
- @res[:an_int] = "1"
255
+ @res.args << "1"
174
256
 
175
- v.convert!(o, @res)
176
- @res[:an_int].should eql(1)
257
+ attempting {
258
+ v.verify_arguments!(@res)
259
+ }.should_not raise_error
177
260
  end
178
- end#convert!
261
+
262
+ it "should fail when no arguments are allowed" do
263
+ @res.args << 'a'
264
+ attempting {
265
+ v.verify_arguments!(@res)
266
+ }.should raise_error(Choosy::ValidationError, /no arguments allowed/)
267
+ end
268
+ end
179
269
  end
180
270
  end
@@ -4,11 +4,11 @@ require 'choosy'
4
4
  describe "Command A" do
5
5
 
6
6
  before :each do
7
- @cmd = Choosy::Command.new :A do |a|
8
- a.integer :count, "The count"
9
- a.boolean :bold, "Bold the output"
10
- a.version "blah"
11
- a.help
7
+ @cmd = Choosy::Command.new :A do
8
+ integer :count, "The count"
9
+ boolean :bold, "Bold the output"
10
+ version "blah"
11
+ help
12
12
  end
13
13
  end
14
14
 
@@ -17,7 +17,7 @@ describe "Command A" do
17
17
  @cmd.parse! ['--help']
18
18
  end
19
19
 
20
- o.should match /USAGE:/
20
+ o.should match /Usage:/
21
21
  end
22
22
 
23
23
  it "should handle multiple arguments" do