当i type
my-cli <TAB>
我可以看到subcmd
自动完成。
当i type
my-cli macos <TAB>
我可以看到
_values
case
my-cli macos make-encrypted-volume <TAB>
自动完成。当i type
_arguments
我看不到该case
compdef
自动完成。
i我在这里读到,
-
需要CLI从a开始,以激活
_arguments
,但是即使我做my-cli macos make-encrypted-volume -<TAB>
都没有显示。任何帮助?
#compdef my-cli
# Filter out global options -v / --verbose
local -a filtered_words
filtered_words=("${(@)words:#(-v|--verbose)}")
# Reassign $words/$CURRENT so that subcommand logic ignores -v/--verbose
words=("${filtered_words[@]}")
CURRENT=$#words
# Use a stateful _arguments approach
_arguments -C \
'1:subcommand:->subcmd' \
'2:action:->action' \
'*::options:->options'
case "${state}" in
subcmd)
_values 'subcommand' \
'macos[utilities for macOS]' \
'--version[display version information and exit]' \
'--help[show help message and exit]' \
;;
action)
case "${words[2]}" in
macos)
_values 'macos subcommand' \
'find-unencrypted-volumes[find all unencrypted volumes]' \
'make-encrypted-volume[make an encrypted APFS volume]' \
'--help[show help message and exit]' \
'-h[show help message and exit]'
;;
esac
;;
options)
case "${words[2]}" in
macos)
case "${words[3]}" in
find-unencrypted-volumes)
_arguments \
'-h[show help message and exit]:show help message and exit'
;;
make-encrypted-volume)
_arguments \
'-h[show help message and exit]:show help message and exit' \
'-n[REQUIRED name of the encrypted volume]:REQUIRED name of the encrypted volume' \
'-q[OPTIONAL size of the encrypted volume in Gb i.e. -q 50g]:OPTIONAL size of the encrypted volume in Gb i.e. -q 50g'
;;
esac
;;
esac
;;
esac
return 0
我们可以通过
functions -T
(或
true
命令或:
都可以像经典的printf/echo样式一样调试调试,这样:
% functions -T _my-cli ;# trace the function to see what's happening.
% my-cli macos make-encrypted-volume <TAB> ;# (added newline here.)
+_my-cli:4> local -a filtered_words
+_my-cli:5> filtered_words=( my-cli macos make-encrypted-volume '' )
+_my-cli:8> words=( my-cli macos make-encrypted-volume '' )
+_my-cli:9> CURRENT=4
+_my-cli:12> _arguments -C '1:subcommand:->subcmd' '2:action:->action' '*::options:->options'
+_my-cli:17> case options (subcmd)
+_my-cli:17> case options (action)
+_my-cli:17> case options (options)
+_my-cli:38> case make-encrypted-volume (macos)
+_my-cli:57> return 0
% my-cli macos make-encrypted-volume
No matches for: `options'
在这种情况下,${words[2]}
是
make-encrypted-volume
而不是
macos
。因此,像以下差异一样倾倒
${words[@]}
:
--- _my-cli.orig
+++ _my-cli
@@ -14,6 +14,7 @@
'2:action:->action' \
'*::options:->options'
+: 'XXX*>' ${(q)words}
case "${state}" in
subcmd)
_values 'subcommand' \
@@ -35,6 +36,7 @@
;;
options)
+ : 'XXX*>' ${(q)words}
case "${words[2]}" in
macos)
case "${words[3]}" in
请参阅跟踪输出:% unfunction _my-cli; autoload -Uz _my-cli; functions -T _my-cli
% my-cli macos make-encrypted-volume <TAB> ;# (added newline here.)
+_my-cli:4> local -a filtered_words
+_my-cli:5> filtered_words=( my-cli macos make-encrypted-volume '' )
+_my-cli:8> words=( my-cli macos make-encrypted-volume '' )
+_my-cli:9> CURRENT=4
+_my-cli:12> _arguments -C '1:subcommand:->subcmd' '2:action:->action' '*::options:->options'
+_my-cli:17> : 'XXX*>' macos make-encrypted-volume ''''''
+_my-cli:18> case options (subcmd)
+_my-cli:18> case options (action)
+_my-cli:18> case options (options)
+_my-cli:39> : 'XXX*>' macos make-encrypted-volume ''''''
+_my-cli:40> case make-encrypted-volume (macos)
+_my-cli:59> return 0
% my-cli macos make-encrypted-volume
No matches for: `options'
因此,我们可以看到_arguments ... '*::options:->options'
从
$words
$line
中删除了一些部分。快速的解决方法将遵循:
使用
_arguments
使用
->
notement²(因为_arguments
$words
)。
使用
compset
强迫修改
$words
(和
$CURRENT
_arguments
.。
_arguments
上文的一些注释:从
--- _my-cli.orig
+++ _my-cli
@@ -1,5 +1,9 @@
#compdef my-cli
+# _arguments documentation says this: ³
+local context state state_descr line ret=1
+local -A opt_args
+
# Filter out global options -v / --verbose
local -a filtered_words
filtered_words=("${(@)words:#(-v|--verbose)}")
@@ -14,6 +18,8 @@
'2:action:->action' \
'*::options:->options'
+: 'XXX*>' ${(q)words}
+: 'XXX*=' ${(q)line}
case "${state}" in
subcmd)
_values 'subcommand' \
@@ -35,9 +41,13 @@
;;
options)
- case "${words[2]}" in
+ : 'XXX*>' ${(q)words}
+ : 'XXX*=' ${(q)line}
+ compset -n 2
+ : 'XXX*>' ${(q)words}
+ case "${line[1]}" in
macos)
- case "${words[3]}" in
+ case "${line[2]}" in
find-unencrypted-volumes)
_arguments \
'-h[show help message and exit]:show help message and exit'
_arguments ... '*::options:->options'
):
$words
...
在消息前有两个结肠,“特殊数组”和“当前特殊参数”单词被修改以在执行或评估操作时仅参考正常参数。
_arguments
notations,请使用*::MESSAGE:ACTION
检查命令行元素
在ZSH手册中的在动作的性能中,数组“行”将设置为命令行的正常参数,即命令名称后的命令行中的单词不包括所有选项及其参数。
$line
是什么(来自'Specs:Actions
'的底部附近):
_arguments
这些声明在ZSH手册中(摘自
->
,'Specs:actions',
$line
):
在$ state和$ state_descr中,_arguments还设置了如下所述的全局参数“上下文”,“ line”和“ opt_args”,并且不会重置对特殊参数(例如前缀和单词)所做的任何更改。 这使调用函数可以选择重置这些参数或在其中传播更改。
函数呼叫_arguments至少一个包含一个操作_arguments
的函数必须声明适当的本地参数:
+local context state state_descr line
这里是以上整个代码:
local
在将来添加选项时,检查the theckile是脆弱的。因此,这是一个实现,避免了使用
_arguments
的实现,使用->string
更多,然后筑巢->string
用于命令,然后将其嵌套。
local context state state_descr line
typeset -A opt_args