- แนะนำวิธีสร้างฟีเจอร์เติมคำอัตโนมัติด้วยแท็บใน Bash และ Zsh ที่แสดงคำอธิบายได้แม้กับคำที่เติมครบแล้ว
- Bash และ Zsh ใช้ API สำหรับ tab completion คนละแบบ และมีเพียง Zsh ที่รองรับ การแสดงคำอธิบายในรายการเติมคำอัตโนมัติ มาให้โดยพื้นฐาน
- ใช้
_generate_foo_completions เพื่อสร้างตัวเลือก และส่งกลับผ่าน COMPREPLY ใน Bash, และ compadd ใน Zsh
- เพื่อให้ Bash แสดงคำอธิบายแบบเดียวกับ Zsh จึงใช้วิธี ใส่คำอธิบายไว้ในสตริงของตัวเลือก และลบคำอธิบายออกเฉพาะตอนที่มีตัวเลือกเดียว
- แม้ในกรณีที่มีตัวเลือกเดียว ก็ยังปรับปรุงให้แสดงคำอธิบายเมื่อกด
<TAB> ได้ โดย จงใจเพิ่มความกำกวม เข้าไป
- สคริปต์สุดท้ายให้ประสบการณ์ใช้งานแบบเดียวกันในทั้งสองเชลล์ และรองรับครบทั้ง การเติมบางส่วน การเติมทั้งหมด และการแสดงคำอธิบายของตัวเลือก
ที่มาของปัญหา
- การเติมคำอัตโนมัติด้วยแท็บ (tab-completion) มีประโยชน์มากเวลาไล่ดูคำสั่งหรือแฟล็ก โดยเฉพาะเมื่อเพิ่งเริ่มใช้ API หรือเครื่องมือ CLI
- โดยปกติ Zsh จะแสดง คำอธิบายเมื่อมีหลายตัวเลือกเท่านั้น ส่วน Bash ต้องอาศัย การตั้งค่าเพิ่มเติม
- แต่สำหรับ คำที่เติมครบอยู่แล้ว ทั้งสองเชลล์ จะไม่แสดงคำอธิบาย
- ทำให้ผู้ใช้ต้องผ่านขั้นตอนที่ยุ่งยากดังนี้เพื่อดูคำอธิบาย
- ลบตัวอักษรบางส่วนออกเพื่อให้ตรงกับหลายตัวเลือก
- กดปุ่ม
<TAB> เพื่อดูรายการตัวเลือก
- มองหาและแยกคำอธิบายที่ต้องการด้วยสายตา
- พิมพ์ตัวอักษรที่ลบไปกลับเข้าไปอีกครั้งเพื่อรันคำสั่ง
ภาพรวมของวิธีแก้
- เมื่อมีตัวเลือกเดียว ก็ เพิ่มตัวเลือกหลอก (dummy completion) เข้าไปเพื่อทำให้เกิดความกำกวมในรายการตัวเลือก
- วิธีนี้ทำให้ ทั้ง Bash และ Zsh แสดงรายการตัวเลือกพร้อมคำอธิบาย ได้
- อย่างไรก็ตาม ต้องระวังไม่ให้ข้อความคำอธิบายถูกแทรกเข้าไปในคำสั่งจริง
แนวคิดพื้นฐาน
- การเติมคำอัตโนมัติด้วยแท็บจะทำงานโดยรับคำปัจจุบันและตำแหน่งเคอร์เซอร์เมื่อกด
<TAB> แล้วคืนรายการตัวเลือกที่เป็นไปได้
- Bash: กำหนดตัวเลือกลงในอาร์เรย์
COMPREPLY
- Zsh: ลงทะเบียนตัวเลือกด้วยคำสั่ง
compadd
- ฟังก์ชัน
_generate_foo_completions จะพิมพ์สตริงของตัวเลือกออกมา และในการใช้งานจริงสามารถสร้างแบบไดนามิกตามสถานะของ CLI ได้
รองรับ Bash และ Zsh พร้อมกัน
- แยกเขียนตามเชลล์ด้วยฟังก์ชัน
_complete_foo_bash และ _complete_foo_zsh
- ใช้
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi เพื่อแยกกรณี
- ผู้ใช้สามารถนำสคริปต์ไปลงใน
.bashrc หรือ .zshrc แล้วใช้งานได้
การแสดงคำอธิบายใน Zsh
- ใช้รูปแบบ
ชื่อ: คำอธิบาย กับสตริงของตัวเลือก
- Zsh: ส่งชื่อและคำอธิบายด้วยอาร์เรย์ขนานผ่าน
compadd -d raw -- $trimmed
- Bash: ส่งเข้า
COMPREPLY เฉพาะตัวเลือกที่ตัดส่วนคำอธิบายออกแล้วเท่านั้น (เพราะปกติไม่รองรับคำอธิบาย)
ทำให้ Bash แสดงคำอธิบาย
- ถ้ามีหลายตัวเลือก ให้แสดงสตริงที่มีคำอธิบายติดมาด้วยตรง ๆ
- ถ้ามีตัวเลือกเดียว ให้ตัดคำอธิบายออกเฉพาะกรณีนั้น
- อาศัยพฤติกรรมของการเติมคำอัตโนมัติใน Bash ที่จะแทรกเฉพาะคำนำหน้าร่วมกัน เพื่อไม่ให้คำอธิบายถูกใส่ลงไปในอินพุตจริง
แสดงคำอธิบายได้แม้มีตัวเลือกเดียว
- เพื่อให้กด
<TAB> แล้วเห็นคำอธิบายได้แม้คำจะเติมครบแล้ว จึง เพิ่มตัวเลือกหลอก เพื่อสร้างความกำกวมโดยตั้งใจ
- Zsh: เพิ่มตัวเลือกหลอกลงในทั้งสองอาร์เรย์ขนาน (
raw, trimmed)
- Bash: ถ้ามีตัวเลือกเดียว ให้เพิ่มเฉพาะชื่อเข้าไปใน
trimmed
ผลลัพธ์สุดท้าย
ยังไม่มีความคิดเห็น