Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/argcomplete/__init__.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 # Copyright 2012-2019, Andrey Kislyuk and argcomplete contributors. | |
2 # Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info. | |
3 | |
4 from __future__ import absolute_import, division, print_function, unicode_literals | |
5 | |
6 import os, sys, argparse, contextlib | |
7 from . import completers, my_shlex as shlex | |
8 from .compat import USING_PYTHON2, str, sys_encoding, ensure_str, ensure_bytes | |
9 from .completers import FilesCompleter, SuppressCompleter | |
10 from .my_argparse import IntrospectiveArgumentParser, action_is_satisfied, action_is_open, action_is_greedy | |
11 from .shell_integration import shellcode | |
12 | |
13 _DEBUG = "_ARC_DEBUG" in os.environ | |
14 | |
15 debug_stream = sys.stderr | |
16 | |
17 def debug(*args): | |
18 if _DEBUG: | |
19 if USING_PYTHON2: | |
20 # debug_stream has to be binary mode in Python 2. | |
21 # Attempting to write unicode directly uses the default ascii conversion. | |
22 # Convert any unicode to bytes, leaving non-string input alone. | |
23 args = [ensure_bytes(x) if isinstance(x, str) else x for x in args] | |
24 print(file=debug_stream, *args) | |
25 | |
26 BASH_FILE_COMPLETION_FALLBACK = 79 | |
27 BASH_DIR_COMPLETION_FALLBACK = 80 | |
28 | |
29 safe_actions = (argparse._StoreAction, | |
30 argparse._StoreConstAction, | |
31 argparse._StoreTrueAction, | |
32 argparse._StoreFalseAction, | |
33 argparse._AppendAction, | |
34 argparse._AppendConstAction, | |
35 argparse._CountAction) | |
36 | |
37 @contextlib.contextmanager | |
38 def mute_stdout(): | |
39 stdout = sys.stdout | |
40 sys.stdout = open(os.devnull, "w") | |
41 try: | |
42 yield | |
43 finally: | |
44 sys.stdout = stdout | |
45 | |
46 @contextlib.contextmanager | |
47 def mute_stderr(): | |
48 stderr = sys.stderr | |
49 sys.stderr = open(os.devnull, "w") | |
50 try: | |
51 yield | |
52 finally: | |
53 sys.stderr.close() | |
54 sys.stderr = stderr | |
55 | |
56 class ArgcompleteException(Exception): | |
57 pass | |
58 | |
59 def split_line(line, point=None): | |
60 if point is None: | |
61 point = len(line) | |
62 lexer = shlex.shlex(line, posix=True) | |
63 lexer.whitespace_split = True | |
64 lexer.wordbreaks = os.environ.get("_ARGCOMPLETE_COMP_WORDBREAKS", "") | |
65 words = [] | |
66 | |
67 def split_word(word): | |
68 # TODO: make this less ugly | |
69 point_in_word = len(word) + point - lexer.instream.tell() | |
70 if isinstance(lexer.state, (str, bytes)) and lexer.state in lexer.whitespace: | |
71 point_in_word += 1 | |
72 if point_in_word > len(word): | |
73 debug("In trailing whitespace") | |
74 words.append(word) | |
75 word = "" | |
76 prefix, suffix = word[:point_in_word], word[point_in_word:] | |
77 prequote = "" | |
78 # posix | |
79 if lexer.state is not None and lexer.state in lexer.quotes: | |
80 prequote = lexer.state | |
81 # non-posix | |
82 # if len(prefix) > 0 and prefix[0] in lexer.quotes: | |
83 # prequote, prefix = prefix[0], prefix[1:] | |
84 | |
85 return prequote, prefix, suffix, words, lexer.last_wordbreak_pos | |
86 | |
87 while True: | |
88 try: | |
89 word = lexer.get_token() | |
90 if word == lexer.eof: | |
91 # TODO: check if this is ever unsafe | |
92 # raise ArgcompleteException("Unexpected end of input") | |
93 return "", "", "", words, None | |
94 if lexer.instream.tell() >= point: | |
95 debug("word", word, "split, lexer state: '{s}'".format(s=lexer.state)) | |
96 return split_word(word) | |
97 words.append(word) | |
98 except ValueError: | |
99 debug("word", lexer.token, "split (lexer stopped, state: '{s}')".format(s=lexer.state)) | |
100 if lexer.instream.tell() >= point: | |
101 return split_word(lexer.token) | |
102 else: | |
103 msg = ("Unexpected internal state. " | |
104 "Please report this bug at https://github.com/kislyuk/argcomplete/issues.") | |
105 raise ArgcompleteException(msg) | |
106 | |
107 def default_validator(completion, prefix): | |
108 return completion.startswith(prefix) | |
109 | |
110 class CompletionFinder(object): | |
111 """ | |
112 Inherit from this class if you wish to override any of the stages below. Otherwise, use | |
113 ``argcomplete.autocomplete()`` directly (it's a convenience instance of this class). It has the same signature as | |
114 :meth:`CompletionFinder.__call__()`. | |
115 """ | |
116 def __init__(self, argument_parser=None, always_complete_options=True, exclude=None, validator=None, | |
117 print_suppressed=False, default_completer=FilesCompleter(), append_space=None): | |
118 self._parser = argument_parser | |
119 self.always_complete_options = always_complete_options | |
120 self.exclude = exclude | |
121 if validator is None: | |
122 validator = default_validator | |
123 self.validator = validator | |
124 self.print_suppressed = print_suppressed | |
125 self.completing = False | |
126 self._display_completions = {} | |
127 self.default_completer = default_completer | |
128 if append_space is None: | |
129 append_space = os.environ.get("_ARGCOMPLETE_SUPPRESS_SPACE") != "1" | |
130 self.append_space = append_space | |
131 | |
132 def __call__(self, argument_parser, always_complete_options=True, exit_method=os._exit, output_stream=None, | |
133 exclude=None, validator=None, print_suppressed=False, append_space=None, | |
134 default_completer=FilesCompleter()): | |
135 """ | |
136 :param argument_parser: The argument parser to autocomplete on | |
137 :type argument_parser: :class:`argparse.ArgumentParser` | |
138 :param always_complete_options: | |
139 Controls the autocompletion of option strings if an option string opening character (normally ``-``) has not | |
140 been entered. If ``True`` (default), both short (``-x``) and long (``--x``) option strings will be | |
141 suggested. If ``False``, no option strings will be suggested. If ``long``, long options and short options | |
142 with no long variant will be suggested. If ``short``, short options and long options with no short variant | |
143 will be suggested. | |
144 :type always_complete_options: boolean or string | |
145 :param exit_method: | |
146 Method used to stop the program after printing completions. Defaults to :meth:`os._exit`. If you want to | |
147 perform a normal exit that calls exit handlers, use :meth:`sys.exit`. | |
148 :type exit_method: callable | |
149 :param exclude: List of strings representing options to be omitted from autocompletion | |
150 :type exclude: iterable | |
151 :param validator: | |
152 Function to filter all completions through before returning (called with two string arguments, completion | |
153 and prefix; return value is evaluated as a boolean) | |
154 :type validator: callable | |
155 :param print_suppressed: | |
156 Whether or not to autocomplete options that have the ``help=argparse.SUPPRESS`` keyword argument set. | |
157 :type print_suppressed: boolean | |
158 :param append_space: | |
159 Whether to append a space to unique matches. The default is ``True``. | |
160 :type append_space: boolean | |
161 | |
162 .. note:: | |
163 If you are not subclassing CompletionFinder to override its behaviors, | |
164 use ``argcomplete.autocomplete()`` directly. It has the same signature as this method. | |
165 | |
166 Produces tab completions for ``argument_parser``. See module docs for more info. | |
167 | |
168 Argcomplete only executes actions if their class is known not to have side effects. Custom action classes can be | |
169 added to argcomplete.safe_actions, if their values are wanted in the ``parsed_args`` completer argument, or | |
170 their execution is otherwise desirable. | |
171 """ | |
172 self.__init__(argument_parser, always_complete_options=always_complete_options, exclude=exclude, | |
173 validator=validator, print_suppressed=print_suppressed, append_space=append_space, | |
174 default_completer=default_completer) | |
175 | |
176 if "_ARGCOMPLETE" not in os.environ: | |
177 # not an argument completion invocation | |
178 return | |
179 | |
180 global debug_stream | |
181 try: | |
182 debug_stream = os.fdopen(9, "w") | |
183 except: | |
184 debug_stream = sys.stderr | |
185 debug() | |
186 | |
187 if output_stream is None: | |
188 filename = os.environ.get("_ARGCOMPLETE_STDOUT_FILENAME") | |
189 if filename is not None: | |
190 debug("Using output file {}".format(filename)) | |
191 output_stream = open(filename, "wb") | |
192 | |
193 if output_stream is None: | |
194 try: | |
195 output_stream = os.fdopen(8, "wb") | |
196 except: | |
197 debug("Unable to open fd 8 for writing, quitting") | |
198 exit_method(1) | |
199 | |
200 # print("", stream=debug_stream) | |
201 # for v in "COMP_CWORD COMP_LINE COMP_POINT COMP_TYPE COMP_KEY _ARGCOMPLETE_COMP_WORDBREAKS COMP_WORDS".split(): | |
202 # print(v, os.environ[v], stream=debug_stream) | |
203 | |
204 ifs = os.environ.get("_ARGCOMPLETE_IFS", "\013") | |
205 if len(ifs) != 1: | |
206 debug("Invalid value for IFS, quitting [{v}]".format(v=ifs)) | |
207 exit_method(1) | |
208 | |
209 dfs = os.environ.get("_ARGCOMPLETE_DFS") | |
210 if dfs and len(dfs) != 1: | |
211 debug("Invalid value for DFS, quitting [{v}]".format(v=dfs)) | |
212 exit_method(1) | |
213 | |
214 comp_line = os.environ["COMP_LINE"] | |
215 comp_point = int(os.environ["COMP_POINT"]) | |
216 | |
217 comp_line = ensure_str(comp_line) | |
218 cword_prequote, cword_prefix, cword_suffix, comp_words, last_wordbreak_pos = split_line(comp_line, comp_point) | |
219 | |
220 # _ARGCOMPLETE is set by the shell script to tell us where comp_words | |
221 # should start, based on what we're completing. | |
222 # 1: <script> [args] | |
223 # 2: python <script> [args] | |
224 # 3: python -m <module> [args] | |
225 start = int(os.environ["_ARGCOMPLETE"]) - 1 | |
226 comp_words = comp_words[start:] | |
227 | |
228 if cword_prefix and cword_prefix[0] in self._parser.prefix_chars and "=" in cword_prefix: | |
229 # Special case for when the current word is "--optional=PARTIAL_VALUE". Give the optional to the parser. | |
230 comp_words.append(cword_prefix.split("=", 1)[0]) | |
231 | |
232 debug("\nLINE: {!r}".format(comp_line), | |
233 "\nPOINT: {!r}".format(comp_point), | |
234 "\nPREQUOTE: {!r}".format(cword_prequote), | |
235 "\nPREFIX: {!r}".format(cword_prefix), | |
236 "\nSUFFIX: {!r}".format(cword_suffix), | |
237 "\nWORDS:", comp_words) | |
238 | |
239 completions = self._get_completions(comp_words, cword_prefix, cword_prequote, last_wordbreak_pos) | |
240 | |
241 if dfs: | |
242 display_completions = {key_part: value.replace(ifs, " ") if value else "" | |
243 for key, value in self._display_completions.items() | |
244 for key_part in key} | |
245 completions = [dfs.join((key, display_completions.get(key) or "")) for key in completions] | |
246 | |
247 debug("\nReturning completions:", completions) | |
248 output_stream.write(ifs.join(completions).encode(sys_encoding)) | |
249 output_stream.flush() | |
250 debug_stream.flush() | |
251 exit_method(0) | |
252 | |
253 def _get_completions(self, comp_words, cword_prefix, cword_prequote, last_wordbreak_pos): | |
254 active_parsers = self._patch_argument_parser() | |
255 | |
256 parsed_args = argparse.Namespace() | |
257 self.completing = True | |
258 | |
259 if USING_PYTHON2: | |
260 # Python 2 argparse only properly works with byte strings. | |
261 comp_words = [ensure_bytes(word) for word in comp_words] | |
262 | |
263 try: | |
264 debug("invoking parser with", comp_words[1:]) | |
265 with mute_stderr(): | |
266 a = self._parser.parse_known_args(comp_words[1:], namespace=parsed_args) | |
267 debug("parsed args:", a) | |
268 except BaseException as e: | |
269 debug("\nexception", type(e), str(e), "while parsing args") | |
270 | |
271 self.completing = False | |
272 | |
273 if "--" in comp_words: | |
274 self.always_complete_options = False | |
275 | |
276 completions = self.collect_completions(active_parsers, parsed_args, cword_prefix, debug) | |
277 completions = self.filter_completions(completions) | |
278 completions = self.quote_completions(completions, cword_prequote, last_wordbreak_pos) | |
279 return completions | |
280 | |
281 def _patch_argument_parser(self): | |
282 """ | |
283 Since argparse doesn't support much introspection, we monkey-patch it to replace the parse_known_args method and | |
284 all actions with hooks that tell us which action was last taken or about to be taken, and let us have the parser | |
285 figure out which subparsers need to be activated (then recursively monkey-patch those). | |
286 We save all active ArgumentParsers to extract all their possible option names later. | |
287 """ | |
288 self.active_parsers = [] | |
289 self.visited_positionals = [] | |
290 | |
291 completer = self | |
292 | |
293 def patch(parser): | |
294 completer.visited_positionals.append(parser) | |
295 completer.active_parsers.append(parser) | |
296 | |
297 if isinstance(parser, IntrospectiveArgumentParser): | |
298 return | |
299 | |
300 classname = "MonkeyPatchedIntrospectiveArgumentParser" | |
301 if USING_PYTHON2: | |
302 classname = bytes(classname) | |
303 parser.__class__ = type(classname, (IntrospectiveArgumentParser, parser.__class__), {}) | |
304 | |
305 for action in parser._actions: | |
306 | |
307 if hasattr(action, "_orig_class"): | |
308 continue | |
309 | |
310 # TODO: accomplish this with super | |
311 class IntrospectAction(action.__class__): | |
312 def __call__(self, parser, namespace, values, option_string=None): | |
313 debug("Action stub called on", self) | |
314 debug("\targs:", parser, namespace, values, option_string) | |
315 debug("\torig class:", self._orig_class) | |
316 debug("\torig callable:", self._orig_callable) | |
317 | |
318 if not completer.completing: | |
319 self._orig_callable(parser, namespace, values, option_string=option_string) | |
320 elif issubclass(self._orig_class, argparse._SubParsersAction): | |
321 debug("orig class is a subparsers action: patching and running it") | |
322 patch(self._name_parser_map[values[0]]) | |
323 self._orig_callable(parser, namespace, values, option_string=option_string) | |
324 elif self._orig_class in safe_actions: | |
325 if not self.option_strings: | |
326 completer.visited_positionals.append(self) | |
327 | |
328 self._orig_callable(parser, namespace, values, option_string=option_string) | |
329 | |
330 action._orig_class = action.__class__ | |
331 action._orig_callable = action.__call__ | |
332 action.__class__ = IntrospectAction | |
333 | |
334 patch(self._parser) | |
335 | |
336 debug("Active parsers:", self.active_parsers) | |
337 debug("Visited positionals:", self.visited_positionals) | |
338 | |
339 return self.active_parsers | |
340 | |
341 def _get_subparser_completions(self, parser, cword_prefix): | |
342 def filter_aliases(aliases, prefix): | |
343 return tuple(x for x in aliases if x.startswith(prefix)) | |
344 | |
345 aliases_by_parser = {} | |
346 for key in parser.choices.keys(): | |
347 p = parser.choices[key] | |
348 aliases_by_parser.setdefault(p, []).append(key) | |
349 | |
350 for action in parser._get_subactions(): | |
351 subcmd_with_aliases = filter_aliases(aliases_by_parser[parser.choices[action.dest]], cword_prefix) | |
352 if subcmd_with_aliases: | |
353 self._display_completions[subcmd_with_aliases] = action.help | |
354 | |
355 completions = [subcmd for subcmd in parser.choices.keys() if subcmd.startswith(cword_prefix)] | |
356 return completions | |
357 | |
358 def _include_options(self, action, cword_prefix): | |
359 if len(cword_prefix) > 0 or self.always_complete_options is True: | |
360 return [ensure_str(opt) for opt in action.option_strings if ensure_str(opt).startswith(cword_prefix)] | |
361 long_opts = [ensure_str(opt) for opt in action.option_strings if len(opt) > 2] | |
362 short_opts = [ensure_str(opt) for opt in action.option_strings if len(opt) <= 2] | |
363 if self.always_complete_options == "long": | |
364 return long_opts if long_opts else short_opts | |
365 elif self.always_complete_options == "short": | |
366 return short_opts if short_opts else long_opts | |
367 return [] | |
368 | |
369 def _get_option_completions(self, parser, cword_prefix): | |
370 self._display_completions.update( | |
371 [[tuple(ensure_str(x) for x in action.option_strings | |
372 if ensure_str(x).startswith(cword_prefix)), action.help] | |
373 for action in parser._actions | |
374 if action.option_strings]) | |
375 | |
376 option_completions = [] | |
377 for action in parser._actions: | |
378 if not self.print_suppressed: | |
379 completer = getattr(action, "completer", None) | |
380 if isinstance(completer, SuppressCompleter) and completer.suppress(): | |
381 continue | |
382 if action.help == argparse.SUPPRESS: | |
383 continue | |
384 if not self._action_allowed(action, parser): | |
385 continue | |
386 if not isinstance(action, argparse._SubParsersAction): | |
387 option_completions += self._include_options(action, cword_prefix) | |
388 return option_completions | |
389 | |
390 @staticmethod | |
391 def _action_allowed(action, parser): | |
392 # Logic adapted from take_action in ArgumentParser._parse_known_args | |
393 # (members are saved by my_argparse.IntrospectiveArgumentParser) | |
394 for conflict_action in parser._action_conflicts.get(action, []): | |
395 if conflict_action in parser._seen_non_default_actions: | |
396 return False | |
397 return True | |
398 | |
399 def _complete_active_option(self, parser, next_positional, cword_prefix, parsed_args, completions): | |
400 debug("Active actions (L={l}): {a}".format(l=len(parser.active_actions), a=parser.active_actions)) | |
401 | |
402 isoptional = cword_prefix and cword_prefix[0] in parser.prefix_chars | |
403 optional_prefix = "" | |
404 greedy_actions = [x for x in parser.active_actions if action_is_greedy(x, isoptional)] | |
405 if greedy_actions: | |
406 assert len(greedy_actions) == 1, "expect at most 1 greedy action" | |
407 # This means the action will fail to parse if the word under the cursor is not given | |
408 # to it, so give it exclusive control over completions (flush previous completions) | |
409 debug("Resetting completions because", greedy_actions[0], "must consume the next argument") | |
410 self._display_completions = {} | |
411 completions = [] | |
412 elif isoptional: | |
413 if "=" in cword_prefix: | |
414 # Special case for when the current word is "--optional=PARTIAL_VALUE". | |
415 # The completer runs on PARTIAL_VALUE. The prefix is added back to the completions | |
416 # (and chopped back off later in quote_completions() by the COMP_WORDBREAKS logic). | |
417 optional_prefix, _, cword_prefix = cword_prefix.partition("=") | |
418 else: | |
419 # Only run completers if current word does not start with - (is not an optional) | |
420 return completions | |
421 | |
422 complete_remaining_positionals = False | |
423 # Use the single greedy action (if there is one) or all active actions. | |
424 for active_action in greedy_actions or parser.active_actions: | |
425 if not active_action.option_strings: # action is a positional | |
426 if action_is_open(active_action): | |
427 # Any positional arguments after this may slide down into this action | |
428 # if more arguments are added (since the user may not be done yet), | |
429 # so it is extremely difficult to tell which completers to run. | |
430 # Running all remaining completers will probably show more than the user wants | |
431 # but it also guarantees we won't miss anything. | |
432 complete_remaining_positionals = True | |
433 if not complete_remaining_positionals: | |
434 if action_is_satisfied(active_action) and not action_is_open(active_action): | |
435 debug("Skipping", active_action) | |
436 continue | |
437 | |
438 debug("Activating completion for", active_action, active_action._orig_class) | |
439 # completer = getattr(active_action, "completer", DefaultCompleter()) | |
440 completer = getattr(active_action, "completer", None) | |
441 | |
442 if completer is None: | |
443 if active_action.choices is not None and not isinstance(active_action, argparse._SubParsersAction): | |
444 completer = completers.ChoicesCompleter(active_action.choices) | |
445 elif not isinstance(active_action, argparse._SubParsersAction): | |
446 completer = self.default_completer | |
447 | |
448 if completer: | |
449 if isinstance(completer, SuppressCompleter) and completer.suppress(): | |
450 continue | |
451 | |
452 if callable(completer): | |
453 completions_from_callable = [c for c in completer( | |
454 prefix=cword_prefix, action=active_action, parser=parser, parsed_args=parsed_args) | |
455 if self.validator(c, cword_prefix)] | |
456 | |
457 if completions_from_callable: | |
458 completions += completions_from_callable | |
459 if isinstance(completer, completers.ChoicesCompleter): | |
460 self._display_completions.update( | |
461 [[(x,), active_action.help] for x in completions_from_callable]) | |
462 else: | |
463 self._display_completions.update( | |
464 [[(x,), ""] for x in completions_from_callable]) | |
465 else: | |
466 debug("Completer is not callable, trying the readline completer protocol instead") | |
467 for i in range(9999): | |
468 next_completion = completer.complete(cword_prefix, i) | |
469 if next_completion is None: | |
470 break | |
471 if self.validator(next_completion, cword_prefix): | |
472 self._display_completions.update({(next_completion,): ""}) | |
473 completions.append(next_completion) | |
474 if optional_prefix: | |
475 completions = [optional_prefix + "=" + completion for completion in completions] | |
476 debug("Completions:", completions) | |
477 return completions | |
478 | |
479 def collect_completions(self, active_parsers, parsed_args, cword_prefix, debug): | |
480 """ | |
481 Visits the active parsers and their actions, executes their completers or introspects them to collect their | |
482 option strings. Returns the resulting completions as a list of strings. | |
483 | |
484 This method is exposed for overriding in subclasses; there is no need to use it directly. | |
485 """ | |
486 completions = [] | |
487 | |
488 debug("all active parsers:", active_parsers) | |
489 active_parser = active_parsers[-1] | |
490 debug("active_parser:", active_parser) | |
491 if self.always_complete_options or (len(cword_prefix) > 0 and cword_prefix[0] in active_parser.prefix_chars): | |
492 completions += self._get_option_completions(active_parser, cword_prefix) | |
493 debug("optional options:", completions) | |
494 | |
495 next_positional = self._get_next_positional() | |
496 debug("next_positional:", next_positional) | |
497 | |
498 if isinstance(next_positional, argparse._SubParsersAction): | |
499 completions += self._get_subparser_completions(next_positional, cword_prefix) | |
500 | |
501 completions = self._complete_active_option(active_parser, next_positional, cword_prefix, parsed_args, | |
502 completions) | |
503 debug("active options:", completions) | |
504 debug("display completions:", self._display_completions) | |
505 | |
506 return completions | |
507 | |
508 def _get_next_positional(self): | |
509 """ | |
510 Get the next positional action if it exists. | |
511 """ | |
512 active_parser = self.active_parsers[-1] | |
513 last_positional = self.visited_positionals[-1] | |
514 | |
515 all_positionals = active_parser._get_positional_actions() | |
516 if not all_positionals: | |
517 return None | |
518 | |
519 if active_parser == last_positional: | |
520 return all_positionals[0] | |
521 | |
522 i = 0 | |
523 for i in range(len(all_positionals)): | |
524 if all_positionals[i] == last_positional: | |
525 break | |
526 | |
527 if i + 1 < len(all_positionals): | |
528 return all_positionals[i + 1] | |
529 | |
530 return None | |
531 | |
532 def filter_completions(self, completions): | |
533 """ | |
534 Ensures collected completions are Unicode text, de-duplicates them, and excludes those specified by ``exclude``. | |
535 Returns the filtered completions as an iterable. | |
536 | |
537 This method is exposed for overriding in subclasses; there is no need to use it directly. | |
538 """ | |
539 # On Python 2, we have to make sure all completions are unicode objects before we continue and output them. | |
540 # Otherwise, because python disobeys the system locale encoding and uses ascii as the default encoding, it will | |
541 # try to implicitly decode string objects using ascii, and fail. | |
542 completions = [ensure_str(c) for c in completions] | |
543 | |
544 # De-duplicate completions and remove excluded ones | |
545 if self.exclude is None: | |
546 self.exclude = set() | |
547 seen = set(self.exclude) | |
548 return [c for c in completions if c not in seen and not seen.add(c)] | |
549 | |
550 def quote_completions(self, completions, cword_prequote, last_wordbreak_pos): | |
551 """ | |
552 If the word under the cursor started with a quote (as indicated by a nonempty ``cword_prequote``), escapes | |
553 occurrences of that quote character in the completions, and adds the quote to the beginning of each completion. | |
554 Otherwise, escapes all characters that bash splits words on (``COMP_WORDBREAKS``), and removes portions of | |
555 completions before the first colon if (``COMP_WORDBREAKS``) contains a colon. | |
556 | |
557 If there is only one completion, and it doesn't end with a **continuation character** (``/``, ``:``, or ``=``), | |
558 adds a space after the completion. | |
559 | |
560 This method is exposed for overriding in subclasses; there is no need to use it directly. | |
561 """ | |
562 special_chars = "\\" | |
563 # If the word under the cursor was quoted, escape the quote char. | |
564 # Otherwise, escape all special characters and specially handle all COMP_WORDBREAKS chars. | |
565 if cword_prequote == "": | |
566 # Bash mangles completions which contain characters in COMP_WORDBREAKS. | |
567 # This workaround has the same effect as __ltrim_colon_completions in bash_completion | |
568 # (extended to characters other than the colon). | |
569 if last_wordbreak_pos: | |
570 completions = [c[last_wordbreak_pos + 1:] for c in completions] | |
571 special_chars += "();<>|&!`$* \t\n\"'" | |
572 elif cword_prequote == '"': | |
573 special_chars += '"`$!' | |
574 | |
575 if os.environ.get("_ARGCOMPLETE_SHELL") in ("tcsh", "fish"): | |
576 # tcsh and fish escapes special characters itself. | |
577 special_chars = "" | |
578 elif cword_prequote == "'": | |
579 # Nothing can be escaped in single quotes, so we need to close | |
580 # the string, escape the single quote, then open a new string. | |
581 special_chars = "" | |
582 completions = [c.replace("'", r"'\''") for c in completions] | |
583 | |
584 for char in special_chars: | |
585 completions = [c.replace(char, "\\" + char) for c in completions] | |
586 | |
587 if self.append_space: | |
588 # Similar functionality in bash was previously turned off by supplying the "-o nospace" option to complete. | |
589 # Now it is conditionally disabled using "compopt -o nospace" if the match ends in a continuation character. | |
590 # This code is retained for environments where this isn't done natively. | |
591 continuation_chars = "=/:" | |
592 if len(completions) == 1 and completions[0][-1] not in continuation_chars: | |
593 if cword_prequote == "": | |
594 completions[0] += " " | |
595 | |
596 return completions | |
597 | |
598 def rl_complete(self, text, state): | |
599 """ | |
600 Alternate entry point for using the argcomplete completer in a readline-based REPL. See also | |
601 `rlcompleter <https://docs.python.org/2/library/rlcompleter.html#completer-objects>`_. | |
602 Usage: | |
603 | |
604 .. code-block:: python | |
605 | |
606 import argcomplete, argparse, readline | |
607 parser = argparse.ArgumentParser() | |
608 ... | |
609 completer = argcomplete.CompletionFinder(parser) | |
610 readline.set_completer_delims("") | |
611 readline.set_completer(completer.rl_complete) | |
612 readline.parse_and_bind("tab: complete") | |
613 result = input("prompt> ") | |
614 | |
615 (Use ``raw_input`` instead of ``input`` on Python 2, or use `eight <https://github.com/kislyuk/eight>`_). | |
616 """ | |
617 if state == 0: | |
618 cword_prequote, cword_prefix, cword_suffix, comp_words, first_colon_pos = split_line(text) | |
619 comp_words.insert(0, sys.argv[0]) | |
620 matches = self._get_completions(comp_words, cword_prefix, cword_prequote, first_colon_pos) | |
621 self._rl_matches = [text + match[len(cword_prefix):] for match in matches] | |
622 | |
623 if state < len(self._rl_matches): | |
624 return self._rl_matches[state] | |
625 else: | |
626 return None | |
627 | |
628 def get_display_completions(self): | |
629 """ | |
630 This function returns a mapping of option names to their help strings for displaying to the user | |
631 | |
632 Usage: | |
633 | |
634 .. code-block:: python | |
635 | |
636 def display_completions(substitution, matches, longest_match_length): | |
637 _display_completions = argcomplete.autocomplete.get_display_completions() | |
638 print("") | |
639 if _display_completions: | |
640 help_len = [len(x) for x in _display_completions.values() if x] | |
641 | |
642 if help_len: | |
643 maxlen = max([len(x) for x in _display_completions]) | |
644 print("\\n".join("{0:{2}} -- {1}".format(k, v, maxlen) | |
645 for k, v in sorted(_display_completions.items()))) | |
646 else: | |
647 print(" ".join(k for k in sorted(_display_completions))) | |
648 else: | |
649 print(" ".join(x for x in sorted(matches))) | |
650 | |
651 import readline | |
652 print("cli /> {0}".format(readline.get_line_buffer()), end="") | |
653 readline.redisplay() | |
654 | |
655 ... | |
656 readline.set_completion_display_matches_hook(display_completions) | |
657 | |
658 """ | |
659 return {" ".join(k): v for k, v in self._display_completions.items()} | |
660 | |
661 class ExclusiveCompletionFinder(CompletionFinder): | |
662 @staticmethod | |
663 def _action_allowed(action, parser): | |
664 if not CompletionFinder._action_allowed(action, parser): | |
665 return False | |
666 | |
667 append_classes = (argparse._AppendAction, argparse._AppendConstAction) | |
668 if action._orig_class in append_classes: | |
669 return True | |
670 | |
671 if action not in parser._seen_non_default_actions: | |
672 return True | |
673 | |
674 return False | |
675 | |
676 autocomplete = CompletionFinder() | |
677 autocomplete.__doc__ = """ Use this to access argcomplete. See :meth:`argcomplete.CompletionFinder.__call__()`. """ | |
678 | |
679 def warn(*args): | |
680 """ | |
681 Prints **args** to standard error when running completions. This will interrupt the user's command line interaction; | |
682 use it to indicate an error condition that is preventing your completer from working. | |
683 """ | |
684 print("\n", file=debug_stream, *args) |