emacs: add a "godoc" command, like M-x man

This runs godoc and displays its output in a new buffer.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5268041
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 271677b..e099214 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -541,4 +541,49 @@
  (interactive)
  (when (eq major-mode 'go-mode) (gofmt)))
 
+
+(defun godoc-read-query ()
+  "Read a godoc query from the minibuffer."
+  ;; Compute the default query as the symbol under the cursor.
+  ;; TODO: This does the wrong thing for e.g. multipart.NewReader (it only grabs
+  ;; half) but I see no way to disambiguate that from e.g. foobar.SomeMethod.
+  (let* ((bounds (bounds-of-thing-at-point 'symbol))
+         (symbol (if bounds
+                     (buffer-substring-no-properties (car bounds)
+                                                     (cdr bounds)))))
+    (read-string (if symbol
+                     (format "godoc (default %s): " symbol)
+                   "godoc: ")
+                 nil nil symbol)))
+
+(defun godoc-get-buffer (query)
+  "Get an empty buffer for a godoc query."
+  (let* ((buffer-name (concat "*godoc " query "*"))
+         (buffer (get-buffer buffer-name)))
+    ;; Kill the existing buffer if it already exists.
+    (when buffer (kill-buffer buffer))
+    (get-buffer-create buffer-name)))
+
+(defun godoc-buffer-sentinel (proc event)
+  "Sentinel function run when godoc command completes."
+  (with-current-buffer (process-buffer proc)
+    (cond ((string= event "finished\n")  ;; Successful exit.
+           (goto-char (point-min))
+           (display-buffer (current-buffer) 'not-this-window))
+          ((not (= (process-exit-status proc) 0))  ;; Error exit.
+           (let ((output (buffer-string)))
+             (kill-buffer (current-buffer))
+             (message (concat "godoc: " output)))))))
+
+;;;###autoload
+(defun godoc (query)
+  "Show go documentation for a query, much like M-x man."
+  (interactive (list (godoc-read-query)))
+  (unless (string= query "")
+    (set-process-sentinel
+     (start-process-shell-command "godoc" (godoc-get-buffer query)
+                                  (concat "godoc " query))
+     'godoc-buffer-sentinel)
+    nil))
+
 (provide 'go-mode)