From 6bcf163261fd846a12dc1faee86543d5bc6d3ec9 Mon Sep 17 00:00:00 2001 From: Albert Nigmatzianov Date: Mon, 1 May 2017 22:52:58 +0200 Subject: [PATCH] cmd: Validate cmd names Fix #269 --- cobra/cmd/add.go | 51 ++++++++++++++++++++++++++++++++++++++++--- cobra/cmd/add_test.go | 25 +++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 cobra/cmd/add_test.go diff --git a/cobra/cmd/add.go b/cobra/cmd/add.go index 8bc8c449..81ef8171 100644 --- a/cobra/cmd/add.go +++ b/cobra/cmd/add.go @@ -17,12 +17,14 @@ import ( "fmt" "os" "path/filepath" + "unicode" "github.com/spf13/cobra" "github.com/spf13/viper" ) func init() { + addCmd.Flags().StringVarP(&parentName, "parent", "p", "RootCmd", "name of parent command for this command") RootCmd.AddCommand(addCmd) } @@ -50,12 +52,55 @@ Example: cobra add server -> resulting in a new cmd/server.go`, er(err) } project := NewProjectFromPath(wd) - createCmdFile(project, args[0]) + cmdName := validateCmdName(args[0]) + createCmdFile(project, cmdName) }, } -func init() { - addCmd.Flags().StringVarP(&parentName, "parent", "p", "RootCmd", "name of parent command for this command") +// validateCmdName returns source without any dashes and underscore. +// If there will be dash or underscore, next letter will be uppered. +// It supports only ASCII (1-byte character) strings. +func validateCmdName(source string) string { + i := 0 + l := len(source) + // The output is initialized on demand, then first dash or underscore + // occurs. + var output string + + for i < l { + if source[i] == '-' || source[i] == '_' { + if output == "" { + output = source[:i] + } + + // If next character is dash or underscore, + // just skip the current character. + if source[i+1] == '-' || source[i+1] == '_' { + i++ + continue + } + + // If the current character is dash or underscore, + // upper next letter and add to output. + output += string(unicode.ToUpper(rune(source[i+1]))) + // We know, what source[i] is dash or underscore and source[i+1] is + // uppered character, so make i = i+2. + i += 2 + continue + } + + // If the current character isn't dash or underscore, + // just add it. + if output != "" { + output += string(source[i]) + } + i++ + } + + if output == "" { + return source // source is initially valid name. + } + return output } func createCmdFile(project *Project, cmdName string) { diff --git a/cobra/cmd/add_test.go b/cobra/cmd/add_test.go new file mode 100644 index 00000000..037930fd --- /dev/null +++ b/cobra/cmd/add_test.go @@ -0,0 +1,25 @@ +package cmd + +import "testing" + +func TestValidateCmdName(t *testing.T) { + testCases := []struct { + input string + expected string + }{ + {"cmdName", "cmdName"}, + {"cmd_name", "cmdName"}, + {"cmd-name", "cmdName"}, + {"cmd______Name", "cmdName"}, + {"cmd------Name", "cmdName"}, + {"cmd______name", "cmdName"}, + {"cmd------name", "cmdName"}, + } + + for _, testCase := range testCases { + got := validateCmdName(testCase.input) + if testCase.expected != got { + t.Errorf("Expected %q, got %q", testCase.expected, got) + } + } +}