diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py')
-rw-r--r-- | contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py | 411 |
1 files changed, 0 insertions, 411 deletions
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py deleted file mode 100644 index 62a3184ee2..0000000000 --- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/layout/layout.py +++ /dev/null @@ -1,411 +0,0 @@ -""" -Wrapper for the layout. -""" -from typing import Dict, Generator, Iterable, List, Optional, Union - -from prompt_toolkit.buffer import Buffer - -from .containers import ( - AnyContainer, - ConditionalContainer, - Container, - Window, - to_container, -) -from .controls import BufferControl, SearchBufferControl, UIControl - -__all__ = [ - "Layout", - "InvalidLayoutError", - "walk", -] - -FocusableElement = Union[str, Buffer, UIControl, AnyContainer] - - -class Layout: - """ - The layout for a prompt_toolkit - :class:`~prompt_toolkit.application.Application`. - This also keeps track of which user control is focused. - - :param container: The "root" container for the layout. - :param focused_element: element to be focused initially. (Can be anything - the `focus` function accepts.) - """ - - def __init__( - self, - container: AnyContainer, - focused_element: Optional[FocusableElement] = None, - ) -> None: - - self.container = to_container(container) - self._stack: List[Window] = [] - - # Map search BufferControl back to the original BufferControl. - # This is used to keep track of when exactly we are searching, and for - # applying the search. - # When a link exists in this dictionary, that means the search is - # currently active. - # Map: search_buffer_control -> original buffer control. - self.search_links: Dict[SearchBufferControl, BufferControl] = {} - - # Mapping that maps the children in the layout to their parent. - # This relationship is calculated dynamically, each time when the UI - # is rendered. (UI elements have only references to their children.) - self._child_to_parent: Dict[Container, Container] = {} - - if focused_element is None: - try: - self._stack.append(next(self.find_all_windows())) - except StopIteration as e: - raise InvalidLayoutError( - "Invalid layout. The layout does not contain any Window object." - ) from e - else: - self.focus(focused_element) - - # List of visible windows. - self.visible_windows: List[Window] = [] # List of `Window` objects. - - def __repr__(self) -> str: - return f"Layout({self.container!r}, current_window={self.current_window!r})" - - def find_all_windows(self) -> Generator[Window, None, None]: - """ - Find all the :class:`.UIControl` objects in this layout. - """ - for item in self.walk(): - if isinstance(item, Window): - yield item - - def find_all_controls(self) -> Iterable[UIControl]: - for container in self.find_all_windows(): - yield container.content - - def focus(self, value: FocusableElement) -> None: - """ - Focus the given UI element. - - `value` can be either: - - - a :class:`.UIControl` - - a :class:`.Buffer` instance or the name of a :class:`.Buffer` - - a :class:`.Window` - - Any container object. In this case we will focus the :class:`.Window` - from this container that was focused most recent, or the very first - focusable :class:`.Window` of the container. - """ - # BufferControl by buffer name. - if isinstance(value, str): - for control in self.find_all_controls(): - if isinstance(control, BufferControl) and control.buffer.name == value: - self.focus(control) - return - raise ValueError(f"Couldn't find Buffer in the current layout: {value!r}.") - - # BufferControl by buffer object. - elif isinstance(value, Buffer): - for control in self.find_all_controls(): - if isinstance(control, BufferControl) and control.buffer == value: - self.focus(control) - return - raise ValueError(f"Couldn't find Buffer in the current layout: {value!r}.") - - # Focus UIControl. - elif isinstance(value, UIControl): - if value not in self.find_all_controls(): - raise ValueError( - "Invalid value. Container does not appear in the layout." - ) - if not value.is_focusable(): - raise ValueError("Invalid value. UIControl is not focusable.") - - self.current_control = value - - # Otherwise, expecting any Container object. - else: - value = to_container(value) - - if isinstance(value, Window): - # This is a `Window`: focus that. - if value not in self.find_all_windows(): - raise ValueError( - "Invalid value. Window does not appear in the layout: %r" - % (value,) - ) - - self.current_window = value - else: - # Focus a window in this container. - # If we have many windows as part of this container, and some - # of them have been focused before, take the last focused - # item. (This is very useful when the UI is composed of more - # complex sub components.) - windows = [] - for c in walk(value, skip_hidden=True): - if isinstance(c, Window) and c.content.is_focusable(): - windows.append(c) - - # Take the first one that was focused before. - for w in reversed(self._stack): - if w in windows: - self.current_window = w - return - - # None was focused before: take the very first focusable window. - if windows: - self.current_window = windows[0] - return - - raise ValueError( - f"Invalid value. Container cannot be focused: {value!r}" - ) - - def has_focus(self, value: FocusableElement) -> bool: - """ - Check whether the given control has the focus. - :param value: :class:`.UIControl` or :class:`.Window` instance. - """ - if isinstance(value, str): - if self.current_buffer is None: - return False - return self.current_buffer.name == value - if isinstance(value, Buffer): - return self.current_buffer == value - if isinstance(value, UIControl): - return self.current_control == value - else: - value = to_container(value) - if isinstance(value, Window): - return self.current_window == value - else: - # Check whether this "container" is focused. This is true if - # one of the elements inside is focused. - for element in walk(value): - if element == self.current_window: - return True - return False - - @property - def current_control(self) -> UIControl: - """ - Get the :class:`.UIControl` to currently has the focus. - """ - return self._stack[-1].content - - @current_control.setter - def current_control(self, control: UIControl) -> None: - """ - Set the :class:`.UIControl` to receive the focus. - """ - for window in self.find_all_windows(): - if window.content == control: - self.current_window = window - return - - raise ValueError("Control not found in the user interface.") - - @property - def current_window(self) -> Window: - "Return the :class:`.Window` object that is currently focused." - return self._stack[-1] - - @current_window.setter - def current_window(self, value: Window) -> None: - "Set the :class:`.Window` object to be currently focused." - self._stack.append(value) - - @property - def is_searching(self) -> bool: - "True if we are searching right now." - return self.current_control in self.search_links - - @property - def search_target_buffer_control(self) -> Optional[BufferControl]: - """ - Return the :class:`.BufferControl` in which we are searching or `None`. - """ - # Not every `UIControl` is a `BufferControl`. This only applies to - # `BufferControl`. - control = self.current_control - - if isinstance(control, SearchBufferControl): - return self.search_links.get(control) - else: - return None - - def get_focusable_windows(self) -> Iterable[Window]: - """ - Return all the :class:`.Window` objects which are focusable (in the - 'modal' area). - """ - for w in self.walk_through_modal_area(): - if isinstance(w, Window) and w.content.is_focusable(): - yield w - - def get_visible_focusable_windows(self) -> List[Window]: - """ - Return a list of :class:`.Window` objects that are focusable. - """ - # focusable windows are windows that are visible, but also part of the - # modal container. Make sure to keep the ordering. - visible_windows = self.visible_windows - return [w for w in self.get_focusable_windows() if w in visible_windows] - - @property - def current_buffer(self) -> Optional[Buffer]: - """ - The currently focused :class:`~.Buffer` or `None`. - """ - ui_control = self.current_control - if isinstance(ui_control, BufferControl): - return ui_control.buffer - return None - - def get_buffer_by_name(self, buffer_name: str) -> Optional[Buffer]: - """ - Look in the layout for a buffer with the given name. - Return `None` when nothing was found. - """ - for w in self.walk(): - if isinstance(w, Window) and isinstance(w.content, BufferControl): - if w.content.buffer.name == buffer_name: - return w.content.buffer - return None - - @property - def buffer_has_focus(self) -> bool: - """ - Return `True` if the currently focused control is a - :class:`.BufferControl`. (For instance, used to determine whether the - default key bindings should be active or not.) - """ - ui_control = self.current_control - return isinstance(ui_control, BufferControl) - - @property - def previous_control(self) -> UIControl: - """ - Get the :class:`.UIControl` to previously had the focus. - """ - try: - return self._stack[-2].content - except IndexError: - return self._stack[-1].content - - def focus_last(self) -> None: - """ - Give the focus to the last focused control. - """ - if len(self._stack) > 1: - self._stack = self._stack[:-1] - - def focus_next(self) -> None: - """ - Focus the next visible/focusable Window. - """ - windows = self.get_visible_focusable_windows() - - if len(windows) > 0: - try: - index = windows.index(self.current_window) - except ValueError: - index = 0 - else: - index = (index + 1) % len(windows) - - self.focus(windows[index]) - - def focus_previous(self) -> None: - """ - Focus the previous visible/focusable Window. - """ - windows = self.get_visible_focusable_windows() - - if len(windows) > 0: - try: - index = windows.index(self.current_window) - except ValueError: - index = 0 - else: - index = (index - 1) % len(windows) - - self.focus(windows[index]) - - def walk(self) -> Iterable[Container]: - """ - Walk through all the layout nodes (and their children) and yield them. - """ - yield from walk(self.container) - - def walk_through_modal_area(self) -> Iterable[Container]: - """ - Walk through all the containers which are in the current 'modal' part - of the layout. - """ - # Go up in the tree, and find the root. (it will be a part of the - # layout, if the focus is in a modal part.) - root: Container = self.current_window - while not root.is_modal() and root in self._child_to_parent: - root = self._child_to_parent[root] - - yield from walk(root) - - def update_parents_relations(self) -> None: - """ - Update child->parent relationships mapping. - """ - parents = {} - - def walk(e: Container) -> None: - for c in e.get_children(): - parents[c] = e - walk(c) - - walk(self.container) - - self._child_to_parent = parents - - def reset(self) -> None: - # Remove all search links when the UI starts. - # (Important, for instance when control-c is been pressed while - # searching. The prompt cancels, but next `run()` call the search - # links are still there.) - self.search_links.clear() - - self.container.reset() - - def get_parent(self, container: Container) -> Optional[Container]: - """ - Return the parent container for the given container, or ``None``, if it - wasn't found. - """ - try: - return self._child_to_parent[container] - except KeyError: - return None - - -class InvalidLayoutError(Exception): - pass - - -def walk(container: Container, skip_hidden: bool = False) -> Iterable[Container]: - """ - Walk through layout, starting at this container. - """ - # When `skip_hidden` is set, don't go into disabled ConditionalContainer containers. - if ( - skip_hidden - and isinstance(container, ConditionalContainer) - and not container.filter() - ): - return - - yield container - - for c in container.get_children(): - # yield from walk(c) - yield from walk(c, skip_hidden=skip_hidden) |