[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/go-mode cfaa193 348/495: cmd/guru: rename oracle to guru,
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/go-mode cfaa193 348/495: cmd/guru: rename oracle to guru, copying it to a single package |
Date: |
Sat, 7 Aug 2021 09:05:45 -0400 (EDT) |
branch: elpa/go-mode
commit cfaa193487c9b053880d18da3670d243f021d4b0
Author: Alan Donovan <adonovan@google.com>
Commit: Dominik Honnef <dominik@honnef.co>
cmd/guru: rename oracle to guru, copying it to a single package
See plans at:
https://docs.google.com/document/d/1UErU12vR7jTedYvKHVNRzGPmXqdMASZ6PfE7B-p6sIg/edit#heading=h.t5rbcuy7di7j
Change-Id: I369747e0ce8cd42a2975eb0f651a2e5fba47cf9e
Reviewed-on: https://go-review.googlesource.com/19475
Reviewed-by: Alan Donovan <adonovan@google.com>
---
guru_import/cmd/guru/guru.el | 230 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 230 insertions(+)
diff --git a/guru_import/cmd/guru/guru.el b/guru_import/cmd/guru/guru.el
new file mode 100644
index 0000000..e33c30c
--- /dev/null
+++ b/guru_import/cmd/guru/guru.el
@@ -0,0 +1,230 @@
+;;;
+;;; Integration of the Go 'guru' analysis tool into Emacs.
+;;;
+;;; To install the Go guru, run:
+;;; % export GOROOT=... GOPATH=...
+;;; % go get golang.org/x/tools/cmd/guru
+;;; % mv $GOPATH/bin/guru $GOROOT/bin/
+;;;
+;;; Load this file into Emacs and set go-guru-scope to your
+;;; configuration. Then, find a file of Go source code, enable
+;;; go-guru-mode, select an expression of interest, and press `C-c C-o d'
+;;; (for "describe") or run one of the other go-guru-xxx commands.
+;;;
+;;; TODO(adonovan): simplify installation and configuration by making
+;;; guru a subcommand of 'go tool'.
+
+(require 'compile)
+(require 'go-mode)
+(require 'cl)
+
+(defgroup go-guru nil
+ "Options specific to the Go guru."
+ :group 'go)
+
+(defcustom go-guru-command "guru"
+ "The Go guru command."
+ :type 'string
+ :group 'go-guru)
+
+(defcustom go-guru-scope ""
+ "The scope of the analysis. See `go-guru-set-scope'."
+ :type 'string
+ :group 'go-guru)
+
+(defvar go-guru--scope-history
+ nil
+ "History of values supplied to `go-guru-set-scope'.")
+
+;; Extend go-mode-map.
+(let ((m go-mode-map))
+ (define-key m (kbd "C-c C-o t") #'go-guru-describe) ; t for type
+ (define-key m (kbd "C-c C-o f") #'go-guru-freevars)
+ (define-key m (kbd "C-c C-o g") #'go-guru-callgraph)
+ (define-key m (kbd "C-c C-o i") #'go-guru-implements)
+ (define-key m (kbd "C-c C-o c") #'go-guru-peers) ; c for channel
+ (define-key m (kbd "C-c C-o r") #'go-guru-referrers)
+ (define-key m (kbd "C-c C-o d") #'go-guru-definition)
+ (define-key m (kbd "C-c C-o p") #'go-guru-pointsto)
+ (define-key m (kbd "C-c C-o s") #'go-guru-callstack)
+ (define-key m (kbd "C-c C-o <") #'go-guru-callers)
+ (define-key m (kbd "C-c C-o >") #'go-guru-callees)
+ (define-key m (kbd "<f5>") #'go-guru-describe)
+ (define-key m (kbd "<f6>") #'go-guru-referrers))
+
+;; TODO(dominikh): Rethink set-scope some. Setting it to a file is
+;; painful because it doesn't use find-file, and variables/~ aren't
+;; expanded. Setting it to an import path is somewhat painful because
+;; it doesn't make use of go-mode's import path completion. One option
+;; would be having two different functions, but then we can't
+;; automatically call it when no scope has been set. Also it wouldn't
+;; easily allow specifying more than one file/package.
+(defun go-guru-set-scope ()
+ "Set the scope for the Go guru, prompting the user to edit the
+previous scope.
+
+The scope specifies a set of arguments, separated by spaces.
+It may be:
+1) a set of packages whose main() functions will be analyzed.
+2) a list of *.go filenames; they will treated like as a single
+ package (see #3).
+3) a single package whose main() function and/or Test* functions
+ will be analyzed.
+
+In the common case, this is similar to the argument(s) you would
+specify to 'go build'."
+ (interactive)
+ (let ((scope (read-from-minibuffer "Go guru scope: "
+ go-guru-scope
+ nil
+ nil
+ 'go-guru--scope-history)))
+ (if (string-equal "" scope)
+ (error "You must specify a non-empty scope for the Go guru"))
+ (setq go-guru-scope scope)))
+
+(defun go-guru--run (mode &optional need-scope)
+ "Run the Go guru in the specified MODE, passing it the
+selected region of the current buffer. If NEED-SCOPE, prompt for
+a scope if not already set. Process the output to replace each
+file name with a small hyperlink. Display the result."
+ (if (not buffer-file-name)
+ (error "Cannot use guru on a buffer without a file name"))
+ ;; It's not sufficient to save a modified buffer 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 buffer before invoking go-guru"))
+ (and need-scope
+ (string-equal "" go-guru-scope)
+ (go-guru-set-scope))
+ (let* ((filename (file-truename buffer-file-name))
+ (posflag (if (use-region-p)
+ (format "-pos=%s:#%d,#%d"
+ filename
+ (1- (go--position-bytes (region-beginning)))
+ (1- (go--position-bytes (region-end))))
+ (format "-pos=%s:#%d"
+ filename
+ (1- (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)
":"))))
+ (with-current-buffer (get-buffer-create "*go-guru*")
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (insert "Go Guru\n")
+ (let ((args (append (list go-guru-command nil t nil posflag mode)
+ (split-string go-guru-scope " " t))))
+ ;; Log the command to *Messages*, for debugging.
+ (message "Command: %s:" args)
+ (message nil) ; clears/shrinks minibuffer
+
+ (message "Running guru...")
+ ;; Use dynamic binding to modify/restore the environment
+ (let ((process-environment (list* goroot-env gopath-env
process-environment)))
+ (apply #'call-process args)))
+ (insert "\n")
+ (compilation-mode)
+ (setq compilation-error-screen-columns nil)
+
+ ;; Hide the file/line info to save space.
+ ;; Replace each with a little widget.
+ ;; compilation-mode + this loop = slooow.
+ ;; TODO(adonovan): have guru give us JSON
+ ;; and we'll do the markup directly.
+ (let ((buffer-read-only nil)
+ (p 1))
+ (while (not (null p))
+ (let ((np (compilation-next-single-property-change p
'compilation-message)))
+ (if np
+ (when (equal (line-number-at-pos p) (line-number-at-pos np))
+ ;; Using a fixed width greatly improves readability, so
+ ;; if the filename is longer than 20, show
".../last/17chars.go".
+ ;; This usually includes the last segment of the package
name.
+ ;; Don't show the line or column number.
+ (let* ((loc (buffer-substring p np)) ;
"/home/foo/go/pkg/file.go:1:2-3:4"
+ (i (search ":" loc)))
+ (setq loc (cond
+ ((null i) "...")
+ ((>= i 17) (concat "..." (substring loc (- i
17) i)))
+ (t (substring loc 0 i))))
+ ;; np is (typically) the space following ":"; consume it
too.
+ (put-text-property p np 'display (concat loc ":")))
+ (goto-char np)
+ (insert " ")
+ (incf np))) ; so we don't get stuck (e.g. on a panic stack
dump)
+ (setq p np)))
+ (message nil))
+
+ (let ((w (display-buffer (current-buffer))))
+ (balance-windows)
+ (shrink-window-if-larger-than-buffer w)
+ (set-window-point w (point-min))))))
+
+(defun go-guru-callees ()
+ "Show possible callees of the function call at the current point."
+ (interactive)
+ (go-guru--run "callees" t))
+
+(defun go-guru-callers ()
+ "Show the set of callers of the function containing the current point."
+ (interactive)
+ (go-guru--run "callers" t))
+
+(defun go-guru-callgraph ()
+ "Show the callgraph of the current program."
+ (interactive)
+ (go-guru--run "callgraph" t))
+
+(defun go-guru-callstack ()
+ "Show an arbitrary path from a root of the call graph to the
+function containing the current point."
+ (interactive)
+ (go-guru--run "callstack" t))
+
+(defun go-guru-definition ()
+ "Show the definition of the selected identifier."
+ (interactive)
+ (go-guru--run "definition"))
+
+(defun go-guru-describe ()
+ "Describe the selected syntax, its kind, type and methods."
+ (interactive)
+ (go-guru--run "describe"))
+
+(defun go-guru-pointsto ()
+ "Show what the selected expression points to."
+ (interactive)
+ (go-guru--run "pointsto" t))
+
+(defun go-guru-implements ()
+ "Describe the 'implements' relation for types in the package
+containing the current point."
+ (interactive)
+ (go-guru--run "implements"))
+
+(defun go-guru-freevars ()
+ "Enumerate the free variables of the current selection."
+ (interactive)
+ (go-guru--run "freevars"))
+
+(defun go-guru-peers ()
+ "Enumerate the set of possible corresponding sends/receives for
+this channel receive/send operation."
+ (interactive)
+ (go-guru--run "peers" t))
+
+(defun go-guru-referrers ()
+ "Enumerate all references to the object denoted by the selected
+identifier."
+ (interactive)
+ (go-guru--run "referrers"))
+
+(defun go-guru-whicherrs ()
+ "Show globals, constants and types to which the selected
+expression (of type 'error') may refer."
+ (interactive)
+ (go-guru--run "whicherrs" t))
+
+(provide 'go-guru)
- [nongnu] elpa/go-mode 6e8373e 267/495: go-goto-docstring: handle empty comments, (continued)
- [nongnu] elpa/go-mode 6e8373e 267/495: go-goto-docstring: handle empty comments, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d1ebde8 271/495: Rename go--get-function-name to go--function-name, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode eddbcff 277/495: Make sure we're looking at func keyword, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 45a8131 284/495: Implement go--goto-opening-curly-brace as in go-end-of-defun, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d6aa01a 287/495: Merge branch 'movement', ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 27b7415 293/495: Allow passing additional arguments to gofmt, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 1214f77 294/495: Bind go-goto-map to C-f, not C-g, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 17bd2b2 296/495: Add GOPATH detection, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 9f785cc 298/495: Document stability of the master branch, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode f8b4bf9 300/495: Add to beginning of compilation-error-regexp-alist, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode cfaa193 348/495: cmd/guru: rename oracle to guru, copying it to a single package,
ELPA Syncer <=
- [nongnu] elpa/go-mode 4d1ab9f 347/495: cmd/oracle: improve error messages, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 9c2bf9b 360/495: cmd/guru: emacs: push mark in go-guru-definition, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 5ef1d53 355/495: cmd/guru: use byte (not rune) count in -modified archive, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 60ed26e 368/495: cmd/guru: emacs: only check modified buffers with file names, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode d209550 353/495: cmd/guru: emacs: minor changes to keybindings, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 6ac5669 372/495: cmd/guru: emacs: interpret byte offsets correctly, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode afb2a24 382/495: go.tools: use golang.org/x/... import paths, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 3a82342 379/495: Regenerate AUTHORS, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode 8991b83 384/495: refactor/rename: emacs: kill go-rename buffer correctly, ELPA Syncer, 2021/08/07
- [nongnu] elpa/go-mode adea2e5 395/495: Make go-guru-build-tags a list of strings, ELPA Syncer, 2021/08/07