From 00b8b1eb95b8e621c9a6db8c4b2c3cfcd700ea85 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 12 Feb 2016 00:04:56 -0500 Subject: [PATCH] cmd/guru: clean ups to command-line interface -pos is now a positional argument; -scope is now a flag. Tidy up usage message. Update Vim and Emacs scripts and test Remove call to GOMAXPROCS. Use log.{SetPrefix,SetFlags} and Fatalf Change-Id: I3786ed83aecb17d622b29d2a538a374f813f0adc Reviewed-on: https://go-review.googlesource.com/19438 Reviewed-by: Michael Matloob --- cmd/guru/emacs-test.bash | 5 +-- cmd/guru/guru.el | 28 ++++++------ cmd/guru/guru.vim | 8 ++-- cmd/guru/main.go | 92 ++++++++++++++++------------------------ 4 files changed, 55 insertions(+), 78 deletions(-) diff --git a/cmd/guru/emacs-test.bash b/cmd/guru/emacs-test.bash index 154a1f7c..8dcc8b75 100755 --- a/cmd/guru/emacs-test.bash +++ b/cmd/guru/emacs-test.bash @@ -26,15 +26,14 @@ mv -f $GOPATH/bin/guru $GOROOT/bin/ $GOROOT/bin/guru >$log 2>&1 || true # (prints usage and exits 1) grep -q "Run.*help" $log || die "$GOROOT/bin/guru not installed" - # Run Emacs, set the scope to the guru tool itself, # load ./main.go, and describe the "fmt" import. emacs --batch --no-splash --no-window-system --no-init \ - --load $GOROOT/misc/emacs/go-mode.el \ + --load $GOPATH/src/github.com/dominikh/go-mode.el/go-mode.el \ --load $thisdir/guru.el \ --eval ' (progn - (setq go-guru-scope "golang.org/x/tools/cmd/guru") + (princ (emacs-version)) ; requires Emacs v23 (find-file "'$thisdir'/main.go") (search-forward "\"fmt\"") (backward-char) diff --git a/cmd/guru/guru.el b/cmd/guru/guru.el index e33c30c7..d00f44c6 100644 --- a/cmd/guru/guru.el +++ b/cmd/guru/guru.el @@ -2,20 +2,16 @@ ;;; 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/ +;;; $ go get golang.org/x/tools/cmd/guru ;;; ;;; 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 'simple) (require 'cl) (defgroup go-guru nil @@ -99,14 +95,14 @@ file name with a small hyperlink. Display the result." (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)))))) + (posn (if (use-region-p) + (format "%s:#%d,#%d" + filename + (1- (go--position-bytes (region-beginning))) + (1- (go--position-bytes (region-end)))) + (format "%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) ":")))) @@ -114,8 +110,8 @@ file name with a small hyperlink. Display the result." (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)))) + (let ((args (list go-guru-command nil t nil + "-scope" go-guru-scope mode posn))) ;; Log the command to *Messages*, for debugging. (message "Command: %s:" args) (message nil) ; clears/shrinks minibuffer diff --git a/cmd/guru/guru.vim b/cmd/guru/guru.vim index ab96fef1..aab37d73 100644 --- a/cmd/guru/guru.vim +++ b/cmd/guru/guru.vim @@ -68,14 +68,14 @@ func! s:RunGuru(mode, selected) range abort if a:selected != -1 let pos1 = s:getpos(line("'<"), col("'<")) let pos2 = s:getpos(line("'>"), col("'>")) - let cmd = printf('%s -pos=%s:#%d,#%d %s %s', + let cmd = printf('%s -scope=\'%s\' %s %s:#%d,#%d', \ s:go_guru, - \ shellescape(fname), pos1, pos2, a:mode, shellescape(sname)) + \ shellescape(fname), shellescape(sname), a:mode, pos1, pos2) else let pos = s:getpos(line('.'), col('.')) - let cmd = printf('%s -pos=%s:#%d %s %s', + let cmd = printf('%s -scope=\'%s\' %s %s:#%d', \ s:go_guru, - \ shellescape(fname), pos, a:mode, shellescape(sname)) + \ shellescape(fname), shellescape(sname), a:mode, pos) endif call s:qflist(system(cmd)) endfun diff --git a/cmd/guru/main.go b/cmd/guru/main.go index ed338d1b..0aa30ee3 100644 --- a/cmd/guru/main.go +++ b/cmd/guru/main.go @@ -21,23 +21,20 @@ import ( "io" "log" "os" - "runtime" "runtime/pprof" + "strings" "golang.org/x/tools/go/buildutil" - "golang.org/x/tools/go/loader" ) -var posFlag = flag.String("pos", "", - "Filename and byte offset or extent of a syntax element about which to query, "+ - "e.g. foo.go:#123,#456, bar.go:#123.") - -var ptalogFlag = flag.String("ptalog", "", - "Location of the points-to analysis log file, or empty to disable logging.") - -var formatFlag = flag.String("format", "plain", "Output format. One of {plain,json,xml}.") - -var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).") +// flags +var ( + scopeFlag = flag.String("scope", "", "comma-separated list of `packages` to which the analysis should be limited (default=all)") + ptalogFlag = flag.String("ptalog", "", "write points-to analysis log to `file`") + formatFlag = flag.String("format", "plain", "output `format`; one of {plain,json,xml}") + reflectFlag = flag.Bool("reflect", false, "analyze reflection soundly (slow)") + cpuprofileFlag = flag.String("cpuprofile", "", "write CPU profile to `file`") +) func init() { flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc) @@ -46,15 +43,7 @@ func init() { const useHelp = "Run 'guru -help' for more information.\n" const helpMessage = `Go source code guru. -Usage: guru [ ...] ... - -The -format flag controls the output format: - plain an editor-friendly format in which every line of output - is of the form "pos: text", where pos is "-" if unknown. - json structured data in JSON syntax. - xml structured data in XML syntax. - -The -pos flag is required in all modes. +Usage: guru [flags] The mode argument determines the query to perform: @@ -71,29 +60,24 @@ The mode argument determines the query to perform: what show basic information about the selected syntax node whicherrs show possible values of the selected error variable -The user manual is available here: http://golang.org/s/guru-user-manual +The position argument specifies the filename and byte offset (or range) +of the syntax element to query. For example: -Examples: + foo.go:#123,#128 + bar.go:#123 -Describe the syntax at offset 530 in this file (an import spec): -% guru -pos=src/golang.org/x/tools/cmd/guru/main.go:#530 describe \ - golang.org/x/tools/cmd/guru +The -format flag controls the output format: + plain an editor-friendly format in which every line of output + is of the form "pos: text", where pos is "-" if unknown. + json structured data in JSON syntax. + xml structured data in XML syntax. -` + loader.FromArgsUsage +User manual: http://golang.org/s/oracle-user-manual -var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") +Example: describe syntax at offset 530 in this file (an import spec): -func init() { - // If $GOMAXPROCS isn't set, use the full capacity of the machine. - // For small machines, use at least 4 threads. - if os.Getenv("GOMAXPROCS") == "" { - n := runtime.NumCPU() - if n < 4 { - n = 4 - } - runtime.GOMAXPROCS(n) - } -} + $ guru describe src/golang.org/x/tools/cmd/guru/main.go:#530 +` func printHelp() { fmt.Fprintln(os.Stderr, helpMessage) @@ -102,6 +86,9 @@ func printHelp() { } func main() { + log.SetPrefix("guru: ") + log.SetFlags(0) + // Don't print full help unless -help was requested. // Just gently remind users that it's there. flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) } @@ -115,13 +102,12 @@ func main() { } args := flag.Args() - if len(args) == 0 || args[0] == "" { - fmt.Fprint(os.Stderr, "guru: a mode argument is required.\n"+useHelp) + if len(args) != 2 { + flag.Usage() os.Exit(2) } + mode, posn := args[0], args[1] - mode := args[0] - args = args[1:] if mode == "help" { printHelp() os.Exit(2) @@ -147,8 +133,8 @@ func main() { } // Profiling support. - if *cpuprofile != "" { - f, err := os.Create(*cpuprofile) + if *cpuprofileFlag != "" { + f, err := os.Create(*cpuprofileFlag) if err != nil { log.Fatal(err) } @@ -161,23 +147,21 @@ func main() { case "json", "plain", "xml": // ok default: - fmt.Fprintf(os.Stderr, "guru: illegal -format value: %q.\n"+useHelp, *formatFlag) - os.Exit(2) + log.Fatalf("illegal -format value: %q.\n"+useHelp, *formatFlag) } // Ask the guru. query := Query{ Mode: mode, - Pos: *posFlag, + Pos: posn, Build: &build.Default, - Scope: args, + Scope: strings.Split(*scopeFlag, ","), PTALog: ptalog, Reflection: *reflectFlag, } if err := Run(&query); err != nil { - fmt.Fprintf(os.Stderr, "guru: %s\n", err) - os.Exit(1) + log.Fatal(err) } // Print the result. @@ -185,16 +169,14 @@ func main() { case "json": b, err := json.MarshalIndent(query.Serial(), "", "\t") if err != nil { - fmt.Fprintf(os.Stderr, "guru: JSON error: %s\n", err) - os.Exit(1) + log.Fatalf("JSON error: %s", err) } os.Stdout.Write(b) case "xml": b, err := xml.MarshalIndent(query.Serial(), "", "\t") if err != nil { - fmt.Fprintf(os.Stderr, "guru: XML error: %s\n", err) - os.Exit(1) + log.Fatalf("XML error: %s", err) } os.Stdout.Write(b)