aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2022-10-28 17:54:43 -0700
committerYuan Fu2022-10-28 17:54:43 -0700
commit0c7a7df98e1fb0bc156707b379e4147fac97359a (patch)
treeef517530077b515034b38833e7014623988b710c
parent434fc2a22e4fd65fd63018e9373cbf56b51f8ab2 (diff)
downloademacs-0c7a7df98e1fb0bc156707b379e4147fac97359a.tar.gz
emacs-0c7a7df98e1fb0bc156707b379e4147fac97359a.zip
Add treesit-indent-region
Now indenting a large buffer is reasonably fast. * lisp/treesit.el (treesit-indent): Move meat to treesit--indent-1. (treesit--indent-1) (treesit-indent-region): New functions. (treesit-major-mode-setup): Setup indent-region-function.
-rw-r--r--lisp/treesit.el79
1 files changed, 65 insertions, 14 deletions
diff --git a/lisp/treesit.el b/lisp/treesit.el
index f1440412028..9c4d4535342 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -922,11 +922,13 @@ is a point (not a node), and OFFSET is a number. Emacs finds the
922column of ANCHOR and adds OFFSET to it as the final indentation 922column of ANCHOR and adds OFFSET to it as the final indentation
923of the current line.") 923of the current line.")
924 924
925(defun treesit-indent () 925(defun treesit--indent-1 ()
926 "Indent according to the result of `treesit-indent-function'." 926 "Indent the current line.
927 (treesit-update-ranges) 927Return the column we should indent this line to, or nil if we
928 (let* ((orig-pos (point)) 928can't figure it out. This function is used by `treesit-indent'
929 (bol (save-excursion 929and `treesit-indent-region'."
930 ;; Basically holds the common part between the two indent function.
931 (let* ((bol (save-excursion
930 (forward-line 0) 932 (forward-line 0)
931 (skip-chars-forward " \t") 933 (skip-chars-forward " \t")
932 (point))) 934 (point)))
@@ -957,14 +959,62 @@ of the current line.")
957 (funcall treesit-indent-function node parent bol))) 959 (funcall treesit-indent-function node parent bol)))
958 (if (or (null anchor) (null offset)) 960 (if (or (null anchor) (null offset))
959 nil 961 nil
960 (let ((col (+ (save-excursion 962 (+ (save-excursion
961 (goto-char anchor) 963 (goto-char anchor)
962 (current-column)) 964 (current-column))
963 offset))) 965 offset)))))
964 (if (< bol orig-pos) 966
965 (save-excursion 967(defun treesit-indent ()
966 (indent-line-to col)) 968 "Indent according to the result of `treesit-indent-function'."
967 (indent-line-to col))))))) 969 (treesit-update-ranges)
970 (let* ((orig-pos (point))
971 (bol (current-indentation))
972 (col (treesit--indent-1)))
973 (when col
974 (if (< bol orig-pos)
975 (save-excursion
976 (indent-line-to col))
977 (indent-line-to col)))))
978
979(defvar treesit--indent-region-batch-size 1000
980 "How many lines of indent value do we precompute.
981In `treesit-indent-region' we indent in batches: precompute
982indent for each line, apply them in one go, let parser reparse,
983and do it again. This way the parser don't need to unnecessarily
984reparse after indenting every single line.")
985
986(defun treesit-indent-region (beg end)
987 "Indent the region between BEG and END.
988Similar to `treesit-indent', but indent a region instead."
989 (treesit-update-ranges)
990 (let ((indents (make-vector treesit--indent-region-batch-size 0))
991 (lines-left-to-move 0)
992 (idx 0)
993 (jdx 0)
994 (starting-pos 0)
995 (announce-progress (> (- end beg) 80000)))
996 (save-excursion
997 (goto-char beg)
998 (while (and (eq lines-left-to-move 0) (< (point) end))
999 (setq idx 0 jdx 0
1000 starting-pos (point))
1001 (while (and (eq lines-left-to-move 0)
1002 (< idx treesit--indent-region-batch-size)
1003 (< (point) end))
1004 (setf (aref indents idx) (or (treesit--indent-1) 0))
1005 (cl-incf idx)
1006 (setq lines-left-to-move (forward-line 1)))
1007 ;; Now IDX = last valid IDX + 1.
1008 (goto-char starting-pos)
1009 (while (< jdx idx)
1010 (let ((col (aref indents jdx)))
1011 (when (not (eq col 0))
1012 (indent-line-to col)))
1013 (forward-line 1)
1014 (cl-incf jdx))
1015 (when announce-progress
1016 (message "Indenting region...%s%%"
1017 (/ (* (- (point) beg) 100) (- end beg))))))))
968 1018
969(defun treesit-simple-indent (node parent bol) 1019(defun treesit-simple-indent (node parent bol)
970 "Calculate indentation according to `treesit-simple-indent-rules'. 1020 "Calculate indentation according to `treesit-simple-indent-rules'.
@@ -1235,7 +1285,8 @@ If `treesit-defun-type-regexp' is non-nil, setup
1235 (treesit-font-lock-recompute-features)) 1285 (treesit-font-lock-recompute-features))
1236 ;; Indent. 1286 ;; Indent.
1237 (when treesit-simple-indent-rules 1287 (when treesit-simple-indent-rules
1238 (setq-local indent-line-function #'treesit-indent)) 1288 (setq-local indent-line-function #'treesit-indent)
1289 (setq-local indent-region-function #'treesit-indent-region))
1239 ;; Navigation. 1290 ;; Navigation.
1240 (when treesit-defun-type-regexp 1291 (when treesit-defun-type-regexp
1241 (setq-local beginning-of-defun-function #'treesit-beginning-of-defun) 1292 (setq-local beginning-of-defun-function #'treesit-beginning-of-defun)