Panda Noir

JavaScript の限界を究めるブログでした。最近は幅広めに書いてます。

標準出力に色をつけてカラフルにログ表示する

こんなカッコイイことができるようになれます。

f:id:panda_noir:20180203005001p:plain

制御文字とは?

標準出力する際、ある「特殊な文字列」を出力すると、

  • 色がつく(今回のテーマ)
  • カーソル位置を変える
  • 標準出力をクリアする

など特殊な操作を行うことができます。これらの文字列は、標準出力を制御するので「制御文字」と呼ばれます。

制御文字自体はただの文字列なので、どの言語でも使用できます。

今回は制御文字のうち、文字の色を変えるものを使っていきます。

とりあえず色をつけてみる

うだうだ解説してないで、さっそく色を変えてみましょう。

console.log('\u001b[31mhoge\u001b[0m');

赤色で「hoge」と表示されれば成功です。

なんだか呪文みたいな文字列ですが、解きほぐせばすぐ理解できます。

コード解説

まず、「\u001b[31m」と「\u001b[0m」が制御文字です。似た形をしているのが分かります。

これは3つの部分からできています。

  • : \u001b[
  • 310
  • m

\u001bというのはエスケープを指します((JavaScriptでは他にも「\x1b」「\033」をエスケープとして使えます。「\e」「\0x1b」を使える言語もあるそうです))。「ここからエスケープシーケンスだよ」という指示です。

310はそのままではただの数字です。後ろに続く命令(この場合はm)がこの数字を受け取って様々な処理をします。

ではmはどんな命令かというと、「グラフィカルな処理をしろ」という命令です。m数字に応じて文字色や背景色を変えます。例えば31なら赤に、0ならデフォルトの色に変更します。

他にもABなどの命令が存在します。このあたりを詳しく知りたいかたは、こちらがとてもわかりやすいので参照ください。

色一覧

色としては次の色が使えます。

  • 30:黒
  • 31:赤
  • 32:緑
  • 33:黄色
  • 34:青
  • 35:赤紫
  • 36:シアン
  • 37:白

f:id:panda_noir:20180203005015p:plain

ちなみに、10の位を4にすると、背景色が指定した色に変わります。

使いやすいように関数化する

制御文字で文字色を変更したら、最後に必ず\u001b[0mで元の色に戻さなければなりません。さらに、制御文字を見て「ここから赤色になるのか」なんてわかる人は変態だと思います

なので、人間が読めるように関数化します。

const color = col => str => `\u001b[${col}m${str}\u001b[0m`; // 補助関数
// こっちがメイン
const colors = {
    black: color('30'),
    red: color('31'),
    green: color('32'),
    yellow: color('33'),
    blue: color('34'),
    magenta: color('35'),
    cyan: color('36'),
    white: color('37')
};

console.log(`[${colors.blue('INFO')}] Hello world!`);
console.log(`[${colors.green('DEBUG')}] I'm Panda Noir!`);

これなら「INFOが青になるんだな」とすぐわかりますよね?最高です。

おまけ: 背景色もカスタマイズする

背景色バージョンも作ってみました。ただ、注意していただきたいのが、\u001b[0mが背景色ごとリセットしてしまう」ことです。そのため、文字色と一緒に使う場合はご注意ください。

例えば、下のコードは変更が打ち消されて意図した動作をしません。

const color = col => str => `\u001b[${col}m${str}\u001b[0m`;
const colors = {
    black: color('30'),
    red: color('31'),
    green: color('32'),
    yellow: color('33'),
    blue: color('34'),
    magenta: color('35'),
    cyan: color('36'),
    white: color('37')
};
const bg = {
    black: color('40'),
    red: color('41'),
    green: color('42'),
    yellow: color('43'),
    blue: color('44'),
    magenta: color('45'),
    cyan: color('46'),
    white: color('47')
};

console.log(`[${bg.white(colors.blue('INFO'))}] Hello world!`);
console.log(`${bg.white(`[このカッコの中を白にしたい${colors.blue('ここだけ青くしたい')}ここでリセットされてしまった…]`)}`);

f:id:panda_noir:20180203010531p:plain

細かい指定をしたい場合は、関数化をあきらめて普通に書くことをオススメします。