diff --git a/README.md b/README.md index 27efea8..eaee53f 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,44 @@ fmt.Println(strings2.ToKebabCase(words, strings2.OptionDelimiter("|"))) fmt.Println(strings2.ToSnakeCase(words, strings2.OptionCaseMode(strings2.CMScreaming))) ``` +### CLI Mode + +The library also provides a command-line interface that exposes all these options, ensuring that the CLI mode has as much flexibility as the code (without being obligated to use smart defaults). + +```bash +strings2 camel "hello world" +# Result: helloWorld + +strings2 snake --screaming "hello world" +# Result: HELLO_WORLD + +strings2 kebab --first-upper "hello world" +# Result: Hello-world +``` + +You can pipe input into the CLI as well: +```bash +echo "hello world" | strings2 pascal +# Result: HelloWorld +``` + +Available flags across commands: +- `--delimiter`, `-d` (string): Override the delimiter +- `--screaming`, `-S`: Enforce uppercase formatting +- `--whispering`, `-w`: Enforce lowercase formatting +- `--first-upper`, `-U`: Capitalize the first letter +- `--first-lower`, `-l`: Lowercase the first letter +- `--mix-case-support`, `-m`: Enable splitting of mixed case words +- `--no-smart-acronyms`: Disable acronym preservation +- `--number-splitting`: Enable letter-digit boundary splitting +``` + Options are composable so multiple behaviours can be applied at once. See the documentation in `types.go` for details on further options. +## TODO + +- Support slices for flags when the gosubc version supports it. + ## License This project is licensed under the BSD 3-Clause License - see the [LICENSE](LICENSE) file for details. diff --git a/cli/main.go b/cli/main.go index 2b07ead..f5e9090 100644 --- a/cli/main.go +++ b/cli/main.go @@ -9,7 +9,7 @@ import ( "github.com/arran4/strings2" ) -func process(input string, output string, args []string, fn func(string, ...any) (string, error)) { +func process(input string, output string, args []string, fn func(string, ...any) (string, error), opts ...any) { var in io.Reader if input == "-" { in = os.Stdin @@ -33,7 +33,7 @@ func process(input string, output string, args []string, fn func(string, ...any) os.Exit(1) } - res, err := fn(string(b)) + res, err := fn(string(b), opts...) if err != nil { fmt.Fprintf(os.Stderr, "Error processing: %v\n", err) os.Exit(1) @@ -55,15 +55,57 @@ func process(input string, output string, args []string, fn func(string, ...any) fmt.Fprintln(out, res) } +func buildOpts(delimiter string, screaming bool, whispering bool, firstUpper bool, firstLower bool, mixCaseSupport bool, noSmartAcronyms bool, numberSplitting bool, strict bool) []any { + var opts []any + if delimiter != "" { + opts = append(opts, strings2.OptionDelimiter(delimiter)) + } + if screaming { + opts = append(opts, strings2.OptionCaseMode(strings2.CMScreaming)) + } + if whispering { + opts = append(opts, strings2.OptionCaseMode(strings2.CMWhispering)) + } + if firstUpper { + opts = append(opts, strings2.OptionFirstUpper()) + } + if firstLower { + opts = append(opts, strings2.OptionFirstLower()) + } + if mixCaseSupport { + opts = append(opts, strings2.OptionMixCaseSupport()) + } + if noSmartAcronyms { + opts = append(opts, strings2.WithSmartAcronyms(false)) + } + if numberSplitting { + opts = append(opts, strings2.WithNumberSplitting(true)) + } + if strict { + opts = append(opts, strings2.OptionStrict()) + } + return opts +} + // Camel is a subcommand `strings2 camel` // // Flags: // // input: -i --input (default: "") Input file or - for stdin // output: -o --output (default: "") Output file or - for stdout +// delimiter: -d --delimiter (default: "") Delimiter +// screaming: -S --screaming (default: false) Screaming mode +// whispering: -w --whispering (default: false) Whispering mode +// firstUpper: -U --first-upper (default: false) First char upper +// firstLower: -l --first-lower (default: false) First char lower +// mixCaseSupport: -m --mix-case-support (default: false) Mix case support +// noSmartAcronyms: --no-smart-acronyms (default: false) Disable smart acronyms +// numberSplitting: --number-splitting (default: false) Enable number splitting +// strict: --strict (default: false) Strict UTF8 mode // args: ... String to convert if file/stdin not provided -func Camel(input string, output string, args ...string) { - process(input, output, args, strings2.ToCamel) +func Camel(input string, output string, delimiter string, screaming bool, whispering bool, firstUpper bool, firstLower bool, mixCaseSupport bool, noSmartAcronyms bool, numberSplitting bool, strict bool, args ...string) { + opts := buildOpts(delimiter, screaming, whispering, firstUpper, firstLower, mixCaseSupport, noSmartAcronyms, numberSplitting, strict) + process(input, output, args, strings2.ToCamel, opts...) } // Snake is a subcommand `strings2 snake` @@ -72,9 +114,19 @@ func Camel(input string, output string, args ...string) { // // input: -i --input (default: "") Input file or - for stdin // output: -o --output (default: "") Output file or - for stdout +// delimiter: -d --delimiter (default: "") Delimiter +// screaming: -S --screaming (default: false) Screaming mode +// whispering: -w --whispering (default: false) Whispering mode +// firstUpper: -U --first-upper (default: false) First char upper +// firstLower: -l --first-lower (default: false) First char lower +// mixCaseSupport: -m --mix-case-support (default: false) Mix case support +// noSmartAcronyms: --no-smart-acronyms (default: false) Disable smart acronyms +// numberSplitting: --number-splitting (default: false) Enable number splitting +// strict: --strict (default: false) Strict UTF8 mode // args: ... String to convert if file/stdin not provided -func Snake(input string, output string, args ...string) { - process(input, output, args, strings2.ToSnake) +func Snake(input string, output string, delimiter string, screaming bool, whispering bool, firstUpper bool, firstLower bool, mixCaseSupport bool, noSmartAcronyms bool, numberSplitting bool, strict bool, args ...string) { + opts := buildOpts(delimiter, screaming, whispering, firstUpper, firstLower, mixCaseSupport, noSmartAcronyms, numberSplitting, strict) + process(input, output, args, strings2.ToSnake, opts...) } // Kebab is a subcommand `strings2 kebab` @@ -83,9 +135,19 @@ func Snake(input string, output string, args ...string) { // // input: -i --input (default: "") Input file or - for stdin // output: -o --output (default: "") Output file or - for stdout +// delimiter: -d --delimiter (default: "") Delimiter +// screaming: -S --screaming (default: false) Screaming mode +// whispering: -w --whispering (default: false) Whispering mode +// firstUpper: -U --first-upper (default: false) First char upper +// firstLower: -l --first-lower (default: false) First char lower +// mixCaseSupport: -m --mix-case-support (default: false) Mix case support +// noSmartAcronyms: --no-smart-acronyms (default: false) Disable smart acronyms +// numberSplitting: --number-splitting (default: false) Enable number splitting +// strict: --strict (default: false) Strict UTF8 mode // args: ... String to convert if file/stdin not provided -func Kebab(input string, output string, args ...string) { - process(input, output, args, strings2.ToKebab) +func Kebab(input string, output string, delimiter string, screaming bool, whispering bool, firstUpper bool, firstLower bool, mixCaseSupport bool, noSmartAcronyms bool, numberSplitting bool, strict bool, args ...string) { + opts := buildOpts(delimiter, screaming, whispering, firstUpper, firstLower, mixCaseSupport, noSmartAcronyms, numberSplitting, strict) + process(input, output, args, strings2.ToKebab, opts...) } // Pascal is a subcommand `strings2 pascal` @@ -94,7 +156,17 @@ func Kebab(input string, output string, args ...string) { // // input: -i --input (default: "") Input file or - for stdin // output: -o --output (default: "") Output file or - for stdout +// delimiter: -d --delimiter (default: "") Delimiter +// screaming: -S --screaming (default: false) Screaming mode +// whispering: -w --whispering (default: false) Whispering mode +// firstUpper: -U --first-upper (default: false) First char upper +// firstLower: -l --first-lower (default: false) First char lower +// mixCaseSupport: -m --mix-case-support (default: false) Mix case support +// noSmartAcronyms: --no-smart-acronyms (default: false) Disable smart acronyms +// numberSplitting: --number-splitting (default: false) Enable number splitting +// strict: --strict (default: false) Strict UTF8 mode // args: ... String to convert if file/stdin not provided -func Pascal(input string, output string, args ...string) { - process(input, output, args, strings2.ToPascal) +func Pascal(input string, output string, delimiter string, screaming bool, whispering bool, firstUpper bool, firstLower bool, mixCaseSupport bool, noSmartAcronyms bool, numberSplitting bool, strict bool, args ...string) { + opts := buildOpts(delimiter, screaming, whispering, firstUpper, firstLower, mixCaseSupport, noSmartAcronyms, numberSplitting, strict) + process(input, output, args, strings2.ToPascal, opts...) } diff --git a/cmd/agents.md b/cmd/agents.md new file mode 100644 index 0000000..5ca988b --- /dev/null +++ b/cmd/agents.md @@ -0,0 +1,79 @@ + +All code under /cmd is generated code, do not place files here. + +# Go Subcommand Information + +Go Subcommand (`gosubc`) generates subcommand code for command-line interfaces (CLIs) in Go from source code comments. + +## Key Features + +- **Convention over Configuration:** Define your CLI structure with simple, intuitive code comments. +- **Zero Dependencies:** The generated code is self-contained and doesn't require any external libraries. +- **Automatic Code Generation:** `gosubc` parses your Go files and generates a complete, ready-to-use CLI. + +## Installation + +`gosubc` is a standalone tool and should not be added as a dependency in your `go.mod`. Install it using: + +```bash +go install github.com/arran4/go-subcommand/cmd/gosubc@latest +``` + +## How it works + +1. **Define Your Commands**: Create a Go file and define a function that will serve as your command. Add a comment above the function. +2. **Generate**: Run `gosubc generate` (or via `go generate`). +3. **Result**: `gosubc` creates a `cmd/` directory containing the generated CLI code. + +## Comment Syntax + +### Command Definition + +```go +// FuncName is a subcommand 'root-cmd parent child' +func FuncName() {} +``` + +### Flags + +Use a `Flags:` block or inline comments. Adhere to Go formatting. + +```go +// FuncName is a subcommand 'root-cmd parent child' +// +// Flags: +// +// username: --username -u (default: "guest") The user to greet +// count: --count -c (default: 1) Number of times +func FuncName(username string, count int) {} +``` + +### Positional Arguments + +Map positional arguments using `@N`. + +```go +// Greet is a subcommand 'app greet' +// +// Flags: +// +// name: @1 The name to greet +func Greet(name string) {} +``` + +### Variadic Arguments + +Map remaining arguments using `...`. + +```go +// Process is a subcommand 'app process' +// +// Flags: +// +// files: ... List of files +func Process(files ...string) {} +``` + +## Important Note + +Do not edit files in this directory directly if you can avoid it. They are overwritten on every generation. Modify the source code comments instead. diff --git a/cmd/errors.go b/cmd/errors.go index 6e87800..e1e1846 100644 --- a/cmd/errors.go +++ b/cmd/errors.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package cmd @@ -9,3 +9,20 @@ var ErrPrintHelp = errors.New("print help") // ErrHelp tells the user to use help. var ErrHelp = errors.New("help requested") + +// ErrExitCode Mostly used as a pass through, it's caught, but if the sub error is nil and it's not wrapped in another error, it counts as no error. +type ErrExitCode struct { + Err error + Code int +} + +func (e *ErrExitCode) Error() string { + if e.Err == nil { + return "" + } + return e.Err.Error() +} + +func (e *ErrExitCode) Unwrap() error { + return e.Err +} diff --git a/cmd/strings2/camel.go b/cmd/strings2/camel.go index aabcf6a..cdcaaea 100644 --- a/cmd/strings2/camel.go +++ b/cmd/strings2/camel.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "strconv" "strings" "github.com/arran4/strings2/cli" @@ -15,12 +16,21 @@ var _ Cmd = (*Camel)(nil) type Camel struct { *RootCmd - Flags *flag.FlagSet - input string - output string - args []string - SubCommands map[string]Cmd - CommandAction func(c *Camel) error + Flags *flag.FlagSet + input string + output string + delimiter string + screaming bool + whispering bool + firstUpper bool + firstLower bool + mixCaseSupport bool + noSmartAcronyms bool + numberSplitting bool + strict bool + args []string + SubCommands map[string]Cmd + CommandAction func(c *Camel) error } type UsageDataCamel struct { @@ -89,6 +99,105 @@ func (c *Camel) Execute(args []string) error { } } c.output = value + + case "delimiter", "d": + if !hasValue { + if i+1 < len(args) { + value = args[i+1] + i++ + } else { + return fmt.Errorf("flag %s requires a value", name) + } + } + c.delimiter = value + + case "screaming", "S": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.screaming = b + } else { + c.screaming = true + } + + case "whispering", "w": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.whispering = b + } else { + c.whispering = true + } + + case "firstUpper", "first-upper", "U": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstUpper = b + } else { + c.firstUpper = true + } + + case "firstLower", "first-lower", "l": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstLower = b + } else { + c.firstLower = true + } + + case "mixCaseSupport", "mix-case-support", "m": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.mixCaseSupport = b + } else { + c.mixCaseSupport = true + } + + case "noSmartAcronyms", "no-smart-acronyms": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.noSmartAcronyms = b + } else { + c.noSmartAcronyms = true + } + + case "numberSplitting", "number-splitting": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.numberSplitting = b + } else { + c.numberSplitting = true + } + + case "strict": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.strict = b + } else { + c.strict = true + } case "help", "h": c.Usage() return nil @@ -133,11 +242,35 @@ func (c *RootCmd) NewCamel() *Camel { set.StringVar(&v.output, "output", "", "Output file or - for stdout") set.StringVar(&v.output, "o", "", "Output file or - for stdout") + + set.StringVar(&v.delimiter, "delimiter", "", "Delimiter") + set.StringVar(&v.delimiter, "d", "", "Delimiter") + + set.BoolVar(&v.screaming, "screaming", false, "Screaming mode") + set.BoolVar(&v.screaming, "S", false, "Screaming mode") + + set.BoolVar(&v.whispering, "whispering", false, "Whispering mode") + set.BoolVar(&v.whispering, "w", false, "Whispering mode") + + set.BoolVar(&v.firstUpper, "first-upper", false, "First char upper") + set.BoolVar(&v.firstUpper, "U", false, "First char upper") + + set.BoolVar(&v.firstLower, "first-lower", false, "First char lower") + set.BoolVar(&v.firstLower, "l", false, "First char lower") + + set.BoolVar(&v.mixCaseSupport, "mix-case-support", false, "Mix case support") + set.BoolVar(&v.mixCaseSupport, "m", false, "Mix case support") + + set.BoolVar(&v.noSmartAcronyms, "no-smart-acronyms", false, "Disable smart acronyms") + + set.BoolVar(&v.numberSplitting, "number-splitting", false, "Enable number splitting") + + set.BoolVar(&v.strict, "strict", false, "Strict UTF8 mode") set.Usage = v.Usage v.CommandAction = func(c *Camel) error { - cli.Camel(c.input, c.output, c.args...) + cli.Camel(c.input, c.output, c.delimiter, c.screaming, c.whispering, c.firstUpper, c.firstLower, c.mixCaseSupport, c.noSmartAcronyms, c.numberSplitting, c.strict, c.args...) return nil } diff --git a/cmd/strings2/camel_test.go b/cmd/strings2/camel_test.go index e1eaf61..e190c78 100644 --- a/cmd/strings2/camel_test.go +++ b/cmd/strings2/camel_test.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -22,6 +22,20 @@ func TestCamel_Execute(t *testing.T) { } args := []string{} + args = append(args, "--input") + args = append(args, "test") + args = append(args, "--output") + args = append(args, "test") + args = append(args, "--delimiter") + args = append(args, "test") + args = append(args, "--screaming") + args = append(args, "--whispering") + args = append(args, "--firstUpper") + args = append(args, "--firstLower") + args = append(args, "--mixCaseSupport") + args = append(args, "--noSmartAcronyms") + args = append(args, "--numberSplitting") + args = append(args, "--strict") err := cmd.Execute(args) if err != nil { @@ -30,4 +44,38 @@ func TestCamel_Execute(t *testing.T) { if !called { t.Error("CommandAction was not called") } + + if cmd.input != "test" { + t.Errorf("Expected input to be 'test', got '%v'", cmd.input) + } + if cmd.output != "test" { + t.Errorf("Expected output to be 'test', got '%v'", cmd.output) + } + if cmd.delimiter != "test" { + t.Errorf("Expected delimiter to be 'test', got '%v'", cmd.delimiter) + } + if cmd.screaming != true { + t.Errorf("Expected screaming to be true, got '%v'", cmd.screaming) + } + if cmd.whispering != true { + t.Errorf("Expected whispering to be true, got '%v'", cmd.whispering) + } + if cmd.firstUpper != true { + t.Errorf("Expected firstUpper to be true, got '%v'", cmd.firstUpper) + } + if cmd.firstLower != true { + t.Errorf("Expected firstLower to be true, got '%v'", cmd.firstLower) + } + if cmd.mixCaseSupport != true { + t.Errorf("Expected mixCaseSupport to be true, got '%v'", cmd.mixCaseSupport) + } + if cmd.noSmartAcronyms != true { + t.Errorf("Expected noSmartAcronyms to be true, got '%v'", cmd.noSmartAcronyms) + } + if cmd.numberSplitting != true { + t.Errorf("Expected numberSplitting to be true, got '%v'", cmd.numberSplitting) + } + if cmd.strict != true { + t.Errorf("Expected strict to be true, got '%v'", cmd.strict) + } } diff --git a/cmd/strings2/kebab.go b/cmd/strings2/kebab.go index dbec970..14c536c 100644 --- a/cmd/strings2/kebab.go +++ b/cmd/strings2/kebab.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "strconv" "strings" "github.com/arran4/strings2/cli" @@ -15,12 +16,21 @@ var _ Cmd = (*Kebab)(nil) type Kebab struct { *RootCmd - Flags *flag.FlagSet - input string - output string - args []string - SubCommands map[string]Cmd - CommandAction func(c *Kebab) error + Flags *flag.FlagSet + input string + output string + delimiter string + screaming bool + whispering bool + firstUpper bool + firstLower bool + mixCaseSupport bool + noSmartAcronyms bool + numberSplitting bool + strict bool + args []string + SubCommands map[string]Cmd + CommandAction func(c *Kebab) error } type UsageDataKebab struct { @@ -89,6 +99,105 @@ func (c *Kebab) Execute(args []string) error { } } c.output = value + + case "delimiter", "d": + if !hasValue { + if i+1 < len(args) { + value = args[i+1] + i++ + } else { + return fmt.Errorf("flag %s requires a value", name) + } + } + c.delimiter = value + + case "screaming", "S": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.screaming = b + } else { + c.screaming = true + } + + case "whispering", "w": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.whispering = b + } else { + c.whispering = true + } + + case "firstUpper", "first-upper", "U": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstUpper = b + } else { + c.firstUpper = true + } + + case "firstLower", "first-lower", "l": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstLower = b + } else { + c.firstLower = true + } + + case "mixCaseSupport", "mix-case-support", "m": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.mixCaseSupport = b + } else { + c.mixCaseSupport = true + } + + case "noSmartAcronyms", "no-smart-acronyms": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.noSmartAcronyms = b + } else { + c.noSmartAcronyms = true + } + + case "numberSplitting", "number-splitting": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.numberSplitting = b + } else { + c.numberSplitting = true + } + + case "strict": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.strict = b + } else { + c.strict = true + } case "help", "h": c.Usage() return nil @@ -133,11 +242,35 @@ func (c *RootCmd) NewKebab() *Kebab { set.StringVar(&v.output, "output", "", "Output file or - for stdout") set.StringVar(&v.output, "o", "", "Output file or - for stdout") + + set.StringVar(&v.delimiter, "delimiter", "", "Delimiter") + set.StringVar(&v.delimiter, "d", "", "Delimiter") + + set.BoolVar(&v.screaming, "screaming", false, "Screaming mode") + set.BoolVar(&v.screaming, "S", false, "Screaming mode") + + set.BoolVar(&v.whispering, "whispering", false, "Whispering mode") + set.BoolVar(&v.whispering, "w", false, "Whispering mode") + + set.BoolVar(&v.firstUpper, "first-upper", false, "First char upper") + set.BoolVar(&v.firstUpper, "U", false, "First char upper") + + set.BoolVar(&v.firstLower, "first-lower", false, "First char lower") + set.BoolVar(&v.firstLower, "l", false, "First char lower") + + set.BoolVar(&v.mixCaseSupport, "mix-case-support", false, "Mix case support") + set.BoolVar(&v.mixCaseSupport, "m", false, "Mix case support") + + set.BoolVar(&v.noSmartAcronyms, "no-smart-acronyms", false, "Disable smart acronyms") + + set.BoolVar(&v.numberSplitting, "number-splitting", false, "Enable number splitting") + + set.BoolVar(&v.strict, "strict", false, "Strict UTF8 mode") set.Usage = v.Usage v.CommandAction = func(c *Kebab) error { - cli.Kebab(c.input, c.output, c.args...) + cli.Kebab(c.input, c.output, c.delimiter, c.screaming, c.whispering, c.firstUpper, c.firstLower, c.mixCaseSupport, c.noSmartAcronyms, c.numberSplitting, c.strict, c.args...) return nil } diff --git a/cmd/strings2/kebab_test.go b/cmd/strings2/kebab_test.go index 675eb7a..b93ceca 100644 --- a/cmd/strings2/kebab_test.go +++ b/cmd/strings2/kebab_test.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -22,6 +22,20 @@ func TestKebab_Execute(t *testing.T) { } args := []string{} + args = append(args, "--input") + args = append(args, "test") + args = append(args, "--output") + args = append(args, "test") + args = append(args, "--delimiter") + args = append(args, "test") + args = append(args, "--screaming") + args = append(args, "--whispering") + args = append(args, "--firstUpper") + args = append(args, "--firstLower") + args = append(args, "--mixCaseSupport") + args = append(args, "--noSmartAcronyms") + args = append(args, "--numberSplitting") + args = append(args, "--strict") err := cmd.Execute(args) if err != nil { @@ -30,4 +44,38 @@ func TestKebab_Execute(t *testing.T) { if !called { t.Error("CommandAction was not called") } + + if cmd.input != "test" { + t.Errorf("Expected input to be 'test', got '%v'", cmd.input) + } + if cmd.output != "test" { + t.Errorf("Expected output to be 'test', got '%v'", cmd.output) + } + if cmd.delimiter != "test" { + t.Errorf("Expected delimiter to be 'test', got '%v'", cmd.delimiter) + } + if cmd.screaming != true { + t.Errorf("Expected screaming to be true, got '%v'", cmd.screaming) + } + if cmd.whispering != true { + t.Errorf("Expected whispering to be true, got '%v'", cmd.whispering) + } + if cmd.firstUpper != true { + t.Errorf("Expected firstUpper to be true, got '%v'", cmd.firstUpper) + } + if cmd.firstLower != true { + t.Errorf("Expected firstLower to be true, got '%v'", cmd.firstLower) + } + if cmd.mixCaseSupport != true { + t.Errorf("Expected mixCaseSupport to be true, got '%v'", cmd.mixCaseSupport) + } + if cmd.noSmartAcronyms != true { + t.Errorf("Expected noSmartAcronyms to be true, got '%v'", cmd.noSmartAcronyms) + } + if cmd.numberSplitting != true { + t.Errorf("Expected numberSplitting to be true, got '%v'", cmd.numberSplitting) + } + if cmd.strict != true { + t.Errorf("Expected strict to be true, got '%v'", cmd.strict) + } } diff --git a/cmd/strings2/main.go b/cmd/strings2/main.go index 8855959..0c65f47 100644 --- a/cmd/strings2/main.go +++ b/cmd/strings2/main.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -7,6 +7,8 @@ package main import ( "fmt" "os" + + "github.com/arran4/strings2/cmd" ) var ( @@ -23,6 +25,12 @@ func main() { } if err := root.Execute(os.Args[1:]); err != nil { + if e, ok := err.(*cmd.ErrExitCode); ok { + if e.Err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", e.Err) + } + os.Exit(e.Code) + } fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } diff --git a/cmd/strings2/pascal.go b/cmd/strings2/pascal.go index dab3914..ec352bb 100644 --- a/cmd/strings2/pascal.go +++ b/cmd/strings2/pascal.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "strconv" "strings" "github.com/arran4/strings2/cli" @@ -15,12 +16,21 @@ var _ Cmd = (*Pascal)(nil) type Pascal struct { *RootCmd - Flags *flag.FlagSet - input string - output string - args []string - SubCommands map[string]Cmd - CommandAction func(c *Pascal) error + Flags *flag.FlagSet + input string + output string + delimiter string + screaming bool + whispering bool + firstUpper bool + firstLower bool + mixCaseSupport bool + noSmartAcronyms bool + numberSplitting bool + strict bool + args []string + SubCommands map[string]Cmd + CommandAction func(c *Pascal) error } type UsageDataPascal struct { @@ -89,6 +99,105 @@ func (c *Pascal) Execute(args []string) error { } } c.output = value + + case "delimiter", "d": + if !hasValue { + if i+1 < len(args) { + value = args[i+1] + i++ + } else { + return fmt.Errorf("flag %s requires a value", name) + } + } + c.delimiter = value + + case "screaming", "S": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.screaming = b + } else { + c.screaming = true + } + + case "whispering", "w": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.whispering = b + } else { + c.whispering = true + } + + case "firstUpper", "first-upper", "U": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstUpper = b + } else { + c.firstUpper = true + } + + case "firstLower", "first-lower", "l": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstLower = b + } else { + c.firstLower = true + } + + case "mixCaseSupport", "mix-case-support", "m": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.mixCaseSupport = b + } else { + c.mixCaseSupport = true + } + + case "noSmartAcronyms", "no-smart-acronyms": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.noSmartAcronyms = b + } else { + c.noSmartAcronyms = true + } + + case "numberSplitting", "number-splitting": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.numberSplitting = b + } else { + c.numberSplitting = true + } + + case "strict": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.strict = b + } else { + c.strict = true + } case "help", "h": c.Usage() return nil @@ -133,11 +242,35 @@ func (c *RootCmd) NewPascal() *Pascal { set.StringVar(&v.output, "output", "", "Output file or - for stdout") set.StringVar(&v.output, "o", "", "Output file or - for stdout") + + set.StringVar(&v.delimiter, "delimiter", "", "Delimiter") + set.StringVar(&v.delimiter, "d", "", "Delimiter") + + set.BoolVar(&v.screaming, "screaming", false, "Screaming mode") + set.BoolVar(&v.screaming, "S", false, "Screaming mode") + + set.BoolVar(&v.whispering, "whispering", false, "Whispering mode") + set.BoolVar(&v.whispering, "w", false, "Whispering mode") + + set.BoolVar(&v.firstUpper, "first-upper", false, "First char upper") + set.BoolVar(&v.firstUpper, "U", false, "First char upper") + + set.BoolVar(&v.firstLower, "first-lower", false, "First char lower") + set.BoolVar(&v.firstLower, "l", false, "First char lower") + + set.BoolVar(&v.mixCaseSupport, "mix-case-support", false, "Mix case support") + set.BoolVar(&v.mixCaseSupport, "m", false, "Mix case support") + + set.BoolVar(&v.noSmartAcronyms, "no-smart-acronyms", false, "Disable smart acronyms") + + set.BoolVar(&v.numberSplitting, "number-splitting", false, "Enable number splitting") + + set.BoolVar(&v.strict, "strict", false, "Strict UTF8 mode") set.Usage = v.Usage v.CommandAction = func(c *Pascal) error { - cli.Pascal(c.input, c.output, c.args...) + cli.Pascal(c.input, c.output, c.delimiter, c.screaming, c.whispering, c.firstUpper, c.firstLower, c.mixCaseSupport, c.noSmartAcronyms, c.numberSplitting, c.strict, c.args...) return nil } diff --git a/cmd/strings2/pascal_test.go b/cmd/strings2/pascal_test.go index c74e83c..828f170 100644 --- a/cmd/strings2/pascal_test.go +++ b/cmd/strings2/pascal_test.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -22,6 +22,20 @@ func TestPascal_Execute(t *testing.T) { } args := []string{} + args = append(args, "--input") + args = append(args, "test") + args = append(args, "--output") + args = append(args, "test") + args = append(args, "--delimiter") + args = append(args, "test") + args = append(args, "--screaming") + args = append(args, "--whispering") + args = append(args, "--firstUpper") + args = append(args, "--firstLower") + args = append(args, "--mixCaseSupport") + args = append(args, "--noSmartAcronyms") + args = append(args, "--numberSplitting") + args = append(args, "--strict") err := cmd.Execute(args) if err != nil { @@ -30,4 +44,38 @@ func TestPascal_Execute(t *testing.T) { if !called { t.Error("CommandAction was not called") } + + if cmd.input != "test" { + t.Errorf("Expected input to be 'test', got '%v'", cmd.input) + } + if cmd.output != "test" { + t.Errorf("Expected output to be 'test', got '%v'", cmd.output) + } + if cmd.delimiter != "test" { + t.Errorf("Expected delimiter to be 'test', got '%v'", cmd.delimiter) + } + if cmd.screaming != true { + t.Errorf("Expected screaming to be true, got '%v'", cmd.screaming) + } + if cmd.whispering != true { + t.Errorf("Expected whispering to be true, got '%v'", cmd.whispering) + } + if cmd.firstUpper != true { + t.Errorf("Expected firstUpper to be true, got '%v'", cmd.firstUpper) + } + if cmd.firstLower != true { + t.Errorf("Expected firstLower to be true, got '%v'", cmd.firstLower) + } + if cmd.mixCaseSupport != true { + t.Errorf("Expected mixCaseSupport to be true, got '%v'", cmd.mixCaseSupport) + } + if cmd.noSmartAcronyms != true { + t.Errorf("Expected noSmartAcronyms to be true, got '%v'", cmd.noSmartAcronyms) + } + if cmd.numberSplitting != true { + t.Errorf("Expected numberSplitting to be true, got '%v'", cmd.numberSplitting) + } + if cmd.strict != true { + t.Errorf("Expected strict to be true, got '%v'", cmd.strict) + } } diff --git a/cmd/strings2/root.go b/cmd/strings2/root.go index f5d2a97..024359d 100644 --- a/cmd/strings2/root.go +++ b/cmd/strings2/root.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -60,7 +60,7 @@ type RootCmd struct { func (c *RootCmd) Usage() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) - c.FlagSet.PrintDefaults() + c.PrintDefaults() fmt.Fprintln(os.Stderr, " Commands:") for name := range c.Commands { fmt.Fprintf(os.Stderr, " %s\n", name) @@ -69,7 +69,7 @@ func (c *RootCmd) Usage() { func (c *RootCmd) UsageRecursive() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) - c.FlagSet.PrintDefaults() + c.PrintDefaults() fmt.Fprintln(os.Stderr, " Commands:") fmt.Fprintf(os.Stderr, " %s\n", "camel") fmt.Fprintf(os.Stderr, " %s\n", "kebab") @@ -130,10 +130,10 @@ func NewRoot(name, version, commit, date string) (*RootCmd, error) { } func (c *RootCmd) Execute(args []string) error { - if err := c.FlagSet.Parse(args); err != nil { + if err := c.Parse(args); err != nil { return NewUserError(err, fmt.Sprintf("flag parse error %s", err.Error())) } - remainingArgs := c.FlagSet.Args() + remainingArgs := c.Args() if len(remainingArgs) < 1 { c.Usage() return nil diff --git a/cmd/strings2/root_test.go b/cmd/strings2/root_test.go index 6d4868c..87ca9a9 100644 --- a/cmd/strings2/root_test.go +++ b/cmd/strings2/root_test.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main diff --git a/cmd/strings2/snake.go b/cmd/strings2/snake.go index 31fb548..10bbb18 100644 --- a/cmd/strings2/snake.go +++ b/cmd/strings2/snake.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "strconv" "strings" "github.com/arran4/strings2/cli" @@ -15,12 +16,21 @@ var _ Cmd = (*Snake)(nil) type Snake struct { *RootCmd - Flags *flag.FlagSet - input string - output string - args []string - SubCommands map[string]Cmd - CommandAction func(c *Snake) error + Flags *flag.FlagSet + input string + output string + delimiter string + screaming bool + whispering bool + firstUpper bool + firstLower bool + mixCaseSupport bool + noSmartAcronyms bool + numberSplitting bool + strict bool + args []string + SubCommands map[string]Cmd + CommandAction func(c *Snake) error } type UsageDataSnake struct { @@ -89,6 +99,105 @@ func (c *Snake) Execute(args []string) error { } } c.output = value + + case "delimiter", "d": + if !hasValue { + if i+1 < len(args) { + value = args[i+1] + i++ + } else { + return fmt.Errorf("flag %s requires a value", name) + } + } + c.delimiter = value + + case "screaming", "S": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.screaming = b + } else { + c.screaming = true + } + + case "whispering", "w": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.whispering = b + } else { + c.whispering = true + } + + case "firstUpper", "first-upper", "U": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstUpper = b + } else { + c.firstUpper = true + } + + case "firstLower", "first-lower", "l": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.firstLower = b + } else { + c.firstLower = true + } + + case "mixCaseSupport", "mix-case-support", "m": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.mixCaseSupport = b + } else { + c.mixCaseSupport = true + } + + case "noSmartAcronyms", "no-smart-acronyms": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.noSmartAcronyms = b + } else { + c.noSmartAcronyms = true + } + + case "numberSplitting", "number-splitting": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.numberSplitting = b + } else { + c.numberSplitting = true + } + + case "strict": + if hasValue { + b, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("invalid boolean value for flag %s: %s", name, value) + } + c.strict = b + } else { + c.strict = true + } case "help", "h": c.Usage() return nil @@ -133,11 +242,35 @@ func (c *RootCmd) NewSnake() *Snake { set.StringVar(&v.output, "output", "", "Output file or - for stdout") set.StringVar(&v.output, "o", "", "Output file or - for stdout") + + set.StringVar(&v.delimiter, "delimiter", "", "Delimiter") + set.StringVar(&v.delimiter, "d", "", "Delimiter") + + set.BoolVar(&v.screaming, "screaming", false, "Screaming mode") + set.BoolVar(&v.screaming, "S", false, "Screaming mode") + + set.BoolVar(&v.whispering, "whispering", false, "Whispering mode") + set.BoolVar(&v.whispering, "w", false, "Whispering mode") + + set.BoolVar(&v.firstUpper, "first-upper", false, "First char upper") + set.BoolVar(&v.firstUpper, "U", false, "First char upper") + + set.BoolVar(&v.firstLower, "first-lower", false, "First char lower") + set.BoolVar(&v.firstLower, "l", false, "First char lower") + + set.BoolVar(&v.mixCaseSupport, "mix-case-support", false, "Mix case support") + set.BoolVar(&v.mixCaseSupport, "m", false, "Mix case support") + + set.BoolVar(&v.noSmartAcronyms, "no-smart-acronyms", false, "Disable smart acronyms") + + set.BoolVar(&v.numberSplitting, "number-splitting", false, "Enable number splitting") + + set.BoolVar(&v.strict, "strict", false, "Strict UTF8 mode") set.Usage = v.Usage v.CommandAction = func(c *Snake) error { - cli.Snake(c.input, c.output, c.args...) + cli.Snake(c.input, c.output, c.delimiter, c.screaming, c.whispering, c.firstUpper, c.firstLower, c.mixCaseSupport, c.noSmartAcronyms, c.numberSplitting, c.strict, c.args...) return nil } diff --git a/cmd/strings2/snake_test.go b/cmd/strings2/snake_test.go index 6e74249..61a0459 100644 --- a/cmd/strings2/snake_test.go +++ b/cmd/strings2/snake_test.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package main @@ -22,6 +22,20 @@ func TestSnake_Execute(t *testing.T) { } args := []string{} + args = append(args, "--input") + args = append(args, "test") + args = append(args, "--output") + args = append(args, "test") + args = append(args, "--delimiter") + args = append(args, "test") + args = append(args, "--screaming") + args = append(args, "--whispering") + args = append(args, "--firstUpper") + args = append(args, "--firstLower") + args = append(args, "--mixCaseSupport") + args = append(args, "--noSmartAcronyms") + args = append(args, "--numberSplitting") + args = append(args, "--strict") err := cmd.Execute(args) if err != nil { @@ -30,4 +44,38 @@ func TestSnake_Execute(t *testing.T) { if !called { t.Error("CommandAction was not called") } + + if cmd.input != "test" { + t.Errorf("Expected input to be 'test', got '%v'", cmd.input) + } + if cmd.output != "test" { + t.Errorf("Expected output to be 'test', got '%v'", cmd.output) + } + if cmd.delimiter != "test" { + t.Errorf("Expected delimiter to be 'test', got '%v'", cmd.delimiter) + } + if cmd.screaming != true { + t.Errorf("Expected screaming to be true, got '%v'", cmd.screaming) + } + if cmd.whispering != true { + t.Errorf("Expected whispering to be true, got '%v'", cmd.whispering) + } + if cmd.firstUpper != true { + t.Errorf("Expected firstUpper to be true, got '%v'", cmd.firstUpper) + } + if cmd.firstLower != true { + t.Errorf("Expected firstLower to be true, got '%v'", cmd.firstLower) + } + if cmd.mixCaseSupport != true { + t.Errorf("Expected mixCaseSupport to be true, got '%v'", cmd.mixCaseSupport) + } + if cmd.noSmartAcronyms != true { + t.Errorf("Expected noSmartAcronyms to be true, got '%v'", cmd.noSmartAcronyms) + } + if cmd.numberSplitting != true { + t.Errorf("Expected numberSplitting to be true, got '%v'", cmd.numberSplitting) + } + if cmd.strict != true { + t.Errorf("Expected strict to be true, got '%v'", cmd.strict) + } } diff --git a/cmd/strings2/templates/camel_usage.txt b/cmd/strings2/templates/camel_usage.txt index 7eff533..aef74ee 100644 --- a/cmd/strings2/templates/camel_usage.txt +++ b/cmd/strings2/templates/camel_usage.txt @@ -1,12 +1,22 @@ -{{/* Generated by github.com/arran4/go-subcommand/cmd/gosubc */}}Usage: strings2 camel [flags...] [args...] +{{/* Do not modify: Generated by github.com/arran4/go-subcommand/cmd/gosubc */-}} +Usage: strings2 camel [flags...] [args...] Subcommands: help Print this help message usage Print this usage message Flags: - --input, -i string Input file or - for stdin - --output, -o string Output file or - for stdout + --input, -i string Input file or - for stdin + --output, -o string Output file or - for stdout + --delimiter, -d string Delimiter + --screaming, -S (default: false) Screaming mode + --whispering, -w (default: false) Whispering mode + --first-upper, -U (default: false) First char upper + --first-lower, -l (default: false) First char lower + --mix-case-support, -m (default: false) Mix case support + --no-smart-acronyms (default: false) Disable smart acronyms + --number-splitting (default: false) Enable number splitting + --strict (default: false) Strict UTF8 mode Positional Arguments: args String to convert if file/stdin not provided diff --git a/cmd/strings2/templates/kebab_usage.txt b/cmd/strings2/templates/kebab_usage.txt index 08b810a..2eb63ff 100644 --- a/cmd/strings2/templates/kebab_usage.txt +++ b/cmd/strings2/templates/kebab_usage.txt @@ -1,12 +1,22 @@ -{{/* Generated by github.com/arran4/go-subcommand/cmd/gosubc */}}Usage: strings2 kebab [flags...] [args...] +{{/* Do not modify: Generated by github.com/arran4/go-subcommand/cmd/gosubc */-}} +Usage: strings2 kebab [flags...] [args...] Subcommands: help Print this help message usage Print this usage message Flags: - --input, -i string Input file or - for stdin - --output, -o string Output file or - for stdout + --input, -i string Input file or - for stdin + --output, -o string Output file or - for stdout + --delimiter, -d string Delimiter + --screaming, -S (default: false) Screaming mode + --whispering, -w (default: false) Whispering mode + --first-upper, -U (default: false) First char upper + --first-lower, -l (default: false) First char lower + --mix-case-support, -m (default: false) Mix case support + --no-smart-acronyms (default: false) Disable smart acronyms + --number-splitting (default: false) Enable number splitting + --strict (default: false) Strict UTF8 mode Positional Arguments: args String to convert if file/stdin not provided diff --git a/cmd/strings2/templates/pascal_usage.txt b/cmd/strings2/templates/pascal_usage.txt index 01e3345..dacb506 100644 --- a/cmd/strings2/templates/pascal_usage.txt +++ b/cmd/strings2/templates/pascal_usage.txt @@ -1,12 +1,22 @@ -{{/* Generated by github.com/arran4/go-subcommand/cmd/gosubc */}}Usage: strings2 pascal [flags...] [args...] +{{/* Do not modify: Generated by github.com/arran4/go-subcommand/cmd/gosubc */-}} +Usage: strings2 pascal [flags...] [args...] Subcommands: help Print this help message usage Print this usage message Flags: - --input, -i string Input file or - for stdin - --output, -o string Output file or - for stdout + --input, -i string Input file or - for stdin + --output, -o string Output file or - for stdout + --delimiter, -d string Delimiter + --screaming, -S (default: false) Screaming mode + --whispering, -w (default: false) Whispering mode + --first-upper, -U (default: false) First char upper + --first-lower, -l (default: false) First char lower + --mix-case-support, -m (default: false) Mix case support + --no-smart-acronyms (default: false) Disable smart acronyms + --number-splitting (default: false) Enable number splitting + --strict (default: false) Strict UTF8 mode Positional Arguments: args String to convert if file/stdin not provided diff --git a/cmd/strings2/templates/snake_usage.txt b/cmd/strings2/templates/snake_usage.txt index 03e82e9..3cd9b99 100644 --- a/cmd/strings2/templates/snake_usage.txt +++ b/cmd/strings2/templates/snake_usage.txt @@ -1,12 +1,22 @@ -{{/* Generated by github.com/arran4/go-subcommand/cmd/gosubc */}}Usage: strings2 snake [flags...] [args...] +{{/* Do not modify: Generated by github.com/arran4/go-subcommand/cmd/gosubc */-}} +Usage: strings2 snake [flags...] [args...] Subcommands: help Print this help message usage Print this usage message Flags: - --input, -i string Input file or - for stdin - --output, -o string Output file or - for stdout + --input, -i string Input file or - for stdin + --output, -o string Output file or - for stdout + --delimiter, -d string Delimiter + --screaming, -S (default: false) Screaming mode + --whispering, -w (default: false) Whispering mode + --first-upper, -U (default: false) First char upper + --first-lower, -l (default: false) First char lower + --mix-case-support, -m (default: false) Mix case support + --no-smart-acronyms (default: false) Disable smart acronyms + --number-splitting (default: false) Enable number splitting + --strict (default: false) Strict UTF8 mode Positional Arguments: args String to convert if file/stdin not provided diff --git a/cmd/strings2/templates/templates.go b/cmd/strings2/templates/templates.go index 45cfbb5..2b4ce08 100644 --- a/cmd/strings2/templates/templates.go +++ b/cmd/strings2/templates/templates.go @@ -1,4 +1,4 @@ -// Generated by github.com/arran4/go-subcommand/cmd/gosubc +// Code generated by github.com/arran4/go-subcommand/cmd/gosubc. DO NOT EDIT. package templates diff --git a/permutations.go b/permutations.go index 1c23ebf..d0c0cf3 100644 --- a/permutations.go +++ b/permutations.go @@ -5,44 +5,52 @@ package strings2 // ToCamel converts an input string (auto-detected format) to camelCase. func ToCamel(input string, opts ...any) (string, error) { // Camel: Delimiter "", FirstLower, AllTitle - return ToFormattedString(input, append(opts, OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle)} + return ToFormattedString(input, append(defaults, opts...)...) } // ToSnake converts an input string (auto-detected format) to snake_case. func ToSnake(input string, opts ...any) (string, error) { // Snake: Delimiter "_" - return ToFormattedString(input, append(opts, OptionDelimiter("_"))...) + defaults := []any{OptionDelimiter("_")} + return ToFormattedString(input, append(defaults, opts...)...) } // ToKebab converts an input string (auto-detected format) to kebab-case. func ToKebab(input string, opts ...any) (string, error) { // Kebab: Delimiter "-" - return ToFormattedString(input, append(opts, OptionDelimiter("-"))...) + defaults := []any{OptionDelimiter("-")} + return ToFormattedString(input, append(defaults, opts...)...) } // ToPascal converts an input string (auto-detected format) to PascalCase. func ToPascal(input string, opts ...any) (string, error) { // Pascal: Delimiter "", FirstUpper, AllTitle - return ToFormattedString(input, append(opts, OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle)} + return ToFormattedString(input, append(defaults, opts...)...) } // FromWordsToY // FromWordsToCamel converts words to camelCase. func FromWordsToCamel(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle)} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } func FromWordsToSnake(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter("_"))...) + defaults := []any{OptionDelimiter("_")} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } func FromWordsToKebab(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter("-"))...) + defaults := []any{OptionDelimiter("-")} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } func FromWordsToPascal(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle)} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } // FromXToWords diff --git a/types.go b/types.go index 1e58b8b..1bf1568 100644 --- a/types.go +++ b/types.go @@ -478,20 +478,24 @@ func splitMixCase(input, delimiter string) string { // ToKebabCase converts words into kebab-case format. func ToKebabCase(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter("-"))...) + defaults := []any{OptionDelimiter("-")} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } // ToSnakeCase converts words into snake_case format. func ToSnakeCase(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter("_"))...) + defaults := []any{OptionDelimiter("_")} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } // ToPascalCase converts words into PascalCase format. func ToPascalCase(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstUpper(), OptionCaseMode(CMAllTitle)} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) } // ToCamelCase converts words into camelCase format. func ToCamelCase(words []Word, opts ...Option) (string, error) { - return WordsToFormattedCase(words, append(convertOptions(opts), OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle))...) + defaults := []any{OptionDelimiter(""), OptionFirstLower(), OptionCaseMode(CMAllTitle)} + return WordsToFormattedCase(words, append(defaults, convertOptions(opts)...)...) }