CLI作成を簡単にしてくれるkleurとpromptsを試してみた

promptsとkleurの素振りをしたので例とともに使い方を紹介します。
2022.11.11

どうも。CX事業本部Delivery部のえーたん(@eetann092)です。

lukeed/kleurterkelg/promptsを使ってみたので紹介します。

kleur使ってみた

先にkleurを紹介します。

kleurはターミナルでの出力に簡単に色を付けることができるNode.jsライブラリです。文字や背景の色を変えるだけではなく、下線や打ち消し線といった装飾もできます。 以下が使ってみた例です。

const kleur = require("kleur")

console.log(kleur.red("red"))
console.log(kleur.green("green"))
console.log(kleur.yellow("yellow"))
console.log(kleur.blue("blue"))
console.log(kleur.magenta("magenta"))
console.log(kleur.bgWhite().black("bgWhite black"))
console.log(kleur.bgBlack().white("bgBlack white"))
console.log(kleur.bgBlack().gray("bgBlack gray"))
console.log(kleur.bgBlack().grey("bgBlack grey"))

console.log(kleur.bgBlack("bgBlack"))
console.log(kleur.bgRed("bgRed"))
console.log(kleur.bgGreen("bgGreen")) console.log(kleur.bgYellow("bgYellow"))
console.log(kleur.bgBlue("bgBlue"))
console.log(kleur.bgMagenta("bgMagenta"))
console.log(kleur.bgWhite("bgWhite"))

console.log(kleur.bold("bold"))
console.log(kleur.bgBlue(`bgBlue and ${kleur.dim("dim")}`))
console.log(kleur.underline("underline"))
console.log(kleur.bgBlue(`bgBlue and ${kleur.inverse("inverse")}`))
console.log(kleur.strikethrough("strikethrough"))

console.log(kleur.cyan("cyan"))
console.log(kleur.bgCyan("bgCyan"))
console.log(kleur.italic("italic"))
console.log(kleur.bgBlue(`bgBlue and ${kleur.hidden("hidden")}`))

筆者の環境では、cyanやイタリック、hiddenがうまく表示されていないようです。おそらくターミナルの色やフォントの設定によるものだと思います。正しく表示できるようになったら追記します。

kleur.bgBlack().gray("bgBlack gray")のようにチェインで書けるほか、以下のようにネストして書くこともできます。

const {black, red, bgGreen, bgYellow, underline} = require("kleur")

console.log(bgYellow(underline(black("bgYellow(underline(black))"))))
console.log(red(bgGreen("red(bgGreen)")))

kleur.dimは文字色を薄暗くしてくれる装飾です。

console.log(red(`red ${dim("dim")}`))
console.log(green(`green ${dim("dim")}`))
console.log(yellow(`yellow ${dim("dim")}`))
console.log(blue(`blue ${dim("dim")}`))
console.log(magenta(`magenta ${dim("dim")}`))
console.log(bgWhite().black(`bgWhite black ${dim("dim")}`))
console.log(bgBlack().white(`bgBlack white ${dim("dim")}`))
console.log(bgBlack().gray(`bgBlack gray ${dim("dim")}`))
console.log(bgBlack().grey(`bgBlack grey ${dim("dim")}`))

console.log(bgBlack(`bgBlack ${dim("dim")}`))
console.log(bgRed(`bgRed ${dim("dim")}`))
console.log(bgGreen(`bgGreen ${dim("dim")}`))
console.log(bgYellow(`bgYellow ${dim("dim")}`))
console.log(bgBlue(`bgBlue ${dim("dim")}`))
console.log(bgMagenta(`bgMagenta ${dim("dim")}`))
console.log(bgWhite(`bgWhite ${dim("dim")}`))

kleur.inverseを使った部分は、文字色と背景色が入れ替わって表示されます。

console.log(red(`red ${inverse("inverse")} undo`))
console.log(green(`green ${inverse("inverse")} undo`))
console.log(yellow(`yellow ${inverse("inverse")} undo`))
console.log(blue(`blue ${inverse("inverse")} undo`))
console.log(magenta(`magenta ${inverse("inverse")} undo`))
console.log(bgWhite().black(`bgWhite black ${inverse("inverse")} undo`))
console.log(bgBlack().white(`bgBlack white ${inverse("inverse")} undo`))
console.log(bgBlack().gray(`bgBlack gray ${inverse("inverse")} undo`))
console.log(bgBlack().grey(`bgBlack grey ${inverse("inverse")} undo`))

console.log(bgBlack(`bgBlack ${inverse("inverse")} undo`))
console.log(bgRed(`bgRed ${inverse("inverse")} undo`))
console.log(bgGreen(`bgGreen ${inverse("inverse")} undo`))
console.log(bgYellow(`bgYellow ${inverse("inverse")} undo`))
console.log(bgBlue(`bgBlue ${inverse("inverse")} undo`))
console.log(bgMagenta(`bgMagenta ${inverse("inverse")} undo`))
console.log(bgWhite(`bgWhite ${inverse("inverse")} undo`))

prompts使ってみた

promptsは、CLIでよくあるプロンプトを簡単に作ることができるNode.jsライブラリです。引数にプロンプトの種類と表示したい内容を指定します。以下は文字入力のプロンプトの例です。

const prompts = require('prompts');

(async () => {
  const response = await prompts({
    type: "text",
    message: "名前を入力してください",
    name: "username",
    initial: "Kerry",
    validate: name => name.match(/^a{3,}/) ? "適当に入力しないで😡" : true
  });

  console.log(response);
})();

以下が実行した例です。色が見づらいという人向けのカスタマイズは後で説明します。

    type: "text",
    message: "名前を入力してください",
    name: "username",
    initial: "Kerry",
    validate: name => name.match(/^a{3,}/) ? "適当に入力しないで😡" : true

nameで指定した文字列がresponseのキーになります。初期値はinitialに指定できます。

バリデーションはvalidateで可能です。validateでは、true以外を返すと「無効あると警告するメッセージ」として表示できます。

promptsでkleurが使える

onRenderでは、先程紹介したkleurを使うことで、プロンプトの文字や背景色、装飾を変更できます。

const prompts = require('prompts');

(async () => {
  const response = await prompts({
    type: "text",
    message: "onRenderのthis.msgがあったら上書きされます",
    name: "username",
    initial: "Kerry",
    onRender(kleur) {
      this.msg = `${kleur.bgBlue().yellow().underline("kleurが使える")}`;
    }
  });

  console.log(response);
})();

promptsの日時入力を使ってみた

promptsには日時入力があります。 以下は2022年12月7日(水) 14時10分のような形式で日時入力する例です。

const prompts = require('prompts');

(async () => {
  const response = await prompts({
    type: "date",
    name: "day",
    message: "空いてる日時を教えて下さい",
    initial: new Date(),
    validate: date => date < Date.now() ? "今日以降を指定してください": true,
    mask: "YYYY年M月D日(dddd) H時m分",
    locales: {
      weekdays: ['日', '月', '火', '水', '木', '金', '土'],
    },
  });

  console.log(response);
})();

カーソルの上下で数値を上下し、左右に動かすことで「年、月、日……」と移動できます。

デフォルトでは日本語には対応していなかったため、masklocalesに自分でフォーマット指定しました。

    mask: "YYYY年M月D日(dddd) H時m分",
    locales: {
      weekdays: ['日', '月', '火', '水', '木', '金', '土'],
    },

実装を見てみると、maskのフォーマットのddddlocalesweekdaysに対応しているようです。そのため、maskの曜日部分にはddddを、localesweekdaysに日本語での曜日を指定しました。

CLIで簡単に日付を入力させることができるのは良いですね。

エラーメッセージが見づらい人向け

デフォルトのエラーメッセージは背景色が赤です。見づらい方もいると思うので、エラーメッセージの色を変えてみました。

まず、エラーメッセージはerrorMsgで取得できることと、 エラーメッセージの色を定義している箇所を見つけました。 エラーメッセージの表示には、kleurのredが使われているようですね。

したがってonRender内でerrorMsgの表示をkleurを使って変えることにしました。

const prompts = require('prompts');

(async () => {
  const response = await prompts({
    type: "text",
    message: "名前を入力してください",
    name: "username",
    initial: "Kerry",
    validate: name => name.match(/^a{3,}/) ? "適当に入力しないで😡" : true,
    onRender(kleur) {
      this.errorMsg = `${kleur.reset().bgYellow().black(this.errorMsg)}`;
    }
  });

  console.log(response);
})();

以下がBefore/Afterです。

最後に

promptsにはconfirmや絞り込みなど、他にもさまざまなの種類のプロンプトが使えます。ただし、2022年11月11日現在、promptsは1年ほどメンテナンスされていない状態でしたのでご注意ください。

今回使用したサンプルのコードは以下のリポジトリにあります。