Skip to content

Commit f80210c

Browse files
committed
move commonly used top-level commands to the top of --help
This adds a new annotation to commands that are known to be frequently used, and allows setting a custom weight/order for these commands to influence in what order they appear in the --help output. I'm not entirely happy with the implementation (we could at least use some helpers for this, and/or make it more generic to group commands in output), but it could be a start. For now, limiting this to only be used for the top-level --help, but we can expand this to subcommands as well if we think it makes sense to highlight "common" / "commonly used" commands. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 8ee784e commit f80210c

13 files changed

Lines changed: 78 additions & 0 deletions

File tree

cli/cobra.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"sort"
78
"strings"
89

910
pluginmanager "github.com/docker/cli/cli-plugins/manager"
@@ -12,6 +13,7 @@ import (
1213
cliflags "github.com/docker/cli/cli/flags"
1314
"github.com/docker/docker/pkg/homedir"
1415
"github.com/docker/docker/registry"
16+
"github.com/fvbommel/sortorder"
1517
"github.com/moby/term"
1618
"github.com/morikuni/aec"
1719
"github.com/pkg/errors"
@@ -30,9 +32,11 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
3032

3133
cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
3234
cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
35+
cobra.AddTemplateFunc("hasTopCommands", hasTopCommands)
3336
cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
3437
cobra.AddTemplateFunc("hasOrchestratorSubCommands", hasOrchestratorSubCommands)
3538
cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins)
39+
cobra.AddTemplateFunc("topCommands", topCommands)
3640
cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
3741
cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
3842
cobra.AddTemplateFunc("orchestratorSubCommands", orchestratorSubCommands)
@@ -250,12 +254,43 @@ func hasInvalidPlugins(cmd *cobra.Command) bool {
250254
return len(invalidPlugins(cmd)) > 0
251255
}
252256

257+
func hasTopCommands(cmd *cobra.Command) bool {
258+
return len(topCommands(cmd)) > 0
259+
}
260+
261+
func topCommands(cmd *cobra.Command) []*cobra.Command {
262+
cmds := []*cobra.Command{}
263+
if cmd.Parent() != nil {
264+
// for now, only use top-commands for the root-command, and skip
265+
// for sub-commands
266+
return cmds
267+
}
268+
for _, sub := range cmd.Commands() {
269+
if isPlugin(sub) || !sub.IsAvailableCommand() {
270+
continue
271+
}
272+
if _, ok := sub.Annotations["category-top"]; ok {
273+
cmds = append(cmds, sub)
274+
}
275+
}
276+
sort.SliceStable(cmds, func(i, j int) bool {
277+
return sortorder.NaturalLess(cmds[i].Annotations["category-top"], cmds[j].Annotations["category-top"])
278+
})
279+
return cmds
280+
}
281+
253282
func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
254283
cmds := []*cobra.Command{}
255284
for _, sub := range cmd.Commands() {
256285
if isPlugin(sub) {
257286
continue
258287
}
288+
if _, ok := sub.Annotations["category-top"]; ok {
289+
if cmd.Parent() == nil {
290+
// for now, only use top-commands for the root-command
291+
continue
292+
}
293+
}
259294
if sub.IsAvailableCommand() && !sub.HasSubCommands() {
260295
cmds = append(cmds, sub)
261296
}
@@ -378,6 +413,13 @@ Examples:
378413
Options:
379414
{{ wrappedFlagUsages . | trimRightSpace}}
380415
416+
{{- end}}
417+
{{- end}}
418+
{{- if hasTopCommands .}}
419+
420+
Common Commands:
421+
{{- range topCommands .}}
422+
{{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}
381423
{{- end}}
382424
{{- end}}
383425
{{- if hasManagementSubCommands . }}

cli/command/container/exec.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
5252
options.Command = args[1:]
5353
return RunExec(dockerCli, options)
5454
},
55+
Annotations: map[string]string{
56+
"category-top": "2",
57+
},
5558
}
5659

5760
flags := cmd.Flags()

cli/command/container/list.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func NewPsCommand(dockerCli command.Cli) *cobra.Command {
3737
RunE: func(cmd *cobra.Command, args []string) error {
3838
return runPs(dockerCli, &options)
3939
},
40+
Annotations: map[string]string{
41+
"category-top": "3",
42+
},
4043
}
4144

4245
flags := cmd.Flags()

cli/command/container/run.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
4444
}
4545
return runRun(dockerCli, cmd.Flags(), &opts, copts)
4646
},
47+
Annotations: map[string]string{
48+
"category-top": "1",
49+
},
4750
}
4851

4952
flags := cmd.Flags()

cli/command/image/build.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
105105
options.context = args[0]
106106
return runBuild(dockerCli, options)
107107
},
108+
Annotations: map[string]string{
109+
"category-top": "4",
110+
},
108111
}
109112

110113
flags := cmd.Flags()

cli/command/image/list.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func NewImagesCommand(dockerCli command.Cli) *cobra.Command {
3737
}
3838
return runImages(dockerCli, options)
3939
},
40+
Annotations: map[string]string{
41+
"category-top": "7",
42+
},
4043
}
4144

4245
flags := cmd.Flags()

cli/command/image/pull.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
3434
opts.remote = args[0]
3535
return RunPull(dockerCli, opts)
3636
},
37+
Annotations: map[string]string{
38+
"category-top": "5",
39+
},
3740
}
3841

3942
flags := cmd.Flags()

cli/command/image/push.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command {
3535
opts.remote = args[0]
3636
return RunPush(dockerCli, opts)
3737
},
38+
Annotations: map[string]string{
39+
"category-top": "6",
40+
},
3841
}
3942

4043
flags := cmd.Flags()

cli/command/registry/login.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ func NewLoginCommand(dockerCli command.Cli) *cobra.Command {
4444
}
4545
return runLogin(dockerCli, opts)
4646
},
47+
Annotations: map[string]string{
48+
"category-top": "8",
49+
},
4750
}
4851

4952
flags := cmd.Flags()

cli/command/registry/logout.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ func NewLogoutCommand(dockerCli command.Cli) *cobra.Command {
2323
}
2424
return runLogout(dockerCli, serverAddress)
2525
},
26+
Annotations: map[string]string{
27+
"category-top": "9",
28+
},
2629
}
2730

2831
return cmd

0 commit comments

Comments
 (0)