| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You 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 ( |
| "bytes" |
| "fmt" |
| "github.com/apache/servicecomb-service-center/scctl/pkg/version" |
| "github.com/spf13/cobra" |
| "github.com/spf13/pflag" |
| "io" |
| "os" |
| "strings" |
| "text/tabwriter" |
| "text/template" |
| ) |
| |
| var ( |
| commandUsageTemplate *template.Template |
| templFuncs = template.FuncMap{ |
| "descToLines": func(s string) []string { |
| // trim leading/trailing whitespace and split into slice of lines |
| return strings.Split(strings.Trim(s, "\n\t "), "\n") |
| }, |
| "cmdName": func(cmd *cobra.Command, startCmd *cobra.Command) string { |
| parts := []string{cmd.Name()} |
| for cmd.HasParent() && cmd.Parent().Name() != startCmd.Name() { |
| cmd = cmd.Parent() |
| parts = append([]string{cmd.Name()}, parts...) |
| } |
| return strings.Join(parts, " ") |
| }, |
| } |
| ) |
| |
| func init() { |
| commandUsage := ` |
| {{ $cmd := .Cmd }}\ |
| {{ $cmdname := cmdName .Cmd .Cmd.Root }}\ |
| NAME: |
| {{ if not .Cmd.HasParent }}\ |
| {{printf "\t%s - %s" .Cmd.Name .Cmd.Short}} |
| {{else}}\ |
| {{printf "\t%s - %s" $cmdname .Cmd.Short}} |
| {{end}}\ |
| |
| USAGE: |
| {{printf "\t%s" .Cmd.UseLine}} |
| {{ if .Cmd.HasExample }}\ |
| |
| EXAMPLE: |
| {{printf "\t%s" .Cmd.Example}} |
| {{end}}\ |
| {{ if not .Cmd.HasParent }}\ |
| |
| VERSION: |
| {{printf "\t%s" .Version}} |
| {{end}}\ |
| {{if .Cmd.HasSubCommands}}\ |
| |
| COMMANDS: |
| {{range .SubCommands}}\ |
| {{ $cmdname := cmdName . $cmd }}\ |
| {{ if .Runnable }}\ |
| {{printf "\t%s\t%s" $cmdname .Short}} |
| {{end}}\ |
| {{end}}\ |
| {{end}}\ |
| {{ if .Cmd.Long }}\ |
| |
| DESCRIPTION: |
| {{range $line := descToLines .Cmd.Long}}{{printf "\t%s" $line}} |
| {{end}}\ |
| {{end}}\ |
| {{if .Cmd.HasLocalFlags}}\ |
| |
| OPTIONS: |
| {{.LocalFlags}}\ |
| {{end}}\ |
| {{if .Cmd.HasInheritedFlags}}\ |
| |
| GLOBAL OPTIONS: |
| {{.GlobalFlags}}\ |
| {{end}} |
| `[1:] |
| |
| commandUsageTemplate = template.Must(template.New("command_usage").Funcs(templFuncs).Parse(strings.Replace(commandUsage, "\\\n", "", -1))) |
| } |
| |
| func toolFlagUsages(flagSet *pflag.FlagSet) string { |
| x := new(bytes.Buffer) |
| |
| flagSet.VisitAll(func(flag *pflag.Flag) { |
| if len(flag.Deprecated) > 0 { |
| return |
| } |
| format := "" |
| if len(flag.Shorthand) > 0 { |
| format = " -%s, --%s" |
| } else { |
| format = " %s --%s" |
| } |
| if len(flag.NoOptDefVal) > 0 { |
| format = format + "[" |
| } |
| if flag.Value.Type() == "string" { |
| // put quotes on the value |
| format = format + "=%q" |
| } else { |
| format = format + "=%s" |
| } |
| if len(flag.NoOptDefVal) > 0 { |
| format = format + "]" |
| } |
| format = format + "\t%s\n" |
| shorthand := flag.Shorthand |
| fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage) |
| }) |
| |
| return x.String() |
| } |
| |
| func getSubCommands(cmd *cobra.Command) []*cobra.Command { |
| var subCommands []*cobra.Command |
| for _, subCmd := range cmd.Commands() { |
| subCommands = append(subCommands, subCmd) |
| subCommands = append(subCommands, getSubCommands(subCmd)...) |
| } |
| return subCommands |
| } |
| |
| func UsageFunc(cmd *cobra.Command) error { |
| subCommands := getSubCommands(cmd) |
| tabOut := getTabOutWithWriter(os.Stdout) |
| if err := commandUsageTemplate.Execute(tabOut, struct { |
| Cmd *cobra.Command |
| LocalFlags string |
| GlobalFlags string |
| SubCommands []*cobra.Command |
| Version string |
| }{ |
| cmd, |
| toolFlagUsages(cmd.LocalFlags()), |
| toolFlagUsages(cmd.InheritedFlags()), |
| subCommands, |
| version.Ver().Version, |
| }); err != nil { |
| return err |
| } |
| return tabOut.Flush() |
| } |
| |
| func getTabOutWithWriter(writer io.Writer) *tabwriter.Writer { |
| aTabOut := new(tabwriter.Writer) |
| aTabOut.Init(writer, 0, 8, 1, '\t', 0) |
| return aTabOut |
| } |