mirror of https://github.com/golang/go.git
internal/tool: implement structured help command
'gopls help cmd...' is redirected to 'gopls cmd... -h'. The tool.Run operation for each subcommand already has logic to show the usage message when it parses a -h flag. Examples: $ gopls help $ gopls help remote $ gopls help remote sessions Fixes golang/go#52598 Change-Id: I5135c6e7b130d839f880d0613534ac08de199bcf Reviewed-on: https://go-review.googlesource.com/c/tools/+/403677 Run-TryBot: Alan Donovan <adonovan@google.com> Reviewed-by: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
d27d783e99
commit
45c8a71312
|
|
@ -245,6 +245,7 @@ func (app *Application) mainCommands() []tool.Application {
|
|||
&app.Serve,
|
||||
&version{app: app},
|
||||
&bug{app: app},
|
||||
&help{app: app},
|
||||
&apiJSON{app: app},
|
||||
&licenses{app: app},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,57 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/browser"
|
||||
"golang.org/x/tools/internal/lsp/debug"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/tool"
|
||||
)
|
||||
|
||||
// help implements the help command.
|
||||
type help struct {
|
||||
app *Application
|
||||
}
|
||||
|
||||
func (h *help) Name() string { return "help" }
|
||||
func (h *help) Parent() string { return h.app.Name() }
|
||||
func (h *help) Usage() string { return "" }
|
||||
func (h *help) ShortHelp() string { return "print usage information for subcommands" }
|
||||
func (h *help) DetailedHelp(f *flag.FlagSet) {
|
||||
fmt.Fprint(f.Output(), `
|
||||
|
||||
Examples:
|
||||
$ gopls help # main gopls help message
|
||||
$ gopls help remote # help on 'remote' command
|
||||
$ gopls help remote sessions # help on 'remote sessions' subcommand
|
||||
`)
|
||||
printFlagDefaults(f)
|
||||
}
|
||||
|
||||
// Run prints help information about a subcommand.
|
||||
func (h *help) Run(ctx context.Context, args ...string) error {
|
||||
find := func(cmds []tool.Application, name string) tool.Application {
|
||||
for _, cmd := range cmds {
|
||||
if cmd.Name() == name {
|
||||
return cmd
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find the subcommand denoted by args (empty => h.app).
|
||||
var cmd tool.Application = h.app
|
||||
for i, arg := range args {
|
||||
cmd = find(getSubcommands(cmd), arg)
|
||||
if cmd == nil {
|
||||
return tool.CommandLineErrorf(
|
||||
"no such subcommand: %s", strings.Join(args[:i+1], " "))
|
||||
}
|
||||
}
|
||||
|
||||
// 'gopls help cmd subcmd' is equivalent to 'gopls cmd subcmd -h'.
|
||||
// The flag package prints the usage information (defined by tool.Run)
|
||||
// when it sees the -h flag.
|
||||
fs := flag.NewFlagSet(cmd.Name(), flag.ExitOnError)
|
||||
return tool.Run(ctx, fs, h.app, append(args[:len(args):len(args)], "-h"))
|
||||
}
|
||||
|
||||
// version implements the version command.
|
||||
type version struct {
|
||||
JSON bool `flag:"json" help:"outputs in json format."`
|
||||
|
|
|
|||
|
|
@ -42,3 +42,18 @@ func (s subcommands) Run(ctx context.Context, args ...string) error {
|
|||
}
|
||||
return tool.CommandLineErrorf("unknown subcommand %v", command)
|
||||
}
|
||||
|
||||
func (s subcommands) Commands() []tool.Application { return s }
|
||||
|
||||
// getSubcommands returns the subcommands of a given Application.
|
||||
func getSubcommands(a tool.Application) []tool.Application {
|
||||
// This interface is satisfied both by tool.Applications
|
||||
// that embed subcommands, and by *cmd.Application.
|
||||
type hasCommands interface {
|
||||
Commands() []tool.Application
|
||||
}
|
||||
if sub, ok := a.(hasCommands); ok {
|
||||
return sub.Commands()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
print usage information for subcommands
|
||||
|
||||
Usage:
|
||||
gopls [flags] help
|
||||
|
||||
|
||||
Examples:
|
||||
$ gopls help # main gopls help message
|
||||
$ gopls help remote # help on 'remote' command
|
||||
$ gopls help remote sessions # help on 'remote sessions' subcommand
|
||||
|
|
@ -14,6 +14,7 @@ Main
|
|||
serve run a server for Go code using the Language Server Protocol
|
||||
version print the gopls version information
|
||||
bug report a bug in gopls
|
||||
help print usage information for subcommands
|
||||
api-json print json describing gopls API
|
||||
licenses print licenses of included software
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ func Main(ctx context.Context, app Application, args []string) {
|
|||
if err := Run(ctx, s, app, args); err != nil {
|
||||
fmt.Fprintf(s.Output(), "%s: %v\n", app.Name(), err)
|
||||
if _, printHelp := err.(commandLineError); printHelp {
|
||||
// TODO(adonovan): refine this. It causes
|
||||
// any command-line error to result in the full
|
||||
// usage message, which typically obscures
|
||||
// the actual error.
|
||||
s.Usage()
|
||||
}
|
||||
os.Exit(2)
|
||||
|
|
|
|||
Loading…
Reference in New Issue