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

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

内容简介:在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风格的子命令;
  • 自动化的帮助信息;
  • ....

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


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

查看所有标签

猜你喜欢:

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

Head First Design Patterns

Head First Design Patterns

Elisabeth Freeman、Eric Freeman、Bert Bates、Kathy Sierra、Elisabeth Robson / O'Reilly Media / 2004-11-1 / USD 49.99

You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire),......一起来看看 《Head First Design Patterns》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具