Source code for django_typer.shells.zsh
import os
import typing as t
from functools import cached_property
from pathlib import Path
from click.shell_completion import CompletionItem
from . import DjangoTyperShellCompleter
[docs]
class ZshComplete(DjangoTyperShellCompleter):
"""
This completer class supports Zsh_. Completion scripts are installed to the
``.zfunc`` directory in the user's home directory. Style and completion
initialization instructions are added to the user's ``.zshrc`` file if needed.
Returned suggestions are delimited by newlines. Each suggestion is on three lines:
* The first line is the type of the completion.
* The second line is the value of the completion.
* The third line is the help text for the completion.
See also:
https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
"""
name = "zsh"
"""
shell executable.
"""
template = "shell_complete/zsh.sh"
"""
The template used to render the zsh completion script.
"""
supports_scripts = True
"""
The zsh completer supports script invocations.
"""
color = False
"""
Zsh_ does support ansi control codes in completion suggestions, but we disable them
by default.
"""
def get_user_profile(self) -> Path:
"""
Get the user's .zshrc file. It is located in the user's home directory by
default unless the ``ZDOTDIR`` environment variable is set.
"""
return Path(os.environ.get("ZDOTDIR", Path.home())) / ".zshrc"
@cached_property
def install_dir(self) -> Path:
"""
The directory where completer scripts will be installed.
"""
install_dir = self.get_user_profile().parent / ".zfunc"
install_dir.mkdir(parents=True, exist_ok=True)
return install_dir
def format_completion(self, item: CompletionItem) -> str:
hlp = self.process_rich_text(item.help.replace("\n", " ")) if item.help else "_"
return f"{item.type}\n{self.process_rich_text(item.value)}\n{hlp}"
def install(self, prompt: bool = True) -> t.List[Path]:
assert self.prog_name
zshrc = self.get_user_profile()
zshrc_source = ""
start_line = 0
if zshrc.is_file():
zshrc_source = zshrc.read_text()
start_line = zshrc_source.count("\n") + 2
additions = ""
if "fpath" not in zshrc_source:
additions += f"if type brew &>/dev/null; then{os.linesep}"
additions += (
f"\tfpath=(~/.zfunc $(brew --prefix)/share/zsh-completions $fpath)"
f"{os.linesep}"
)
additions += f"else{os.linesep}"
additions += f"\tfpath=(~/.zfunc $fpath){os.linesep}"
additions += f"fi{os.linesep}{os.linesep}"
if "compinit" not in zshrc_source:
additions += f"autoload -Uz compinit{os.linesep}"
additions += f"compinit{os.linesep}"
style = (
f"zstyle ':completion:*:*:{self.prog_name}:*' menu select"
if self.is_installed
else "zstyle ':completion:*' menu select"
)
if style not in zshrc_source:
additions += f"{style}{os.linesep}"
edited = []
script = self.install_dir / f"_{self.prog_name}"
if additions:
if self.prompt(
prompt=prompt,
source=additions,
file=zshrc,
start_line=start_line,
):
Path.home().mkdir(parents=True, exist_ok=True)
with open(zshrc, "a") as zrc_file:
zrc_file.write(f"{os.linesep}{additions}")
edited.append(zshrc)
source = self.source()
if self.prompt(prompt=prompt, source=source, file=script, start_line=0):
script.write_text(self.source())
edited.append(script)
return edited
def uninstall(self):
script = self.install_dir / f"_{self.prog_name}"
if script.is_file():
script.unlink()
zshrc = self.get_user_profile()
if zshrc.is_file():
zshrc_source = zshrc.read_text()
zshrc.write_text(
zshrc_source.replace(
f"zstyle ':completion:*:*:{self.prog_name}:*' menu select\n", ""
)
)