From 7e27c8ecf54f10863747529c60f90f39aac02092 Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Tue, 9 Feb 2021 15:08:22 +1100 Subject: [PATCH] Support a simplified `kong.Groups{: }` way of specifiying groups. See #135. --- build.go | 2 +- help.go | 8 ++++---- help_test.go | 25 ++++++++----------------- model.go | 4 ++-- options.go | 34 ++++++++++++++++++++++++++++++++-- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/build.go b/build.go index 8e70674..0e3bc5f 100644 --- a/build.go +++ b/build.go @@ -232,7 +232,7 @@ func buildGroupForKey(k *Kong, key string) *Group { } } - // No group provided with kong.Groups. We create one ad-hoc for this key. + // No group provided with kong.ExplicitGroups. We create one ad-hoc for this key. return &Group{ Key: key, Title: key, diff --git a/help.go b/help.go index 31b0b75..90e3708 100644 --- a/help.go +++ b/help.go @@ -150,8 +150,8 @@ func printNodeDetail(w *helpWriter, node *Node, hide bool) { if group.Metadata.Title != "" { w.Print(group.Metadata.Title) } - if group.Metadata.Header != "" { - w.Print(group.Metadata.Header) + if group.Metadata.Description != "" { + w.Print(group.Metadata.Description) } writeFlags(w.Indent(), group.Flags) } @@ -170,8 +170,8 @@ func printNodeDetail(w *helpWriter, node *Node, hide bool) { if group.Metadata.Title != "" { w.Print(group.Metadata.Title) } - if group.Metadata.Header != "" { - w.Print(group.Metadata.Header) + if group.Metadata.Description != "" { + w.Print(group.Metadata.Description) } if w.Compact { diff --git a/help_test.go b/help_test.go index 51b5132..b83a16b 100644 --- a/help_test.go +++ b/help_test.go @@ -295,20 +295,11 @@ func TestHelpGrouping(t *testing.T) { app := mustNew(t, &cli, kong.Name("test-app"), kong.Description("A test app."), - kong.Groups([]kong.Group{ - { - Key: "Group A", - Title: "Group title taken from the kong.Groups option", - Header: "A group header", - }, - { - Key: "Group 1", - Title: "Another group title, this time without header", - }, - { - Key: "Unknown key", - }, - }), + kong.Groups{ + "Group A": "Group title taken from the kong.ExplicitGroups option\nA group header", + "Group 1": "Another group title, this time without header", + "Unknown key": "", + }, kong.Writers(w, w), kong.Exit(func(int) { exited = true @@ -331,7 +322,7 @@ Flags: --free-string=STRING A non grouped string flag. --free-bool A non grouped bool flag. -Group title taken from the kong.Groups option +Group title taken from the kong.ExplicitGroups option A group header --grouped-a-string=STRING A string flag grouped in A. --grouped-a-bool A bool flag grouped in A. @@ -343,7 +334,7 @@ Commands: two A non grouped subcommand. -Group title taken from the kong.Groups option +Group title taken from the kong.ExplicitGroups option A group header one thing <arg> subcommand thing @@ -387,7 +378,7 @@ Flags: --a-free-string=STRING A non grouped string flag. -Group title taken from the kong.Groups option +Group title taken from the kong.ExplicitGroups option A group header --grouped-a-string=STRING A string flag grouped in A. --grouped-a-bool A bool flag grouped in A. diff --git a/model.go b/model.go index c13c693..c64cab3 100644 --- a/model.go +++ b/model.go @@ -412,9 +412,9 @@ type Group struct { Key string // Title is displayed above the grouped items. Title string - // Header is optional and displayed under the Title when non empty. + // Description is optional and displayed under the Title when non empty. // It can be used to introduce the group's purpose to the user. - Header string + Description string } // This is directly from the Go 1.13 source code. diff --git a/options.go b/options.go index fc218d1..bdb57f6 100644 --- a/options.go +++ b/options.go @@ -208,10 +208,40 @@ func ConfigureHelp(options HelpOptions) Option { }) } -// Groups associates `group` field tags with their metadata. +// Groups associates `group` field tags with group metadata. +// +// This option is used to simplify Kong tags while providing +// rich group information such as title and optional description. +// +// Each key in the "groups" map corresponds to the value of a +// `group` Kong tag, while the first line of the value will be +// the title, and subsequent lines if any will be the description of +// the group. +// +// See also ExplicitGroups for a more structured alternative. +type Groups map[string]string + +func (g Groups) Apply(k *Kong) error { // nolint: golint + for key, info := range g { + lines := strings.Split(info, "\n") + title := strings.TrimSpace(lines[0]) + description := "" + if len(lines) > 1 { + description = strings.TrimSpace(strings.Join(lines[1:], "\n")) + } + k.groups = append(k.groups, Group{ + Key: key, + Title: title, + Description: description, + }) + } + return nil +} + +// ExplicitGroups associates `group` field tags with their metadata. // // It can be used to provide a title or header to a command or flag group. -func Groups(groups []Group) Option { +func ExplicitGroups(groups []Group) Option { return OptionFunc(func(k *Kong) error { k.groups = groups return nil