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)
|
$GOROOT/bin/guru >$log 2>&1 || true # (prints usage and exits 1)
|
||||||
grep -q "Run.*help" $log || die "$GOROOT/bin/guru not installed"
|
grep -q "Run.*help" $log || die "$GOROOT/bin/guru not installed"
|
||||||
|
|
||||||
|
|
||||||
# Run Emacs, set the scope to the guru tool itself,
|
# Run Emacs, set the scope to the guru tool itself,
|
||||||
# load ./main.go, and describe the "fmt" import.
|
# load ./main.go, and describe the "fmt" import.
|
||||||
emacs --batch --no-splash --no-window-system --no-init \
|
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 \
|
--load $thisdir/guru.el \
|
||||||
--eval '
|
--eval '
|
||||||
(progn
|
(progn
|
||||||
(setq go-guru-scope "golang.org/x/tools/cmd/guru")
|
(princ (emacs-version)) ; requires Emacs v23
|
||||||
(find-file "'$thisdir'/main.go")
|
(find-file "'$thisdir'/main.go")
|
||||||
(search-forward "\"fmt\"")
|
(search-forward "\"fmt\"")
|
||||||
(backward-char)
|
(backward-char)
|
||||||
|
|
|
@ -2,20 +2,16 @@
|
||||||
;;; Integration of the Go 'guru' analysis tool into Emacs.
|
;;; Integration of the Go 'guru' analysis tool into Emacs.
|
||||||
;;;
|
;;;
|
||||||
;;; To install the Go guru, run:
|
;;; To install the Go guru, run:
|
||||||
;;; % export GOROOT=... GOPATH=...
|
;;; $ go get golang.org/x/tools/cmd/guru
|
||||||
;;; % 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
|
;;; Load this file into Emacs and set go-guru-scope to your
|
||||||
;;; configuration. Then, find a file of Go source code, enable
|
;;; 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'
|
;;; 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.
|
;;; (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 'compile)
|
||||||
(require 'go-mode)
|
(require 'go-mode)
|
||||||
|
(require 'simple)
|
||||||
(require 'cl)
|
(require 'cl)
|
||||||
|
|
||||||
(defgroup go-guru nil
|
(defgroup go-guru nil
|
||||||
|
@ -99,12 +95,12 @@ file name with a small hyperlink. Display the result."
|
||||||
(string-equal "" go-guru-scope)
|
(string-equal "" go-guru-scope)
|
||||||
(go-guru-set-scope))
|
(go-guru-set-scope))
|
||||||
(let* ((filename (file-truename buffer-file-name))
|
(let* ((filename (file-truename buffer-file-name))
|
||||||
(posflag (if (use-region-p)
|
(posn (if (use-region-p)
|
||||||
(format "-pos=%s:#%d,#%d"
|
(format "%s:#%d,#%d"
|
||||||
filename
|
filename
|
||||||
(1- (go--position-bytes (region-beginning)))
|
(1- (go--position-bytes (region-beginning)))
|
||||||
(1- (go--position-bytes (region-end))))
|
(1- (go--position-bytes (region-end))))
|
||||||
(format "-pos=%s:#%d"
|
(format "%s:#%d"
|
||||||
filename
|
filename
|
||||||
(1- (position-bytes (point))))))
|
(1- (position-bytes (point))))))
|
||||||
(env-vars (go-root-and-paths))
|
(env-vars (go-root-and-paths))
|
||||||
|
@ -114,8 +110,8 @@ file name with a small hyperlink. Display the result."
|
||||||
(setq buffer-read-only nil)
|
(setq buffer-read-only nil)
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert "Go Guru\n")
|
(insert "Go Guru\n")
|
||||||
(let ((args (append (list go-guru-command nil t nil posflag mode)
|
(let ((args (list go-guru-command nil t nil
|
||||||
(split-string go-guru-scope " " t))))
|
"-scope" go-guru-scope mode posn)))
|
||||||
;; Log the command to *Messages*, for debugging.
|
;; Log the command to *Messages*, for debugging.
|
||||||
(message "Command: %s:" args)
|
(message "Command: %s:" args)
|
||||||
(message nil) ; clears/shrinks minibuffer
|
(message nil) ; clears/shrinks minibuffer
|
||||||
|
|
|
@ -68,14 +68,14 @@ func! s:RunGuru(mode, selected) range abort
|
||||||
if a:selected != -1
|
if a:selected != -1
|
||||||
let pos1 = s:getpos(line("'<"), col("'<"))
|
let pos1 = s:getpos(line("'<"), col("'<"))
|
||||||
let pos2 = 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,
|
\ s:go_guru,
|
||||||
\ shellescape(fname), pos1, pos2, a:mode, shellescape(sname))
|
\ shellescape(fname), shellescape(sname), a:mode, pos1, pos2)
|
||||||
else
|
else
|
||||||
let pos = s:getpos(line('.'), col('.'))
|
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,
|
\ s:go_guru,
|
||||||
\ shellescape(fname), pos, a:mode, shellescape(sname))
|
\ shellescape(fname), shellescape(sname), a:mode, pos)
|
||||||
endif
|
endif
|
||||||
call s:qflist(system(cmd))
|
call s:qflist(system(cmd))
|
||||||
endfun
|
endfun
|
||||||
|
|
|
@ -21,23 +21,20 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/buildutil"
|
"golang.org/x/tools/go/buildutil"
|
||||||
"golang.org/x/tools/go/loader"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var posFlag = flag.String("pos", "",
|
// flags
|
||||||
"Filename and byte offset or extent of a syntax element about which to query, "+
|
var (
|
||||||
"e.g. foo.go:#123,#456, bar.go:#123.")
|
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`")
|
||||||
var ptalogFlag = flag.String("ptalog", "",
|
formatFlag = flag.String("format", "plain", "output `format`; one of {plain,json,xml}")
|
||||||
"Location of the points-to analysis log file, or empty to disable logging.")
|
reflectFlag = flag.Bool("reflect", false, "analyze reflection soundly (slow)")
|
||||||
|
cpuprofileFlag = flag.String("cpuprofile", "", "write CPU profile to `file`")
|
||||||
var formatFlag = flag.String("format", "plain", "Output format. One of {plain,json,xml}.")
|
)
|
||||||
|
|
||||||
var reflectFlag = flag.Bool("reflect", false, "Analyze reflection soundly (slow).")
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
|
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 useHelp = "Run 'guru -help' for more information.\n"
|
||||||
|
|
||||||
const helpMessage = `Go source code guru.
|
const helpMessage = `Go source code guru.
|
||||||
Usage: guru [<flag> ...] <mode> <args> ...
|
Usage: guru [flags] <mode> <position>
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
The mode argument determines the query to perform:
|
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
|
what show basic information about the selected syntax node
|
||||||
whicherrs show possible values of the selected error variable
|
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):
|
The -format flag controls the output format:
|
||||||
% guru -pos=src/golang.org/x/tools/cmd/guru/main.go:#530 describe \
|
plain an editor-friendly format in which every line of output
|
||||||
golang.org/x/tools/cmd/guru
|
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() {
|
$ guru describe src/golang.org/x/tools/cmd/guru/main.go:#530
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printHelp() {
|
func printHelp() {
|
||||||
fmt.Fprintln(os.Stderr, helpMessage)
|
fmt.Fprintln(os.Stderr, helpMessage)
|
||||||
|
@ -102,6 +86,9 @@ func printHelp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
log.SetPrefix("guru: ")
|
||||||
|
log.SetFlags(0)
|
||||||
|
|
||||||
// Don't print full help unless -help was requested.
|
// Don't print full help unless -help was requested.
|
||||||
// Just gently remind users that it's there.
|
// Just gently remind users that it's there.
|
||||||
flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) }
|
flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) }
|
||||||
|
@ -115,13 +102,12 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
args := flag.Args()
|
args := flag.Args()
|
||||||
if len(args) == 0 || args[0] == "" {
|
if len(args) != 2 {
|
||||||
fmt.Fprint(os.Stderr, "guru: a mode argument is required.\n"+useHelp)
|
flag.Usage()
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
mode, posn := args[0], args[1]
|
||||||
|
|
||||||
mode := args[0]
|
|
||||||
args = args[1:]
|
|
||||||
if mode == "help" {
|
if mode == "help" {
|
||||||
printHelp()
|
printHelp()
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
|
@ -147,8 +133,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profiling support.
|
// Profiling support.
|
||||||
if *cpuprofile != "" {
|
if *cpuprofileFlag != "" {
|
||||||
f, err := os.Create(*cpuprofile)
|
f, err := os.Create(*cpuprofileFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -161,23 +147,21 @@ func main() {
|
||||||
case "json", "plain", "xml":
|
case "json", "plain", "xml":
|
||||||
// ok
|
// ok
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "guru: illegal -format value: %q.\n"+useHelp, *formatFlag)
|
log.Fatalf("illegal -format value: %q.\n"+useHelp, *formatFlag)
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the guru.
|
// Ask the guru.
|
||||||
query := Query{
|
query := Query{
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Pos: *posFlag,
|
Pos: posn,
|
||||||
Build: &build.Default,
|
Build: &build.Default,
|
||||||
Scope: args,
|
Scope: strings.Split(*scopeFlag, ","),
|
||||||
PTALog: ptalog,
|
PTALog: ptalog,
|
||||||
Reflection: *reflectFlag,
|
Reflection: *reflectFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Run(&query); err != nil {
|
if err := Run(&query); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "guru: %s\n", err)
|
log.Fatal(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the result.
|
// Print the result.
|
||||||
|
@ -185,16 +169,14 @@ func main() {
|
||||||
case "json":
|
case "json":
|
||||||
b, err := json.MarshalIndent(query.Serial(), "", "\t")
|
b, err := json.MarshalIndent(query.Serial(), "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "guru: JSON error: %s\n", err)
|
log.Fatalf("JSON error: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
os.Stdout.Write(b)
|
os.Stdout.Write(b)
|
||||||
|
|
||||||
case "xml":
|
case "xml":
|
||||||
b, err := xml.MarshalIndent(query.Serial(), "", "\t")
|
b, err := xml.MarshalIndent(query.Serial(), "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "guru: XML error: %s\n", err)
|
log.Fatalf("XML error: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
os.Stdout.Write(b)
|
os.Stdout.Write(b)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue