go-plugin/cli/flag_string_slice.go
Robert Kaussow 044f72ed49 feat: add custom cli flags (#48)
Adds two custom cli flags:
- `StringMapFlag` parses JSON to string map used for plugin map options
- `StringSliceFlag` parses comma-separated plugin slice options to slice and supports escaping

Reviewed-on: https://codeberg.org/woodpecker-plugins/go-plugin/pulls/48
Reviewed-by: Patrick Schratz <pat-s@noreply.codeberg.org>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
Co-committed-by: Robert Kaussow <mail@thegeeklab.de>
2025-04-23 18:01:11 +00:00

84 lines
1.8 KiB
Go

package cli
import (
"fmt"
"strings"
"github.com/urfave/cli/v3"
)
// StringSliceFlag is a flag type which support comma separated values and escaping to not split at unwanted lines.
type (
StringSliceFlag = cli.FlagBase[[]string, StringSliceConfig, StringSlice]
)
// StringConfig defines the configuration for string flags.
type StringSliceConfig struct {
Delimiter string
EscapeString string
}
// StringSlice implements the Value and ValueCreator interfaces for string slices.
type StringSlice struct {
destination *[]string
delimiter string
escapeString string
}
// Create implements the ValueCreator interface.
func (s StringSlice) Create(v []string, p *[]string, c StringSliceConfig) cli.Value {
*p = v
return &StringSlice{
destination: p,
delimiter: c.Delimiter,
escapeString: c.EscapeString,
}
}
// ToString implements the ValueCreator interface.
func (s StringSlice) ToString(v []string) string {
if len(v) == 0 {
return ""
}
return fmt.Sprintf("%q", strings.Join(v, s.delimiter))
}
// Set implements the flag.Value interface.
func (s *StringSlice) Set(v string) error {
if v == "" {
*s.destination = []string{}
return nil
}
out := strings.Split(v, s.delimiter)
//nolint:mnd
for i := len(out) - 2; i >= 0; i-- {
if strings.HasSuffix(out[i], s.escapeString) {
out[i] = out[i][:len(out[i])-len(s.escapeString)] + s.delimiter + out[i+1]
out = append(out[:i+1], out[i+2:]...)
}
}
*s.destination = out
return nil
}
// Get implements the flag.Value interface.
func (s *StringSlice) Get() any {
return *s.destination
}
// String implements the flag.Value interface.
func (s *StringSlice) String() string {
if s.destination == nil || len(*s.destination) == 0 {
return ""
}
return strings.Join(*s.destination, s.delimiter)
}