diff options
author | nkozlovskiy <nmk@ydb.tech> | 2023-09-29 12:24:06 +0300 |
---|---|---|
committer | nkozlovskiy <nmk@ydb.tech> | 2023-09-29 12:41:34 +0300 |
commit | e0e3e1717e3d33762ce61950504f9637a6e669ed (patch) | |
tree | bca3ff6939b10ed60c3d5c12439963a1146b9711 /contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py | |
parent | 38f2c5852db84c7b4d83adfcb009eb61541d1ccd (diff) | |
download | ydb-e0e3e1717e3d33762ce61950504f9637a6e669ed.tar.gz |
add ydb deps
Diffstat (limited to 'contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py')
-rw-r--r-- | contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py new file mode 100644 index 0000000000..2934dfc9a7 --- /dev/null +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py @@ -0,0 +1,253 @@ +""" +Margin implementations for a :class:`~prompt_toolkit.layout.containers.Window`. +""" +from __future__ import unicode_literals + +from abc import ABCMeta, abstractmethod +from six import with_metaclass +from six.moves import range + +from prompt_toolkit.filters import to_cli_filter +from prompt_toolkit.token import Token +from prompt_toolkit.utils import get_cwidth +from .utils import token_list_to_text + +__all__ = ( + 'Margin', + 'NumberredMargin', + 'ScrollbarMargin', + 'ConditionalMargin', + 'PromptMargin', +) + + +class Margin(with_metaclass(ABCMeta, object)): + """ + Base interface for a margin. + """ + @abstractmethod + def get_width(self, cli, get_ui_content): + """ + Return the width that this margin is going to consume. + + :param cli: :class:`.CommandLineInterface` instance. + :param get_ui_content: Callable that asks the user control to create + a :class:`.UIContent` instance. This can be used for instance to + obtain the number of lines. + """ + return 0 + + @abstractmethod + def create_margin(self, cli, window_render_info, width, height): + """ + Creates a margin. + This should return a list of (Token, text) tuples. + + :param cli: :class:`.CommandLineInterface` instance. + :param window_render_info: + :class:`~prompt_toolkit.layout.containers.WindowRenderInfo` + instance, generated after rendering and copying the visible part of + the :class:`~prompt_toolkit.layout.controls.UIControl` into the + :class:`~prompt_toolkit.layout.containers.Window`. + :param width: The width that's available for this margin. (As reported + by :meth:`.get_width`.) + :param height: The height that's available for this margin. (The height + of the :class:`~prompt_toolkit.layout.containers.Window`.) + """ + return [] + + +class NumberredMargin(Margin): + """ + Margin that displays the line numbers. + + :param relative: Number relative to the cursor position. Similar to the Vi + 'relativenumber' option. + :param display_tildes: Display tildes after the end of the document, just + like Vi does. + """ + def __init__(self, relative=False, display_tildes=False): + self.relative = to_cli_filter(relative) + self.display_tildes = to_cli_filter(display_tildes) + + def get_width(self, cli, get_ui_content): + line_count = get_ui_content().line_count + return max(3, len('%s' % line_count) + 1) + + def create_margin(self, cli, window_render_info, width, height): + relative = self.relative(cli) + + token = Token.LineNumber + token_current = Token.LineNumber.Current + + # Get current line number. + current_lineno = window_render_info.ui_content.cursor_position.y + + # Construct margin. + result = [] + last_lineno = None + + for y, lineno in enumerate(window_render_info.displayed_lines): + # Only display line number if this line is not a continuation of the previous line. + if lineno != last_lineno: + if lineno is None: + pass + elif lineno == current_lineno: + # Current line. + if relative: + # Left align current number in relative mode. + result.append((token_current, '%i' % (lineno + 1))) + else: + result.append((token_current, ('%i ' % (lineno + 1)).rjust(width))) + else: + # Other lines. + if relative: + lineno = abs(lineno - current_lineno) - 1 + + result.append((token, ('%i ' % (lineno + 1)).rjust(width))) + + last_lineno = lineno + result.append((Token, '\n')) + + # Fill with tildes. + if self.display_tildes(cli): + while y < window_render_info.window_height: + result.append((Token.Tilde, '~\n')) + y += 1 + + return result + + +class ConditionalMargin(Margin): + """ + Wrapper around other :class:`.Margin` classes to show/hide them. + """ + def __init__(self, margin, filter): + assert isinstance(margin, Margin) + + self.margin = margin + self.filter = to_cli_filter(filter) + + def get_width(self, cli, ui_content): + if self.filter(cli): + return self.margin.get_width(cli, ui_content) + else: + return 0 + + def create_margin(self, cli, window_render_info, width, height): + if width and self.filter(cli): + return self.margin.create_margin(cli, window_render_info, width, height) + else: + return [] + + +class ScrollbarMargin(Margin): + """ + Margin displaying a scrollbar. + + :param display_arrows: Display scroll up/down arrows. + """ + def __init__(self, display_arrows=False): + self.display_arrows = to_cli_filter(display_arrows) + + def get_width(self, cli, ui_content): + return 1 + + def create_margin(self, cli, window_render_info, width, height): + total_height = window_render_info.content_height + display_arrows = self.display_arrows(cli) + + window_height = window_render_info.window_height + if display_arrows: + window_height -= 2 + + try: + items_per_row = float(total_height) / min(total_height, window_height) + except ZeroDivisionError: + return [] + else: + def is_scroll_button(row): + " True if we should display a button on this row. " + current_row_middle = int((row + .5) * items_per_row) + return current_row_middle in window_render_info.displayed_lines + + # Up arrow. + result = [] + if display_arrows: + result.extend([ + (Token.Scrollbar.Arrow, '^'), + (Token.Scrollbar, '\n') + ]) + + # Scrollbar body. + for i in range(window_height): + if is_scroll_button(i): + result.append((Token.Scrollbar.Button, ' ')) + else: + result.append((Token.Scrollbar, ' ')) + result.append((Token, '\n')) + + # Down arrow + if display_arrows: + result.append((Token.Scrollbar.Arrow, 'v')) + + return result + + +class PromptMargin(Margin): + """ + Create margin that displays a prompt. + This can display one prompt at the first line, and a continuation prompt + (e.g, just dots) on all the following lines. + + :param get_prompt_tokens: Callable that takes a CommandLineInterface as + input and returns a list of (Token, type) tuples to be shown as the + prompt at the first line. + :param get_continuation_tokens: Callable that takes a CommandLineInterface + and a width as input and returns a list of (Token, type) tuples for the + next lines of the input. + :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`) + Display line numbers instead of the continuation prompt. + """ + def __init__(self, get_prompt_tokens, get_continuation_tokens=None, + show_numbers=False): + assert callable(get_prompt_tokens) + assert get_continuation_tokens is None or callable(get_continuation_tokens) + show_numbers = to_cli_filter(show_numbers) + + self.get_prompt_tokens = get_prompt_tokens + self.get_continuation_tokens = get_continuation_tokens + self.show_numbers = show_numbers + + def get_width(self, cli, ui_content): + " Width to report to the `Window`. " + # Take the width from the first line. + text = token_list_to_text(self.get_prompt_tokens(cli)) + return get_cwidth(text) + + def create_margin(self, cli, window_render_info, width, height): + # First line. + tokens = self.get_prompt_tokens(cli)[:] + + # Next lines. (Show line numbering when numbering is enabled.) + if self.get_continuation_tokens: + # Note: we turn this into a list, to make sure that we fail early + # in case `get_continuation_tokens` returns something else, + # like `None`. + tokens2 = list(self.get_continuation_tokens(cli, width)) + else: + tokens2 = [] + + show_numbers = self.show_numbers(cli) + last_y = None + + for y in window_render_info.displayed_lines[1:]: + tokens.append((Token, '\n')) + if show_numbers: + if y != last_y: + tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width))) + else: + tokens.extend(tokens2) + last_y = y + + return tokens |