Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make help and usage templates consistent across all commands #1584

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Integrating help and usage templates in all commands
  • Loading branch information
fabianofranz committed Apr 2, 2015
commit ae0b905ec5c3ade9f6cf0448891a63d449964b22
3 changes: 0 additions & 3 deletions pkg/cmd/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
exregistry "github.com/openshift/origin/pkg/cmd/experimental/registry"
exrouter "github.com/openshift/origin/pkg/cmd/experimental/router"
"github.com/openshift/origin/pkg/cmd/server/admin"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/openshift/origin/pkg/version"
)
Expand Down Expand Up @@ -43,8 +42,6 @@ func NewCommandAdmin(name, fullName string, out io.Writer) *cobra.Command {

f := clientcmd.New(cmds.PersistentFlags())

templates.UseAdminTemplates(cmds)

cmds.AddCommand(project.NewCmdNewProject(f, fullName, "new-project"))
cmds.AddCommand(policy.NewCommandPolicy(f, fullName, "policy"))
cmds.AddCommand(exrouter.NewCmdRouter(f, fullName, "router", out))
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/openshift/origin/pkg/cmd/cli/cmd"
"github.com/openshift/origin/pkg/cmd/experimental/config"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/openshift/origin/pkg/version"
)
Expand Down Expand Up @@ -62,8 +61,6 @@ func NewCommandCLI(name, fullName string) *cobra.Command {
in := os.Stdin
out := os.Stdout

templates.UseCliTemplates(cmds)

cmds.AddCommand(cmd.NewCmdLogin(f, in, out))
cmds.AddCommand(cmd.NewCmdProject(f, out))
cmds.AddCommand(cmd.NewCmdNewApplication(fullName, f, out))
Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/cli/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ func NewCmdLogin(f *osclientcmd.Factory, reader io.Reader, out io.Writer) *cobra
cmds.Flags().StringVarP(&options.Password, "password", "p", "", "Password, will prompt if not provided")

templater := templates.Templater{
UsageTemplate: templates.CliUsageTemplate(),
Exposed: []string{"server", "username", "password", "certificate-authority", "insecure-skip-tls-verify", "context"},
UsageTemplate: templates.MainUsageTemplate(),
Exposed: []string{"server", "certificate-authority", "insecure-skip-tls-verify", "context"},
}
cmds.SetUsageFunc(templater.UsageFunc())
cmds.SetHelpTemplate(templates.CliHelpTemplate())
cmds.SetHelpTemplate(templates.MainHelpTemplate())

return cmds
}
Expand Down
5 changes: 0 additions & 5 deletions pkg/cmd/infra/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift/origin/pkg/build/builder/cmd"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/version"
)

Expand All @@ -26,8 +25,6 @@ func NewCommandSTIBuilder(name string) *cobra.Command {
},
}

templates.UseMainTemplates(cmd)

cmd.AddCommand(version.NewVersionCommand(name))
return cmd
}
Expand All @@ -49,8 +46,6 @@ func NewCommandDockerBuilder(name string) *cobra.Command {
cmd.RunDockerBuild()
},
}
cmd.SetUsageTemplate(templates.MainUsageTemplate())
cmd.SetHelpTemplate(templates.MainHelpTemplate())
cmd.AddCommand(version.NewVersionCommand(name))
return cmd
}
3 changes: 0 additions & 3 deletions pkg/cmd/infra/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift/origin/pkg/api/latest"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/cmd/util"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
deployapi "github.com/openshift/origin/pkg/deploy/api"
Expand Down Expand Up @@ -67,8 +66,6 @@ func NewCommandDeployer(name string) *cobra.Command {
},
}

templates.UseMainTemplates(cmd)

cmd.AddCommand(version.NewVersionCommand(name))

flag := cmd.Flags()
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/infra/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/golang/glog"
"github.com/spf13/cobra"

"github.com/openshift/origin/pkg/cmd/templates"
"github.com/openshift/origin/pkg/cmd/util"
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
"github.com/openshift/origin/pkg/router"
Expand Down Expand Up @@ -52,8 +51,6 @@ func NewCommandTemplateRouter(name string) *cobra.Command {
},
}

templates.UseMainTemplates(cmd)

cmd.AddCommand(version.NewVersionCommand(name))

flag := cmd.Flags()
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/openshift/openshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func CommandFor(basename string) *cobra.Command {
cmd = NewCommandOpenShift()
}

templates.UseMainTemplates(cmd)
flagtypes.GLog(cmd.PersistentFlags())

return cmd
Expand All @@ -79,8 +80,6 @@ func NewCommandOpenShift() *cobra.Command {
},
}

templates.UseMainTemplates(root)

startAllInOne, _ := start.NewCommandStartAllInOne()
root.AddCommand(startAllInOne)
root.AddCommand(admin.NewCommandAdmin("admin", "openshift admin", os.Stdout))
Expand Down
128 changes: 78 additions & 50 deletions pkg/cmd/templates/templater.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ func (templater *Templater) UsageFunc() func(*cobra.Command) error {
t := template.New("custom")

t.Funcs(template.FuncMap{
"trim": strings.TrimSpace,
"gt": cobra.Gt,
"eq": cobra.Eq,
"rpad": func(s string, padding int) string {
template := fmt.Sprintf("%%-%ds", padding)
return fmt.Sprintf(template, s)
},
"exposed": func(*cobra.Command) *flag.FlagSet {
"trim": strings.TrimSpace,
"gt": cobra.Gt,
"eq": cobra.Eq,
"rpad": rpad,
"flagsNotIntersected": flagsNotIntersected,
"flagsUsages": flagsUsages,
"rootCmd": rootCmdName,
"isRootCmd": isRootCmd,
"exposed": func(c *cobra.Command) *flag.FlagSet {
exposed := flag.NewFlagSet("exposed", flag.ContinueOnError)
if len(templater.Exposed) > 0 {
for _, name := range templater.Exposed {
Expand All @@ -38,55 +39,13 @@ func (templater *Templater) UsageFunc() func(*cobra.Command) error {
}
return exposed
},
"flagsNotIntersected": func(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
},
"flagsUsages": func(f *flag.FlagSet) string {
x := new(bytes.Buffer)

f.VisitAll(func(flag *flag.Flag) {
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()
},
})

template.Must(t.Parse(templater.UsageTemplate))
return t.Execute(c.Out(), c)
}
}

func UseCliTemplates(cmd *cobra.Command) {
cmd.SetHelpTemplate(CliHelpTemplate())
templater := &Templater{UsageTemplate: CliUsageTemplate()}
cmd.SetUsageFunc(templater.UsageFunc())
}

func UseAdminTemplates(cmd *cobra.Command) {
cmd.SetHelpTemplate(AdminHelpTemplate())
templater := &Templater{UsageTemplate: AdminUsageTemplate()}
cmd.SetUsageFunc(templater.UsageFunc())
}

func UseMainTemplates(cmd *cobra.Command) {
cmd.SetHelpTemplate(MainHelpTemplate())
templater := &Templater{UsageTemplate: MainUsageTemplate()}
Expand All @@ -98,3 +57,72 @@ func UseOptionsTemplates(cmd *cobra.Command) {
templater := &Templater{UsageTemplate: OptionsUsageTemplate()}
cmd.SetUsageFunc(templater.UsageFunc())
}

func rootCmd(c *cobra.Command) []string {
root := []string{}

var appendCmdName func(*cobra.Command)
appendCmdName = func(x *cobra.Command) {
if x.HasParent() {
appendCmdName(x.Parent())
root = append(root, x.Parent().Name())
}
}
appendCmdName(c)

if cName := c.Name(); c.HasSubCommands() && len(root) == 1 && root[0] == "openshift" && cName != "openshift" {
root = append(root, cName)
}

if len(root) == 0 {
root = append(root, c.Name())
}

return root
}

func rootCmdName(c *cobra.Command) string {
return strings.Join(rootCmd(c), " ")
}

func isRootCmd(c *cobra.Command) bool {
r := rootCmd(c)
return c.HasSubCommands() && r[len(r)-1] == c.Name()
}

func flagsUsages(f *flag.FlagSet) string {
x := new(bytes.Buffer)

f.VisitAll(func(flag *flag.Flag) {
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 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
}
74 changes: 11 additions & 63 deletions pkg/cmd/templates/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,7 @@ func MainHelpTemplate() string {
}

func MainUsageTemplate() string {
return decorate(mainUsageTemplate, false)
}

func CliHelpTemplate() string {
return decorate(cliHelpTemplate, false)
}

func CliUsageTemplate() string {
return decorate(cliUsageTemplate, true)
}

func AdminHelpTemplate() string {
return decorate(adminHelpTemplate, false)
}

func AdminUsageTemplate() string {
return decorate(adminUsageTemplate, true)
return decorate(mainUsageTemplate, true)
}

func OptionsHelpTemplate() string {
Expand All @@ -36,65 +20,29 @@ func OptionsUsageTemplate() string {

func decorate(template string, trim bool) string {
if trim && len(strings.Trim(template, " ")) > 0 {
trimmed := strings.Trim(template, "\n")
return funcs + trimmed
template = strings.Trim(template, "\n")
}
return funcs + template
return template
}

const (
// TODO: $isRootCmd should be done in code, not in the template
funcIsRootCmd = `{{$isRootCmd := or (and (eq .Name "cli") (eq .Root.Name "openshift")) (eq .Name "osc") (and (eq .Name "admin") (eq .Root.Name "openshift")) (eq .Name "osadm")}}`
funcRootCli = `{{define "rootCli"}}{{if eq .Root.Name "osadm"}}osadm{{else}}{{if eq .Root.Name "osc"}}osc{{else}}openshift {{.Name}}{{end}}{{end}}{{end}}`
funcs = funcIsRootCmd + funcRootCli
vars = `{{$isRootCmd := isRootCmd .}}` +
`{{$rootCmd := rootCmd .}}` +
`{{$explicitlyExposedFlags := exposed .}}` +
`{{$localNotPersistentFlags := flagsNotIntersected .LocalFlags .PersistentFlags}}`

mainHelpTemplate = `{{.Long | trim}}
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`

mainUsageTemplate = `{{ $cmd := . }}
Usage: {{if .Runnable}}
{{.UseLine}}{{if .HasFlags}} [options]{{end}}{{end}}{{if .HasSubCommands}}
{{ .CommandPath}} <command>{{end}}{{if gt .Aliases 0}}

Aliases:
{{.NameAndAliases}}{{end}}
{{ if .HasSubCommands}}
Available Commands: {{range .Commands}}{{if .Runnable}}
{{rpad .Use .UsagePadding }} {{.Short}}{{end}}{{end}}
{{end}}
{{ if .HasLocalFlags}}Options:
{{flagsUsages .LocalFlags}}{{end}}
{{ if .HasInheritedFlags}}Global Options:
{{flagsUsages .InheritedFlags}}{{end}}{{ if .HasSubCommands }}
Use "{{.Root.Name}} <command> --help" for more information about a given command.
{{end}}`

cliHelpTemplate = `{{.Long | trim}}
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`

cliUsageTemplate = `{{ $cmd := . }}{{$explicitlyExposedFlags := exposed .}}{{$localNotPersistentFlags := flagsNotIntersected .LocalFlags .PersistentFlags}}{{ if .HasSubCommands}}
Available Commands: {{range .Commands}}{{if .Runnable}}{{if ne .Name "options"}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}
{{end}}
{{ if or $localNotPersistentFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options:
{{ if $localNotPersistentFlags.HasFlags}}{{flagsUsages $localNotPersistentFlags}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{flagsUsages $explicitlyExposedFlags}}{{end}}
{{end}}{{ if not $isRootCmd}}Use "{{template "rootCli" .}} --help" for a list of all commands available in {{template "rootCli" .}}.
{{end}}{{ if .HasSubCommands }}Use "{{template "rootCli" .}} <command> --help" for more information about a given command.
{{end}}{{ if .HasInheritedFlags}}Use "{{template "rootCli" .}} options" for a list of global command-line options (applies to all commands).
{{end}}`

adminHelpTemplate = `{{.Long | trim}}
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`

adminUsageTemplate = `{{ $cmd := . }}{{$explicitlyExposedFlags := exposed .}}{{$localNotPersistentFlags := flagsNotIntersected .LocalFlags .PersistentFlags}}{{ if .HasSubCommands}}
mainUsageTemplate = vars + `{{ $cmd := . }}{{ if .HasSubCommands}}
Available Commands: {{range .Commands}}{{if .Runnable}}{{if ne .Name "options"}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}
{{end}}
{{ if or $localNotPersistentFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options:
{{ if $localNotPersistentFlags.HasFlags}}{{flagsUsages $localNotPersistentFlags}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{flagsUsages $explicitlyExposedFlags}}{{end}}
{{end}}{{ if not $isRootCmd}}Use "{{template "rootCli" .}} --help" for a list of all commands available in {{template "rootCli" .}}.
{{end}}{{ if .HasSubCommands }}Use "{{template "rootCli" .}} <command> --help" for more information about a given command.
{{end}}{{ if .HasInheritedFlags}}Use "{{template "rootCli" .}} options" for a list of global command-line options (applies to all commands).
{{end}}{{ if not $isRootCmd}}Use "{{$rootCmd}} --help" for a list of all commands available in {{$rootCmd}}.
{{end}}{{ if .HasSubCommands }}Use "{{$rootCmd}} <command> --help" for more information about a given command.
{{end}}{{ if and .HasInheritedFlags (not $isRootCmd)}}Use "{{$rootCmd}} options" for a list of global command-line options (applies to all commands).
{{end}}`

optionsHelpTemplate = ``
Expand Down