diff options
| author | Yuan Fu | 2022-10-29 09:04:35 -0700 |
|---|---|---|
| committer | Yuan Fu | 2022-10-29 09:09:09 -0700 |
| commit | bde8e87cb7b3be0e0bc9e72c3634f108570cac3e (patch) | |
| tree | 76b52c4dacc6fa49106c37535e4b0f7a9c42515f | |
| parent | 4552b01d8c8052f607dca2fcddcf7b2e270f1db6 (diff) | |
| download | emacs-bde8e87cb7b3be0e0bc9e72c3634f108570cac3e.tar.gz emacs-bde8e87cb7b3be0e0bc9e72c3634f108570cac3e.zip | |
Fix treesit-indent-region
* lisp/treesit.el (treesit-simple-indent-presets): Remove extra comma.
(treesit--indent-1): Return (ANCHOR . OFFSET) instead of column.
(treesit-indent): Accept (ANCHOR . OFFSET) from treesit--indent-1.
(treesit--indent-region-batch-size): Reduce to 400.
(treesit-indent-region): Put a marker on each line's ANCHOR and
compute the indentation with ANCHOR + OFFSET. Precomputing column
gives wrong indentation when the ANHOR line doesn't have correct
indent yet.
| -rw-r--r-- | lisp/treesit.el | 103 |
1 files changed, 63 insertions, 40 deletions
diff --git a/lisp/treesit.el b/lisp/treesit.el index 264935f1854..22d1fe5f89b 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el | |||
| @@ -724,10 +724,10 @@ See `treesit-simple-indent-presets'.") | |||
| 724 | (and (or (null node-t) | 724 | (and (or (null node-t) |
| 725 | (string-match-p | 725 | (string-match-p |
| 726 | node-t (or (treesit-node-type node) ""))) | 726 | node-t (or (treesit-node-type node) ""))) |
| 727 | (or (null ,parent-t) | 727 | (or (null parent-t) |
| 728 | (string-match-p | 728 | (string-match-p |
| 729 | parent-t (treesit-node-type parent))) | 729 | parent-t (treesit-node-type parent))) |
| 730 | (or (null ,grand-parent-t) | 730 | (or (null grand-parent-t) |
| 731 | (string-match-p | 731 | (string-match-p |
| 732 | grand-parent-t | 732 | grand-parent-t |
| 733 | (treesit-node-type | 733 | (treesit-node-type |
| @@ -941,9 +941,8 @@ of the current line.") | |||
| 941 | 941 | ||
| 942 | (defun treesit--indent-1 () | 942 | (defun treesit--indent-1 () |
| 943 | "Indent the current line. | 943 | "Indent the current line. |
| 944 | Return the column we should indent this line to, or nil if we | 944 | Return (ANCHOR . OFFSET). This function is used by |
| 945 | can't figure it out. This function is used by `treesit-indent' | 945 | `treesit-indent' and `treesit-indent-region'." |
| 946 | and `treesit-indent-region'." | ||
| 947 | ;; Basically holds the common part between the two indent function. | 946 | ;; Basically holds the common part between the two indent function. |
| 948 | (let* ((bol (save-excursion | 947 | (let* ((bol (save-excursion |
| 949 | (forward-line 0) | 948 | (forward-line 0) |
| @@ -960,7 +959,7 @@ and `treesit-indent-region'." | |||
| 960 | smallest-node | 959 | smallest-node |
| 961 | (lambda (node) | 960 | (lambda (node) |
| 962 | (eq bol (treesit-node-start node)))))) | 961 | (eq bol (treesit-node-start node)))))) |
| 963 | (pcase-let* | 962 | (let* |
| 964 | ((parser (if smallest-node | 963 | ((parser (if smallest-node |
| 965 | (treesit-node-parser smallest-node) | 964 | (treesit-node-parser smallest-node) |
| 966 | nil)) | 965 | nil)) |
| @@ -971,29 +970,26 @@ and `treesit-indent-region'." | |||
| 971 | (treesit-node-parent node)) | 970 | (treesit-node-parent node)) |
| 972 | (parser | 971 | (parser |
| 973 | (treesit-node-at bol parser)) | 972 | (treesit-node-at bol parser)) |
| 974 | (t nil))) | 973 | (t nil)))) |
| 975 | (`(,anchor . ,offset) | 974 | (funcall treesit-indent-function node parent bol)))) |
| 976 | (funcall treesit-indent-function node parent bol))) | ||
| 977 | (if (or (null anchor) (null offset)) | ||
| 978 | nil | ||
| 979 | (+ (save-excursion | ||
| 980 | (goto-char anchor) | ||
| 981 | (current-column)) | ||
| 982 | offset))))) | ||
| 983 | 975 | ||
| 984 | (defun treesit-indent () | 976 | (defun treesit-indent () |
| 985 | "Indent according to the result of `treesit-indent-function'." | 977 | "Indent according to the result of `treesit-indent-function'." |
| 986 | (treesit-update-ranges) | 978 | (treesit-update-ranges) |
| 987 | (let* ((orig-pos (point)) | 979 | (pcase-let* ((orig-pos (point)) |
| 988 | (bol (current-indentation)) | 980 | (bol (current-indentation)) |
| 989 | (col (treesit--indent-1))) | 981 | (`(,anchor . ,offset) (treesit--indent-1))) |
| 990 | (when col | 982 | (when (and anchor offset) |
| 991 | (if (< bol orig-pos) | 983 | (let ((col (+ (save-excursion |
| 992 | (save-excursion | 984 | (goto-char anchor) |
| 993 | (indent-line-to col)) | 985 | (current-column)) |
| 994 | (indent-line-to col))))) | 986 | offset))) |
| 995 | 987 | (if (< bol orig-pos) | |
| 996 | (defvar treesit--indent-region-batch-size 1000 | 988 | (save-excursion |
| 989 | (indent-line-to col)) | ||
| 990 | (indent-line-to col)))))) | ||
| 991 | |||
| 992 | (defvar treesit--indent-region-batch-size 400 | ||
| 997 | "How many lines of indent value do we precompute. | 993 | "How many lines of indent value do we precompute. |
| 998 | In `treesit-indent-region' we indent in batches: precompute | 994 | In `treesit-indent-region' we indent in batches: precompute |
| 999 | indent for each line, apply them in one go, let parser reparse, | 995 | indent for each line, apply them in one go, let parser reparse, |
| @@ -1004,34 +1000,61 @@ reparse after indenting every single line.") | |||
| 1004 | "Indent the region between BEG and END. | 1000 | "Indent the region between BEG and END. |
| 1005 | Similar to `treesit-indent', but indent a region instead." | 1001 | Similar to `treesit-indent', but indent a region instead." |
| 1006 | (treesit-update-ranges) | 1002 | (treesit-update-ranges) |
| 1007 | (let ((indents (make-vector treesit--indent-region-batch-size 0)) | 1003 | (let* ((meta-len 2) |
| 1008 | (lines-left-to-move 0) | 1004 | (vector-len (* meta-len treesit--indent-region-batch-size)) |
| 1009 | (idx 0) | 1005 | ;; This vector saves the indent meta for each line in the |
| 1010 | (jdx 0) | 1006 | ;; batch. It is a vector of [ANCHOR OFFSET BOL DELTA], where |
| 1011 | (starting-pos 0) | 1007 | ;; BOL is the position of BOL of that line, and DELTA = |
| 1012 | (announce-progress (> (- end beg) 80000))) | 1008 | ;; DESIRED-INDENT - CURRENT-INDENT. |
| 1009 | (meta-vec (make-vector vector-len 0)) | ||
| 1010 | (lines-left-to-move 0) | ||
| 1011 | (end (copy-marker end t)) | ||
| 1012 | (idx 0) | ||
| 1013 | (starting-pos 0) | ||
| 1014 | (announce-progress (> (- end beg) 80000))) | ||
| 1013 | (save-excursion | 1015 | (save-excursion |
| 1014 | (goto-char beg) | 1016 | (goto-char beg) |
| 1017 | ;; First pass. Go through each line and compute the | ||
| 1018 | ;; indentation. | ||
| 1015 | (while (and (eq lines-left-to-move 0) (< (point) end)) | 1019 | (while (and (eq lines-left-to-move 0) (< (point) end)) |
| 1016 | (setq idx 0 jdx 0 | 1020 | (setq idx 0 |
| 1017 | starting-pos (point)) | 1021 | starting-pos (point)) |
| 1018 | (while (and (eq lines-left-to-move 0) | 1022 | (while (and (eq lines-left-to-move 0) |
| 1019 | (< idx treesit--indent-region-batch-size) | 1023 | (< idx treesit--indent-region-batch-size) |
| 1020 | (< (point) end)) | 1024 | (< (point) end)) |
| 1021 | (setf (aref indents idx) (or (treesit--indent-1) 0)) | 1025 | (pcase-let* ((`(,anchor . ,offset) (treesit--indent-1)) |
| 1026 | (marker (aref meta-vec (* idx meta-len)))) | ||
| 1027 | ;; Set ANCHOR. | ||
| 1028 | (when anchor | ||
| 1029 | (if (markerp marker) | ||
| 1030 | (move-marker marker anchor) | ||
| 1031 | (setf (aref meta-vec (* idx meta-len)) | ||
| 1032 | (copy-marker anchor t)))) | ||
| 1033 | ;; SET OFFSET. | ||
| 1034 | (setf (aref meta-vec (+ 1 (* idx meta-len))) offset)) | ||
| 1022 | (cl-incf idx) | 1035 | (cl-incf idx) |
| 1023 | (setq lines-left-to-move (forward-line 1))) | 1036 | (setq lines-left-to-move (forward-line 1))) |
| 1024 | ;; Now IDX = last valid IDX + 1. | 1037 | ;; Now IDX = last valid IDX + 1. |
| 1025 | (goto-char starting-pos) | 1038 | (goto-char starting-pos) |
| 1026 | (while (< jdx idx) | 1039 | ;; Second pass, go to each line and apply the indentation. |
| 1027 | (let ((col (aref indents jdx))) | 1040 | (dotimes (jdx idx) |
| 1028 | (when (not (eq col 0)) | 1041 | (let ((anchor (aref meta-vec (* jdx meta-len))) |
| 1029 | (indent-line-to col))) | 1042 | (offset (aref meta-vec (+ 1 (* jdx meta-len))))) |
| 1030 | (forward-line 1) | 1043 | (when offset |
| 1031 | (cl-incf jdx)) | 1044 | (let ((col (save-excursion |
| 1045 | (goto-char anchor) | ||
| 1046 | (+ offset (current-column))))) | ||
| 1047 | (indent-line-to col)))) | ||
| 1048 | (forward-line 1)) | ||
| 1032 | (when announce-progress | 1049 | (when announce-progress |
| 1033 | (message "Indenting region...%s%%" | 1050 | (message "Indenting region...%s%%" |
| 1034 | (/ (* (- (point) beg) 100) (- end beg)))))))) | 1051 | (/ (* (- (point) beg) 100) (- end beg))))) |
| 1052 | ;; Delete markers. | ||
| 1053 | (dotimes (idx treesit--indent-region-batch-size) | ||
| 1054 | (let ((marker (aref meta-vec (* idx meta-len)))) | ||
| 1055 | (when (markerp marker) | ||
| 1056 | (move-marker marker nil)))) | ||
| 1057 | (move-marker end nil)))) | ||
| 1035 | 1058 | ||
| 1036 | (defun treesit-simple-indent (node parent bol) | 1059 | (defun treesit-simple-indent (node parent bol) |
| 1037 | "Calculate indentation according to `treesit-simple-indent-rules'. | 1060 | "Calculate indentation according to `treesit-simple-indent-rules'. |