Skip to content

用 NodeJS 写 CLI

关于执行脚本,肯定会想到 shell 脚本,借助于存量庞大的资源储备,生产力很不错。 但上手难度大,语法略显逆天,也是不争的事实。如果可以使用 javascript 来写脚本,对于前端工程师来说可谓减轻不少工作量。

开发 CLI

CLI 的开发最开始过程与普通的前端项目相同,需要一个入口文件 command.js 和配置文件 package.json。

与其他配置文件不同的是,你需要在 command.js 文件第一行增加如下声明:

bash
#! /usr/bin/env node
#! /usr/bin/env node

同时需要在 package.json 文件中加上一下一项:

json
{
  "bin": {
    "cm-cli": "command.js"
  }
}
{
  "bin": {
    "cm-cli": "command.js"
  }
}

在配置文件中增加了此项后,只需要在配置文件根目录下执行 npm link 命令,即可使用 your-cli --help 命令来查看加载的 your-cli。

如果你发布了你的 CLI,那么在其他用户使用命令 npm install -g your-cli 之后,便可以在全局下使用你的 CLI 了。

简洁的 CLI 模块 commander

https://www.npmjs.com/package/commander

虽然理论上来说利用原生模块即可实现脚本编写,但是需要处理的细节过多,会造成脚本臃肿,所以需要使用第三方模块。 commandar, inquirer。前者主要负责脚本功能定义,后者负责交互。

javascript
#!/usr/bin/env node

var program = require("commander");
var readline = require("readline");

program
  .version("0.1.0")
  .option("-p, --no-peppers", "Add peppers")
  .option("-P, --pineapple", "Add pineapple")
  .option("-n, --name [name]", "Add bbq sauce");

program.parse(process.argv);
#!/usr/bin/env node

var program = require("commander");
var readline = require("readline");

program
  .version("0.1.0")
  .option("-p, --no-peppers", "Add peppers")
  .option("-P, --pineapple", "Add pineapple")
  .option("-n, --name [name]", "Add bbq sauce");

program.parse(process.argv);

执行 --help 看输出结果,非常熟悉,非常简洁。

bash
MacdeMacBook-Pro-3:command mac$ ./love --help

  Usage: love [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    -p, --no-peppers   Add peppers
    -P, --pineapple    Add pineapple
    -n, --name [name]  Add bbq sauce
MacdeMacBook-Pro-3:command mac$ ./love --help

  Usage: love [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    -p, --no-peppers   Add peppers
    -P, --pineapple    Add pineapple
    -n, --name [name]  Add bbq sauce

强大的 CLI 界面库 inquirer

https://www.npmjs.com/package/inquirer

简单例子

javascript
var inquirer = require("inquirer");
var questions = [
  {
    type: "checkbox",
    name: "selection",
    message: "select fruits",
    choices: [
      {
        name: "apple",
      },
      {
        name: "banana",
      },
      {
        name: "melon",
      },
    ],
  },
];

inquirer.prompt(questions, function (answers) {
  console.log(answers.selection);
});
var inquirer = require("inquirer");
var questions = [
  {
    type: "checkbox",
    name: "selection",
    message: "select fruits",
    choices: [
      {
        name: "apple",
      },
      {
        name: "banana",
      },
      {
        name: "melon",
      },
    ],
  },
];

inquirer.prompt(questions, function (answers) {
  console.log(answers.selection);
});

执行结果如下:

bash
MacdeMacBook-Pro-3:command mac$ ./inquir
? select fruits:
  apple
  banana
❯◉ melon
MacdeMacBook-Pro-3:command mac$ ./inquir
? select fruits:
  apple
  banana
❯◉ melon

nodejs 获取用户的输入进行交互

注意 nodejs 是异步的。

javascript
function read(prompt, callback) {
  process.stdout.write(prompt + ":");
  process.stdin.resume();
  process.stdin.setEncoding("utf-8");
  process.stdin.on("data", function (chunk) {
    process.stdin.pause();
    callback(chunk.trim());
  });
}
function read(prompt, callback) {
  process.stdout.write(prompt + ":");
  process.stdin.resume();
  process.stdin.setEncoding("utf-8");
  process.stdin.on("data", function (chunk) {
    process.stdin.pause();
    callback(chunk.trim());
  });
}

Node.js 操作 windows 注册表,关闭命令提示符的快速编辑模式

typescript
export async function setQuickEdit(enable = false) {
  if (process.platform !== "win32") return;
  try {
    let cmd = "reg query HKEY_CURRENT_USER\\Console /v QuickEdit";
    const quickEditSetting = await child_process.execSync(cmd);
    const isEnabled = quickEditSetting && String(quickEditSetting).trim().endsWith("1");
    if (isEnabled === enable) return;
    const e = enable ? "1" : "0";
    cmd = `reg add HKEY_CURRENT_USER\\Console /v QuickEdit /t REG_DWORD /d 0000000${e} /f`;
    await child_process.execSync(cmd);
    return true;
  } catch (err) {
    console.log(err);
    return false;
  }
}
export async function setQuickEdit(enable = false) {
  if (process.platform !== "win32") return;
  try {
    let cmd = "reg query HKEY_CURRENT_USER\\Console /v QuickEdit";
    const quickEditSetting = await child_process.execSync(cmd);
    const isEnabled = quickEditSetting && String(quickEditSetting).trim().endsWith("1");
    if (isEnabled === enable) return;
    const e = enable ? "1" : "0";
    cmd = `reg add HKEY_CURRENT_USER\\Console /v QuickEdit /t REG_DWORD /d 0000000${e} /f`;
    await child_process.execSync(cmd);
    return true;
  } catch (err) {
    console.log(err);
    return false;
  }
}

最后编辑时间:

Version 4.0 (framework-1.0.0-rc.20)