diff --git a/internal/lsp/cmd/call_hierarchy.go b/internal/lsp/cmd/call_hierarchy.go index 2f870f0c72..3ab925ef4b 100644 --- a/internal/lsp/cmd/call_hierarchy.go +++ b/internal/lsp/cmd/call_hierarchy.go @@ -21,15 +21,16 @@ type callHierarchy struct { } func (c *callHierarchy) Name() string { return "call_hierarchy" } +func (c *callHierarchy) Parent() string { return c.app.Name() } func (c *callHierarchy) Usage() string { return "" } func (c *callHierarchy) ShortHelp() string { return "display selected identifier's call hierarchy" } func (c *callHierarchy) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls call_hierarchy helper/helper.go:8:6 - $ gopls call_hierarchy helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls call_hierarchy helper/helper.go:8:6 + $ gopls call_hierarchy helper/helper.go:#53 `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/check.go b/internal/lsp/cmd/check.go index 42d1976ec3..bd8cb6fa14 100644 --- a/internal/lsp/cmd/check.go +++ b/internal/lsp/cmd/check.go @@ -19,13 +19,14 @@ type check struct { } func (c *check) Name() string { return "check" } +func (c *check) Parent() string { return c.app.Name() } func (c *check) Usage() string { return "" } func (c *check) ShortHelp() string { return "show diagnostic results for the specified file" } func (c *check) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: show the diagnostic results of this file: - $ gopls check internal/lsp/cmd/check.go + $ gopls check internal/lsp/cmd/check.go `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index 3b61abfe61..629a5e0199 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -17,6 +17,7 @@ import ( "os" "strings" "sync" + "text/tabwriter" "time" "golang.org/x/tools/internal/jsonrpc2" @@ -94,6 +95,7 @@ func New(name, wd string, env []string, options func(*source.Options)) *Applicat RemoteListenTimeout: 1 * time.Minute, }, } + app.Serve.app = app return app } @@ -111,28 +113,25 @@ func (app *Application) ShortHelp() string { // DetailedHelp implements tool.Application returning the main binary help. // This includes the short help for all the sub commands. func (app *Application) DetailedHelp(f *flag.FlagSet) { - fmt.Fprint(f.Output(), ` + w := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0) + defer w.Flush() + + fmt.Fprint(w, ` gopls is a Go language server. It is typically used with an editor to provide language features. When no command is specified, gopls will default to the 'serve' command. The language features can also be accessed via the gopls command-line interface. -Available commands are: -`) - fmt.Fprint(f.Output(), ` -main: +command: `) + fmt.Fprint(w, "\nMain\t\n") for _, c := range app.mainCommands() { - fmt.Fprintf(f.Output(), " %s : %v\n", c.Name(), c.ShortHelp()) + fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) } - fmt.Fprint(f.Output(), ` -features: -`) + fmt.Fprint(w, "\t\nFeatures\t\n") for _, c := range app.featureCommands() { - fmt.Fprintf(f.Output(), " %s : %v\n", c.Name(), c.ShortHelp()) + fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) } - fmt.Fprint(f.Output(), ` -gopls flags are: -`) + fmt.Fprint(w, "\nflags:\n") f.PrintDefaults() } @@ -142,7 +141,6 @@ gopls flags are: // temporary measure for compatibility. func (app *Application) Run(ctx context.Context, args ...string) error { ctx = debug.WithInstance(ctx, app.wd, app.OCAgent) - app.Serve.app = app if len(args) == 0 { s := flag.NewFlagSet(app.Name(), flag.ExitOnError) return tool.Run(ctx, s, &app.Serve, args) @@ -171,8 +169,8 @@ func (app *Application) mainCommands() []tool.Application { return []tool.Application{ &app.Serve, &version{app: app}, - &bug{}, - &apiJSON{}, + &bug{app: app}, + &apiJSON{app: app}, &licenses{app: app}, } } diff --git a/internal/lsp/cmd/definition.go b/internal/lsp/cmd/definition.go index e15540f9e5..d147fa4a7b 100644 --- a/internal/lsp/cmd/definition.go +++ b/internal/lsp/cmd/definition.go @@ -43,16 +43,17 @@ type definition struct { } func (d *definition) Name() string { return "definition" } -func (d *definition) Usage() string { return "" } +func (d *definition) Parent() string { return d.app.Name() } +func (d *definition) Usage() string { return "[definition-flags] " } func (d *definition) ShortHelp() string { return "show declaration of selected identifier" } func (d *definition) DetailedHelp(f *flag.FlagSet) { fmt.Fprintf(f.Output(), ` Example: show the definition of the identifier at syntax at offset %[1]v in this file (flag.FlagSet): -$ gopls definition internal/lsp/cmd/definition.go:%[1]v:%[2]v -$ gopls definition internal/lsp/cmd/definition.go:#%[3]v + $ gopls definition internal/lsp/cmd/definition.go:%[1]v:%[2]v + $ gopls definition internal/lsp/cmd/definition.go:#%[3]v - gopls query definition flags are: +definition-flags: `, exampleLine, exampleColumn, exampleOffset) f.PrintDefaults() } diff --git a/internal/lsp/cmd/folding_range.go b/internal/lsp/cmd/folding_range.go index f655f30ce0..584a39f5a1 100644 --- a/internal/lsp/cmd/folding_range.go +++ b/internal/lsp/cmd/folding_range.go @@ -20,13 +20,14 @@ type foldingRanges struct { } func (r *foldingRanges) Name() string { return "folding_ranges" } +func (r *foldingRanges) Parent() string { return r.app.Name() } func (r *foldingRanges) Usage() string { return "" } func (r *foldingRanges) ShortHelp() string { return "display selected file's folding ranges" } func (r *foldingRanges) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ gopls folding_ranges helper/helper.go + $ gopls folding_ranges helper/helper.go `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/format.go b/internal/lsp/cmd/format.go index d1ecf56963..1a8db1780b 100644 --- a/internal/lsp/cmd/format.go +++ b/internal/lsp/cmd/format.go @@ -27,7 +27,8 @@ type format struct { } func (c *format) Name() string { return "format" } -func (c *format) Usage() string { return "" } +func (c *format) Parent() string { return c.app.Name() } +func (c *format) Usage() string { return "[format-flags] " } func (c *format) ShortHelp() string { return "format the code according to the go standard" } func (c *format) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` @@ -35,9 +36,9 @@ The arguments supplied may be simple file names, or ranges within files. Example: reformat this file: - $ gopls format -w internal/lsp/cmd/check.go + $ gopls format -w internal/lsp/cmd/check.go - gopls format flags are: +format-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/highlight.go b/internal/lsp/cmd/highlight.go index b60d513452..31ca6f2cda 100644 --- a/internal/lsp/cmd/highlight.go +++ b/internal/lsp/cmd/highlight.go @@ -21,15 +21,16 @@ type highlight struct { } func (r *highlight) Name() string { return "highlight" } +func (r *highlight) Parent() string { return r.app.Name() } func (r *highlight) Usage() string { return "" } func (r *highlight) ShortHelp() string { return "display selected identifier's highlights" } func (r *highlight) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls highlight helper/helper.go:8:6 - $ gopls highlight helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls highlight helper/helper.go:8:6 + $ gopls highlight helper/helper.go:#53 `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/implementation.go b/internal/lsp/cmd/implementation.go index 18eaa4ed3f..4c688c6dfe 100644 --- a/internal/lsp/cmd/implementation.go +++ b/internal/lsp/cmd/implementation.go @@ -21,15 +21,16 @@ type implementation struct { } func (i *implementation) Name() string { return "implementation" } +func (i *implementation) Parent() string { return i.app.Name() } func (i *implementation) Usage() string { return "" } func (i *implementation) ShortHelp() string { return "display selected identifier's implementation" } func (i *implementation) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls implementation helper/helper.go:8:6 - $ gopls implementation helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls implementation helper/helper.go:8:6 + $ gopls implementation helper/helper.go:#53 `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/imports.go b/internal/lsp/cmd/imports.go index a6d00e9f0d..10e1082da6 100644 --- a/internal/lsp/cmd/imports.go +++ b/internal/lsp/cmd/imports.go @@ -27,15 +27,16 @@ type imports struct { } func (t *imports) Name() string { return "imports" } -func (t *imports) Usage() string { return "" } +func (t *imports) Parent() string { return t.app.Name() } +func (t *imports) Usage() string { return "[imports-flags] " } func (t *imports) ShortHelp() string { return "updates import statements" } func (t *imports) DetailedHelp(f *flag.FlagSet) { fmt.Fprintf(f.Output(), ` Example: update imports statements in a file: -  $ gopls imports -w internal/lsp/cmd/check.go + $ gopls imports -w internal/lsp/cmd/check.go -gopls imports flags are: +imports-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/info.go b/internal/lsp/cmd/info.go index 87ba4283be..5622c2ce2e 100644 --- a/internal/lsp/cmd/info.go +++ b/internal/lsp/cmd/info.go @@ -25,6 +25,7 @@ type version struct { } func (v *version) Name() string { return "version" } +func (v *version) Parent() string { return v.app.Name() } func (v *version) Usage() string { return "" } func (v *version) ShortHelp() string { return "print the gopls version information" } func (v *version) DetailedHelp(f *flag.FlagSet) { @@ -39,9 +40,12 @@ func (v *version) Run(ctx context.Context, args ...string) error { } // bug implements the bug command. -type bug struct{} +type bug struct { + app *Application +} func (b *bug) Name() string { return "bug" } +func (b *bug) Parent() string { return b.app.Name() } func (b *bug) Usage() string { return "" } func (b *bug) ShortHelp() string { return "report a bug in gopls" } func (b *bug) DetailedHelp(f *flag.FlagSet) { @@ -84,9 +88,12 @@ func (b *bug) Run(ctx context.Context, args ...string) error { return nil } -type apiJSON struct{} +type apiJSON struct { + app *Application +} func (j *apiJSON) Name() string { return "api-json" } +func (j *apiJSON) Parent() string { return j.app.Name() } func (j *apiJSON) Usage() string { return "" } func (j *apiJSON) ShortHelp() string { return "print json describing gopls API" } func (j *apiJSON) DetailedHelp(f *flag.FlagSet) { @@ -108,6 +115,7 @@ type licenses struct { } func (l *licenses) Name() string { return "licenses" } +func (l *licenses) Parent() string { return l.app.Name() } func (l *licenses) Usage() string { return "" } func (l *licenses) ShortHelp() string { return "print licenses of included software" } func (l *licenses) DetailedHelp(f *flag.FlagSet) { diff --git a/internal/lsp/cmd/links.go b/internal/lsp/cmd/links.go index 1d5a669214..2196698fa2 100644 --- a/internal/lsp/cmd/links.go +++ b/internal/lsp/cmd/links.go @@ -25,15 +25,16 @@ type links struct { } func (l *links) Name() string { return "links" } -func (l *links) Usage() string { return "" } +func (l *links) Parent() string { return l.app.Name() } +func (l *links) Usage() string { return "[links-flags] " } func (l *links) ShortHelp() string { return "list links in a file" } func (l *links) DetailedHelp(f *flag.FlagSet) { fmt.Fprintf(f.Output(), ` Example: list links contained within a file: -  $ gopls links internal/lsp/cmd/check.go + $ gopls links internal/lsp/cmd/check.go -gopls links flags are: +links-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/prepare_rename.go b/internal/lsp/cmd/prepare_rename.go index 2e6965e911..58d90c3129 100644 --- a/internal/lsp/cmd/prepare_rename.go +++ b/internal/lsp/cmd/prepare_rename.go @@ -21,6 +21,7 @@ type prepareRename struct { } func (r *prepareRename) Name() string { return "prepare_rename" } +func (r *prepareRename) Parent() string { return r.app.Name() } func (r *prepareRename) Usage() string { return "" } func (r *prepareRename) ShortHelp() string { return "test validity of a rename operation at location" } func (r *prepareRename) DetailedHelp(f *flag.FlagSet) { diff --git a/internal/lsp/cmd/references.go b/internal/lsp/cmd/references.go index 562601906f..4a452c5db4 100644 --- a/internal/lsp/cmd/references.go +++ b/internal/lsp/cmd/references.go @@ -23,17 +23,18 @@ type references struct { } func (r *references) Name() string { return "references" } -func (r *references) Usage() string { return "" } +func (r *references) Parent() string { return r.app.Name() } +func (r *references) Usage() string { return "[references-flags] " } func (r *references) ShortHelp() string { return "display selected identifier's references" } func (r *references) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls references helper/helper.go:8:6 - $ gopls references helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls references helper/helper.go:8:6 + $ gopls references helper/helper.go:#53 - gopls references flags are: +references-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/remote.go b/internal/lsp/cmd/remote.go index 86c2299527..b6ab7f4bcc 100644 --- a/internal/lsp/cmd/remote.go +++ b/internal/lsp/cmd/remote.go @@ -18,6 +18,7 @@ import ( ) type remote struct { + app *Application subcommands // For backward compatibility, allow aliasing this command (it was previously @@ -30,6 +31,7 @@ type remote struct { func newRemote(app *Application, alias string) *remote { return &remote{ + app: app, subcommands: subcommands{ &listSessions{app: app}, &startDebugging{app: app}, @@ -45,6 +47,8 @@ func (r *remote) Name() string { return "remote" } +func (r *remote) Parent() string { return r.app.Name() } + func (r *remote) ShortHelp() string { short := "interact with the gopls daemon" if r.alias != "" { @@ -58,8 +62,9 @@ type listSessions struct { app *Application } -func (c *listSessions) Name() string { return "sessions" } -func (c *listSessions) Usage() string { return "" } +func (c *listSessions) Name() string { return "sessions" } +func (c *listSessions) Parent() string { return c.app.Name() } +func (c *listSessions) Usage() string { return "" } func (c *listSessions) ShortHelp() string { return "print information about current gopls sessions" } diff --git a/internal/lsp/cmd/rename.go b/internal/lsp/cmd/rename.go index 5742082334..12e3ac398c 100644 --- a/internal/lsp/cmd/rename.go +++ b/internal/lsp/cmd/rename.go @@ -31,17 +31,18 @@ type rename struct { } func (r *rename) Name() string { return "rename" } -func (r *rename) Usage() string { return " " } +func (r *rename) Parent() string { return r.app.Name() } +func (r *rename) Usage() string { return "[rename-flags] " } func (r *rename) ShortHelp() string { return "rename selected identifier" } func (r *rename) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-based location (:line:column or :#position) of the thing to change - $ gopls rename helper/helper.go:8:6 Foo - $ gopls rename helper/helper.go:#53 Foo + $ # 1-based location (:line:column or :#position) of the thing to change + $ gopls rename helper/helper.go:8:6 Foo + $ gopls rename helper/helper.go:#53 Foo - gopls rename flags are: +rename-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/semantictokens.go b/internal/lsp/cmd/semantictokens.go index e8f9018c7d..0cb1270dd6 100644 --- a/internal/lsp/cmd/semantictokens.go +++ b/internal/lsp/cmd/semantictokens.go @@ -14,7 +14,6 @@ import ( "io/ioutil" "log" "os" - "runtime" "unicode/utf8" "golang.org/x/tools/internal/lsp" @@ -53,20 +52,14 @@ type semtok struct { var colmap *protocol.ColumnMapper func (c *semtok) Name() string { return "semtok" } +func (c *semtok) Parent() string { return c.app.Name() } func (c *semtok) Usage() string { return "" } func (c *semtok) ShortHelp() string { return "show semantic tokens for the specified file" } func (c *semtok) DetailedHelp(f *flag.FlagSet) { - for i := 1; ; i++ { - _, f, l, ok := runtime.Caller(i) - if !ok { - break - } - log.Printf("%d: %s:%d", i, f, l) - } fmt.Fprint(f.Output(), ` Example: show the semantic tokens for this file: - $ gopls semtok internal/lsp/cmd/semtok.go + $ gopls semtok internal/lsp/cmd/semtok.go `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/serve.go b/internal/lsp/cmd/serve.go index 4164b5869f..152ee6dad6 100644 --- a/internal/lsp/cmd/serve.go +++ b/internal/lsp/cmd/serve.go @@ -41,8 +41,9 @@ type Serve struct { app *Application } -func (s *Serve) Name() string { return "serve" } -func (s *Serve) Usage() string { return "" } +func (s *Serve) Name() string { return "serve" } +func (s *Serve) Parent() string { return s.app.Name() } +func (s *Serve) Usage() string { return "[server-flags]" } func (s *Serve) ShortHelp() string { return "run a server for Go code using the Language Server Protocol" } @@ -51,7 +52,7 @@ func (s *Serve) DetailedHelp(f *flag.FlagSet) { The server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as a child of an editor process. -gopls server flags are: +server-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/signature.go b/internal/lsp/cmd/signature.go index 0a7a599c97..8db7ca7b43 100644 --- a/internal/lsp/cmd/signature.go +++ b/internal/lsp/cmd/signature.go @@ -20,15 +20,16 @@ type signature struct { } func (r *signature) Name() string { return "signature" } +func (r *signature) Parent() string { return r.app.Name() } func (r *signature) Usage() string { return "" } func (r *signature) ShortHelp() string { return "display selected identifier's signature" } func (r *signature) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls signature helper/helper.go:8:6 - $ gopls signature helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls signature helper/helper.go:8:6 + $ gopls signature helper/helper.go:#53 `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/subcommands.go b/internal/lsp/cmd/subcommands.go index a72645c498..1903c92077 100644 --- a/internal/lsp/cmd/subcommands.go +++ b/internal/lsp/cmd/subcommands.go @@ -8,6 +8,7 @@ import ( "context" "flag" "fmt" + "text/tabwriter" "golang.org/x/tools/internal/tool" ) @@ -17,14 +18,16 @@ import ( type subcommands []tool.Application func (s subcommands) DetailedHelp(f *flag.FlagSet) { - fmt.Fprint(f.Output(), "\nsubcommands:\n") + w := tabwriter.NewWriter(f.Output(), 0, 0, 2, ' ', 0) + defer w.Flush() + fmt.Fprint(w, "\nsubcommands:\n") for _, c := range s { - fmt.Fprintf(f.Output(), " %s: %s\n", c.Name(), c.ShortHelp()) + fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) } f.PrintDefaults() } -func (s subcommands) Usage() string { return " [args...]" } +func (s subcommands) Usage() string { return " [arg]..." } func (s subcommands) Run(ctx context.Context, args ...string) error { if len(args) == 0 { diff --git a/internal/lsp/cmd/suggested_fix.go b/internal/lsp/cmd/suggested_fix.go index 51ab4db909..c99e4d0716 100644 --- a/internal/lsp/cmd/suggested_fix.go +++ b/internal/lsp/cmd/suggested_fix.go @@ -28,15 +28,15 @@ type suggestedFix struct { } func (s *suggestedFix) Name() string { return "fix" } -func (s *suggestedFix) Usage() string { return "" } +func (s *suggestedFix) Parent() string { return s.app.Name() } +func (s *suggestedFix) Usage() string { return "[fix-flags] " } func (s *suggestedFix) ShortHelp() string { return "apply suggested fixes" } func (s *suggestedFix) DetailedHelp(f *flag.FlagSet) { fmt.Fprintf(f.Output(), ` -Example: apply suggested fixes for this file: +Example: apply suggested fixes for this file + $ gopls fix -w internal/lsp/cmd/check.go -  $ gopls fix -w internal/lsp/cmd/check.go - -gopls fix flags are: +fix-flags: `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/symbols.go b/internal/lsp/cmd/symbols.go index b4a503b0ce..2549cacdd5 100644 --- a/internal/lsp/cmd/symbols.go +++ b/internal/lsp/cmd/symbols.go @@ -22,12 +22,13 @@ type symbols struct { } func (r *symbols) Name() string { return "symbols" } +func (r *symbols) Parent() string { return r.app.Name() } func (r *symbols) Usage() string { return "" } func (r *symbols) ShortHelp() string { return "display selected file's symbols" } func (r *symbols) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ gopls symbols helper/helper.go + $ gopls symbols helper/helper.go `) f.PrintDefaults() } diff --git a/internal/lsp/cmd/usage/api-json.hlp b/internal/lsp/cmd/usage/api-json.hlp index aa2b3fca5b..cb9fbfbea9 100644 --- a/internal/lsp/cmd/usage/api-json.hlp +++ b/internal/lsp/cmd/usage/api-json.hlp @@ -1,3 +1,4 @@ print json describing gopls API -Usage: api-json [flags] +Usage: + gopls [flags] api-json diff --git a/internal/lsp/cmd/usage/bug.hlp b/internal/lsp/cmd/usage/bug.hlp index 3ac58c9090..772d54d5f1 100644 --- a/internal/lsp/cmd/usage/bug.hlp +++ b/internal/lsp/cmd/usage/bug.hlp @@ -1,3 +1,4 @@ report a bug in gopls -Usage: bug [flags] +Usage: + gopls [flags] bug diff --git a/internal/lsp/cmd/usage/call_hierarchy.hlp b/internal/lsp/cmd/usage/call_hierarchy.hlp index 4fc9841ecd..07fccc8285 100644 --- a/internal/lsp/cmd/usage/call_hierarchy.hlp +++ b/internal/lsp/cmd/usage/call_hierarchy.hlp @@ -1,9 +1,10 @@ display selected identifier's call hierarchy -Usage: call_hierarchy [flags] +Usage: + gopls [flags] call_hierarchy Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls call_hierarchy helper/helper.go:8:6 - $ gopls call_hierarchy helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls call_hierarchy helper/helper.go:8:6 + $ gopls call_hierarchy helper/helper.go:#53 diff --git a/internal/lsp/cmd/usage/check.hlp b/internal/lsp/cmd/usage/check.hlp index 0b62556895..ba89588d50 100644 --- a/internal/lsp/cmd/usage/check.hlp +++ b/internal/lsp/cmd/usage/check.hlp @@ -1,7 +1,8 @@ show diagnostic results for the specified file -Usage: check [flags] +Usage: + gopls [flags] check Example: show the diagnostic results of this file: - $ gopls check internal/lsp/cmd/check.go + $ gopls check internal/lsp/cmd/check.go diff --git a/internal/lsp/cmd/usage/definition.hlp b/internal/lsp/cmd/usage/definition.hlp index 6a4b4e7321..500e6c9a41 100644 --- a/internal/lsp/cmd/usage/definition.hlp +++ b/internal/lsp/cmd/usage/definition.hlp @@ -1,13 +1,14 @@ show declaration of selected identifier -Usage: definition [flags] +Usage: + gopls [flags] definition [definition-flags] Example: show the definition of the identifier at syntax at offset 44 in this file (flag.FlagSet): -$ gopls definition internal/lsp/cmd/definition.go:44:47 -$ gopls definition internal/lsp/cmd/definition.go:#1270 + $ gopls definition internal/lsp/cmd/definition.go:44:47 + $ gopls definition internal/lsp/cmd/definition.go:#1270 - gopls query definition flags are: +definition-flags: -json emit output in JSON format -markdown diff --git a/internal/lsp/cmd/usage/fix.hlp b/internal/lsp/cmd/usage/fix.hlp index e8ef826110..ceba97096b 100644 --- a/internal/lsp/cmd/usage/fix.hlp +++ b/internal/lsp/cmd/usage/fix.hlp @@ -1,12 +1,12 @@ apply suggested fixes -Usage: fix [flags] +Usage: + gopls [flags] fix [fix-flags] -Example: apply suggested fixes for this file: +Example: apply suggested fixes for this file + $ gopls fix -w internal/lsp/cmd/check.go -  $ gopls fix -w internal/lsp/cmd/check.go - -gopls fix flags are: +fix-flags: -a apply all fixes, not just preferred fixes -d display diffs instead of rewriting files -w write result to (source) file instead of stdout diff --git a/internal/lsp/cmd/usage/folding_ranges.hlp b/internal/lsp/cmd/usage/folding_ranges.hlp index 9d601e61e4..4af2da6150 100644 --- a/internal/lsp/cmd/usage/folding_ranges.hlp +++ b/internal/lsp/cmd/usage/folding_ranges.hlp @@ -1,7 +1,8 @@ display selected file's folding ranges -Usage: folding_ranges [flags] +Usage: + gopls [flags] folding_ranges Example: - $ gopls folding_ranges helper/helper.go + $ gopls folding_ranges helper/helper.go diff --git a/internal/lsp/cmd/usage/format.hlp b/internal/lsp/cmd/usage/format.hlp index f7542fb0da..2fbf1862f9 100644 --- a/internal/lsp/cmd/usage/format.hlp +++ b/internal/lsp/cmd/usage/format.hlp @@ -1,14 +1,15 @@ format the code according to the go standard -Usage: format [flags] +Usage: + gopls [flags] format [format-flags] The arguments supplied may be simple file names, or ranges within files. Example: reformat this file: - $ gopls format -w internal/lsp/cmd/check.go + $ gopls format -w internal/lsp/cmd/check.go - gopls format flags are: +format-flags: -d display diffs instead of rewriting files -l list files whose formatting differs from gofmt's -w write result to (source) file instead of stdout diff --git a/internal/lsp/cmd/usage/highlight.hlp b/internal/lsp/cmd/usage/highlight.hlp index 8e6f425010..e128eb7de5 100644 --- a/internal/lsp/cmd/usage/highlight.hlp +++ b/internal/lsp/cmd/usage/highlight.hlp @@ -1,9 +1,10 @@ display selected identifier's highlights -Usage: highlight [flags] +Usage: + gopls [flags] highlight Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls highlight helper/helper.go:8:6 - $ gopls highlight helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls highlight helper/helper.go:8:6 + $ gopls highlight helper/helper.go:#53 diff --git a/internal/lsp/cmd/usage/implementation.hlp b/internal/lsp/cmd/usage/implementation.hlp index 3e9e87a56d..09414f1904 100644 --- a/internal/lsp/cmd/usage/implementation.hlp +++ b/internal/lsp/cmd/usage/implementation.hlp @@ -1,9 +1,10 @@ display selected identifier's implementation -Usage: implementation [flags] +Usage: + gopls [flags] implementation Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls implementation helper/helper.go:8:6 - $ gopls implementation helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls implementation helper/helper.go:8:6 + $ gopls implementation helper/helper.go:#53 diff --git a/internal/lsp/cmd/usage/imports.hlp b/internal/lsp/cmd/usage/imports.hlp index b7e6721723..661f64d291 100644 --- a/internal/lsp/cmd/usage/imports.hlp +++ b/internal/lsp/cmd/usage/imports.hlp @@ -1,11 +1,12 @@ updates import statements -Usage: imports [flags] +Usage: + gopls [flags] imports [imports-flags] Example: update imports statements in a file: -  $ gopls imports -w internal/lsp/cmd/check.go + $ gopls imports -w internal/lsp/cmd/check.go -gopls imports flags are: +imports-flags: -d display diffs instead of rewriting files -w write result to (source) file instead of stdout diff --git a/internal/lsp/cmd/usage/inspect.hlp b/internal/lsp/cmd/usage/inspect.hlp index 8f84d93193..8271f50c7a 100644 --- a/internal/lsp/cmd/usage/inspect.hlp +++ b/internal/lsp/cmd/usage/inspect.hlp @@ -1,7 +1,8 @@ interact with the gopls daemon (deprecated: use 'remote') -Usage: inspect [flags] [args...] +Usage: + gopls [flags] inspect [arg]... subcommands: - sessions: print information about current gopls sessions - debug: start the debug server + sessions print information about current gopls sessions + debug start the debug server diff --git a/internal/lsp/cmd/usage/licenses.hlp b/internal/lsp/cmd/usage/licenses.hlp index c7115d57cb..ab60ebc2f1 100644 --- a/internal/lsp/cmd/usage/licenses.hlp +++ b/internal/lsp/cmd/usage/licenses.hlp @@ -1,3 +1,4 @@ print licenses of included software -Usage: licenses [flags] +Usage: + gopls [flags] licenses diff --git a/internal/lsp/cmd/usage/links.hlp b/internal/lsp/cmd/usage/links.hlp index 49ba65573e..7f7612ce79 100644 --- a/internal/lsp/cmd/usage/links.hlp +++ b/internal/lsp/cmd/usage/links.hlp @@ -1,11 +1,12 @@ list links in a file -Usage: links [flags] +Usage: + gopls [flags] links [links-flags] Example: list links contained within a file: -  $ gopls links internal/lsp/cmd/check.go + $ gopls links internal/lsp/cmd/check.go -gopls links flags are: +links-flags: -json emit document links in JSON format diff --git a/internal/lsp/cmd/usage/prepare_rename.hlp b/internal/lsp/cmd/usage/prepare_rename.hlp index caf17a3ee6..7f8a6f32db 100644 --- a/internal/lsp/cmd/usage/prepare_rename.hlp +++ b/internal/lsp/cmd/usage/prepare_rename.hlp @@ -1,6 +1,7 @@ test validity of a rename operation at location -Usage: prepare_rename [flags] +Usage: + gopls [flags] prepare_rename Example: diff --git a/internal/lsp/cmd/usage/references.hlp b/internal/lsp/cmd/usage/references.hlp index 514ae10ef6..34aef38f19 100644 --- a/internal/lsp/cmd/usage/references.hlp +++ b/internal/lsp/cmd/usage/references.hlp @@ -1,12 +1,13 @@ display selected identifier's references -Usage: references [flags] +Usage: + gopls [flags] references [references-flags] Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls references helper/helper.go:8:6 - $ gopls references helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls references helper/helper.go:8:6 + $ gopls references helper/helper.go:#53 - gopls references flags are: +references-flags: -d include the declaration of the specified identifier in the results diff --git a/internal/lsp/cmd/usage/remote.hlp b/internal/lsp/cmd/usage/remote.hlp index 7b5f380b93..cbcfd03f84 100644 --- a/internal/lsp/cmd/usage/remote.hlp +++ b/internal/lsp/cmd/usage/remote.hlp @@ -1,7 +1,8 @@ interact with the gopls daemon -Usage: remote [flags] [args...] +Usage: + gopls [flags] remote [arg]... subcommands: - sessions: print information about current gopls sessions - debug: start the debug server + sessions print information about current gopls sessions + debug start the debug server diff --git a/internal/lsp/cmd/usage/rename.hlp b/internal/lsp/cmd/usage/rename.hlp index ddcc8e9598..73446872d4 100644 --- a/internal/lsp/cmd/usage/rename.hlp +++ b/internal/lsp/cmd/usage/rename.hlp @@ -1,14 +1,15 @@ rename selected identifier -Usage: rename [flags] +Usage: + gopls [flags] rename [rename-flags] Example: - $ # 1-based location (:line:column or :#position) of the thing to change - $ gopls rename helper/helper.go:8:6 Foo - $ gopls rename helper/helper.go:#53 Foo + $ # 1-based location (:line:column or :#position) of the thing to change + $ gopls rename helper/helper.go:8:6 Foo + $ gopls rename helper/helper.go:#53 Foo - gopls rename flags are: +rename-flags: -d display diffs instead of rewriting files -preserve preserve original files diff --git a/internal/lsp/cmd/usage/semtok.hlp b/internal/lsp/cmd/usage/semtok.hlp index fad4f6e157..459ed596c8 100644 --- a/internal/lsp/cmd/usage/semtok.hlp +++ b/internal/lsp/cmd/usage/semtok.hlp @@ -1,7 +1,8 @@ show semantic tokens for the specified file -Usage: semtok [flags] +Usage: + gopls [flags] semtok Example: show the semantic tokens for this file: - $ gopls semtok internal/lsp/cmd/semtok.go + $ gopls semtok internal/lsp/cmd/semtok.go diff --git a/internal/lsp/cmd/usage/serve.hlp b/internal/lsp/cmd/usage/serve.hlp index 13812de6cc..3460a2725a 100644 --- a/internal/lsp/cmd/usage/serve.hlp +++ b/internal/lsp/cmd/usage/serve.hlp @@ -1,11 +1,12 @@ run a server for Go code using the Language Server Protocol -Usage: serve [flags] +Usage: + gopls [flags] serve [server-flags] The server communicates using JSONRPC2 on stdin and stdout, and is intended to be run directly as a child of an editor process. -gopls server flags are: +server-flags: -debug string serve debug information on the supplied address -listen string diff --git a/internal/lsp/cmd/usage/signature.hlp b/internal/lsp/cmd/usage/signature.hlp index aaedac204c..f9fd0bfb7e 100644 --- a/internal/lsp/cmd/usage/signature.hlp +++ b/internal/lsp/cmd/usage/signature.hlp @@ -1,9 +1,10 @@ display selected identifier's signature -Usage: signature [flags] +Usage: + gopls [flags] signature Example: - $ # 1-indexed location (:line:column or :#offset) of the target identifier - $ gopls signature helper/helper.go:8:6 - $ gopls signature helper/helper.go:#53 + $ # 1-indexed location (:line:column or :#offset) of the target identifier + $ gopls signature helper/helper.go:8:6 + $ gopls signature helper/helper.go:#53 diff --git a/internal/lsp/cmd/usage/symbols.hlp b/internal/lsp/cmd/usage/symbols.hlp index 3514a13f6d..2aa36aa841 100644 --- a/internal/lsp/cmd/usage/symbols.hlp +++ b/internal/lsp/cmd/usage/symbols.hlp @@ -1,6 +1,7 @@ display selected file's symbols -Usage: symbols [flags] +Usage: + gopls [flags] symbols Example: - $ gopls symbols helper/helper.go + $ gopls symbols helper/helper.go diff --git a/internal/lsp/cmd/usage/usage.hlp b/internal/lsp/cmd/usage/usage.hlp index 0be73bcd3b..9288f534b4 100644 --- a/internal/lsp/cmd/usage/usage.hlp +++ b/internal/lsp/cmd/usage/usage.hlp @@ -1,43 +1,44 @@ The Go Language source tools. -Usage: gopls [flags] [command-flags] [command-args] +Usage: + gopls [flags] [command-flags] [command-args] gopls is a Go language server. It is typically used with an editor to provide language features. When no command is specified, gopls will default to the 'serve' command. The language features can also be accessed via the gopls command-line interface. -Available commands are: +command: -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 - api-json : print json describing gopls API - licenses : print licenses of included software +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 + api-json print json describing gopls API + licenses print licenses of included software + +Features + call_hierarchy display selected identifier's call hierarchy + check show diagnostic results for the specified file + definition show declaration of selected identifier + folding_ranges display selected file's folding ranges + format format the code according to the go standard + highlight display selected identifier's highlights + implementation display selected identifier's implementation + imports updates import statements + remote interact with the gopls daemon + inspect interact with the gopls daemon (deprecated: use 'remote') + links list links in a file + prepare_rename test validity of a rename operation at location + references display selected identifier's references + rename rename selected identifier + semtok show semantic tokens for the specified file + signature display selected identifier's signature + fix apply suggested fixes + symbols display selected file's symbols + workspace manage the gopls workspace (experimental: under development) + workspace_symbol search symbols in workspace -features: - call_hierarchy : display selected identifier's call hierarchy - check : show diagnostic results for the specified file - definition : show declaration of selected identifier - folding_ranges : display selected file's folding ranges - format : format the code according to the go standard - highlight : display selected identifier's highlights - implementation : display selected identifier's implementation - imports : updates import statements - remote : interact with the gopls daemon - inspect : interact with the gopls daemon (deprecated: use 'remote') - links : list links in a file - prepare_rename : test validity of a rename operation at location - references : display selected identifier's references - rename : rename selected identifier - semtok : show semantic tokens for the specified file - signature : display selected identifier's signature - fix : apply suggested fixes - symbols : display selected file's symbols - workspace : manage the gopls workspace (experimental: under development) - workspace_symbol : search symbols in workspace - -gopls flags are: +flags: -debug string serve debug information on the supplied address -listen string diff --git a/internal/lsp/cmd/usage/version.hlp b/internal/lsp/cmd/usage/version.hlp index ec3352cdea..3ac26b96fe 100644 --- a/internal/lsp/cmd/usage/version.hlp +++ b/internal/lsp/cmd/usage/version.hlp @@ -1,3 +1,4 @@ print the gopls version information -Usage: version [flags] +Usage: + gopls [flags] version diff --git a/internal/lsp/cmd/usage/workspace.hlp b/internal/lsp/cmd/usage/workspace.hlp index 01556f5bc0..8c40125b8a 100644 --- a/internal/lsp/cmd/usage/workspace.hlp +++ b/internal/lsp/cmd/usage/workspace.hlp @@ -1,6 +1,7 @@ manage the gopls workspace (experimental: under development) -Usage: workspace [flags] [args...] +Usage: + gopls [flags] workspace [arg]... subcommands: - generate: generate a gopls.mod file for a workspace + generate generate a gopls.mod file for a workspace diff --git a/internal/lsp/cmd/usage/workspace_symbol.hlp b/internal/lsp/cmd/usage/workspace_symbol.hlp index 3d9f84d41f..697e26f975 100644 --- a/internal/lsp/cmd/usage/workspace_symbol.hlp +++ b/internal/lsp/cmd/usage/workspace_symbol.hlp @@ -1,12 +1,13 @@ search symbols in workspace -Usage: workspace_symbol [flags] +Usage: + gopls [flags] workspace_symbol [workspace_symbol-flags] Example: - $ gopls workspace_symbol -matcher fuzzy 'wsymbols' + $ gopls workspace_symbol -matcher fuzzy 'wsymbols' -gopls workspace_symbol flags are: +workspace_symbol-flags: -matcher string specifies the type of matcher: fuzzy, caseSensitive, or caseInsensitive. The default is caseInsensitive. diff --git a/internal/lsp/cmd/workspace.go b/internal/lsp/cmd/workspace.go index 61757d2973..03a6e41122 100644 --- a/internal/lsp/cmd/workspace.go +++ b/internal/lsp/cmd/workspace.go @@ -19,18 +19,21 @@ import ( // used for manipulating the workspace mod file, rather than editing it // manually. type workspace struct { + app *Application subcommands } func newWorkspace(app *Application) *workspace { return &workspace{ + app: app, subcommands: subcommands{ &generateWorkspaceMod{app: app}, }, } } -func (w *workspace) Name() string { return "workspace" } +func (w *workspace) Name() string { return "workspace" } +func (w *workspace) Parent() string { return w.app.Name() } func (w *workspace) ShortHelp() string { return "manage the gopls workspace (experimental: under development)" } diff --git a/internal/lsp/cmd/workspace_symbol.go b/internal/lsp/cmd/workspace_symbol.go index cd21f9be7a..fdbe4c4f50 100644 --- a/internal/lsp/cmd/workspace_symbol.go +++ b/internal/lsp/cmd/workspace_symbol.go @@ -22,15 +22,16 @@ type workspaceSymbol struct { } func (r *workspaceSymbol) Name() string { return "workspace_symbol" } -func (r *workspaceSymbol) Usage() string { return "" } +func (r *workspaceSymbol) Parent() string { return r.app.Name() } +func (r *workspaceSymbol) Usage() string { return "[workspace_symbol-flags] " } func (r *workspaceSymbol) ShortHelp() string { return "search symbols in workspace" } func (r *workspaceSymbol) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ` Example: - $ gopls workspace_symbol -matcher fuzzy 'wsymbols' + $ gopls workspace_symbol -matcher fuzzy 'wsymbols' -gopls workspace_symbol flags are: +workspace_symbol-flags: `) f.PrintDefaults() } diff --git a/internal/tool/tool.go b/internal/tool/tool.go index c9b1a76437..d4ad8c3ae4 100644 --- a/internal/tool/tool.go +++ b/internal/tool/tool.go @@ -64,6 +64,10 @@ type Application interface { Run(ctx context.Context, args ...string) error } +type SubCommand interface { + Parent() string +} + // This is the type returned by CommandLineErrorf, which causes the outer main // to trigger printing of the command line help. type commandLineError string @@ -97,8 +101,16 @@ func Main(ctx context.Context, app Application, args []string) { // error. func Run(ctx context.Context, s *flag.FlagSet, app Application, args []string) error { s.Usage = func() { - fmt.Fprint(s.Output(), app.ShortHelp()) - fmt.Fprintf(s.Output(), "\n\nUsage: %v [flags] %v\n", app.Name(), app.Usage()) + fmt.Fprintf(s.Output(), "%s\n\nUsage:\n ", app.ShortHelp()) + if sub, ok := app.(SubCommand); ok && sub.Parent() != "" { + fmt.Fprintf(s.Output(), "%s [flags] %s", sub.Parent(), app.Name()) + } else { + fmt.Fprintf(s.Output(), "%s [flags]", app.Name()) + } + if usage := app.Usage(); usage != "" { + fmt.Fprintf(s.Output(), " %s", usage) + } + fmt.Fprint(s.Output(), "\n") app.DetailedHelp(s) } p := addFlags(s, reflect.StructField{}, reflect.ValueOf(app))