package cmd import ( "errors" "fmt" "strings" "git.iamthefij.com/iamthefij/slog" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( ErrMissingArgument = errors.New("missing positional argument") ErrTooManyRequiredArgs = errors.New("more args specified as required than provided") ) func bindFlag(flagname string) { slog.OnErrFatalf( viper.BindPFlag(flagname, rootCmd.PersistentFlags().Lookup(flagname)), "failed binding flag: "+flagname, ) } func WrapPositionalArgs(cmd *cobra.Command, positionalArgs []string, numRequired int) *cobra.Command { // TODO: Find a better place for this validation if numRequired > len(positionalArgs) { panic(ErrTooManyRequiredArgs) } // Add required args to Use if numRequired > 0 { cmd.Use = fmt.Sprintf("%s <%s>", cmd.Use, strings.Join(positionalArgs[0:numRequired], "> <")) } // Add optional args to Use optionalArgs := positionalArgs[numRequired:] if len(optionalArgs) > 0 { cmd.Use = fmt.Sprintf("%s [%s]", cmd.Use, strings.Join(optionalArgs, "] [")) } oldArgs := cmd.Args cmd.Args = func(cmd *cobra.Command, args []string) error { lastArgPos := len(args) if lastArgPos < numRequired { return fmt.Errorf("missing argument `%s` in position %d: %w", positionalArgs[lastArgPos], lastArgPos, ErrMissingArgument) } if oldArgs != nil { return oldArgs(cmd, args) } return nil } return cmd }