為自訂腳本新增自動完成功能

為自訂腳本新增自動完成功能

我目前正在編寫一個名為makeyourself.sh(連結到/usr/bin/mys)的 shell 腳本,它會自動從原始程式碼(透過 )安裝 debian 軟體包apt-get source -b $1

因此,我決定為作為第一個參數給出的包名稱添加自動完成功能:sudo mys panth<tab><tab>然後應該列出以 — 開頭的每個包,panth我的嘗試如下:

complete -C "apt-cache --no-generate pkgnames" mys

但它似乎不起作用:當我按上面提到的 Tab 鍵時, at 將參數更改為mys,這會返回 me sudo mys mys

我究竟做錯了什麼?我是否必須在命令中指定complete必須插入應完成的字串的位置,例如{}or $1

我使用 ElementaryOS,一個基於 Ubuntu 的 Linux 發行版。這個腳本是一個標準的 *.sh shell 腳本,它使用標準#!/bin/bash

答案1

正如您所懷疑的,該命令會收到一些有關要完成的操作的資訊。這在手冊中有記錄,但在complete內建文檔,您需要閱讀可程式完成的介紹部分

呼叫使用-F和選項指定的任何 shell 函數或命令。-C當呼叫命令或函數時,COMP_LINECOMP_POINTCOMP_KEYCOMP_TYPE變數將按上述方式指派值(請參閱Bash 變數)。如果正在呼叫 shell 函數,則也會設定COMP_WORDS和變數。COMP_CWORD當呼叫函數或命令時,第一個參數是正在完成其參數的命令的名稱,第二個參數是正在完成的單詞,第三個參數是當前命令列上正在完成的單字之前的單字。不會根據正在完成的單字對生成的完成進行過濾;函數或命令在產生匹配時具有完全的自由。

因此,使用三個參數來呼叫該命令:

  • 指令名稱 — 這樣您就可以在一個腳本中組合相似指令的完成。
  • 要完成的單字 - 因此您可以將輸出限制為無論如何都會被過濾的前綴。
  • 前一個字——例如用於完成選項很有用。

相同的參數傳遞給完成函數 ( complete -F somefunction)。請注意,無論您使用函數還是命令,過濾所需的匹配項都是您的工作。

根據您的嘗試,最終執行的命令是apt-cache --no-generate pkgnames mys '' mys。這將列印以mys(apt-cache pkgnames僅查看第一個操作數)開頭的包名稱列表。最長的公共前綴是mys,因此 bash 開始完成mys並期望您選擇下一個字母。

由於參數被附加到命令中(不是作為位置參數傳遞 — 參數被-C解析為 shell 命令),因此沒有簡單的方法來解析它們。最簡單的解決方案是使用包裝函數。

_mys () {
  COMPREPLY=$(apt-cache --no-generate pkgnames "$2")
}
complete -F _mys mys

相關內容