• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubernetes-sigs / kubebuilder / 24093595660

07 Apr 2026 04:53PM UTC coverage: 80.48% (-0.2%) from 80.667%
24093595660

Pull #5587

github

vitorfloriano
feat(cli): show hint when file completion not applicable

When hitting TAB on subcommands that don't
take files as arguments, the cli will show a
hint message (ActiveHelp) on how to list flags
instead of showing file completions.
Pull Request #5587: ✨ feat(cli): Show hint message when file completion not applicable to subcommand

31 of 56 new or added lines in 5 files covered. (55.36%)

6601 of 8202 relevant lines covered (80.48%)

45.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.06
/pkg/cli/init.go
1
/*
2
Copyright 2020 The Kubernetes Authors.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package cli
18

19
import (
20
        "fmt"
21
        "slices"
22
        "strconv"
23
        "strings"
24

25
        "github.com/spf13/cobra"
26

27
        "sigs.k8s.io/kubebuilder/v4/pkg/config"
28
        "sigs.k8s.io/kubebuilder/v4/pkg/plugin"
29
)
30

31
const initErrorMsg = "failed to initialize project"
32

33
func (c CLI) newInitCmd() *cobra.Command {
10✔
34
        cmd := &cobra.Command{
10✔
35
                Use:   "init",
10✔
36
                Short: "Initialize a new project",
10✔
37
                Long: `Initialize a new project.
10✔
38

10✔
39
For further help about a specific plugin, set --plugins.
10✔
40
`,
10✔
41
                Example: c.getInitHelpExamples(),
10✔
42
                Run:     func(_ *cobra.Command, _ []string) {},
10✔
43
        }
44

45
        // Show hint message on how to list flags instead of showing file completion for
46
        // commands that don't take files as arguments
47
        cmd.ValidArgsFunction = func(
10✔
48
                _ *cobra.Command,
10✔
49
                args []string,
10✔
50
                toComplete string,
10✔
51
        ) ([]cobra.Completion, cobra.ShellCompDirective) {
10✔
NEW
52
                completions := []cobra.Completion{}
×
NEW
53
                if len(args) == 0 && toComplete == "" {
×
NEW
54
                        completions = cobra.AppendActiveHelp(completions, "Type '--' and press TAB to list flags")
×
NEW
55
                }
×
NEW
56
                return completions, cobra.ShellCompDirectiveNoFileComp
×
57
        }
58

59
        // Register --project-version on the dynamically created command
60
        // so that it shows up in help and does not cause a parse error.
61
        cmd.Flags().String(projectVersionFlag, c.defaultProjectVersion.String(), "project version")
10✔
62

10✔
63
        // In case no plugin was resolved, instead of failing the construction of the CLI, fail the execution of
10✔
64
        // this subcommand. This allows the use of subcommands that do not require resolved plugins like help.
10✔
65
        if len(c.resolvedPlugins) == 0 {
13✔
66
                cmdErr(cmd, noResolvedPluginError{})
3✔
67
                return cmd
3✔
68
        }
3✔
69

70
        // Obtain the plugin keys and subcommands from the plugins that implement plugin.Init.
71
        subcommands := c.filterSubcommands(
7✔
72
                func(p plugin.Plugin) bool {
14✔
73
                        _, isValid := p.(plugin.Init)
7✔
74
                        return isValid
7✔
75
                },
7✔
76
                func(p plugin.Plugin) plugin.Subcommand {
6✔
77
                        return p.(plugin.Init).GetInitSubcommand()
6✔
78
                },
6✔
79
        )
80

81
        // Verify that there is at least one remaining plugin.
82
        if len(subcommands) == 0 {
8✔
83
                cmdErr(cmd, noAvailablePluginError{"project initialization"})
1✔
84
                return cmd
1✔
85
        }
1✔
86

87
        c.applySubcommandHooks(cmd, subcommands, initErrorMsg, true)
6✔
88

6✔
89
        // Append plugin table after metadata updates
6✔
90
        c.appendPluginTable(cmd, func(p plugin.Plugin) bool {
12✔
91
                _, isValid := p.(plugin.Init)
6✔
92
                return isValid
6✔
93
        }, "Available plugins that support 'init'")
6✔
94

95
        return cmd
6✔
96
}
97

98
func (c CLI) getInitHelpExamples() string {
13✔
99
        var sb strings.Builder
13✔
100
        for _, version := range c.getAvailableProjectVersions() {
17✔
101
                rendered := fmt.Sprintf(`  # Help for initializing a project with version %[2]s
4✔
102
  %[1]s init --project-version=%[2]s -h
4✔
103

4✔
104
`,
4✔
105
                        c.commandName, version)
4✔
106
                sb.WriteString(rendered)
4✔
107
        }
4✔
108
        return strings.TrimSuffix(sb.String(), "\n\n")
13✔
109
}
110

111
func (c CLI) getAvailableProjectVersions() (projectVersions []string) {
18✔
112
        versionSet := make(map[config.Version]struct{})
18✔
113
        for _, p := range c.plugins {
38✔
114
                // Only return versions of non-deprecated plugins.
20✔
115
                if _, isDeprecated := p.(plugin.Deprecated); !isDeprecated {
32✔
116
                        for _, version := range p.SupportedProjectVersions() {
27✔
117
                                versionSet[version] = struct{}{}
15✔
118
                        }
15✔
119
                }
120
        }
121
        for version := range versionSet {
31✔
122
                projectVersions = append(projectVersions, strconv.Quote(version.String()))
13✔
123
        }
13✔
124
        slices.Sort(projectVersions)
18✔
125
        return projectVersions
18✔
126
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc