emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/rust-mode 664c7b0 277/486: improve position recovery in ru


From: ELPA Syncer
Subject: [nongnu] elpa/rust-mode 664c7b0 277/486: improve position recovery in rust-format-buffer
Date: Sat, 7 Aug 2021 09:25:35 -0400 (EDT)

branch: elpa/rust-mode
commit 664c7b037c2fe2e2b2d1c0629835715194b844bb
Author: Trevor Spiteri <tspiteri@ieee.org>
Commit: Trevor Spiteri <tspiteri@ieee.org>

    improve position recovery in rust-format-buffer
---
 rust-mode.el | 145 ++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 103 insertions(+), 42 deletions(-)

diff --git a/rust-mode.el b/rust-mode.el
index 55148f6..cced21c 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -1281,6 +1281,88 @@ This is written mainly to be used as 
`end-of-defun-function' for Rust."
           (kill-buffer))
       (error "Rustfmt failed, see *rustfmt* buffer for details"))))
 
+(defconst rust--format-word 
"\\b\\(else\\|enum\\|fn\\|for\\|if\\|let\\|loop\\|match\\|struct\\|unsafe\\|while\\)\\b")
+(defconst rust--format-line "\\([\n]\\)")
+
+;; Counts number of matches of regex beginning up to max-beginning,
+;; leaving the point at the beginning of the last match.
+(defun rust--format-count (regex max-beginning)
+  (let ((count 0)
+        save-point
+        beginning)
+    (while (and (< (point) max-beginning)
+                (re-search-forward regex max-beginning t))
+      (setq count (1+ count))
+      (setq beginning (match-beginning 1)))
+    ;; try one more in case max-beginning lies in the middle of a match
+    (setq save-point (point))
+    (when (re-search-forward regex nil t)
+      (let ((try-beginning (match-beginning 1)))
+        (if (> try-beginning max-beginning)
+            (goto-char save-point)
+          (setq count (1+ count))
+          (setq beginning try-beginning))))
+    (when beginning (goto-char beginning))
+    count))
+
+;; Gets list describing pos or (point).
+;; The list contains:
+;; 1. the number of matches of rust--format-word,
+;; 2. the number of matches of rust--format-line after that,
+;; 3. the number of columns after that.
+(defun rust--format-get-loc (buffer &optional pos)
+  (with-current-buffer buffer
+    (save-excursion
+      (let ((pos (or pos (point)))
+            words lines columns)
+        (goto-char (point-min))
+        (setq words (rust--format-count rust--format-word pos))
+        (setq lines (rust--format-count rust--format-line pos))
+        (if (> lines 0)
+            (if (= (point) pos)
+                (setq columns -1)
+              (forward-char 1)
+              (goto-char pos)
+              (setq columns (current-column)))
+          (let ((initial-column (current-column)))
+            (goto-char pos)
+            (setq columns (- (current-column) initial-column))))
+        (list words lines columns)))))
+
+;; Moves the point forward by count matches of regex up to max-pos,
+;; and returns new max-pos making sure final position does not include another 
match.
+(defun rust--format-forward (regex count max-pos)
+  (when (< (point) max-pos)
+    (let ((beginning (point)))
+      (while (> count 0)
+        (setq count (1- count))
+        (re-search-forward regex nil t)
+        (setq beginning (match-beginning 1)))
+      (when (re-search-forward regex nil t)
+        (setq max-pos (min max-pos (match-beginning 1))))
+      (goto-char beginning)))
+  max-pos)
+
+;; Gets the position from a location list obtained using rust--format-get-loc.
+(defun rust--format-get-pos (buffer loc)
+  (with-current-buffer buffer
+    (save-excursion
+      (goto-char (point-min))
+      (let ((max-pos (point-max))
+            (words (pop loc))
+            (lines (pop loc))
+            (columns (pop loc)))
+        (setq max-pos (rust--format-forward rust--format-word words max-pos))
+        (setq max-pos (rust--format-forward rust--format-line lines max-pos))
+        (when (> lines 0) (forward-char))
+        (let ((initial-column (current-column))
+              (save-point (point)))
+          (move-end-of-line nil)
+          (when (> (current-column) (+ initial-column columns))
+            (goto-char save-point)
+            (forward-char columns)))
+        (min (point) max-pos)))))
+
 (defun rust-format-buffer ()
   "Format the current buffer using rustfmt."
   (interactive)
@@ -1289,58 +1371,37 @@ This is written mainly to be used as 
`end-of-defun-function' for Rust."
 
   (let* ((current (current-buffer))
          (base (or (buffer-base-buffer current) current))
-         buffer-pos
-         window-pos)
+         buffer-loc
+         window-loc)
     (dolist (buffer (buffer-list))
       (when (or (eq buffer base)
                 (eq (buffer-base-buffer buffer) base))
-        (with-current-buffer buffer
-          (push (list buffer
-                      (line-number-at-pos)
-                      (current-column))
-                buffer-pos))))
+        (push (list buffer
+                    (rust--format-get-loc buffer nil))
+              buffer-loc)))
     (dolist (window (window-list))
       (let ((buffer (window-buffer window)))
         (when (or (eq buffer base)
                   (eq (buffer-base-buffer buffer) base))
           (let ((start (window-start window))
                 (point (window-point window)))
-            (with-current-buffer buffer
-              (push (list window
-                          (line-number-at-pos start)
-                          (save-excursion (goto-char start) (current-column))
-                          (line-number-at-pos point)
-                          (save-excursion (goto-char point) (current-column)))
-                    window-pos))))))
-    (rust--format-call current)
-    (dolist (pos buffer-pos)
-      (let ((buffer (pop pos))
-            (line (pop pos))
-            (column (pop pos)))
+            (push (list window
+                        (rust--format-get-loc buffer start)
+                        (rust--format-get-loc buffer point))
+                  window-loc)))))
+    (rust--format-call (current-buffer))
+    (dolist (loc buffer-loc)
+      (let* ((buffer (pop loc))
+             (pos (rust--format-get-pos buffer (pop loc))))
         (with-current-buffer buffer
-          ;; Move to the same line and column as before.  This is best
-          ;; effort: if rustfmt inserted lines before point, we end up in
-          ;; the wrong place. See issue #162.
-          (goto-char (point-min))
-          (forward-line (1- line))
-          (forward-char column))))
-    (dolist (pos window-pos)
-      (let ((window (pop pos))
-            (start-line (pop pos))
-            (start-column (pop pos))
-            (point-line (pop pos))
-            (point-column (pop pos)))
-        (with-current-buffer (window-buffer window)
-          (let ((start (save-excursion (goto-char (point-min))
-                                       (forward-line (1- start-line))
-                                       (forward-char start-column)
-                                       (point)))
-                (point (save-excursion (goto-char (point-min))
-                                       (forward-line (1- point-line))
-                                       (forward-char point-column)
-                                       (point))))
-            (set-window-start window start)
-            (set-window-point window point))))))
+          (goto-char pos))))
+    (dolist (loc window-loc)
+      (let* ((window (pop loc))
+             (buffer (window-buffer window))
+             (start (rust--format-get-pos buffer (pop loc)))
+             (pos (rust--format-get-pos buffer (pop loc))))
+        (set-window-start window start)
+        (set-window-point window pos))))
 
   ;; Issue #127: Running this on a buffer acts like a revert, and could cause
   ;; the fontification to get out of sync.  Call the same hook to ensure it is



reply via email to

[Prev in Thread] Current Thread [Next in Thread]