[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)