1 // Copyright © 2015 Steve Francia <spf@spf13.com>.
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
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.
22 "github.com/spf13/cobra"
23 "github.com/spf13/viper"
26 var initCmd = &cobra.Command{
28 Aliases: []string{"initialize", "initialise", "create"},
29 Short: "Initialize a Cobra Application",
30 Long: `Initialize (cobra init) will create a new application, with a license
31 and the appropriate structure for a Cobra-based CLI application.
33 * If a name is provided, it will be created in the current directory;
34 * If no name is provided, the current directory will be assumed;
35 * If a relative path is provided, it will be created inside $GOPATH
36 (e.g. github.com/spf13/hugo);
37 * If an absolute path is provided, it will be created;
38 * If the directory already exists but is empty, it will be used.
40 Init will not use an existing directory with contents.`,
42 Run: func(cmd *cobra.Command, args []string) {
50 project = NewProjectFromPath(wd)
51 } else if len(args) == 1 {
54 arg = filepath.Join(wd, arg)
56 if filepath.IsAbs(arg) {
57 project = NewProjectFromPath(arg)
59 project = NewProject(arg)
62 er("please provide only one argument")
65 initializeProject(project)
67 fmt.Fprintln(cmd.OutOrStdout(), `Your Cobra application is ready at
68 `+project.AbsPath()+`.
70 Give it a try by going there and running `+"`go run main.go`."+`
71 Add commands to it by running `+"`cobra add [cmdname]`.")
75 func initializeProject(project *Project) {
76 if !exists(project.AbsPath()) { // If path doesn't yet exist, create it
77 err := os.MkdirAll(project.AbsPath(), os.ModePerm)
81 } else if !isEmpty(project.AbsPath()) { // If path exists and is not empty don't use it
82 er("Cobra will not create a new project in a non empty directory: " + project.AbsPath())
85 // We have a directory and it's empty. Time to initialize it.
86 createLicenseFile(project.License(), project.AbsPath())
87 createMainFile(project)
88 createRootCmdFile(project)
91 func createLicenseFile(license License, path string) {
92 data := make(map[string]interface{})
93 data["copyright"] = copyrightLine()
95 // Generate license template from text and data.
96 text, err := executeTemplate(license.Text, data)
101 // Write license text to LICENSE file.
102 err = writeStringToFile(filepath.Join(path, "LICENSE"), text)
108 func createMainFile(project *Project) {
109 mainTemplate := `{{ comment .copyright }}
110 {{if .license}}{{ comment .license }}{{end}}
114 import "{{ .importpath }}"
120 data := make(map[string]interface{})
121 data["copyright"] = copyrightLine()
122 data["license"] = project.License().Header
123 data["importpath"] = path.Join(project.Name(), filepath.Base(project.CmdPath()))
125 mainScript, err := executeTemplate(mainTemplate, data)
130 err = writeStringToFile(filepath.Join(project.AbsPath(), "main.go"), mainScript)
136 func createRootCmdFile(project *Project) {
137 template := `{{comment .copyright}}
138 {{if .license}}{{comment .license}}{{end}}
146 homedir "github.com/mitchellh/go-homedir"{{end}}
147 "github.com/spf13/cobra"{{if .viper}}
148 "github.com/spf13/viper"{{end}}
151 var cfgFile string{{end}}
153 // RootCmd represents the base command when called without any subcommands
154 var RootCmd = &cobra.Command{
156 Short: "A brief description of your application",
157 Long: ` + "`" + `A longer description that spans multiple lines and likely contains
158 examples and usage of using your application. For example:
160 Cobra is a CLI library for Go that empowers applications.
161 This application is a tool to generate the needed files
162 to quickly create a Cobra application.` + "`" + `,
163 // Uncomment the following line if your bare application
164 // has an action associated with it:
165 // Run: func(cmd *cobra.Command, args []string) { },
168 // Execute adds all child commands to the root command and sets flags appropriately.
169 // This is called by main.main(). It only needs to happen once to the rootCmd.
171 if err := RootCmd.Execute(); err != nil {
177 func init() { {{if .viper}}
178 cobra.OnInitialize(initConfig)
180 // Here you will define your flags and configuration settings.
181 // Cobra supports persistent flags, which, if defined here,
182 // will be global for your application.{{ if .viper }}
183 RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ else }}
184 // RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ end }}
186 // Cobra also supports local flags, which will only run
187 // when this action is called directly.
188 RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
191 // initConfig reads in config file and ENV variables if set.
194 // Use config file from the flag.
195 viper.SetConfigFile(cfgFile)
197 // Find home directory.
198 home, err := homedir.Dir()
204 // Search config in home directory with name ".{{ .appName }}" (without extension).
205 viper.AddConfigPath(home)
206 viper.SetConfigName(".{{ .appName }}")
209 viper.AutomaticEnv() // read in environment variables that match
211 // If a config file is found, read it in.
212 if err := viper.ReadInConfig(); err == nil {
213 fmt.Println("Using config file:", viper.ConfigFileUsed())
218 data := make(map[string]interface{})
219 data["copyright"] = copyrightLine()
220 data["viper"] = viper.GetBool("useViper")
221 data["license"] = project.License().Header
222 data["appName"] = path.Base(project.Name())
224 rootCmdScript, err := executeTemplate(template, data)
229 err = writeStringToFile(filepath.Join(project.CmdPath(), "root.go"), rootCmdScript)