[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/rust-mode a36c96a 435/486: integrate rustfmt error message
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/rust-mode a36c96a 435/486: integrate rustfmt error messages |
Date: |
Sat, 7 Aug 2021 09:26:09 -0400 (EDT) |
branch: elpa/rust-mode
commit a36c96ab556ddf9cd098ab0109acfdd94b106675
Author: Nikodemus Siivola <nikodemus@random-state.net>
Commit: Nathan Moreau <nathan.moreau@m4x.org>
integrate rustfmt error messages
If rustfmt reports an error, by default display it in the message
area and jump to the location. (custom rust-format-goto-problem)
Optionally display the *rustfmt* buffer when rustfmt reports an error.
(custom rust-format-show-buffer)
---
rust-mode.el | 132 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 108 insertions(+), 24 deletions(-)
diff --git a/rust-mode.el b/rust-mode.el
index 919ec8e..0245527 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -198,6 +198,18 @@ to the function arguments. When nil, `->' will be
indented one level."
:safe #'booleanp
:group 'rust-mode)
+(defcustom rust-format-show-buffer nil
+ "Show *rustfmt* buffer if formatting detected problems."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'rust-mode)
+
+(defcustom rust-format-goto-problem t
+ "Jump to location of first detected probem when formatting buffer."
+ :type 'boolean
+ :safe #'booleanp
+ :group 'rust-mode)
+
(defcustom rust-rustfmt-bin "rustfmt"
"Path to rustfmt executable."
:type 'string
@@ -1455,13 +1467,76 @@ This is written mainly to be used as
`end-of-defun-function' for Rust."
(copy-to-buffer buf (point-min) (point-max)))
(erase-buffer)
(insert-file-contents tmpf)
+ (rust--format-fix-rustfmt-buffer (buffer-name buf))
(error "Rustfmt could not format some lines, see *rustfmt* buffer
for details"))
(t
(erase-buffer)
(insert-file-contents tmpf)
+ (rust--format-fix-rustfmt-buffer (buffer-name buf))
(error "Rustfmt failed, see *rustfmt* buffer for details"))))
(delete-file tmpf))))
+;; Since we run rustfmt through stdin we get <stdin> markers in the
+;; output. This replaces them with the buffer name instead.
+(defun rust--format-fix-rustfmt-buffer (buffer-name)
+ (with-current-buffer (get-buffer "*rustfmt*")
+ (goto-char (point-min))
+ (while (re-search-forward "--> <stdin>:")
+ (replace-match (format "--> %s:" buffer-name)))))
+
+;; If rust-mode has been configured to navigate to source of the error
+;; or display it, do so -- and return true. Otherwise return nil to
+;; indicate nothing was done.
+(defun rust--format-error-handler ()
+ (let ((ok nil))
+ (when rust-format-show-buffer
+ (display-buffer (get-buffer "*rustfmt*"))
+ (setq ok t))
+ (when rust-format-goto-problem
+ (rust-goto-format-problem)
+ (setq ok t))
+ ok))
+
+(defun rust-goto-format-problem ()
+ "Jumps to problem reported by rustfmt, if any.
+
+In case of multiple problems cycles through them. Displays the
+rustfmt complain in the echo area."
+ (interactive)
+ ;; This uses position in *rustfmt* buffer to know which is the next
+ ;; error to jump to, and source: line in the buffer to figure which
+ ;; buffer it is from.
+ (let ((rustfmt (get-buffer "*rustfmt*")))
+ (if (not rustfmt)
+ (message "No *rustfmt*, no problems.")
+ (let ((target-buffer (with-current-buffer rustfmt
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "--> \\([^:]+\\):")
+ (match-string 1)))))
+ (target-point (with-current-buffer rustfmt
+ ;; No save-excursion, this is how we cycle through!
+ (let ((regex "-->
[^:]+:\\([0-9]+\\):\\([0-9]+\\)"))
+ (when (or (re-search-forward regex nil t)
+ (progn (goto-char (point-min))
+ (re-search-forward regex nil
t)))
+ (cons (string-to-number (match-string 1))
+ (string-to-number (match-string 2)))))))
+ (target-problem (with-current-buffer rustfmt
+ (save-excursion
+ (when (re-search-backward "^error:.+\n" nil t)
+ (forward-char (length "error: "))
+ (let ((p0 (point)))
+ (if (re-search-forward "\nerror:.+\n" nil
t)
+ (buffer-substring p0 (point))
+ (buffer-substring p0 (point-max)))))))))
+ (when (and target-buffer target-point)
+ (switch-to-buffer target-buffer)
+ (goto-char (point-min))
+ (forward-line (1- (car target-point)))
+ (forward-char (1- (cdr target-point))))
+ (message target-problem)))))
+
(defconst rust--format-word "\
\\b\\(else\\|enum\\|fn\\|for\\|if\\|let\\|loop\\|\
match\\|struct\\|union\\|unsafe\\|while\\)\\b")
@@ -1606,28 +1681,31 @@ Return the created process."
(rust--format-get-loc buffer start)
(rust--format-get-loc buffer point))
window-loc))))))
- (unwind-protect
- ;; save and restore window start position
- ;; after reformatting
- ;; to avoid the disturbing scrolling
- (let ((w-start (window-start)))
- (rust--format-call (current-buffer))
- (set-window-start (selected-window) w-start))
- (dolist (loc buffer-loc)
- (let* ((buffer (pop loc))
- (pos (rust--format-get-pos buffer (pop loc))))
- (with-current-buffer buffer
- (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))))
- (unless (eq buffer current)
- (set-window-start window start))
- (set-window-point window pos)))))
-
- (message "Formatted buffer with rustfmt."))
+ (condition-case err
+ (unwind-protect
+ ;; save and restore window start position
+ ;; after reformatting
+ ;; to avoid the disturbing scrolling
+ (let ((w-start (window-start)))
+ (rust--format-call (current-buffer))
+ (set-window-start (selected-window) w-start)
+ (message "Formatted buffer with rustfmt."))
+ (dolist (loc buffer-loc)
+ (let* ((buffer (pop loc))
+ (pos (rust--format-get-pos buffer (pop loc))))
+ (with-current-buffer buffer
+ (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))))
+ (unless (eq buffer current)
+ (set-window-start window start))
+ (set-window-point window pos))))
+ (error
+ (or (rust--format-error-handler)
+ (signal (car err) (cdr err)))))))
(defun rust-enable-format-on-save ()
"Enable formatting using rustfmt when saving buffer."
@@ -1658,6 +1736,7 @@ Return the created process."
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-f") 'rust-format-buffer)
(define-key map (kbd "C-c C-d") 'rust-dbg-wrap-or-unwrap)
+ (define-key map (kbd "C-c C-n") 'rust-goto-format-problem)
map)
"Keymap for Rust major mode.")
@@ -1736,8 +1815,13 @@ Return the created process."
(defun rust-after-save-hook ()
(when rust-format-on-save
- (unless (executable-find rust-rustfmt-bin)
- (error "Could not locate executable \"%s\"" rust-rustfmt-bin))))
+ (if (not (executable-find rust-rustfmt-bin))
+ (error "Could not locate executable \"%s\"" rust-rustfmt-bin)
+ (when (get-buffer "*rustfmt*")
+ ;; KLDUGE: re-run the error handlers -- otherwise message area
+ ;; would show "Wrote ..." instead of the error description.
+ (or (rust--format-error-handler)
+ (message "rustfmt detected problems, see *rustfmt* for more."))))))
(defvar rustc-compilation-regexps
(let ((file "\\([^\n]+\\)")
- [nongnu] elpa/rust-mode a364b24 445/486: Make *rustfmt* buffer readonly., (continued)
- [nongnu] elpa/rust-mode a364b24 445/486: Make *rustfmt* buffer readonly., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 15a077a 458/486: rustc-colon-compilation-regexps: improve highlighting., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 00177f5 461/486: compile-mode integration: add link to code references. (#391), ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 5585cf9 477/486: rust-mode: Cosmetics, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 3fa8f0b 479/486: Add non-empty commentary section, slightly reword summary, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 7ff04a8 337/486: Merge pull request #234 from jjwest/master, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 70ff9a0 421/486: electric-pair-mode: prevent self-insert of `>' when already inserted. (#337), ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 4fd637c 428/486: rust-insert-dbg: handle the case of string literals. (#342), ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 844bb51 429/486: add support for "async fn", ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 63ec74c 434/486: Enforce use of spaces for indentation and cleanup whitespace (#353), ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode a36c96a 435/486: integrate rustfmt error messages,
ELPA Syncer <=
- [nongnu] elpa/rust-mode 8665005 436/486: Introduce constant for *rustfmt*., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 08d7141 449/486: README: support for emacs 24 has been dropped., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 1603a25 455/486: Change 'rust-build' to 'rust-compile' in README.md, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 6e4835c 456/486: Update README.md, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 5dc219f 465/486: rearrange III: Mode, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode beda16d 466/486: rearrange IV: Misc, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode f9e3618 468/486: Divide library into sections, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode e9e9e32 472/486: Add release build/run functions, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode e006788 474/486: Add .dir-locals.el, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 7fdb9c2 450/486: Use <kbd> to indicate keyboard input in README (#375), ELPA Syncer, 2021/08/07