summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorDominik Honnef <dominik.honnef@gmail.com>2013-03-19 11:29:28 -0400
committerDominik Honnef <dominik.honnef@gmail.com>2013-03-19 11:29:28 -0400
commit86715d1557942dab5343101fb888d6222375b9e1 (patch)
treea9743eed2e340fb5163633a83f8cabcf7f305ddf /misc
parent68a71094ef91e0380bc84025bb79b6b4571f8603 (diff)
downloadgo-86715d1557942dab5343101fb888d6222375b9e1.tar.gz
misc/emacs: Add support for godef
godef[1][2] is a third party tool for printing information about expressions, especially the location of their definition. This can be used to implement a "jump to definition" function. Unlike cross-language solutions like ctags, godef does not require an index, operates on the Go AST instead of symbols and works across packages, including the standard library. This patch implements two new public functions: godef-describe (C-c C-d) and godef-jump (C-d C-j). godef-describe describes the expression at point, printing its type, and godef-jump jumps to its definition. [1]: https://code.google.com/p/rog-go/source/browse/exp/cmd/godef/ [2]: go get code.google.com/p/rog-go/exp/cmd/godef R=adonovan, cw, patrick.allen.higgins, sameer CC=golang-dev https://codereview.appspot.com/7781043 Committer: Alan Donovan <adonovan@google.com>
Diffstat (limited to 'misc')
-rw-r--r--misc/emacs/go-mode.el73
1 files changed, 73 insertions, 0 deletions
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index b1dd0d5d9..93e2a6867 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -15,6 +15,8 @@
;; - Functions that could be backported but won't because 21.5.32
;; covers them: plenty.
;; - Features that are still partly broken:
+;; - godef will not work correctly if multibyte characters are
+;; being used
;; - Fontification will not handle unicode correctly
;;
;; - Do not use \_< and \_> regexp delimiters directly; use
@@ -163,6 +165,8 @@
(define-key m ":" 'go-mode-insert-and-indent)
(define-key m "=" 'go-mode-insert-and-indent)
(define-key m (kbd "C-c C-a") 'go-import-add)
+ (define-key m (kbd "C-c C-j") 'godef-jump)
+ (define-key m (kbd "C-c C-d") 'godef-describe)
m)
"Keymap used by Go mode to implement electric keys.")
@@ -391,12 +395,26 @@ The following extra functions are defined:
- `go-goto-imports'
- `go-play-buffer' and `go-play-region'
- `go-download-play'
+- `godef-describe' and `godef-jump'
If you want to automatically run `gofmt' before saving a file,
add the following hook to your emacs configuration:
\(add-hook 'before-save-hook 'gofmt-before-save)
+If you want to use `godef-jump' instead of etags (or similar),
+consider binding godef-jump to `M-.', which is the default key
+for `find-tag':
+
+\(add-hook 'go-mode-hook (lambda ()
+ (local-set-key (kbd \"M-.\") 'godef-jump)))
+
+Please note that godef is an external dependency. You can install
+it with
+
+go get code.google.com/p/rog-go/exp/cmd/godef
+
+
If you're looking for even more integration with Go, namely
on-the-fly syntax checking, auto-completion and snippets, it is
recommended that you look at goflymake
@@ -823,4 +841,59 @@ will be commented, otherwise they will be removed completely."
(message "Removed %d imports" (length lines)))
(if flymake-state (flymake-mode-on)))))
+(defun godef--find-file-line-column (specifier)
+ "Given a file name in the format of `filename:line:column',
+visit FILENAME and go to line LINE and column COLUMN."
+ (let* ((components (split-string specifier ":"))
+ (line (string-to-number (nth 1 components)))
+ (column (string-to-number (nth 2 components))))
+ (with-current-buffer (find-file (car components))
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (beginning-of-line)
+ (forward-char (1- column))
+ (if (buffer-modified-p)
+ (message "Buffer is modified, file position might not have been correct")))))
+
+(defun godef--call (point)
+ "Call godef, acquiring definition position and expression
+description at POINT."
+ (if (go--xemacs-p)
+ (message "godef does not reliably work in XEmacs, expect bad results"))
+ (if (not buffer-file-name)
+ (message "Cannot use godef on a buffer without a file name")
+ (let ((outbuf (get-buffer-create "*godef*")))
+ (with-current-buffer outbuf
+ (erase-buffer))
+ (call-process-region (point-min) (point-max) "godef" nil outbuf nil "-i" "-t" "-f" (file-truename buffer-file-name) "-o" (number-to-string (go--position-bytes (point))))
+ (with-current-buffer outbuf
+ (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")))))
+
+(defun godef-describe (point)
+ "Describe the expression at POINT."
+ (interactive "d")
+ (condition-case nil
+ (let ((description (nth 1 (godef--call point))))
+ (if (string= "" description)
+ (message "No description found for expression at point")
+ (message "%s" description)))
+ (file-error (message "Could not run godef binary"))))
+
+(defun godef-jump (point)
+ "Jump to the definition of the expression at POINT."
+ (interactive "d")
+ (condition-case nil
+ (let ((file (car (godef--call point))))
+ (cond
+ ((string= "-" file)
+ (message "godef: expression is not defined anywhere"))
+ ((string= "godef: no identifier found" file)
+ (message "%s" file))
+ ((go--string-prefix-p "godef: no declaration found for " file)
+ (message "%s" file))
+ (t
+ (push-mark)
+ (godef--find-file-line-column file))))
+ (file-error (message "Could not run godef binary"))))
+
(provide 'go-mode)