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	"unicode"
20
21	"github.com/spf13/cobra"
22)
23
24var (
25	packageName string
26	parentName  string
27
28	addCmd = &cobra.Command{
29		Use:     "add [command name]",
30		Aliases: []string{"command"},
31		Short:   "Add a command to a Cobra Application",
32		Long: `Add (cobra add) will create a new command, with a license and
33the appropriate structure for a Cobra-based CLI application,
34and register it to its parent (default rootCmd).
35
36If you want your command to be public, pass in the command name
37with an initial uppercase letter.
38
39Example: cobra add server -> resulting in a new cmd/server.go`,
40
41		Run: func(cmd *cobra.Command, args []string) {
42			if len(args) < 1 {
43				cobra.CheckErr(fmt.Errorf("add needs a name for the command"))
44			}
45
46			wd, err := os.Getwd()
47			cobra.CheckErr(err)
48
49			commandName := validateCmdName(args[0])
50			command := &Command{
51				CmdName:   commandName,
52				CmdParent: parentName,
53				Project: &Project{
54					AbsolutePath: wd,
55					Legal:        getLicense(),
56					Copyright:    copyrightLine(),
57				},
58			}
59
60			cobra.CheckErr(command.Create())
61
62			fmt.Printf("%s created at %s\n", command.CmdName, command.AbsolutePath)
63		},
64	}
65)
66
67func init() {
68	addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
69	addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
70	cobra.CheckErr(addCmd.Flags().MarkDeprecated("package", "this operation has been removed."))
71}
72
73// validateCmdName returns source without any dashes and underscore.
74// If there will be dash or underscore, next letter will be uppered.
75// It supports only ASCII (1-byte character) strings.
76// https://github.com/spf13/cobra/issues/269
77func validateCmdName(source string) string {
78	i := 0
79	l := len(source)
80	// The output is initialized on demand, then first dash or underscore
81	// occurs.
82	var output string
83
84	for i < l {
85		if source[i] == '-' || source[i] == '_' {
86			if output == "" {
87				output = source[:i]
88			}
89
90			// If it's last rune and it's dash or underscore,
91			// don't add it output and break the loop.
92			if i == l-1 {
93				break
94			}
95
96			// If next character is dash or underscore,
97			// just skip the current character.
98			if source[i+1] == '-' || source[i+1] == '_' {
99				i++
100				continue
101			}
102
103			// If the current character is dash or underscore,
104			// upper next letter and add to output.
105			output += string(unicode.ToUpper(rune(source[i+1])))
106			// We know, what source[i] is dash or underscore and source[i+1] is
107			// uppered character, so make i = i+2.
108			i += 2
109			continue
110		}
111
112		// If the current character isn't dash or underscore,
113		// just add it.
114		if output != "" {
115			output += string(source[i])
116		}
117		i++
118	}
119
120	if output == "" {
121		return source // source is initially valid name.
122	}
123	return output
124}
125