collect_completion_arguments,
finalize_completion_bash,
finalize_completion_fish,
+ finalize_completion_zsh,
format_bytes,
parse_config,
summary,
print(finalize_completion_bash(completion_args, resources))
elif args.shell_completion == ShellCompletion.fish:
print(finalize_completion_fish(completion_args, resources))
+ elif args.shell_completion == ShellCompletion.zsh:
+ print(finalize_completion_zsh(completion_args, resources))
def expand_specifier(s: str) -> str:
none = enum.auto()
bash = enum.auto()
fish = enum.auto()
+ zsh = enum.auto()
def __bool__(self) -> bool:
return self != ShellCompletion.none
else:
return "-f"
+ def to_zsh(self) -> str:
+ if self == CompGen.files:
+ return ":path:_files -/"
+ elif self == CompGen.dirs:
+ return ":directory:_files -f"
+ else:
+ return ""
+
+
@dataclasses.dataclass(frozen=True)
class ConfigSetting:
dest: str
c.write(option.compgen.to_fish())
c.write("\n")
return c.getvalue()
+
+
+def finalize_completion_zsh(options: list[CompletionItem], resources: Path) -> str:
+ def to_zsh_array(name: str, entries: Iterable[str]) -> str:
+ return f"declare -a {name.replace('-', '_')}=(" + " ".join(shlex.quote(str(e)) for e in entries) + ")"
+
+ completion = resources / "completion.zsh"
+
+ with io.StringIO() as c:
+ c.write("#compdef mkosi\n")
+ c.write("# SPDX-License-Identifier: LGPL-2.1-or-later\n\n")
+
+ c.write(to_zsh_array("_mkosi_verbs", [str(v) for v in Verb]))
+ c.write("\n\n")
+
+
+ c.write(completion.read_text())
+ c.write("\n")
+
+ c.write("_arguments -s \\\n")
+ c.write(" '(- *)'{-h,--help}'[Show this help]' \\\n")
+ c.write(" '(- *)--version[Show package version]' \\\n")
+
+ for option in options:
+ if not option.short and not option.long:
+ continue
+
+ posix = option.help and "'" in option.help
+ open_quote = "$'" if posix else "'"
+ if option.short and option.long:
+ c.write(f" '({option.short} {option.long})'{{{option.short},{option.long}}}{open_quote}")
+ else:
+ c.write(f" {open_quote}{option.short or option.long}")
+
+ if option.help:
+ help = option.help.replace("'", r"\'")
+ c.write(f"[{help}]")
+ if option.choices:
+ # TODO: maybe use metavar here? At least for me it's not shown, though
+ c.write(":arg:(")
+ c.write(" ".join(option.choices))
+ c.write(")")
+ c.write(option.compgen.to_zsh())
+ c.write("' \\\n")
+
+ c.write(" '*::mkosi verb:_mkosi_verb'\n\n")
+
+ return c.getvalue()
--- /dev/null
+_mkosi_verb(){
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'mkosi verb' _mkosi_verbs
+ else
+ local curcontext="$curcontext"
+ cmd="${${_mkosi_verbs[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ if (( $+functions[_mkosi_$cmd] )); then
+ _mkosi_$cmd
+ else
+ _message "no more options"
+ fi
+ else
+ _message "unknown mkosi verb: $words[1]"
+ fi
+ fi
+}