Skip to content
Back to top

# Source code for xompletions.python

    """Completers for ``python -m <module>`` commands."""

    import os

    from xonsh.completers.tools import complete_from_sub_proc
    from xonsh.parsers.completion_context import CommandArg, CommandContext

    def _complete_pip(ctx, module_arg_index):
        """Delegate to pip's completer."""
        from xompletions import pip as _pip

        args = (CommandArg("pip"),) + ctx.args[module_arg_index + 1 :]
        pip_ctx = ctx._replace(args=args, arg_index=ctx.arg_index - module_arg_index)
        return _pip.xonsh_complete(pip_ctx)

    def _complete_argcomplete(ctx, module_arg_index):
        """Complete using argcomplete protocol (pytest, pipx, nox, etc.)."""
        module_name = ctx.args[module_arg_index].value
        # Build COMP_LINE as if the module is the command
        line_parts = [arg.value for arg in ctx.args[module_arg_index:]]
        if ctx.prefix:
            line_parts.append(ctx.prefix)
        comp_line = " ".join(line_parts)
        if not ctx.prefix:
            comp_line += " "

        return complete_from_sub_proc(
            ctx.args[0].value,
            "-m",
            module_name,
            _ARGCOMPLETE="1",
            _ARGCOMPLETE_IFS="\n",
            _ARGCOMPLETE_OUTPUT_FD="1",
            COMP_LINE=comp_line,
            COMP_POINT=str(len(comp_line)),
        )

    # Map module names to their completer functions.
    # Extend from xonshrc: ``from xompletions.python import PYTHON_MODULE_COMPLETERS``
    #
    # Available helpers:
    #   _complete_pip          — pip's PIP_AUTO_COMPLETE protocol
    #   _complete_argcomplete  — argcomplete protocol (_ARGCOMPLETE=1, output to stdout)
    PYTHON_MODULE_COMPLETERS = {
        "pip": _complete_pip,
    }

    def xonsh_complete(ctx: CommandContext):
        """Completes ``python -m <module>`` by delegating to the module's completer."""

        if (
            len(ctx.args) >= 3
            and os.path.basename(ctx.args[0].value).startswith("python")
            and ctx.args[1].value == "-m"
            and ctx.arg_index >= 3
        ):
            module_name = ctx.args[2].value
            completer = PYTHON_MODULE_COMPLETERS.get(module_name)
            if completer:
                return completer(ctx, module_arg_index=2)
        return None