branch: elpa/rust-mode
commit 668069ad8b6ca20bd0d2334db1c0d046809affd6
Author: kovan <[email protected]>
Commit: GitHub <[email protected]>
feat: improve rust-toggle-mutability to handle references (#584)
* feat: improve rust-toggle-mutability to handle references
Extends `rust-toggle-mutability` to handle `&` <-> `&mut` and
`&self` <-> `&mut self` in addition to `let` <-> `let mut`.
Closes #194
Co-authored-by: Claude Opus 4.6 <[email protected]>
* test: add tests for rust-toggle-mutability
Co-authored-by: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
rust-mode-tests.el | 36 ++++++++++++++++++++++++++++++++++++
rust-utils.el | 35 +++++++++++++++++++++++++++++------
2 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/rust-mode-tests.el b/rust-mode-tests.el
index 259afb2888..4c970c43b8 100644
--- a/rust-mode-tests.el
+++ b/rust-mode-tests.el
@@ -3809,3 +3809,39 @@ let b = 1;"
(string-match "^C-c C" ,match)))
t))
(should (< 0 match-count)))))
+
+;; Toggle mutability tests
+
+(ert-deftest rust-toggle-mutability-let ()
+ "Test toggling let <-> let mut."
+ (with-temp-buffer
+ (rust-mode)
+ (insert " let x = 5;")
+ (rust-toggle-mutability)
+ (should (string= (buffer-string) " let mut x = 5;"))
+ (rust-toggle-mutability)
+ (should (string= (buffer-string) " let x = 5;"))))
+
+(ert-deftest rust-toggle-mutability-ref ()
+ "Test toggling & <-> &mut."
+ (with-temp-buffer
+ (rust-mode)
+ (insert " let y = & x;")
+ (goto-char (line-end-position))
+ (rust-toggle-mutability)
+ (should (string-match-p "&mut " (buffer-string)))
+ (goto-char (line-end-position))
+ (rust-toggle-mutability)
+ (should (string-match-p "& x" (buffer-string)))))
+
+(ert-deftest rust-toggle-mutability-self ()
+ "Test toggling &self <-> &mut self."
+ (with-temp-buffer
+ (rust-mode)
+ (insert " fn foo(&self) {")
+ (goto-char (line-end-position))
+ (rust-toggle-mutability)
+ (should (string-match-p "&mut self" (buffer-string)))
+ (goto-char (line-end-position))
+ (rust-toggle-mutability)
+ (should (string-match-p "&self" (buffer-string)))))
diff --git a/rust-utils.el b/rust-utils.el
index d93bd0a07f..b0b0ae17c1 100644
--- a/rust-utils.el
+++ b/rust-utils.el
@@ -108,15 +108,38 @@ if not. Move cursor to the end of macro."
)
)
+;;;###autoload
(defun rust-toggle-mutability ()
- "Toggles the mutability of the variable defined on the current line"
+ "Toggle the mutability of the binding or reference near point.
+Handles `let' <-> `let mut' and `&' <-> `&mut' (including `&self')."
(interactive)
(save-excursion
- (back-to-indentation)
- (forward-word)
- (if (string= " mut" (buffer-substring (point) (+ (point) 4)))
- (delete-region (point) (+ (point) 4))
- (insert " mut"))))
+ (let ((line-start (line-beginning-position))
+ (line-end (line-end-position)))
+ (cond
+ ;; Remove: &mut -> &
+ ((search-backward "&mut " line-start t)
+ (forward-char 1)
+ (delete-region (point) (+ (point) 4)))
+ ;; Remove: let mut -> let
+ ((progn (goto-char (line-beginning-position))
+ (re-search-forward "\\_<let mut\\_>" line-end t))
+ (replace-match "let"))
+ ;; Add: & -> &mut
+ ((progn (goto-char (line-end-position))
+ (search-backward "& " line-start t))
+ (forward-char 1)
+ (insert "mut "))
+ ;; Add: &self -> &mut self
+ ((progn (goto-char (line-end-position))
+ (search-backward "&self" line-start t))
+ (forward-char 1)
+ (insert "mut "))
+ ;; Add: let -> let mut
+ ((progn (goto-char (line-beginning-position))
+ (re-search-forward "\\_<let\\_>" line-end t))
+ (insert " mut"))
+ (t (message "No mutable/immutable binding or reference found on this
line"))))))
;;; _
(provide 'rust-utils)
;;; rust-utils.el ends here