Emacsのクロスリファレンス用ライブラリであるxref.elについて調べたり考えたりする。
xref.elとは
xref.elはタグジャンプなどの機能のためのI/Fを提供している。一般的に関数の名前の上にカーソルを当てて M-.
を実行するとカーソルの定義位置にジャンプする。この時 xref-find-definitions
が呼び出されているが、この関数はxref.elに定義されている。
xrefバックエンドを実装する
xrefを使用してタグジャンプなどを実現するには、xrefバックエンドが実装されている必要がある。通常、各種言語のxrefバックエンドは既に実装されている事が多いだろう。しかし新しい言語や、ユーザーが少ない言語、自作言語の場合は、xrefバックエンドを実装する必要に迫られる事もある。ここでは、簡単なxrefバックエンドを実装する事で、その実装方法を確認する。
ここでは、全ての機能を実装しない。 xref-find-definitions
によって特定の位置にジャンプする機能を実装し xref-go-back
によってジャンプ先からジャンプ元に戻れる事までを確認する。便宜上 symdon
というxrefバックエンドを実装する事にする。
xrefバックエンドは xref-backend-functions
に登録される。テストで実装するバックエンド以外を無効化するために、変数をnilに設定しておく。
(setq-local xref-backend-functions nil)
xrefバックエンドのシンボルを返す関数を実装する。ここでは symdon
というシンボルにしている。このシンボルによって各種バックエンドは処理を分岐する。この関数は先程初期化した xref-backend-functions
に登録する事で有効になる。
(defun symdon--xref-backend () 'symdon)
(add-to-list 'xref-backend-functions #'symdon--xref-backend)
xref-backend-identifier-completion-table
は xref-find-definitions
を実行した際に使用される、識別子の補完テーブルを返す関数を返す関数を実装する。識別子の補完テーブルは文字列のリストになる。補完テーブルからデータを読み出し、それらのリストになるようにデータを変換し返す。
(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql 'symdon)))
(lambda (string pred action)
'("aaa" "bbb" "ccc")))
xref-backend-definitions
は xref-backend-identifier-completion-table
によって選択されたシンボルの位置を特定し、外部参照として返す。外部参照は xref-make
を用いて作成する。先頭のスロットは summary
、その次のスロットは location
だ。 summary
には文字列を、 location
には位置を設定する。位置の形式はいくつかある。ここではバッファの位置を表現する形式である xref-buffer-location
を返している。またここでは、スクラッチバッファの先頭から200ポイントの位置を指定している。通常の実装では、きちんと位置を特定する必要がある。
(cl-defmethod xref-backend-definitions ((_backend (eql 'symdon)) symbol)
`(,(xref-make "testing"
(make-xref-buffer-location :buffer (get-buffer "*scratch*") :position 200))))
ここまで実装すると、 xref-find-definitions
と xref-go-back
は動作するようになる。
xref系で用意されているコマンド
xref.el.gzには以下の関数がコマンドとして用意されている。
- xref-find-apropos
- xref-find-backend
- xref-find-definitions
- xref-find-definitions-at-mouse
- xref-find-definitions-other-frame
- xref-find-definitions-other-window
- xref-find-references
- xref-marker-stack-empty-p
- xref-matches-in-directory
- xref-matches-in-files
- xref-pop-marker-stack
- xref-references-in-directory
(autoloadが宣言されている関数)
その他
Emacs 26.1の段階ではxref.el.gzには実験段階である旨の記述がある。
;; NOTE: The xref API is still experimental and can change in major, ;; backward-incompatible ways. Everyone is encouraged to try it, and ;; report to us any problems or use cases we hadn't anticipated, by ;; sending an email to emacs-devel, or `M-x report-emacs-bug'.
翻訳すると以下の意味だ。
注:外部参照APIはまだ実験段階であり、大幅に変更される可能性があります。 後方互換性のない方法。誰もがそれを試すことをお勧めします、そして 予期していなかった問題やユースケースを報告してください。 emacs-devel、または `M-xreport-emacs-bug 'にメールを送信します。
Emacs 28にはその記述はなくなっていた。