我有一个名为 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 "$@"