8000 completions/jj: use dynamic completions by default, also fix them by ilyagr · Pull Request #11046 · fish-shell/fish-shell · GitHub
[go: up one dir, main page]

Skip to content

completions/jj: use dynamic completions by default, also fix them#11046

Merged
krobelus merged 1 commit intofish-shell:masterfrom
ilyagr:jjdynamic
Mar 17, 2025
Merged

completions/jj: use dynamic completions by default, also fix them#11046
krobelus merged 1 commit intofish-shell:masterfrom
ilyagr:jjdynamic

Conversation

@ilyagr
Copy link
Contributor
@ilyagr ilyagr commented Jan 15, 2025

This uses jj's dynamic completions when possible.

This avoids an annoying problem. Because of 04a4e5c (so, in fish 4.0beta, but not in fish 3.7.1), jj's dynamic completions (added to jj recently, see the second paragraph of https://jj-vcs.github.io/jj/latest/install-and-setup/#command-line-completion) do not work very well in fish if the user puts COMPLETE=fish jj | source in their ~/.config/fish/config.fish. When the user types jj <TAB>, they are instead overridden by fish's built-in non-dynamic completions.

The difference is subtle. One problem I saw is that jj new <TAB> works as expected (and shows revisions) while jj new -A <TAB> becomes broken (and shows files).

If the user puts COMPLETE=fish jj | source in ~/.config/fish/completions/jj.fish there is no problem. However, users might be confused if they run COMPLETE=fish jj | source or put it in their config and it works in a broken fashion. I certainly was, this took a while to debug.

Meanwhile, I checked that if the user has jj completion fish | source in their config.fish, executing COMPLETE=fish jj __this_command_does_not_exist | source afterwards still seems to work correctly. So, this PR should not cause the opposite
problem to the one it tries to solve.

Let me know if there's a better approach to this problem.

TODOs:

  • Changes to fish usage are reflected in user documentation/manpages.
  • Tests have been added for regressions fixed
  • User-visible changes noted in CHANGELOG.rst

@github-actions github-actions bot added the < 8000 a id="label-6e46c2" href="/fish-shell/fish-shell/issues?q=state%3Aopen%20label%3Acompletions" data-name="completions" style="--label-r:230;--label-g:192;--label-b:229;--label-h:301;--label-s:43;--label-l:82;" data-view-component="true" class="IssueLabel hx_IssueLabel d-inline-block v-align-middle"> completions label Jan 15, 2025
@ilyagr ilyagr force-pushed the jjdynamic branch 2 times, most recently from cc4ae67 to 076f9ee Compare January 15, 2025 07:08
@ilyagr ilyagr marked this pull request as ready for review January 15, 2025 07:08
@ilyagr ilyagr changed the title jj completions: use dynamic completions by default, also fixing them jj completions: use dynamic completions by default, also fixing them in the process Jan 15, 2025
@ilyagr ilyagr force-pushed the jjdynamic branch 4 times, most recently from d6c1b53 to f7174db Compare January 15, 2025 07:21
@ilyagr ilyagr changed the title jj completions: use dynamic completions by default, also fixing them in the process jj completions: use dynamic completions by default, also fix them Jan 15, 2025
@ilyagr
Copy link
Contributor Author
ilyagr commented Jan 15, 2025

There are two other options that come to mind. I'll mark this as a draft until I figure out how viable option 2 is. I'd love to resolve this between fish 4 is released (if possible, of course).

The two other options I see are:

  1. Remove jj completions from fish for now
  2. Change jj so that jj util completion fish | source turns on dynamic completions. This may or may not require changes to the CLI parsing library that generates the completions (clap). I think the dynamic completions are good enough that this is otherwise possible, though they might still have bugs I don't know about.

@ilyagr ilyagr marked this pull request as draft January 15, 2025 22:41
@ilyagr
Copy link
Contributor Author
ilyagr commented Jan 16, 2025

After reading clap-rs/clap#5668, it seems like Clap would not recommend using the same command for static and dynamic completions, since they do not want distributions to package the output of COMPLETE=fish jj in the way they package the output of static completions (e.g. jj util completion fish). Also, AFAICT, this would require a change to clap (a small one, technically, but I now doubt it would be accepted).

So, I'm back to thinking that this PR is the best we can do. If it has a good chance to be accepted, I'll try adding a test to jj that COMPLETE=fish jj __this-command-does-not-exist does print dynamic completions in the same way as COMPLETE=fish jj. (Update: The test is added in jj-vcs/jj#5376)

Update: Option 3

Yet another option (call it "Option 3") I don't really like would be to change jj's docs. We could instruct people to enable dynamic completions for fish by running

# In fish 4.0beta and later, follow these instructions exactly or the
# completions will be subtly broken.
mkdir -p $__fish_config_path/completions
echo 'COMPLETE=fish jj | source' > $__fish_config_path/completions/jj.fish

Again, this doesn't seem great to me. It would also only work if __fish_complete_path is ordered correctly, with user completion dir before built-in completion dir (which wasn't the case for me once).

@ilyagr ilyagr marked this pull request as ready for review January 16, 2025 00:16
ilyagr added a commit to jj-vcs/jj that referenced this pull request Jan 16, 2025
ilyagr added a commit to jj-vcs/jj that referenced this pull request Jan 16, 2025
@krobelus krobelus self-assigned this Jan 16, 2025
# https://jj-vcs.github.io/jj/latest/config/#default-command
if set -l completion (COMPLETE=fish jj __this-command-does-not-exist 2>/dev/null)
# jj is new enough for dynamic completions to be implemented
echo "$completion" | source
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure this seems like the right solution -- assuming "dynamic" completions are a superset of "static" completions.

We'll take whatever is a stable way to get all completions. Looks fine as is.

Keeping it seems valuable since otherwise adding completions requires manual steps for the user.
(Either way we need to make sure that COMPLETE=fish jj __this-command-does-not-exist always outputs safe fish for any relevant fish version.)

I did not yet have a chance to test dynamic completions but I saw from

$ COMPLETE=fish jj asdf
complete --keep-order --exclusive --command jj --arguments "(COMPLETE=fish "'jj'" -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))"

That it uses --tokenize; this should be updated to --tokens-expanded (see #10212),
else completions for jj --repository=$HOME/my-repo ... will not work -- unless jj is overstepping its boundaries by expanding shell syntax

(not a blocker; it's probably not a regression)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is coming from clap_complete. I doubt it can adopt the new option, since it probably wants to stay compatible with older versions of fish. Once clap_complete does decide to adopt this, jj will automatically get it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it can, with feature testing as suggested in that link:

set -l tokens
if commandline -x >/dev/null 2>&1
    set tokens (commandline -xpc)
else
    set tokens (commandline -opc)
end

I'll send a patch to clap eventually (unless someone else does it first)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assuming "dynamic" completions are a superset of "static" completions.

Yes, they are.

# is not implemented, we'd like to get an error reliably. However, the
# behavior of `jj` without arguments depends on the value of a config, see
# https://jj-vcs.github.io/jj/latest/config/#default-command
if set -l completion (COMPLETE=fish jj __this-command-does-not-exist 2>/dev/null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jj instructions should probably state that it's only necessary for fish below version 4.
Else some users would load duplicate completion definitions (at least Git completions can be slow).
Could make it say something like if [ -z "$(complete -C'jj ')" ]; COMPLETE=fish jj | source; end
which does nothing if completions are already installed

@senekor
Copy link
senekor commented Jan 16, 2025

Change jj so that jj util completion fish | source turns on dynamic completions. This may or may not require changes to the CLI parsing library

Why do you think clap would need to be changed? We could just have jj util completion fish literally output the string COMPLETE=fish jj | source, right?

That would also solve the problem that packagers shouldn't include the output of COMPLETE=fish jj statically.

@senekor
Copy link
senekor commented Jan 16, 2025

After a quick look at clap-rs/clap#5668, I think the main issue there is that other shells don't do lazy loading of completions. This is not a problem for fish. We can just drop the literal string COMPLETE=fish jj | source in completions/jj.fish. IIRC, it will be executed once per shell, at the moment jj is run for the first time in that shell.

@krobelus
Copy link
Contributor

Why do you think clap would need to be changed? We could just have jj util completion fish literally output the string COMPLETE=fish jj | source, right?

yeah a stable invocation would be preferrable, Seems there is no reason to change the interface

IIRC, it will be executed once per shell

yeah, lazy loaded as soon as completions for jj are requested

This uses jj's dynamic completions when possible.

This avoids an annoying problem. After 04a4e5c, jj's dynamic
completions (see the second paragraph of
<https://jj-vcs.github.io/jj/latest/install-and-setup/#command-line-completion>)
do not work very well in fish if the user puts `COMPLETE=fish jj |
source` in their `~/.config/fish/config.fish`. When the user types `jj
<TAB>`, they are instead overridden by fish's built-in non-dynamic
completions.

The difference is subtle. One problem I saw is that `jj new <TAB>` works
as expected (and shows revisions) while `jj new -A <TAB>` becomes broken
(and shows files).

If the user puts `COMPLETE=fish jj | source` in
`~/.config/fish/completions/jj.fish` there is no problem. However, users
might be confused if they run `COMPLETE=fish jj | source` or put it in
their config and it works in a broken fashion. I certainly was.

Meanwhile, I checked that if the user has `jj completion fish | source`
in their `config.fish`, executing `COMPLETE=fish jj
__this_command_does_not_exist | source` afterwards still works
correctly.

Let me know if there's a better approach to this problem.
@ilyagr
Copy link
Contributor Author
ilyagr commented Jan 17, 2025

I fixed up krobelus's comments, thanks for catching my bugs!

I think the main issue there is that other shells don't do lazy loading of completions.

I agree. For fish, it seems like having jj util completion fish output COMPLETE=fish jj | source, and keeping jj util completion fish | source in completions/jj.fish would work fine. But for bash, the analogue might be slow.

I'm not sure whether it makes sense for jj util completion fish to switch to doing dynamic completions if we need another setup for bash's dynamic completions. Or maybe it does.

Aside: As discussed on Discord, nixpkgs already does the analogous (slow) thing for bash and zsh: nixpkgs. I think brew caches the output of COMPLETE=shell jj (1, 2 ), which is faster but not recommended by clap.

Another aside: perhaps we could implement feature detection in jj so that you could check jj feature check dynamic-completions-v1 instead of the hack in this PR.

# https://jj-vcs.github.io/jj/latest/config/#default-command
if set -l completion (COMPLETE=fish jj __this-command-does-not-exist 2>/dev/null)
# jj is new enough for dynamic completions to be implemented
printf %s\n $completion | source
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue is that computing completions purely inside jj means that
it won't work if there are shell metacharacters. Examples:

  • jj --repository ~/
  • jj --repository $HOME/

These don't get any completions. Note that commandline --tokens-expanded won't
work because (without a heuristic) fish doesn't know how to apply /home/user/foo non-destructively.

The currently recommended approach is to delegate back to fish's file completions if
jj finds that we are completing a file path.
Normally file completions are disabled via complete --exclusive but we can do something like

function __fish_jj_complete
    set -g __fish_jj_completions (COMPLETE=fish jj -- (commandline --current-process --tokenize-expanded --cut-at-cursor) (commandline --current-token))
    test $status -ne 5 # status 5 means "fall back to file completions"
end
complete jj  --keep-order --exclusive --command jj \
    --condition __fish_jj_complete --arguments '(string join \n $__fish_jj_completions)'

I guess in this specific case we wouldn't even fallback but instead compute directory completions, using the existing:

complete -c jj -n "__fish_jj_needs_command" -s R -l repository -d 'Path to repository to operate on' -r -f -a "(__fish_complete_directories)"

This is why hand-written completions are often better - but of course we can fix them (probably needs another change in Clap).

I guess this is not blocking, because using variables in file paths is somewhat rare for jj (given that
most file paths for jj diff and others get completed just fine). But we should fix that.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that commandline --tokens-expanded won't
work because (without a heuristic) fish doesn't know how to apply /home/user/foo non-destructively.

I don't understand this, but my fish version doesn't support that option yet, so I can't experiment with it. What does --tokens-expanded do exactly? Why doesn't it expand jj --repository ~/ to /home/user/ before passing it to clap for dynamic completions?

Copy link
Contributor Author
@ilyagr ilyagr Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. I think this is far from being specific to jj. I don't immediately see a better solution than the commits you linked to this PR (and I don't fully understand them at the moment either).

I think it will only become more of a problem as more CLI libraries support dynamic completion (I think there's already clap, https://github.com/spf13/cobra , and some Python libraries whose name I forgot1). I hope they will; naively it seems like an ultimately better approach than shipping static completions in shell-and-package-manager dependent ways.

To me, this suggests the need for some more detailed communication protocol between the shell and clap or the like. It's hard for me to decide whether --token-expanded is a sufficient protocol for this. I'm glad it exists. I haven't followed the details, but I'm guessing that it's an 80% solution, and something better will eventually be needed for the other 20% (which will take 500% as much work).

Footnotes

  1. I was thinking of https://github.com/kislyuk/argcomplete (which actually supports Fish despite first claiming not to) which works with argparse from the standard library. I think most people use argparse by default? Not sure if something works with the newer Python CLI libraries, or what the fashion of the day is.

Copy link
Contributor
@krobelus krobelus Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I'm guessing that it's an 80% solution

yes absolutely. --tokens-expanded was added as an incremental improvement to fix one bad aspect of --tokens

and something better will eventually be needed for the other 20% (which will take 500% as much work).

--tokens-expanded works fine for getting the list of tokens before the token at cursor.
This list can be fed into a completion generator that has no idea of shell syntax.
Some remaining problems are:

  1. it breaks on multiline tokens (and tokens that expand to multiple lines) -- should probably add a --zero option
  2. when expansion would produce too many values, we pass on the unexpanded string. This is hacky but unlikely to cause problems in practice
  3. The most difficult one: --tokens-expanded only works for tokens to the left, not for the token at cursor.
    To fix this we indeed need some kind of communication protocol for passing arbitrary metadata.
    Consider myapp {foo, where
    the shell would need to tell the completion generator that it should generate something based off myapp foo
    Also given myapp $HOME/, the shell would ask for completions based on the expanded $HOME, but would want to un-expand the variable before applying the completion.

I think it's unrealistic that every completion client implements their own fish tokenizer.
All those completions like ls {foo, already work in fish, so we could get there by plugging this into external completions.

IME apps providing completion generation are reluctant to use wildly different code for fish than for bash/zsh,
so I'd love to find an interface that can be easily implemented in any shell.
That will also be a soft prerequisite for this thing to be adopted (fish is small enough to have self-interest in not being evil ;).

# is not implemented, we'd like to get an error reliably. However, the
# behavior of `jj` without arguments depends on the value of a config, see
# https://jj-vcs.github.io/jj/latest/config/#default-command
if set -l completion (COMPLETE=fish jj __this-command-does-not-exist 2>/dev/null)
Copy link
Contributor
@krobelus krobelus Jan 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using jj 0.23.0-0ca6f00421f6f893e974e0f5349e126abd41a812

Pressing tab on

$ jj --

prints a spurious

Hint: Use jj -h for a list of available commands.

Similar on jj --repository /.

EDIT: Also on jj abandon @ --ignore-im

EDIT2: Missing completions on jj abandon qxnzqwuk:: --ignore-

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT the only remaining regression is clap-rs/clap#5949

I'm planning to merge this PR after that clap fix is in jj. Though it may be worth merging before that, not sure

krobelus added a commit to krobelus/clap that referenced this pull request Jan 19, 2025
In fish, the command line

	cargo b --manifest-path $PWD/clap_complete/Cargo.toml --example

wrongly gets example-name completion $PWD/Cargo.toml instead of
$PWD/clap_complete/Cargo.toml.

This is because fish's "commandline --tokenize" option produces tokens
like "$PWD/clap_complete/Cargo.toml", which clap cannot see through.

Starting in the upcoming fish version 4, there is a new option,
"--tokens-expanded"[^1] to output the expanded arguments, matching
what the program would see during execution.

If an expansion of a token like {1,2,3}{1,2,3} would produce too
many results, the unexpanded token is forwarded, thus falling back to
existing behavior. Similarly, command substitutions ("$()") present
on the command line are forwarded as-is, because they are not deemed
safe to expand given that the user hasn't agreed to running them.

Use this option if available, to fix the above example.

While at it, break up this overlong line.  Add redundant semicolons,
in case a preexisting completion accidentally joins these lines with
spaces[^2], like

	if set -l completions (COMPLETE=fish myapp 2>/dev/null)
		echo "$completions" | source
	end

I have not updated clap_complete/tests/snapshots/register_dynamic.fish
(not sure how?) or tested this but I'm happy to do so.

[^1]: fish-shell/fish-shell#10212
[^2]: fish-shell/fish-shell#11046 (comment)
krobelus added a commit to krobelus/clap that referenced this pull request Jan 19, 2025
In fish, the command line

	cargo b --manifest-path $PWD/clap_complete/Cargo.toml --example

wrongly gets example-name completions from $PWD/Cargo.toml instead of
$PWD/clap_complete/Cargo.toml.

This is because fish's "commandline --tokenize" option produces tokens
like "$PWD/clap_complete/Cargo.toml", which clap cannot see through.

Starting in the upcoming fish version 4, there is a new option,
"--tokens-expanded"[^1] to output the expanded arguments, matching
what the program would see during execution.

If an expansion of a token like {1,2,3}{1,2,3} would produce too
many results, the unexpanded token is forwarded, thus falling back to
existing behavior. Similarly, command substitutions ("$()") present
on the command line are forwarded as-is, because they are not deemed
safe to expand given that the user hasn't agreed to running them.

Use this option if available, to fix the above example.

I have not checked if any existing clap user tries to expand variables
on their own. If this is a real possibility, we could let users
opt into the new behavior.

While at it, break up this overlong line.  Add redundant semicolons,
in case a preexisting completion accidentally joins these lines with
spaces[^2], like

	if set -l completions (COMPLETE=fish myapp 2>/dev/null)
		echo "$completions" | source
	end

I have not updated clap_complete/tests/snapshots/register_dynamic.fish
(not sure how?) or tested this but I'm happy to do so.

[^1]: fish-shell/fish-shell#10212
[^2]: fish-shell/fish-shell#11046 (comment)
@ilyagr ilyagr changed the title jj completions: use dynamic completions by default, also fix them completions/jj: use dynamic completions by default, also fix them Jan 20, 2025
krobelus added a commit to krobelus/clap that referenced this pull request Mar 15, 2025
TODO: should double-check the root cause and add automated tests

jj dynamic completions of option names work as expected ...

	$ COMPLETE=fish jj -- jj abandon --ignore-
	--ignore-working-copy
	--ignore-immutable

... unless there is a positional argument

	$ COMPLETE=fish jj -- jj abandon @ --ignore-

The positional arguments are defined in the "abandon" subcommand as:

```rust
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct AbandonArgs {
    /// The revision(s) to abandon (default: @)
    #[arg(
        value_name = "REVSETS",
        add = ArgValueCandidates::new(complete::mutable_revisions)
    )]
    revisions_pos: Vec<RevisionArg>,
}
```

After clap_complete sees the first positional argument ("@") we are stuck
in "ParseState::Pos(..)" even when we get to parsing "--ignore-".  This is
because "revisions_pos" accepts an arbitrary number of positionals.

While in "ParseState::Pos(..)", we only produce completions for positionals
(via "complete_arg_value()").  This means we fail to produce option-name
completions like "--ignore-immutable".

This was introduced in f0bd475 (feat(clap_complete): Support
multi-values of positional argument with `num_arg(N)`, 2024-07-26).
Presumably, the main intention of that commit was to allow options
with multiple, but finitely many arguments.

For the case where arbitrarily many arguments are allowed, let's get rid of
this restriction, to fix the false negative.

Ref: fish-shell/fish-shell#11046 (comment)
krobelus added a commit to krobelus/clap that referenced this pull request Mar 16, 2025
jj dynamic completions of option names work as expected:

	$ COMPLETE=fish jj -- jj abandon --ignore-
	--ignore-working-copy
	--ignore-immutable

Unless there is a positional argument preceding the option

	$ COMPLETE=fish jj -- jj abandon @ --ignore-

The positional arguments are defined in the "abandon" subcommand as:

```rust
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct AbandonArgs {
    /// The revision(s) to abandon (default: @)
    #[arg(value_name = "REVSETS")]
    revisions_pos: Vec<RevisionArg>,
}
```

After clap_complete sees the first positional argument ("@") we'll be stuck
in "ParseState::Pos(..)" forever; in particular "--ignore-" will be treated
as positional argument by the clap_complete parser.

This is inconsistent with execution where "--ignore-" will correctly be
treated as option.

I have not yet checked if other scenarios than a derived `Vec<>` are affected.

For now fix the parsing of that one only.

Ref: fish-shell/fish-shell#11046 (comment)
krobelus added a commit to krobelus/clap that referenced this pull request Mar 17, 2025
jj dynamic completions of option names work as expected:

	$ COMPLETE=fish jj -- jj abandon --ignore-
	--ignore-working-copy
	--ignore-immutable

Unless there is a positional argument preceding the option

	$ COMPLETE=fish jj -- jj abandon @ --ignore-

The positional arguments are defined in the "abandon" subcommand as:

```rust
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct AbandonArgs {
    /// The revision(s) to abandon (default: @)
    #[arg(value_name = "REVSETS")]
    revisions_pos: Vec<RevisionArg>,
}
```

After clap_complete sees the first positional argument ("@") it will be
stuck in "ParseState::Pos(..)" forever; in particular "--ignore-" will be
treated as positional argument by the clap_complete parser.

This is inconsistent with execution where "--ignore-" will correctly be
treated as option, because the "Append" arg action implies that the arguments
need not be contiguous.  Fix this inconsistency.

Ref: fish-shell/fish-shell#11046 (comment)
@krobelus krobelus added this to the fish 4.1 milestone Mar 17, 2025
krobelus added a commit to krobelus/jj that referenced this pull request Mar 17, 2025
To avoid redundant computation, users who run `COMPLETE=fish jj | source`
in their ~/.config/fish/config.fish should eventually remove that, or move it
to ~/.config/fish/completions/jj.fish which overrides the default completions.

Ref: fish-shell/fish-shell#11046
@krobelus krobelus merged commit 932010c into fish-shell:master Mar 17, 2025
7 checks passed
github-merge-queue bot pushed a commit to jj-vcs/jj that referenced this pull request Mar 17, 2025
To avoid redundant computation, users who run `COMPLETE=fish jj | source`
in their ~/.config/fish/config.fish should eventually remove that, or move it
to ~/.config/fish/completions/jj.fish which overrides the default completions.

Ref: fish-shell/fish-shell#11046
krobelus added a commit to krobelus/clap that referenced this pull request Mar 17, 2025
jj dynamic completions of option names work as expected:

	$ COMPLETE=fish jj -- jj abandon --ignore-
	--ignore-working-copy
	--ignore-immutable

Unless there is a positional argument preceding the option

	$ COMPLETE=fish jj -- jj abandon @ --ignore-

The positional arguments are defined in the "abandon" subcommand as:

```rust
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct AbandonArgs {
    /// The revision(s) to abandon (default: @)
    #[arg(value_name = "REVSETS")]
    revisions_pos: Vec<RevisionArg>,
}
```

After clap_complete sees the first positional argument ("@") it will be
stuck in "ParseState::Pos(..)" forever; in particular "--ignore-" will be
treated as positional argument by the clap_complete parser.

This is inconsistent with execution where "--ignore-" will correctly be
treated as option, because the "Append" arg action implies that the arguments
need not be contiguous.  Fix this inconsistency.

Ref: fish-shell/fish-shell#11046 (comment)
ilyagr added a commit to jj-vcs/jj that referenced this pull request Mar 18, 2025
ilyagr added a commit to jj-vcs/jj that referenced this pull request Mar 18, 2025
See also the discussion in
fish-shell/fish-shell#11046 and discussions
linked from there.
@faho faho modified the milestones: fish 4.1, fish 4.0.2 Apr 2, 2025
heygarrett added a commit to heygarrett/.config that referenced this pull request May 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

0