Comparing version 0.1.3 to 0.1.4
106
cuisinart.js
@@ -23,7 +23,7 @@ var assert = require('assert'); | ||
pattern += ')'; | ||
pattern += '(?:\\s|$)([^-\\s]+)?'; | ||
pattern += '(?:\\s|$)([^\\s]+)?'; | ||
var regex = new RegExp(pattern); | ||
var matches = args.join(' ').match(regex); | ||
var matches = (' ' + args.join(' ')).match(regex); | ||
return matches && matches[0] ? matches.splice(1) : matches; | ||
} | ||
}; | ||
@@ -37,3 +37,3 @@ var matchOption = function(args,option){ | ||
} | ||
} | ||
}; | ||
@@ -48,3 +48,3 @@ var matchCommand = function(args,command){ | ||
} | ||
} | ||
}; | ||
@@ -57,7 +57,7 @@ var usageLength = function(option){ | ||
return length; | ||
} | ||
}; | ||
var optionMaxLength = function(command){ | ||
return (command.options || []).reduce(function(p,option){ return Math.max(p,usageLength(option)); },0); | ||
} | ||
}; | ||
@@ -86,3 +86,3 @@ var printUsage = function(command){ | ||
}); | ||
} | ||
}; | ||
@@ -100,4 +100,22 @@ var hasCallback = function(fn){ | ||
return cbPattern.test(fnString); | ||
} | ||
}; | ||
var unmatchedArgs = function(){ | ||
var args = this.args; | ||
var argsString = Array.prototype.slice.call(args,1).join('##'); | ||
this._commands.forEach(function(command){ | ||
var match = matchCommand(args,command); | ||
if(match){ | ||
argsString = argsString.replace(match,''); | ||
(command.options || []).forEach(function(option){ | ||
var optionMatch = optionMatches(args,option); | ||
if(optionMatch){ | ||
argsString = argsString.replace(optionMatch.join('##').trim(),''); | ||
} | ||
}); | ||
} | ||
}); | ||
return argsString.split('##').filter(function(v){return v;}); | ||
}; | ||
cuisinart.program = function(name){ | ||
@@ -114,2 +132,3 @@ assert(name,'programs must have names.'); | ||
self._baseArgs = []; | ||
self._args = []; | ||
@@ -148,18 +167,2 @@ // setters | ||
}; | ||
self.unmatchedArgs = function(args){ | ||
var argsString = Array.prototype.slice.call(args,2).join('##'); | ||
this._commands.forEach(function(command){ | ||
var match = matchCommand(args,command); | ||
if(match){ | ||
argsString = argsString.replace(match,''); | ||
(command.options || []).forEach(function(option){ | ||
var optionMatch = optionMatches(args,option); | ||
if(optionMatch){ | ||
argsString = argsString.replace(optionMatch.join('##').trim(),''); | ||
} | ||
}); | ||
} | ||
}); | ||
return argsString.split('##').filter(function(v){return v;}); | ||
} | ||
@@ -169,31 +172,42 @@ // methods | ||
self.run = function(command,args,done){ | ||
// trim off the command name | ||
args = args.slice(1); | ||
var optionMap = (command.options || []).reduce(function(o,option){ | ||
var value = matchOption(args,option); | ||
if(value){ | ||
o[option.name] = value; | ||
} | ||
return o; | ||
},{}); | ||
this.unmatchedArgs = unmatchedArgs.apply(this); | ||
var calledBack; | ||
var complete = function(err){ | ||
if(calledBack) return; | ||
calledBack = true; | ||
var args = Array.prototype.slice.call(arguments); | ||
if(command.stop) args[0] = new Error('complete'); | ||
done.apply(null,args); | ||
}; | ||
command.run.apply(self,[optionMap].concat(self._baseArgs,complete)); | ||
// if we don't detect a callback, assume that this is synchronous. | ||
if(!hasCallback(command.run)) complete(); | ||
}; | ||
self.parse = function(args,callback){ | ||
args = Array.prototype.slice.call(args,2); | ||
self.args = args; | ||
var matchedCommands = 0; | ||
async.forEachSeries(self._commands,function(command,done){ | ||
async.mapSeries(self._commands,function(command,done){ | ||
var matched = matchCommand(args,command); | ||
if(matched){ | ||
matchedCommands++; | ||
var optionMap = (command.options || []).reduce(function(o,option){ | ||
var value = matchOption(args,option); | ||
if(value){ | ||
o[option.name] = value; | ||
} | ||
return o; | ||
},{}); | ||
var calledBack; | ||
var complete = function(err){ | ||
if(calledBack) return; | ||
calledBack = true; | ||
if(err) return done(err); | ||
if(command.stop) return done(new Error('complete')); | ||
done(); | ||
}; | ||
command.run.apply(self,[optionMap].concat(self._baseArgs,complete)); | ||
// if we don't detect a callback, assume that this is synchronous. | ||
if(!hasCallback(command.run)) complete(); | ||
self.run(command,args,done); | ||
} else { | ||
done(); | ||
} | ||
},function(err){ | ||
},function(err,results){ | ||
if(!matchedCommands){ | ||
@@ -203,3 +217,3 @@ // print the help if nothing matches | ||
} | ||
if(callback) callback(err); | ||
if(callback) callback(err,results); | ||
}); | ||
@@ -206,0 +220,0 @@ }; |
{ | ||
"name": "cuisinart", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "A node js command line parser", | ||
@@ -5,0 +5,0 @@ "main": "cuisinart.js", |
@@ -18,2 +18,3 @@ var cuisinart = require('../../cuisinart.js'); | ||
run : function(options,arg1,arg2){ | ||
console.log(options); | ||
if(options.foo){ | ||
@@ -20,0 +21,0 @@ console.log('foo is ' + options.foo); |
var utils = require('../utils/utils'); | ||
var assert = require('assert'); | ||
var cuisinart = require('../../cuisinart.js'); | ||
var command = { | ||
options : [ | ||
{ | ||
name : 'foo', | ||
flag : 'f', | ||
description : 'foo' | ||
},{ | ||
name : 'bar', | ||
longFlag : 'bar', | ||
description : 'bar' | ||
} | ||
], | ||
name : 'command', | ||
run : function(options){ | ||
console.log('command ran'); | ||
} | ||
}; | ||
describe('when called with unmatched arguments', function () { | ||
it('should properly return the unmatched arguments',function(){ | ||
var program = cuisinart.program('app'); | ||
var dir; | ||
var bin; | ||
program | ||
.usage('[command]') | ||
.description('an app with an async command and no base args') | ||
.command(command) | ||
before(function (done) { | ||
utils.createEnvironment('app_unmatchedargs.js',function (err, newDir, binPath) { | ||
if (err) return done(err); | ||
dir = newDir; | ||
bin = binPath; | ||
done(); | ||
}); | ||
}); | ||
var unmatched = program.unmatchedArgs(['command','-f','--bar','barargument','extra']); | ||
after(function (done) { | ||
this.timeout(30000); | ||
utils.cleanup(dir, done); | ||
}); | ||
assert.deepEqual(unmatched,['extra']); | ||
it('should properly return the unmatched arguments',function(done){ | ||
utils.run(dir,bin,['command','-f','foo','--bar','bar','extra','arguments'],function(err,stdout){ | ||
if (err) return done(err); | ||
assert.ok(/unmatched arguments: extra,arguments/.test(stdout)); | ||
done(); | ||
}); | ||
}); | ||
}); |
39004
22
1064