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 <matloob@golang.org>
This commit is contained in:
parent
789265387f
commit
00b8b1eb95
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 [<flag> ...] <mode> <args> ...
|
||||
|
||||
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] <mode> <position>
|
||||
|
||||
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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue