つうさにメモブログ

つうさにがメモをブログとして書いていくところ

端末エミュレータ上のEmacsで24-bit colorを表示する(Emacs 27以降でも)

Emacs 27では端末上での24-bit color表示が簡単になるらしいですよ。

端末上のEmacsで24-bit colorの話

端末上のEmacsで24-bit colorとは

端末上で動かすEmacsで使える色は普通、グラフィカルなEmacsで使える色よりも大きく限られています。「同じカラーテーマなのに端末上かグラフィカル環境かで色が違う!」なんて経験をした人もいると思います1。これはEmacsが悪いわけではなく端末という環境自体の制限によるものだったのですが、最近では多くの端末エミュレータで「グラフィカル環境と同等の24-bit colorを表示する能力」が追加されており、端末上のアプリケーションでもグラフィカル環境と同じ色が出せることは当たり前になりつつあります。

実はEmacsもバージョン26.1からそのような端末エミュレータの能力に対応していて、端末上で24-bit colorを表示することができるようになっています。ただ、Emacs 26で24-bit colorを表示するには特別な作業が必要でした。

Emacs 26で24-bit color

作業というのは以下の記事に書かれている通りです。 qiita.com

efaq.texi (tag:26.3)に詳しく書かれている通り、特別なケイパビリティを持つエントリをterminfoに登録する必要がありました。

Emacsはtermcap/terminfo2データベースを使って、端末がどのような能力を持ってるか(どのような特性であるか)を起動時に判断します。当時は「24-bit colorを表示する能力」を端末が持つかどうかを確認する標準的な方法がなかった(そのようなterminfoエントリがなかった)ため、自分で登録する必要があったのです3

Emacs 27で24-bit color

いきなり結論。

TERM=xterm-direct emacs -nw

TERM環境変数xterm-directを指定してEmacsを起動しましょう。最新のterminfoではxterm-directエントリが存在しEmacsもそれに対応しているため、いちいちエントリを追加しなくて済むようになりました。efaq.texi (tag:27.0.91)も加筆されていて詳しく書かれています4

もしこれでEmacsが起動しなくなった場合、システムのterminfoが古い(xterm-directエントリが存在しない)ことが考えられます。最新のterminfoをインストールするか、諦めてEmacs 26からある方法を使いましょう。

.bashrcにexport TERM=xterm-direct書いちゃダメ?

いちいち先頭にTERM=xterm-directを入力するのが面倒だからといって、.bashrcなどのシェルの初期化ファイルにexport TERM=xterm-directと書くのはオススメできません。

例えばターミナルマルチプレクサであるtmuxは、tmux用のTERM環境変数を設定しシェルを起動します。.bashrcなどのシェルの初期化ファイルにTERM環境変数の設定を書いてしまうと、シェル起動後にそれで上書きされてしまいます。tmuxの中のシェルでTERMがtmux用のものに適切に設定されていないと表示に問題が起こる可能性があります5

端末エミュレータの設定でTERMxterm-directをセットしちゃダメ?

端末エミュレータの設定でTERM環境変数のデフォルトをxterm-directに変更するのもオススメできません。

TERM環境変数xterm-directがセットされることを想定しているアプリケーション、環境は多くありません。例えば、Emacs 26はTERM=xterm-directの状態だとうまく動きません6。また、Ubuntuのデフォルトの.bashrcではTERM=xterm-directとするとプロンプトに色がつかなくなっています(TERMxterm-directをセットされることが想定されていない)。xterm-directは登場が最近すぎて、対応するアプリケーションが少なく、xterm-256colorと互換性もないためアプリケーションがうまく動かなくなってしまう可能性が高いです7

というわけで、現状だとxterm-directに対応しているアプリケーションにだけTERM=xterm-directをつけて実行するのがオススメなのです。

tmux内のシェルでTERM=xterm-direct emacs -nwしたら表示がバグった?!

私がハマりました。最新版のtmux使いましょう。

Emacs 28で24-bit color

Emacs 27はまだリリースされてませんが、次々期バージョンであるEmacs 28はすでにmasterブランチで開発されています。

実はEmacs 28では下のようなパッチが投げられて、そのパッチは取り込まれました。

debbugs.gnu.org

github.com

github.com

terminfoが使われないFreeBSDのために、24-bit colorを表示する能力(つまりエスケープシーケンス)がハードコードされました。

ということで、COLORTERM環境変数truecolorがセット8されていれば、terminfo関係なしに24-bit colorを表示することができるようになりました。

で、これはFreeBSDだけでなく、同梱されているterminfo (ncurses)が化石古いmacOSも恩恵を受けます。terminfoが古いmacOSでも、独自のterminfoエントリを追加せずとも(TERM環境変数を気にせずとも)、iTerm2で開けば何の設定もせずに24-bit colorを表示することができるようになっちゃったのです。

まとめ

Emacsの端末上での24-bit colorのサポートはどんどん改良されています。 端末エミュレータ上でEmacsを利用するのが好きな方はどんどん24-bit colorしましょう!

おしまい。


  1. 端末上では色に限りがあるため、近い色に丸められてしまっているわけです。

  2. termcap/terminfoは(ハードウェア)端末のエスケープシーケンスにベンダー間で互換性がなかった時代に生まれたもので、そういった端末用に移植性の高いTUIアプリケーションを作成するのに便利でした。ただ、最近の端末エミュレータはほぼ全てANSIエンスケープシーケンス互換であることから、termcap/terminfoが使われずANSIエスケープシーケンスがハードコードされることも多いです。termcap/terminfoを利用したアプリケーションをうまく動作させるには普通TERM環境変数に適切な名前をセットする必要があります。

  3. ちなみに、Emacsが「自分は24-bit color表示可能な端末で動作している」と判断しているとき、(display-color-cells)は16777216を返します。

  4. efaqにも書かれている通り、xterm-directを使う場合#000001〜#000007が互換性の問題で青色として使えないというデメリットがあります((insert (propertize "aaa" 'font-lock-face '(:background "#000002")))などで確認可能)。

  5. 参考: FAQ · tmux/tmux Wiki · GitHub

  6. Unsupported number of xterm colors (32767)と表示されます(真っ黒で何もできない)。

  7. 他にも、自分のシステムではTERM=xterm-directで大丈夫でも、sshでサーバにアクセスする際はTERMが引き継がれるため、サーバのterminfoやアプリケーションが古い場合に問題になる。

  8. 確実なルールではありませんが、「端末が24-bit colorのエスケープシーケンスに対応してるならCOLORTERM環境変数truecolorをセットする」としている端末が多くあります。 参考: True Colour (16 million colours) support in various terminal applications and terminals · GitHub