การทุบตีเสร็จสมบูรณ์สำหรับค่าที่คั่นด้วยเครื่องหมายจุลภาค


16

ฉันต้องการสร้างกฎความสมบูรณ์สำหรับรายการพารามิเตอร์ที่คั่นด้วยเครื่องหมายจุลภาค เช่นฉันมีคำสั่งที่ได้รับรายชื่อเซิร์ฟเวอร์:

myscript -s name1,name2,name3

ในขณะนี้ฉันได้จัดการเขียนเสร็จสมบูรณ์ดังต่อไปนี้:

_myscript () {
  local cur prev opts

  _get_comp_words_by_ref cur prev

  opts='-s'

  servers='name1 name2 name3'

  if [[ ${cur} == -* ]] ; then
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  else
    case "${prev}" in
      -s)
        if [[ "$cur" == *,* ]]; then
          local realcur prefix
          realcur=${cur##*,}
          prefix=${cur%,*}
          COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
        else
          COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
        fi
        ;;
      *)
        # do nothing
        ;;
    esac
  fi
}

แต่มันมีปัญหาอย่างน้อย 2 ข้อ:

  1. คำแนะนำสำหรับค่าปัจจุบันรวมถึงค่าก่อนหน้าทั้งหมดในคำนำหน้าของพวกเขา
  2. ไม่ถือว่าค่าที่ซ้ำกัน

แนวปฏิบัติที่ดีที่สุดสำหรับกรณีดังกล่าวคืออะไร? บางที bash-completions มีฟังก์ชั่นบางอย่างที่รวมมาสำหรับ csv-list?


3
สิ่งที่อาจช่วยได้คือคุณสามารถแบ่งค่าที่คั่นด้วยเครื่องหมายจุลภาคออกเป็นรายการที่สามารถทำซ้ำได้เช่นนี้IFS=, LIST=("$VARIABLE")โดยที่ $ VARIABLE มีค่าที่คั่นด้วยเครื่องหมายจุลภาคของคุณ
Michael Ehrenreich

2
ความคิดที่ดี @MichaelEhrenreich แต่คุณต้องไม่พูดถึง$VARIABLEมิฉะนั้นการแตกคำจะไม่เกิดขึ้น IFS=, LIST=($VARIABLE)เพียงแค่ใช้
Guss

คำตอบ:


6

โดยทั่วไปจะไม่มีวิธีการแก้ไขปัญหาที่คุณอธิบายเพราะทุบตีใช้ค่าในCOMPREPLYหน้าจอโดยตรงและจากนั้นแทนที่ข้อความของผู้ใช้ - ในขณะที่ได้รับสิ่งที่คุณต้องการคุณจะต้องสร้างความสำเร็จที่เป็นไปได้ก่อน ชื่อเซิร์ฟเวอร์โดยไม่มีคำนำหน้า) สำหรับ bash to display จากนั้นเมื่อ bash กำลังจะแทนที่ข้อความผู้ใช้ด้วยสตริงที่ไม่ขัดแย้งที่ยาวที่สุดคุณจะต้องเรียกให้สคริปต์ของคุณอีกครั้งเพื่อสร้างข้อความด้วยคำนำหน้า - และ bash ไม่มีสิ่งอำนวยความสะดวกสำหรับสิ่งนั้น

สิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือการCOMPREPLYสร้างด้วยคำแรกที่มีคำนำหน้าทั้งหมด ( COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )) เพื่อที่ว่าถ้ามีเพียงหนึ่งความสำเร็จที่เป็นไปได้มันจะเสร็จสิ้นโดยอัตโนมัติอย่างถูกต้องในขณะที่ถ้ามีความสมบูรณ์มากกว่าหนึ่ง แล้ว bash จะไม่ลบสิ่งที่พิมพ์ไปแล้ว (เนื่องจากคำแรกในCOMPREPLYคำนำหน้ามีทั้งหมดและตรงกับข้อความที่พิมพ์ในปัจจุบันและจะถูกเลือกโดย bash เพื่อแทนที่ข้อความของผู้ใช้) และจะแสดงตัวเลือกโดยไม่มีคำนำหน้า - ยกเว้น สำหรับคำเดียวที่มีคำนำหน้าอยู่แล้วดังนั้นผลลัพธ์จะเป็นดังนี้:

$ command -s banana,a
ananas     apricot    banana,apple

"apple" เรียงตามสุดท้ายในตัวเลือกความสมบูรณ์เพราะมันมีคำนำหน้าซึ่งเริ่มต้นด้วย "b" - สับสนมาก ดังนั้นฉันไม่แนะนำให้ทำเช่นนั้น

เกี่ยวกับรายการที่ซ้ำกัน - เพื่อไม่ให้แสดงรายการที่ซ้ำกันคุณเพียงแค่ต้องแบ่ง$prefixส่วนของมัน (ง่ายIFS="," prefix_parts=($prefix):) จากนั้นวนซ้ำพวกเขาและปล่อยเฉพาะใน$serversชื่อที่ไม่ได้ระบุไว้แล้ว มันน่าเบื่อที่จะพิมพ์ดังนั้นฉันจะไม่แสดงที่นี่ แต่ค่อนข้างน่ารำคาญดังนั้นฉันแน่ใจว่าคุณสามารถจัดการ :-)

เพื่อสรุปฉันไม่คิดว่าคุณควรใช้ค่าคั่นด้วยเครื่องหมายจุลภาคสำหรับตัวเลือกการป้อนอย่างน้อยถ้าคุณคาดหวังทุบตีเพื่อช่วยให้คุณเสร็จ

คุณสามารถรองรับรูปแบบตัวเลือกที่เป็นเช่นนี้: command -s <server> [<server> [..]]จากนั้นให้ทำรายการอื่นนอกเหนือจากรายการทันทีหลังจาก-sสแกนตัวเลือกเพียงสแกนกลับผ่าน$COMP_WORDSอาร์เรย์จาก$COMP_CWORDจนกว่าคุณจะพบตัวเลือก (สตริงที่ตรงกับ-*) และถ้าเป็น "-s" คุณต้องทำให้ชื่อเซิร์ฟเวอร์สมบูรณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.