Skip to content

Commit 7b49cd2

Browse files
authored
feat: added coerce option, for providing specialized argument parsing (#42)
1 parent f3e4616 commit 7b49cd2

3 files changed

Lines changed: 89 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ Parses command line arguments returning a simple mapping of keys and values.
5454
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.
5555
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
5656
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
57+
* `opts.coerce`: provide a custom function to coerce a value from the argument provided,
58+
e.g., `{coerce: {foo: function (arg, cb) {return cb(err, modifiedArg)}}}`.
5759
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
5860
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
5961
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.

index.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ function parse (args, opts) {
3737
normalize: {},
3838
configs: {},
3939
defaulted: {},
40-
nargs: {}
40+
nargs: {},
41+
coercions: {}
4142
}
4243

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

72+
Object.keys(opts.coerce || {}).forEach(function (k) {
73+
flags.coercions[k] = opts.coerce[k]
74+
})
75+
7176
if (Array.isArray(opts.config) || typeof opts.config === 'string') {
7277
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
7378
flags.configs[key] = true
@@ -331,7 +336,7 @@ function parse (args, opts) {
331336
}
332337

333338
var value = val
334-
if (!checkAllAliases(key, flags.strings)) {
339+
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.coercions)) {
335340
if (isNumber(val)) value = Number(val)
336341
if (!isUndefined(val) && !isNumber(val) && checkAllAliases(key, flags.numbers)) value = NaN
337342
}
@@ -512,6 +517,13 @@ function parse (args, opts) {
512517
})
513518

514519
var key = keys[keys.length - 1]
520+
var coerce = checkAllAliases(key, flags.coercions)
521+
if (coerce) {
522+
coerce(value, function (err, val) {
523+
error = err
524+
value = val
525+
})
526+
}
515527

516528
if (value === increment) {
517529
o[key] = increment(o[key])

test/yargs-parser.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,4 +1933,77 @@ describe('yargs-parser', function () {
19331933
parsed.f.should.deep.equal([])
19341934
parsed.files.should.deep.equal([])
19351935
})
1936+
1937+
describe('coerce', function () {
1938+
it('applies coercion function to simple arguments', function () {
1939+
var parsed = parser(['--foo', '99'], {
1940+
coerce: {
1941+
foo: function (arg, cb) {
1942+
return cb(null, arg * -1)
1943+
}
1944+
}
1945+
})
1946+
parsed.foo.should.equal(-99)
1947+
})
1948+
1949+
it('applies coercion function to aliases', function () {
1950+
var parsed = parser(['--foo', '99'], {
1951+
coerce: {
1952+
f: function (arg, cb) {
1953+
return cb(null, arg * -1)
1954+
}
1955+
},
1956+
alias: {
1957+
f: ['foo']
1958+
}
1959+
})
1960+
parsed.foo.should.equal(-99)
1961+
parsed.f.should.equal(-99)
1962+
})
1963+
1964+
it('applies coercion function to an array', function () {
1965+
var parsed = parser(['--foo', '99', '-f', '33'], {
1966+
coerce: {
1967+
f: function (arg, cb) {
1968+
return cb(null, arg * -1)
1969+
}
1970+
},
1971+
array: ['foo'],
1972+
alias: {
1973+
f: ['foo']
1974+
}
1975+
})
1976+
parsed.f.should.deep.equal([-99, -33])
1977+
parsed.foo.should.deep.equal([-99, -33])
1978+
})
1979+
1980+
// see: https://github.com/yargs/yargs/issues/550
1981+
it('coercion function can be used to parse large #s', function () {
1982+
var fancyNumberParser = function (arg, cb) {
1983+
if (arg.length > 10) return cb(null, arg)
1984+
else return cb(null, parseInt(arg))
1985+
}
1986+
var parsed = parser(['--foo', '88888889999990000998989898989898', '--bar', '998'], {
1987+
coerce: {
1988+
foo: fancyNumberParser,
1989+
bar: fancyNumberParser
1990+
}
1991+
})
1992+
;(typeof parsed.foo).should.equal('string')
1993+
parsed.foo.should.equal('88888889999990000998989898989898')
1994+
;(typeof parsed.bar).should.equal('number')
1995+
parsed.bar.should.equal(998)
1996+
})
1997+
1998+
it('populates argv.error, if an error is returned', function () {
1999+
var parsed = parser.detailed(['--foo', '99'], {
2000+
coerce: {
2001+
foo: function (arg, cb) {
2002+
return cb(Error('banana'), arg * -1)
2003+
}
2004+
}
2005+
})
2006+
parsed.error.message.should.equal('banana')
2007+
})
2008+
})
19362009
})

0 commit comments

Comments
 (0)