4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Emacsのvtable.elで表を書く

Last updated at Posted at 2025-12-17

この記事では、Emacs 29.1で導入されたvtable.elについて紹介します。

vtable.el(以下vtable)は、動的で操作できる表のUIを簡単に作成できるライブラリです。
整列や列幅調整などの機能を標準装備しています。
似たパッケージとしては、同じく標準のtabulated-list-modeがあります。

基本的な使い方

……はEmacsのマニュアルに、端的にまとまっています(個人的に翻訳しかけたものもあるためよろしければ)。

ひとまず動かしてみましょう。
いろいろ試す上では専用のバッファがあるとよいと思うので、以下の雛形を用意します。

(let ((buf (get-buffer-create "*vtable-playground*")))
  (with-current-buffer buf
    (erase-buffer)
    ;; ここに書いていきます。
    (insert "hello\n"))
  (pop-to-buffer buf));^^)

次のようにして実行できます:

  1. *scratch*バッファに貼り付け
  2. ;^^)のセミコロンにポイント(カーソルみたいなもの)を持って行く
  3. C-x C-e (eval-last-sexp) で実行

実行すると、*vtable-playground*バッファに「hello」と表示されるはずです。

以降は ;; ここに書いていきます。 の部分のコードを示します。

最小限の例

(require 'vtable)
(make-vtable
 :columns '("県名" "県庁所在地")
 :objects '(("栃木県" "宇都宮市")
            ("山梨県" "甲府市")
            ("Loiret" "Orléans")))

以下のような表が表示されます。

県名 県庁所在地
栃木県 宇都宮市
山梨県 甲府市
Loiret Orléans

:columnsには列の設定を書きます。
ここでは単に、列名のリストにしています。

:objectsには表示するデータを入れます。
ここでは単に、そのまま表示するデータを指定しています。

列の設定

県庁所在地の列を設定して、文字を逆にしてみましょう。

(make-vtable
 :columns '((:name "県名")
            (:name "県庁所在地"
             :formatter reverse))
 :objects '(("栃木県" "宇都宮市")
            ("山梨県" "甲府市")
            ("Loiret" "Orléans")))

「県名」は、同じ見た目ですが、'(:name "県名") のように冗長な書き方をしています。
「県庁所在地」はさらに複雑にして '(:name "県庁所在地" :formatter reverse) になっています。
このように、属性を足していくことで、柔軟に見た目や動きを調整できます。

主なAPI

なんとなくvtableのイメージが掴めたでしょうか。

よく使うAPIは、なにはともあれmake-vtable関数です。
主な引数について……

  • 多くの場合、:columnsを指定します。
  • ここでの例はデータが固定だったため:objectsでいいのですが、動的に取得して表示したいときは:objects-functionが便利です。
  • データが複雑なときは、:getterを使うときもあります。

実際にvtableを使うときは、マニュアルにあるインターフェース関数を使うことになります。
vtable-goto-table, vtable-beginning-of-table, vtable-end-of-tableなどです。

実装時のTips

ここでは実装時のコツといいますか、気付いたことをいくつか紹介します。

キーバインド

vtableの表にポイントがあるとき、:actions:keymapで指定されたキーバインドが使えます。
おそらく、:actionsが各行に対応するデータに対するもので、:keymapは表全体で使うものという棲み分けだと思います。

それはいいとして、問題はvtableを含むようなメジャーモードを作っているときです。
おそらくvtableを埋め込みたくなるメジャーモードは、special-modeを継承して読み専用にしたいはずです。
そしてそのバッファ全体に対してキーマップを追加したいときは、次のような感じにするとよさそうな気がしています。

(define-derived-mode your-awesome-mode special-mode "YourAwesomeMode"
  "Your awesome mode (hopefully)."
  (let ((inhibit-read-only t))
    (erase-buffer)
    (use-some-vtable-or-something))
  (beginning-of-buffer)
  (use-local-map (make-composed-keymap some-keymap special-mode-map)))

use-local-mapの行がミソです。

ちなみに、special-modeにそのままではvtableを書き込めないため、一時的にinhibit-read-onlytにする必要があります。

表の再描画

表を更新するとき、普通はvtable-revertvtable-revert-commandを使うのだと思います。
しかしそれでも更新されないときは、腕力に訴えるよりなさそうです。

(defun some-awesome--revert-vtable (table inserter)
  "現在ある表TABLEを、表を新たに挿入する関数INSERTERを使って再生成します.
`vtable-revert'の実装を参考にしています。"
  (save-excursion
    (vtable-goto-table table)
    (let ((inhibit-read-only t))
      (delete-region (vtable-beginning-of-table) (vtable-end-of-table))
      (funcall inserter))))

この関数は既に存在するvtableの表と、新しく表を描く関数を取ります。
delete-regionのところで現在の表を消し去っているわけですね。

なお、save-excursionはポイントの位置を保存しておくためのマクロです。

間に入り込ませない

表のヘッダとデータ本体の間は、気を抜くと何かしら挟み込まれてしまうことがあります。

  • 表の上に何かがあるとき
  • 表の下に何かがあるとき

それぞれの場合を見てみましょう。
まず、表の上に何かがあるとき。

(insert "ほうとう\n")
(make-vtable
 :columns '("県名" "県庁所在地")
 :objects '(("栃木県" "宇都宮市")
            ("山梨県" "甲府市")
            ("Loiret" "Orléans")))

すると、以下みたいな感じになるはずです。

県名 県庁所在地
ほうとう
栃木県 宇都宮市
山梨県 甲府市
Loiret Orléans

こうなるのは、ヘッダがバッファの一番上に陣取ってこようとしているからです。
:use-header-line nilを使うと解消します。

    (insert "ほうとう\n")
    (make-vtable
     :columns '("県名" "県庁所在地")
     :objects '(("栃木県" "宇都宮市")
                ("山梨県" "甲府市")
                ("Loiret" "Orléans"))
     :use-header-line nil)

次に、表の下に何かがあるとき。

(make-vtable
 :columns '("県名" "県庁所在地")
 :objects '(("栃木県" "宇都宮市")
            ("山梨県" "甲府市")
            ("Loiret" "Orléans")))
(insert "ほうとう\n")

これもやっぱり、ほうとうが注ぎ込まれてしまいます。

正解は(vtable-end-of-table)です。
要は、表を描き終えたら、ポイントを表の末尾に移動しておくわけです。

(make-vtable
 :columns '("県名" "県庁所在地")
 :objects '(("栃木県" "宇都宮市")
            ("山梨県" "甲府市")
            ("Loiret" "Orléans")))
(vtable-end-of-table)
(insert "ほうとう\n")

まとめ

vtableを使うことで、Emacs上で簡単に表のUIを実装できます。
パッケージ開発やカスタムコマンドの作成に活用してみてください。

Copyright (c)  2025 gemmaro.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
The license is located at <https://www.gnu.org/licenses/fdl-1.3.html>.
4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?