├── README.md └── fzf-simple-completion.sh /README.md: -------------------------------------------------------------------------------- 1 | # Fzf simple completion 2 | Pipe bash tab-completion suggestions into ``fzf`` fuzzy finder 3 | 4 | 5 | 6 | ## Prerequisites 7 | - [fzf](https://github.com/junegunn/fzf) (command-line fuzzy finder) 8 | - [bash-completion](https://github.com/scop/bash-completion) (most Linux distros ship ``bash-completion`` by default, so there is less chance you will have to install it) 9 | 10 | ## Quick start 11 | Source ``fzf-simple-completion.sh`` at the end of your ``.bashrc``. For example: 12 | ```sh 13 | source ~/path/fzf-simple-completion.sh 14 | ``` 15 | This will replace the default bash completion by fzf selection menu whenever you hit ``TAB``. 16 | ## Features 17 | - Commands and arguments completion 18 | - Directories shortening 19 | - Color support 20 | ## How does it work? 21 | This project is motivated by [Accessing tab-completion programmatically in Bash](https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/). You may find some alternatives on Github as well, but the implementations looks overwhelming to me (I'm not a bash guru so I want to keep things as clean and manageable as possible). 22 | 23 | The idea this project works on is straightforward: 24 | - Pipe all suggestions from ``bash-completion`` directly into ``fzf`` for easy search and selection. 25 | 26 | There is an extra work to make the complettion handle directories with spaces, shortening paths, and coloring. The script itself is written in just a few lines of code, making it easy to modify and customize as needed. 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /fzf-simple-completion.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF SIMPLE COMPLETION - Pipe bash tab-completion suggestions into fzf fuzzy finder 4 | # More details at https://github.com/duong-db/fzf-simple-completion 5 | 6 | bind '"\e[0n": redraw-current-line' 7 | export FZF_DEFAULT_OPTS="--bind=tab:down --bind=btab:up --cycle" 8 | 9 | _fzf_command_completion() { 10 | [[ -z "${COMP_LINE// /}" || $COMP_POINT -ne ${#COMP_LINE} ]] && return 11 | COMPREPLY=$( 12 | # Use compgen for commands completion 13 | compgen -c -- "${COMP_WORDS[COMP_CWORD]}" 2>/dev/null | LC_ALL=C sort -u | 14 | fzf --reverse --height 12 --select-1 --exit-0 15 | ) 16 | printf '\e[5n' 17 | } 18 | 19 | _fzf_get_argument_list() { 20 | local _command command=${COMP_LINE%% *} 21 | source /usr/share/bash-completion/bash_completion 22 | _command=$(complete -p "$command" 2>/dev/null | awk '{print $(NF-1)}') 23 | 24 | if [[ -z $_command ]]; then 25 | # Load completion using _completion_loader from bash_completion script 26 | _completion_loader "$command" 27 | _command=$(complete -p "$command" 2>/dev/null | awk '{print $(NF-1)}') 28 | fi 29 | "$_command" 2>/dev/null 30 | 31 | # Add color 32 | for i in "${!COMPREPLY[@]}"; do 33 | # "~/Documents" is not recognized as a directory due to quotes so we need to expand tilde 34 | if [[ -e "${COMPREPLY[i]/#~/$HOME}" ]]; then 35 | COMPREPLY[i]=$(ls -F -d --color=always "${COMPREPLY[i]/#~/$HOME}" 2>/dev/null) 36 | fi 37 | done 38 | printf '%s\n' "${COMPREPLY[@]}" | LC_ALL=C sort -u | LC_ALL=C sort -t '.' -k2 39 | } 40 | 41 | _fzf_argument_completion() { 42 | [[ $COMP_POINT -ne ${#COMP_LINE} ]] && return 43 | local fzf_opts="--ansi --reverse --height 12 --select-1 --exit-0" 44 | 45 | # Hack on directories completion 46 | # - Only display the last sub directory for fzf searching 47 | # Example. a/b/c/ -> a//b//c/ -> c/ 48 | # - Handle the case where directory contains spaces 49 | # Example. New Folder/ -> New\ Folder/ 50 | # - Revert $HOME back to tilde 51 | COMPREPLY=$( 52 | _fzf_get_argument_list | 53 | sed 's|/|//|g; s|/$||' | fzf $fzf_opts -d '//' --with-nth='-1..' | sed 's|//|/|g' | 54 | sed 's| |\\ |g; s|\\ $| |' | 55 | sed "s|^$HOME|~|" 56 | ) 57 | printf '\e[5n' 58 | } 59 | 60 | # Remove default completions 61 | complete -r 62 | 63 | # Set fuzzy completion 64 | complete -o nospace -I -F _fzf_command_completion 65 | complete -o nospace -D -F _fzf_argument_completion 66 | 67 | # Turn off case sensitivity for better user experience 68 | bind 'set completion-ignore-case on' --------------------------------------------------------------------------------