必知必会的Node-CLI开发基础

栏目: JavaScript · 发布时间: 6年前

内容简介:在NodeJS中可以通过以下代码获取命令行中传递的参数:但是这对于构建一个CLI工具远远不够,首先需要考虑参数输入的各种风格:这里可以通过正则表达式对process.argv进行加工:

在NodeJS中可以通过以下代码获取命令行中传递的参数:

process.argv.slice(2)
复制代码

但是这对于构建一个CLI工具远远不够,首先需要考虑参数输入的各种风格:

  • Unix参数风格:前面加-,不过后面跟的是单个字符,例如-abc解析为['a', 'b', 'c']。
  • GNU参数风格:前面加--,例如npm中的命令,npm --save-dev webpack。
  • BSD参数风格:前面不加修饰符。

这里可以通过正则表达式对process.argv进行加工:

/**
 * 解析Unix、BSD和GNU参数风格
 * @param {Array} argv 命令行参数数组
 * @returns
 */
function parseArgv (argv) {
  const max = argv.length
  const result = {
    _: []
  }
  for (let i = 0; i < max; i++) {
    const arg = argv[i]
    const next = argv[i + 1]
    if (/^--.+/.test(arg)) {
      // GNU风格
      const key = arg.match(/^--(.+)/)[1]
      if (next != null && !/^-.+/.test(next)) {
        result[key] = next
        i++
      } else {
        result[key] = true
      }
    } else if (/^-[^-]+/.test(arg)) {
      // Unix风格
      const items = arg.match(/^-([^-]+)/)[1].split('')
      for (let j = 0, max = items.length; j < max; j++) {
        const item = items[j]
        // 非字母不解析
        if (!/[a-zA-Z]/.test(item)) {
          continue
        }
        if (next != null && !/^-.+/.test(next) && j === max - 1) {
          result[item] = next
          i++
        } else {
          result[item] = true
        }
      }
    } else {
      // BSD风格
      result._.push(arg)
    }
  }
  return result
}
复制代码

通过以上的方法可以得到如下结果:

node example1.js --save-dev -age 20 some
  // => 结果
  {
    _: ['some'],
    'save-dev': true,
    a: true,
    g: true,
    e: 20
  }
复制代码

上面这个示例不仅仅为了展示解析的结果,而且还强调了Unix参数风格只解析单个字母,所以这种风格的参数可能表达的意思不太明确并且数量有限,那么就需要在正确的场景中使用这种风格的参数:

npm --save-dev webpack
  npm -D webpack
复制代码

npm中采用Unix参数风格表示简写,这就是一种很恰当的方式,那么前面示例中的-age按照语义应该改为--age更加合理一点。

二、命令行界面

NodeJS中的readline模块提供question和prompt方法构建命令行界面,下面是一个简单的问答式的交互界面:

const readline = require('readline');
const question = ['请输入您的姓名', '请输入您的年龄']
const result = []
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: `?${question[0]} `
});
rl.prompt();

rl.on('line', (line) => {
  result.push(line.trim())
  const max = result.length
  if (max === question.length) {
    rl.close()
  }
  rl.setPrompt(`?${question[max]} `)
  rl.prompt();
}).on('close', () => {
  console.log(`谢谢参与问答 *** 姓名: ${result[0]} 年龄: ${result[1]}`);
  process.exit(0);
}); 
复制代码
必知必会的Node-CLI开发基础

当然交互界面的元素并不只有这一种,在使用各类CLI工具时,你应该会遇到诸如:单项选择、下载进度条...

下面可以尝试实现一个单项选择交互界面:

const readline = require('readline')
let selected = 0
const choices = ['javascript', 'css', 'html']
let lineCount = 0
const rl = readline.createInterface(process.stdin, process.stdout)
function reader () {
  let str = ''
  for (let i = 0; i < choices.length; i++) {
    lineCount++
    str += `${selected === i ? '[X]' : '[ ]'} ${choices[i]}\r\n`
  }
  process.stdout.write(str)
}

reader()

process.stdin.on('keypress', (s, key) => {
  const name = key.name
  const max = choices.length
  if (name === 'up' && selected > 0) {
    selected--
  } else if (name === 'down' && selected < max - 1) {
    selected++
  } else if (name === 'down' && selected === max - 1) {
    selected = 0
  } else if (name === 'up' && selected === 0) {
    selected = max - 1
  } else {
    return true
  }
  // 移动光标,并且删除光标右边的内容
  readline.moveCursor(process.stdout, 0, -lineCount)
  readline.clearLine(process.stdout, -1)
  lineCount -= choices.length
  reader()
})

rl.on('line', () => {
  console.log(`you choose ${choices[selected]}`)
  process.exit(0)
}).on('close', () => {
  rl.close()
})
复制代码
必知必会的Node-CLI开发基础

三、定制样式

为了有效的区别命令行界面中信息的差异性,我们可以为这里输出信息添加适当的样式。

这里介绍一下字符串添加样式的语法:

\x1b[背景颜色编号;字体颜色编号m
复制代码

每条样式都要以\x1b[开头:

// \x1b[0m 清除样式
  process.stdout.write('\x1b[44;37m OK \x1b[0m just do it\n')
复制代码
必知必会的Node-CLI开发基础

四、自定义Node命令

接下来就是自定义Node命令,首先需要创建一个命令执行的文件:

// hello.js 首行需要指定脚本的解释程序
  #!/usr/bin/env node
  console.log('hello')
复制代码

再利用package.json中的bin配置:

{
    "bin": {
      "hello": "./hello.js"
    },
  }
复制代码

执行npm的link命令:

npm link
  
  # 输入自定义命令
  hello

  # 输出 hello
复制代码

五、总结

上面介绍了开发Node-CLI时所需要的一些基本知识,但是对于用过诸如webpack-cli、vue-cli工具的你可能会发现这些优秀的CLI工具还具有:

  • git风格的子命令;
  • 自动化的帮助信息;
  • ....

那么下面这些成熟的框架会给你很大的帮助:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程之道

编程之道

杰弗雷﹒詹姆斯 / 清华大学出版社 / 1999-05 / 18.00元

本书出自美国一位善于进行哲学思考、有十多年工作经验的程序设计师——杰弗雷·詹姆斯之手,他以一种敏锐的眼光审视着发生在程序设计室里的各种各样的小故事,并利用古老的道家思想对其进行分析。简单的故事蕴含深奥的道理,是本书的最大特色。本书语言优美,比喻生动,可读性极强。一起来看看 《编程之道》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具