Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Bash tab completion doesn't handle backslashes correctly #100

Open
JeffFaer opened this issue Apr 18, 2024 · 3 comments
Open

Bash tab completion doesn't handle backslashes correctly #100

JeffFaer opened this issue Apr 18, 2024 · 3 comments

Comments

@JeffFaer
Copy link

JeffFaer commented Apr 18, 2024

I have some bash completions which end up including special characters, but it looks like the tab completion here doesn't quite handle them correctly.

I was able to reproduce the issue I've been running into:

generate_suggestions() {
  local suggestions=(
    abcd
    efgh
    ijkl
    '\\@today'
  )
  local i
  for ((i=0; i < ${#suggestions[@]}; i++)); do
    # compgen -W respects shell quoting, so we need to escape special
    # characters.
    suggestions[i]="$(printf "%q" "${suggestions[i]}")"
  done

  local cur="${COMP_WORDS[COMP_CWORD]}"
  # compgen -W respects shell quoting _after_ checking to make sure elements of
  # the wordlist start with ${cur}, so we need to escape it, too.
  cur="$(printf "%q" "${cur}")"

  mapfile -t COMPREPLY < <(compgen -W "${suggestions[*]}" -- "${cur}")
}

complete -F generate_suggestions complete.bash

The goal of this is to put the string \\@today on the command line so that it passes \@today to the program when executed.


With regular bash completion:

  • complete.bash <TAB> generates abcd efgh ijkl \\@today
  • complete.bash \<TAB> autofills \\@today
  • complete.bash \\<TAB> autofills \\@today

With fzf_bash_completion:

  • complete.bash <TAB> generates abcd efgh ijkl \\@today, if I select \\@today it's entered onto the command line correctly
  • complete.bash \<TAB> autofills \\@today
  • complete.bash \\<TAB> autofills \@today, losing a backslash

If you add another entry with a similar prefix, say \\@tomorrow and set FZF_COMPLETION_AUTO_COMMON_PREFIX and FZF_COMPLETION_AUTO_COMMON_PREFIX_PART:

  • complete.bash \<TAB> autofills \\@to
  • complete.bash \\@to<TAB> generates \@today \@tomorrow, losing a backslash
  • complete.bash \\<TAB> autofills \@to, losing a backslash
@lincheney
Copy link
Owner

I can't reproduce this, but I think it is possible this is fixed as a result of #91 (comment)

@JeffFaer
Copy link
Author

JeffFaer commented May 1, 2024

I can't reproduce my example anymore either, so it looks something about this problem has changed, but now I've found a new issue:

Tab completion seems to be processing escape sequences and splitting words as a result

#!/usr/bin/env bash

generate_suggestions() {
  local suggestions=(
    'foo\>bar1'
    'foo\>bar2'
  )
  local i
  for ((i=0; i < ${#suggestions[@]}; i++)); do
    # compgen -W respects shell quoting, so we need to escape special
    # characters.
    suggestions[i]="$(printf "%q" "${suggestions[i]}")"
  done

  local cur="${COMP_WORDS[COMP_CWORD]}"
  # compgen -W respects shell quoting _after_ checking to make sure elements of
  # the wordlist start with ${cur}, so we need to escape it, too.
  cur="$(printf "%q" "${cur}")"

  mapfile -t COMPREPLY < <(compgen -W "${suggestions[*]}" -- "${cur}")

  local log="completion.log"
  {
    echo "COMP_WORDS"
    local i
    for ((i=0; i < "${#COMP_WORDS[@]}"; i++)); do
      local cur=" "
      if ((i == COMP_CWORD)); then
        cur="*"
      fi
      echo "${cur}${i}: ${COMP_WORDS[i]}"
    done
    echo "COMPREPLY"
    local i
    for i in "${COMPREPLY[@]}"; do
      echo "${i}"
    done
  } >> "${log}"
}

complete -F generate_suggestions complete.bash

With regular bash completion:

  • complete.bash <TAB> autofills foo\>bar and logs
    COMPWORDS
     0: complete.bash
    *1: 
    COMPREPLY
    foo\>bar1
    foo\>bar2
    
  • complete.bash foo\>bar<TAB> displays foo\>bar1 foo\>bar2 and logs
    COMPWORDS
     0: complete.bash
    *1: foo\>bar
    COMPREPLY
    foo\>bar1
    foo\>bar2
    

With fzf_bash_completion

  • complete.bash <TAB> autofills foo\>bar and logs the same as regular bash completion
  • complete.bash foo\>bar<TAB> displays nothing and logs
    COMPWORDS
     0: complete.bash
     1: foo>
    *2: bar
    COMPREPLY
    

@KGoodacre
Copy link

@lincheney
Is there a way to enable tab completion for directories without using “cd”? I have autocd enabled (“shopt -s autocd”) and it fzf will not invoke unless I type either “cd” or “./“ before I tab.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants