dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

go-rename.el (4031B)


      1 ;;; go-rename.el --- Integration of the 'gorename' tool into Emacs.
      2 
      3 ;; Copyright 2014 The Go Authors. All rights reserved.
      4 ;; Use of this source code is governed by a BSD-style
      5 ;; license that can be found in the LICENSE file.
      6 
      7 ;; Version: 0.1
      8 ;; Package-Requires: ((go-mode "1.3.1"))
      9 ;; Keywords: tools
     10 
     11 ;;; Commentary:
     12 
     13 ;; To install:
     14 
     15 ;; % go get golang.org/x/tools/cmd/gorename
     16 ;; % go build golang.org/x/tools/cmd/gorename
     17 ;; % mv gorename $HOME/bin/         # or elsewhere on $PATH
     18 
     19 ;; The go-rename-command variable can be customized to specify an
     20 ;; alternative location for the installed command.
     21 
     22 ;;; Code:
     23 
     24 (require 'cl-lib)
     25 (require 'compile)
     26 (require 'go-mode)
     27 (require 'thingatpt)
     28 
     29 (defgroup go-rename nil
     30   "Options specific to the Go rename."
     31   :group 'go)
     32 
     33 (defcustom go-rename-command "gorename"
     34   "The `gorename' command; by the default, $PATH is searched."
     35   :type 'string
     36   :group 'go-rename)
     37 
     38 ;;;###autoload
     39 (defun go-rename (new-name &optional force)
     40   "Rename the entity denoted by the identifier at point, using
     41 the `gorename' tool. With FORCE, call `gorename' with the
     42 `-force' flag."
     43   (interactive (list
     44                 (if (and buffer-file-name (not (buffer-modified-p)))
     45                   (read-string "New name: " (thing-at-point 'symbol)))
     46                 current-prefix-arg))
     47   (if (not buffer-file-name)
     48       (error "Cannot use go-rename on a buffer without a file name"))
     49   ;; It's not sufficient to save the current buffer if modified,
     50   ;; since if gofmt-before-save is on the before-save-hook,
     51   ;; saving will disturb the selected region.
     52   (if (buffer-modified-p)
     53       (error "Please save the current buffer before invoking go-rename"))
     54   ;; Prompt-save all other modified Go buffers, since they might get written.
     55   (save-some-buffers nil #'(lambda ()
     56               (and (buffer-file-name)
     57                    (string= (file-name-extension (buffer-file-name)) ".go"))))
     58   (let* ((posflag (format "-offset=%s:#%d"
     59                           buffer-file-name
     60                           (1- (position-bytes (point)))))
     61          (env-vars (go-root-and-paths))
     62          (goroot-env (concat "GOROOT=" (car env-vars)))
     63          (gopath-env (concat "GOPATH=" (mapconcat #'identity (cdr env-vars) ":")))
     64          success)
     65     (with-current-buffer (get-buffer-create "*go-rename*")
     66       (setq buffer-read-only nil)
     67       (erase-buffer)
     68       (let ((args (append (list go-rename-command nil t nil posflag "-to" new-name) (if force '("-force")))))
     69         ;; Log the command to *Messages*, for debugging.
     70         (message "Command: %s:" args)
     71         (message "Running gorename...")
     72         ;; Use dynamic binding to modify/restore the environment
     73         (setq success (zerop (let ((process-environment (cl-list* goroot-env gopath-env process-environment)))
     74           (apply #'call-process args))))
     75       (insert "\n")
     76       (compilation-mode)
     77       (setq compilation-error-screen-columns nil)
     78 
     79       ;; On success, print the one-line result in the message bar,
     80       ;; and hide the *go-rename* buffer.
     81       (if success
     82           (progn
     83             (message "%s" (go--buffer-string-no-trailing-space))
     84             (gofmt--kill-error-buffer (current-buffer)))
     85         ;; failure
     86         (let ((w (display-buffer (current-buffer))))
     87           (message "gorename exited")
     88           (set-window-point w (point-min)))))))
     89 
     90   ;; Reload the modified files, saving line/col.
     91   ;; (Don't restore the point since the text has changed.)
     92   ;;
     93   ;; TODO(adonovan): should we also do this for all other files
     94   ;; that were updated (the tool can print them)?
     95   (let ((line (line-number-at-pos))
     96         (col (current-column)))
     97     (revert-buffer t t t) ; safe, because we just saved it
     98     (goto-char (point-min))
     99     (forward-line (1- line))
    100     (forward-char col)))
    101 
    102 
    103 (defun go--buffer-string-no-trailing-space ()
    104   (replace-regexp-in-string "[\t\n ]*\\'"
    105                             ""
    106                             (buffer-substring (point-min) (point-max))))
    107 
    108 (provide 'go-rename)
    109 
    110 ;;; go-rename.el ends here