lincheney / fzf-tab-completion

Tab completion using fzf
GNU General Public License v3.0
623 stars 40 forks source link

FZF_COMPLETION_AUTO_COMMON_PREFIX_PART fails on filenames with spaces in Bash #91

Closed erhhung closed 4 months ago

erhhung commented 7 months ago

First, I'm using the standard setup in my ~/.bashrc:

[ -f $HOME/.fzf.bash_completion ] && \
   . $HOME/.fzf.bash_completion
bind -x '"\t": fzf_bash_completion'

export FZF_COMPLETION_AUTO_COMMON_PREFIX=true
# enable common prefix completion
# following standard Bash behavior
export FZF_COMPLETION_AUTO_COMMON_PREFIX_PART=true

Let's assume we have these files in a directory:

drwxrwxr-x  2 erhhung 4096 2024-02-06 17:00  ./
drwxrwxrwt 14 root    4096 2024-02-06 17:00  ../
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00 'bar baz fred.txt'
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00 'baz qux fred.txt'
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00 'foo bar baz.txt'
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00 'foo baz qux.txt'
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00  qux_bar_baz.txt
-rw-rw-r--  1 erhhung    5 2024-02-06 17:00  qux_baz_foo.txt

Here are some scenarios, with the second illustrating the problem:

  1. $ less bar\<tab> This works fine as there's only one match. $ less bar\ baz\ fred.txt(cursor after trailing space)

  2. $ less foo\<tab> Initial completion to common prefix works fine. $ less foo\ ba(cursor right after a)

    $ less foo\ ba\<tab> I'd would expect to see a popup with two choices, but the current partial
    command just repeats on a new line after the loading message flashes.
    $ less foo\ ba(cursor still right after a)

    Now delete a character, then hit tab, and repeat... $ less foo\ b\<tab> Same as above: existing partial command repeats. $ less foo\ b(cursor still right after b)

    $ less foo\\<tab> (cursor right after escaped space) *Hey, a popup! But I see all filenames instead of `foo`.**

    ╭─────────────────────────────╮
    │ > less foo\ ▆           6/6 │
    │ ▶ bar\ baz\ fred.txt        │
    │   baz\ qux\ fred.txt        │
    │   foo\ bar\ baz.txt         │
    │   foo\ baz\ qux.txt         │
    │   qux_baz_foo.txt           │
    │   qux_bar_baz.txt           │

    If I choose foo\ bar\ baz.txt from the list and hit Enter, the
    entire filename gets appended instead of completed to prefix,
    and the completed prompt line is repeated on a separate line.
    $ less foo\ $ less foo\ foo\ bar\ baz.txt(cursor after trailing space)

  3. $ less qux\<tab> Initial completion to common prefix works fine. $ less qux_ba(cursor right after a)

    $ less qux_ba\<tab> Popup appears with filtered choices, as expected!

    ╭─────────────────────────────╮
    │ > less qux_ba▆          2/2 │
    │ ▶ qux_baz_foo.txt           │
    │   qux_bar_baz.txt           │

    If I choose a file from the list and hit Enter, name completion works fine—on the same line. $ less qux_baz_foo.txt(cursor after trailing space)

  4. $ unset FZF_COMPLETION_AUTO_COMMON_PREFIX_PART

    $ less foo\<tab> Without partial common prefix completion, popup appears.

    ╭─────────────────────────────╮
    │ > less foo▆             2/2 │
    │ ▶ foo\ bar\ baz.txt         │
    │   foo\ baz\ qux.txt         │

    Again, name completion works as expected—on the same line. $ less foo\ bar\ baz.txt(cursor after trailing space)

d-enk commented 7 months ago

When I made this functionality, I added a partial completion solely for some kind of compatibility of native behavior. In practice, I never used it myself, so I never ran into a problem. Just wondering why you need it. Basically, it just forces you to press Tab 2 times. Just got used to it?

erhhung commented 7 months ago

It's often that one has files named with a common base followed by a digit, like:

So when I type less foo\<tab>, I'd like to first see less foo_bar_baz partially completed, and then I can simply type 8 and hit tab again to do the full completion if I knew the exact number I need, instead of having to navigate down a possibly long list.

If I actually wanted to search for a foo* file containing qux from a popup, then I'd just hit tab twice.

d-enk commented 6 months ago

The problem comes here

https://github.com/lincheney/fzf-tab-completion/blob/9bcc7098f79510765b9f539118dd92a2366ec992/bash/fzf-bash-completion.sh#L475

the next call fails compgen -o bashdefault -o default -- "foo\ ba"

intuitive fix compgen "${compgen_opts[@]}" -- "${2//\\/}"

partially correct the situation, but there are arises other problems with escaping I think @lincheney will be able to get into it easier

overtomanu commented 5 months ago

I had faced similar issue and I had reported it for fzf. cd to sub directory of directory with spaces does not work as slash gets removed

overtomanu commented 5 months ago

Reported another issue for this repo as well

https://github.com/lincheney/fzf-tab-completion/issues/96

lincheney commented 4 months ago

I've made a number of changes https://github.com/lincheney/fzf-tab-completion/compare/b8e71337d3a78a67f858f0fcbc4193aff5cb0720...32fd6371a6e266c2c10239690e5d93a583c3c5e4 which I think fixes this issue, but it will need a bit of testing.

erhhung commented 4 months ago

@lincheney Thanks for the fix! I've used it for a little while now and saw no more issues. I have so many files with spaces in their names that it has been driving me nuts...

overtomanu commented 4 months ago

@lincheney Thanks. I just tested it and didn't see the issue.