Fine-tune the formatting of Cobra’s generated code

This commit is contained in:
Anthony Fok 2015-11-20 15:28:40 -07:00
parent c7feee9f20
commit 1e63ad8ed1
5 changed files with 83 additions and 81 deletions

View file

@ -33,12 +33,14 @@ var addCmd = &cobra.Command{
Use: "add [command name]", Use: "add [command name]",
Aliases: []string{"command"}, Aliases: []string{"command"},
Short: "Add a command to a Cobra Application", Short: "Add a command to a Cobra Application",
Long: `Add will create a new command, with a license and the appropriate structure Long: `Add (cobra add) will create a new command, with a license and
for a Cobra based CLI application and register it to it's parent (default RootCmd). the appropriate structure for a Cobra-based CLI application,
and register it to its parent (default RootCmd).
If you want your command to be public, pass in the command name with an initial upper case letter. If you want your command to be public, pass in the command name
with an initial uppercase letter.
Example: cobra add server -> resulting in a new cmd/server.go Example: cobra add server -> resulting in a new cmd/server.go
`, `,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -66,12 +68,12 @@ func createCmdFile(cmdName string) {
lic := getLicense() lic := getLicense()
template := `{{ comment .copyright }} template := `{{ comment .copyright }}
//
{{ comment .license }} {{ comment .license }}
package cmd package cmd
import ( import (
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -83,25 +85,27 @@ var {{ .cmdName }}Cmd = &cobra.Command{
Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example: and usage of using your command. For example:
Cobra is a Cli library for Go that empowers applications. This Cobra is a CLI library for Go that empowers applications.
application is a tool to generate the needed files to quickly create a Cobra This application is a tool to generate the needed files
application.` + "`" + `, to quickly create a Cobra application.` + "`" + `,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// TODO: Work your own magic here // TODO: Work your own magic here
fmt.Println("{{ .cmdName }} called") fmt.Println("{{ .cmdName }} called")
}, },
} }
func init() { func init() {
{{ .parentName }}.AddCommand({{ .cmdName }}Cmd) {{ .parentName }}.AddCommand({{ .cmdName }}Cmd)
// Here you will define your flags and configuration settings // Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command and all subcommands // Cobra supports Persistent Flags which will work for this command
// {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo") // and all subcommands, e.g.:
// {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command is called directly // Cobra supports local flags which will only run when this command
// {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle" ) // is called directly, e.g.:
// {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
} }
` `

View file

@ -141,18 +141,19 @@ func guessProjectPath() {
} }
srcPath := getSrcPath() srcPath := getSrcPath()
// if provided inspect for logical locations // if provided, inspect for logical locations
if strings.ContainsRune(inputPath, os.PathSeparator) { if strings.ContainsRune(inputPath, os.PathSeparator) {
if filepath.IsAbs(inputPath) { if filepath.IsAbs(inputPath) {
// if Absolute, use it // if Absolute, use it
projectPath = filepath.Clean(inputPath) projectPath = filepath.Clean(inputPath)
return return
} }
// If not absolute but contains slashes.. assuming it means create it from $GOPATH // If not absolute but contains slashes,
// assuming it means create it from $GOPATH
count := strings.Count(inputPath, string(os.PathSeparator)) count := strings.Count(inputPath, string(os.PathSeparator))
switch count { switch count {
// If only one directory deep assume "github.com" // If only one directory deep, assume "github.com"
case 1: case 1:
projectPath = filepath.Join(srcPath, "github.com", inputPath) projectPath = filepath.Join(srcPath, "github.com", inputPath)
return return
@ -178,7 +179,7 @@ func guessProjectPath() {
} }
} }
// IsEmpty checks if a given path is empty. // isEmpty checks if a given path is empty.
func isEmpty(path string) (bool, error) { func isEmpty(path string) (bool, error) {
if b, _ := exists(path); !b { if b, _ := exists(path); !b {
return false, fmt.Errorf("%q path does not exist", path) return false, fmt.Errorf("%q path does not exist", path)
@ -202,7 +203,7 @@ func isEmpty(path string) (bool, error) {
return fi.Size() == 0, nil return fi.Size() == 0, nil
} }
// IsDir checks if a given path is a directory. // isDir checks if a given path is a directory.
func isDir(path string) (bool, error) { func isDir(path string) (bool, error) {
fi, err := os.Stat(path) fi, err := os.Stat(path)
if err != nil { if err != nil {
@ -211,7 +212,7 @@ func isDir(path string) (bool, error) {
return fi.IsDir(), nil return fi.IsDir(), nil
} }
// DirExists checks if a path exists and is a directory. // dirExists checks if a path exists and is a directory.
func dirExists(path string) (bool, error) { func dirExists(path string) (bool, error) {
fi, err := os.Stat(path) fi, err := os.Stat(path)
if err == nil && fi.IsDir() { if err == nil && fi.IsDir() {
@ -308,13 +309,13 @@ func getLicense() License {
} }
func whichLicense() string { func whichLicense() string {
// if explicitly flagged use that // if explicitly flagged, use that
if userLicense != "" { if userLicense != "" {
return matchLicense(userLicense) return matchLicense(userLicense)
} }
// if already present in the project, use that // if already present in the project, use that
// TODO:Inpect project for existing license // TODO: Inspect project for existing license
// default to viper's setting // default to viper's setting
@ -325,7 +326,7 @@ func copyrightLine() string {
author := viper.GetString("author") author := viper.GetString("author")
year := time.Now().Format("2006") year := time.Now().Format("2006")
return "Copyright ©" + year + " " + author return "Copyright © " + year + " " + author
} }
func commentifyString(in string) string { func commentifyString(in string) string {
@ -333,7 +334,11 @@ func commentifyString(in string) string {
lines := strings.Split(in, "\n") lines := strings.Split(in, "\n")
for _, x := range lines { for _, x := range lines {
if !strings.HasPrefix(x, "//") { if !strings.HasPrefix(x, "//") {
newlines = append(newlines, "// "+x) if x != "" {
newlines = append(newlines, "// "+x)
} else {
newlines = append(newlines, "//")
}
} else { } else {
newlines = append(newlines, x) newlines = append(newlines, x)
} }

View file

@ -30,17 +30,17 @@ var initCmd = &cobra.Command{
Use: "init [name]", Use: "init [name]",
Aliases: []string{"initialize", "initalise", "create"}, Aliases: []string{"initialize", "initalise", "create"},
Short: "Initalize a Cobra Application", Short: "Initalize a Cobra Application",
Long: `Initalize will create a new application, with a license and the appropriate structure Long: `Initialize (cobra init) will create a new application, with a license
for a Cobra based CLI application. and the appropriate structure for a Cobra-based CLI application.
If a name is provided it will create it in the current directory. * If a name is provided, it will be created in the current directory;
If no name is provided it will assume the current directory. * If no name is provided, the current directory will be assumed;
If a relative path is provided it will create it inside of $GOPATH (eg github.com/spf13/hugo). * If a relative path is provided, it will be created inside $GOPATH
If an absolute path is provided it will create it. (e.g. github.com/spf13/hugo);
* If an absolute path is provided, it will be created;
* If the directory already exists but is empty, it will be used.
If the directory already exists but is empty it will use it. Init will not use an exiting directory with contents.`,
Init will not use an exiting directory with contents.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
switch len(args) { switch len(args) {
@ -98,7 +98,6 @@ func createMainFile() {
lic := getLicense() lic := getLicense()
template := `{{ comment .copyright }} template := `{{ comment .copyright }}
//
{{ comment .license }} {{ comment .license }}
package main package main
@ -127,8 +126,8 @@ func createRootCmdFile() {
lic := getLicense() lic := getLicense()
template := `{{ comment .copyright }} template := `{{ comment .copyright }}
//
{{ comment .license }} {{ comment .license }}
package cmd package cmd
import ( import (
@ -136,29 +135,28 @@ import (
"os" "os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
{{ if .viper }}"github.com/spf13/viper"{{ end }} {{ if .viper }} "github.com/spf13/viper"
) {{ end }})
{{if .viper}} {{if .viper}}
var cfgFile string var cfgFile string
{{ end }} {{ end }}
// This represents the base command when called without any subcommands // This represents the base command when called without any subcommands
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: "{{ .appName }}", Use: "{{ .appName }}",
Short: "A brief description of your application", Short: "A brief description of your application",
Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples Long: ` + "`" + `A longer description that spans multiple lines and likely contains
and usage of using your application. For example: examples and usage of using your application. For example:
Cobra is a Cli library for Go that empowers applications. This Cobra is a CLI library for Go that empowers applications.
application is a tool to generate the needed files to quickly create a Cobra This application is a tool to generate the needed files
application.` + "`" + `, to quickly create a Cobra application.` + "`" + `,
// Uncomment the following line if your bare application has an action associated with it // Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { }, // Run: func(cmd *cobra.Command, args []string) { },
} }
//Execute adds all child commands to the root command sets flags appropriately. // Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd // This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() { func Execute() {
if err := RootCmd.Execute(); err != nil { if err := RootCmd.Execute(); err != nil {
fmt.Println(err) fmt.Println(err)
@ -167,21 +165,21 @@ func Execute() {
} }
func init() { func init() {
{{ if .viper }}cobra.OnInitialize(initConfig){{ end}} {{ if .viper }} cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings
// Cobra supports Persistent Flags which if defined here will be global for your application
{{ if .viper }}
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)")
{{ else }}
// RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)")
{{ end }}
// Cobra also supports local flags which will only run when this action is called directly
RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle" )
}
{{ end }} // Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags, which, if defined here,
// will be global for your application.
{{ if .viper }} {{ if .viper }}
// Read in config file and ENV variables if set. RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)")
{{ else }}
// RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)")
{{ end }} // Cobra also supports local flags, which will only run
// when this action is called directly.
RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
{{ if .viper }}
// initConfig reads in config file and ENV variables if set.
func initConfig() { func initConfig() {
if cfgFile != "" { // enable ability to specify config file via flag if cfgFile != "" { // enable ability to specify config file via flag
viper.SetConfigFile(cfgFile) viper.SetConfigFile(cfgFile)
@ -196,8 +194,7 @@ func initConfig() {
fmt.Println("Using config file:", viper.ConfigFileUsed()) fmt.Println("Using config file:", viper.ConfigFileUsed())
} }
} }
{{ end }} {{ end }}`
`
var data map[string]interface{} var data map[string]interface{}
data = make(map[string]interface{}) data = make(map[string]interface{})

View file

@ -55,8 +55,7 @@ func init() {
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.`,
`,
Text: ` Text: `
Apache License Apache License
@ -260,7 +259,7 @@ func init() {
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
`, `,
} }
Licenses["mit"] = License{ Licenses["mit"] = License{
@ -285,8 +284,7 @@ func init() {
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.`,
`,
Text: ` Text: `
The MIT License (MIT) The MIT License (MIT)
@ -307,7 +305,7 @@ func init() {
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
`, `,
} }
Licenses["bsd"] = License{ Licenses["bsd"] = License{
@ -336,8 +334,7 @@ func init() {
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.`,
`,
Text: ` Text: `
All rights reserved. All rights reserved.
@ -362,7 +359,7 @@ func init() {
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
`, `,
} }
Licenses["freebsd"] = License{ Licenses["freebsd"] = License{
@ -393,8 +390,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies, of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project. either expressed or implied, of the FreeBSD Project.`,
`,
Text: ` Text: `
All rights reserved. All rights reserved.
@ -421,7 +417,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies, of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project. either expressed or implied, of the FreeBSD Project.
`, `,
} }
// Licenses["apache20"] = License{ // Licenses["apache20"] = License{

View file

@ -28,9 +28,9 @@ var userLicense string
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: "cobra", Use: "cobra",
Short: "A generator for Cobra based Applications", Short: "A generator for Cobra based Applications",
Long: `Cobra is a Cli library for Go that empowers applications. This Long: `Cobra is a CLI library for Go that empowers applications.
application is a tool to generate the needed files to quickly create a Cobra This application is a tool to generate the needed files
application.`, to quickly create a Cobra application.`,
} }
//Execute adds all child commands to the root command sets flags appropriately. //Execute adds all child commands to the root command sets flags appropriately.
@ -44,7 +44,7 @@ func Execute() {
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory, e.g. github.com/spf13/")
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")