SVGでEmacs上にGUIを表示するデモ

書いた人: taku0

はじめに

Emacsのアドベントカレンダー2022、8日目の記事です。

Emacsのスクリーンショット。Excelのような表が表示されていて、その中のテキストの一部が選択されている
スクリーンショット

Emacs上でNotionみたいなリッチなテキストが表示/編集できたらよいなと思い、なんとかできないか考えてみました。とりあえずproof of conceptレベルにはなったので公開します。

svg-table.elをevalして、svg-table-demoを実行してみてください。C-n C-p C-f C-bによるカーソルの移動や、テキストの挿入・削除ができます。

どうやって?

Emacsには画像を表示する機能があります。「オーバーレイ」という機能を使うとテキストの一部を画像で置き替えて表示できます。そして画像としてSVGが表示できます(rsvgライブラリが使われています)。つまり、Emacsで画面が更新されるごとにSVGでGUIっぽい画像を作成して表示すれば、リッチなテキストが表示できるはずです。

具体的にはpre-redisplay-functionsというフックを使います。これは画面が更新される前に呼ばれますので、その中でSVGを作成してバッファ全体にオーバーレイを設定します。

大変だったところ

SVGにはテキストに合わせて図形のサイズを変える機能は無いので、自分でテキストのサイズを測って図形のサイズを設定する必要があります。いろいろ調べた結果、window-text-pixel-size関数を使うとテキストのサイズがピクセル単位で計測できるということがわかりました。LinuxのX11上ではEmacsの表示とrsvgによる表示はほぼ一致しているようですが、他の環境ではテストしていません。

C-pC-nで上下のセルに移動する機能はまだ未完成です。今のところ文字の幅は1か2であるという仮定でカーソルを移動させています(current-columnが返す値を使っています)。しかし、プロポーショナルフォントを使っている場合はその仮定は崩れてEmacsの標準の動作とずれてしまいます。

マウスによる操作も未実装です。Emacsではマウスイベントが取れるので、座標から文字の位置を調べれば原理的には実装できるはずです。

バッファのフォーマット

fundamental-modeに切り替えると生のテキストが見えます。

各セルはASCIIのunit separatorのみを持つ行で区切られていて、テーブルの各行はrecord separatorでのみを持つ行で区切られています。

CSVや、Org modeの表形式なども考えましたが、セルに複数行のテキストを入れたかったのと、C-aC-ereplace-stringなどがなるべくそのまま動くようにしたかったのでこうなりました。

関連するもの