เพิ่มอาร์กิวเมนต์จากคำสั่งก่อนหน้าไปยังการเติม zsh ให้สมบูรณ์


21

ใน zsh (รวมถึง bash) คุณสามารถใช้การขยายคำประวัติเพื่อแสดงถึงอาร์กิวเมนต์จากคำสั่งก่อนหน้า

ตัวอย่างนี้แสดงการรับพารามิเตอร์ที่ 2 จากคำสั่งก่อนหน้าในประวัติที่มี!:#การขยาย:

% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar

ฉันมักจะลืมสิ่งที่ # พารามิเตอร์อาร์กิวเมนต์เฉพาะคือและการพิมพ์!:#ไม่เสมอว่ารวดเร็วเมื่อฉันจำได้ว่ามันขัดแย้ง ฉันรู้ว่าmeta-.จะแทนที่อาร์กิวเมนต์สุดท้าย แต่บางครั้งก็ไม่ใช่อาร์กิวเมนต์สุดท้ายที่ฉันต้องการ

ฉันต้องการเพิ่มข้อโต้แย้งจากคำสั่งก่อนหน้าเป็นข้อเสนอแนะเพื่อดำเนินการคำสั่งใด ๆ ที่ฉันพิมพ์ใน zsh

ฉันสามารถหาวิธีสร้างฟังก์ชันเชลล์ที่สามารถสร้างอาร์เรย์ของอาร์กิวเมนต์ (0..N) จากคำสั่งสุดท้ายและผูกเข้ากับคำสั่งเฉพาะ

_last_command_args() {
    last_command=$history[$[HISTCMD-1]]
    last_command_array=("${(s/ /)last_command}") 
    _sep_parts last_command_array
}

# trying to get last_command_args to be suggested for any command, this just works for foo
compdef _last_command_args foo

นี่คือสิ่งที่ดูเหมือนว่าจะเสร็จสิ้นเพียงแค่ foo ที่ฉันกดปุ่มแท็บที่<TAB>:

% echo bar baz qux
bar baz qux
% foo <TAB>
bar   baz   echo  qux 

นี่ใช้งานได้ดีสำหรับการทำคำสั่ง "foo" ให้สมบูรณ์ แต่ฉันต้องการให้ตัวเลือกเหล่านี้เป็นตัวเลือกสำหรับการขยาย zsh ที่ฉันทำ ฉันคิดว่ามันมีบางอย่างที่เกี่ยวข้องกับสิ่งที่คอมไพล์เตอร์ของ zstyle แต่หลังจากผ่านไปสองสามชั่วโมงของการแฮ็ครอบ ๆ ฉันก็รู้ว่าฉันไม่ได้อยู่ลึก

ฉันจะรับอาร์กิวเมนต์จากคำสั่งก่อนหน้าของฉันเป็นความสมบูรณ์ที่แนะนำสำหรับคำสั่งใด ๆ ใน zsh ได้อย่างไร

ฉันมีไฟล์เต็มรูปแบบของzshrc ที่ฉันได้ติดตั้งร่วมกันบน bitbucket ถ้ามันช่วยได้ มันมีเปลมากมายจากแหล่งที่มาที่หลากหลายและบางส่วนที่ฉันได้แฮ็กด้วยกัน

UPDATE:

คำตอบของ @Julien Nicoulaud ทำให้ฉันสนิทฉันทำเครื่องหมายว่ายอมรับได้เพราะทำให้ฉันได้รับในที่ที่ฉันต้องการ

ด้วยการตั้งค่าเฉพาะของฉันโดยใช้สิ่งที่แนะนำ:

zstyle ':completion:*' completer _last_command_args _complete

ไม่ได้ผลสำหรับฉันเนื่องจากมันทำให้แท็บเสร็จสมบูรณ์เพื่อแสดงรายการอาร์กิวเมนต์จากคำสั่งสุดท้ายเท่านั้น (แม้ว่าจริง ๆ แล้วมันจะเสร็จสมบูรณ์ด้วยชื่อไฟล์เช่นกัน การเปลี่ยนคำสั่งซื้อ_complete _last_command_argsเป็นแบบย้อนกลับ มันจะแสดงชื่อไฟล์ปกติ แต่ไม่ใช่ last_command_args

ฉันคาดเดาว่าสิ่งนี้เกี่ยวข้องกับวิธีที่คอมไพเลอร์ทำงานได้ ฉันคิดว่ามันจะแสดงผลลัพธ์จากวิธีแรกที่กลับมาสำเร็จ แต่ฉันมีปัญหาในการแยกวิเคราะห์แหล่ง zsh เพื่อทำความเข้าใจอย่างสมบูรณ์ว่าเกิดอะไรขึ้น ฉันสามารถปรับแต่งวิธีการของฉันเพื่อรวมการเรียกไป_completeเพื่อให้มันแสดงทั้งคำสั่งอาร์กิวเมนต์ล่าสุดเช่นเดียวกับสิ่งที่เติมข้อความอัตโนมัติปกติ ไม่ค่อยแยกกัน แต่ทำงานได้ดีพอสำหรับฉัน

นี่คือฟังก์ชั่นเต็มรูปแบบที่ฉันใช้พร้อมกับสิ่ง zstyle อื่น ๆ ที่ฉันมี:

# adds the arguments from the last commadn to the autocomplete list
# I wasn't able to get this to work standalone and still print out both regular
# completion plus the last args, but this works well enough.
_complete_plus_last_command_args() {
    last_command=$history[$[HISTCMD-1]]
    last_command_array=("${(s/ /)last_command}") 
    _sep_parts last_command_array
    _complete 
}


_force_rehash() {
  (( CURRENT == 1 )) && rehash
  return 1  # Because we didn't really complete anything
}

zstyle ':completion:::::' completer _force_rehash _complete_plus_last_command_args _approximate 

เส้น zstyle อื่น ๆ ที่ฉันมีไม่จำเป็นสำหรับการทำงาน แต่อาจส่งผลต่อสาเหตุที่ทำให้ฉัน:

zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes

ตอนนี้ถ้าฉันอยู่ในไดเรกทอรีด้วยfile1.txtและfile2.txtและคำสั่งสุดท้ายของฉันคือecho foo bar bazฉันได้รับมันสำหรับการเติมข้อความอัตโนมัติซึ่งเป็นเพียงสิ่งที่ฉันต้องการ:

% ls
bar   baz   echo  foo 
- files -
file1.txt   file2.txt 

2
นี่เป็นความคิดที่น่าทึ่ง
Michael Mrozek

2
เพื่อเสริม^[ .( insert-last-word) ผมชอบที่รอบระหว่างคำของเส้นเข้าถึงได้โดยcopy-earlier-word insert-last-wordสำหรับคุณ.zshrc:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word
Gilles 'หยุดความชั่วร้าย'

@Gilles ขอบคุณ! นั่นทำให้ฉันเข้าใกล้ฟังก์ชั่นมากขึ้นถ้าฉันไม่สามารถเติมข้อความอัตโนมัติได้อย่างสมบูรณ์ ~ 80% ของเวลาถ้าไม่ใช่อาร์กิวเมนต์สุดท้ายมันเป็นอาร์กิวเมนต์อันดับ 2 ถึงสุดท้ายที่ฉันต้องการและ C- + C- ค่อนข้างดี
Ted Naleid

คำตอบ:


6

คุณสามารถเพิ่มคอมไพเลอร์ของคุณไปยังรายการคอมไพล์ที่ใช้โดยค่าเริ่มต้น:

zstyle ':completion:*' completer _last_command_args _complete

1
หากมีความ_last_command_argsสำเร็จใด ๆอื่น ๆ จะไม่ปรากฏขึ้น คุณจะได้รับพวกเขานอกเหนือจากคนปกติได้อย่างไร
Gilles 'หยุดความชั่วร้าย'

1
ขอบคุณสำหรับคำตอบนี่ทำให้ฉันสนิทพอที่จะทำบางสิ่งบางอย่างให้ฉันดังนั้นฉันจึงยอมรับ สิ่งที่ฉันทำแตกต่างกันจะถูกบันทึกไว้เป็นการอัปเดตของคำถามด้านบน โซลูชันของคุณไม่ได้พิมพ์ทั้งอาร์กิวเมนต์จากคำสั่งสุดท้ายเช่นเดียวกับไฟล์ ฯลฯ จากคอมไพเลอร์ปกติ ฉันแต่ง_completeภายในฟังก์ชั่นที่ฉันสร้างขึ้นและทำงานได้เหมือนที่ฉันต้องการ
Ted Naleid

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