Komutun tamamlanması (diğer şeylerle birlikte) bash okuma satırı tamamlaması ile gerçekleştirilir . Bu, normal "programlanabilir tamamlama" dan biraz daha düşük bir seviyede çalışır (yalnızca komut tanımlandığında ve yukarıda tanımladığınız iki özel durum çağrılır).
Güncelleme: bash-5.0'ın yeni çıkması (Ocak 2019) complete -I
bu soruna kesinlikle katılıyor .
İlgili okuma satırı komutları:
complete (TAB)
Attempt to perform completion on the text before point. Bash
attempts completion treating the text as a variable (if the text
begins with $), username (if the text begins with ~), hostname
(if the text begins with @), or command (including aliases and
functions) in turn. If none of these produces a match, filename
completion is attempted.
complete-command (M-!)
Attempt completion on the text before point, treating it as a
command name. Command completion attempts to match the text
against aliases, reserved words, shell functions, shell
builtins, and finally executable filenames, in that order.
Daha yaygın olana benzer şekilde, bunun bir complete -F
kısmı kullanılarak bir işleve devredilebilir bind -x
.
function _complete0 () {
local -a _cmds
local -A _seen
local _path=$PATH _ii _xx _cc _cmd _short
local _aa=( ${READLINE_LINE} )
if [[ -f ~/.complete.d/"${_aa[0]}" && -x ~/.complete.d/"${_aa[0]}" ]]; then
## user-provided hook
_cmds=( $( ~/.complete.d/"${_aa[0]}" ) )
elif [[ -x ~/.complete.d/DEFAULT ]]; then
_cmds=( $( ~/.complete.d/DEFAULT ) )
else
## compgen -c for default "command" complete
_cmds=( $(PATH=$_path compgen -o bashdefault -o default -c ${_aa[0]}) )
fi
## remove duplicates, cache shortest name
_short="${_cmds[0]}"
_cc=${#_cmds[*]} # NB removing indexes inside loop
for (( _ii=0 ; _ii<$_cc ; _ii++ )); do
_cmd=${_cmds[$_ii]}
[[ -n "${_seen[$_cmd]}" ]] && unset _cmds[$_ii]
_seen[$_cmd]+=1
(( ${#_short} > ${#_cmd} )) && _short="$_cmd"
done
_cmds=( "${_cmds[@]}" ) ## recompute contiguous index
## find common prefix
declare -a _prefix=()
for (( _xx=0; _xx<${#_short}; _xx++ )); do
_prev=${_cmds[0]}
for (( _ii=0 ; _ii<${#_cmds[*]} ; _ii++ )); do
_cmd=${_cmds[$_ii]}
[[ "${_cmd:$_xx:1}" != "${_prev:$_xx:1}" ]] && break
_prev=$_cmd
done
[[ $_ii -eq ${#_cmds[*]} ]] && _prefix[$_xx]="${_cmd:$_xx:1}"
done
printf -v _short "%s" "${_prefix[@]}" # flatten
## emulate completion list of matches
if [[ ${#_cmds[*]} -gt 1 ]]; then
for (( _ii=0 ; _ii<${#_cmds[*]} ; _ii++ )); do
_cmd=${_cmds[$_ii]}
[[ -n "${_seen[$_cmds]}" ]] && printf "%-12s " "$_cmd"
done | sort | fmt -w $((COLUMNS-8)) | column -tx
# fill in shortest match (prefix)
printf -v READLINE_LINE "%s" "$_short"
READLINE_POINT=${#READLINE_LINE}
fi
## exactly one match
if [[ ${#_cmds[*]} -eq 1 ]]; then
_aa[0]="${_cmds[0]}"
printf -v READLINE_LINE "%s " "${_aa[@]}"
READLINE_POINT=${#READLINE_LINE}
else
: # nop
fi
}
bind -x '"\C-i":_complete0'
Bu, kendi başına komut veya önek dizginin kancalarına takılmasını sağlar ~/.complete.d/
. Örn ~/.complete.d/loc
: ile çalıştırılabilir bir dosya oluşturursanız
#!/bin/bash
echo localc
Bu (kabaca) beklediğiniz şeyi yapacak.
Yukarıdaki işlev, normal bash komut tamamlama davranışını taklit etmek için bazı uzunluklara gider, ancak kusursuz olmasına rağmen (özellikle sort | fmt | column
bir eşleşme listesi görüntülemek için şüpheli bir şekilde devam eder).
Bununla birlikte , bunun önemsiz bir sorunu sadece ana complete
işleve bağlamayı değiştirmek için bir işlev kullanabilir (varsayılan olarak TAB ile çağrılır).
Bu yaklaşım sadece özel komut tamamlama için kullanılan farklı bir anahtar bağlama ile iyi çalışır, ancak bundan sonra tam tamamlama mantığını uygulamaz (örneğin komut satırında daha sonra kelimeler). Bunu yapmak komut satırının ayrıştırılmasını, imleç konumunun ele alınmasını ve muhtemelen bir kabuk komut dosyasında düşünülmemesi gereken diğer zor şeyleri gerektirir.
loc
vermeyi düşündün mülocalc
? Alternatifler öneriyorum, çünkü oldukça uzun bir süre kazı ve arama yaptıktan sonra bash tamamlamayı bu şekilde özelleştirmenin bir yolunu bulamadım. Bu mümkün olmayabilir.