From 82d7ac78ab77fed2d35d4b697bfc35d99c27685b Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sun, 4 Jul 2021 18:20:45 +0100 Subject: [PATCH 1/7] Use project-roots on emacs <= 28.0. Based on #257 (@iitalics's work). --- rustic-rustfmt.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 921cfdd5..0564147d 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -8,7 +8,9 @@ (require 'rustic-cargo) -(declare-function project-root "project") +(if (version<= emacs-version "28.0") + (declare-function project-roots "project") + (declare-function project-root "project")) ;;; Options @@ -226,7 +228,9 @@ This is basically a wrapper around `project--buffer-list'." (if (fboundp 'project--buffer-list) (project--buffer-list pr) ;; Like the above function but for releases before Emacs 28. - (let ((root (project-root pr)) + (let ((root (if (version<= emacs-version "28.0") + (car (project-roots pr)) + (project-root pr))) bufs) (dolist (buf (buffer-list)) (let ((filename (or (buffer-file-name buf) From a1ef56f15a047dd85b90f057faa1c04c1774b05f Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sun, 4 Jul 2021 18:21:44 +0100 Subject: [PATCH 2/7] Implement `rustic-format-region`. This unfortunately only works with rustfmt nightly, but it's still an interesting function to have at your disposal. Fixes: #229 --- rustic-rustfmt.el | 29 +++++++++++++++++++++++++++++ test/rustic-format-test.el | 16 ++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 0564147d..244df393 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -105,6 +105,12 @@ and it's `cdr' is a list of arguments." (push (format "%s=%s" key (if (booleanp val) (if val "true" "false") val)) args) (push "--config" args))))) +(defun rustic-compute-rustfmt-file-lines-args (file start end) + "Compute the arguments to rustfmt to modify a particular region." + (list "--unstable-features" + "--file-lines" + (format "[{\"file\":\"%s\",\"range\":[%d,%d]}]" file start end))) + (defun rustic-format-sentinel (proc output) "Sentinel for rustfmt processes when using stdin." (ignore-errors @@ -190,6 +196,29 @@ and it's `cdr' is a list of arguments." (kill-buffer proc-buffer) (message "Workspace formatted with cargo-fmt."))))) +;;;###autoload +(defun rustic-format-region () + "Format the current active region using rustfmt. + +This operation requires a nightly version of rustfmt. +" + (interactive) + (unless (or (eq major-mode 'rustic-mode) + (eq major-mode 'rustic-macro-expansion-mode)) + (error "Not a rustic-mode buffer.")) + (let ((file (buffer-file-name (current-buffer))) + (start (+ 1 (count-lines 1 (region-beginning)))) + (len (- (count-lines (region-beginning) (region-end)) 1))) + (rustic-compilation-process-live t) + (rustic-format-start-process + 'rustic-format-file-sentinel + :buffer (current-buffer) + :command + (append (list rustic-cargo-bin "+nightly" "fmt" "--") + (rustic-compute-rustfmt-file-lines-args file + start + (+ start len)))))) + ;;;###autoload (defun rustic-format-buffer () "Format the current buffer using rustfmt. diff --git a/test/rustic-format-test.el b/test/rustic-format-test.el index 3fbf2e98..fdfff883 100644 --- a/test/rustic-format-test.el +++ b/test/rustic-format-test.el @@ -208,3 +208,19 @@ (revert-buffer t t) (should (string= (buffer-string) formatted-string))) (kill-buffer buffer1)))) + +(ert-deftest rustic-test-format-file () + (let* ((string "fn main() \n{\nlet x = 1;\n}\n") + (formatted-string "fn main() \n{\n let x = 1;\n}\n") + (dir (rustic-babel-generate-project t)) + (main (expand-file-name "main.rs" (concat dir "/src"))) + (buf (get-buffer-create "test"))) + (with-current-buffer buf (write-file main)) + (write-region string nil main nil 0) + (goto-char 13) + (push-mark (buffer-end-position)) + (setq mark-active t) + (rustic-format-region) + (with-temp-buffer + (insert-file-contents main) + (should (string= (buffer-string) formatted-string))))) From 47378ffb2fe43fcbbe608ced146eb601b20e20c8 Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Thu, 8 Jul 2021 23:15:30 +0100 Subject: [PATCH 3/7] Use interactive "r", and check for region. --- rustic-rustfmt.el | 37 +++++++++++++++++++++++-------------- test/rustic-format-test.el | 26 ++++++++++++++------------ 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 244df393..d0d420a0 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -197,27 +197,36 @@ and it's `cdr' is a list of arguments." (message "Workspace formatted with cargo-fmt."))))) ;;;###autoload -(defun rustic-format-region () +(defun rustic-format-region (begin end) "Format the current active region using rustfmt. This operation requires a nightly version of rustfmt. " - (interactive) + (interactive "r") (unless (or (eq major-mode 'rustic-mode) (eq major-mode 'rustic-macro-expansion-mode)) (error "Not a rustic-mode buffer.")) - (let ((file (buffer-file-name (current-buffer))) - (start (+ 1 (count-lines 1 (region-beginning)))) - (len (- (count-lines (region-beginning) (region-end)) 1))) - (rustic-compilation-process-live t) - (rustic-format-start-process - 'rustic-format-file-sentinel - :buffer (current-buffer) - :command - (append (list rustic-cargo-bin "+nightly" "fmt" "--") - (rustic-compute-rustfmt-file-lines-args file - start - (+ start len)))))) + (let* ((buf (current-buffer)) + (file (buffer-file-name buf)) + (r-begin) + (r-end)) + (cond ((region-active-p) + (setq r-begin begin) + (setq r-end end)) + (t + (setq r-begin (region-beginning)) + (setq r-end (region-end)))) + (let ((start (+ 1 (count-lines 1 r-begin))) + (len (- (count-lines r-begin r-end) 1))) + (rustic-compilation-process-live t) + (rustic-format-start-process + 'rustic-format-file-sentinel + :buffer buf + :command + (append (list rustic-cargo-bin "+nightly" "fmt" "--") + (rustic-compute-rustfmt-file-lines-args file + start + (+ start len))))))) ;;;###autoload (defun rustic-format-buffer () diff --git a/test/rustic-format-test.el b/test/rustic-format-test.el index fdfff883..8f886cc9 100644 --- a/test/rustic-format-test.el +++ b/test/rustic-format-test.el @@ -209,18 +209,20 @@ (should (string= (buffer-string) formatted-string))) (kill-buffer buffer1)))) -(ert-deftest rustic-test-format-file () - (let* ((string "fn main() \n{\nlet x = 1;\n}\n") - (formatted-string "fn main() \n{\n let x = 1;\n}\n") +(ert-deftest rustic-test-format-region () + (let* ((buffer1 (get-buffer-create "b1")) + (string "fn main() {\n let x =\n 1;\n}") + (formatted-string "fn main() {\n let x = 1;\n}\n") (dir (rustic-babel-generate-project t)) (main (expand-file-name "main.rs" (concat dir "/src"))) - (buf (get-buffer-create "test"))) - (with-current-buffer buf (write-file main)) - (write-region string nil main nil 0) - (goto-char 13) - (push-mark (buffer-end-position)) - (setq mark-active t) - (rustic-format-region) - (with-temp-buffer - (insert-file-contents main) + (default-directory dir)) + (with-current-buffer buffer1 + (insert string) + (write-file main) + (rustic-mode) + (goto-char 16) + (push-mark 34) + (setq mark-active t) + (rustic-format-region 16 34) + (sit-for 1) (should (string= (buffer-string) formatted-string))))) From 34f0ef7e814921c26dc8c8ec2f2135d99a3551cb Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sat, 10 Jul 2021 20:57:24 +0100 Subject: [PATCH 4/7] Format buffer when no region is active. --- rustic-rustfmt.el | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index d0d420a0..6e9e34a5 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -206,27 +206,20 @@ This operation requires a nightly version of rustfmt. (unless (or (eq major-mode 'rustic-mode) (eq major-mode 'rustic-macro-expansion-mode)) (error "Not a rustic-mode buffer.")) - (let* ((buf (current-buffer)) - (file (buffer-file-name buf)) - (r-begin) - (r-end)) - (cond ((region-active-p) - (setq r-begin begin) - (setq r-end end)) - (t - (setq r-begin (region-beginning)) - (setq r-end (region-end)))) - (let ((start (+ 1 (count-lines 1 r-begin))) - (len (- (count-lines r-begin r-end) 1))) - (rustic-compilation-process-live t) - (rustic-format-start-process - 'rustic-format-file-sentinel - :buffer buf - :command - (append (list rustic-cargo-bin "+nightly" "fmt" "--") - (rustic-compute-rustfmt-file-lines-args file - start - (+ start len))))))) + (if (not (region-active-p)) (rustic-format-buffer) + (let* ((buf (current-buffer)) + (file (buffer-file-name buf))) + (let ((start (+ 1 (count-lines 1 begin))) + (len (- (count-lines begin end) 1))) + (rustic-compilation-process-live t) + (rustic-format-start-process + 'rustic-format-file-sentinel + :buffer buf + :command + (append (list rustic-cargo-bin "+nightly" "fmt" "--") + (rustic-compute-rustfmt-file-lines-args file + start + (+ start len)))))))) ;;;###autoload (defun rustic-format-buffer () From 524923e38efeab566be2751a7cbcca04f7a8d785 Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sat, 10 Jul 2021 21:14:24 +0100 Subject: [PATCH 5/7] Error when nightly toolchain is not available. --- rustic-rustfmt.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 6e9e34a5..840b5a50 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -207,6 +207,8 @@ This operation requires a nightly version of rustfmt. (eq major-mode 'rustic-macro-expansion-mode)) (error "Not a rustic-mode buffer.")) (if (not (region-active-p)) (rustic-format-buffer) + (unless (equal (call-process "cargo" nil nil nil "+nightly") 0) + (error "Need nightly toolchain to format region.")) (let* ((buf (current-buffer)) (file (buffer-file-name buf))) (let ((start (+ 1 (count-lines 1 begin))) From 6ee624c21fae70afa6542009c38b053219e496d4 Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sat, 10 Jul 2021 21:20:18 +0100 Subject: [PATCH 6/7] Remove unnecessary 'let'. --- rustic-rustfmt.el | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 840b5a50..4c4788e6 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -210,18 +210,18 @@ This operation requires a nightly version of rustfmt. (unless (equal (call-process "cargo" nil nil nil "+nightly") 0) (error "Need nightly toolchain to format region.")) (let* ((buf (current-buffer)) - (file (buffer-file-name buf))) - (let ((start (+ 1 (count-lines 1 begin))) - (len (- (count-lines begin end) 1))) - (rustic-compilation-process-live t) - (rustic-format-start-process - 'rustic-format-file-sentinel - :buffer buf - :command - (append (list rustic-cargo-bin "+nightly" "fmt" "--") - (rustic-compute-rustfmt-file-lines-args file - start - (+ start len)))))))) + (file (buffer-file-name buf)) + (start (+ 1 (count-lines 1 begin))) + (len (- (count-lines begin end) 1))) + (rustic-compilation-process-live t) + (rustic-format-start-process + 'rustic-format-file-sentinel + :buffer buf + :command + (append (list rustic-cargo-bin "+nightly" "fmt" "--") + (rustic-compute-rustfmt-file-lines-args file + start + (+ start len)))))))) ;;;###autoload (defun rustic-format-buffer () From 1628fcb2e5f6076277cac9aba93cc40dfed1b5eb Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Sun, 11 Jul 2021 00:31:50 +0100 Subject: [PATCH 7/7] Define `rustic--get-line-number`. This helps get the line number at a particular position in the buffer. Some context: https://emacs.stackexchange.com/questions/3821/a-faster-method-to-obtain-line-number-at-pos-in-large-buffers --- rustic-rustfmt.el | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rustic-rustfmt.el b/rustic-rustfmt.el index 4c4788e6..c0ed222d 100644 --- a/rustic-rustfmt.el +++ b/rustic-rustfmt.el @@ -196,6 +196,13 @@ and it's `cdr' is a list of arguments." (kill-buffer proc-buffer) (message "Workspace formatted with cargo-fmt."))))) +(defun rustic--get-line-number (pos) + (let ((line-number 0)) + (save-excursion + (goto-char pos) + (setq line-number (string-to-number (format-mode-line "%l")))) + line-number)) + ;;;###autoload (defun rustic-format-region (begin end) "Format the current active region using rustfmt. @@ -211,8 +218,8 @@ This operation requires a nightly version of rustfmt. (error "Need nightly toolchain to format region.")) (let* ((buf (current-buffer)) (file (buffer-file-name buf)) - (start (+ 1 (count-lines 1 begin))) - (len (- (count-lines begin end) 1))) + (start (rustic--get-line-number begin)) + (finish (rustic--get-line-number end))) (rustic-compilation-process-live t) (rustic-format-start-process 'rustic-format-file-sentinel @@ -221,7 +228,7 @@ This operation requires a nightly version of rustfmt. (append (list rustic-cargo-bin "+nightly" "fmt" "--") (rustic-compute-rustfmt-file-lines-args file start - (+ start len)))))))) + finish)))))) ;;;###autoload (defun rustic-format-buffer ()