Необходимая основа для разработки Node-CLI

Node.js внешний интерфейс Командная строка NPM
Необходимая основа для разработки Node-CLI

В этой статье вы ознакомитесь с базовыми знаниями, необходимыми для создания инструмента Node-CLI.

Во-первых, анализ параметров командной строки

  В 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 в соответствии с семантикой, что более разумно.

Во-вторых, интерфейс командной строки.

  Модуль readline в NodeJS предоставляет методы вопросов и подсказок для создания интерфейса командной строки. Ниже приведен простой интерфейс вопросов и ответов:

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

   Конечно, элементы интерактивного интерфейса не единственные.При использовании различных инструментов 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)
  lineCount -= choices.length
  reader()
})

rl.on('line', () => {
  console.log(`you choose ${choices[selected]}`)
  process.exit(0)
}).on('close', () => {
  rl.close()
})

3. Индивидуальный стиль

   Чтобы эффективно отличать информацию в интерфейсе командной строки, мы можем добавить соответствующие стили к выходной информации здесь.

   Вот синтаксис добавления стилей к строкам:

  \x1b[背景颜色编号;字体颜色编号m

   Каждый стиль должен начинаться с \x1b[:

  // \x1b[0m 清除样式
  process.stdout.write('\x1b[44;37m OK \x1b[0m just do it\n')

В-четвертых, пользовательские команды Node.

  Следующим шагом является настройка команды Node.Сначала необходимо создать файл выполнения команды:

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

   Повторно используйте конфигурацию bin в package.json:

  {
    "bin": {
      "hello": "./hello.js"
    },
  }

   Выполните команду ссылки npm:

  npm link
  
  # 输入自定义命令
  hello

  # 输出 hello

V. Резюме

  Вышеизложенное представляет некоторые базовые знания, необходимые для разработки Node-CLI, но для тех, кто использовал такие инструменты, как webpack-cli и vue-cli, вы можете обнаружить, что эти отличные инструменты CLI также имеют:

  • подкоманды в стиле git;
  • автоматизированная справочная информация;
  • ....

   Тогда вам очень помогут следующие зрелые фреймворки: