# ble/contrib/integration/bash-completion.bash (C) 2024, akinomyoga ## @fn ble/string#hash-pjw text [size shift] ## @var[out] ret function ble/string#hash-pjw { local size=${2:-32} local S=${3:-$(((size+7)/8))} # shift 4 local C=$((size-2*S)) # co-shift 24 local M=$(((1<>C&N)&M)) done ret=$h } #------------------------------------------------------------------------------ # Hooks for completion loaders ## @fn ble/contrib/integration:bash-completion/loader/.adjust-progcomp cmd ## @param[in] cmd ## The command name whose completion setting should be parsed and adjusted. function ble/contrib/integration:bash-completion/loader/.adjust-progcomp { local ret ble/syntax:bash/simple-word/safe-eval "$1" nonull || return 0 local cmd=$ret local compdef ble/util/assign compdef 'builtin complete -p -- "$cmd"' 2>/dev/null || { cmd=${cmd##*/}; ble/util/assign compdef 'builtin complete -p -- "$cmd"' 2>/dev/null; } || return 0 compdef=${compdef%"${cmd:-''}"} compdef=${compdef%' '}' ' local comp_opts=$comp_opts comp_prog comp_func compoptions flag_noquote ble/complete/progcomp/parse-complete "$compdef" # Call adjustments based on the values of "comp_prog" and "comp_func" ble/complete/progcomp/adjust-third-party-completions } function ble/contrib/integration:bash-completion/loader/_comp_load.advice { [[ ${BLE_ATTACHED-} ]] || return 0 ((ADVICE_EXIT==0)) || return 0 # command-line argument parsing taken from _comp_load (bash_completion). local flag_fallback_default="" IFS=$' \t\n' local OPTIND=1 OPTARG="" OPTERR=0 opt set -- "${ADVICE_WORDS[@]:1}" while getopts ':D' opt "$@"; do case $opt in D) flag_fallback_default=set ;; *) return 2 ;; esac done shift "$((OPTIND - 1))" ble/contrib/integration:bash-completion/loader/.adjust-progcomp "$@" } function ble/contrib/integration:bash-completion/loader/__load_completion.advice { [[ ${BLE_ATTACHED-} ]] || return 0 ((ADVICE_EXIT==0)) || return 0 ble/contrib/integration:bash-completion/loader/.adjust-progcomp "$@" } function ble/contrib/integration:bash-completion/loader/adjust { if ble/is-function _comp_load; then ble/function#advice after _comp_load ble/contrib/integration:bash-completion/loader/_comp_load.advice elif ble/is-function __load_completion; then ble/function#advice after __load_completion ble/contrib/integration:bash-completion/loader/__load_completion.advice fi } #------------------------------------------------------------------------------ # Hooks for mandb ## @fn ble/contrib/integration:bash-completion/mandb/.alloc-subcache command hash [opts] ## @var[out] ret function ble/contrib/integration:bash-completion/mandb/.alloc-subcache { ret= [[ $_ble_attached ]] || return 1 local command=$1 hash=$2 opts=$3 if [[ :$opts: == *:dequote:* ]]; then ble/syntax:bash/simple-word/safe-eval "$command" noglob:nonull && command=$ret fi [[ $command ]] || return 1 [[ $command == ble*/* ]] || command=${1##*/} ble/string#hash-pjw "$args" 64; local hash=$ret local lc_messages=${LC_ALL:-${LC_MESSAGES:-${LANG:-C}}} local mandb_cache_dir=$_ble_base_cache/complete.mandb/${lc_messages//'/'/%} ble/util/sprintf ret '%s.%014x' "$mandb_cache_dir/_parse_help.d/$command" "$hash" [[ -s $ret && $ret -nt $_ble_base/lib/core-complete.sh ]] && return 1 ble/util/mkd "${ret%/*}" } ## @fn ble/contrib/integration:bash-completion/mandb/_parse_help.advice command args function ble/contrib/integration:bash-completion/mandb/_parse_help.advice { [[ ${BLE_ATTACHED-} ]] || return 0 local cmd=$1 args=$2 func=$ADVICE_FUNCNAME # 現在のコマンド名。 Note: ADVICE_WORDS には実際に現在補完しようとしているコ # マンドとは異なるものが指定される場合があるので (例えば help や - 等) 信用で # きない。 local command=${COMP_WORDS[0]-} hash="${ADVICE_WORDS[*]}" ret ble/contrib/integration:bash-completion/mandb/.alloc-subcache "$command" "$hash" dequote || return 0 local subcache=$ret local default_option=--help help_opts= [[ $func == _parse_usage ]] && default_option=--usage help_opts=mandb-usage if [[ ( $func == _parse_help || $func == _parse_usage ) && $cmd == - ]]; then # 標準入力からの読み取り ble/complete/mandb:help/generate-cache "$help_opts" >| "$subcache" # Note: _parse_help が読み取る筈だった内容を横取りしたので抽出した内容を標 # 準出力に出力する。但し、対応する long option がある short option は除外す # る。 LC_ALL= LC_COLLATE=C ble/bin/awk -F "$_ble_term_FS" ' BEGIN { entry_count = 0; } { entries[entry_count++] = $1; # Assumption: the descriptions of long options have the form # "[short_opt] desc". The format is defined by # ble/complete/mandb:help/generate-cache. desc = $4; gsub(/\033\[[ -?]*[@-~]/, "", desc); # disable=#D1440 (LC_COLLATE=C is set) if (match(desc, /^\[[^]'"$_ble_term_blank"'[]*\] /) > 0) { # #D1709 safe short_opt = substr(desc, 2, RLENGTH - 3); excludes[short_opt] =1; } } END { for (i = 0; i < entry_count; i++) if (!excludes[entries[i]]) print entries[i]; } ' "$subcache" 2>/dev/null # suppress locale error #D1440 else local cmd_args ble/string#split-words cmd_args "${args:-$default_option}" "$cmd" "${cmd_args[@]}" 2>&1 | ble/complete/mandb:help/generate-cache "$help_opts" >| "$subcache" fi } function ble/contrib/integration:bash-completion/mandb/_get_help_lines.advice { [[ ${BLE_ATTACHED-} ]] || return 0 ((${#_lines[@]})) || return 0 # @var cmd # 現在のコマンド名。Note: _comp_command_offset 等によって別のコマンドの補完 # を呼び出している場合があるので ble.sh の用意する comp_words は信用できな # い。bash-completion の使っている _comp_args[0] または bash-completion が # 上書きしている COMP_WORDS を参照する。 local cmd=${_comp_args[0]-${COMP_WORDS[0]-}} hash="${ADVICE_WORDS[*]}" ble/contrib/integration:bash-completion/mandb/.alloc-subcache "$cmd" "$hash" dequote || return 0 local subcache=$ret local help_opts= [[ ${ADVICE_FUNCNAME[1]} == *_usage ]] && help_opts=mandb-usage printf '%s\n' "${_lines[@]}" | ble/complete/mandb:help/generate-cache "$help_opts" >| "$subcache" } ## @fn ble/contrib/integration:bash-completion/mandb/_comp_command_offset.yield ## process generated completions stored in COMPREPLY. function ble/contrib/integration:bash-completion/mandb/_comp_command_offset.yield { local word_offset=$1 # Other variables for ble/complete/progcomp/process-compgen-output local comp_words comp_cword comp_line comp_point IFS=$' \t\n' comp_cword=$((COMP_CWORD-word_offset)) ((comp_cword==0)) && return 0 comp_words=("${COMP_WORDS[@]:word_offset}") comp_line="${comp_words[*]}" comp_point="${comp_words[*]::comp_cword+1}" comp_point=${#comp_point} if ((${#COMPREPLY[@]}==0)); then ble/complete/source:argument/fallback reuse-comp_words; local ext=$? compopt +o ble/default +o default +o dirnames return "$ext" fi # Input local compgen parse_compgen_opts=array compgen=("${COMPREPLY[@]}") COMPREPLY=() # Arguments for ble/complete/progcomp/process-compgen-output local cmd=${comp_words[0]} ret ble/syntax:bash/simple-word/safe-eval "$cmd" nonull && cmd=$ret [[ ${cmd##*/} == git ]] && parse_compgen_opts=work-around-git ble/complete/progcomp/process-compgen-output "$cmd" "$parse_compgen_opts" } function ble/contrib/integration:bash-completion/mandb/_comp_command_offset.advice { [[ ${BLE_ATTACHED-} ]] || return 0 local REPLY _comp__find_original_word "${ADVICE_WORDS[1]}" ble/contrib/integration:bash-completion/mandb/_comp_command_offset.yield "$REPLY" } function ble/contrib/integration:bash-completion/mandb/_command_offset.advice { [[ ${BLE_ATTACHED-} ]] || return 0 local word_offset=${ADVICE_WORDS[1]} i j for ((i=0;i/dev/null # _parse_help が別の枠組みで定義されている事がある? #D1900 #------------------------------------------------------------------------------ function ble/contrib/integration:bash-completion/cmd-with-conditional-sync.advice { if [[ ${BLE_ATTACHED-} ]]; then ble/function#push "${ADVICE_WORDS[1]}" ' local -a cmd_args; cmd_args=("${ADVICE_WORDS[1]}" "$@") ble/util/conditional-sync \ '\''command "${cmd_args[@]}"'\'' \ '\''! ble/complete/check-cancel'\'' 128 progressive-weight:killall' ble/function#advice/do ble/function#pop "${ADVICE_WORDS[1]}" else ble/function#advice/do fi } function ble/contrib/integration:bash-completion/_do_dnf5_completion.advice { ble/contrib/integration:bash-completion/cmd-with-conditional-sync.advice "$@" [[ ${BLE_ATTACHED-} ]] || return 0 if ((${#COMPREPLY[@]}>=2)); then local i has_desc= for i in "${!COMPREPLY[@]}"; do if ble/string#match "${COMPREPLY[i]}" '[[:blank:]]+\((.*)\)$'; then local cand=${COMPREPLY[i]%"$BASH_REMATCH"} desc=${BASH_REMATCH[1]} if [[ $cand && $cand != "${COMPREPLY[i]}" ]]; then ble/complete/cand/yield word "$cand" "$desc" has_desc=1 builtin unset -v 'COMPREPLY[i]' continue fi fi if [[ ! -e ${COMPREPLY[i]} ]]; then ble/complete/cand/yield word "$cand" builtin unset -v 'COMPREPLY[i]' fi done COMPREPLY=("${COMPREPLY[@]}") [[ $has_desc ]] && bleopt complete_menu_style=desc fi } function ble/contrib/integration:bash-completion/adjust { ble/is-function _comp_initialize || ble/is-function _quote_readline_by_ref || return 0 ble/contrib/integration:bash-completion/loader/adjust _ble_contrib_integration_bash_completion_cmd_conditional_sync=(_comp_cmd_make _make _do_dnf5_completion) if [[ $comp_func == _comp_cmd_make || $comp_func == _make ]]; then ble/is-function "$comp_func" && ble/function#advice around "$comp_func" ble/contrib/integration:bash-completion/cmd-with-conditional-sync.advice elif [[ $comp_func == _do_dnf5_completion ]]; then ble/is-function "$comp_func" && ble/function#advice around "$comp_func" ble/contrib/integration:bash-completion/_do_dnf5_completion.advice fi if ((BASH_COMPLETION_VERSINFO[0]<2||BASH_COMPLETION_VERSINFO[0]==2&&BASH_COMPLETION_VERSINFO[1]<12)); then # Fix issues with bash-completion <= 2.11 # https://github.com/scop/bash-completion/pull/492 (fixed in bash-completion 2.12) function _quote_readline_by_ref { if [[ $1 == \'* ]]; then printf -v "$2" %s "${1:1}" else printf -v "$2" %q "$1" [[ ${!2} == \$* ]] && builtin eval "$2=${!2}" fi } ble/function#suppress-stderr _filedir 2>/dev/null # https://github.com/scop/bash-completion/issues/509 (fixed in bash-completion 2.12) ble/function#suppress-stderr _find 2>/dev/null # https://github.com/scop/bash-completion/pull/556 (fixed in bash-completion 2.12) ble/function#suppress-stderr _scp_remote_files 2>/dev/null # https://github.com/scop/bash-completion/pull/773 (fixed in bash-completion 2.12) ble/function#suppress-stderr _function 2>/dev/null fi ble/contrib/integration:bash-completion/mandb/adjust }