New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate builtin test's one- and zero-argument modes #10365
Conversation
(I'm pretty sure this will conflict with #10357, that's fine, this is easy to redo) |
For posterity: this breaks with posix? |
Yes. Posix explicitly demands the zero- and one-argument behavior as we implement it currently. This is a regular source of confusion and so I believe the break is warranted. |
After mulling it over, I'm more open to this change. The "error out" behavior is easier to stomach vs the more "silent breakage" changes, but we've seen so many of these issues that I think it's overall warranted. Funnily enough, the part I hate the most about this is "oh no, not another feature flag!" |
program_name | ||
)); | ||
builtin_print_error_trailer(parser, streams.err, program_name); | ||
return STATUS_INVALID_ARGS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good change.
One alternative is to keep returning the same exit code as today, but only print the error. This way we wouldn't really need a feature flag. I'm fine with either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a bad idea. That could be our "depreciation phase".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this is used, errors and warnings are often already breaking - if your prompt or worse a binding suddenly prints a warning that makes you want to avoid it, and so you would want to fix it immediately.
This isn't e.g. python, where you can add warnings that, for the most part, will be logged away with a script's output. The context of interactive use makes this different. (and for scripted use, stderr needs to be redirected and read pretty often, it's not separated enough)
That means printing an error strikes me as a bad idea without a feature flag.
Additionally "the same exit code as today" means that test -z
returns true. This would mean that test -z
returns true while printing an error.
Of course erroring out for all single-argument calls instead of allowing test -n
and test -z
is a possibility, but I would want to have it behind a feature flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correction, we'd still want a feature flag
Alright, summarizing, I think we're agreed that a change is good. I think it's not possible to do it without a feature flag. I also think we're agreed that So, the remaining cases are:
My idea is that this proposal allows you to do The counter-argument is that that will still break if $foo contains more than one element and that you should quote it. The counter to that is that |
right so sounds like we don't want to approve of any one-argument invocation -- knowing this, I'd keep the current exit code, to prevent disatrous breakage (but do print an error) |
Well, no. We don't approve of
I still do not believe this is helpful - you would have to silence the error to prevent breakage anyway, and if you are touching the line anyway you can just quote the variable instead. An error message in a prompt or keybinding, or when you redirect stderr (because many things print on stderr! often useful output!) is already breakage. We could add a FLOG message to any one-argument test invocation that you can turn on? So you would do |
I understand that extra output is breakage, sorry if I gave the wrong impression. |
What would break is something like Personally, I feel like having that behind a feature flag is already a lot. We could go further by adding FLOG messages. It would also be quite cool to have some form of static checking for this (unfortunately writing a good It would also be possible to have an in-between step where we warn about the change, but I would not want to have that as the endpoint. I would like to end up without errors where it returns true. So how about this:
Note that FLOG isn't redirectable via stderr - it'll go to fish's |
5f08123
to
3dbffcc
Compare
This removes builtin test's zero and one argument special modes. That means: - `test -n` returns false - `test -z` returns true - `test -x` with any other option errors out with "missing argument" - `test foo` errors out as expecting an option
FLOG category "deprecated-test", run `fish -d deprecated-test` and it will show any test call that would change in future.
Alright, I've added the FLOG message (in category "deprecated-test") and documented it. Since this is a feature flag that would introduce a backwards-incompatible change, I'm going to wait for a sort of "final call" for comments before merging. |
@@ -79,6 +79,8 @@ pub mod categories { | |||
|
|||
(warning_path, "warning-path", "Warnings about unusable paths for config/history (on by default)", true); | |||
|
|||
(deprecated_test, "deprecated-test", "Warning about using test's zero- or one-argument modes (`test -d $foo`), which will be changed in future."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine by me.
Given what I know I'm fine with enabling this warning now already
(and I'd probably not change the exit code but I'm not gonna fight)
In the light of that I'd also rephrase "will change" to "may change"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear: As this PR stands, by default, it will not do anything.
If the warning is enabled, it will show the warning, the exit code will remain.
If the feature flag is enabled, the exit code will change.
The end goal is to have the behavior that I consider best, which is that test -n
and test -z
are fine with no additional arguments, anything else is an error.
The plan is to stage this carefully:
- People can, once this is merged, enable the warning. Once they've fixed their code, they can set the feature flag
- The next step is to enable the warning, but keep the flag off by default, so the exit codes stay
- The step after that is to enable the warning and the flag, but allow disabling them
- The step after that is to make the flag read-only and remove the warning - now we have the behavior we would want from
test
That means we have a step where there's a warning but no change in the exit code (by default), but it's only a step. I do not consider "warn about bad behavior but keep it" to be a good final outcome, I would like to go further and end at "okay behavior".
But I also believe that giving people some time where they know the change is coming without already throwing warnings at them - which is, as we have discussed, itself a breaking change for many uses, even if it is easy to revert. That's why I would like to have that first step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think everything that can be said has been said already. You go ahead.
I don't fully agree but my expertise in this area is quite limited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The plan is to stage this carefully:
People can, once this is merged, enable the warning. Once they've fixed their code, they can set the feature flag
yeah you're right that announcing things in release notes before we change anything is the proper way to do it.
Then plugin authors can react to it. Hard to tell if it matters in this case but it's good practice
This introduces the "test-require-arg" feature flag.
When enabled, it removes builtin test's zero and one argument special modes.
That means:
test -n
returns falsetest -z
returns truetest -x
,test foo
andtest ""
error outCurrently, all of these return true, except for the last which returns false, all silently.
This is a recognition that this is a frequent cause of problems. While we could (and still should) introduce a better replacement for
test
, this will fix a frequently recurring question, and remove awkward explanations we need to give.Nobody needs zero- or one-argument
test
, and few people want it as a shortcut.Fixes #2037.
TODOs:
grep
their code instead?