Permalink
Browse files

User typeof rather than constructor.name. Also user lower case types.

  • Loading branch information...
1 parent 1677b4d commit 593246df01c6d8530464a42fd755d89132ffe6b1 @relistan committed Dec 7, 2012
Showing with 32 additions and 23 deletions.
  1. +6 −6 spec/options.spec.coffee
  2. +6 −6 spec/troll.spec.coffee
  3. +20 −11 src/troll.coffee
View
12 spec/options.spec.coffee
@@ -56,7 +56,7 @@ describe 'Options', ->
it 'detects required opts', ->
opts = new Options()
- opts.opt 'header', 'Add a header', type: 'String', required: 'true'
+ opts.opt 'header', 'Add a header', type: 'string', required: 'true'
expect(_.contains(opts.requiredOpts, 'header')).toBe true
expect(_.contains(opts.requiredOpts, 'asdf')).toBe false
@@ -66,7 +66,7 @@ describe 'Options', ->
@opts = new Options()
it 'requires an argument if type is defined', ->
- @opts.opt 'header', 'Add a header', type: 'String'
+ @opts.opt 'header', 'Add a header', type: 'string'
expect(@opts.getParsedOpts().header.takesValue).toBe true
it 'does not require an argument if type is undefined and default is a boolean', ->
@@ -79,14 +79,14 @@ describe 'Options', ->
it 'sets the right type based on the provided default', ->
@opts.opt 'header', 'Add a header', default: 'X-Something'
- expect(@opts.getParsedOpts().header.type).toEqual 'String'
+ expect(@opts.getParsedOpts().header.type).toEqual 'string'
@opts.opt 'silent', 'Enable silent mode', default: false
- expect(@opts.getParsedOpts().silent.type).toEqual 'Boolean'
+ expect(@opts.getParsedOpts().silent.type).toEqual 'boolean'
it 'raises when the type was set and a default was provided', ->
expect( =>
- @opts.opt 'header', 'Add a header', default: 'X-Something', type: 'String'
+ @opts.opt 'header', 'Add a header', default: 'X-Something', type: 'string'
).toThrow('type defined when default was provided')
it 'raises when no options are set', ->
@@ -97,7 +97,7 @@ describe 'Options', ->
'Neither default nor type is set for \'header\'')
it 'raises when unknown settings are passed', ->
- expect( => @opts.opt 'header', 'Add a header', type: 'Boolean', asdf: true ).toThrow(
+ expect( => @opts.opt 'header', 'Add a header', type: 'boolean', asdf: true ).toThrow(
'Unrecognized options \'asdf\'')
it 'raises when default and required are both specified', ->
View
12 spec/troll.spec.coffee
@@ -19,7 +19,7 @@ describe 'Troll', ->
it 'resolves shorthand options assigned by hand that collide', ->
@troll.parseOptions (t) ->
t.opt 'header', 'Add a new header', default: 'X-Shakespeare'
- t.opt 'collision', 'A colliding opt', short: 'h', type: 'String'
+ t.opt 'collision', 'A colliding opt', short: 'h', type: 'string'
expect(@troll.getOpts().getShortOpts()['h']).toEqual 'collision'
expect(@troll.getOpts().getParsedOpts()['header']['short']).toEqual 'H'
@@ -32,7 +32,7 @@ describe 'Troll', ->
t.banner 'We few, we happy few, we band of brothers'
t.opt 'one', 'Option one', default: true
t.opt 'two', 'Option two', default: true
- t.opt 'three','Option three', type: 'String', required: true
+ t.opt 'three','Option three', type: 'string', required: true
spyOn(@troll, 'puts').andCallFake((args...) => @buffer += x for x in args)
@@ -72,7 +72,7 @@ describe 'Troll', ->
t.banner 'We few, we happy few, we band of brothers'
t.opt 'one', 'Option one', default: true
t.opt 'two', 'Option two', default: false
- t.opt 'three','Option three', type: 'Integer'
+ t.opt 'three','Option three', type: 'integer'
t.opt 'four' ,'Option four', default: 'default for four'
t.opt 'five' ,'Option five', default: 'default for five'
@@ -94,23 +94,23 @@ describe 'Troll', ->
spyOn(troll, 'exit').andCallFake(-> )
troll.options (t) ->
- t.opt 'one', 'Option one', required: true, type: 'String'
+ t.opt 'one', 'Option one', required: true, type: 'string'
).toThrow('--one is required. Try --help for more info.')
it 'handles short options just like long ones', ->
@troll = new Troll()
@troll.setCommandLine('test.coffee', '-o', 'shakespeare')
@troll.options (t) =>
- t.opt 'one', 'Option one', type: 'String'
+ t.opt 'one', 'Option one', type: 'string'
expect(_.has(@troll.givenOpts, 'one')).toBe true
it 'raises if the same argument is passed more than once', ->
@troll.setCommandLine('test.coffee', '-o', 'shakespeare', '-o', 'foo')
expect(=>
@troll.options (t) ->
- t.opt 'one', 'Option one', type: 'String'
+ t.opt 'one', 'Option one', type: 'string'
).toThrow('--one specified twice!')
it 'does type conversion to the desired type', ->
View
31 src/troll.coffee
@@ -80,7 +80,7 @@ class Options
@helpBanner = " #{text}"
calculateOptionLength: (k) ->
- return k.length if @parsedOpts[k].type is 'Boolean'
+ return k.length if @parsedOpts[k].type is 'boolean'
k.length + 4
optsWithDefaults: ->
@@ -91,14 +91,14 @@ class Options
if _.has(opts, 'default')
throw new TrollOptError('type defined when default was provided') if opts['type']
if _.contains([true, false], opts.default)
- opts['type'] = 'Boolean'
+ opts['type'] = 'boolean'
else
- opts['type'] = opts['default'].constructor.name
+ opts['type'] = typeof opts['default']
opts
processFlagOrOptFor: (opts) ->
- if _.has(opts, 'type') and opts.type != 'Boolean'
+ if _.has(opts, 'type') and opts.type != 'boolean'
opts['takesValue'] = true
else
opts['takesValue'] = false
@@ -152,7 +152,7 @@ class Options
throw new TrollOptError("'#{badOpts.join(', ')}' are required. Try --help for more info.")
validateTypeFor: (opt) ->
- unless _.contains(['String', 'Boolean', 'Integer', 'Float'], opt.type)
+ unless _.contains(['string', 'boolean', 'integer', 'float', 'number'], opt.type)
throw new TrollOptError("Invalid type: #{opt.type}")
class Troll
@@ -238,7 +238,7 @@ class Troll
output = @spacePad("#{name}", len + 1)
output += ", -#{opts.short}"
- output += " <#{@opts.displayTypeFor(opts.type)}>" if opts.type != 'Boolean'
+ output += " <#{@opts.displayTypeFor(opts.type)}>" if opts.type != 'boolean'
output += ": #{opts.desc}"
output += " (default: #{opts.default})" if _.has(opts, 'default')
output += " (required)" if _.has(opts, 'required') and opts.required
@@ -264,18 +264,27 @@ class Troll
optSpec = @opts.getParsedOpts()[opt]
@givenOpts[opt] = optSpec.default unless _.has(@givenOpts, opt)
+ isInt: (n) ->
+ typeof n is 'number' and (n % 1 == 0)
+
convert: (opt, value) ->
type = @opts.get(opt).type
- retValue = switch type
- when 'Integer' then parseInt(value)
- when 'Float' then parseFloat(value)
- when 'String' then value
+ retValue = switch type.toLowerCase()
+ when 'integer' then parseInt(value)
+ when 'float' then parseFloat(value)
+ when 'number' then @convertNumber(number)
+ when 'string' then value
- if _.contains([ 'Integer', 'Float' ], type) and !(retValue > 0) and !(retValue < 0)
+ if _.contains([ 'integer', 'float', 'number' ], type.toLowerCase()) and !(retValue > 0) and !(retValue < 0)
throw new TrollArgumentError("#{opt} has an invalid value supplied! Must be a #{type}")
retValue
+ convertNumber: (value) ->
+ if isInt(value)
+ parseInt(value)
+ else
+ parseFloat(value)
puts: (args...) ->
console.log args...

0 comments on commit 593246d

Please sign in to comment.