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.
This commit is contained in:
parent
25b4bf7fcd
commit
10b4d3045e
2 changed files with 76 additions and 40 deletions
|
@ -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
|
||||
|
|
113
lisp/treesit.el
113
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue