Open dearchap opened 1 month ago
@ldelossa what release are you using ?
Hey there @dearchap
module github.com/ldelossa/cmds
go 1.22.2
require (
github.com/urfave/cli/v3 v3.0.0-alpha9
gopkg.in/yaml.v3 v3.0.1
)
So v3.
You can see my code here: https://github.com/ldelossa/cmds/blob/main/main.go#L129
Tho its a bit funky, since I'm generating a command graph based off a yaml config.
@ldelossa Its okay to generate the cmd graph from a yaml. I dont see any real issues with your implementation. It should work. You sourced the zsh completion script for this app correct ? Everytime you hit
@dearchap Here is a screencap of the issue, as you can see, I can not get tab completion for any flag hanging off the sub command 'automation'
https://github.com/urfave/cli/assets/5642902/dddea9f3-3448-473e-bc5e-f66eee0ec02c
I'm not sure how I can debug the simulation of hitting tab
at a particular location in the desired command.
For example, I want my debugger to stop at the code that generates the shell completion, but only after I have the string cmds automation rocky-linux --
as the prefix to completion. Does the --generate-shell-completion
command take a string prefix?
Here is the output from just running the flag:
cmds --generate-shell-completion
extract-scripts:extracts all embedded scripts to XDG_CONFIG_DIR/cmds/scripts/
kernel:Various commands to assist with Linux Kernel development
ker:Various commands to assist with Linux Kernel development
rsync:Various Rsync helpers
rs:Various Rsync helpers
debug:Various helpers related to debugging software
automation:Scripts for automating server setup.
git:Various git helpers
g:Various git helpers
k8s:Various Kubernetes helpers
k:Various Kubernetes helpers
help:Shows a list of commands or help for one command
h:Shows a list of commands or help for one command
By the way, this is only a problem with flags, completion of arbitrarily nested sub-command names work fine.
@dearchap
Are you sure I should be seeing completion for flags?
~/go/cmds main*
01:38:11PM 🖳 ./cmds automation rocky-linux --generate-shell-completion
~/go/cmds main*
01:38:26PM 🖳 ./cmds automation --generate-shell-completion
rocky-linux:Setup a Rocky Linux instance for development
~/go/cmds main*
01:38:32PM 🖳 ./cmds automation rocky-linux
NAME:
cmds automation rocky-linux - Setup a Rocky Linux instance for development
USAGE:
cmds automation rocky-linux [arguments...]
DESCRIPTION:
Connects to a remote Rocky Linux instance and applies an automated setup.
Once the setup is finished the instance is capable of compiling and running a custom Linux kernel.
The automated setup process will interactively prompt for a password for the provided user.
OPTIONS:
--remote value, -r value The remote host
--user value, -u value The non-root user created for general usage
--help, -h show help (default: false)
2024/05/30 13:38:49 Required flags "remote, user" not set
I think the above demonstrates clearly that no flags are being generated for completion.
I debugged it a bit, but I never see the --
characters being submitted for any completion func to evaluate flags.
@dearchap
Here is a repo with a very lean reproduction: https://github.com/ldelossa/urfacecli_test
Just
go build -o main .
source ./main_autocomplete
And try to perform autocompletion for the flag hanging off subcommand
in a ZSH instance. It does not work.
@ldelossa I tried out your lean code and it works for me. Are you in a zsh first of all ? also how are you invoking the program main
or ./main
. For me main
is throwing some vague output whereas ./main
works just fine with tab completion
% echo $ZSH_NAME
zsh
% echo $ZSH_VERSION
5.8
Very interesting!
Okay thank you for confirming this is an issue locally.
I always invoke with ./main.
But now, let me enter a zsh with absolute minimum config and see if it works.
Okay @dearchap
So I am on zsh 5.9 and this does not work. Here is an example on my system:
https://github.com/urfave/cli/assets/5642902/ff5efe15-5277-4a03-9585-cb4e87874076
And here is the script:
03:44:53PM 🖳 zsh -f
fedora% echo $ZSH_VERSION
5.9
fedora% autoload -Uz compinit
fedora% compinit
fedora% source ./main_autocomplete
fedora%
fedora%
fedora% ./main command subcommand
NAME:
cli command subcommand
USAGE:
cli command subcommand [command [command options]] [arguments...]
COMMANDS:
help, h Shows a list of commands or help for one command
OPTIONS:
--flag value, -f value flag
--help, -h show help (default: false)
fedora% ./main command subcommand --generate-shell-completion
help:Shows a list of commands or help for one command
h:Shows a list of commands or help for one command
fedora%
Tried the same thing in a zsh 5.8 container:
03:50:38PM 🖳 docker run -v $(pwd):/src -it --rm zshusers/zsh:5.8
6befea125665# cd /src
6befea125665# ls -la
total 4444
drwxr-xr-x. 1 1000 1000 88 May 30 18:13 .
drwxr-xr-x. 1 root root 158 May 30 19:50 ..
drwxr-xr-x. 1 1000 1000 196 May 30 18:14 .git
-rw-r--r--. 1 1000 1000 154 May 30 18:05 go.mod
-rw-r--r--. 1 1000 1000 1078 May 30 18:05 go.sum
-rwxr-xr-x. 1 1000 1000 4528215 May 30 18:12 main
-rw-r--r--. 1 1000 1000 662 May 30 18:12 main.go
-rw-r--r--. 1 1000 1000 750 May 30 18:11 main_autocomplete
6befea125665# autoload -Uz compinit
6befea125665# compinit
6befea125665# source ./main_autocomplete
6befea125665# ./main command subcommand --
NAME:
cli command subcommand
USAGE:
cli command subcommand [command [command options]] [arguments...]
COMMANDS:
help, h Shows a list of commands or help for one command
OPTIONS:
--flag value, -f value flag
--help, -h show help (default: false)
6befea125665# ./main command subcommand --generate-shell-completion
help
h
6befea125665#
Are you hitting TAB after the command and you see the subcommand ? If you hit the TAB after subcommand you should see h for help. The generate-shell-completion arg is automatically passed to the program when TAB is hit. You shouldn't need to type in --generate-shell-completion manually unless you are testing the autocomplete behavior . So what exactly is the problem here ? I'm confused
@dearchap
I'm trying to get completion for the flag hanging off 'subcommand'.
For instance if I do this:
./main command subcommand -<TAB>
I expect to see completion suggestions like this:
-f --flag
That was the original question created in the discussion topic.
@ldelossa Ok I understand now. Yes looks like there is an issue. Let me see what I can do
@ldelossa Can you do export URFAVE_CLI_TRACING="on"
and then try hitting the TAB during subcommand .?
No problem @dearchap
The output was very large so put it in a pastebin: https://pastebin.com/Y84QDy2h
@ldelossa Are you typing "--" at the end ? Can you try "-" and then hit the tab ?
@dearchap no problem, here's latest: https://pastebin.com/jtEf28Xt
We seem to be going into printCommandSuggestions
instead of printFlagSuggestions
when we are in the DefaultCompleteWithFlags
@ldelossa Yes you're right. The code doesnt make sense. Something isnt right. v2 has the correct behaviour, we seem to have broken it in v3. I will put in a fix. Thanks for raising this issue
No problem, looking forward to seeing it fixed :-D. Thanks for working with me on explaining this situation.
@dearchap
If i comment out:
if cmd != nil && cmd.flagSet != nil && cmd.parent != nil {
args = cmd.Args().Slice()
tracef("running default complete with flags[%v] on command %[1]q", args, cmd.Name)
} else {
tracef("running default complete with os.Args flags")
}
Things begin to work. Maybe this is a bad heuristic, since having defined flags does not necessary mean cmd.Args().Slice()
returns anything. IIUC cmd.Args()
returns explicitly defined arguments on the command structure.
@dearchap
Unfortunately, your fix does not fix the issue.
Like I mentioned above, the replacement of 'args' here:
if cmd != nil && cmd.flagSet != nil && cmd.parent != nil {
args = cmd.Args().Slice()
tracef("running default complete with flags[%v] on command %[2]q", args, cmd.Name)
} else {
tracef("running default complete with os.Args flags[%v]", args)
}
Is breaking things.
As soon as I do this:
func DefaultCompleteWithFlags(ctx context.Context, cmd *Command) {
args := os.Args
if cmd != nil && cmd.flagSet != nil && cmd.parent != nil {
// args = cmd.Args().Slice()
tracef("running default complete with flags[%v] on command %[2]q", args, cmd.Name)
} else {
tracef("running default complete with os.Args flags[%v]", args)
}
argsLen := len(args)
lastArg := ""
// parent command will have --generate-shell-completion so we need
// to account for that
if argsLen > 1 {
lastArg = args[argsLen-2]
} else if argsLen > 0 {
lastArg = args[argsLen-1]
}
if strings.HasPrefix(lastArg, "-") {
tracef("printing flag suggestion for flag[%v] on command %[1]q", lastArg, cmd.Name)
printFlagSuggestions(lastArg, cmd.Flags, cmd.Root().Writer)
return
}
if cmd != nil {
tracef("printing command suggestions on command %[1]q", cmd.Name)
printCommandSuggestions(cmd.Commands, cmd.Root().Writer)
return
}
}
Everything works.
https://github.com/urfave/cli/assets/5642902/e9e364ae-0ae7-48ea-ba15-fa1a50d2f60d
@ldelossa did you use the latest fix I just merged ?
Yes, dont you see the code present in the video I just sent? That is latest.
@ldelossa sorry yes I was reading the comments in my email and didnt watch the video. Let me dig into this a bit more.
@ldelossa The problem is much more complex than I first thought. Can you try with latest code(without your changes) and try just "-" and TAB instead of "--" and TAB ?
@dearchap yup, I tried both, both do not complete.
@ldelossa if you comment out the args it might work with flags but will fail with subcommands.
main command <TAB>
Not for me. Everything works when i comment that out. This, i don't know about positional argument competition. I don't use that only flags
@ldelossa can you try fix from latest PR ? Kind of kludgy but works
hey @dearchap running out of cycles to keep testing this unfortunately, I provided the test example which should determine if your fixes work or not. I would just ensure to check for all tab completion "-", "--", arguments and subcommands.
Discussed in https://github.com/urfave/cli/discussions/1915