def do_command_completion(): """ ndt command completion function """ output_stream = os.fdopen(8, "wb") ifs = os.environ.get("_ARGCOMPLETE_IFS", "\v") if len(ifs) != 1: sys.exit(1) current = os.environ["COMP_CUR"] prev = os.environ["COMP_PREV"] comp_line = os.environ["COMP_LINE"] comp_point = int(os.environ["COMP_POINT"]) # Adjust comp_point for wide chars if USING_PYTHON2: comp_point = len(comp_line[:comp_point].decode(SYS_ENCODING)) else: comp_point = len( comp_line.encode(SYS_ENCODING)[:comp_point].decode(SYS_ENCODING)) comp_line = ensure_str(comp_line) comp_words = split_line(comp_line, comp_point)[3] if "COMP_CWORD" in os.environ and os.environ["COMP_CWORD"] == "1": keys = [ x for x in list(COMMAND_MAPPINGS.keys()) if x.startswith(current) ] output_stream.write(ifs.join(keys).encode(SYS_ENCODING)) output_stream.flush() sys.exit(0) else: command = prev if len(comp_words) > 1: command = comp_words[1] if command not in COMMAND_MAPPINGS: sys.exit(1) command_type = COMMAND_MAPPINGS[command] if command_type == "shell": command = command + ".sh" if command_type == "ndtshell": command = command + ".sh" if command_type == "ndtshell" or command_type == "ndtscript": command = find_include(command) if command_type == "shell" or command_type == "script" or \ command_type == "ndtshell" or command_type == "ndtscript": proc = Popen([command], stderr=PIPE, stdout=PIPE) output = proc.communicate()[0] if proc.returncode == 0: output_stream.write( output.replace("\n", ifs).decode(SYS_ENCODING)) output_stream.flush() else: sys.exit(1) else: line = comp_line[3:].lstrip() os.environ['COMP_POINT'] = str(comp_point - (len(comp_line) - len(line))) os.environ['COMP_LINE'] = line parts = command_type.split(":") getattr(__import__(parts[0], fromlist=[parts[1]]), parts[1])() sys.exit(0)
def get_argcomplete_prefix(): if "_ARGCOMPLETE_BENCHMARK" in os.environ: os.environ["_ARGCOMPLETE_IFS"] = "\n" # os.environ["COMP_LINE"] = "cheribuild.py " # return all targets os.environ["COMP_LINE"] = "cheribuild.py foo --sq" # return all options starting with --sq # os.environ["COMP_LINE"] = "cheribuild.py foo --no-s" # return all options os.environ["COMP_POINT"] = str(len(os.environ["COMP_LINE"])) comp_line = argcomplete.ensure_str(os.environ["COMP_LINE"]) result = argcomplete.split_line(comp_line, int(os.environ["COMP_POINT"]))[1] if "_ARGCOMPLETE_BENCHMARK" in os.environ: print("argcomplete_prefix =", result, file=sys.stderr) return result
def __call__(self, argument_parser, completer=None, always_complete_options=True, exit_method=os._exit, output_stream=None, exclude=None, validator=None, print_suppressed=False, append_space=None, default_completer=DEFAULT_COMPLETER): """ :param argument_parser: The argument parser to autocomplete on :type argument_parser: :class:`argparse.ArgumentParser` :param always_complete_options: Controls the autocompletion of option strings if an option string opening character (normally ``-``) has not been entered. If ``True`` (default), both short (``-x``) and long (``--x``) option strings will be suggested. If ``False``, no option strings will be suggested. If ``long``, long options and short options with no long variant will be suggested. If ``short``, short options and long options with no short variant will be suggested. :type always_complete_options: boolean or string :param exit_method: Method used to stop the program after printing completions. Defaults to :meth:`os._exit`. If you want to perform a normal exit that calls exit handlers, use :meth:`sys.exit`. :type exit_method: callable :param exclude: List of strings representing options to be omitted from autocompletion :type exclude: iterable :param validator: Function to filter all completions through before returning (called with two string arguments, completion and prefix; return value is evaluated as a boolean) :type validator: callable :param print_suppressed: Whether or not to autocomplete options that have the ``help=argparse.SUPPRESS`` keyword argument set. :type print_suppressed: boolean :param append_space: Whether to append a space to unique matches. The default is ``True``. :type append_space: boolean .. note:: If you are not subclassing CompletionFinder to override its behaviors, use ``argcomplete.autocomplete()`` directly. It has the same signature as this method. Produces tab completions for ``argument_parser``. See module docs for more info. Argcomplete only executes actions if their class is known not to have side effects. Custom action classes can be added to argcomplete.safe_actions, if their values are wanted in the ``parsed_args`` completer argument, or their execution is otherwise desirable. """ # Older versions of argcomplete have fewer keyword arguments if sys.version_info >= (3, 5): self.__init__(argument_parser, always_complete_options=always_complete_options, exclude=exclude, validator=validator, print_suppressed=print_suppressed, append_space=append_space, default_completer=default_completer) else: self.__init__(argument_parser, always_complete_options=always_complete_options, exclude=exclude, validator=validator, print_suppressed=print_suppressed) if "_ARGCOMPLETE" not in os.environ: # not an argument completion invocation return try: argcomplete.debug_stream = os.fdopen(9, "w") except IOError: argcomplete.debug_stream = sys.stderr if output_stream is None: try: output_stream = os.fdopen(8, "wb") except IOError: argcomplete.debug( "Unable to open fd 8 for writing, quitting") exit_method(1) ifs = os.environ.get("_ARGCOMPLETE_IFS", "\013") if len(ifs) != 1: argcomplete.debug( "Invalid value for IFS, quitting [{v}]".format(v=ifs)) exit_method(1) comp_line = os.environ["COMP_LINE"] comp_point = int(os.environ["COMP_POINT"]) comp_line = argcomplete.ensure_str(comp_line) ############################## # SWAPPED FOR AUTOCOMPLETER # # Replaced with our own tokenizer function ############################## tokens, _, begidx, endidx = tokens_for_completion( comp_line, comp_point) # _ARGCOMPLETE is set by the shell script to tell us where comp_words # should start, based on what we're completing. # 1: <script> [args] # 2: python <script> [args] # 3: python -m <module> [args] start = int(os.environ["_ARGCOMPLETE"]) - 1 ############################## # SWAPPED FOR AUTOCOMPLETER # # Applying the same token dropping to our tokens ############################## # comp_words = comp_words[start:] tokens = tokens[start:] # debug("\nLINE: {!r}".format(comp_line), # "\nPOINT: {!r}".format(comp_point), # "\nPREQUOTE: {!r}".format(cword_prequote), # "\nPREFIX: {!r}".format(cword_prefix), # "\nSUFFIX: {!r}".format(cword_suffix), # "\nWORDS:", comp_words) ############################## # SWAPPED FOR AUTOCOMPLETER # # Replaced with our own completion function and customizing the returned values ############################## # completions = self._get_completions(comp_words, cword_prefix, cword_prequote, last_wordbreak_pos) # capture stdout from the autocompleter result = StringIO() with redirect_stdout(result): completions = completer.complete_command( tokens, tokens[-1], comp_line, begidx, endidx) outstr = result.getvalue() if completions: # If any completion has a space in it, then quote all completions # this improves the user experience so they don't nede to go back and add a quote if ' ' in ''.join(completions): completions = [ '"{}"'.format(entry) for entry in completions ] argcomplete.debug("\nReturning completions:", completions) output_stream.write( ifs.join(completions).encode(argcomplete.sys_encoding)) elif outstr: # if there are no completions, but we got something from stdout, try to print help # trick the bash completion into thinking there are 2 completions that are unlikely # to ever match. comp_type = int(os.environ["COMP_TYPE"]) if comp_type == 63: # type is 63 for second tab press print(outstr.rstrip(), file=argcomplete.debug_stream, end='') if completions is not None: output_stream.write( ifs.join([ifs, ' ']).encode(argcomplete.sys_encoding)) else: output_stream.write( ifs.join([]).encode(argcomplete.sys_encoding)) else: # if completions is None we assume we don't know how to handle it so let bash # go forward with normal filesystem completion output_stream.write( ifs.join([]).encode(argcomplete.sys_encoding)) output_stream.flush() argcomplete.debug_stream.flush() exit_method(0)