ターミナルページャー新時代

※ 本記事は私が作ったページャーである[ov](https://github.com/noborus/ov)の宣伝記事でもあります。ご留意ください。

## 最初に結論

（ターミナル）ページャーを見直そう。
表形式（複数の項目の繰り返し）のテキストを表示するには、[新しいless](http://greenwoodsoftware.com/less/)、または[pspg](https://github.com/okbob/pspg)、または[**ov**](https://github.com/noborus/ov)を使ってみよう。

CLIを作るときは、色付けと画面に収まらない出力するときにページャーを自動で呼び出すのが便利になる。
その際、ページャーを設定出来ようにするのと無効に出来るようにするのを忘れずに。

CLIでリストを出力するなら、ヘッダーを付けよう。
出来れば列は区切り文字で区切ろう。

## ターミナルページャー(terminal pager)とは？

ターミナルページャーとは黒い画面と言われているターミナル（エミューレーター）上でターミナルの大きさに合わせて、表示するソフトです。表示したい内容がターミナルよりも大きい場合は、その一部を表示してユーザーがスクロールを操作します。

エディタは時代とともに新しいエディタが台頭して変遷していきますが、ページャーのデファクトスタンダードは、かなり昔から今までずっと[less](http://greenwoodsoftware.com/less/)です。
長い間、定番ソフトが変わらないジャンルでは、そのジャンル自体が徐々に使われなくなっていくパターンもありますが、ページャーはむしろ昔よりも今の方が多く使われています。

**ただし**、ユーザーが意識せずに使っている場面が増えています。

## 最近のCLI事情

現代でも多くのCLIソフトが利用されて、また新しいソフトが開発されています。

Unixの定番となったコマンドは、昔から大きくからわずに現在も使えるものが多いですが、そのコマンドのリプレースを狙ったCLIソフトも多く開発されるようになってきました。例えばcatの代替となる[bat](https://github.com/sharkdp/bat)やpsの代替となる[procs](https://github.com/dalance/procs)などがあります。

そんなリプレースを狙ったCLIソフトは、C言語で書かれていたコマンドを[Rust](https://www.rust-lang.org/)などのモダンな言語で書き直したものですが、機能の強化として「カラフルに見やすく表示をする」という特徴があります。

初期のUnixとしては、白黒画面でも使用できるように、ただただ画面に文字を返していた訳ですが、現代ではフルカラーに対応したターミナル（エミュレーター）上で実行されることがほとんどなので、できるだけ装飾とカラー対応を入れるのは必然と言えます。

## エスケープシーケンス

しかし、ターミナル（エミュレーター）上で装飾とカラー対応するにはエスケープシーケンスを使用しなければならないという事情があります。

```console:エスケープシーケンス例
$ echo -e "\e[38;5;6mcyan\e[m"
cyan #（水色で表示）
```

ターミナルに出力する場合はエスケープシーケンスを上記のように使用しますが、ファイル等に出力したい場合やエスケープシーケンスを理解しない環境では、エスケープシーケンスの文字がそのまま見えてしまい、読みづらくなってしまいます。
そのためCLIコマンドはオプションや環境変数でエスケープシーケンスを**無効**にする方法を提供しています。

また、それだけではなくデフォルトでカラー対応しているCLIの多くは、出力先がターミナル(tty)でない場合は、エスケープシーケンスを無効にして出力します。

そうすると、今度はパイプで受け取ってページャーで表示するときにエスケープシーケンスが無効になってカラー化の恩恵を受けられなくなってしまいます。元のCLIからはターミナルかそれ以外かの判別はできますが、パイプで渡した先のソフトがエスケープシーケンスに対応しているかは判断できないためです。

```console:cliからは判らないので、エスケープシーケンスを無効にして出力する。
$ cli > file.txt
$ cli | less
```

そのため、今度は逆に強制的に有効にする環境変数(`FORCE_COLOR`)やコマンドラインオプション(`--color=always`)が存在しますが、出力先や表示先は状況に応じて変わるため、環境変数を使用するのは利便性が高くありませんし、コマンドラインオプションを毎回つけるのは面倒です。

## ページャー自動呼び出し

そういった事情により、CLIがページャーを自動で呼び出すソフトが増えてきました。出力先がターミナル(tty)の場合で、さらに出力量がターミナル画面内に収まる量ではないような場合には、環境変数`PAGER`や設定ファイルに指定されたページャーを自動で呼び出します
（ページャーを起動して、標準出力の代わりにページャーが受け取るパイプに書き込みます）。

ユーザーが意識せずにページャーがカラー対応と１画面ずつ表示の両立することが可能となります。

※ ページャー自動呼び出し自体は、パイプ`(|)`を使用しづらい、psqlやmysqlなどの対話的インターフェイスやmanコマンドなどで、昔から使われていました。

### ページャーを設定していなくても呼び出されている場合がある

ただし、冒頭に書いたとおり、ページャーのデファクトスタンダードは`less`ですが、どんな環境でも必ず入っているという訳ではありません。さらに`less`はオプションの`-R`(`--RAW-CONTROL-CHARS`)を付けないとエスケープシーケンスを解釈せずにそのまま出力してしまうので、ユーザーの環境整備と設定により、カラー化されなかったり、エスケープシーケンスの文字がそのまま見えてしまうといったことが起こります。

そのため、ユーザーが設定ファイルや環境変数`PAGER`を指定していない場合、は`less`がインストールされているかを判別して、最適な出力にしている場合があります。

例えば、`ps`では、長い出力のときは、`ps aux|less`のようにページャーを使用することがありましたが、`procs`では自動でページャーを呼び出します。

このようにユーザーが意識せずにページャー呼び出しがおこなわれているため、ページャーを使用していることに気づいていないユーザーも存在します。例えば、[bat](https://github.com/sharkdp/bat)は、`cat`の代わりであり、ページャーではない（内部でページャーを呼び出している）のですが、環境変数`PAGER`に使用したり、ページャーの代わりとして使っても普通に使えてしまうので、ページャーだと誤解しているユーザーもいます。

## ページャーを使わないという選択肢

一方で、ターミナルエミュレーターやターミナルプレクサ([tmux](https://github.com/tmux/tmux)等）の機能を使えば出力をさかのぼって見ることが可能なので、ページャーを使わないという選択をする人もいます。
この場合出力はターミナル(tty)と認識され、エスケープシーケンスにも対応しているため、CLIからは動作がシンプルになります。
ユーザーからするとページャーを終了する手間が減るため、上級ユーザーにとっては、より素早く操作が可能になります。

そういったユーザーのために、ページャー自動呼び出しをしているソフトは、ページャーを無効にする設定を用意しています。ただ、設定はソフトによって違ったりするため、メジャーなソフトではページャーを無効にする方法がQiitaでもよく投稿されています:sweat_smile:

## ターミナルページャー新時代

ページャーを使わないという選択が出来るのは、良くも悪くもページャーを使用するメリットが出力した内容をそのまま表示し、変えるのは「どこを表示するか」だけに特化していたためです（もう一つ検索も大きな機能ですが、ターミナルプレクサでも代替できます）。

### lessの新機能

しかし、ここにきて[lessに新たな機能追加](http://greenwoodsoftware.com/less/news.608.html)がされました。**`--header`オプションが追加されたのです。**
`--header`オプションは、指定した行数を固定表示にして、それ以外をスクロールするもので、表形式の出力ではヘッダー行がその後の行の意味を表しているので、非常に便利になります。

ページャーでは、人が書いたテキストやソースコードを見ることもありますが、なんらかのリストを表示することも良くあります。そのリストは１列のみよりも複数列で構成されたリストの方が多いです。つまりそれらは表形式と言えます。
例えば、一番良く使うであろう`ls`もそうですし、debやrpm、その他のパッケージリストの表示もそうです。

`ps`コマンドでは、最初の一行目にヘッダーとして項目名が出力されますが、すべてのプロセスを表示しようとすると１画面に収まらないことが多いため、スクロールしてしまうと項目名が消えてしまいます。Unix使いとしては、よく使うコマンドはヘッダーが無くても覚えてしまっているかもしれませんが、使うコマンドが増えてしまえば、それも困難になります。

新しいバージョンの`less`では、ヘッダーを固定しておけばスクロールしても項目名がすぐわかるようになります。

```console
$ ps aux | less --header 1
```
![Screenshot from 2023-01-18 13-48-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18555/43c95fff-64c8-bb76-c58e-9d50cb3f8bb2.png)

そして`procs`では、自動でページャーが起動します。その際、ページャーの設定に`--header 2`を足せば、常にいい感じに表示し続けることができます。
![Screenshot from 2023-01-18 13-51-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18555/8335519d-dbe3-faa0-4a9a-4a231d137b4f.png)

この機能はページャー以外で実現しようとすると難しくなります。

まだ`less`の新しいバージョンは、多くの環境で使えるようになっていないため、デフォルトにすることは難しいですが、新しいコマンドでリスト表示するときには、ヘッダーを出力すると良いでしょう。
数年後には`less`の新しいバージョンが普及すると`less`の`-R`オプションのように`--header`オプションが使えるのを期待してCLIソフトが対応するようになると予想されます。

※ 既にあるコマンドでヘッダーを追加表示すると互換性に問題が出ることがあるかもしれません。特にシェルスクリプト内で使われているコマンド等の変更は注意が必要です。

つまり、これまでページャーが必要ないとしてきたユーザーも今後のCLIでは、ページャーを使用したほうが便利になることが出てきました。
これからCLIソフトを作る人たちも数年後には、ページャーのヘッダー機能が普通に使える環境になっていることを想定するとよいでしょう。

## ページャーovの紹介

[ov](https://github.com/noborus/ov)は私が作ったページャーで、[go製](https://go.dev/)です。実は`less`よりも前にヘッダー機能を実装してました。
多くの場合に`less`の代わりに使えるだけの機能を備えています。

もともとは`psql`の表示をもっと見やすくしたいと考えて開発を開始しました。
ovには他にも以下のような表形式に適した機能があります。

* 行を交互に背景色（スタイル）を変えられる
* （区切り文字を指定して）列単位でハイライト・色表示、スクロールが可能。
* ヘッダーと折返しの両立。

`less`では今のところ、ヘッダーオプションを使用すると折り返さない表示になります。`ov`では折返し表示も可能です。
折返し表示をするとヘッダー行から縦を辿って見づらくなるため、列のハイライト表示ができるようにしています。
![Screenshot from 2023-01-18 10-40-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18555/4e27cc3e-70b7-9aea-44a0-fbe3d5afb77b.png)
折り返さない表示をした場合は、列単位でカーソルを移動して合わせて、右スクロールできます。

実はpsql用に使えるページャーとして[pspg](https://github.com/okbob/pspg)が既にあったのですが、いくつか違う動作のものを実装したかったのと、汎用で多くの場面で使えるようにしたかったので、新規で作りました。

### 表形式以外にも便利な機能

`ov`では表形式以外にも豊富な機能があります。
そのひとつが、行の区切り文字列（正規表現）を指定して、行のブロック単位で移動できる”セクション機能”です。

例えば`git log`では、`^commit`を区切り文字列として指定すると、該当するキーがハイライト表示され、デフォルトキー`space`と`^`で、そのブロック単位で下と上に移動します。
![ov-gitlog.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18555/f603afaa-a5ff-ba62-cd02-3d5da10158d7.gif)
`less`の機能はまた豊富なため、全部の機能は実装出来ていませんが、通常使用するページャーとしてかなりの機能を実装して、さらにov独自の便利機能を実装しているので、ぜひ試してみてください。

## まとめ

`less`にヘッダー機能が実装されたことで、ページャーを使用するメリットが増えました。
ページャーを無効にしていた人も再考の価値ありです。

表形式のテキストファイル（やソフトのアウトプット）は、これまでよりも使いやすくなります。その際にはヘッダーを付けましょう。

複数の列を出力するときには、できれば区切り文字を付けてください。`ov`を使う人に便利になります。