Skip to content

Commit

Permalink
feat: added coerce option, for providing specialized argument parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Coe committed Aug 8, 2016
1 parent f3e4616 commit 8d13abc
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -54,6 +54,8 @@ Parses command line arguments returning a simple mapping of keys and values.
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
* `opts.coerce`: provide a custom function to coerce a value from the argument provided,
e.g., `{coerce: {foo: function (arg, cb) {return cb(err, modifiedArg)}}}`.
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.
Expand Down
16 changes: 14 additions & 2 deletions index.js
Expand Up @@ -37,7 +37,8 @@ function parse (args, opts) {
normalize: {},
configs: {},
defaulted: {},
nargs: {}
nargs: {},
coercions: {}
}

;[].concat(opts.array).filter(Boolean).forEach(function (key) {
Expand Down Expand Up @@ -68,6 +69,10 @@ function parse (args, opts) {
flags.nargs[k] = opts.narg[k]
})

Object.keys(opts.coerce || {}).forEach(function (k) {
flags.coercions[k] = opts.coerce[k]
})

if (Array.isArray(opts.config) || typeof opts.config === 'string') {
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
flags.configs[key] = true
Expand Down Expand Up @@ -331,7 +336,7 @@ function parse (args, opts) {
}

var value = val
if (!checkAllAliases(key, flags.strings)) {
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.coercions)) {
if (isNumber(val)) value = Number(val)
if (!isUndefined(val) && !isNumber(val) && checkAllAliases(key, flags.numbers)) value = NaN
}
Expand Down Expand Up @@ -512,6 +517,13 @@ function parse (args, opts) {
})

var key = keys[keys.length - 1]
var coerce = checkAllAliases(key, flags.coercions)
if (coerce) {
coerce(value, function (err, val) {
error = err
value = val
})
}

if (value === increment) {
o[key] = increment(o[key])
Expand Down
73 changes: 73 additions & 0 deletions test/yargs-parser.js
Expand Up @@ -1933,4 +1933,77 @@ describe('yargs-parser', function () {
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
})

describe('coerce', function () {
it('applies coercion function to simple arguments', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
foo: function (arg, cb) {
return cb(null, arg * -1)
}
}
})
parsed.foo.should.equal(-99)
})

it('applies coercion function to aliases', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
f: function (arg, cb) {
return cb(null, arg * -1)
}
},
alias: {
f: ['foo']
}
})
parsed.foo.should.equal(-99)
parsed.f.should.equal(-99)
})

it('applies coercion function to an array', function () {
var parsed = parser(['--foo', '99', '-f', '33'], {
coerce: {
f: function (arg, cb) {
return cb(null, arg * -1)
}
},
array: ['foo'],
alias: {
f: ['foo']
}
})
parsed.f.should.deep.equal([-99, -33])
parsed.foo.should.deep.equal([-99, -33])
})

// see: https://github.com/yargs/yargs/issues/550
it('coercion function can be used to parse large #s', function () {
var fancyNumberParser = function (arg, cb) {
if (arg.length > 10) return cb(null, arg)
else return cb(null, parseInt(arg))
}
var parsed = parser(['--foo', '88888889999990000998989898989898', '--bar', '998'], {
coerce: {
foo: fancyNumberParser,
bar: fancyNumberParser
}
})
;(typeof parsed.foo).should.equal('string')
parsed.foo.should.equal('88888889999990000998989898989898')
;(typeof parsed.bar).should.equal('number')
parsed.bar.should.equal(998)
})

it('populates argv.error, if an error is returned', function () {
var parsed = parser.detailed(['--foo', '99'], {
coerce: {
foo: function (arg, cb) {
return cb(Error('banana'), arg * -1)
}
}
})
parsed.error.message.should.equal('banana')
})
})
})

0 comments on commit 8d13abc

Please sign in to comment.