ターミナルで複数のファイルを並べて表示する方法（応用編）

[ansicolumn]: https://github.com/kaz-utashiro/App-ansicolumn
[greple]: https://github.com/kaz-utashiro/greple
[optex]: https://github.com/kaz-utashiro/optex

先の記事で、UNIX 端末上で複数のファイルを並べて表示する方法について考えた。そして、ansicolumn コマンドを改造する経緯について述べた。

https://qiita.com/kaz-utashiro/private/345cd9abcd8e1f0d81a2

結果を示す前に、まず ansicolumn コマンドについて説明する。

# ansicolumn

https://github.com/kaz-utashiro/App-ansicolumn

元はと言えば、先の記事でも書いた column コマンドを ANSI 端末制御文字列に対応させたものだ。20世紀中、コマンドは端末に表示する時にのみ制御文字列を使って反転、アンダーライン、ボールド、イタリックなどの効果や、カラー端末であれば背景色と前景色を変化させ、コマンド間でデータを受け渡す時には制御情報を付加しないというのが当たり前だった。しかし、最近は結果を印刷したりはせずに、端末上に表示するだけになり、制御情報付きのデータを受け渡して加工して処理することも多くなってきた。以前より、文書処理系のツールを作ることが多く、最近では画面上でのビジュアルな効果を使った方が見やすいので、結果として ANSI 制御文字入りのテキストを処理ツールが整ってきた。ansicolumn もその一環だ。

## カラム表示

column コマンドの典型的な使い方は、1行に1つずつ並んだデータを、ls の結果のように縦に整列して表示することだ。横に並べるよりオリジナルの形式に近いし、横書きのデータの場合、縦方向にスキャンできた方が便利だからだろう。1から30までの数字を column コマンドに通すと、下の最初の例のように並べてくれる。２番目は、同じデータを ansicolumn に与えたもので、column と同じ結果を出力している。この例では jot を使っているが、seq の方が一般的か。

![ac-grep.png](https://raw.githubusercontent.com/kaz-utashiro/App-ansicolumn/master/images/ac-grep.png)

３番目は、grep の --color オプションを使って各行に着色した結果を column コマンドに渡している。すると、最初とは違う結果になる。これは、表示幅を消費しない ANSI 制御文字も文字列の一部として長さを計算しているからだ。一方、最後の例で、同じ色付きのデータを ansicolumn に与えると、色がない時と同じように整形している。

これが、column コマンドの典型的な使い方と言える。

## ページ制御

出力が画面に収まる間はいいが、それより長いと困る。そこで ansicolumn にはページ制御の機能を付けた。次の画面は1から1000までの数字を上と同様に表示した結果を less で見ているところだ。入試の合格発表で合格者の受験番号が何ページにも渡って掲示されている場面を想像してもらえばいいだろうか。数字は縦に並べたいが、100番台の番号がどのページにあるのかわからないようでは困る。

![ac-page-option.png](https://raw.githubusercontent.com/kaz-utashiro/App-ansicolumn/master/images/ac-page-option.png)

この端末の画面は24行なので、各ページの高さは自動的に23行に設定される。2ページ目で、24行から46行までが表示されている。様々な色が使われているのは greple コマンドで多色表示しているからだ。

ansicolumn では、各ページ内のカラムを pane と呼び、ボーダーで囲んで表示することができる。この例では vbar (vertical bar) というボーダーテーマを使っているので、各 pane の間に仕切りの線が引かれている。

## テキストファイルを表示する

上のように、column コマンドは元々比較的短い項目を整列して表示することを想定し、プログラムやドキュメントなどのテキストファイルに対して利用されることは考えられていなかったように思われる。空白行を無視することから考えても間違いないだろう。しかし、普通のテキストファイルを同じように折り返して表示する要求は当然あるし、column コマンドの仕様はその目的に沿ったものだと考えるので、ansicolumn はテキストファイルを普通に処理できるように作られている。

次の例は、プログラムのソースを src-highlight でハイライトした結果を ansicolumn で3カラム表示している。ボーダーテーマは dumbbell (ダンベル)。

![ac-color-code](https://raw.githubusercontent.com/kaz-utashiro/App-ansicolumn/master/images/ac-color-code.png)

このように、多彩なカラーを使ったテキストでも、正しく表示幅を計算して、長い行は折り返して表示することができる。

## 日本語テキストを表示する

column コマンドが想定する短いデータ列とは異なるが、テキストファイルを対象にしても、column コマンドが本来持っている役割は、ほとんど変わっていないことがわかるだろう。もっともソースコードは、半ばデータファイルのようなもので、あまりじっくり順番に読むようなものではない。では、今度は読むことを目的とした日本語のテキストファイルを表示してみよう。

次の例は、青空文庫にあった江戸川乱歩の黄金豹の冒頭を ansicolumn を使って4カラムで表示したものである。文章ファイルは、あまり横長に表示すると、視線の移動が大きくなってしまうので、適度な長さで折り返した方が読みやすい。

![ac-japanese-document](https://raw.githubusercontent.com/kaz-utashiro/App-ansicolumn/master/images/ac-japanese-document.png)

よく見るとわかるが、日本語の禁則処理も実装してある。右側に半角4文字分のマージンがとってあり、4文字までの行頭および行末禁則を施した結果だ。2カラム目の「スーッ」という部分では2文字が前の行に追い込まれている。それ以外にも、カラムの最後に1行だけ残った場合には次のカラムに送るとか、カラムの先頭の空白を削除するなどの、組版的な処理も行う機能がある。この例ではそれを適用していないのだが、1カラム目の最後の1行や、3カラム目の先頭に空白が処理対象になる。

当初は禁則処理は実装していなかったし、端末で文章を読むくらいなら、別にそこまでやらなくてもいいのではないかと思った。しかし実装してみると、やはり圧倒的に読みやすい。文章の内容に集中して読み込みたい時に、行頭に閉じ括弧があったりすると興醒めなのだ。

日本語の文章中に ANSI 制御文字が出てくることももちろんある。次の例は、文章中の漢字とカタカナの連続する文字列に色をつけたものだ。greple の --uc (unique color) オプションで、同じ文字列は同じ色で表示している。

![ac-japanese-color-document](https://raw.githubusercontent.com/kaz-utashiro/App-ansicolumn/master/images/ac-japanese-color-document.png)

このように、文章校正などでツールを活用する際にもなかなか便利に使える。

## ボーダー

ここでは詳しく書かないが、上で紹介した以外にも様々なボーダーに対応している。また、自分だけのボーダーをカスタマイズすることもできる。ちょっとした環境を整えると、fortune コマンドの結果を次のようにデコレーションして表示することも可能だ。この例は、ansicolumn 以外に、[optex] と [greple] という、いずれも自作のコマンドを利用している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/82fe98f0-73be-2bce-e322-ae52b9c0b310.png)

# ansicolumn に複数のファイルを与える

column コマンドは、元々標準入力からのデータストリームを処理することを前提にしていて、複数のファイルが与えられることはまったく想定していないように思える。ansicolumn コマンドは、この記事で紹介したようにテキストファイルを読みやすく表示できるように拡張してきた。当初の実装では、複数のファイルを与えた場合、column コマンドと同様にすべての内容を連結して処理していた。それであれば、事前にすべてのファイルを cat しても同じなので面白くない。そこで、複数ファイルが指定した場合、どのように振る舞うべきかを考えて実装してみた。ということで、前の記事の内容にやっと戻る。それについては[次の記事](https://qiita.com/kaz-utashiro/items/32e1c2d4c42a80c42422)で。

https://qiita.com/kaz-utashiro/items/32e1c2d4c42a80c42422