ความสำเร็จของคำสั่ง (พร้อมกับสิ่งอื่น ๆ ) จะถูกจัดการผ่านทุบตีReadLine เสร็จสิ้น สิ่งนี้ทำงานในระดับที่ต่ำกว่า "การทำโปรแกรมให้เสร็จสมบูรณ์" (ซึ่งถูกเรียกใช้เมื่อระบุคำสั่งและสองกรณีพิเศษที่คุณระบุไว้ด้านบน)
อัปเดต: bash-5.0 รุ่นใหม่ (ม.ค. 2019) เพิ่มcomplete -I
สำหรับปัญหานี้อย่างแน่นอน
คำสั่ง readline ที่เกี่ยวข้องคือ:
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
ฟังก์ชั่นหลัก(เรียกใช้กับ TAB โดยค่าเริ่มต้น)
วิธีการนี้จะทำงานได้ดีกับการโยงคีย์ที่แตกต่างกันซึ่งใช้สำหรับการทำคำสั่งที่กำหนดเองให้เสร็จสมบูรณ์ แต่ก็ไม่ได้ใช้ตรรกะการเติมเต็มที่สมบูรณ์หลังจากนั้น (เช่นคำต่อมาในบรรทัดคำสั่ง) การทำเช่นนั้นจะต้องแยกวิเคราะห์บรรทัดคำสั่งจัดการกับตำแหน่งเคอร์เซอร์และสิ่งอื่น ๆ ที่อาจไม่ควรพิจารณาในเชลล์สคริปต์ ...
loc
เพื่อlocalc
? ฉันแนะนำทางเลือกเพราะหลังจากผ่านไประยะหนึ่งในการขุดและค้นหาฉันยังไม่พบวิธีในการปรับแต่ง bash ให้สมบูรณ์ด้วยวิธีนี้ มันอาจเป็นไปไม่ได้