github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/help.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "bytes" 19 "fmt" 20 "os" 21 "strings" 22 "text/template" 23 24 "github.com/appc/spec/schema" 25 "github.com/rkt/rkt/version" 26 "github.com/spf13/cobra" 27 "github.com/spf13/pflag" 28 ) 29 30 var ( 31 commandUsageTemplate *template.Template 32 templFuncs = template.FuncMap{ 33 "descToLines": func(s string) []string { 34 // trim leading/trailing whitespace and split into slice of lines 35 return strings.Split(strings.Trim(s, "\n\t "), "\n") 36 }, 37 "cmdName": func(cmd *cobra.Command, startCmd *cobra.Command) string { 38 parts := []string{cmd.Name()} 39 for cmd.HasParent() && cmd.Parent().Name() != startCmd.Name() { 40 cmd = cmd.Parent() 41 parts = append([]string{cmd.Name()}, parts...) 42 } 43 return strings.Join(parts, " ") 44 }, 45 } 46 ) 47 48 func init() { 49 commandUsage := ` 50 {{ $cmd := .Cmd }}\ 51 {{ $cmdname := cmdName .Cmd .Cmd.Root }}\ 52 NAME: 53 {{ if not .Cmd.HasParent }}\ 54 {{printf "\t%s - %s" .Cmd.Name .Cmd.Short}} 55 {{else}}\ 56 {{printf "\t%s - %s" $cmdname .Cmd.Short}} 57 {{end}}\ 58 59 USAGE: 60 {{printf "\t%s" .Cmd.UseLine}} 61 {{ if not .Cmd.HasParent }}\ 62 63 VERSION: 64 {{printf "\t%s" .Version}} 65 {{end}}\ 66 {{if .Cmd.HasSubCommands}}\ 67 68 COMMANDS: 69 {{range .SubCommands}}\ 70 {{ $cmdname := cmdName . $cmd }}\ 71 {{ if .Runnable }}\ 72 {{printf "\t%s\t%s" $cmdname .Short}} 73 {{end}}\ 74 {{end}}\ 75 {{end}}\ 76 {{ if .Cmd.Long }}\ 77 78 DESCRIPTION: 79 {{range $line := descToLines .Cmd.Long}}{{printf "\t%s" $line}} 80 {{end}}\ 81 {{end}}\ 82 {{if .Cmd.HasLocalFlags}}\ 83 84 OPTIONS: 85 {{.LocalFlags}}\ 86 {{end}}\ 87 {{if .Cmd.HasInheritedFlags}}\ 88 89 GLOBAL OPTIONS: 90 {{.GlobalFlags}}\ 91 {{end}} 92 `[1:] 93 94 commandUsageTemplate = template.Must(template.New("command_usage").Funcs(templFuncs).Parse(strings.Replace(commandUsage, "\\\n", "", -1))) 95 } 96 97 func rktFlagUsages(flagSet *pflag.FlagSet) string { 98 x := new(bytes.Buffer) 99 100 flagSet.VisitAll(func(flag *pflag.Flag) { 101 if len(flag.Deprecated) > 0 || flag.Hidden { 102 return 103 } 104 format := "" 105 if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { 106 format = " -%s, --%s" 107 } else { 108 format = " %s --%s" 109 } 110 if len(flag.NoOptDefVal) > 0 { 111 format = format + "[" 112 } 113 if flag.Value.Type() == "string" { 114 // put quotes on the value 115 format = format + "=%q" 116 } else { 117 format = format + "=%s" 118 } 119 if len(flag.NoOptDefVal) > 0 { 120 format = format + "]" 121 } 122 format = format + "\t%s\n" 123 shorthand := flag.Shorthand 124 fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage) 125 }) 126 127 return x.String() 128 } 129 130 func getSubCommands(cmd *cobra.Command) []*cobra.Command { 131 var subCommands []*cobra.Command 132 for _, subCmd := range cmd.Commands() { 133 if !subCmd.Hidden { 134 subCommands = append(subCommands, subCmd) 135 subCommands = append(subCommands, getSubCommands(subCmd)...) 136 } 137 } 138 return subCommands 139 } 140 141 func usageFunc(cmd *cobra.Command) error { 142 subCommands := getSubCommands(cmd) 143 tabOut := getTabOutWithWriter(os.Stdout) 144 commandUsageTemplate.Execute(tabOut, struct { 145 Cmd *cobra.Command 146 LocalFlags string 147 GlobalFlags string 148 SubCommands []*cobra.Command 149 Version string 150 }{ 151 cmd, 152 rktFlagUsages(cmd.LocalFlags()), 153 rktFlagUsages(cmd.InheritedFlags()), 154 subCommands, 155 version.Version, 156 }) 157 tabOut.Flush() 158 return nil 159 } 160 161 func printErrors(errors []error, operation string) { 162 sep := "----------------------------------------" 163 stderr.Printf("%d error(s) encountered when %s:", len(errors), operation) 164 stderr.Print(sep) 165 for _, err := range errors { 166 stderr.Error(err) 167 stderr.Print(sep) 168 } 169 stderr.Print("misc:") 170 stderr.Printf(" rkt's appc version: %s", schema.AppContainerVersion) 171 // make a visible break between errors and the listing 172 stderr.Print("") 173 }