Ejemplo n.º 1
0
class CommandAutoSuggest(AutoSuggest):
    """Atomix command/resource/action auto-suggester."""
    def __init__(self, commands):
        self.commands = commands
        self.history_suggester = AutoSuggestFromHistory()

    def get_suggestion(self, cli, buffer, document):
        in_quote = False
        for word in document.text.split(' '):
            if not in_quote and word.startswith('"'):
                in_quote = True
            elif in_quote and word.endswith('"'):
                in_quote = False

        # If the last word is in a quote, don't suggest anything.
        if in_quote:
            return None

        args = shlex.split(document.text)
        if len(args) == 0:
            return None

        args = list(args)
        if document.text.endswith(' '):
            args.append('')

        command_name = args.pop(0)
        if len(args) == 0:
            for name in sorted(self.commands.commands):
                if name.startswith(command_name):
                    return Suggestion(name[len(command_name):])

        try:
            command = self.commands.command(command_name)
        except UnknownCommand:
            return None

        suggestion = command.suggest_tail(*args)
        if suggestion is None:
            return self.history_suggester.get_suggestion(cli, buffer, document)
        return Suggestion(suggestion)
Ejemplo n.º 2
0
class PromptToolkitCompleter(Completer):
    """Simple prompt_toolkit Completer object.

    It just redirects requests to normal Xonsh completer.
    """
    def __init__(self, completer, ctx, shell):
        """Takes instance of xonsh.completer.Completer, the xonsh execution
        context, and the shell instance itself.
        """
        self.completer = completer
        self.ctx = ctx
        self.shell = shell
        self.hist_suggester = AutoSuggestFromHistory()

    def get_completions(self, document, complete_event):
        """Returns a generator for list of completions."""
        env = XSH.env
        should_complete = complete_event.completion_requested or env.get(
            "UPDATE_COMPLETIONS_ON_KEYPRESS")
        #  Only generate completions when the user hits tab.
        if not should_complete or self.completer is None:
            return
        # generate actual completions
        line = document.current_line

        endidx = document.cursor_position_col
        line_ex = XSH.aliases.expand_alias(line, endidx)

        begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(
            " ") >= 0 else 0
        prefix = line[begidx:endidx]
        expand_offset = len(line_ex) - len(line)

        multiline_text = document.text
        cursor_index = document.cursor_position
        if line != line_ex:
            line_start = cursor_index - len(
                document.current_line_before_cursor)
            multiline_text = (multiline_text[:line_start] + line_ex +
                              multiline_text[line_start + len(line):])
            cursor_index += expand_offset

        # get normal completions
        completions, plen = self.completer.complete(
            prefix,
            line_ex,
            begidx + expand_offset,
            endidx + expand_offset,
            self.ctx,
            multiline_text=multiline_text,
            cursor_index=cursor_index,
        )

        # completions from auto suggest
        sug_comp = None
        if env.get("AUTO_SUGGEST") and env.get("AUTO_SUGGEST_IN_COMPLETIONS"):
            sug_comp = self.suggestion_completion(document, line)
            if sug_comp is None:
                pass
            elif len(completions) == 0:
                completions = (sug_comp, )
            else:
                completions = set(completions)
                completions.discard(sug_comp)
                completions = (sug_comp, ) + tuple(sorted(completions))
        # reserve space, if needed.
        if len(completions) <= 1:
            pass
        elif len(os.path.commonprefix(completions)) <= len(prefix):
            self.reserve_space()
        # Find common prefix (strip quoting)
        c_prefix = os.path.commonprefix([a.strip("'\"") for a in completions])
        # Find last split symbol, do not trim the last part
        while c_prefix:
            if c_prefix[-1] in r"/\.:@,":
                break
            c_prefix = c_prefix[:-1]
        # yield completions
        if sug_comp is None:
            pre = min(document.cursor_position_col - begidx, len(c_prefix))
        else:
            pre = len(c_prefix)
        for comp in completions:
            # do not display quote
            if isinstance(comp, RichCompletion):
                # ptk doesn't render newlines. This can be removed once it is supported.
                desc = (comp.description.replace(os.linesep, " ")
                        if comp.description else None)
                yield Completion(
                    comp,
                    -comp.prefix_len if comp.prefix_len is not None else -plen,
                    display=comp.display or comp[pre:].strip("'\""),
                    display_meta=desc,
                    style=comp.style or "",
                )
            elif isinstance(comp, Completion):
                yield comp
            else:
                disp = comp[pre:].strip("'\"")
                yield Completion(comp, -plen, display=disp)

    def suggestion_completion(self, document, line):
        """Provides a completion based on the current auto-suggestion."""
        app = self.shell.prompter.app
        sug = self.hist_suggester.get_suggestion(app.current_buffer, document)
        if sug is None:
            return None
        comp, _, _ = sug.text.partition(" ")
        _, _, prev = line.rpartition(" ")
        return prev + comp

    def reserve_space(self):
        """Adjust the height for showing autocompletion menu."""
        app = get_app()
        render = app.renderer

        window = None
        try:
            # this raises error sometimes when COMPLETE_WHILE_TYPE is enabled
            window = app.layout.current_window
        except Exception:
            pass

        if window and window.render_info:
            h = window.render_info.content_height
            r = XSH.env.get("COMPLETIONS_MENU_ROWS")
            size = h + r
            last_h = render._last_screen.height if render._last_screen else 0
            last_h = max(render._min_available_height, last_h)
            if last_h < size:
                if render._last_screen:
                    render._last_screen.height = size
Ejemplo n.º 3
0
class PromptToolkitCompleter(Completer):
    """Simple prompt_toolkit Completer object.

    It just redirects requests to normal Xonsh completer.
    """
    def __init__(self, completer, ctx, shell):
        """Takes instance of xonsh.completer.Completer, the xonsh execution
        context, and the shell instance itself.
        """
        self.completer = completer
        self.ctx = ctx
        self.shell = shell
        self.hist_suggester = AutoSuggestFromHistory()

    def get_completions(self, document, complete_event):
        """Returns a generator for list of completions."""
        env = builtins.__xonsh_env__
        should_complete = (complete_event.completion_requested
                           or env.get('UPDATE_COMPLETIONS_ON_KEYPRESS'))
        #  Only generate completions when the user hits tab.
        if not should_complete or self.completer is None:
            return
        # generate actual completions
        line = document.current_line.lstrip()
        line_ex = builtins.aliases.expand_alias(line)

        endidx = document.cursor_position_col
        begidx = (line[:endidx].rfind(' ') +
                  1 if line[:endidx].rfind(' ') >= 0 else 0)
        prefix = line[begidx:endidx]
        expand_offset = len(line_ex) - len(line)
        # get normal completions
        completions, l = self.completer.complete(prefix, line_ex,
                                                 begidx + expand_offset,
                                                 endidx + expand_offset,
                                                 self.ctx)
        # completions from auto suggest
        sug_comp = None
        if env.get('AUTO_SUGGEST') and env.get('AUTO_SUGGEST_IN_COMPLETIONS'):
            sug_comp = self.suggestion_completion(document, line)
            if sug_comp is None:
                pass
            elif len(completions) == 0:
                completions = (sug_comp, )
            else:
                completions = set(completions)
                completions.discard(sug_comp)
                completions = (sug_comp, ) + tuple(sorted(completions))
        # reserve space, if needed.
        if len(completions) <= 1:
            pass
        elif len(os.path.commonprefix(completions)) <= len(prefix):
            self.reserve_space()
        # Find common prefix (strip quoting)
        c_prefix = os.path.commonprefix([a.strip('\'"') for a in completions])
        # Find last split symbol, do not trim the last part
        while c_prefix:
            if c_prefix[-1] in r'/\.:@,':
                break
            c_prefix = c_prefix[:-1]
        # yield completions
        if sug_comp is None:
            pre = min(document.cursor_position_col - begidx, len(c_prefix))
        else:
            pre = len(c_prefix)
        for comp in completions:
            # do not display quote
            disp = comp[pre:].strip('\'"')
            yield Completion(comp, -l, display=disp)

    def suggestion_completion(self, document, line):
        """Provides a completion based on the current auto-suggestion."""
        cli = self.shell.prompter.cli
        sug = self.hist_suggester.get_suggestion(cli, cli.current_buffer,
                                                 document)
        if sug is None:
            return None
        comp, _, _ = sug.text.partition(' ')
        _, _, prev = line.rpartition(' ')
        return prev + comp

    def reserve_space(self):
        cli = builtins.__xonsh_shell__.shell.prompter.cli
        window = cli.application.layout.children[0].content.children[1]

        if window and window.render_info:
            h = window.render_info.content_height
            r = builtins.__xonsh_env__.get('COMPLETIONS_MENU_ROWS')
            size = h + r

            def comp_height(cli):
                # If there is an autocompletion menu to be shown, make sure that o
                # layout has at least a minimal height in order to display it.
                if not cli.is_done:
                    return LayoutDimension(min=size)
                else:
                    return LayoutDimension()

            window._height = comp_height
Ejemplo n.º 4
0
class PromptToolkitCompleter(Completer):
    """Simple prompt_toolkit Completer object.

    It just redirects requests to normal Xonsh completer.
    """

    def __init__(self, completer, ctx, shell):
        """Takes instance of xonsh.completer.Completer, the xonsh execution
        context, and the shell instance itself.
        """
        self.completer = completer
        self.ctx = ctx
        self.shell = shell
        self.hist_suggester = AutoSuggestFromHistory()

    def get_completions(self, document, complete_event):
        """Returns a generator for list of completions."""
        env = builtins.__xonsh__.env
        should_complete = complete_event.completion_requested or env.get(
            "UPDATE_COMPLETIONS_ON_KEYPRESS"
        )
        #  Only generate completions when the user hits tab.
        if not should_complete or self.completer is None:
            return
        # generate actual completions
        line = document.current_line.lstrip()
        line_ex = builtins.aliases.expand_alias(line)

        endidx = document.cursor_position_col
        begidx = line[:endidx].rfind(" ") + 1 if line[:endidx].rfind(" ") >= 0 else 0
        prefix = line[begidx:endidx]
        expand_offset = len(line_ex) - len(line)
        # get normal completions
        completions, l = self.completer.complete(
            prefix, line_ex, begidx + expand_offset, endidx + expand_offset, self.ctx
        )
        # completions from auto suggest
        sug_comp = None
        if env.get("AUTO_SUGGEST") and env.get("AUTO_SUGGEST_IN_COMPLETIONS"):
            sug_comp = self.suggestion_completion(document, line)
            if sug_comp is None:
                pass
            elif len(completions) == 0:
                completions = (sug_comp,)
            else:
                completions = set(completions)
                completions.discard(sug_comp)
                completions = (sug_comp,) + tuple(sorted(completions))
        # reserve space, if needed.
        if len(completions) <= 1:
            pass
        elif len(os.path.commonprefix(completions)) <= len(prefix):
            self.reserve_space()
        # Find common prefix (strip quoting)
        c_prefix = os.path.commonprefix([a.strip("'\"") for a in completions])
        # Find last split symbol, do not trim the last part
        while c_prefix:
            if c_prefix[-1] in r"/\.:@,":
                break
            c_prefix = c_prefix[:-1]
        # yield completions
        if sug_comp is None:
            pre = min(document.cursor_position_col - begidx, len(c_prefix))
        else:
            pre = len(c_prefix)
        for comp in completions:
            # do not display quote
            disp = comp[pre:].strip("'\"")
            yield Completion(comp, -l, display=disp)

    def suggestion_completion(self, document, line):
        """Provides a completion based on the current auto-suggestion."""
        app = self.shell.prompter.app
        sug = self.hist_suggester.get_suggestion(app.current_buffer, document)
        if sug is None:
            return None
        comp, _, _ = sug.text.partition(" ")
        _, _, prev = line.rpartition(" ")
        return prev + comp

    def reserve_space(self):
        """Adjust the height for showing autocompletion menu."""
        app = get_app()
        render = app.renderer
        window = app.layout.container.children[0].content.children[1].content

        if window and window.render_info:
            h = window.render_info.content_height
            r = builtins.__xonsh__.env.get("COMPLETIONS_MENU_ROWS")
            size = h + r
            last_h = render._last_screen.height if render._last_screen else 0
            last_h = max(render._min_available_height, last_h)
            if last_h < size:
                if render._last_screen:
                    render._last_screen.height = size
Ejemplo n.º 5
0
class PromptToolkitCompleter(Completer):
    """Simple prompt_toolkit Completer object.

    It just redirects requests to normal Xonsh completer.
    """

    def __init__(self, completer, ctx, shell):
        """Takes instance of xonsh.completer.Completer, the xonsh execution
        context, and the shell instance itself.
        """
        self.completer = completer
        self.ctx = ctx
        self.shell = shell
        self.hist_suggester = AutoSuggestFromHistory()

    def get_completions(self, document, complete_event):
        """Returns a generator for list of completions."""
        env = builtins.__xonsh_env__
        should_complete = (
            complete_event.completion_requested or
            env.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
            )
        #  Only generate completions when the user hits tab.
        if not should_complete or self.completer is None:
            return
        # generate actual completions
        line = document.current_line.lstrip()
        line_ex = builtins.aliases.expand_alias(line)

        endidx = document.cursor_position_col
        begidx = (line[:endidx].rfind(' ') + 1
                  if line[:endidx].rfind(' ') >= 0 else 0)
        prefix = line[begidx:endidx]
        expand_offset = len(line_ex) - len(line)
        # get normal completions
        completions, l = self.completer.complete(prefix, line_ex,
                                                 begidx + expand_offset,
                                                 endidx + expand_offset,
                                                 self.ctx)
        # completions from auto suggest
        sug_comp = None
        if env.get('AUTO_SUGGEST'):
            sug_comp = self.suggestion_completion(document, line)
            if sug_comp is None:
                pass
            elif len(completions) == 0:
                completions = (sug_comp,)
            else:
                completions = set(completions)
                completions.discard(sug_comp)
                completions = (sug_comp,) + tuple(sorted(completions))
        # reserve space, if needed.
        if len(completions) <= 1:
            pass
        elif len(os.path.commonprefix(completions)) <= len(prefix):
            self.reserve_space()
        # Find common prefix (strip quoting)
        c_prefix = os.path.commonprefix([a.strip('\'"') for a in completions])
        # Find last split symbol, do not trim the last part
        while c_prefix:
            if c_prefix[-1] in r'/\.:@,':
                break
            c_prefix = c_prefix[:-1]
        # yield completions
        if sug_comp is None:
            pre = min(document.cursor_position_col - begidx, len(c_prefix))
        else:
            pre = len(c_prefix)
        for comp in completions:
            # do not display quote
            disp = comp[pre:].strip('\'"')
            yield Completion(comp, -l, display=disp)

    def suggestion_completion(self, document, line):
        """Provides a completion based on the current auto-suggestion."""
        cli = self.shell.prompter.cli
        sug = self.hist_suggester.get_suggestion(cli, cli.current_buffer, document)
        if sug is None:
            return None
        comp, _, _ = sug.text.partition(' ')
        _, _, prev = line.rpartition(' ')
        return prev + comp

    def reserve_space(self):
        cli = builtins.__xonsh_shell__.shell.prompter.cli
        window = cli.application.layout.children[0].content.children[1]

        if window and window.render_info:
            h = window.render_info.content_height
            r = builtins.__xonsh_env__.get('COMPLETIONS_MENU_ROWS')
            size = h + r

            def comp_height(cli):
                # If there is an autocompletion menu to be shown, make sure that o
                # layout has at least a minimal height in order to display it.
                if not cli.is_done:
                    return LayoutDimension(min=size)
                else:
                    return LayoutDimension()
            window._height = comp_height