emacs-tree-sitter / elisp-tree-sitter

Emacs Lisp bindings for tree-sitter

Home Page:https://emacs-tree-sitter.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generalize tree-sitter-query--eval-query

ymarco opened this issue · comments

I wrote this code. A big part of it (tree-sitter-occur--find-patterns) is a copy-paste of tree-sitter-query--eval-query but returning the matches instead of highlighting.
Would you accept a PR modifying tree-sitter-query--eval-query to return a list or maybe accept a lambda in place of tree-sitter-query--highlight-capture?

I am doing basically the same thing right now for a moldable emacs mold.

(me-register-mold
 :key "TreesitterGrep"
 :given (:fn (and
              (executable-find "tree-grepper")
              (eq major-mode 'tree-sitter-query-mode)
              ;; (bound-and-true-p tree-sitter-language)
              ))
 :then (:fn  ;; the :then clause
        (let* ((file buffer-file-name)
               (language-name ())
               (language (with-current-buffer tree-sitter-query--target-buffer
                             tree-sitter-language))
               (language-symbol (with-current-buffer tree-sitter-query--target-buffer
                           (alist-get major-mode tree-sitter-major-mode-language-alist)))
                            
               (contents (save-excursion
                         (goto-char (point-min))
                         (eval `',(read (current-buffer)))))) ;; the scope here is in the original buffer you called the mold from
          (with-current-buffer buffername ;; `buffername' is available by default
            (erase-buffer)
            (insert (format "tree-grepper --query %S \"%S\" ." language-symbol contents))
            (setq-local self contents)))) ;; always set the `self' variable!
 :docs "Run tree-grepper")

and in another version I am wanting to run the query directly as

(defun me-mold-treesitter-query1 ()
  "Evaluate query PATTERNS against the target buffer."
  (interactive)
  (let ((patterns "(pair (string) @foo)"))
    (with-current-buffer (current-buffer)
      (tsc--without-restriction
        (remove-overlays)
        (when-let*
            ((query
              (condition-case err
                  (tsc-make-query tree-sitter-language patterns)
                ((tsc-query-invalid-node-type
                  tsc-query-invalid-field
                  tsc-query-invalid-capture)
                 (message "%s: %s" (get (car err) 'error-message) (cadr err))
                 nil)
                (tsc-query-invalid
                 (message "%s" (get (car err) 'error-message))
                 nil)))
             (root-node (tsc-root-node tree-sitter-tree))
             (captures (tsc-query-captures query root-node #'tsc--buffer-substring-no-properties)))
          (if (= (length captures) 0)
              (message "No captures found")
              (message "captures found:%S" (mapcar #'me-mold-treesitter-capture-to-plist captures))
            (mapc #'tree-sitter-query--highlight-capture captures)))))))

;; derived from tree-sitter-query--highlight-capture
(defun me-mold-treesitter-capture-to-plist (capture)
  "Convert CAPTURE to a plist."
  (pcase-let* ((`(,capture-symbol . ,captured-node) capture)
               (`(,node-start . ,node-end) (tsc-node-position-range captured-node))
               (capture-name (symbol-name capture-symbol)))
    (list :symbol capture-symbol :name capture-name :start node-start :end node-end)
    ))

Never mind. I see that most of the stuff I'm copy-pasting is error handling which maybe shouldn't be generalized.
@alanz I don't know what's a mold, I see you're using tree-grepper. My thought process with tree-sitter-occur was basically "We have tree-grepper but adding languages to it is a pain, why can't I do it with the languages already in tree-sitter-langs"

Perhaps a mold is related to this?

There's a molds directory: https://github.com/ag91/moldable-emacs/tree/master/molds

@sogaiu yes it is. It's a way of quickly stringing together snippets of code to do some kind of analysis. See https://emacsconf.org/2021/talks/mold/ for an overview. It is an emacs version of https://gtoolkit.com/

@alanz Thanks for the explanation and links!