Coverage for typer/_completion_classes.py: 100%
109 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-09 18:26 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-09 18:26 +0000
1import os 1habcdefg
2import re 1habcdefg
3import sys 1habcdefg
4from typing import Any, Dict, List, Tuple 1habcdefg
6import click 1habcdefg
7import click.parser 1habcdefg
8import click.shell_completion 1habcdefg
10from ._completion_shared import ( 1habcdefg
11 COMPLETION_SCRIPT_BASH,
12 COMPLETION_SCRIPT_FISH,
13 COMPLETION_SCRIPT_POWER_SHELL,
14 COMPLETION_SCRIPT_ZSH,
15 Shells,
16)
18try: 1habcdefg
19 import shellingham 1habcdefg
20except ImportError: # pragma: no cover
21 shellingham = None
24class BashComplete(click.shell_completion.BashComplete): 1habcdefg
25 name = Shells.bash.value 1habcdefg
26 source_template = COMPLETION_SCRIPT_BASH 1habcdefg
28 def source_vars(self) -> Dict[str, Any]: 1habcdefg
29 return { 1abcdefg
30 "complete_func": self.func_name,
31 "autocomplete_var": self.complete_var,
32 "prog_name": self.prog_name,
33 }
35 def get_completion_args(self) -> Tuple[List[str], str]: 1habcdefg
36 cwords = click.parser.split_arg_string(os.environ["COMP_WORDS"]) 1habcdefg
37 cword = int(os.environ["COMP_CWORD"]) 1habcdefg
38 args = cwords[1:cword] 1habcdefg
40 try: 1habcdefg
41 incomplete = cwords[cword] 1habcdefg
42 except IndexError: 1habcdefg
43 incomplete = "" 1habcdefg
45 return args, incomplete 1habcdefg
47 def format_completion(self, item: click.shell_completion.CompletionItem) -> str: 1habcdefg
48 # TODO: Explore replicating the new behavior from Click, with item types and
49 # triggering completion for files and directories
50 # return f"{item.type},{item.value}"
51 return f"{item.value}" 1habcdefg
53 def complete(self) -> str: 1habcdefg
54 args, incomplete = self.get_completion_args() 1habcdefg
55 completions = self.get_completions(args, incomplete) 1habcdefg
56 out = [self.format_completion(item) for item in completions] 1habcdefg
57 return "\n".join(out) 1habcdefg
60class ZshComplete(click.shell_completion.ZshComplete): 1habcdefg
61 name = Shells.zsh.value 1habcdefg
62 source_template = COMPLETION_SCRIPT_ZSH 1habcdefg
64 def source_vars(self) -> Dict[str, Any]: 1habcdefg
65 return { 1abcdefg
66 "complete_func": self.func_name,
67 "autocomplete_var": self.complete_var,
68 "prog_name": self.prog_name,
69 }
71 def get_completion_args(self) -> Tuple[List[str], str]: 1habcdefg
72 completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") 1habcdefg
73 cwords = click.parser.split_arg_string(completion_args) 1habcdefg
74 args = cwords[1:] 1habcdefg
75 if args and not completion_args.endswith(" "): 1habcdefg
76 incomplete = args[-1] 1habcdefg
77 args = args[:-1] 1habcdefg
78 else:
79 incomplete = "" 1habcdefg
80 return args, incomplete 1habcdefg
82 def format_completion(self, item: click.shell_completion.CompletionItem) -> str: 1habcdefg
83 def escape(s: str) -> str: 1habcdefg
84 return ( 1abcdefg
85 s.replace('"', '""')
86 .replace("'", "''")
87 .replace("$", "\\$")
88 .replace("`", "\\`")
89 )
91 # TODO: Explore replicating the new behavior from Click, pay attention to
92 # the difference with and without escape
93 # return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}"
94 if item.help: 1habcdefg
95 return f'"{escape(item.value)}":"{escape(item.help)}"' 1habcdefg
96 else:
97 return f'"{escape(item.value)}"' 1habcdefg
99 def complete(self) -> str: 1habcdefg
100 args, incomplete = self.get_completion_args() 1habcdefg
101 completions = self.get_completions(args, incomplete) 1habcdefg
102 res = [self.format_completion(item) for item in completions] 1habcdefg
103 if res: 1habcdefg
104 args_str = "\n".join(res) 1habcdefg
105 return f"_arguments '*: :(({args_str}))'" 1habcdefg
106 else:
107 return "_files" 1habcdefg
110class FishComplete(click.shell_completion.FishComplete): 1habcdefg
111 name = Shells.fish.value 1habcdefg
112 source_template = COMPLETION_SCRIPT_FISH 1habcdefg
114 def source_vars(self) -> Dict[str, Any]: 1habcdefg
115 return { 1abcdefg
116 "complete_func": self.func_name,
117 "autocomplete_var": self.complete_var,
118 "prog_name": self.prog_name,
119 }
121 def get_completion_args(self) -> Tuple[List[str], str]: 1habcdefg
122 completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") 1habcdefg
123 cwords = click.parser.split_arg_string(completion_args) 1habcdefg
124 args = cwords[1:] 1habcdefg
125 if args and not completion_args.endswith(" "): 1habcdefg
126 incomplete = args[-1] 1habcdefg
127 args = args[:-1] 1habcdefg
128 else:
129 incomplete = "" 1habcdefg
130 return args, incomplete 1habcdefg
132 def format_completion(self, item: click.shell_completion.CompletionItem) -> str: 1habcdefg
133 # TODO: Explore replicating the new behavior from Click, pay attention to
134 # the difference with and without formatted help
135 # if item.help:
136 # return f"{item.type},{item.value}\t{item.help}"
138 # return f"{item.type},{item.value}
139 if item.help: 1habcdefg
140 formatted_help = re.sub(r"\s", " ", item.help) 1habcdefg
141 return f"{item.value}\t{formatted_help}" 1habcdefg
142 else:
143 return f"{item.value}" 1habcdefg
145 def complete(self) -> str: 1habcdefg
146 complete_action = os.getenv("_TYPER_COMPLETE_FISH_ACTION", "") 1habcdefg
147 args, incomplete = self.get_completion_args() 1habcdefg
148 completions = self.get_completions(args, incomplete) 1habcdefg
149 show_args = [self.format_completion(item) for item in completions] 1habcdefg
150 if complete_action == "get-args": 1habcdefg
151 if show_args: 1habcdefg
152 return "\n".join(show_args) 1habcdefg
153 elif complete_action == "is-args": 1habcdefg
154 if show_args: 1habcdefg
155 # Activate complete args (no files)
156 sys.exit(0) 1habcdefg
157 else:
158 # Deactivate complete args (allow files)
159 sys.exit(1) 1habcdefg
160 return "" # pragma: no cover
163class PowerShellComplete(click.shell_completion.ShellComplete): 1habcdefg
164 name = Shells.powershell.value 1habcdefg
165 source_template = COMPLETION_SCRIPT_POWER_SHELL 1habcdefg
167 def source_vars(self) -> Dict[str, Any]: 1habcdefg
168 return { 1abcdefg
169 "complete_func": self.func_name,
170 "autocomplete_var": self.complete_var,
171 "prog_name": self.prog_name,
172 }
174 def get_completion_args(self) -> Tuple[List[str], str]: 1habcdefg
175 completion_args = os.getenv("_TYPER_COMPLETE_ARGS", "") 1habcdefg
176 incomplete = os.getenv("_TYPER_COMPLETE_WORD_TO_COMPLETE", "") 1habcdefg
177 cwords = click.parser.split_arg_string(completion_args) 1habcdefg
178 args = cwords[1:-1] if incomplete else cwords[1:] 1habcdefg
179 return args, incomplete 1habcdefg
181 def format_completion(self, item: click.shell_completion.CompletionItem) -> str: 1habcdefg
182 return f"{item.value}:::{item.help or ' '}" 1habcdefg
185def completion_init() -> None: 1habcdefg
186 click.shell_completion.add_completion_class(BashComplete, Shells.bash.value) 1habcdefg
187 click.shell_completion.add_completion_class(ZshComplete, Shells.zsh.value) 1habcdefg
188 click.shell_completion.add_completion_class(FishComplete, Shells.fish.value) 1habcdefg
189 click.shell_completion.add_completion_class( 1habcdefg
190 PowerShellComplete, Shells.powershell.value
191 )
192 click.shell_completion.add_completion_class(PowerShellComplete, Shells.pwsh.value) 1habcdefg