nodejs写工具时,需要用命令函参数来控制程序的行为。由于不想用npm上的解析器,因为他们的api设计不符合我的要求,所以准备自己实现一个。
这个模块的主要功能是把字符串形式的命令行参数解析成 json
给程序调用,因此设计api时必然要把规则和对应的回调函数注册到一个列表中,之后以循环的方式取出匹配的回调函数并执行。此外最重要的是保持api的干净简洁,绝对不添加多余的接口名称。 因为多一个名称对于使用者就是增加学习成本。
这个模块我命名为cmd-args,调用形式如下:
var c=require('cmd-args');
// 用户输入的命令行
// 命令行的格式为:
// 命令名称 --开关=值|--开关数组[]=值|目标
c.resolve('X --a=1 --b=" 21" "target 1" --c --d="" --e[]=e1 --e[]=e2 target2 ',
// 解析之后回调函数,参数def用来定义解析规则,参数effectAll用来设置是否只对第一条匹配的规则生效
function(def,effectAll){
// def的回调函数接收的参数顺序和定义的一致,最后的target为命令行中的目标
// 此处的e是开关数组,所以需要用[]标记,取出的时候也是一个数组
def('X --a --b --c --d --e[]',function(a,b,c,d,e,target1,target2){
console.log(a,b,c,d,e,target1,target2);
});
})
// 返回的是Promise,所以可以很方便的用then处理结果
.then(function(o){
console.log('success',o);
},function(){
console.log('fail, no matches');
});
cmd-args.js
模块代码:
exports.resolve=function(line,callback){
var result={ id:null, target:[], list:{}};
var trim=function(s){return s.replace(/^"|"$/g,'');};
var matches={ count:0, lines:[], effectAll:false };
(line||'').replace(
/(^\S+)|(?:\-\-([^\=\s\[]+(\[\s*\]){0,1}))(?:\=("[^"]*"|\S+)){0,1}|("[^"]*"|\S+)/g,
function(a,id,key,isArray,value,target){
switch(false){
case !id: return result.id=id.toLowerCase();
case !target: return result.target.push(trim(target));
default:
value=trim(value||'')||true;
if(!isArray)return result.list[key]=value;
result.list[key]=result.list[key]||[];
result.list[key].push(value);
}
});
callback(function callee(key,beside,handler){
if(!handler)return callee(key,'',beside);
key=key.toLowerCase().split(/\s+\-+/);
beside=beside.toLowerCase().split(/\s+/);
if(result.id!==key.shift())return;
if(!key.every(function(k,i){
key[i]=result.list[k];
return k && result.list.hasOwnProperty(k);
}))return;
if(!beside.every(function(k){
k=k.replace(/^\-+/,'');
return !k || !result.list.hasOwnProperty(k);
}))return;
handler.apply({},key.concat(result.target));
matches.count++;
matches.lines.push(line);
return true;
},function(){ matches.effectAll=true; });
return new Promise(function(resolve,reject){
matches.count>0?resolve(matches):reject();
});
};
相关文档
暂无
随便看看
畅言模块加载中