Skip to content

Instantly share code, notes, and snippets.

@buzztaiki
Created August 25, 2025 07:21
Show Gist options
  • Save buzztaiki/6bc04dd4df1ce65e0d7c876455dcef0f to your computer and use it in GitHub Desktop.
Save buzztaiki/6bc04dd4df1ce65e0d7c876455dcef0f to your computer and use it in GitHub Desktop.
treesit query の pred に closure は渡せない

treesit query の pred に closure は渡せない

それはそう。

(let* ((pred (lambda (captured) (eq (treesit-node-start captured) (treesit-node-start node))))
       (query `(((element
                  (start_tag
                   (tag_name) @tag_name
                   (attribute
                    (attribute_name) @_attr_name
                    (quoted_attribute_value (attribute_value) @class_name))))
                 @element
                 (:match "class" @_attr_name)
                 (:pred ,pred @element)))))
  (treesit-query-validate 'vue query))
=>
Syntax error at: 186
((element (start_tag (tag_name) @tag_name (attribute (attribute_name) @_attr_name (quoted_attribute_value (attribute_value) @class_name)))) @element (#match "class" @_attr_name) (#pred #[(captured) ((eq (treesit-node-start captured) (treesit-node-start node))) (t)] @element))

みやすくする

((element
  (start_tag (tag_name) @tag_name
             (attribute (attribute_name) @_attr_name
                        (quoted_attribute_value (attribute_value)
                                                @class_name))))
 @element (#match "class" @_attr_name)
 (#pred #[(captured)
          ((eq (treesit-node-start captured) (treesit-node-start node)))
          (t)]
        @element))

というかコンパイル時に何かが解決されるわけじゃない。

(let* ((query '(((element
                  (start_tag
                   (tag_name) @tag_name
                   (attribute
                    (attribute_name) @_attr_name
                    (quoted_attribute_value (attribute_value) @class_name))))
                 @element
                 (:match "class" @_attr_name)
                 (:pred pred @element)))))
  (treesit-query-validate 'vue query))
=>
"QUERY is valid"

一時的に fset すればいけなくはない (cl-flet だと駄目)。

(defun --pred (&rest _))

(defun query-test (node use-pred)
  (let ((orig-pred (symbol-function #'--pred)))
    (fset #'--pred (lambda (captured) (eq (treesit-node-start captured) (treesit-node-start node))))
    (unwind-protect
        (let ((query `b(((element
                         (start_tag
                          (tag_name) @tag_name
                          (attribute
                           (attribute_name) @_attr_name
                           (quoted_attribute_value (attribute_value) @class_name))))
                        @element
                        (:match "class" @_attr_name)
                        ,@(if use-pred '((:pred --pred @element)) ())))))
          (treesit-query-capture node query))
      (fset #'--pred orig-pred))))

(query-test (treesit-parent-until (treesit-node-at (point)) "element") t)
=>
((element . #<treesit-node element in 589-919>)
 (tag_name . #<treesit-node tag_name in 590-593>)
 (_attr_name . #<treesit-node attribute_name in 594-599>)
 (class_name . #<treesit-node attribute_value in 601-610>)
 (element . #<treesit-node element in 617-650>)
 (tag_name . #<treesit-node tag_name in 618-620>)
 (_attr_name . #<treesit-node attribute_name in 621-626>)
 (class_name . #<treesit-node attribute_value in 628-634>)
 (element . #<treesit-node element in 670-910>)
 (tag_name . #<treesit-node tag_name in 671-673>)
 (_attr_name . #<treesit-node attribute_name in 674-679>)
 (class_name . #<treesit-node attribute_value in 681-685>))


(query-test (treesit-parent-until (treesit-node-at (point)) "element") t)
=>
((element . #<treesit-node element in 589-919>)
 (tag_name . #<treesit-node tag_name in 590-593>)
 (_attr_name . #<treesit-node attribute_name in 594-599>)
 (class_name . #<treesit-node attribute_value in 601-610>))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment