urfave/cli

How to use a custom CLI flag separator

Closed this issue · 8 comments

I'm new to Go so please bare with me.

I have an application which accepts multiple --groups flags by using StringSliceFlag which works great.

I can use it with fancy_name --groups="asdf" --groups="qwertz" and get [asdf qwertz].

As soon as the value of the args contains a , it does the right thing and splits it at the comma. fancy_name --groups="asdf,foo" --groups="qwertz" becomes [asdf foo qwertz] but I would need [asdf,foo qwertz]. This is where #1241 and #1134 becomes interesting. I already tried to set app.SliceFlagSeparator = ";" but this has no effect on the flag parsing. Changing the defaultSliceFlagSeparator in flag.go to e.g. ; solved the problem of course.

So my question in the end is how to set a slice separator for all or a specific flag

func main() {
    app := cli.NewApp()

    cli.AppHelpTemplate = flags.Template
    cli.HelpPrinterCustom = flags.HelpPrinter
    // Force the use of cli.HelpPrinterCustom.
    app.ExtraInfo = func() map[string]string { return map[string]string{} }
    app.SliceFlagSeparator = ";"
    // app.DisableSliceFlagSeparator = true
    
    app.Flags = flags.GetCliFlags()
    app.Action = run

    err := app.Run(os.Args)
    if err != nil {
        log.Fatal("terminated:", err)
    }
}

func GetCliFlags() []cli.Flag {
    return []cli.Flag{
        &cli.StringSliceFlag{
            Name:    "groups",
            Value:   cli.NewStringSlice("this,that,other", "foo"),
            Usage:   "Groups, can be given multiple times",
            // EnvVars: []string{"GROUPS"},
    }
}

not setting a Value for StringSliceFlag solves the issue somehow. fancy_name --groups="asdf,foo" --groups="qwertz" then returns the expected content which is [asdf,foo qwertz]

I already tried to set app.SliceFlagSeparator = ";" but this has no effect
I guess that is a bug

or a specific flag
I don't see a real usage fof setting separator per flag but having a Separator string on the StringSliceFlag could solve it

Can you try WithSeparatorSpec on the string slice flag ?

could you give me a code hint for WithSeparatorSpec on a StringSliceFlag? May I do something wrong as Go newbie, because of unknown field 'WithSeparatorSpec' in struct literal of type cli.StringSliceFlag

yes I do, v2.27.0

I still believe this is a syntax thing on my side

func GetCliFlags() []cli.Flag {
    return []cli.Flag{
        &cli.StringSliceFlag{
            Name:    "groups",
            Value:   cli.NewStringSlice("this,that,other", "foo"),
            Usage:   "Groups, can be given multiple times",
            WithSeparatorSpec: cli.separatorSpec{sep: ";"},
    }
}

Ah no you need to do

func GetCliFlags() []cli.Flag {
    ssflag := &cli.StringSliceFlag{
            Name:    "groups",
            Value:   cli.NewStringSlice("this,that,other", "foo"),
            Usage:   "Groups, can be given multiple times",
    }
    ssflag.WithSeparatorSpec(cli.separatorSpec{sep: ";"})

    return []cli.Flag{
        ssflag,
    }
}

Thanks for the hint, but it does not work as separatorSpec is not exported (function starting with lower case). In the yet unreleased v3 this is even no longer available

./first.go:90:34: separatorSpec not exported by package cli
./first.go:90:48: unknown field 'sep' in struct literal of type cli.separatorSpec

I'll stay with v2, keep the setting globally and use no default value