バッファーにおいて関数やクラスの定義、ステートメント、コードブロック、文字列、コメント等といった特定のthings(物、オブジェクト)を識別して探せれば便利なときが多々あります。Emacsではどんな種類のtree-sitterノードが“thing”に相当するかをユーザーが定義できます。これにより次の関数へのジャンプ、ポイント位置にあるコードブロックのマーク、2つの関数の引数の入れ替えといった便利な機能が有効になります。
Emacsの“things”機能はtree-sitterのパターンマッチング機能とは独立した機能であり、パワーは比較的劣るもののパースツリーのナビゲーションと横断にはより適しています。
You can define things with treesit-thing-settings, retrieve the
predicate of a defined thing with treesit-thing-definition
, and test
if a thing is defined with treesit-thing-defined-p
.
これは言語それぞれにたいするthing定義のalistである。各エントリーのキーは言語シンボル、値は(thing pred)
という形式のthing定義のリスト。ここでthingはdefun
、sexp
、sentence
のようにthingを表すシンボル、predはこのthingがtree-sitterの何の種類のノードかを指定する。
predはノードのタイプにマッチするregexp文字列、ノードを引数としてそのノードがthingとして適格かを示すブーリアン値をリターンする関数、あるいは(regexp . fn)
というコンスでもよい。これは正規表現regexpと関数fnからなるコンスであり、ノードはregexpとthingとしての適格性を調べるfnの両方を満足する必要がある。
predは再帰的に定義することもできる。(or pred…)
と記述すると、predのいずれかが満たされればノードがthingとして適格であることを意味する。(not pred)
と記述すれば、predが満たされないことでノードが適格であることを意味する。
最後にpredはこのリスト内で定義された他のpredを参照できる。たとえば(or sexp sentence)
はこのあist内の他のルールとして定義されたsexp
かsentence
いずれかのthingであることを定義している。
以下はC/C++にたいするtreesit-thing-settings
の例:
((c (defun "function_definition") (sexp (not "[](),[{}]")) (comment "comment") (string "raw_string_literal") (text (or comment string))) (cpp (defun ("function_definition" . cpp-ts-mode-defun-valid-p)) (defclass "class_specifier") (comment "comment")))
これは教示目的のために修正された例であって、C/C++
のモードが実際にthingを定義する方法とは異なることに注意。
このセクションの残りの部分では、thing定義の恩恵を受ける関数をいくつか紹介します。以下の関数の他にもthing機能を利用する、たとえばtreesit-search-forward
やtreesit-induce-sparse-tree
等のツリー横断関数のような他の関数も別の場所で紹介されています。ノードの取得を参照してください。
This function checks whether node is a thing.
If node is a thing, return non-nil
, otherwise return
nil
. For convenience, if node
is nil
, this function
just returns nil
.
The thing can be either a thing symbol like defun
, or simply a
predicate that defines a thing, like "function_definition"
, or
(or comment string)
.
By default, if thing is undefined or malformed, this function signals
treesit-invalid-predicate
error. If ignore-missing is
t
, this function doesn’t signal the error when thing is
undefined and just returns nil
; but it still signals the error if
thing is a malformed predicate.
この関数はpositionの前にある指定されたthingであるような最初のノードをリターンする。そのようなノードがなければnil
をリターンする。ノードがリターンされた場合には、ノード終端位置はposition以前であることが保証されている。言い換えると、この関数がpositionを取り囲むようなノードをリターンすることはあり得ない
Again, thing can be either a symbol or a predicate.
この関数はtreesit-thing-prev
と似ているがpositionとり後にあるthingであるような最初のノードだけをリターンする点が異なる。ノードがリターンされた場合には、ノード先頭位置はposition以降であることが保証されている。
この関数はtreesit-thing-prev
とtreesit-thing-next
上に構築されており、ナビゲーションコマンドにおいて役に立つと思われる機能を提供する。この関数はpositionからarg個のthingインスタンスを横断して移動した後の位置をリターンする。横断するだけの十分なthingが存在しなければnilをリターンする。この関数はポイントを移動しない。
正のargはthingのその個数のインスタンス分前方への移動、負のargは後方への移動を意味する。この関数はsideがbeg
ならthingの先頭で停止、end
ならthingの終端で停止する。
Like in treesit-thing-prev
, thing can be a thing symbol defined
in treesit-thing-settings
, or a predicate.
tacticはこの関数がthing間を移動する方法を決定する。nested
、top-level
、restricted
、nil
のいずれか。nested
とnil
は通常のネストされたナビゲーションを意味する。まず兄弟を横断しての移動を試み、カレントレベルに兄弟がなければ親に移動してその兄弟を横断、のように移動する。top-level
はネストされたthingを無視してトップレベルのthingだけを横断した移動、restricted
はpositionを囲い込むようなthingがあればその中に制限された移動を意味する。このtactic(戦術)はカレントネストレベルに留まって上位に移動したくないようなコマンドにたいして有用。
この関数はpositionを囲い込むthingであるような最小のノードをリターンする。そのようなノードがなければnil
をリターンする。
リターンされるノードはpositionを囲い込んでいなければならない。すなわちノード開始位置がposition以前、ノード終端位置がposition以降であること。
strictが非nil
なら、この関数は厳格な比較を使用する。すなわち開始位置はpositionより厳密に前、終端位置はpositionより厳密に後でなければならない。
thing can be either a thing symbol defined in
treesit-thing-settings
, or a predicate.
便利なラッパー関数もあります。treesit-beginning-of-thing
はthing先頭にポイントを移動、treesit-end-of-thing
はthing終端にポイントを移動、treesit-thing-at-point
はポイント位置にあるthingをリターンします。
treesit-beginning-of-defun
、treesit-end-of-defun
、treesit-defun-at-point
のように、(treesit-defun-type-regexp
のフォールバックとしての)defun
定義使用に特化したdefunコマンドもあります。さらにこれらの関数は移動の戦術としてtreesit-defun-tactic
を使用します。これらの詳細については別のセクションで説明します(Tree-sitterとのメジャーモード開発を参照)。