1// Copyright © 2015 Steve Francia <spf@spf13.com>. 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// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package cmd 15 16import ( 17 "fmt" 18 "os" 19 "path/filepath" 20 "unicode" 21 22 "github.com/spf13/cobra" 23) 24 25func init() { 26 addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)") 27 addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command") 28} 29 30var packageName, parentName string 31 32var addCmd = &cobra.Command{ 33 Use: "add [command name]", 34 Aliases: []string{"command"}, 35 Short: "Add a command to a Cobra Application", 36 Long: `Add (cobra add) will create a new command, with a license and 37the appropriate structure for a Cobra-based CLI application, 38and register it to its parent (default rootCmd). 39 40If you want your command to be public, pass in the command name 41with an initial uppercase letter. 42 43Example: cobra add server -> resulting in a new cmd/server.go`, 44 45 Run: func(cmd *cobra.Command, args []string) { 46 if len(args) < 1 { 47 er("add needs a name for the command") 48 } 49 50 var project *Project 51 if packageName != "" { 52 project = NewProject(packageName) 53 } else { 54 wd, err := os.Getwd() 55 if err != nil { 56 er(err) 57 } 58 project = NewProjectFromPath(wd) 59 } 60 61 cmdName := validateCmdName(args[0]) 62 cmdPath := filepath.Join(project.CmdPath(), cmdName+".go") 63 createCmdFile(project.License(), cmdPath, cmdName) 64 65 fmt.Fprintln(cmd.OutOrStdout(), cmdName, "created at", cmdPath) 66 }, 67} 68 69// validateCmdName returns source without any dashes and underscore. 70// If there will be dash or underscore, next letter will be uppered. 71// It supports only ASCII (1-byte character) strings. 72// https://github.com/spf13/cobra/issues/269 73func validateCmdName(source string) string { 74 i := 0 75 l := len(source) 76 // The output is initialized on demand, then first dash or underscore 77 // occurs. 78 var output string 79 80 for i < l { 81 if source[i] == '-' || source[i] == '_' { 82 if output == "" { 83 output = source[:i] 84 } 85 86 // If it's last rune and it's dash or underscore, 87 // don't add it output and break the loop. 88 if i == l-1 { 89 break 90 } 91 92 // If next character is dash or underscore, 93 // just skip the current character. 94 if source[i+1] == '-' || source[i+1] == '_' { 95 i++ 96 continue 97 } 98 99 // If the current character is dash or underscore, 100 // upper next letter and add to output. 101 output += string(unicode.ToUpper(rune(source[i+1]))) 102 // We know, what source[i] is dash or underscore and source[i+1] is 103 // uppered character, so make i = i+2. 104 i += 2 105 continue 106 } 107 108 // If the current character isn't dash or underscore, 109 // just add it. 110 if output != "" { 111 output += string(source[i]) 112 } 113 i++ 114 } 115 116 if output == "" { 117 return source // source is initially valid name. 118 } 119 return output 120} 121 122func createCmdFile(license License, path, cmdName string) { 123 template := `{{comment .copyright}} 124{{if .license}}{{comment .license}}{{end}} 125 126package {{.cmdPackage}} 127 128import ( 129 "fmt" 130 131 "github.com/spf13/cobra" 132) 133 134// {{.cmdName}}Cmd represents the {{.cmdName}} command 135var {{.cmdName}}Cmd = &cobra.Command{ 136 Use: "{{.cmdName}}", 137 Short: "A brief description of your command", 138 Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples 139and usage of using your command. For example: 140 141Cobra is a CLI library for Go that empowers applications. 142This application is a tool to generate the needed files 143to quickly create a Cobra application.` + "`" + `, 144 Run: func(cmd *cobra.Command, args []string) { 145 fmt.Println("{{.cmdName}} called") 146 }, 147} 148 149func init() { 150 {{.parentName}}.AddCommand({{.cmdName}}Cmd) 151 152 // Here you will define your flags and configuration settings. 153 154 // Cobra supports Persistent Flags which will work for this command 155 // and all subcommands, e.g.: 156 // {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo") 157 158 // Cobra supports local flags which will only run when this command 159 // is called directly, e.g.: 160 // {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 161} 162` 163 164 data := make(map[string]interface{}) 165 data["copyright"] = copyrightLine() 166 data["license"] = license.Header 167 data["cmdPackage"] = filepath.Base(filepath.Dir(path)) // last dir of path 168 data["parentName"] = parentName 169 data["cmdName"] = cmdName 170 171 cmdScript, err := executeTemplate(template, data) 172 if err != nil { 173 er(err) 174 } 175 err = writeStringToFile(path, cmdScript) 176 if err != nil { 177 er(err) 178 } 179} 180