Mar*_*ter 3 command-line zsh autocomplete
我有自定义脚本,需要:
短/长命令行选项例如:
-r, --readonly
-m, --mount
Run Code Online (Sandbox Code Playgroud)
对于一个必需的参数,这些参数实际上在脚本中指定为 case 语句,即foo在bar本例中:
case $1 in
foo )
:
;;
bar )
:
;;
Run Code Online (Sandbox Code Playgroud)
如何zsh completion为我的脚本创建,以便在参数以 开头时完成可选参数-,并从我的脚本 case 语句中获取所需参数?
这是我到目前为止所得到的,受到答案的启发@Marlon Richert。
假设调用我的自定义脚本myscript.sh并且我创建的完成规则位于/usr/share/zsh/functions/Completion/Unix/_myscript.sh:
#compdef myscript.sh
_myscript () {
local -a args
args+=(
{-r,--readonly}'[description for "readonly"]'
{-m,--mount}'[description for "mount"]'
)
_arguments $args && return
}
_myscript "$@"
Run Code Online (Sandbox Code Playgroud)
我的脚本myscript.sh本身位于/usr/local/bin/myscript.sh.
因此,现在当我有了可选参数-r并-m得到处理时,我需要修改我的完成规则,以便对于我的脚本所需的命令行参数,来自 case 语句的项目作为/usr/local/bin/myscript.sh完成提供。
另外,我不确定args+=(完成脚本中第 6 行开始的块的语法是否正确。我必须在哪里放置单引号?
让我们假设您要为其定义完成的函数称为myfunc。
首先,让我们设置实际的功能:
\nmyfunc. 没有10.zsh或结尾.sh。funcname() {\xe2\x80\xa6}样板文件。myfunc位于您的$fpath. 例如,如果文件myfunc位于 中~/Functions,请将其添加到您的~/.zshrc文件中:\nfpath+=( ~/Functions )\nRun Code Online (Sandbox Code Playgroud)\nmyfunc到您的~/.zshrc文件中:\n# We pass a couple of options that make the code \n# less likely to break:\n# -U suppresses alias expansion\n# -z marks the function for zsh-style autoloading == \n# `unsetopt KSH_AUTOLOAD`\nautoload -Uz myfunc\nRun Code Online (Sandbox Code Playgroud)\n您现在应该能够myfunc在命令行上使用(但还没有任何完成)。
接下来,让我们创建完成函数:
\n_myfunc.#compdef myfunc\n\n# The line above means "This function generates \n# completions for myfunc."\n# The combination of that line, plus the file name\n# starting with an `_`, plus having this file\'s \n# parent dir in your `$fpath`, ensures this file \n# will be autoloaded when you call `compinit`.\n\n# `+X` makes sure `myfunc`\'s definition will get \n# loaded immediately, even if you have not called \n# this function yet.\nautoload +X -Uz myfunc\n\n# Get the definition of `myfunc` in string form.\nlocal funcdef="$( type -f myfunc )"\n\n# Get the part that matches `case*esac`, then split\n# it on whitespace and put the resulting words in an \n# array.\nlocal -a words=( ${=funcdef[(r)case,(r)esac]} )\n\n# Keep only the words that start with `(` and end \n# with `)`.\n# Even if you used the `case` syntax with only the \n# closing `)`s, `type -f` will show your cases with\n# both `(` and `)`.\nlocal -a required=( ${(M)words:#\'(\'*\')\'} )\n\n# `-s`: Allow options to `myfunc ` to be stacked, \n# that is, you are allowed to specify `myfunc -rm`.\n# If not, remove the `-s` option.\n# `*:`: Let this argument be completed in any \n# position.\n_arguments -s \\\n {-r,--readonly}\'[description for "readonly"]\' \\\n {-m,--mount}\'[description for "mount"]\' \\\n "*:required argument:( ${required//[()]/} )"\nRun Code Online (Sandbox Code Playgroud)\nrequired argument为您想要调用的任何参数。$fpath.autoload -Uz compinit; compinit在您的.zshrc文件中执行此操作,并确保它在上面的目录添加到您的$fpath.exec zsh或关闭终端窗口并打开一个新窗口。您现在应该能够完成myfunc.
如果readonly和mount互斥,您需要重写完成函数的最后一行,如下所示:
_arguments \\\n (-m --mount){-r,--readonly}\'[description for "readonly"]\' \\\n (-r --readonly){-m,--mount}\'[description for "mount"]\' \\\n "*:required argument:( ${required//[()]/} )"\nRun Code Online (Sandbox Code Playgroud)\n