美文网首页首页投稿(暂停使用,暂停投稿)
使用nodejs书写命令行程序的简单框架

使用nodejs书写命令行程序的简单框架

作者: tpglzu | 来源:发表于2016-07-25 16:58 被阅读0次

引子

本文使用Nodejs主要实现了如下形式的命令行程序

node index -A 100 //主命令
node index cmd1 -C 100 -D 200 //使用option的子命令
node index cmd2 param1 param2 param3 //使用argments的子命令
node index cmd3 -E 100 -F 200 param1 param2 //同时使用argments和option的子命令

文中option的取值通过options.option名的方式取得,option名在option定义时,通过--option名定义

导入第三方package

var co = require('co');
var program = require('commander');
var colors = require('colors');
  • co以同步的书写方式书写回调函数
  • commander解析命令行参数和选项,执行Action
  • colors修改输出文字颜色,美化控制台输出

书写流程控制函数

对于每一个命令,虽然执行内容不同,但执行流程如下所示大致相同

  • 使用co调用该命令的处理函数
  • 执行成功后输出success信息,退出程序
  • 执行失败后输出error信息,退出程序
var execute = function(target, args) {
  co(function*() {
    yield target.apply(this, args);
  }).then(function() {
    console.log(colors.green('[end]') + ' success');
    process.exit();
  }, function(error) {
    console.log(error);
    process.exit();
  });
};

书写各命令的处理函数

  • 主命令处理函数
    接受program作为入参,从中可获取指定的option的值。
var doMain = function*(program) {
  console.log(colors.green('[start]') + ' doMain1...');
  // do something
  console.log(program.aa);
  console.log(colors.green('[end  ]') + ' doMain1');
};
  • 子命令1的处理函数
    使用options作为入参,从中可获取指定的option的值。
var doCmd1 = function*(options) {
  console.log(colors.green('[start]') + ' doCmd1...');
  // do something
  console.log(options.cc + ',' + options.dd);
  console.log(colors.green('[end  ]') + ' doCmd1');
};
  • 子命令2的处理函数
    使用命令行参数作为入参
var doCmd2 = function*(arg1, arg2, arg3) {
  console.log(colors.green('[start]') + ' doCmd2...');
  // do something
  console.log(arg1 + ',' + arg2 + ',' + arg3);
  console.log(colors.green('[end  ]') + ' doCmd2');
};
  • 子命令3的处理函数
    使用命令行参数和options作为入参,options中可获取指定的option的值。
var doCmd3 = function*(arg1, arg2, arg3, options) {
  console.log(colors.green('[start]') + ' doCmd3...');
  // do something
  console.log(arg1 + ',' + arg2 + ',' + arg3 + ',' + options.ee + ',' +
    options.ff);
  console.log(colors.green('[end  ]') + ' doCmd3');
};

定义命令行参数,Option以及Action

  • 主命令定义
    定义程序的版本,option信息和帮助信息。
program
  .version('0.0.1');
program
  .description('使用node书写命令行程序的简单框架')
  .option('-A, --aa <optionA>', 'XXXX数.')
  .option('-B, --bb <optionB>', 'XXXX数.');
program.on('--help', function() {
  console.log('  Examples:');
  console.log('');
  console.log('    node index cmd1 -C 100 -D 200');
  console.log('    node index cmd2 param1 param2 param3');
  console.log('    node index cmd3 -E 100 -F 200 param1 param2');
  console.log('');
});
  • 子命令定义
    定义各命令的option和处理action,以及描述信息和帮助信息
program
  .command('cmd1')
  .description('只包含Option的子命令')
  .option('-C, --cc <optionC>', 'XXXX数.')
  .option('-D, --dd <optionD>', 'XXXX数.')
  .action(function() {
    execute(doCmd1, arguments);
  });
program
  .command('cmd2 <arg1> <arg2> [arg3]')
  .description('只包含命令行参数的子命令')
  .action(function() {
    execute(doCmd2, arguments);
  }).on('--help', function() {
    console.log('  arg1:');
    console.log('');
    console.log('    arg1的含义说明');
    console.log('');
  });
program
  .command('cmd3 <arg1> <arg2> [arg3]')
  .option('-E, --ee <optionE>', 'XXXX数.')
  .option('-F, --ff <optionF>', 'XXXX数.')
  .description('同时包含命令行参数和Option的子命令')
  .action(function() {
    execute(doCmd3, arguments);
  }).on('--help', function() {
    console.log('  arg1:');
    console.log('');
    console.log('    arg1的含义说明');
    console.log('');
  });

命令行解析和执行

program.parse(process.argv);

主程序流程控制

  • 设置主程序运行flag
var mainFlg = true;
  • 运行程序时,如果未指定任何子命令或option信息,输出帮助信息,不执行主命令
if (!process.argv.slice(2).length) {
  program.outputHelp(make_red);
  mainFlg = false;
}
function make_red(txt) {
  return colors.red(txt); //display the help text in red on the console
}
  • 运行程序时,如果指定了子命令,执行子命令,不执行主命令
var cmds = [];
program.commands.map(function(cmd) {
  cmds.push(cmd._name);
});
for (var arg of process.argv.slice(2)) {
  if (cmds.indexOf(arg) >= 0) {
    mainFlg = false;
  }
}
if (mainFlg) {
  execute(doMain, [program]);
}

完整的程序文件

'use strict';
var co = require('co');
var program = require('commander');
var colors = require('colors');
var execute = function(target, args) {
  co(function*() {
    yield target.apply(this, args);
  }).then(function() {
    console.log(colors.green('[end  ]') + ' success');
    process.exit();
  }, function(error) {
    console.log(error);
    process.exit();
  });
};
var doMain = function*(program) {
  console.log(colors.green('[start]') + ' doMain1...');
  // do something
  console.log(program.aa);
  console.log(colors.green('[end  ]') + ' doMain1');
};
var doCmd1 = function*(options) {
  console.log(colors.green('[start]') + ' doCmd1...');
  // do something
  console.log(options.cc + ',' + options.dd);
  console.log(colors.green('[end  ]') + ' doCmd1');
};
var doCmd2 = function*(arg1, arg2, arg3) {
  console.log(colors.green('[start]') + ' doCmd2...');
  // do something
  console.log(arg1 + ',' + arg2 + ',' + arg3);
  console.log(colors.green('[end  ]') + ' doCmd2');
};
var doCmd3 = function*(arg1, arg2, arg3, options) {
  console.log(colors.green('[start]') + ' doCmd3...');
  // do something
  console.log(arg1 + ',' + arg2 + ',' + arg3 + ',' + options.ee + ',' +
    options.ff);
  console.log(colors.green('[end  ]') + ' doCmd3');
};
program
  .version('0.0.1');
program
  .description('使用node书写命令行程序的简单框架')
  .option('-A, --aa <optionA>', 'XXXX数.')
  .option('-B, --bb <optionB>', 'XXXX数.');
program.on('--help', function() {
  console.log('  Examples:');
  console.log('');
  console.log('    node index cmd1 -C 100 -D 200');
  console.log('    node index cmd2 param1 param2 param3');
  console.log('    node index cmd3 -E 100 -F 200 param1 param2');
  console.log('');
});
program
  .command('cmd1')
  .description('只包含Option的子命令')
  .option('-C, --cc <optionC>', 'XXXX数.')
  .option('-D, --dd <optionD>', 'XXXX数.')
  .action(function() {
    execute(doCmd1, arguments);
  });
program
  .command('cmd2 <arg1> <arg2> [arg3]')
  .description('只包含命令行参数的子命令')
  .action(function() {
    execute(doCmd2, arguments);
  }).on('--help', function() {
    console.log('  arg1:');
    console.log('');
    console.log('    arg1的含义说明');
    console.log('');
  });
program
  .command('cmd3 <arg1> <arg2> [arg3]')
  .option('-E, --ee <optionE>', 'XXXX数.')
  .option('-F, --ff <optionF>', 'XXXX数.')
  .description('同时包含命令行参数和Option的子命令')
  .action(function() {
    execute(doCmd3, arguments);
  }).on('--help', function() {
    console.log('  arg1:');
    console.log('');
    console.log('    arg1的含义说明');
    console.log('');
  });
program.parse(process.argv);
var mainFlg = true;
if (!process.argv.slice(2).length) {
  program.outputHelp(make_red);
  mainFlg = false;
}
function make_red(txt) {
  return colors.red(txt); //display the help text in red on the console
}
var cmds = [];
program.commands.map(function(cmd) {
  cmds.push(cmd._name);
});
for (var arg of process.argv.slice(2)) {
  if (cmds.indexOf(arg) >= 0) {
    mainFlg = false;
  }
}
if (mainFlg) {
  execute(doMain, [program]);
}

相关文章

网友评论

    本文标题:使用nodejs书写命令行程序的简单框架

    本文链接:https://www.haomeiwen.com/subject/agugjttx.html