展开目录
简易命令行解析器
nodejsjavascriptcmd
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

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();
  });
};

相关文档

暂无

随便看看

  1. 定长消息队列读写优化

  2. css多行文本超出截断显示省略号

  3. css3自定义滚动条样式

  4. sass变量和继承类写法

  5. npm远程服务器某些配置不兼容代理的解决办法

  6. html5 全屏代码

  7. 判断变量是否 0 或者 '0'

  8. nodejs俄罗斯方块

  9. heroku查看app使用时间

  10. heroku登陆cli

  11. 单页应用的单向数据流的流程图

  12. cdn资源列表

  13. webpack使用外部资源

  14. 树莓派配置wifi

  15. mysql选取内容导出到文件

  16. centos7 开放或者关闭端口

  17. 随机取某个概率区间的代码

  18. 数据库清理优化

  19. youku电脑版跳过广告代码

  20. 配置mysql ssl连接

畅言模块加载中