Skip to content

Commit 8a392d6

Browse files
committed
fixes after review
1 parent 628416a commit 8a392d6

7 files changed

Lines changed: 137 additions & 73 deletions

File tree

cmd/root.go

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package cmd
33
import (
44
"fmt"
55
"strings"
6+
"sort"
67

78
"github.com/spf13/cobra"
9+
"github.com/lets-cli/lets/set"
810
)
911

1012
// newRootCmd represents the base command when called without any subcommands.
@@ -58,42 +60,58 @@ func PrintHelpMessage(cmd *cobra.Command) error {
5860
return err
5961
}
6062

61-
func buildGroupedCommandHelp(cmd *cobra.Command) string {
62-
help := ""
63-
cmds := cmd.Commands()
64-
groups := cmd.Groups()
65-
66-
groupCmdMap := make(map[string]map[string][]*cobra.Command)
67-
68-
// todo: add sort
69-
70-
for _, group := range groups {
71-
if _, ok := groupCmdMap[group.Title]; !ok {
72-
groupCmdMap[group.Title] = make(map[string][]*cobra.Command)
73-
}
74-
for _, c := range cmds {
75-
if c.GroupID == group.ID && (c.IsAvailableCommand() || c.Name() == "help") {
76-
subgroup := c.Annotations["SubGroupName"]
77-
groupCmdMap[group.Title][subgroup] = append(groupCmdMap[group.Title][subgroup], c)
78-
}
79-
}
80-
}
81-
82-
for groupName, GroupsMap := range groupCmdMap {
83-
help += fmt.Sprintf("%s\n", groupName)
84-
for subgroupName, cmds := range GroupsMap {
85-
intend := ""
86-
if len(GroupsMap) > 1 {
87-
help += fmt.Sprintf("\n %-*s\n", cmd.NamePadding(), subgroupName)
88-
intend = " "
89-
}
90-
for _, c := range cmds {
63+
func buildGroupCommandHelp(cmd *cobra.Command, group *cobra.Group) string {
64+
help := ""
65+
cmds := []*cobra.Command{}
66+
67+
// select commands that belong to the specified group
68+
for _, c := range cmd.Commands() {
69+
if c.GroupID == group.ID && (c.IsAvailableCommand() || c.Name() == "help") {
70+
cmds = append(cmds, c)
71+
}
72+
}
73+
74+
sort.Slice(cmds, func(i, j int) bool {
75+
return cmds[i].Name() < cmds[j].Name()
76+
})
77+
78+
// Create a list of subgroups
79+
subGroupNameSet := set.NewSet[string]()
80+
81+
for _, c := range cmds {
82+
if subgroup, ok := c.Annotations["SubGroupName"]; ok && subgroup != "" {
83+
subGroupNameSet.Add(subgroup)
84+
}
85+
}
86+
87+
subGroupNameList := subGroupNameSet.ToList()
88+
sort.Strings(subGroupNameList)
89+
90+
// generate output
91+
help += fmt.Sprintf("%s\n", group.Title)
92+
93+
for _, subgroupName := range subGroupNameList {
94+
intend := ""
95+
if len(subGroupNameList) > 1 {
96+
help += fmt.Sprintf("\n %s\n", subgroupName)
97+
intend = " "
98+
}
99+
for _, c := range cmds {
100+
if subgroup, ok := c.Annotations["SubGroupName"]; ok && subgroup == subgroupName {
91101
help += fmt.Sprintf("%s %-*s %s\n", intend, cmd.NamePadding(), c.Name(), c.Short)
92-
}
93-
}
94-
help += "\n"
95-
}
96-
return help
102+
}
103+
}
104+
}
105+
106+
for _, c := range cmds {
107+
if _, ok := c.Annotations["SubGroupName"]; !ok {
108+
help += fmt.Sprintf(" %-*s %s\n", cmd.NamePadding(), c.Name(), c.Short)
109+
}
110+
}
111+
112+
help += "\n"
113+
114+
return help
97115
}
98116

99117

@@ -112,7 +130,9 @@ func PrintRootHelpMessage(cmd *cobra.Command) error {
112130
help += "\n"
113131

114132
// Commands
115-
help += buildGroupedCommandHelp(cmd)
133+
for _, group := range cmd.Groups() {
134+
help += buildGroupCommandHelp(cmd, group)
135+
}
116136

117137
// Flags
118138
if cmd.HasAvailableLocalFlags() {

config/config/command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (c *Command) UnmarshalYAML(unmarshal func(interface{}) error) error {
5858
}
5959

6060
var cmd struct {
61-
GroupName string `yaml:"group_name"`
61+
GroupName string `yaml:"group"`
6262
Cmd Cmds
6363
Description string
6464
Shell string

config/config/command_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@ func CommandFixture(t *testing.T, text string) *Command {
1919
}
2020

2121
func TestParseCommand(t *testing.T) {
22-
t.Run("default group_name", func(t *testing.T) {
22+
t.Run("default group", func(t *testing.T) {
2323
text := dedent.Dedent(`
2424
cmd: [echo, Hello]
2525
`)
2626
command := CommandFixture(t, text)
27-
exp := ""
27+
exp := "Common"
2828

2929
if command.GroupName != exp {
3030
t.Errorf("wrong output. \nexpect %s \ngot: %s", exp, command.GroupName)
3131
}
3232
})
3333

34-
t.Run("provided custom group_name", func(t *testing.T) {
34+
t.Run("provided custom group", func(t *testing.T) {
3535
text := dedent.Dedent(`
36-
group_name: Group Name
36+
group: Group Name
3737
cmd: [echo, Hello]
3838
`)
3939
command := CommandFixture(t, text)

docs/docs/config.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ title: Config reference
3131
- [`persist_checksum`](#persist_checksum)
3232
- [`ref`](#ref)
3333
- [`args`](#args)
34+
- [`group`](#group)
3435
- [Aliasing:](#aliasing)
3536
- [Env aliasing](#env-aliasing)
3637

@@ -193,7 +194,7 @@ Bar
193194
#### Conditional init
194195

195196
If you need to make sure that code in `init` is called once with some condition,
196-
you can for example create a file at the end of `init` script and check if this
197+
you can for example create a file at the end of `init` script and check if this
197198
file exists at the beginning of `init` script.
198199

199200
Example:
@@ -871,6 +872,46 @@ commands:
871872
`args` is used only with [ref](#ref) and allows to set additional positional args to referenced command. See [ref](#ref) example.
872873

873874

875+
### `group`
876+
877+
`key: group`
878+
879+
`type: string`
880+
881+
Commands can be organized into groups for better readability in the help output. To assign a command to a group, use the `group` key:
882+
883+
```yaml
884+
commands:
885+
build:
886+
group: Build & Deploy
887+
description: Build the project
888+
cmd: npm run build
889+
890+
deploy:
891+
group: Build & Deploy
892+
description: Deploy the project
893+
cmd: npm run deploy
894+
895+
test:
896+
group: Testing
897+
description: Run tests
898+
cmd: npm test
899+
```
900+
901+
When you run `lets help`, commands will be listed under their respective groups, making it easier to find related commands.
902+
903+
```
904+
Commands:
905+
906+
Build & Deploy
907+
build Build the project
908+
deploy Deploy the project
909+
910+
Testing
911+
test Run tests
912+
```
913+
914+
874915
## Aliasing:
875916
876917
Lets supports YAML aliasing in various places in the config
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ load test_helpers
33
setup() {
44
load "${BATS_UTILS_PATH}/bats-support/load.bash"
55
load "${BATS_UTILS_PATH}/bats-assert/load.bash"
6-
cd ./tests/command_group_name
6+
cd ./tests/command_group
77
}
88

99
HELP_MESSAGE=$(cat <<EOF
@@ -15,15 +15,19 @@ Usage:
1515
1616
Commands:
1717
18-
Common
19-
run Run the application
18+
A group
19+
c c command
20+
21+
B group
22+
a a command
23+
b b command
2024
21-
Test
22-
test Runs all tests
25+
Common
26+
d d command
2327
24-
Linters
25-
linter1 Runs first linter
26-
linter2 Runs second linter
28+
Internal commands:
29+
help Help about any command
30+
self Manage lets CLI itself
2731
2832
Flags:
2933
--all show all commands (including the ones with _)
@@ -44,7 +48,7 @@ EOF
4448

4549

4650
@test "help: running 'lets help' should group commands by their group names" {
47-
run lets --help
51+
run lets help
4852
assert_success
4953

5054
assert_output "$HELP_MESSAGE"

tests/command_group/lets.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
shell: bash
2+
3+
commands:
4+
b:
5+
group: B group
6+
description: b command
7+
cmd: echo
8+
9+
a:
10+
group: B group
11+
description: a command
12+
cmd: echo
13+
14+
c:
15+
group: A group
16+
description: c command
17+
cmd: echo
18+
19+
d:
20+
description: d command
21+
cmd: echo

tests/command_group_name/lets.yaml

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)