कमांड का समापन (अन्य चीजों के साथ) को बैश रीडलाइन पूरा करने के माध्यम से नियंत्रित किया जाता है । यह सामान्य "प्रोग्रामेबल कम्प्लीमेंट" की तुलना में थोड़े निचले स्तर पर संचालित होता है (जो केवल कमांड की पहचान होने पर, और आपके द्वारा पहचाने गए दो विशेष मामलों के लिए लागू होता है)।
अपडेट: बैश-5.0 (जनवरी 2019) की नई रिलीज complete -I
इस समस्या के लिए जोड़ती है।
प्रासंगिक रीडलाइन कमांड हैं:
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.
अधिक समान तरीके से complete -F
, कुछ का उपयोग करके इसे किसी फ़ंक्शन को सौंपा जा सकता है 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'
यह आपकी प्रति-कमांड या उपसर्ग स्ट्रिंग हुक को सक्षम करता है ~/.complete.d/
। जैसे यदि आप एक निष्पादन योग्य बनाते हैं ~/.complete.d/loc
:
#!/bin/bash
echo localc
यह (मोटे तौर पर) आप क्या उम्मीद करेंगे।
उपरोक्त फ़ंक्शन सामान्य बैश कमांड पूरा होने के व्यवहार का अनुकरण करने के लिए कुछ लंबाई तक जाता है, हालांकि यह अपूर्ण है (विशेष रूप से संदिग्ध sort | fmt | column
कैरी-ऑन मैचों की सूची प्रदर्शित करने के लिए)।
हालांकि , इसके साथ एक गैर-तुच्छ मुद्दा यह केवल फ़ंक्शन को मुख्य complete
फ़ंक्शन के लिए बाइंडिंग को बदलने के लिए उपयोग कर सकता है (डिफ़ॉल्ट रूप से टीएबी के साथ संलग्न)।
यह दृष्टिकोण केवल कस्टम कमांड पूर्णता के लिए उपयोग किए जाने वाले एक अलग कुंजी-बाइंडिंग के साथ अच्छी तरह से काम करेगा, लेकिन यह उसके बाद पूर्ण पूर्ण तर्क को लागू नहीं करता है (जैसे कमांड लाइन में बाद के शब्द)। ऐसा करने के लिए कमांड लाइन को पार्स करने की आवश्यकता होगी, कर्सर की स्थिति से निपटने के लिए, और अन्य मुश्किल चीजें जो शायद एक शेल में नहीं मानी जानी चाहिए ...
loc
करने पर विचार किया हैlocalc
? मैं विकल्प सुझाता हूं क्योंकि काफी समय के बाद खुदाई करने और खोज करने के बाद मुझे इस तरह से बैश को पूरा करने का कोई तरीका नहीं मिला है। यह संभव नहीं हो सकता है।