読者です 読者をやめる 読者になる 読者になる

詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

任意の入力を human-readable にする humr ってツールを書いた

Web サーバのアクセスログを tail してながめている時にパーセントエンコーディングされた文字列をデコードしたり、コマンドラインで数字を sort -n したあとにでかい数字を丸めて表示したり("1234567" を "1.2M" に、とか)したくなることが多かったので、その辺を汎用的におこなってくれる humr というツールを書きました。

npm でインストールできます:

npm install -g humr

簡単に動きを確認するには、以下のコマンドを試してみてください:

% echo '/search?q=%E6%97%A5%E6%9C%AC%E8%AA%9E 1234567' | humr

f:id:motemen:20151225104506p:plain

入力のうち読みづらいところが色付きで変換されて出力されたことが分かります。冒頭に書いたようにログなどの入力をパイプしてご利用ください。

仕組み

humr は入力を

  1. Parser によって各行ごとにフィールドに分解し、さらに
  2. 各フィールドを Formatter によって人間向けの表現にする、

ということを行っています。Parser は1つしか指定できませんが Formatter は複数存在しえて、可能なものを順番に試していってフィールドを解釈できた場合、その結果に色付けされて出力されます。解釈できなかった場合は入力そのまま。

それぞれ、

  • Parser
    • regexp: 行を正規表現(デフォルトでは s+)で区切られたフィールドの列とみなす
    • ltsv: 入力を LTSV として解析し、それぞれの値をフィールドとする
    • apache 入力を Apache Common Log フォーマットのログとみなす
  • Formatter
    • si: SI 接頭辞(k、M など)で数値を略記する
    • url: 文字列中のパーセントエンコーディングをデコードする
    • date: 日付っぽい文字列を解釈して現在のロケールに合わせて表現する
    • emoji: :+1: みたいな文字列を絵文字に変換する

ってのを同梱して提供しています。

オプション

オプションなしだと Parser には regexp、Formatter には上記すべてが利用されるのですが、もちろんオプションでこれを変更できます。

humr -p <parser>[=<arg>] -f [<label>:]<formatter>

-p は Parser を指定します。例えば -p ltsv とすると入力は LTSV として解釈され、

size:1234567[tab]path:/search?q=%E6%97%A5%E6%9C%AC%E8%AA%9E

な入力のうち、"1234567" と "/search?..." がフォーマット対象となります。

-f で Formatter を指定できます(複数指定可)。基本的にすべてのフィールドにすべての Formatter が試みられますが、<label> を指定することで Formatter を特定のフィールドのみに適用できます。上の例だと

humr -p ltsv -f size:si -f path:url

とすることができます。またフィールドの指定は LTSV のように名前か、単純に1オリジンのインデックスを使えます。

humr -p ltsv -f 1:si -f 2:url

カスタマイズ

humr は起動時に ~/.config/humr/*.js にあるスクリプトを評価するようになっているので、自前の Parser/Formatter を定義できます。

+function () {
  'use strict';

  let formatters = require('humr/formatter').registry;

  class JapaneseNumbersFormatter {
    format (text, hl) {
      const NUMBERS = '〇一二三四五六七八九';
      return text.replace(/[0-9]/g, (n) => hl(NUMBERS[n]));
    }
  }

  formatters.register('japanese_numbers', JapaneseNumbersFormatter);
} ();

以上のような内容のファイルを ~/.config/humr/japanese_numbers.js (ファイル名は .js で終わっていればなんでもよいです)として配置しておけば、Formatter として "japanese_numbers" を利用できます。

humr -p ltsv -f size:japanese_numbers

Parser, Formatter としてどんなクラスが期待されているかはそれぞれの定義を見るのが手っ取り早いです: ParserFormatter

Parser としては行を受け取り、フィールドを { label?: string; text: string } に、それ以外の文字列を string に分解する parse メソッドを持ったクラスを登録します。

Formatter としてはフィールドの文字列とハイライト関数を受け取り、フォーマット可能であればフォーマットした文字列をハイライト関数に渡したうえで文字列を返す format メソッドを持ったクラスを登録します。

以上

昔 Ruby で書いてたやつなんだけど、拡張のしやすさ考えると JavaScript で書きたいなってことで Node で書きなおした。役立ててくださいね。日付の解釈に moment を使ってるのが良い選択だったか気になってます。