Search code examples
linuxbashtab-completioncompletionfzf

Bash prompt disappears after selecting a completion from the FZF list


I am trying to program Tab completion in Bash using FZF. The below code tries directory path completion for a custom command mycmd. For the first argument, upon hitting tab, directories found by the find command will be passed to FZF and the directory path that's selected will be assigned to the COMPREPLY array. This works well.

_mycmd_fzf_completions() {
    if (( COMP_CWORD == 1 )); then
        local dir_select && dir_select=$(find -L ${COMP_WORDS[COMP_CWORD]:-.} -maxdepth 1 -mindepth 1 -type d 2> /dev/null | fzf --height 100% --query="${COMP_WORDS[COMP_CWORD]}" )
        case "$?" in
                0) COMPREPLY=( ${dir_select} );;
                *) return 0;;
            esac
        fi
}

# Register the completion function for the custom command `mycmd`
complete -F _mycmd_fzf_completions mycmd

However, now when I change the height of FZF to less than 100%, the TAB completions works but the prompt disappears.

enter image description here

enter image description here

The prompt strangely disappears!

enter image description here

What could be the reason and how to resolve this?


Solution

    • Added bind '"\e[0n": redraw-current-line' and printf '\e[5n' to fix terminal visual corruption and misalignment when FZF closes with height less than 100%, ensuring a stable command line interface.
    • The redraw-current-line function in Readline causes the current command line in the terminal to be redrawn.
    • \e[5n is part of the ANSI Device Status Report (DSR). It requests a report of whether the terminal is busy or not. If the terminal is ready (not busy), it responds with \e[0n.
    • \e[0n is another DSR sequence and it's being bound to redraw-current-line. This means that whenever the terminal outputs the \e[0n escape sequence, Bash will interpret it as a signal to redraw the current command line.

    Refactored code:

    _mycmd_fzf_completions() {
        bind '"\e[0n": redraw-current-line'
        if (( COMP_CWORD == 1 )); then
            local dir_select && dir_select=$(find -L ${COMP_WORDS[COMP_CWORD]:-.} -maxdepth 1 -mindepth 1 -type d 2> /dev/null | fzf --height 100% --query="${COMP_WORDS[COMP_CWORD]}" )
            case "$?" in
                    0) COMPREPLY=( ${dir_select} ); printf '\e[5n';;
                    *) printf '\e[5n'; return 0;;
                esac
            fi
    }
    
    # Register the completion function for the custom command `mycmd`
    complete -F _mycmd_fzf_completions mycmd