lincheney / fzf-tab-completion

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

Bash tab completion doesn't handle backslashes correctly #100

Open JeffFaer opened 4 months ago

JeffFaer commented 4 months ago

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:

With fzf_bash_completion:


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:

lincheney commented 4 months ago

I can't reproduce this, but I think it is possible this is fixed as a result of https://github.com/lincheney/fzf-tab-completion/issues/91#issuecomment-2074019581

JeffFaer commented 4 months ago

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:

With fzf_bash_completion

KGoodacre commented 3 months ago

@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.