diff --git a/.generated_docs b/.generated_docs
index c2fae3285d4..e88bda62ae5 100644
--- a/.generated_docs
+++ b/.generated_docs
@@ -51,6 +51,7 @@ docs/man/man1/kubectl-get.1
docs/man/man1/kubectl-label.1
docs/man/man1/kubectl-logs.1
docs/man/man1/kubectl-namespace.1
+docs/man/man1/kubectl-options.1
docs/man/man1/kubectl-patch.1
docs/man/man1/kubectl-port-forward.1
docs/man/man1/kubectl-proxy.1
@@ -120,6 +121,7 @@ docs/user-guide/kubectl/kubectl_get.md
docs/user-guide/kubectl/kubectl_label.md
docs/user-guide/kubectl/kubectl_logs.md
docs/user-guide/kubectl/kubectl_namespace.md
+docs/user-guide/kubectl/kubectl_options.md
docs/user-guide/kubectl/kubectl_patch.md
docs/user-guide/kubectl/kubectl_port-forward.md
docs/user-guide/kubectl/kubectl_proxy.md
@@ -164,6 +166,7 @@ docs/yaml/kubectl/kubectl_get.yaml
docs/yaml/kubectl/kubectl_label.yaml
docs/yaml/kubectl/kubectl_logs.yaml
docs/yaml/kubectl/kubectl_namespace.yaml
+docs/yaml/kubectl/kubectl_options.yaml
docs/yaml/kubectl/kubectl_patch.yaml
docs/yaml/kubectl/kubectl_port-forward.yaml
docs/yaml/kubectl/kubectl_proxy.yaml
diff --git a/docs/man/man1/kubectl-options.1 b/docs/man/man1/kubectl-options.1
new file mode 100644
index 00000000000..b6fd7a0f989
--- /dev/null
+++ b/docs/man/man1/kubectl-options.1
@@ -0,0 +1,3 @@
+This file is autogenerated, but we've stopped checking such files into the
+repository to reduce the need for rebases. Please run hack/generate-docs.sh to
+populate this file.
diff --git a/docs/user-guide/kubectl/kubectl_options.md b/docs/user-guide/kubectl/kubectl_options.md
new file mode 100644
index 00000000000..8f90c5c1cb1
--- /dev/null
+++ b/docs/user-guide/kubectl/kubectl_options.md
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
PLEASE NOTE: This document applies to the HEAD of the source tree
+
+If you are using a released version of Kubernetes, you should
+refer to the docs that go with that version.
+
+Documentation for other releases can be found at
+[releases.k8s.io](http://releases.k8s.io).
+
+--
+
+
+
+
+
+This file is autogenerated, but we've stopped checking such files into the
+repository to reduce the need for rebases. Please run hack/generate-docs.sh to
+populate this file.
+
+
+[]()
+
diff --git a/docs/yaml/kubectl/kubectl_options.yaml b/docs/yaml/kubectl/kubectl_options.yaml
new file mode 100644
index 00000000000..b6fd7a0f989
--- /dev/null
+++ b/docs/yaml/kubectl/kubectl_options.yaml
@@ -0,0 +1,3 @@
+This file is autogenerated, but we've stopped checking such files into the
+repository to reduce the need for rebases. Please run hack/generate-docs.sh to
+populate this file.
diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go
index 958cc533351..273e59a16e3 100644
--- a/pkg/kubectl/cmd/cmd.go
+++ b/pkg/kubectl/cmd/cmd.go
@@ -17,16 +17,18 @@ limitations under the License.
package cmd
import (
+ "fmt"
"io"
- "github.com/golang/glog"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
"k8s.io/kubernetes/pkg/kubectl/cmd/rollout"
"k8s.io/kubernetes/pkg/kubectl/cmd/set"
+ "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/flag"
+ "github.com/golang/glog"
"github.com/spf13/cobra"
)
@@ -222,59 +224,89 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
Run: runHelp,
BashCompletionFunction: bash_completion_func,
}
- cmds.SetHelpTemplate(help_template)
- cmds.SetUsageTemplate(usage_template)
f.BindFlags(cmds.PersistentFlags())
f.BindExternalFlags(cmds.PersistentFlags())
- cmds.SetHelpCommand(NewCmdHelp(f, out))
-
// From this point and forward we get warnings on flags that contain "_" separators
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
- cmds.AddCommand(NewCmdGet(f, out, err))
- cmds.AddCommand(set.NewCmdSet(f, out))
- cmds.AddCommand(NewCmdDescribe(f, out))
- cmds.AddCommand(NewCmdCreate(f, out))
- cmds.AddCommand(NewCmdReplace(f, out))
- cmds.AddCommand(NewCmdPatch(f, out))
- cmds.AddCommand(NewCmdDelete(f, out))
- cmds.AddCommand(NewCmdEdit(f, out, err))
- cmds.AddCommand(NewCmdApply(f, out))
+ groups := templates.CommandGroups{
+ {
+ Message: "Basic Commands (Beginner):",
+ Commands: []*cobra.Command{
+ NewCmdCreate(f, out),
+ NewCmdExposeService(f, out),
+ NewCmdRun(f, in, out, err),
+ set.NewCmdSet(f, out),
+ },
+ },
+ {
+ Message: "Basic Commands (Intermediate):",
+ Commands: []*cobra.Command{
+ NewCmdGet(f, out, err),
+ NewCmdExplain(f, out),
+ NewCmdEdit(f, out, err),
+ NewCmdDelete(f, out),
+ },
+ },
+ {
+ Message: "Deploy Commands:",
+ Commands: []*cobra.Command{
+ rollout.NewCmdRollout(f, out),
+ NewCmdRollingUpdate(f, out),
+ NewCmdScale(f, out),
+ NewCmdAutoscale(f, out),
+ },
+ },
+ {
+ Message: "Cluster Management Commands:",
+ Commands: []*cobra.Command{
+ NewCmdClusterInfo(f, out),
+ NewCmdTop(f, out),
+ NewCmdCordon(f, out),
+ NewCmdUncordon(f, out),
+ NewCmdDrain(f, out),
+ NewCmdTaint(f, out),
+ },
+ },
+ {
+ Message: "Troubleshooting and Debugging Commands:",
+ Commands: []*cobra.Command{
+ NewCmdDescribe(f, out),
+ NewCmdLogs(f, out),
+ NewCmdAttach(f, in, out, err),
+ NewCmdExec(f, in, out, err),
+ NewCmdPortForward(f, out, err),
+ NewCmdProxy(f, out),
+ },
+ },
+ {
+ Message: "Advanced Commands:",
+ Commands: []*cobra.Command{
+ NewCmdApply(f, out),
+ NewCmdPatch(f, out),
+ NewCmdReplace(f, out),
+ NewCmdConvert(f, out),
+ },
+ },
+ {
+ Message: "Settings Commands:",
+ Commands: []*cobra.Command{
+ NewCmdLabel(f, out),
+ NewCmdAnnotate(f, out),
+ NewCmdCompletion(f, out),
+ },
+ },
+ }
+ groups.Add(cmds)
- cmds.AddCommand(NewCmdNamespace(out))
- cmds.AddCommand(NewCmdLogs(f, out))
- cmds.AddCommand(NewCmdRollingUpdate(f, out))
- cmds.AddCommand(NewCmdScale(f, out))
- cmds.AddCommand(NewCmdCordon(f, out))
- cmds.AddCommand(NewCmdDrain(f, out))
- cmds.AddCommand(NewCmdUncordon(f, out))
-
- cmds.AddCommand(NewCmdAttach(f, in, out, err))
- cmds.AddCommand(NewCmdExec(f, in, out, err))
- cmds.AddCommand(NewCmdPortForward(f, out, err))
- cmds.AddCommand(NewCmdProxy(f, out))
-
- cmds.AddCommand(NewCmdRun(f, in, out, err))
- cmds.AddCommand(NewCmdStop(f, out))
- cmds.AddCommand(NewCmdExposeService(f, out))
- cmds.AddCommand(NewCmdAutoscale(f, out))
- cmds.AddCommand(rollout.NewCmdRollout(f, out))
-
- cmds.AddCommand(NewCmdLabel(f, out))
- cmds.AddCommand(NewCmdAnnotate(f, out))
- cmds.AddCommand(NewCmdTaint(f, out))
-
- cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), out))
- cmds.AddCommand(NewCmdClusterInfo(f, out))
- cmds.AddCommand(NewCmdApiVersions(f, out))
- cmds.AddCommand(NewCmdVersion(f, out))
- cmds.AddCommand(NewCmdExplain(f, out))
- cmds.AddCommand(NewCmdConvert(f, out))
- cmds.AddCommand(NewCmdCompletion(f, out))
-
- cmds.AddCommand(NewCmdTop(f, out))
+ filters := []string{
+ "options",
+ Deprecated("kubectl", "delete", cmds, NewCmdStop(f, out)),
+ Deprecated("kubectl", "config set-context", cmds, NewCmdNamespace(out)),
+ }
+ templates.ActsAsRootCommand(cmds, filters, groups...)
if cmds.Flag("namespace") != nil {
if cmds.Flag("namespace").Annotations == nil {
@@ -286,6 +318,11 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
)
}
+ cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), out))
+ cmds.AddCommand(NewCmdVersion(f, out))
+ cmds.AddCommand(NewCmdApiVersions(f, out))
+ cmds.AddCommand(NewCmdOptions(out))
+
return cmds
}
@@ -296,3 +333,10 @@ func runHelp(cmd *cobra.Command, args []string) {
func printDeprecationWarning(command, alias string) {
glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
}
+
+func Deprecated(baseName, to string, parent, cmd *cobra.Command) string {
+ cmd.Long = fmt.Sprintf("Deprecated: This command is deprecated, all its functionalities are covered by \"%s %s\"", baseName, to)
+ cmd.Short = fmt.Sprintf("Deprecated: %s", to)
+ parent.AddCommand(cmd)
+ return cmd.Name()
+}
diff --git a/pkg/kubectl/cmd/options.go b/pkg/kubectl/cmd/options.go
new file mode 100644
index 00000000000..a3538ef9fb4
--- /dev/null
+++ b/pkg/kubectl/cmd/options.go
@@ -0,0 +1,39 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+ "io"
+
+ "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
+
+ "github.com/spf13/cobra"
+)
+
+// NewCmdOptions implements the options command
+func NewCmdOptions(out io.Writer) *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "options",
+ Run: func(cmd *cobra.Command, args []string) {
+ cmd.Usage()
+ },
+ }
+
+ templates.UseOptionsTemplates(cmd)
+
+ return cmd
+}
diff --git a/pkg/kubectl/cmd/templates/templater.go b/pkg/kubectl/cmd/templates/templater.go
new file mode 100644
index 00000000000..b51f45a1630
--- /dev/null
+++ b/pkg/kubectl/cmd/templates/templater.go
@@ -0,0 +1,300 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package templates
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+ "text/template"
+ "unicode"
+
+ "github.com/spf13/cobra"
+ flag "github.com/spf13/pflag"
+)
+
+// Content of this package was borrowed from openshift/origin.
+
+type CommandGroup struct {
+ Message string
+ Commands []*cobra.Command
+}
+
+type CommandGroups []CommandGroup
+
+func (g CommandGroups) Add(c *cobra.Command) {
+ for _, group := range g {
+ for _, command := range group.Commands {
+ c.AddCommand(command)
+ }
+ }
+}
+
+func (g CommandGroups) Has(c *cobra.Command) bool {
+ for _, group := range g {
+ for _, command := range group.Commands {
+ if command == c {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func AddAdditionalCommands(g CommandGroups, message string, cmds []*cobra.Command) CommandGroups {
+ group := CommandGroup{Message: message}
+ for _, c := range cmds {
+ // Don't show commands that has no short description
+ if !g.Has(c) && len(c.Short) != 0 {
+ group.Commands = append(group.Commands, c)
+ }
+ }
+ if len(group.Commands) == 0 {
+ return g
+ }
+ return append(g, group)
+}
+
+func filter(cmds []*cobra.Command, names ...string) []*cobra.Command {
+ out := []*cobra.Command{}
+ for _, c := range cmds {
+ if c.Hidden {
+ continue
+ }
+ skip := false
+ for _, name := range names {
+ if name == c.Name() {
+ skip = true
+ break
+ }
+ }
+ if skip {
+ continue
+ }
+ out = append(out, c)
+ }
+ return out
+}
+
+type FlagExposer interface {
+ ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer
+}
+
+func ActsAsRootCommand(cmd *cobra.Command, filters []string, groups ...CommandGroup) FlagExposer {
+ if cmd == nil {
+ panic("nil root command")
+ }
+ cmd.SetHelpTemplate(MainHelpTemplate())
+ templater := &templater{
+ RootCmd: cmd,
+ UsageTemplate: MainUsageTemplate(),
+ CommandGroups: groups,
+ Filtered: filters,
+ }
+ cmd.SetUsageFunc(templater.UsageFunc())
+ return templater
+}
+
+func UseOptionsTemplates(cmd *cobra.Command) {
+ cmd.SetHelpTemplate(OptionsHelpTemplate())
+ templater := &templater{
+ UsageTemplate: OptionsUsageTemplate(),
+ }
+ cmd.SetUsageFunc(templater.UsageFunc())
+}
+
+type templater struct {
+ UsageTemplate string
+ RootCmd *cobra.Command
+ CommandGroups
+ Filtered []string
+}
+
+func (templater *templater) ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer {
+ cmd.SetUsageFunc(templater.UsageFunc(flags...))
+ return templater
+}
+
+func (templater *templater) UsageFunc(exposedFlags ...string) func(*cobra.Command) error {
+ return func(c *cobra.Command) error {
+ t := template.New("custom")
+
+ t.Funcs(template.FuncMap{
+ "trim": strings.TrimSpace,
+ "trimRight": func(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) },
+ "trimLeft": func(s string) string { return strings.TrimLeftFunc(s, unicode.IsSpace) },
+ "gt": cobra.Gt,
+ "eq": cobra.Eq,
+ "rpad": rpad,
+ "appendIfNotPresent": appendIfNotPresent,
+ "flagsNotIntersected": flagsNotIntersected,
+ "visibleFlags": visibleFlags,
+ "flagsUsages": flagsUsages,
+ "indentLines": indentLines,
+ "cmdGroups": templater.cmdGroups,
+ "rootCmd": templater.rootCmdName,
+ "isRootCmd": templater.isRootCmd,
+ "optionsCmdFor": templater.optionsCmdFor,
+ "usageLine": templater.usageLine,
+ "exposed": func(c *cobra.Command) *flag.FlagSet {
+ exposed := flag.NewFlagSet("exposed", flag.ContinueOnError)
+ if len(exposedFlags) > 0 {
+ for _, name := range exposedFlags {
+ if flag := c.Flags().Lookup(name); flag != nil {
+ exposed.AddFlag(flag)
+ }
+ }
+ }
+ return exposed
+ },
+ })
+
+ template.Must(t.Parse(templater.UsageTemplate))
+ return t.Execute(c.OutOrStdout(), c)
+ }
+}
+
+func (templater *templater) cmdGroups(c *cobra.Command, all []*cobra.Command) []CommandGroup {
+ if len(templater.CommandGroups) > 0 && c == templater.RootCmd {
+ all = filter(all, templater.Filtered...)
+ return AddAdditionalCommands(templater.CommandGroups, "Other Commands:", all)
+ }
+ all = filter(all, "options")
+ return []CommandGroup{
+ {
+ Message: "Available Commands:",
+ Commands: all,
+ },
+ }
+}
+
+func (t *templater) rootCmdName(c *cobra.Command) string {
+ return t.rootCmd(c).CommandPath()
+}
+
+func (t *templater) isRootCmd(c *cobra.Command) bool {
+ return t.rootCmd(c) == c
+}
+
+func (t *templater) parents(c *cobra.Command) []*cobra.Command {
+ parents := []*cobra.Command{c}
+ for current := c; !t.isRootCmd(current) && current.HasParent(); {
+ current = current.Parent()
+ parents = append(parents, current)
+ }
+ return parents
+}
+
+func (t *templater) rootCmd(c *cobra.Command) *cobra.Command {
+ if c != nil && !c.HasParent() {
+ return c
+ }
+ if t.RootCmd == nil {
+ panic("nil root cmd")
+ }
+ return t.RootCmd
+}
+
+func (t *templater) optionsCmdFor(c *cobra.Command) string {
+ if !c.Runnable() {
+ return ""
+ }
+ rootCmdStructure := t.parents(c)
+ for i := len(rootCmdStructure) - 1; i >= 0; i-- {
+ cmd := rootCmdStructure[i]
+ if _, _, err := cmd.Find([]string{"options"}); err == nil {
+ return cmd.CommandPath() + " options"
+ }
+ }
+ return ""
+}
+
+func (t *templater) usageLine(c *cobra.Command) string {
+ usage := c.UseLine()
+ suffix := "[options]"
+ if c.HasFlags() && !strings.Contains(usage, suffix) {
+ usage += " " + suffix
+ }
+ return usage
+}
+
+func flagsUsages(f *flag.FlagSet) string {
+ x := new(bytes.Buffer)
+
+ f.VisitAll(func(flag *flag.Flag) {
+ if flag.Hidden {
+ return
+ }
+ format := "--%s=%s: %s\n"
+
+ if flag.Value.Type() == "string" {
+ format = "--%s='%s': %s\n"
+ }
+
+ if len(flag.Shorthand) > 0 {
+ format = " -%s, " + format
+ } else {
+ format = " %s " + format
+ }
+
+ fmt.Fprintf(x, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage)
+ })
+
+ return x.String()
+}
+
+func rpad(s string, padding int) string {
+ template := fmt.Sprintf("%%-%ds", padding)
+ return fmt.Sprintf(template, s)
+}
+
+func indentLines(s string, indentation int) string {
+ r := []string{}
+ for _, line := range strings.Split(s, "\n") {
+ indented := strings.Repeat(" ", indentation) + line
+ r = append(r, indented)
+ }
+ return strings.Join(r, "\n")
+}
+
+func appendIfNotPresent(s, stringToAppend string) string {
+ if strings.Contains(s, stringToAppend) {
+ return s
+ }
+ return s + " " + stringToAppend
+}
+
+func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet {
+ f := flag.NewFlagSet("notIntersected", flag.ContinueOnError)
+ l.VisitAll(func(flag *flag.Flag) {
+ if r.Lookup(flag.Name) == nil {
+ f.AddFlag(flag)
+ }
+ })
+ return f
+}
+
+func visibleFlags(l *flag.FlagSet) *flag.FlagSet {
+ hidden := "help"
+ f := flag.NewFlagSet("visible", flag.ContinueOnError)
+ l.VisitAll(func(flag *flag.Flag) {
+ if flag.Name != hidden {
+ f.AddFlag(flag)
+ }
+ })
+ return f
+}
diff --git a/pkg/kubectl/cmd/templates/templates.go b/pkg/kubectl/cmd/templates/templates.go
new file mode 100644
index 00000000000..d89e6007481
--- /dev/null
+++ b/pkg/kubectl/cmd/templates/templates.go
@@ -0,0 +1,99 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package templates
+
+import "strings"
+
+func MainHelpTemplate() string {
+ return decorate(mainHelpTemplate, false)
+}
+
+func MainUsageTemplate() string {
+ return decorate(mainUsageTemplate, true) + "\n"
+}
+
+func OptionsHelpTemplate() string {
+ return decorate(optionsHelpTemplate, false)
+}
+
+func OptionsUsageTemplate() string {
+ return decorate(optionsUsageTemplate, false)
+}
+
+func decorate(template string, trim bool) string {
+ if trim && len(strings.Trim(template, " ")) > 0 {
+ template = strings.Trim(template, "\n")
+ }
+ return template
+}
+
+const (
+ vars = `{{$isRootCmd := isRootCmd .}}` +
+ `{{$rootCmd := rootCmd .}}` +
+ `{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` +
+ `{{$explicitlyExposedFlags := exposed .}}` +
+ `{{$optionsCmdFor := optionsCmdFor .}}` +
+ `{{$usageLine := usageLine .}}`
+
+ mainHelpTemplate = `{{with or .Long .Short }}{{. | trim}}{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
+
+ mainUsageTemplate = vars +
+ // ALIASES
+ `{{if gt .Aliases 0}}
+
+Aliases:
+{{.NameAndAliases}}{{end}}` +
+
+ // EXAMPLES
+ `{{if .HasExample}}
+
+Examples:
+{{ indentLines (.Example | trimLeft) 2 }}{{end}}` +
+
+ // SUBCOMMANDS
+ `{{ if .HasAvailableSubCommands}}
+{{range cmdGroups . .Commands}}
+{{.Message}}
+{{range .Commands}}{{if .Runnable}} {{rpad .Name .NamePadding }} {{.Short}}
+{{end}}{{end}}{{end}}{{end}}` +
+
+ // VISIBLE FLAGS
+ `{{ if or $visibleFlags.HasFlags $explicitlyExposedFlags.HasFlags}}
+
+Options:
+{{ if $visibleFlags.HasFlags}}{{flagsUsages $visibleFlags}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{flagsUsages $explicitlyExposedFlags}}{{end}}{{end}}` +
+
+ // USAGE LINE
+ `{{if and .Runnable (ne .UseLine "") (ne .UseLine $rootCmd)}}
+Usage:
+ {{$usageLine}}
+{{end}}` +
+
+ // TIPS: --help
+ `{{ if .HasSubCommands }}
+Use "{{$rootCmd}} --help" for more information about a given command.{{end}}` +
+
+ // TIPS: global options
+ `{{ if $optionsCmdFor}}
+Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands).{{end}}`
+
+ optionsHelpTemplate = ``
+
+ optionsUsageTemplate = `{{ if .HasInheritedFlags}}The following options can be passed to any command:
+
+{{flagsUsages .InheritedFlags}}{{end}}`
+)