Skip to content

Instantly share code, notes, and snippets.

@mashingan
Created January 12, 2017 17:35
Show Gist options
  • Save mashingan/68f2930b0e311af02a2c5b573209c175 to your computer and use it in GitHub Desktop.
Save mashingan/68f2930b0e311af02a2c5b573209c175 to your computer and use it in GitHub Desktop.
An attempt to implement cmd parser like commander.
var mycommander = require('./mycommander');
console.log(mycommander);
console.log(process.argv.slice(2));
mycommander
.option('-f, --foo i', 'Integer value for foo', parseInt, 0)
.option('-b, --bar j', 'Integer value for bar', parseInt, 0)
.option('-z, --baz', 'Boolean argument baz')
.parse(process.argv.slice(2));
console.log(mycommander);
console.log(mycommander.foo.value);
console.log(mycommander.bar.value);
console.log(mycommander.baz.value);
function MyCommander() {
var self = this;
self.option = function (cmdString, info, parserCb, defaultVal) {
return option(self, cmdString, info, parserCb, defaultVal);
};
self.parse = function (args) {
return parse(self, args);
};
self.prompt = prompt;
//somehow cannot be functioning well
//self.confirm = confirm;
return this;
}
function option (thisObj, cmdString, info, parserCb, defaultVal) {
var cmds = cmdString.split(',').map(function (option) {
return option.trim();
});
var shortOpt;
var idx = 0;
if (cmds.length === 1 && cmds[0].indexOf('--') === 0) {
idx = 0;
}
else if (cmds.length === 2 && cmds[1].indexOf('--') === 0) {
idx = 1;
shortOpt = cmds[0];
}
var memberName = cmds[idx].trim().substr(2).trim().split(' ')[0];
memberName = memberName.split('=', 2)[0];
thisObj[memberName] = {};
thisObj[memberName].info = info;
if (shortOpt) thisObj[shortOpt] = memberName;
thisObj[memberName].parse = function (value) {
var result = value? parserCb(value) :
(defaultVal !== undefined) ? defaultVal : true;
console.log('parse result:', result);
return result;
};
return thisObj;
}
function parse(thisObj, args) {
var prevArg = '';
args.forEach(function (arg, idx) {
arg = arg.trim();
switch (optionTester(arg)) {
case 'option':
var somearg = getMemberName(thisObj, arg);
if (prevArg) {
executeParse(thisObj, prevArg);
} else if (idx === args.length - 1) {
executeParse(thisObj, somearg);
}
prevArg = somearg;
break;
case 'option-value':
if (prevArg) {
executeParse(thisObj, prevArg);
}
var optVal = arg.split('=', 2);
var thearg = optVal[0];
var value = optVal[1];
var memberName;
try {
memberName = getMemberName(thisObj, thearg);
} catch (error) {
console.log(error);
}
thisObj[memberName].value = thisObj[memberName].parse(value);
prevArg = '';
break;
case 'value':
if (prevArg) {
thisObj[prevArg].value = thisObj[prevArg].parse(arg);
prevArg = '';
}
break;
}
});
return thisObj;
}
function getMemberName (thisObj, opt) {
if (opt.indexOf('--') === 0)
return opt.substr(2);
else if (opt.indexOf('-') === 0)
return thisObj[opt];
else
throw new Error('No ' + opt + ' option defined.');
}
function executeParse (thisObj, memberName) {
thisObj[memberName].value = thisObj[memberName].parse();
}
function optionTester (arg) {
if (arg.indexOf('=') !== -1)
return 'option-value';
else if (arg.indexOf('--') === 0 || arg.indexOf('-') === 0)
return 'option';
else
return 'value';
}
function prompt(question, cb) {
console.log(question);
process.stdin.on('data', cb);
process.stdin.setEncoding('utf8');
process.stdin.resume();
}
function confirm(question, cb) {
prompt(question, function(data) {
var trueAnswer = [ 'y', 'ok', 'yes', 'true' ];
if (trueAnswer.indexOf(data.toLowerCase()) !== -1) {
cb(true);
}
else {
cb(false);
}
});
}
module.exports = (function () { return new MyCommander(); })();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment