From 2dbc88d3afdacf6449f299c70f29e5456904779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 11:31:14 +0300 Subject: [PATCH] Improve bash completion escaping `compopt -o filenames` is a cheap way to accomplish mostly wanted behavior. However it is semantically incorrect when we are not actually completing filenames, and has side effects -- for example adds a trailing slash to candidates matching present dirs. bash >= 4.1 can `printf -v` to an array index, use it instead where available. --- assets/completions/bat.bash.in | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index 7969442d..40481b48 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -10,6 +10,27 @@ __bat_init_completion() _get_comp_words_by_ref "$@" cur prev words cword } +__bat_escape_completions() +{ + # Do not escape if completing a quoted value. + [[ $cur == [\"\']* ]] && return 0 + # printf -v to an array index is available in bash >= 4.1. + # Use it if available, as -o filenames is semantically incorrect if + # we are not actually completing filenames, and it has side effects + # (e.g. adds trailing slash to candidates matching present dirs). + if (( + BASH_VERSINFO[0] > 4 || \ + BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] > 0 + )); then + local i + for i in ${!COMPREPLY[*]}; do + printf -v "COMPREPLY[i]" %q "${COMPREPLY[i]}" + done + else + compopt -o filenames + fi +} + _bat() { local cur prev words cword split=false if declare -F _init_completion >/dev/null 2>&1; then @@ -45,7 +66,7 @@ _bat() { printf "%s\n" "$lang" done )" -- "$cur")) - compopt -o filenames # for escaping + __bat_escape_completions return 0 ;; -H | --highlight-line | \ @@ -92,7 +113,7 @@ _bat() { --theme) local IFS=$'\n' COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur")) - compopt -o filenames # for escaping + __bat_escape_completions return 0 ;; --style)