complete icon indicating copy to clipboard operation
complete copied to clipboard

'Sub:' and 'Flags:' don't seem to work together.

Open colecrouter opened this issue 3 years ago • 3 comments

var force = flag.String("f", "", "force")
...

// Auto completion
cmd := &complete.Command{
	Sub: map[string]*complete.Command{
		"update": {
			Sub: offPred,
			Flags: map[string]complete.Predictor{
				"f": predict.Nothing,
			},
		},
	},
}
cmd.Complete("<cmd>")

On the latest version, when I execute this code, only Sub: will get suggested. However, if I remove the Sub: entirely, then Flags: show up. I have the feeling I'm doing it wrong, but I've boiled it down to this, at least.

PS: I'm using Kong as well, and the -h flag always shows up automatically (not sure if that's Kong or this package), but that flag shows up fine.

colecrouter avatar Mar 06 '21 01:03 colecrouter

Not sure what is the issue.

I've copied your code and removed the Sub:

package main

import (
	"flag"

	"github.com/posener/complete/v2"
	"github.com/posener/complete/v2/predict"
)

var force = flag.String("f", "", "force")

func main() {
	cmd := &complete.Command{
		Sub: map[string]*complete.Command{
			"update": {
				Flags: map[string]complete.Predictor{
					"f": predict.Nothing,
				},
			},
		},
	}
	cmd.Complete("issue134")
}

Then installed it:

$ go build .
$ COMP_INSTALL=1 ./issue134
$ source ~/.bashrc

Then, checked completion, and it works:

$ ./issue134<tab>
-h      update
$ ./issue134 update -<tab>
-f  -h  

Regarding the -h flag:

This is due to Go's flag library behavior, where the -h and --help flags not necessarily need to be explicitly defined, but could also be used when an ErrHelp is returned: https://github.com/golang/go/blob/afe7c8d0b25f26f0abd749ca52c7e1e7dfdee8cb/src/flag/flag.go#L945. Maybe the completion should not be there, I'm not sure about the right behavior.

posener avatar Mar 13 '21 10:03 posener

After seeing your example, I think I see where my problem is. It looks like the way it's designed is so you would put the "flag" on the last "subcommand", instead of beside it. In theory, you wouldn't ever need to have a "flag" and a "subcommand" in the same complete.Command.

Here's my issue. I have a program set up (I'm programming it) that takes in any amount of inputs. Example:

command update -f <name1> <name2> <name3> ...

What I've been doing so far is making a recursive complete.Command, and passing that in as Sub to my "subcommands". The "subcommands" are just the predicted "name1, name2, etc", and that works fine (really janky I guess). When I pass in a flag (like above), it applies the -f flag to each name, as opposed to just one, ie:

command update <name1> -f <name2> -f <name3> -f ...

Just now, I found a workaround by adding each flag as a recursive subcommand.

offPred := make(map[string]*complete.Command)      // Instances that are off
updatePred := make(map[string]*complete.Command)
...
// Copy offPred into updatePred
for k, v := range offPred {
    updatePred[k] = v
}
// Pseudo "flags"
updatePred["-f"] = &complete.Command{Sub: offPred}
updatePred["-n"] = &complete.Command{Sub: offPred}
...
cmd := &complete.Command{
    Sub: map[string]*complete.Command{
	"update": {
	    Sub: updatePred,
	},
    },
}

This way, I can have the flag after "update" instead of after each name. This works I guess, but it's very janky and probably super inefficient. It would be nice to be able to specify a flag alongside subcommands (at least, I don't see a reason why not).

That being said, I'm already 10 miles outside the intended use case anyway, so I could understand if you think this "suggestion" is bad, although I know there are a handful of programs out there which use flags in the same manner as I am right now.

Thanks for the example, btw.

colecrouter avatar Mar 14 '21 02:03 colecrouter

^ this is how v1 worked. It feels like there are a lot of assumptions made in v2 that — IMO — take away the thing I liked most about the library. Not every command framework has -h as a default. Not every tool inherits flags from previous commands.

Yes, these are good hygiene and things arguably should do those. But this lib should just take a hierarchy of commands, flags, and persistent flags to complete, and follow it strictly.

coxley avatar Jan 14 '23 05:01 coxley