[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/go-mode 856eff3 105/495: Instead of relying on gofmt's -d
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/go-mode 856eff3 105/495: Instead of relying on gofmt's -d flag, use diff -n directly. This |
Date: |
Sat, 7 Aug 2021 09:04:53 -0400 (EDT) |
branch: elpa/go-mode
commit 856eff3eafaa04fa6d1d54fbc1fd06558449e21a
Author: Dominik Honnef <dominikh@fork-bomb.org>
Commit: Dominik Honnef <dominikh@fork-bomb.org>
Instead of relying on gofmt's -d flag, use diff -n directly. This
allows us to implement our own patch function instead of having to use
diff-mode.
This fixes two issues:
- no more skipping over changes
- no more problems with whitespace in file names
---
go-mode.el | 149 +++++++++++++++++++++++++------------------------------------
1 file changed, 62 insertions(+), 87 deletions(-)
diff --git a/go-mode.el b/go-mode.el
index 4b0de54..8d65fe9 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -5,13 +5,11 @@
;; license that can be found in the LICENSE file.
(require 'cl)
-(require 'diff-mode)
(require 'ffap)
(require 'find-lisp)
(require 'url)
(defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]")
-(defconst gofmt-stdin-tag "<standard input>")
(defconst go-identifier-regexp "[[:word:][:multibyte:]_]+")
(defconst go-label-regexp go-identifier-regexp)
(defconst go-type-regexp "[[:word:][:multibyte:]_*]+")
@@ -360,99 +358,76 @@ recommended that you look at goflymake
;;;###autoload
(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode))
+(defun go--apply-rcs-patch (patch-buffer)
+ (let ((target-buffer (current-buffer))
+ (line-offset 0))
+ (save-excursion
+ (with-current-buffer patch-buffer
+ (goto-char (point-min))
+ (while (not (eobp))
+ (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)")
+ (error "invalid rcs patch or internal error in
go--apply-rcs-patch"))
+ (forward-line)
+ (let ((action (match-string 1))
+ (from (string-to-number (match-string 2)))
+ (len (string-to-number (match-string 3))))
+ (cond
+ ((equal action "a")
+ (let ((start (point)))
+ (forward-line len)
+ (let ((text (buffer-substring start (point))))
+ (with-current-buffer target-buffer
+ (decf line-offset len)
+ (goto-char (point-min))
+ (forward-line (- from len line-offset))
+ (insert text)))))
+ ((equal action "d")
+ (with-current-buffer target-buffer
+ (goto-char (point-min))
+ (forward-line (- from line-offset 1))
+ (incf line-offset len)
+ (kill-whole-line len)))
+ (t
+ (error "invalid rcs patch or internal error in
go--apply-rcs-patch")))))))))
+
(defun gofmt ()
- "Pipe the current buffer through the external tool `gofmt`.
-Replace the current buffer on success; display errors on failure."
+ "Formats the current buffer according to the gofmt tool."
(interactive)
- (let ((currconf (current-window-configuration)))
- (let ((srcbuf (current-buffer))
- (filename buffer-file-name)
- (patchbuf (get-buffer-create "*Gofmt patch*")))
- (with-current-buffer patchbuf
- (let ((errbuf (get-buffer-create "*Gofmt Errors*"))
- ;; use utf-8 with subprocesses
- (coding-system-for-read 'utf-8)
- (coding-system-for-write 'utf-8))
- (with-current-buffer errbuf
- (setq buffer-read-only nil)
- (erase-buffer))
- (with-current-buffer srcbuf
- (save-restriction
- (let (deactivate-mark)
- (widen)
- ;; If this is a new file, diff-mode can't apply a
- ;; patch to a non-exisiting file, so replace the buffer
- ;; completely with the output of 'gofmt'.
- ;; If the file exists, patch it to keep the 'undo' list happy.
- (let* ((newfile (not (file-exists-p filename)))
- (flag (if newfile "" " -d")))
-
- ;; diff-mode doesn't work too well with missing
- ;; end-of-file newline, so add one
- (if (/= (char-after (1- (point-max))) ?\n)
- (save-excursion
- (goto-char (point-max))
- (insert ?\n)))
-
- (if (zerop (shell-command-on-region (point-min) (point-max)
- (concat "gofmt" flag)
- patchbuf nil errbuf))
- ;; gofmt succeeded: replace buffer or apply patch hunks.
- (let ((old-point (point))
- (old-mark (mark t)))
- (kill-buffer errbuf)
- (if newfile
- ;; New file, replace it (diff-mode won't work)
- (gofmt--replace-buffer srcbuf patchbuf)
- ;; Existing file, patch it
- (gofmt--apply-patch filename srcbuf patchbuf))
- (goto-char (min old-point (point-max)))
- ;; Restore the mark and point
- (if old-mark (push-mark (min old-mark (point-max)) t))
- (set-window-configuration currconf))
-
- ;; gofmt failed: display the errors
- (message "Could not apply gofmt. Check errors for details")
- (gofmt--process-errors filename errbuf))))))
-
- ;; Collapse any window opened on outbuf if shell-command-on-region
- ;; displayed it.
- (delete-windows-on patchbuf)))
- (kill-buffer patchbuf))))
-
-(defun gofmt--replace-buffer (srcbuf patchbuf)
- (with-current-buffer srcbuf
- (erase-buffer)
- (insert-buffer-substring patchbuf))
- (message "Applied gofmt"))
-
-(defun gofmt--apply-patch (filename srcbuf patchbuf)
- ;; apply all the patch hunks
- (let (changed)
+ (let ((tmpfile (make-temp-file "gofmt" nil ".go"))
+ (patchbuf (get-buffer-create "*Gofmt patch*"))
+ (errbuf (get-buffer-create "*Gofmt Errors*"))
+ (coding-system-for-read 'utf-8)
+ (coding-system-for-write 'utf-8))
+
+ (with-current-buffer errbuf
+ (setq buffer-read-only nil)
+ (erase-buffer))
(with-current-buffer patchbuf
- (goto-char (point-min))
- ;; The .* is for TMPDIR, but to avoid dealing with TMPDIR
- ;; having a trailing / or not, it's easier to just search for .*
- ;; especially as we're only replacing the first instance.
- (if (re-search-forward "^--- \\(.*/gofmt[0-9]*\\)" nil t)
- (replace-match filename nil nil nil 1))
- (condition-case nil
- (while t
- (diff-hunk-next)
- (diff-apply-hunk)
- (setq changed t))
- ;; When there's no more hunks, diff-hunk-next signals an error, ignore
it
- (error nil)))
- (if changed (message "Applied gofmt") (message "Buffer was already
gofmted"))))
-
-(defun gofmt--process-errors (filename errbuf)
+ (erase-buffer))
+
+ (write-region nil nil tmpfile)
+ (if (zerop (shell-command (concat "gofmt -w " (shell-quote-argument
tmpfile)) nil errbuf))
+ (progn
+ (if (zerop (shell-command-on-region (point-min) (point-max) (concat
"diff -n - " (shell-quote-argument tmpfile)) patchbuf))
+ (message "Buffer is already gofmted")
+ (go--apply-rcs-patch patchbuf)
+ (kill-buffer errbuf)
+ (message "Applied gofmt")))
+ (message "Could not apply gofmt. Check errors for details")
+ (gofmt--process-errors (buffer-file-name) tmpfile errbuf))
+
+ (kill-buffer patchbuf)
+ (delete-file tmpfile)))
+
+
+(defun gofmt--process-errors (filename tmpfile errbuf)
;; Convert the gofmt stderr to something understood by the compilation mode.
(with-current-buffer errbuf
(goto-char (point-min))
(insert "gofmt errors:\n")
- (if (search-forward gofmt-stdin-tag nil t)
- (replace-match (file-name-nondirectory filename) nil t))
+ (while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile)
"\\):") nil t)
+ (replace-match (file-name-nondirectory filename) t t nil 1))
(display-buffer errbuf)
(compilation-mode)))
- [nongnu] elpa/go-mode c833b77 094/495: Fix cache invalidation for dangling operator cache, (continued)
- [nongnu] elpa/go-mode c833b77 094/495: Fix cache invalidation for dangling operator cache, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 87c8b6e 096/495: do not use dangling op cache when buffer is narrowed, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 8e19ae5 097/495: add some documentation, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode b5960fe 099/495: nicer messages in gofmt, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 939d630 100/495: style fixes, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 47b3928 102/495: disable read-only on error buffer before trying to write to it, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode c94ca2e 064/495: refactor, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 6b77ff1 065/495: allow disabling fontification for function/method calls, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 02d44df 067/495: add function for downloading playgrounds into emacs, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode ec6fef4 066/495: Define a customization group for go-mode, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 856eff3 105/495: Instead of relying on gofmt's -d flag, use diff -n directly. This,
ELPA Syncer <=
- [nongnu] elpa/go-mode d5839a0 106/495: use kill-whole-line directly, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode e1bb58a 109/495: Update README because go-mode.el is now upstream, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode b1bb0e0 111/495: replace shell-command-on-region with call-process-region, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 9f1f94e 113/495: use own implementation of go--string-prefix-p because it has been added in Emacs 24 and people are still using Emacs 23, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 22192f7 121/495: use featurep instead of version string to check for xemacs, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 3b0efdd 132/495: docstrings, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 7ab928a 146/495: Add support for methods that have no name for the receiver, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 83de700 145/495: Enable compilation-mode for gofmt error buffer before displaying it, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 59f1cb5 140/495: add elisp header, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode c693232 137/495: mention flymake-go as an alternative to goflymake, ELPA Syncer, 2021/08/07