diff --git a/rust-mode-tests.el b/rust-mode-tests.el index 259afb2..4c970c4 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 d93bd0a..b0b0ae1 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 "\\_" 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 "\\_" 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