emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 10b4d3045e1 1/4: Make tree-sitter-explorer support selecting loca


From: Yuan Fu
Subject: master 10b4d3045e1 1/4: Make tree-sitter-explorer support selecting local parser
Date: Thu, 5 Dec 2024 01:44:39 -0500 (EST)

branch: master
commit 10b4d3045e1b856009c5ac1e1a1ca257f2d4493f
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>

    Make tree-sitter-explorer support selecting local parser
    
    Now treesit-explore-mode will prompt the user to select a parser
    to explore, rather than a language.  It'll also include the
    local parsers at point for selection.
    
    * lisp/treesit.el (treesit--explorer-language): Change to
    treesit--explorer-parser.
    (treesit--explorer--nodes-to-highlight):
    (treesit--explorer-refresh): Change to use parser.
    (treesit--explorer-generate-parser-alist): New function.
    (treesit-explorer-switch-parser): New command.
    (treesit-explore-mode): Use switch-parser to setup.
    * doc/lispref/parsing.texi (Language Grammar): Mention
    treesit-explorer-switch-parser.
---
 doc/lispref/parsing.texi |   3 ++
 lisp/treesit.el          | 113 ++++++++++++++++++++++++++++++-----------------
 2 files changed, 76 insertions(+), 40 deletions(-)

diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 5ef29f558ef..7fbb8e61ce1 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -240,12 +240,15 @@ which displays the syntax tree of the source in the 
current buffer in
 real time.  Emacs also comes with an ``inspect mode'', which displays
 information of the nodes at point in the mode-line.
 
+@findex treesit-explorer-switch-parser
 @deffn Command treesit-explore
 This command pops up a window displaying the syntax tree of the source in
 the current buffer.  Selecting text in the source buffer highlights
 the corresponding nodes in the syntax tree display.  Clicking
 on nodes in the syntax tree highlights the corresponding text in the
 source buffer.
+
+To switch to another parser, use @code{treesit-explorer-switch-parser}.
 @end deffn
 
 @deffn Command treesit-inspect-mode
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 2acb46ab105..6bebb31ee18 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -3347,7 +3347,7 @@ to the offending pattern and highlight the pattern."
 (defvar-local treesit--explorer-source-buffer nil
   "Source buffer corresponding to the playground buffer.")
 
-(defvar-local treesit--explorer-language nil
+(defvar-local treesit--explorer-parser nil
   "The language used in the playground.")
 
 (defvar-local treesit--explorer-refresh-timer nil
@@ -3361,8 +3361,8 @@ to the offending pattern and highlight the pattern."
 
 (defvar treesit-explore-mode)
 
-(defun treesit--explorer--nodes-to-highlight (language)
-  "Return nodes for LANGUAGE covered in region.
+(defun treesit--explorer--nodes-to-highlight (parser)
+  "Return nodes for PARSER covered in region.
 This function tries to return the largest node possible.  If the
 region covers exactly one node, that node is returned (in a
 list).  If the region covers more than one node, two nodes are
@@ -3370,7 +3370,7 @@ returned: the very first one in the region and the very 
last one
 in the region."
   (let* ((beg (region-beginning))
          (end (region-end))
-         (node (treesit-node-on beg end language))
+         (node (treesit-node-on beg end parser))
          (node (or (treesit-parent-while
                     node
                     (lambda (n)
@@ -3394,7 +3394,7 @@ in the region."
   (when (and treesit-explore-mode
              (buffer-live-p treesit--explorer-buffer))
     (let* ((root (treesit-node-on
-                  (window-start) (window-end) treesit--explorer-language))
+                  (window-start) (window-end) treesit--explorer-parser))
            ;; Only highlight the current top-level construct.
            ;; Highlighting the whole buffer is slow and unnecessary.
            ;; But if the buffer is small (ie, used in playground
@@ -3411,7 +3411,7 @@ in the region."
            (nodes-hl
             (when (region-active-p)
               (treesit--explorer--nodes-to-highlight
-               treesit--explorer-language)))
+               treesit--explorer-parser)))
            ;; If we didn't edit the buffer nor change the top-level
            ;; node, don't redraw the whole syntax tree.
            (highlight-only (treesit-node-eq
@@ -3589,11 +3589,56 @@ leaves point at the end of the last line of NODE."
   (when (buffer-live-p treesit--explorer-buffer)
     (kill-buffer treesit--explorer-buffer)))
 
+(defun treesit--explorer-generate-parser-alist ()
+  "Return an alist of (PARSER-NAME . PARSER) for relevant parsers.
+Relevant parsers include all global parsers and local parsers that
+covers point.  PARSER-NAME are unique."
+  (let* ((local-parsers (treesit-parser-list nil nil 'embedded))
+         (local-parsers-at-point
+          (treesit-local-parsers-at (point)))
+         res)
+    (dolist (parser (treesit-parser-list nil nil t))
+      ;; Exclude local parsers that doesn't cover point.
+      (when (or (memq parser local-parsers-at-point)
+                (not (memq parser local-parsers)))
+        (push (cons (concat (format "%s" parser)
+                            (if (treesit-parser-tag parser)
+                                (format " tag=%s"
+                                        (treesit-parser-tag
+                                         parser))
+                              "")
+                            (if (memq parser
+                                      local-parsers-at-point)
+                                " (local)"
+                              "")
+                            (propertize (format " %s" (gensym))
+                                        'invisible t))
+                    parser)
+              res)))
+    (nreverse res)))
+
 (define-derived-mode treesit--explorer-tree-mode special-mode
   "TS Explorer"
   "Mode for displaying syntax trees for `treesit-explore-mode'."
   nil)
 
+(defun treesit-explorer-switch-parser (parser)
+  "Switch explorer to use PARSER."
+  (interactive
+   (list (let* ((parser-alist
+                 (treesit--explorer-generate-parser-alist))
+                (parser-name (completing-read
+                              "Parser: " (mapcar #'car parser-alist))))
+           (alist-get parser-name parser-alist
+                      nil nil #'equal))))
+  (unless treesit-explore-mode
+    (user-error "Not in `treesit-explore-mode'"))
+  (setq-local treesit--explorer-parser parser)
+  (display-buffer treesit--explorer-buffer
+                  (cons nil '((inhibit-same-window . t))))
+  (setq-local treesit--explorer-last-node nil)
+  (treesit--explorer-refresh))
+
 (define-minor-mode treesit-explore-mode
   "Enable exploring the current buffer's syntax tree.
 Pops up a window showing the syntax tree of the source in the
@@ -3602,40 +3647,28 @@ the text in the active region is highlighted in the 
explorer
 window."
   :lighter " TSexplore"
   (if treesit-explore-mode
-      (let ((language
-             (intern (completing-read
-                      "Language: "
-                      (cl-remove-duplicates
-                       (mapcar #'treesit-parser-language
-                               (treesit-parser-list nil nil t)))))))
-        (if (not (treesit-language-available-p language))
-            (user-error "Cannot find tree-sitter grammar for %s: %s"
-                        language (cdr (treesit-language-available-p
-                                       language t)))
-          ;; Create explorer buffer.
-          (unless (buffer-live-p treesit--explorer-buffer)
-            (setq-local treesit--explorer-buffer
-                        (get-buffer-create
-                         (format "*tree-sitter explorer for %s*"
-                                 (buffer-name))))
-            (setq-local treesit--explorer-language language)
-            (with-current-buffer treesit--explorer-buffer
-              (treesit--explorer-tree-mode)))
-          (display-buffer treesit--explorer-buffer
-                          (cons nil '((inhibit-same-window . t))))
-          (setq-local treesit--explorer-last-node nil)
-          (treesit--explorer-refresh)
-          ;; Set up variables and hooks.
-          (add-hook 'post-command-hook
-                    #'treesit--explorer-post-command 0 t)
-          (add-hook 'kill-buffer-hook
-                    #'treesit--explorer-kill-explorer-buffer 0 t)
-          ;; Tell `desktop-save' to not save explorer buffers.
-          (when (boundp 'desktop-modes-not-to-save)
-            (unless (memq 'treesit--explorer-tree-mode
-                          desktop-modes-not-to-save)
-              (push 'treesit--explorer-tree-mode
-                    desktop-modes-not-to-save)))))
+      (progn
+        ;; Create explorer buffer.
+        (unless (buffer-live-p treesit--explorer-buffer)
+          (setq-local treesit--explorer-buffer
+                      (get-buffer-create
+                       (format "*tree-sitter explorer for %s*"
+                               (buffer-name))))
+          (with-current-buffer treesit--explorer-buffer
+            (treesit--explorer-tree-mode)))
+        ;; Select parser.
+        (call-interactively #'treesit-explorer-switch-parser)
+        ;; Set up variables and hooks.
+        (add-hook 'post-command-hook
+                  #'treesit--explorer-post-command 0 t)
+        (add-hook 'kill-buffer-hook
+                  #'treesit--explorer-kill-explorer-buffer 0 t)
+        ;; Tell `desktop-save' to not save explorer buffers.
+        (when (boundp 'desktop-modes-not-to-save)
+          (unless (memq 'treesit--explorer-tree-mode
+                        desktop-modes-not-to-save)
+            (push 'treesit--explorer-tree-mode
+                  desktop-modes-not-to-save))))
     ;; Turn off explore mode.
     (remove-hook 'post-command-hook
                  #'treesit--explorer-post-command t)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]