我有一個名為 load_pg 的函數,定義如下:
load_pg () {
pg_restore --verbose --clean --no-acl --no-owner -h localhost -U $1 -d $2 $3
}
我正在嘗試使用以下程式碼自動完成每個參數:
#compdef load_pg
_arguments -s \
"1::_ldpguser" \
"2::_ldpgdb" \
"3::_ldpgfile"
_ldpguser () {
compadd $USER
}
_ldpgdb () {
compadd $(cat config/database.yml | grep -i database | awk '{print $2}')
}
_ldpgfile () {
compadd $(ls *.dump*)
}
不幸的是,當我按 TAB 時什麼也沒有發生。我究竟做錯了什麼?我嘗試使用來自以下答案
答案1
_arguments
第一個障礙: is where的參數語法不允許為空。如果您添加訊息,您會看到一些進展:n:message:action
message
_arguments -s \
"1:username:_ldpguser" \
"2:database:_ldpgdb" \
"3:dump file:_ldpgfile"
下一個障礙是輔助函數是在_arguments
運行後定義的,因此第一次完成參數時,您將收到一條錯誤訊息,抱怨其中一個函數不存在。在使用函數之前先定義它們。更好的是,明確函數的定義_load_pg
並在自動載入檔案的末尾呼叫它。這看起來很笨拙,但這是 zsh 附帶的大多數多功能完成函數的編寫方式。
#compdef load_pg
_ldpguser () {
compadd $USER
}
_ldpgdb () {
compadd $(cat config/database.yml | grep -i database | awk '{print $2}')
}
_ldpgfile () {
compadd $(ls *.dump*)
}
_load_pg () {
_arguments -s \
"1:user:_ldpguser" \
"2:database:_ldpgdb" \
"3:dump file:_ldpgfile"
}
_load_pg "$@"
這為您提供了該功能的核心。然後您需要清理各個函數。最低限度:
compadd $USER
似乎毫無意義:如果您只想使用您的用戶名呼叫該函數,為什麼不建立它呢?若要完成用戶名,請呼叫_users
.- 指令替換替換所有空格。要分割線,請使用
@
和f
參數擴展標誌。您還應該使您的grep
命令更加精確,並且您可以將其與grep
. - 當您
compadd
從 中呼叫操作時_arguments
,請將 中的上下文選項傳遞給它$expl
。 - 您可能需要提供完成的描述
_describe
。 $(ls *.dump*)
是一種複雜的書寫方式“*.dump*
,如果沒有匹配,則根據當前 shell 設定執行某些操作”。不解析輸出ls
,嗯嗯?你可以使用N
全域限定符當沒有匹配時有一個空的完成列表。但是,您應該調用_files
除其他細節外,它還負責完成子目錄中的檔案。
#compdef load_pg
_ldpgdb () {
compadd $expl[@] -- "${(@f)$(<config/database.yml grep -i database | awk '{print $2}')}"
}
_load_pg () {
_arguments -s \
'1:user:_users' \
'2:database:_ldpgdb' \
'3:dump file:_files -g "*.dump*"'
}
_load_pg "$@"