Skip to content

Complete: Allow passing multiple conditions#8967

Merged
faho merged 3 commits into
fish-shell:masterfrom
faho:multi-condition
May 30, 2022
Merged

Complete: Allow passing multiple conditions#8967
faho merged 3 commits into
fish-shell:masterfrom
faho:multi-condition

Conversation

@faho
Copy link
Copy Markdown
Member

@faho faho commented May 20, 2022

Description

This makes it so complete -c foo -n test1 -n test2 registers both
conditions (instead of using only test2, as is the case at the moment).

When it comes time to check the candidate, both conditions are attempted,
in that order. If any fails it stops, if all succeed the completion is offered.

The reason for this is that it helps with caching - we have a
condition cache, but conditions like

complete -f -c string -n "test (count (commandline -opc)) -lt 2" -a repeat
complete -x -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] repeat" -s n -l count -xa "(seq 1 10)" -d "Repetition count"
complete -x -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] repeat" -s m -l max -xa "(seq 1 10)" -d "Maximum number of printed chars"
complete -f -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] repeat" -s N -l no-newline -d "Remove newline"
complete -f -c string -n "test (count (commandline -opc)) -lt 2" -a pad
complete -x -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] pad" -s r -l right -d "Pad right instead of left"
complete -x -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] pad" -s c -l char -x -d "Character to use for padding"
complete -x -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] pad" -s w -l width -x -d "Integer width of the result, default is maximum width of inputs"

defeat it pretty easily, because the cache only looks at the entire
script as a string - it can't tell that the first test is the same.

So this will run test (count (commandline -opc)) -lt 2 once, because it's cached, and run

test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] repeat
test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] pad

once each - so the test is run at least twice.

So this means we separate it into two conditions, like

complete -x -c string -n "test (count (commandline -opc)) -ge 2" -n "contains -- (commandline -opc)[2] pad" -s r -l right -d "Pad right instead of left"

which allows the test to be cached.

The entire string completions (which are quite simple) have a total of 3 distinct tests - less than two (and offer a subcommand), greater or equal to two (and offer options) and less or equal to two (and offer --help). So if, say there already are three arguments the le and lt tests only need to be done once each, instead of 17 times. If there are less than two, the gt test only needs to run once instead of 31 times.

In tests, this improves performance for the string completions by 60%
by reducing all the redundant test calls.

The git completions can also greatly benefit from this.

A slight downside is, of course, that the completions need to be altered to take advantage of this.

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

@faho faho added enhancement completions performance Purely performance-related enhancement without any changes in black box output labels May 20, 2022
@faho faho added this to the fish 3.5.0 milestone May 20, 2022
@faho
Copy link
Copy Markdown
Member Author

faho commented May 22, 2022

I have converted the git completions now (locally).

This only helps with the condition, so in case where the argument completion actually needs to do work (by calling git) it won't show up a lot.

So e.g. git checkout <TAB> is sped up a negligible amount (~2%), while git stash sa<TAB> is sped up a lot (~30%). This will matter more on systems where the conditions are slower - #8266 points to msys having issues with argparse.

A quick glimpse at a profile shows that it about halves the __fish_git_using_command calls, and this could be increased by, ironically, splitting some - __fish_git_using_command diff show range-diff apply could be four separate calls so they can be cached.

Note: Rewriting this will, of course, be an issue for the people who try to backport completion scripts to older fishes. I don't believe that's a big problem. We can accomodate them to a degree by not doing backwards-incompatible cleanup, but we shouldn't hold back improvements in correctness or performance for that.

@faho
Copy link
Copy Markdown
Member Author

faho commented May 26, 2022

Fixes #8536. Huh, hadn't seen that one

@faho faho force-pushed the multi-condition branch from d17c16c to 455fca5 Compare May 27, 2022 09:45
@faho
Copy link
Copy Markdown
Member Author

faho commented May 29, 2022

@kidonng Headsup, you'll have to deal with this.

Comment thread src/builtins/complete.cpp Outdated
@krobelus
Copy link
Copy Markdown
Contributor

looks great, nice improvement.

I wonder if we should add a "please restart fish" message when and old fish loads new completions that are known to be incompatible. Or perhaps we can embed them into the binary..

faho added 3 commits May 30, 2022 20:22
This makes it so `complete -c foo -n test1 -n test2` registers *both*
conditions, and when it comes time to check the candidate, tries both,
in that order. If any fails it stops, if all succeed the completion is offered.

The reason for this is that it helps with caching - we have a
condition cache, but conditions like

```fish
test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] length

test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] sub
```

defeats it pretty easily, because the cache only looks at the entire
script as a string - it can't tell that the first `test` is the same
in both.

So this means we separate it into

```fish
complete -f -c string -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] length" -s V -l visible -d "Use the visible width, excluding escape sequences"
+complete -f -c string -n "test (count (commandline -opc)) -ge 2" -n "contains -- (commandline -opc)[2] length" -s V -l visible -d "Use the visible width, excluding escape sequences"
```

which allows the `test` to be cached.

In tests, this improves performance for the string completions by 30%
by reducing all the redundant `test` calls.

The `git` completions can also greatly benefit from this.
@faho faho force-pushed the multi-condition branch from 455fca5 to 711364c Compare May 30, 2022 18:22
@faho
Copy link
Copy Markdown
Member Author

faho commented May 30, 2022

I wonder if we should add a "please restart fish" message when and old fish loads new completions that are known to be incompatible

Tbh you should always restart fish after updating(*). We reload changed function files! (which I still believe we should stop doing, but even if we did autoloading means you get the new files if you do something new anyway)

(*) "updating" here refers to actual version upgrades from 3.3 to 3.4, not a few commits at a time like we do

@faho faho merged commit 905db80 into fish-shell:master May 30, 2022
@faho faho deleted the multi-condition branch June 16, 2022 08:08
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

completions enhancement performance Purely performance-related enhancement without any changes in black box output

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants