|
1
|
""" |
|
2
|
Shell completions — generate tab-completion scripts for bash, zsh, and fish. |
|
3
|
|
|
4
|
Usage: |
|
5
|
Print the eval line to add to your shell rc file: |
|
6
|
navegador completions bash |
|
7
|
navegador completions zsh |
|
8
|
navegador completions fish |
|
9
|
|
|
10
|
Install automatically: |
|
11
|
navegador completions bash --install |
|
12
|
navegador completions zsh --install |
|
13
|
navegador completions fish --install |
|
14
|
""" |
|
15
|
|
|
16
|
from __future__ import annotations |
|
17
|
|
|
18
|
from pathlib import Path |
|
19
|
|
|
20
|
SUPPORTED_SHELLS = ["bash", "zsh", "fish"] |
|
21
|
|
|
22
|
# The env-var source command for each shell |
|
23
|
_SOURCE_COMMANDS: dict[str, str] = { |
|
24
|
"bash": "_NAVEGADOR_COMPLETE=bash_source navegador", |
|
25
|
"zsh": "_NAVEGADOR_COMPLETE=zsh_source navegador", |
|
26
|
"fish": "_NAVEGADOR_COMPLETE=fish_source navegador", |
|
27
|
} |
|
28
|
|
|
29
|
# The eval/source wrapper for each shell |
|
30
|
_EVAL_LINES: dict[str, str] = { |
|
31
|
"bash": 'eval "$(_NAVEGADOR_COMPLETE=bash_source navegador)"', |
|
32
|
"zsh": 'eval "$(_NAVEGADOR_COMPLETE=zsh_source navegador)"', |
|
33
|
"fish": "_NAVEGADOR_COMPLETE=fish_source navegador | source", |
|
34
|
} |
|
35
|
|
|
36
|
# Default rc file paths for each shell (relative to $HOME) |
|
37
|
_RC_PATHS: dict[str, str] = { |
|
38
|
"bash": "~/.bashrc", |
|
39
|
"zsh": "~/.zshrc", |
|
40
|
"fish": "~/.config/fish/config.fish", |
|
41
|
} |
|
42
|
|
|
43
|
|
|
44
|
def get_eval_line(shell: str) -> str: |
|
45
|
"""Return the eval/source line to add to the shell rc file. |
|
46
|
|
|
47
|
Raises ValueError for unsupported shells. |
|
48
|
""" |
|
49
|
if shell not in SUPPORTED_SHELLS: |
|
50
|
raise ValueError( |
|
51
|
f"Unsupported shell: {shell!r}. Choose from: {', '.join(SUPPORTED_SHELLS)}" |
|
52
|
) |
|
53
|
return _EVAL_LINES[shell] |
|
54
|
|
|
55
|
|
|
56
|
def get_rc_path(shell: str) -> str: |
|
57
|
"""Return the default rc file path (unexpanded) for *shell*. |
|
58
|
|
|
59
|
Raises ValueError for unsupported shells. |
|
60
|
""" |
|
61
|
if shell not in SUPPORTED_SHELLS: |
|
62
|
raise ValueError( |
|
63
|
f"Unsupported shell: {shell!r}. Choose from: {', '.join(SUPPORTED_SHELLS)}" |
|
64
|
) |
|
65
|
return _RC_PATHS[shell] |
|
66
|
|
|
67
|
|
|
68
|
def get_install_instruction(shell: str) -> str: |
|
69
|
"""Return a human-readable instruction for adding completions to *shell*.""" |
|
70
|
if shell not in SUPPORTED_SHELLS: |
|
71
|
raise ValueError( |
|
72
|
f"Unsupported shell: {shell!r}. Choose from: {', '.join(SUPPORTED_SHELLS)}" |
|
73
|
) |
|
74
|
rc = _RC_PATHS[shell] |
|
75
|
line = _EVAL_LINES[shell] |
|
76
|
return f"Add the following line to {rc}:\n\n {line}" |
|
77
|
|
|
78
|
|
|
79
|
def install_completion(shell: str, rc_path: str | None = None) -> Path: |
|
80
|
"""Append the completion eval line to the shell rc file. |
|
81
|
|
|
82
|
Args: |
|
83
|
shell: One of 'bash', 'zsh', 'fish'. |
|
84
|
rc_path: Override the default rc file path. Tilde-expansion is applied. |
|
85
|
|
|
86
|
Returns: |
|
87
|
The Path of the file that was written to. |
|
88
|
|
|
89
|
Raises: |
|
90
|
ValueError: For unsupported shells. |
|
91
|
""" |
|
92
|
if shell not in SUPPORTED_SHELLS: |
|
93
|
raise ValueError( |
|
94
|
f"Unsupported shell: {shell!r}. Choose from: {', '.join(SUPPORTED_SHELLS)}" |
|
95
|
) |
|
96
|
|
|
97
|
target = Path(rc_path or _RC_PATHS[shell]).expanduser() |
|
98
|
line = _EVAL_LINES[shell] |
|
99
|
|
|
100
|
# Idempotent: don't append if the line is already present |
|
101
|
if target.exists(): |
|
102
|
existing = target.read_text() |
|
103
|
if line in existing: |
|
104
|
return target |
|
105
|
|
|
106
|
target.parent.mkdir(parents=True, exist_ok=True) |
|
107
|
with target.open("a") as fh: |
|
108
|
fh.write(f"\n# navegador shell completion\n{line}\n") |
|
109
|
|
|
110
|
return target |
|
111
|
|