프로그래밍 언어/NODE JS

commander, inquirer 사용하기(3)

· 코딩마이데이

마지막으로 chalk 패키지를 사용합니다. 이 패키지가 특별한 기능을 가진 것은 아니며, 검은색과 흰색밖에 없는 터미널에 색과 스타일을 추가합니다.

#!/usr/bin/env node
const { program } = require("commander");
const fs = require("fs");
const path = require("path");
const inquirer = require("inquirer");
const chalk = require("chalk");

const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Template</title>
</head>
<body>
  <h1>Hello</h1>
  <p>CLI</p>
</body>
</html>
`;

const routerTemplate = `
const express = require('express');
const router = express.Router();

router.get('/', (req, res, next) => {
  try {
    res.send('ok');
  } catch (error) {
    console.error(error);
    next(error);
  }
});

module.exports = router;
`;

// 파일 존재 확인
const exist = (dir) => {
  try {
    fs.accessSync(
      dir,
      fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK,
    );
    return true;
  } catch (e) {
    return false;
  }
};

// 폴더 재귀 생성
const mkdirp = (dir) => {
  const dirname = path
    .relative(".", path.normalize(dir))
    .split(path.sep)
    .filter((p) => !!p);

  dirname.forEach((d, idx) => {
    const pathBuilder = dirname.slice(0, idx + 1).join(path.sep);
    if (!exist(pathBuilder)) {
      fs.mkdirSync(pathBuilder);
    }
  });
};

// 템플릿 생성
const makeTemplate = (type, name, directory) => {
  mkdirp(directory);

  if (type === "html") {
    const pathToFile = path.join(directory, `${name}.html`);
    if (exist(pathToFile)) {
      console.error(chalk.bold.red("이미 해당 파일이 존재합니다"));
    } else {
      fs.writeFileSync(pathToFile, htmlTemplate);
      console.log(chalk.green(`${pathToFile} 생성 완료`));
    }
  } else if (type === "express-router") {
    const pathToFile = path.join(directory, `${name}.js`);
    if (exist(pathToFile)) {
      console.error(chalk.bold.red("이미 해당 파일이 존재합니다"));
    } else {
      fs.writeFileSync(pathToFile, routerTemplate);
      console.log(chalk.green(`${pathToFile} 생성 완료`));
    }
  } else {
    console.error(
      chalk.bold.red("html 또는 express-router 둘 중 하나를 입력하세요."),
    );
  }
};

program.version("0.0.1", "-v, --version").name("cli");

// template 명령어
program
  .command("template <type>")
  .usage("<type> --filename [filename] --directory [path]")
  .description("템플릿을 생성합니다.")
  .alias("tmpl")
  .option("-f, --filename [filename]", "파일명을 입력하세요.", "index")
  .option("-d, --directory [path]", "생성 경로를 입력하세요", ".")
  .action((cmd, args) => {
    if (args) {
      console.log(chalk.bold.red("해당 명령어를 찾을 수 없습니다."));
      program.help();
    } else {
      inquirer
        .prompt([
          {
            type: "list",
            name: "type",
            message: "템플릿 종류를 선택하세요.",
            choices: ["html", "express-router"],
          },
          {
            type: "input",
            name: "name",
            message: "파일의 이름을 입력하세요.",
            default: "index",
          },
          {
            type: "input",
            name: "directory",
            message: "파일이 위치할 폴더의 경로를 입력하세요.",
            default: ".",
          },
          {
            type: "confirm",
            name: "confirm",
            message: "생성하시겠습니까?",
          },
        ])
        .then((answers) => {
          if (answers.confirm) {
            makeTemplate(answers.type, answers.name, answers.directory);
            console.log(chalk.rgb(128, 128, 128)("터미널을 종료합니다."));
          }
        });
    }
  })
  .parse(process.argv);

 

console.log와 console.error에 chalk에 적용했습니다.

사용법은 간단합니다. chalk 객체의 메서드들로 문자열을 감싸면 됩니다. green, yellow, red, blue와 같은 매우 익숙한 섹이 메서드로 추가되어 있습니다. 직접 색을 지정하고 싶다면 rgb 메서드나 hex 메서드를 사용하면 됩니다. chalk.rgb(12, 34, 56)(텍스트) 또는 chalk.hex('#123456')(텍스트)처럼 사용할 수 있습니다.

글자색 외에도 배경색으로 지정할 수 있습니다. bgGreen, bgYellow, bgRgb, bgHex 등을 사용하면 됩니다.

텍스트의 스타일도 정할 수 있습니다. 텍스트를 굵게(bold) 할 수도 있고, 밑줄(underline)을 그을 수도 없습니다.

글자색, 배경색, 스타일을 동시에 지정할 수도 있습니다. chalk.red.bgBlue.bold(텍스트)처럼 하면 됩니다.

다소 지루할 수도 있는 CLI 프로그램이므로 알롤달록한 색을 넣어 사용자들의 집중력을 끌어올려봅니다. 단, 터미널마다 지원하는 색이나 스타일이 다르므로 모든 환경에서 길게 동작하지는 않습니다.

이상이 적용된 CLI 프로그램

 

지금까지 commander, inquirer, chalk를 사용해 CLI 프로그램을 제작해봤습니다.