Skip to content

Commit

Permalink
in-prep for further refactoring, and a 3.x release I've shuffled some…
Browse files Browse the repository at this point in the history
… things around and gotten test-coverage to 100%.
  • Loading branch information
bcoe committed Feb 8, 2015
1 parent d640745 commit d6edd98
Show file tree
Hide file tree
Showing 20 changed files with 702 additions and 504 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,13 @@ usage information and exit.
The default behaviour is to set the value of any key not followed by an
option value to `true`.

.implies(x, y)
--------------

Given the key `x` is set, it is required that the key `y` is set.

implies can also accept an object specifying multiple implications.

.describe(key, desc)
--------------------

Expand Down Expand Up @@ -469,6 +476,13 @@ Check that certain conditions are met in the provided arguments.
If `fn` throws or returns `false`, show the thrown error, usage information, and
exit.

.fail(fn)
---------

Method to execute when a failure occurs, rather then printing the failure message.

`fn` is called with the failure message that would have been printed.

.boolean(key)
-------------

Expand Down
42 changes: 28 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var path = require('path');
var minimist = require('./lib/minimist');
var wordwrap = require('./lib/wordwrap');
var parser = require('./lib/parser');
var wordwrap = require('wordwrap');

/* Hack an instance of Argv with process.argv into Argv
so people can do
Expand Down Expand Up @@ -189,7 +189,7 @@ function Argv (processArgs, cwd) {
if (exitProcess){
process.exit(1);
}else{
throw new Error(msg);
throw new Error(msg);
}
}
}
Expand Down Expand Up @@ -300,8 +300,8 @@ function Argv (processArgs, cwd) {
var showHelpOnFail = true;
self.showHelpOnFail = function (enabled, message) {
if (typeof enabled === 'string') {
enabled = true;
message = enabled;
enabled = true;
}
else if (typeof enabled === 'undefined') {
enabled = true;
Expand Down Expand Up @@ -440,13 +440,17 @@ function Argv (processArgs, cwd) {
var dlen = dlines.slice(-1)[0].length
+ (dlines.length === 1 ? prelude.length : 0)

body = desc + (dlen + extra.length > wrap - 2
? '\n'
+ new Array(wrap - extra.length + 1).join(' ')
+ extra
: new Array(wrap - extra.length - dlen + 1).join(' ')
+ extra
);
if (extra.length > wrap) {
body = desc + '\n' + wordwrap(switchlen + 4, wrap)(extra)
} else {
body = desc + (dlen + extra.length > wrap - 2
? '\n'
+ new Array(wrap - extra.length + 1).join(' ')
+ extra
: new Array(wrap - extra.length - dlen + 1).join(' ')
+ extra
);
}
}

help.push(prelude + body);
Expand All @@ -457,12 +461,22 @@ function Argv (processArgs, cwd) {
};

Object.defineProperty(self, 'argv', {
get : function () { return parseArgs(processArgs) },
get : function () {
var args = null;

try {
args = parseArgs(processArgs);
} catch (err) {
fail(err.message);
}

return args;
},
enumerable : true
});

function parseArgs (args) {
var parsed = minimist(args, options),
var parsed = parser(args, options),
argv = parsed.argv,
aliases = parsed.aliases;

Expand Down Expand Up @@ -501,7 +515,7 @@ function Argv (processArgs, cwd) {
options.requiresArg.forEach(function(key) {
var value = argv[key];

// minimist sets --foo value to true / --no-foo to false
// parser sets --foo value to true / --no-foo to false
if (value === true || value === false) {
missingRequiredArgs.push(key);
}
Expand Down
9 changes: 3 additions & 6 deletions lib/minimist.js → lib/parser.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// fancy-pants parsing of argv, originally forked
// from minimist: https://www.npmjs.com/package/minimist
var path = require('path');
var fs = require('fs');

Expand Down Expand Up @@ -145,8 +147,7 @@ module.exports = function (args, opts) {
}
});
} catch (ex) {
console.error('Invalid JSON config file: ' + configPath);
throw ex;
throw Error('invalid json config file: ' + configPath);
}
}
});
Expand Down Expand Up @@ -328,7 +329,3 @@ function isNumber (x) {
if (/^0x[0-9a-f]+$/i.test(x)) return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
}

function longest (xs) {
return Math.max.apply(null, xs.map(function (x) { return x.length }));
}
50 changes: 0 additions & 50 deletions lib/wordwrap.js

This file was deleted.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"lib",
"LICENSE"
],
"dependencies": {},
"dependencies": {
"wordwrap": "0.0.2"
},
"devDependencies": {
"blanket": "^1.1.6",
"chai": "^1.10.0",
Expand Down
136 changes: 136 additions & 0 deletions test/argv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
var should = require('chai').should(),
expect = require('chai').expect,
checkOutput = require('./helpers/utils').checkOutput,
yargs = require('../'),
path = require('path');

describe('argv dsl tests', function () {
it('should use bin name for $0, eliminating path', function () {
process.argv[1] = '/usr/local/bin/ndm';
process.env._ = '/usr/local/bin/ndm';
process.execPath = '/usr/local/bin/ndm';
var argv = yargs([]).argv;
argv['$0'].should.eql('ndm');
});

it('accepts an object for aliases', function() {
var argv = yargs([])
.alias({
cool: 'cat'
})
.default('cool', 33)
.argv

argv.cat.should.eql(33);
});

it('accepts an object for implies', function() {
var r = checkOutput(function () {
return yargs(['--x=33'])
.implies({
x: 'y'
})
.argv
});

r.errors[1].should.match(/Implications failed/)
});

it('accepts an object for describes', function() {
var r = checkOutput(function () {
return yargs([])
.describe({
x: 'really cool key'
})
.demand('x')
.argv
});

r.errors[0].should.match(/really cool key/)
});

it('treats usage as alias for options, if object provided as first argument', function() {
var argv = yargs([])
.usage({
a: {
default: 99
}
})
.argv;

argv.a.should.eql(99);
});

it('a function can be provided, to execute when a parsing failure occurs', function(done) {
yargs(['--x=33'])
.implies({
x: 'y'
})
.fail(function(msg) {
msg.should.match(/Implications failed/);
return done();
})
.argv;
});

it('should set alias to string if option is string', function() {
var argv = yargs(['--cat=99'])
.options('c', {
alias: 'cat',
string: true
})
.argv

argv.cat.should.eql('99');
argv.c.should.eql('99');
});

describe('showHelpOnFail', function() {
it('should display custom failure message, if string is provided as first argument', function() {
var r = checkOutput(function () {
return yargs([])
.showHelpOnFail('pork chop sandwiches')
.demand('cat')
.argv;
});

r.errors[3].should.match(/pork chop sandwiches/);
});

it('calling with no arguments should default to displaying help', function() {
var r = checkOutput(function () {
return yargs([])
.showHelpOnFail()
.demand('cat')
.argv;
});

r.errors[1].should.match(/required arguments/);
});
});

describe('exitProcess', function() {
it('throws an execption when a failure occurs, if exitProcess is set to false', function() {
checkOutput(function () {
expect(function() {
var argv = yargs([])
.demand('cat')
.showHelpOnFail(false)
.exitProcess(false)
.argv;
}).to.throw(/Missing required arguments/);
});
});

it('should set exit process to true, if no argument provided', function() {
var r = checkOutput(function () {
return yargs([])
.demand('cat')
.exitProcess()
.argv;
});

r.exit.should.eql(true);
});
});
});
28 changes: 0 additions & 28 deletions test/count.js

This file was deleted.

Loading

0 comments on commit d6edd98

Please sign in to comment.