cli
cli copied to clipboard
Before callback affects bash completions
my urfave/cli version is
v1.22.2, v1.22.3
Checklist
- [x] Are you running the latest v1 release? The list of releases is here.
- [x] Did you check the manual for your release? The v1 manual is here
- [x] Did you perform a search about this problem? Here's the Github guide about searching.
Dependency Management
- My project is using go modules.
Describe the bug
I wanted to introduce pre-check (with .Before
callback) that would be run if the command is being executed. But it seems like the pre-check is also executed when I want to only show the completions for a given command what breaks the completions output if the .Before
has printed anything (in particular the error).
To reproduce
package main
import (
"errors"
"fmt"
"log"
"os"
"github.com/urfave/cli"
)
func main() {
app := cli.NewApp()
app.Name = "example"
app.EnableBashCompletion = true
app.Before = func(_ *cli.Context) error { return errors.New("uups") }
app.Commands = []cli.Command{{
Name: "cmd",
Action: func(c *cli.Context) error { return nil },
Flags: []cli.Flag{cli.StringFlag{Name: "abc"}},
BashComplete: func(c *cli.Context) {
fmt.Println("--abc")
},
}}
app.Action = func(c *cli.Context) error {
fmt.Println("Hello friend!")
return nil
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
- Build the code above.
- Enable completions
-
example cmd [TAB]
Observed behavior
$ example cmd ......2020/03/25 11:53:14 uups
$ example cmd
GLOBAL OPTIONS COMMANDS USAGE NAME --
example - A new cli application uups
--help, -h show help example [global options] command [command options] [arguments...]
cmd help, h Shows a list of commands or help for one command
Expected behavior
Show completions for the given cmd:
$ example cmd [TAB]
--abc
Additional context
Looking at the code I've noticed that the commands are parsed/visited hierarchically and this also applies for the completions. But I'm not sure if the order should be as it is now. To me completions should be executed first even if the command is nested.
Run go version
and paste its output here
go version go1.14 darwin/amd64
I wanted to introduce pre-check (with
.Before
callback) that would be run if the command is being executed. But it seems like the pre-check is also executed when I want to only show the completions for a given command what breaks the completions output if the.Before
has printed anything (in particular the error).
Is the idea that .Before
shouldn't be run when you're doing tab completion?
Is the idea that .Before shouldn't be run when you're doing tab completion?
Hm, I think it all comes down to this. Yes.
And I think the .After
as well.
Interesting! Do you think the most of the people using that package have that same idea? I ask because if they don't, then this would be a breaking change for them.
I would say yes. As provided in the example, the default behaviour of returning an error in .Before
breaks the .BashComplete
output. So then what is the point of returning an error in .Before
if it breaks some other functionality.
Another problem would be printing anything in the .Before
- it cannot be done without buffering the output and then printing it once the .Action
(not .BashComplete
) is executed.
I'm probably missing someone as I have mostly my own use-cases in mind but it seems like using .Before
and .After
together with .BashComplete
is not possible without super crazy hacks. .Before
and .After
seem to be strictly connected to the .Action
not the .BashComplete
which lives its own life.
To mitigate the breaking change (if anyone would be affected) new callbacks could be created: .(Before|After)BashComplete
. But personally I don't see any use case for them.
I could write a fix for that but I would need to know the decision: if we want to do it and if the approach of "skipping .Before
and .After
if bash completing" is okay.
if we want to do it and if the approach of "skipping
.Before
and.After
if bash completing" is okay
I would need to think about this a lot more before I can make this decision!
Also cc @urfave/cli, in case anyone else has a more solid point of view here 🙏
To support my arguments here is my use-case:
I use CLI to communicate with some server via API. To make sure that user correctly connected to the server I do pre-check which sends ping message to server. If that succeeds I set up the CLI and run the command, if not I print the error message. That works well but the problem is that if someone wants to do cli [TAB]
and the configuration is not correct, then the pre-check will fail. And instead of autocompletion the user will get an error message as autocomplete and that's not user-friendly (as shown in the example). Then I thought that I can use .Before
on the root command to do pre-check so only when actual command is requested (not autocomplete) I will display the error message. But to my surprise it wasn't working as suspected and thus the issue.
Also I was kind of surprised that .Before
prints error together with the usage template if the error is returned (I would suspect some control over it) but I think I can live with that.
Also I was kind of surprised that .Before prints error together with the usage template if the error is returned
Good call there. As of https://github.com/urfave/cli/pull/1117 that is no longer the case.
We don't put any documentation around what the intended purpose of Before
and After
are, so it's hard to say what people expect to happen there. In terms of completion, my guess is most people either ignore it, or enable it and don't think about it unless it breaks. I will say, it's unlikely that any printing to stdout or stderr during completion is correct, including printing errors.
I'd have two questions:
- Would the behavior of a
BeforeFunc
ever influence what's available in a completion? - Is it reasonable for users to program a separate code path in a
BeforeFunc
to behave differently during completion?
My guess to both of those are "no" and "no", and we'd be in a better spot if we didn't run Before
if we were completing.
I will also note that I have not used a BeforeFunc
in my apps, and I have heavily customized my completion behavior for various reasons, so I'm likely not generally representative of the average user here.
Good call there. As of #1117 that is no longer the case.
Sounds awesome :)
My guess to both of those are "no" and "no", and we'd be in a better spot if we didn't run Before if we were completing.
That's my view as well. Before/After
are kind of separate from completions and in my opinion shouldn't be mixed as it only leads to problems or nasty hacks. If we really would like to have something like that for completions as well, I would just suggest creating new callbacks: Before/AfterCompletions
.
Any decision on this one?
@lynncyrin if you had any thoughts here
Agree with @VirrageS. Following the thread.
This issue or PR has been automatically marked as stale because it has not had recent activity. Please add a comment bumping this if you're still interested in it's resolution! Thanks for your help, please let us know if you need anything else.
Any updates on this ?
This issue or PR has been bumped and is no longer marked as stale! Feel free to bump it again in the future, if it's still relevant.
This issue or PR has been automatically marked as stale because it has not had recent activity. Please add a comment bumping this if you're still interested in it's resolution! Thanks for your help, please let us know if you need anything else.
Closing this as it has become stale.
Hello, probably related to this, if you have a flag that is required autocompletion for flags seems to break as well.
@dbarrosop Thank you for reporting this! Are you seeing this behavior with the latest 1.22.x
release? I have no reason to believe that the bug has been fixed, but I'd like to make sure your report is in the right bucket.
@meatballhat it still reproduces on latest release.
@VirrageS I dont think this is an easy fix. All the Before functions are called before the CompletionFunc all the way down the chain . So none of the Before functions should be executed during command completion.
Yup, that's sounds correct.
Looks like the fix was simple after all. See PR #1457 . Can you test @VirrageS ?
@dearchap from what I see the PR targets v2. But the issue is raised for v1, which I currently use.
@VirrageS See PR #1459
@meatballhat, @dearchap any planned release for v1 with a fix? Thanks anyway.
@talarian1 Its already merged to v1. Just waiting on @meatballhat to create a release tag. Thanks
@dearchap hey sorry, on it now!
Done? https://github.com/urfave/cli/releases/tag/v1.22.10