]> git.eshelyaron.com Git - emacs.git/commitdiff
Treesit support for show-paren-mode (bug#75122)
authorJuri Linkov <juri@linkov.net>
Sun, 29 Dec 2024 18:08:11 +0000 (20:08 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 4 Jan 2025 20:25:10 +0000 (21:25 +0100)
* lisp/treesit.el (treesit-show-paren-data--categorize):
New internal function.
(treesit-show-paren-data): New function.
(treesit-major-mode-setup): Set 'show-paren-data-function' to
'treesit-show-paren-data'.

(cherry picked from commit 1addae07be1982a6cafc0e0b3955b59bd1fb481c)

etc/NEWS
lisp/treesit.el

index f678751b2f3742fcf19d312dfa1156abc62c369c..e7199bef9767be034a791d82eaeaafb23f98bd9f 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -857,6 +857,10 @@ Tree-sitter conditionally sets 'up-list-function' for major modes
 that have defined 'sexp-list' in 'treesit-thing-settings' to enable
 the 'up-list' motion command.
 
+*** New function 'treesit-show-paren-data'.
+Tree-sitter sets 'show-paren-data-function' to this function
+to support 'show-paren-mode'.
+
 +++
 *** New function 'treesit-language-display-name'.
 This new function returns the display name of a language given the
index 84c29981f50eb884b3df652433539aee75826d5f..99468c91bf540663956bb353597364844fc0fcdf 100644 (file)
@@ -3381,6 +3381,49 @@ For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in
       (setq level (1+ level)))
     (if (zerop level) 1 level)))
 
+;;; Show paren mode
+
+(defun treesit-show-paren-data--categorize (pos &optional end-p)
+  (let* ((pred 'sexp-list)
+         (parent (treesit-node-parent (treesit-node-at (if end-p (1- pos) pos))))
+         (parent (when (treesit-node-match-p parent pred t) parent))
+         (first (when parent (treesit-node-child parent 0)))
+         (first-start (when first (treesit-node-start first)))
+         (first-end (when first (treesit-node-end first)))
+         (last (when parent (treesit-node-child parent -1)))
+         (last-start (when last (treesit-node-start last)))
+         (last-end (when last (treesit-node-end last)))
+         (dir (if show-paren-when-point-inside-paren
+                  (cond
+                   ((and first (<= first-start pos first-end)) 1)
+                   ((and last (<= last-start pos last-end)) -1))
+                (cond
+                 ((and first (= first-start pos)) 1)
+                 ((and last (= pos last-end)) -1)))))
+    (cond
+     ((eq dir 1) (list first-start first-end last-start last-end))
+     ((eq dir -1) (list last-start last-end first-start first-end)))))
+
+(defun treesit-show-paren-data ()
+  "A function suitable for `show-paren-data-function' (which see)."
+  (or (treesit-show-paren-data--categorize (point))
+      (unless (bobp) (treesit-show-paren-data--categorize (point) t))
+      (when show-paren-when-point-in-periphery
+        (let* ((ind-pos (save-excursion (back-to-indentation) (point)))
+              (eol-pos
+               (save-excursion
+                 (end-of-line) (skip-chars-backward " \t" ind-pos) (point))))
+          (cond
+           ((<= (point) ind-pos)
+            (or (treesit-show-paren-data--categorize ind-pos)
+               (unless (bobp)
+                  (treesit-show-paren-data--categorize (1- eol-pos)))))
+           ((>= (point) eol-pos)
+            (unless (bobp)
+              (treesit-show-paren-data--categorize (1- eol-pos)))))))
+      ;; Fall back for parens in e.g. 'for_statement'
+      (show-paren--default)))
+
 ;;; Activating tree-sitter
 
 (defun treesit-ready-p (language &optional quiet)
@@ -3539,6 +3582,8 @@ before calling this function."
     (setq-local outline-search-function #'treesit-outline-search
                 outline-level #'treesit-outline-level))
 
+  (setq-local show-paren-data-function 'treesit-show-paren-data)
+
   ;; Remove existing local parsers.
   (dolist (ov (overlays-in (point-min) (point-max)))
     (when-let ((parser (overlay-get ov 'treesit-parser)))