1
0
mirror of https://github.com/golang/go synced 2024-10-01 10:38:33 -06:00
go/refactor/rename/rename.el
Dominik Honnef 9c7ccd869c refactor/rename: emacs: kill go-rename buffer correctly
Match gofmt's behaviour of closing the status buffer. Don't display the
buffer in case of success as we were going to hide it instantly again,
anyway. Also, instead of using delete-window, use
gofmt--kill-error-buffer. gofmt--kill-error-buffer uses quit-window if
there's a window for the buffer, kill-buffer otherwise.

quit-window only deletes the window if it was created explicitly for the
status buffer and if it is still displaying it. This way, we won't close
windows that the user created or repurposed himself.

Additionally, this change ensures that we don't leave a *go-rename*
buffer lying around when gorename succeeded.

Fixes golang/go#10972.

Change-Id: Id1efb60d399f0062d870e925138aa827e12f3e58
Reviewed-on: https://go-review.googlesource.com/10453
Reviewed-by: Alan Donovan <adonovan@google.com>
2015-05-29 16:50:48 +00:00

95 lines
3.7 KiB
EmacsLisp

;;; Copyright 2014 The Go Authors. All rights reserved.
;;; Use of this source code is governed by a BSD-style
;;; license that can be found in the LICENSE file.
;;;
;;; Integration of the 'gorename' tool into Emacs.
;;;
;;; To install:
;;; % go get golang.org/x/tools/cmd/gorename
;;; % go build golang.org/x/tools/cmd/gorename
;;; % mv gorename $HOME/bin/ # or elsewhere on $PATH
;;;
;;; The go-rename-command variable can be customized to specify an
;;; alternative location for the installed command.
(require 'compile)
(require 'go-mode)
(require 'thingatpt)
(defgroup go-rename nil
"Options specific to the Go rename."
:group 'go)
(defcustom go-rename-command "gorename"
"The `gorename' command; by the default, $PATH is searched."
:type 'string
:group 'go-rename)
(defun go-rename (new-name &optional force)
"Rename the entity denoted by the identifier at point, using
the `gorename' tool. With FORCE, call `gorename' with the
`-force' flag."
(interactive (list (read-string "New name: " (thing-at-point 'symbol))
current-prefix-arg))
(if (not buffer-file-name)
(error "Cannot use go-rename on a buffer without a file name"))
;; It's not sufficient to save the current buffer if modified,
;; since if gofmt-before-save is on the before-save-hook,
;; saving will disturb the selected region.
(if (buffer-modified-p)
(error "Please save the current buffer before invoking go-rename"))
;; Prompt-save all other modified Go buffers, since they might get written.
(save-some-buffers nil #'(lambda ()
(and (buffer-file-name)
(string= (file-name-extension (buffer-file-name)) ".go"))))
(let* ((posflag (format "-offset=%s:#%d"
buffer-file-name
(1- (go--position-bytes (point)))))
(env-vars (go-root-and-paths))
(goroot-env (concat "GOROOT=" (car env-vars)))
(gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":")))
success)
(with-current-buffer (get-buffer-create "*go-rename*")
(setq buffer-read-only nil)
(erase-buffer)
(let ((args (append (list go-rename-command nil t nil posflag "-to" new-name) (if force '("-force")))))
;; Log the command to *Messages*, for debugging.
(message "Command: %s:" args)
(message "Running gorename...")
;; Use dynamic binding to modify/restore the environment
(setq success (zerop (let ((process-environment (list* goroot-env gopath-env process-environment)))
(apply #'call-process args))))
(insert "\n")
(compilation-mode)
(setq compilation-error-screen-columns nil)
;; On success, print the one-line result in the message bar,
;; and hide the *go-rename* buffer.
(if success
(progn
(message "%s" (go--buffer-string-no-trailing-space))
(gofmt--kill-error-buffer (current-buffer)))
;; failure
(let ((w (display-buffer (current-buffer))))
(message "gorename exited")
(shrink-window-if-larger-than-buffer w)
(set-window-point w (point-min)))))))
;; Reload the modified files, saving line/col.
;; (Don't restore the point since the text has changed.)
;;
;; TODO(adonovan): should we also do this for all other files
;; that were updated (the tool can print them)?
(let ((line (line-number-at-pos))
(col (current-column)))
(revert-buffer t t t) ; safe, because we just saved it
(goto-char (point-min))
(forward-line (1- line))
(forward-char col)))
(defun go--buffer-string-no-trailing-space ()
(replace-regexp-in-string "[\t\n ]*\\'"
""
(buffer-substring (point-min) (point-max))))