@@ -5,11 +5,14 @@ _comp_cmd_ssh_keygen()
55 local cur prev words cword comp_args
66 _comp_initialize -n := -- " $@ " || return
77
8+ local IFS=$' \t\n ' # for ${words[*]}
9+ local noargopts=' !(-*|*[ aCIJjMNPSVWzbEFRDwfGKsTmnOrtY]*)'
10+ # shellcheck disable=SC2254
811 case $prev in
9- -* [aCIJjMNPSVWz])
12+ -${noargopts} [aCIJjMNPSVWz])
1013 return
1114 ;;
12- -* b)
15+ -${noargopts} b)
1316 local -a sizes=()
1417 case " ${words[*]} " in
1518 * " -t dsa" ? ( * ))
@@ -26,28 +29,28 @@ _comp_cmd_ssh_keygen()
2629 _comp_compgen -- -W ' "${sizes[@]}"'
2730 return
2831 ;;
29- -* E)
32+ -${noargopts} E)
3033 _comp_compgen -- -W ' md5 sha256'
3134 return
3235 ;;
33- -* [FR])
36+ -${noargopts} [FR])
3437 # TODO: trim this down to actual entries in known hosts files
3538 _comp_compgen_known_hosts -- " $cur "
3639 return
3740 ;;
38- -* [Dw])
41+ -${noargopts} [Dw])
3942 _comp_compgen_filedir so
4043 return
4144 ;;
42- -* [fGKsT])
45+ -${noargopts} [fGKsT])
4346 _comp_compgen_filedir
4447 return
4548 ;;
46- -* m)
49+ -${noargopts} m)
4750 _comp_compgen -- -W ' PEM PKCS8 RFC4716'
4851 return
4952 ;;
50- -* n)
53+ -${noargopts} n)
5154 [[ ${words[*]} != * \ -* Y\ * ]] || return
5255 if [[ ${words[*]} == * \ -* h\ * ]]; then
5356 _comp_compgen_known_hosts -- " ${cur##* ,} "
@@ -58,19 +61,41 @@ _comp_cmd_ssh_keygen()
5861 fi
5962 return
6063 ;;
61- -* O)
64+ -${noargopts} O)
6265 if [[ $cur != * = * ]]; then
63- _comp_compgen -- -W ' clear critical: extension: force-command=
64- no-agent-forwarding no-port-forwarding no-pty no-user-rc
65- no-x11-forwarding permit-agent-forwarding
66- permit-port-forwarding permit-pty permit-user-rc
67- permit-X11-forwarding no-touch-required source-address=
68- verify-required
69-
70- lines= start-line= checkpoint= memory= start= generator=
71-
72- application= challenge= device= no-touch-required resident
73- user= write-attestation='
66+ local -a opts=()
67+ case ${words[*]} in
68+ * \ -${noargopts} M\ * )
69+ opts=(
70+ lines= start-line= checkpoint= memory= start=
71+ generator=
72+ )
73+ ;;
74+ * \ -${noargopts} r\ * )
75+ opts=(hashalg=)
76+ ;;
77+ * \ -${noargopts} s\ * )
78+ opts=(
79+ clear critical: extension: force-command=
80+ no-agent-forwarding no-port-forwarding no-pty
81+ no-user-rc no-x11-forwarding permit-agent-forwarding
82+ permit-port-forwarding permit-pty permit-user-rc
83+ permit-X11-forwarding no-touch-required
84+ source-address= verify-required
85+ )
86+ ;;
87+ * \ -${noargopts} t\ + ([a-z0-9])-sk\ * )
88+ opts=(
89+ application= challenge= device= no-touch-required
90+ resident user= verify-required write-attestation=
91+ )
92+ ;;
93+ * \ -${noargopts} Y\ * )
94+ opts=(hashalg= print-pubkey verify-time)
95+ ;;
96+ esac
97+ (( ${# opts[@]} )) &&
98+ _comp_compgen -- -W ' "${opts[@]}"'
7499
75100 [[ ${COMPREPLY-} == * [:= ] ]] && compopt -o nospace
76101 _comp_ltrim_colon_completions " $cur "
@@ -90,15 +115,28 @@ _comp_cmd_ssh_keygen()
90115 user=* )
91116 _comp_compgen -c " ${cur#* =} " -- -u
92117 ;;
118+ hashalg=* )
119+ local -a args=()
120+ case ${words[*]} in
121+ * \ -* Y\ * )
122+ args=(sha256 sha512)
123+ ;;
124+ * \ -* r\ * )
125+ args=(sha1 sha256)
126+ ;;
127+ esac
128+ (( ${# args[@]} )) &&
129+ _comp_compgen -c " ${cur#* =} " -- -W ' "${args[@]}"'
130+ ;;
93131 esac
94132 fi
95133 return
96134 ;;
97- -* r)
98- [[ ${words[*]} != * \ -* Y\ * ]] || _comp_compgen_filedir
135+ -${noargopts} r)
136+ [[ ${words[*]} != * \ -${noargopts} Y\ * ]] || _comp_compgen_filedir
99137 return
100138 ;;
101- -* t)
139+ -${noargopts} t)
102140 # Prefer `ssh` from same dir for resolving options, etc
103141 local pathcmd protocols
104142 pathcmd=$( type -P -- " $1 " ) && local PATH=${pathcmd%/* } :$PATH
@@ -110,7 +148,7 @@ _comp_cmd_ssh_keygen()
110148 _comp_compgen -- -W " $types "
111149 return
112150 ;;
113- -* Y)
151+ -${noargopts} Y)
114152 _comp_compgen -- -W ' find-principals check-novalidate sign verify'
115153 return
116154 ;;
@@ -122,7 +160,7 @@ _comp_cmd_ssh_keygen()
122160 _comp_compgen_help -- " -?" # OpenSSH < 7
123161 fi
124162
125- if [[ ${words[*]} == * \ -* s\ * ]]; then
163+ if [[ ${words[*]} == * \ -${noargopts} s\ * ]]; then
126164 _comp_compgen -a filedir pub
127165 fi
128166} &&
0 commit comments