aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout
diff options
context:
space:
mode:
authorIvan Blinkov <ivan@blinkov.ru>2022-02-10 16:47:11 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:47:11 +0300
commit5b283123c882433dafbaf6b338adeea16c1a0ea0 (patch)
tree339adc63bce23800021202ae4a8328a843dc447a /contrib/python/prompt-toolkit/py2/prompt_toolkit/layout
parent1aeb9a455974457866f78722ad98114bafc84e8a (diff)
downloadydb-5b283123c882433dafbaf6b338adeea16c1a0ea0.tar.gz
Restoring authorship annotation for Ivan Blinkov <ivan@blinkov.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/prompt-toolkit/py2/prompt_toolkit/layout')
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py100
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py1978
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py774
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py184
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py84
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py234
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py848
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py58
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py570
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py208
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py286
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py376
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py248
13 files changed, 2974 insertions, 2974 deletions
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
index 01ba850d6c..0dec5ecfaf 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
@@ -1,51 +1,51 @@
-"""
-Command line layout definitions
--------------------------------
-
-The layout of a command line interface is defined by a Container instance.
-There are two main groups of classes here. Containers and controls:
-
-- A container can contain other containers or controls, it can have multiple
- children and it decides about the dimensions.
-- A control is responsible for rendering the actual content to a screen.
+"""
+Command line layout definitions
+-------------------------------
+
+The layout of a command line interface is defined by a Container instance.
+There are two main groups of classes here. Containers and controls:
+
+- A container can contain other containers or controls, it can have multiple
+ children and it decides about the dimensions.
+- A control is responsible for rendering the actual content to a screen.
A control can propose some dimensions, but it's the container who decides
- about the dimensions -- or when the control consumes more space -- which part
- of the control will be visible.
-
-
-Container classes::
-
- - Container (Abstract base class)
- |- HSplit (Horizontal split)
- |- VSplit (Vertical split)
- |- FloatContainer (Container which can also contain menus and other floats)
- `- Window (Container which contains one actual control
-
-Control classes::
-
- - UIControl (Abstract base class)
- |- TokenListControl (Renders a simple list of tokens)
- |- FillControl (Fills control with one token/character.)
- `- BufferControl (Renders an input buffer.)
-
-
-Usually, you end up wrapping every control inside a `Window` object, because
-that's the only way to render it in a layout.
-
-There are some prepared toolbars which are ready to use::
-
-- SystemToolbar (Shows the 'system' input buffer, for entering system commands.)
-- ArgToolbar (Shows the input 'arg', for repetition of input commands.)
-- SearchToolbar (Shows the 'search' input buffer, for incremental search.)
-- CompletionsToolbar (Shows the completions of the current buffer.)
-- ValidationToolbar (Shows validation errors of the current buffer.)
-
-And one prepared menu:
-
-- CompletionsMenu
-
-"""
-from __future__ import unicode_literals
-
-from .containers import Float, FloatContainer, HSplit, VSplit, Window, ConditionalContainer
-from .controls import TokenListControl, FillControl, BufferControl
+ about the dimensions -- or when the control consumes more space -- which part
+ of the control will be visible.
+
+
+Container classes::
+
+ - Container (Abstract base class)
+ |- HSplit (Horizontal split)
+ |- VSplit (Vertical split)
+ |- FloatContainer (Container which can also contain menus and other floats)
+ `- Window (Container which contains one actual control
+
+Control classes::
+
+ - UIControl (Abstract base class)
+ |- TokenListControl (Renders a simple list of tokens)
+ |- FillControl (Fills control with one token/character.)
+ `- BufferControl (Renders an input buffer.)
+
+
+Usually, you end up wrapping every control inside a `Window` object, because
+that's the only way to render it in a layout.
+
+There are some prepared toolbars which are ready to use::
+
+- SystemToolbar (Shows the 'system' input buffer, for entering system commands.)
+- ArgToolbar (Shows the input 'arg', for repetition of input commands.)
+- SearchToolbar (Shows the 'search' input buffer, for incremental search.)
+- CompletionsToolbar (Shows the completions of the current buffer.)
+- ValidationToolbar (Shows validation errors of the current buffer.)
+
+And one prepared menu:
+
+- CompletionsMenu
+
+"""
+from __future__ import unicode_literals
+
+from .containers import Float, FloatContainer, HSplit, VSplit, Window, ConditionalContainer
+from .controls import TokenListControl, FillControl, BufferControl
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
index 512c9122d0..0bdafe18e0 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
@@ -1,16 +1,16 @@
-"""
-Container for the layout.
-(Containers can contain other containers or user interface controls.)
-"""
-from __future__ import unicode_literals
-
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
+"""
+Container for the layout.
+(Containers can contain other containers or user interface controls.)
+"""
+from __future__ import unicode_literals
+
+from abc import ABCMeta, abstractmethod
+from six import with_metaclass
from six.moves import range
-
+
from .controls import UIControl, TokenListControl, UIContent
-from .dimension import LayoutDimension, sum_layout_dimensions, max_layout_dimensions
-from .margins import Margin
+from .dimension import LayoutDimension, sum_layout_dimensions, max_layout_dimensions
+from .margins import Margin
from .screen import Point, WritePosition, _CHAR_CACHE
from .utils import token_list_to_text, explode_tokens
from prompt_toolkit.cache import SimpleCache
@@ -19,495 +19,495 @@ from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
from prompt_toolkit.reactive import Integer
from prompt_toolkit.token import Token
from prompt_toolkit.utils import take_using_weights, get_cwidth
-
-__all__ = (
- 'Container',
- 'HSplit',
- 'VSplit',
- 'FloatContainer',
- 'Float',
- 'Window',
- 'WindowRenderInfo',
- 'ConditionalContainer',
+
+__all__ = (
+ 'Container',
+ 'HSplit',
+ 'VSplit',
+ 'FloatContainer',
+ 'Float',
+ 'Window',
+ 'WindowRenderInfo',
+ 'ConditionalContainer',
'ScrollOffsets',
'ColorColumn',
-)
-
-Transparent = Token.Transparent
-
-
-class Container(with_metaclass(ABCMeta, object)):
- """
- Base class for user interface layout.
- """
- @abstractmethod
- def reset(self):
- """
- Reset the state of this container and all the children.
- (E.g. reset scroll offsets, etc...)
- """
-
- @abstractmethod
- def preferred_width(self, cli, max_available_width):
- """
- Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
- represents the desired width for this container.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- """
-
- @abstractmethod
+)
+
+Transparent = Token.Transparent
+
+
+class Container(with_metaclass(ABCMeta, object)):
+ """
+ Base class for user interface layout.
+ """
+ @abstractmethod
+ def reset(self):
+ """
+ Reset the state of this container and all the children.
+ (E.g. reset scroll offsets, etc...)
+ """
+
+ @abstractmethod
+ def preferred_width(self, cli, max_available_width):
+ """
+ Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
+ represents the desired width for this container.
+
+ :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
+ """
+
+ @abstractmethod
def preferred_height(self, cli, width, max_available_height):
- """
- Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
- represents the desired height for this container.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- """
-
- @abstractmethod
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Write the actual content to the screen.
-
- :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
- :param screen: :class:`~prompt_toolkit.layout.screen.Screen`
- :param mouse_handlers: :class:`~prompt_toolkit.layout.mouse_handlers.MouseHandlers`.
- """
-
- @abstractmethod
- def walk(self, cli):
- """
- Walk through all the layout nodes (and their children) and yield them.
- """
-
-
-def _window_too_small():
- " Create a `Window` that displays the 'Window too small' text. "
- return Window(TokenListControl.static(
- [(Token.WindowTooSmall, ' Window too small... ')]))
-
-
-class HSplit(Container):
- """
- Several layouts, one stacked above/under the other.
-
- :param children: List of child :class:`.Container` objects.
- :param window_too_small: A :class:`.Container` object that is displayed if
- there is not enough space for all the children. By default, this is a
- "Window too small" message.
- :param get_dimensions: (`None` or a callable that takes a
- `CommandLineInterface` and returns a list of `LayoutDimension`
- instances.) By default the dimensions are taken from the children and
- divided by the available space. However, when `get_dimensions` is specified,
- this is taken instead.
- :param report_dimensions_callback: When rendering, this function is called
- with the `CommandLineInterface` and the list of used dimensions. (As a
- list of integers.)
- """
- def __init__(self, children, window_too_small=None,
- get_dimensions=None, report_dimensions_callback=None):
- assert all(isinstance(c, Container) for c in children)
- assert window_too_small is None or isinstance(window_too_small, Container)
- assert get_dimensions is None or callable(get_dimensions)
- assert report_dimensions_callback is None or callable(report_dimensions_callback)
-
- self.children = children
- self.window_too_small = window_too_small or _window_too_small()
- self.get_dimensions = get_dimensions
- self.report_dimensions_callback = report_dimensions_callback
-
- def preferred_width(self, cli, max_available_width):
- if self.children:
- dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
- return max_layout_dimensions(dimensions)
- else:
- return LayoutDimension(0)
-
+ """
+ Return a :class:`~prompt_toolkit.layout.dimension.LayoutDimension` that
+ represents the desired height for this container.
+
+ :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
+ """
+
+ @abstractmethod
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ """
+ Write the actual content to the screen.
+
+ :param cli: :class:`~prompt_toolkit.interface.CommandLineInterface`.
+ :param screen: :class:`~prompt_toolkit.layout.screen.Screen`
+ :param mouse_handlers: :class:`~prompt_toolkit.layout.mouse_handlers.MouseHandlers`.
+ """
+
+ @abstractmethod
+ def walk(self, cli):
+ """
+ Walk through all the layout nodes (and their children) and yield them.
+ """
+
+
+def _window_too_small():
+ " Create a `Window` that displays the 'Window too small' text. "
+ return Window(TokenListControl.static(
+ [(Token.WindowTooSmall, ' Window too small... ')]))
+
+
+class HSplit(Container):
+ """
+ Several layouts, one stacked above/under the other.
+
+ :param children: List of child :class:`.Container` objects.
+ :param window_too_small: A :class:`.Container` object that is displayed if
+ there is not enough space for all the children. By default, this is a
+ "Window too small" message.
+ :param get_dimensions: (`None` or a callable that takes a
+ `CommandLineInterface` and returns a list of `LayoutDimension`
+ instances.) By default the dimensions are taken from the children and
+ divided by the available space. However, when `get_dimensions` is specified,
+ this is taken instead.
+ :param report_dimensions_callback: When rendering, this function is called
+ with the `CommandLineInterface` and the list of used dimensions. (As a
+ list of integers.)
+ """
+ def __init__(self, children, window_too_small=None,
+ get_dimensions=None, report_dimensions_callback=None):
+ assert all(isinstance(c, Container) for c in children)
+ assert window_too_small is None or isinstance(window_too_small, Container)
+ assert get_dimensions is None or callable(get_dimensions)
+ assert report_dimensions_callback is None or callable(report_dimensions_callback)
+
+ self.children = children
+ self.window_too_small = window_too_small or _window_too_small()
+ self.get_dimensions = get_dimensions
+ self.report_dimensions_callback = report_dimensions_callback
+
+ def preferred_width(self, cli, max_available_width):
+ if self.children:
+ dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
+ return max_layout_dimensions(dimensions)
+ else:
+ return LayoutDimension(0)
+
def preferred_height(self, cli, width, max_available_height):
dimensions = [c.preferred_height(cli, width, max_available_height) for c in self.children]
- return sum_layout_dimensions(dimensions)
-
- def reset(self):
- for c in self.children:
- c.reset()
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Render the prompt to a `Screen` instance.
-
- :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
- to which the output has to be written.
- """
- sizes = self._divide_heigths(cli, write_position)
-
- if self.report_dimensions_callback:
- self.report_dimensions_callback(cli, sizes)
-
- if sizes is None:
- self.window_too_small.write_to_screen(
- cli, screen, mouse_handlers, write_position)
- else:
- # Draw child panes.
- ypos = write_position.ypos
- xpos = write_position.xpos
- width = write_position.width
-
- for s, c in zip(sizes, self.children):
- c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, width, s))
- ypos += s
-
- def _divide_heigths(self, cli, write_position):
- """
- Return the heights for all rows.
- Or None when there is not enough space.
- """
- if not self.children:
- return []
-
- # Calculate heights.
- given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
-
- def get_dimension_for_child(c, index):
- if given_dimensions and given_dimensions[index] is not None:
- return given_dimensions[index]
- else:
+ return sum_layout_dimensions(dimensions)
+
+ def reset(self):
+ for c in self.children:
+ c.reset()
+
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ """
+ Render the prompt to a `Screen` instance.
+
+ :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
+ to which the output has to be written.
+ """
+ sizes = self._divide_heigths(cli, write_position)
+
+ if self.report_dimensions_callback:
+ self.report_dimensions_callback(cli, sizes)
+
+ if sizes is None:
+ self.window_too_small.write_to_screen(
+ cli, screen, mouse_handlers, write_position)
+ else:
+ # Draw child panes.
+ ypos = write_position.ypos
+ xpos = write_position.xpos
+ width = write_position.width
+
+ for s, c in zip(sizes, self.children):
+ c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, width, s))
+ ypos += s
+
+ def _divide_heigths(self, cli, write_position):
+ """
+ Return the heights for all rows.
+ Or None when there is not enough space.
+ """
+ if not self.children:
+ return []
+
+ # Calculate heights.
+ given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
+
+ def get_dimension_for_child(c, index):
+ if given_dimensions and given_dimensions[index] is not None:
+ return given_dimensions[index]
+ else:
return c.preferred_height(cli, write_position.width, write_position.extended_height)
-
- dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
-
- # Sum dimensions
- sum_dimensions = sum_layout_dimensions(dimensions)
-
- # If there is not enough space for both.
- # Don't do anything.
- if sum_dimensions.min > write_position.extended_height:
- return
-
- # Find optimal sizes. (Start with minimal size, increase until we cover
- # the whole height.)
- sizes = [d.min for d in dimensions]
-
- child_generator = take_using_weights(
- items=list(range(len(dimensions))),
- weights=[d.weight for d in dimensions])
-
- i = next(child_generator)
-
- while sum(sizes) < min(write_position.extended_height, sum_dimensions.preferred):
- # Increase until we meet at least the 'preferred' size.
- if sizes[i] < dimensions[i].preferred:
- sizes[i] += 1
- i = next(child_generator)
-
- if not any([cli.is_returning, cli.is_exiting, cli.is_aborting]):
- while sum(sizes) < min(write_position.height, sum_dimensions.max):
- # Increase until we use all the available space. (or until "max")
- if sizes[i] < dimensions[i].max:
- sizes[i] += 1
- i = next(child_generator)
-
- return sizes
-
- def walk(self, cli):
- """ Walk through children. """
- yield self
- for c in self.children:
- for i in c.walk(cli):
- yield i
-
-
-class VSplit(Container):
- """
- Several layouts, one stacked left/right of the other.
-
- :param children: List of child :class:`.Container` objects.
- :param window_too_small: A :class:`.Container` object that is displayed if
- there is not enough space for all the children. By default, this is a
- "Window too small" message.
- :param get_dimensions: (`None` or a callable that takes a
- `CommandLineInterface` and returns a list of `LayoutDimension`
- instances.) By default the dimensions are taken from the children and
- divided by the available space. However, when `get_dimensions` is specified,
- this is taken instead.
- :param report_dimensions_callback: When rendering, this function is called
- with the `CommandLineInterface` and the list of used dimensions. (As a
- list of integers.)
- """
- def __init__(self, children, window_too_small=None,
- get_dimensions=None, report_dimensions_callback=None):
- assert all(isinstance(c, Container) for c in children)
- assert window_too_small is None or isinstance(window_too_small, Container)
- assert get_dimensions is None or callable(get_dimensions)
- assert report_dimensions_callback is None or callable(report_dimensions_callback)
-
- self.children = children
- self.window_too_small = window_too_small or _window_too_small()
- self.get_dimensions = get_dimensions
- self.report_dimensions_callback = report_dimensions_callback
-
- def preferred_width(self, cli, max_available_width):
- dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
- return sum_layout_dimensions(dimensions)
-
+
+ dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
+
+ # Sum dimensions
+ sum_dimensions = sum_layout_dimensions(dimensions)
+
+ # If there is not enough space for both.
+ # Don't do anything.
+ if sum_dimensions.min > write_position.extended_height:
+ return
+
+ # Find optimal sizes. (Start with minimal size, increase until we cover
+ # the whole height.)
+ sizes = [d.min for d in dimensions]
+
+ child_generator = take_using_weights(
+ items=list(range(len(dimensions))),
+ weights=[d.weight for d in dimensions])
+
+ i = next(child_generator)
+
+ while sum(sizes) < min(write_position.extended_height, sum_dimensions.preferred):
+ # Increase until we meet at least the 'preferred' size.
+ if sizes[i] < dimensions[i].preferred:
+ sizes[i] += 1
+ i = next(child_generator)
+
+ if not any([cli.is_returning, cli.is_exiting, cli.is_aborting]):
+ while sum(sizes) < min(write_position.height, sum_dimensions.max):
+ # Increase until we use all the available space. (or until "max")
+ if sizes[i] < dimensions[i].max:
+ sizes[i] += 1
+ i = next(child_generator)
+
+ return sizes
+
+ def walk(self, cli):
+ """ Walk through children. """
+ yield self
+ for c in self.children:
+ for i in c.walk(cli):
+ yield i
+
+
+class VSplit(Container):
+ """
+ Several layouts, one stacked left/right of the other.
+
+ :param children: List of child :class:`.Container` objects.
+ :param window_too_small: A :class:`.Container` object that is displayed if
+ there is not enough space for all the children. By default, this is a
+ "Window too small" message.
+ :param get_dimensions: (`None` or a callable that takes a
+ `CommandLineInterface` and returns a list of `LayoutDimension`
+ instances.) By default the dimensions are taken from the children and
+ divided by the available space. However, when `get_dimensions` is specified,
+ this is taken instead.
+ :param report_dimensions_callback: When rendering, this function is called
+ with the `CommandLineInterface` and the list of used dimensions. (As a
+ list of integers.)
+ """
+ def __init__(self, children, window_too_small=None,
+ get_dimensions=None, report_dimensions_callback=None):
+ assert all(isinstance(c, Container) for c in children)
+ assert window_too_small is None or isinstance(window_too_small, Container)
+ assert get_dimensions is None or callable(get_dimensions)
+ assert report_dimensions_callback is None or callable(report_dimensions_callback)
+
+ self.children = children
+ self.window_too_small = window_too_small or _window_too_small()
+ self.get_dimensions = get_dimensions
+ self.report_dimensions_callback = report_dimensions_callback
+
+ def preferred_width(self, cli, max_available_width):
+ dimensions = [c.preferred_width(cli, max_available_width) for c in self.children]
+ return sum_layout_dimensions(dimensions)
+
def preferred_height(self, cli, width, max_available_height):
- sizes = self._divide_widths(cli, width)
- if sizes is None:
- return LayoutDimension()
- else:
+ sizes = self._divide_widths(cli, width)
+ if sizes is None:
+ return LayoutDimension()
+ else:
dimensions = [c.preferred_height(cli, s, max_available_height)
- for s, c in zip(sizes, self.children)]
- return max_layout_dimensions(dimensions)
-
- def reset(self):
- for c in self.children:
- c.reset()
-
- def _divide_widths(self, cli, width):
- """
- Return the widths for all columns.
- Or None when there is not enough space.
- """
- if not self.children:
- return []
-
- # Calculate widths.
- given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
-
- def get_dimension_for_child(c, index):
- if given_dimensions and given_dimensions[index] is not None:
- return given_dimensions[index]
- else:
- return c.preferred_width(cli, width)
-
- dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
-
- # Sum dimensions
- sum_dimensions = sum_layout_dimensions(dimensions)
-
- # If there is not enough space for both.
- # Don't do anything.
- if sum_dimensions.min > width:
- return
-
- # Find optimal sizes. (Start with minimal size, increase until we cover
- # the whole height.)
- sizes = [d.min for d in dimensions]
-
- child_generator = take_using_weights(
- items=list(range(len(dimensions))),
- weights=[d.weight for d in dimensions])
-
- i = next(child_generator)
-
- while sum(sizes) < min(width, sum_dimensions.preferred):
- # Increase until we meet at least the 'preferred' size.
- if sizes[i] < dimensions[i].preferred:
- sizes[i] += 1
- i = next(child_generator)
-
- while sum(sizes) < min(width, sum_dimensions.max):
- # Increase until we use all the available space.
- if sizes[i] < dimensions[i].max:
- sizes[i] += 1
- i = next(child_generator)
-
- return sizes
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Render the prompt to a `Screen` instance.
-
- :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
- to which the output has to be written.
- """
- if not self.children:
- return
-
- sizes = self._divide_widths(cli, write_position.width)
-
- if self.report_dimensions_callback:
- self.report_dimensions_callback(cli, sizes)
-
- # If there is not enough space.
- if sizes is None:
- self.window_too_small.write_to_screen(
- cli, screen, mouse_handlers, write_position)
- return
-
- # Calculate heights, take the largest possible, but not larger than write_position.extended_height.
+ for s, c in zip(sizes, self.children)]
+ return max_layout_dimensions(dimensions)
+
+ def reset(self):
+ for c in self.children:
+ c.reset()
+
+ def _divide_widths(self, cli, width):
+ """
+ Return the widths for all columns.
+ Or None when there is not enough space.
+ """
+ if not self.children:
+ return []
+
+ # Calculate widths.
+ given_dimensions = self.get_dimensions(cli) if self.get_dimensions else None
+
+ def get_dimension_for_child(c, index):
+ if given_dimensions and given_dimensions[index] is not None:
+ return given_dimensions[index]
+ else:
+ return c.preferred_width(cli, width)
+
+ dimensions = [get_dimension_for_child(c, index) for index, c in enumerate(self.children)]
+
+ # Sum dimensions
+ sum_dimensions = sum_layout_dimensions(dimensions)
+
+ # If there is not enough space for both.
+ # Don't do anything.
+ if sum_dimensions.min > width:
+ return
+
+ # Find optimal sizes. (Start with minimal size, increase until we cover
+ # the whole height.)
+ sizes = [d.min for d in dimensions]
+
+ child_generator = take_using_weights(
+ items=list(range(len(dimensions))),
+ weights=[d.weight for d in dimensions])
+
+ i = next(child_generator)
+
+ while sum(sizes) < min(width, sum_dimensions.preferred):
+ # Increase until we meet at least the 'preferred' size.
+ if sizes[i] < dimensions[i].preferred:
+ sizes[i] += 1
+ i = next(child_generator)
+
+ while sum(sizes) < min(width, sum_dimensions.max):
+ # Increase until we use all the available space.
+ if sizes[i] < dimensions[i].max:
+ sizes[i] += 1
+ i = next(child_generator)
+
+ return sizes
+
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ """
+ Render the prompt to a `Screen` instance.
+
+ :param screen: The :class:`~prompt_toolkit.layout.screen.Screen` class
+ to which the output has to be written.
+ """
+ if not self.children:
+ return
+
+ sizes = self._divide_widths(cli, write_position.width)
+
+ if self.report_dimensions_callback:
+ self.report_dimensions_callback(cli, sizes)
+
+ # If there is not enough space.
+ if sizes is None:
+ self.window_too_small.write_to_screen(
+ cli, screen, mouse_handlers, write_position)
+ return
+
+ # Calculate heights, take the largest possible, but not larger than write_position.extended_height.
heights = [child.preferred_height(cli, width, write_position.extended_height).preferred
- for width, child in zip(sizes, self.children)]
- height = max(write_position.height, min(write_position.extended_height, max(heights)))
-
- # Draw child panes.
- ypos = write_position.ypos
- xpos = write_position.xpos
-
- for s, c in zip(sizes, self.children):
- c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, s, height))
- xpos += s
-
- def walk(self, cli):
- """ Walk through children. """
- yield self
- for c in self.children:
- for i in c.walk(cli):
- yield i
-
-
-class FloatContainer(Container):
- """
- Container which can contain another container for the background, as well
- as a list of floating containers on top of it.
-
- Example Usage::
-
- FloatContainer(content=Window(...),
- floats=[
- Float(xcursor=True,
- ycursor=True,
- layout=CompletionMenu(...))
- ])
- """
- def __init__(self, content, floats):
- assert isinstance(content, Container)
- assert all(isinstance(f, Float) for f in floats)
-
- self.content = content
- self.floats = floats
-
- def reset(self):
- self.content.reset()
-
- for f in self.floats:
- f.content.reset()
-
- def preferred_width(self, cli, write_position):
- return self.content.preferred_width(cli, write_position)
-
+ for width, child in zip(sizes, self.children)]
+ height = max(write_position.height, min(write_position.extended_height, max(heights)))
+
+ # Draw child panes.
+ ypos = write_position.ypos
+ xpos = write_position.xpos
+
+ for s, c in zip(sizes, self.children):
+ c.write_to_screen(cli, screen, mouse_handlers, WritePosition(xpos, ypos, s, height))
+ xpos += s
+
+ def walk(self, cli):
+ """ Walk through children. """
+ yield self
+ for c in self.children:
+ for i in c.walk(cli):
+ yield i
+
+
+class FloatContainer(Container):
+ """
+ Container which can contain another container for the background, as well
+ as a list of floating containers on top of it.
+
+ Example Usage::
+
+ FloatContainer(content=Window(...),
+ floats=[
+ Float(xcursor=True,
+ ycursor=True,
+ layout=CompletionMenu(...))
+ ])
+ """
+ def __init__(self, content, floats):
+ assert isinstance(content, Container)
+ assert all(isinstance(f, Float) for f in floats)
+
+ self.content = content
+ self.floats = floats
+
+ def reset(self):
+ self.content.reset()
+
+ for f in self.floats:
+ f.content.reset()
+
+ def preferred_width(self, cli, write_position):
+ return self.content.preferred_width(cli, write_position)
+
def preferred_height(self, cli, width, max_available_height):
- """
- Return the preferred height of the float container.
- (We don't care about the height of the floats, they should always fit
- into the dimensions provided by the container.)
- """
+ """
+ Return the preferred height of the float container.
+ (We don't care about the height of the floats, they should always fit
+ into the dimensions provided by the container.)
+ """
return self.content.preferred_height(cli, width, max_available_height)
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
-
- for fl in self.floats:
- # When a menu_position was given, use this instead of the cursor
- # position. (These cursor positions are absolute, translate again
- # relative to the write_position.)
- # Note: This should be inside the for-loop, because one float could
- # set the cursor position to be used for the next one.
- cursor_position = screen.menu_position or screen.cursor_position
- cursor_position = Point(x=cursor_position.x - write_position.xpos,
- y=cursor_position.y - write_position.ypos)
-
- fl_width = fl.get_width(cli)
- fl_height = fl.get_height(cli)
-
- # Left & width given.
- if fl.left is not None and fl_width is not None:
- xpos = fl.left
- width = fl_width
- # Left & right given -> calculate width.
- elif fl.left is not None and fl.right is not None:
- xpos = fl.left
- width = write_position.width - fl.left - fl.right
- # Width & right given -> calculate left.
- elif fl_width is not None and fl.right is not None:
- xpos = write_position.width - fl.right - fl_width
- width = fl_width
- elif fl.xcursor:
- width = fl_width
- if width is None:
- width = fl.content.preferred_width(cli, write_position.width).preferred
- width = min(write_position.width, width)
-
- xpos = cursor_position.x
- if xpos + width > write_position.width:
- xpos = max(0, write_position.width - width)
- # Only width given -> center horizontally.
- elif fl_width:
- xpos = int((write_position.width - fl_width) / 2)
- width = fl_width
- # Otherwise, take preferred width from float content.
- else:
- width = fl.content.preferred_width(cli, write_position.width).preferred
-
- if fl.left is not None:
- xpos = fl.left
- elif fl.right is not None:
- xpos = max(0, write_position.width - width - fl.right)
- else: # Center horizontally.
- xpos = max(0, int((write_position.width - width) / 2))
-
- # Trim.
- width = min(width, write_position.width - xpos)
-
- # Top & height given.
- if fl.top is not None and fl_height is not None:
- ypos = fl.top
- height = fl_height
- # Top & bottom given -> calculate height.
- elif fl.top is not None and fl.bottom is not None:
- ypos = fl.top
- height = write_position.height - fl.top - fl.bottom
- # Height & bottom given -> calculate top.
- elif fl_height is not None and fl.bottom is not None:
- ypos = write_position.height - fl_height - fl.bottom
- height = fl_height
- # Near cursor
- elif fl.ycursor:
- ypos = cursor_position.y + 1
-
- height = fl_height
- if height is None:
+
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
+
+ for fl in self.floats:
+ # When a menu_position was given, use this instead of the cursor
+ # position. (These cursor positions are absolute, translate again
+ # relative to the write_position.)
+ # Note: This should be inside the for-loop, because one float could
+ # set the cursor position to be used for the next one.
+ cursor_position = screen.menu_position or screen.cursor_position
+ cursor_position = Point(x=cursor_position.x - write_position.xpos,
+ y=cursor_position.y - write_position.ypos)
+
+ fl_width = fl.get_width(cli)
+ fl_height = fl.get_height(cli)
+
+ # Left & width given.
+ if fl.left is not None and fl_width is not None:
+ xpos = fl.left
+ width = fl_width
+ # Left & right given -> calculate width.
+ elif fl.left is not None and fl.right is not None:
+ xpos = fl.left
+ width = write_position.width - fl.left - fl.right
+ # Width & right given -> calculate left.
+ elif fl_width is not None and fl.right is not None:
+ xpos = write_position.width - fl.right - fl_width
+ width = fl_width
+ elif fl.xcursor:
+ width = fl_width
+ if width is None:
+ width = fl.content.preferred_width(cli, write_position.width).preferred
+ width = min(write_position.width, width)
+
+ xpos = cursor_position.x
+ if xpos + width > write_position.width:
+ xpos = max(0, write_position.width - width)
+ # Only width given -> center horizontally.
+ elif fl_width:
+ xpos = int((write_position.width - fl_width) / 2)
+ width = fl_width
+ # Otherwise, take preferred width from float content.
+ else:
+ width = fl.content.preferred_width(cli, write_position.width).preferred
+
+ if fl.left is not None:
+ xpos = fl.left
+ elif fl.right is not None:
+ xpos = max(0, write_position.width - width - fl.right)
+ else: # Center horizontally.
+ xpos = max(0, int((write_position.width - width) / 2))
+
+ # Trim.
+ width = min(width, write_position.width - xpos)
+
+ # Top & height given.
+ if fl.top is not None and fl_height is not None:
+ ypos = fl.top
+ height = fl_height
+ # Top & bottom given -> calculate height.
+ elif fl.top is not None and fl.bottom is not None:
+ ypos = fl.top
+ height = write_position.height - fl.top - fl.bottom
+ # Height & bottom given -> calculate top.
+ elif fl_height is not None and fl.bottom is not None:
+ ypos = write_position.height - fl_height - fl.bottom
+ height = fl_height
+ # Near cursor
+ elif fl.ycursor:
+ ypos = cursor_position.y + 1
+
+ height = fl_height
+ if height is None:
height = fl.content.preferred_height(
cli, width, write_position.extended_height).preferred
-
- # Reduce height if not enough space. (We can use the
- # extended_height when the content requires it.)
- if height > write_position.extended_height - ypos:
- if write_position.extended_height - ypos + 1 >= ypos:
- # When the space below the cursor is more than
- # the space above, just reduce the height.
- height = write_position.extended_height - ypos
- else:
- # Otherwise, fit the float above the cursor.
- height = min(height, cursor_position.y)
- ypos = cursor_position.y - height
-
- # Only height given -> center vertically.
- elif fl_width:
- ypos = int((write_position.height - fl_height) / 2)
- height = fl_height
- # Otherwise, take preferred height from content.
- else:
+
+ # Reduce height if not enough space. (We can use the
+ # extended_height when the content requires it.)
+ if height > write_position.extended_height - ypos:
+ if write_position.extended_height - ypos + 1 >= ypos:
+ # When the space below the cursor is more than
+ # the space above, just reduce the height.
+ height = write_position.extended_height - ypos
+ else:
+ # Otherwise, fit the float above the cursor.
+ height = min(height, cursor_position.y)
+ ypos = cursor_position.y - height
+
+ # Only height given -> center vertically.
+ elif fl_width:
+ ypos = int((write_position.height - fl_height) / 2)
+ height = fl_height
+ # Otherwise, take preferred height from content.
+ else:
height = fl.content.preferred_height(
cli, width, write_position.extended_height).preferred
-
- if fl.top is not None:
- ypos = fl.top
- elif fl.bottom is not None:
- ypos = max(0, write_position.height - height - fl.bottom)
- else: # Center vertically.
- ypos = max(0, int((write_position.height - height) / 2))
-
- # Trim.
- height = min(height, write_position.height - ypos)
-
- # Write float.
- # (xpos and ypos can be negative: a float can be partially visible.)
- if height > 0 and width > 0:
- wp = WritePosition(xpos=xpos + write_position.xpos,
- ypos=ypos + write_position.ypos,
- width=width, height=height)
-
+
+ if fl.top is not None:
+ ypos = fl.top
+ elif fl.bottom is not None:
+ ypos = max(0, write_position.height - height - fl.bottom)
+ else: # Center vertically.
+ ypos = max(0, int((write_position.height - height) / 2))
+
+ # Trim.
+ height = min(height, write_position.height - ypos)
+
+ # Write float.
+ # (xpos and ypos can be negative: a float can be partially visible.)
+ if height > 0 and width > 0:
+ wp = WritePosition(xpos=xpos + write_position.xpos,
+ ypos=ypos + write_position.ypos,
+ width=width, height=height)
+
if not fl.hide_when_covering_content or self._area_is_empty(screen, wp):
fl.content.write_to_screen(cli, screen, mouse_handlers, wp)
@@ -530,80 +530,80 @@ class FloatContainer(Container):
return True
- def walk(self, cli):
- """ Walk through children. """
- yield self
-
- for i in self.content.walk(cli):
- yield i
-
- for f in self.floats:
- for i in f.content.walk(cli):
- yield i
-
-
-class Float(object):
- """
- Float for use in a :class:`.FloatContainer`.
-
- :param content: :class:`.Container` instance.
+ def walk(self, cli):
+ """ Walk through children. """
+ yield self
+
+ for i in self.content.walk(cli):
+ yield i
+
+ for f in self.floats:
+ for i in f.content.walk(cli):
+ yield i
+
+
+class Float(object):
+ """
+ Float for use in a :class:`.FloatContainer`.
+
+ :param content: :class:`.Container` instance.
:param hide_when_covering_content: Hide the float when it covers content underneath.
- """
- def __init__(self, top=None, right=None, bottom=None, left=None,
- width=None, height=None, get_width=None, get_height=None,
+ """
+ def __init__(self, top=None, right=None, bottom=None, left=None,
+ width=None, height=None, get_width=None, get_height=None,
xcursor=False, ycursor=False, content=None,
hide_when_covering_content=False):
- assert isinstance(content, Container)
- assert width is None or get_width is None
- assert height is None or get_height is None
-
- self.left = left
- self.right = right
- self.top = top
- self.bottom = bottom
-
- self._width = width
- self._height = height
-
- self._get_width = get_width
- self._get_height = get_height
-
- self.xcursor = xcursor
- self.ycursor = ycursor
-
- self.content = content
+ assert isinstance(content, Container)
+ assert width is None or get_width is None
+ assert height is None or get_height is None
+
+ self.left = left
+ self.right = right
+ self.top = top
+ self.bottom = bottom
+
+ self._width = width
+ self._height = height
+
+ self._get_width = get_width
+ self._get_height = get_height
+
+ self.xcursor = xcursor
+ self.ycursor = ycursor
+
+ self.content = content
self.hide_when_covering_content = hide_when_covering_content
-
- def get_width(self, cli):
- if self._width:
- return self._width
- if self._get_width:
- return self._get_width(cli)
-
- def get_height(self, cli):
- if self._height:
- return self._height
- if self._get_height:
- return self._get_height(cli)
-
- def __repr__(self):
- return 'Float(content=%r)' % self.content
-
-
-class WindowRenderInfo(object):
- """
- Render information, for the last render time of this control.
- It stores mapping information between the input buffers (in case of a
- :class:`~prompt_toolkit.layout.controls.BufferControl`) and the actual
- render position on the output screen.
-
- (Could be used for implementation of the Vi 'H' and 'L' key bindings as
- well as implementing mouse support.)
-
+
+ def get_width(self, cli):
+ if self._width:
+ return self._width
+ if self._get_width:
+ return self._get_width(cli)
+
+ def get_height(self, cli):
+ if self._height:
+ return self._height
+ if self._get_height:
+ return self._get_height(cli)
+
+ def __repr__(self):
+ return 'Float(content=%r)' % self.content
+
+
+class WindowRenderInfo(object):
+ """
+ Render information, for the last render time of this control.
+ It stores mapping information between the input buffers (in case of a
+ :class:`~prompt_toolkit.layout.controls.BufferControl`) and the actual
+ render position on the output screen.
+
+ (Could be used for implementation of the Vi 'H' and 'L' key bindings as
+ well as implementing mouse support.)
+
:param ui_content: The original :class:`.UIContent` instance that contains
the whole input, without clipping. (ui_content)
- :param horizontal_scroll: The horizontal scroll of the :class:`.Window` instance.
- :param vertical_scroll: The vertical scroll of the :class:`.Window` instance.
+ :param horizontal_scroll: The horizontal scroll of the :class:`.Window` instance.
+ :param vertical_scroll: The vertical scroll of the :class:`.Window` instance.
:param window_width: The width of the window that displays the content,
without the margins.
:param window_height: The height of the window that displays the content.
@@ -615,7 +615,7 @@ class WindowRenderInfo(object):
:param rowcol_to_yx: Mapping that maps (row, column) tuples representing
coordinates of the :class:`UIContent` to (y, x) absolute coordinates at
the rendered screen.
- """
+ """
def __init__(self, ui_content, horizontal_scroll, vertical_scroll,
window_width, window_height,
configured_scroll_offsets,
@@ -634,20 +634,20 @@ class WindowRenderInfo(object):
assert isinstance(wrap_lines, bool)
self.ui_content = ui_content
- self.vertical_scroll = vertical_scroll
+ self.vertical_scroll = vertical_scroll
self.window_width = window_width # Width without margins.
- self.window_height = window_height
+ self.window_height = window_height
- self.configured_scroll_offsets = configured_scroll_offsets
+ self.configured_scroll_offsets = configured_scroll_offsets
self.visible_line_to_row_col = visible_line_to_row_col
self.wrap_lines = wrap_lines
-
+
self._rowcol_to_yx = rowcol_to_yx # row/col from input to absolute y/x
# screen coordinates.
self._x_offset = x_offset
self._y_offset = y_offset
- @property
+ @property
def visible_line_to_input_line(self):
return dict(
(visible_line, rowcol[0])
@@ -655,29 +655,29 @@ class WindowRenderInfo(object):
@property
def cursor_position(self):
- """
+ """
Return the cursor position coordinates, relative to the left/top corner
of the rendered screen.
- """
+ """
cpos = self.ui_content.cursor_position
y, x = self._rowcol_to_yx[cpos.y, cpos.x]
return Point(x=x - self._x_offset, y=y - self._y_offset)
-
- @property
+
+ @property
def applied_scroll_offsets(self):
- """
+ """
Return a :class:`.ScrollOffsets` instance that indicates the actual
offset. This can be less than or equal to what's configured. E.g, when
the cursor is completely at the top, the top offset will be zero rather
than what's configured.
- """
+ """
if self.displayed_lines[0] == 0:
top = 0
else:
# Get row where the cursor is displayed.
y = self.input_line_to_visible_line[self.ui_content.cursor_position.y]
top = min(y, self.configured_scroll_offsets.top)
-
+
return ScrollOffsets(
top=top,
bottom=min(self.ui_content.line_count - self.displayed_lines[-1] - 1,
@@ -688,14 +688,14 @@ class WindowRenderInfo(object):
# double width characters in mind.)
left=0, right=0)
- @property
+ @property
def displayed_lines(self):
- """
+ """
List of all the visible rows. (Line numbers of the input buffer.)
The last line may not be entirely visible.
- """
+ """
return sorted(row for row, col in self.visible_line_to_row_col.values())
-
+
@property
def input_line_to_visible_line(self):
"""
@@ -711,74 +711,74 @@ class WindowRenderInfo(object):
result[v] = k
return result
- def first_visible_line(self, after_scroll_offset=False):
- """
- Return the line number (0 based) of the input document that corresponds
- with the first visible line.
- """
- if after_scroll_offset:
+ def first_visible_line(self, after_scroll_offset=False):
+ """
+ Return the line number (0 based) of the input document that corresponds
+ with the first visible line.
+ """
+ if after_scroll_offset:
return self.displayed_lines[self.applied_scroll_offsets.top]
else:
return self.displayed_lines[0]
-
- def last_visible_line(self, before_scroll_offset=False):
- """
- Like `first_visible_line`, but for the last visible line.
- """
- if before_scroll_offset:
+
+ def last_visible_line(self, before_scroll_offset=False):
+ """
+ Like `first_visible_line`, but for the last visible line.
+ """
+ if before_scroll_offset:
return self.displayed_lines[-1 - self.applied_scroll_offsets.bottom]
else:
return self.displayed_lines[-1]
-
- def center_visible_line(self, before_scroll_offset=False,
- after_scroll_offset=False):
- """
- Like `first_visible_line`, but for the center visible line.
- """
- return (self.first_visible_line(after_scroll_offset) +
- (self.last_visible_line(before_scroll_offset) -
+
+ def center_visible_line(self, before_scroll_offset=False,
+ after_scroll_offset=False):
+ """
+ Like `first_visible_line`, but for the center visible line.
+ """
+ return (self.first_visible_line(after_scroll_offset) +
+ (self.last_visible_line(before_scroll_offset) -
self.first_visible_line(after_scroll_offset)) // 2
- )
-
- @property
- def content_height(self):
- """
- The full height of the user control.
- """
+ )
+
+ @property
+ def content_height(self):
+ """
+ The full height of the user control.
+ """
return self.ui_content.line_count
-
- @property
- def full_height_visible(self):
- """
- True when the full height is visible (There is no vertical scroll.)
- """
+
+ @property
+ def full_height_visible(self):
+ """
+ True when the full height is visible (There is no vertical scroll.)
+ """
return self.vertical_scroll == 0 and self.last_visible_line() == self.content_height
-
- @property
- def top_visible(self):
- """
- True when the top of the buffer is visible.
- """
- return self.vertical_scroll == 0
-
- @property
- def bottom_visible(self):
- """
- True when the bottom of the buffer is visible.
- """
+
+ @property
+ def top_visible(self):
+ """
+ True when the top of the buffer is visible.
+ """
+ return self.vertical_scroll == 0
+
+ @property
+ def bottom_visible(self):
+ """
+ True when the bottom of the buffer is visible.
+ """
return self.last_visible_line() == self.content_height - 1
-
- @property
- def vertical_scroll_percentage(self):
- """
- Vertical scroll as a percentage. (0 means: the top is visible,
- 100 means: the bottom is visible.)
- """
+
+ @property
+ def vertical_scroll_percentage(self):
+ """
+ Vertical scroll as a percentage. (0 means: the top is visible,
+ 100 means: the bottom is visible.)
+ """
if self.bottom_visible:
return 100
else:
return (100 * self.vertical_scroll // self.content_height)
-
+
def get_height_for_line(self, lineno):
"""
Return the height of the given line.
@@ -788,20 +788,20 @@ class WindowRenderInfo(object):
return self.ui_content.get_height_for_line(lineno, self.window_width)
else:
return 1
-
-
-class ScrollOffsets(object):
- """
- Scroll offsets for the :class:`.Window` class.
-
- Note that left/right offsets only make sense if line wrapping is disabled.
- """
- def __init__(self, top=0, bottom=0, left=0, right=0):
+
+
+class ScrollOffsets(object):
+ """
+ Scroll offsets for the :class:`.Window` class.
+
+ Note that left/right offsets only make sense if line wrapping is disabled.
+ """
+ def __init__(self, top=0, bottom=0, left=0, right=0):
assert isinstance(top, Integer)
assert isinstance(bottom, Integer)
assert isinstance(left, Integer)
assert isinstance(right, Integer)
-
+
self._top = top
self._bottom = bottom
self._left = left
@@ -823,11 +823,11 @@ class ScrollOffsets(object):
def right(self):
return int(self._right)
- def __repr__(self):
- return 'ScrollOffsets(top=%r, bottom=%r, left=%r, right=%r)' % (
- self.top, self.bottom, self.left, self.right)
-
-
+ def __repr__(self):
+ return 'ScrollOffsets(top=%r, bottom=%r, left=%r, right=%r)' % (
+ self.top, self.bottom, self.left, self.right)
+
+
class ColorColumn(object):
def __init__(self, position, token=Token.ColorColumn):
self.position = position
@@ -837,46 +837,46 @@ class ColorColumn(object):
_in_insert_mode = ViInsertMode() | EmacsInsertMode()
-class Window(Container):
- """
- Container that holds a control.
-
- :param content: :class:`~prompt_toolkit.layout.controls.UIControl` instance.
- :param width: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
- :param height: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
- :param get_width: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
- :param get_height: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
- :param dont_extend_width: When `True`, don't take up more width then the
- preferred width reported by the control.
- :param dont_extend_height: When `True`, don't take up more width then the
- preferred height reported by the control.
- :param left_margins: A list of :class:`~prompt_toolkit.layout.margins.Margin`
- instance to be displayed on the left. For instance:
- :class:`~prompt_toolkit.layout.margins.NumberredMargin` can be one of
- them in order to show line numbers.
- :param right_margins: Like `left_margins`, but on the other side.
- :param scroll_offsets: :class:`.ScrollOffsets` instance, representing the
- preferred amount of lines/columns to be always visible before/after the
- cursor. When both top and bottom are a very high number, the cursor
- will be centered vertically most of the time.
- :param allow_scroll_beyond_bottom: A `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, allow
- scrolling so far, that the top part of the content is not visible
- anymore, while there is still empty space available at the bottom of
- the window. In the Vi editor for instance, this is possible. You will
- see tildes while the top part of the body is hidden.
+class Window(Container):
+ """
+ Container that holds a control.
+
+ :param content: :class:`~prompt_toolkit.layout.controls.UIControl` instance.
+ :param width: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
+ :param height: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
+ :param get_width: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
+ :param get_height: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
+ :param dont_extend_width: When `True`, don't take up more width then the
+ preferred width reported by the control.
+ :param dont_extend_height: When `True`, don't take up more width then the
+ preferred height reported by the control.
+ :param left_margins: A list of :class:`~prompt_toolkit.layout.margins.Margin`
+ instance to be displayed on the left. For instance:
+ :class:`~prompt_toolkit.layout.margins.NumberredMargin` can be one of
+ them in order to show line numbers.
+ :param right_margins: Like `left_margins`, but on the other side.
+ :param scroll_offsets: :class:`.ScrollOffsets` instance, representing the
+ preferred amount of lines/columns to be always visible before/after the
+ cursor. When both top and bottom are a very high number, the cursor
+ will be centered vertically most of the time.
+ :param allow_scroll_beyond_bottom: A `bool` or
+ :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, allow
+ scrolling so far, that the top part of the content is not visible
+ anymore, while there is still empty space available at the bottom of
+ the window. In the Vi editor for instance, this is possible. You will
+ see tildes while the top part of the body is hidden.
:param wrap_lines: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
instance. When True, don't scroll horizontally, but wrap lines instead.
- :param get_vertical_scroll: Callable that takes this window
- instance as input and returns a preferred vertical scroll.
- (When this is `None`, the scroll is only determined by the last and
- current cursor position.)
- :param get_horizontal_scroll: Callable that takes this window
- instance as input and returns a preferred vertical scroll.
- :param always_hide_cursor: A `bool` or
- :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, never
- display the cursor, even when the user control specifies a cursor
- position.
+ :param get_vertical_scroll: Callable that takes this window
+ instance as input and returns a preferred vertical scroll.
+ (When this is `None`, the scroll is only determined by the last and
+ current cursor position.)
+ :param get_horizontal_scroll: Callable that takes this window
+ instance as input and returns a preferred vertical scroll.
+ :param always_hide_cursor: A `bool` or
+ :class:`~prompt_toolkit.filters.CLIFilter` instance. When True, never
+ display the cursor, even when the user control specifies a cursor
+ position.
:param cursorline: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
instance. When True, display a cursorline.
:param cursorcolumn: A `bool` or :class:`~prompt_toolkit.filters.CLIFilter`
@@ -888,73 +888,73 @@ class Window(Container):
if `cursorline` is True.
:param cursorcolumn_token: The token to be used for highlighting the current line,
if `cursorcolumn` is True.
- """
- def __init__(self, content, width=None, height=None, get_width=None,
- get_height=None, dont_extend_width=False, dont_extend_height=False,
- left_margins=None, right_margins=None, scroll_offsets=None,
+ """
+ def __init__(self, content, width=None, height=None, get_width=None,
+ get_height=None, dont_extend_width=False, dont_extend_height=False,
+ left_margins=None, right_margins=None, scroll_offsets=None,
allow_scroll_beyond_bottom=False, wrap_lines=False,
get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False,
cursorline=False, cursorcolumn=False, get_colorcolumns=None,
cursorline_token=Token.CursorLine, cursorcolumn_token=Token.CursorColumn):
- assert isinstance(content, UIControl)
- assert width is None or isinstance(width, LayoutDimension)
- assert height is None or isinstance(height, LayoutDimension)
- assert get_width is None or callable(get_width)
- assert get_height is None or callable(get_height)
- assert width is None or get_width is None
- assert height is None or get_height is None
- assert scroll_offsets is None or isinstance(scroll_offsets, ScrollOffsets)
- assert left_margins is None or all(isinstance(m, Margin) for m in left_margins)
- assert right_margins is None or all(isinstance(m, Margin) for m in right_margins)
- assert get_vertical_scroll is None or callable(get_vertical_scroll)
- assert get_horizontal_scroll is None or callable(get_horizontal_scroll)
+ assert isinstance(content, UIControl)
+ assert width is None or isinstance(width, LayoutDimension)
+ assert height is None or isinstance(height, LayoutDimension)
+ assert get_width is None or callable(get_width)
+ assert get_height is None or callable(get_height)
+ assert width is None or get_width is None
+ assert height is None or get_height is None
+ assert scroll_offsets is None or isinstance(scroll_offsets, ScrollOffsets)
+ assert left_margins is None or all(isinstance(m, Margin) for m in left_margins)
+ assert right_margins is None or all(isinstance(m, Margin) for m in right_margins)
+ assert get_vertical_scroll is None or callable(get_vertical_scroll)
+ assert get_horizontal_scroll is None or callable(get_horizontal_scroll)
assert get_colorcolumns is None or callable(get_colorcolumns)
-
- self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom)
- self.always_hide_cursor = to_cli_filter(always_hide_cursor)
+
+ self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom)
+ self.always_hide_cursor = to_cli_filter(always_hide_cursor)
self.wrap_lines = to_cli_filter(wrap_lines)
self.cursorline = to_cli_filter(cursorline)
self.cursorcolumn = to_cli_filter(cursorcolumn)
-
- self.content = content
- self.dont_extend_width = dont_extend_width
- self.dont_extend_height = dont_extend_height
- self.left_margins = left_margins or []
- self.right_margins = right_margins or []
- self.scroll_offsets = scroll_offsets or ScrollOffsets()
- self.get_vertical_scroll = get_vertical_scroll
- self.get_horizontal_scroll = get_horizontal_scroll
- self._width = get_width or (lambda cli: width)
- self._height = get_height or (lambda cli: height)
+
+ self.content = content
+ self.dont_extend_width = dont_extend_width
+ self.dont_extend_height = dont_extend_height
+ self.left_margins = left_margins or []
+ self.right_margins = right_margins or []
+ self.scroll_offsets = scroll_offsets or ScrollOffsets()
+ self.get_vertical_scroll = get_vertical_scroll
+ self.get_horizontal_scroll = get_horizontal_scroll
+ self._width = get_width or (lambda cli: width)
+ self._height = get_height or (lambda cli: height)
self.get_colorcolumns = get_colorcolumns or (lambda cli: [])
self.cursorline_token = cursorline_token
self.cursorcolumn_token = cursorcolumn_token
-
- # Cache for the screens generated by the margin.
+
+ # Cache for the screens generated by the margin.
self._ui_content_cache = SimpleCache(maxsize=8)
self._margin_width_cache = SimpleCache(maxsize=1)
-
- self.reset()
-
- def __repr__(self):
- return 'Window(content=%r)' % self.content
-
- def reset(self):
- self.content.reset()
-
- #: Scrolling position of the main content.
- self.vertical_scroll = 0
- self.horizontal_scroll = 0
-
+
+ self.reset()
+
+ def __repr__(self):
+ return 'Window(content=%r)' % self.content
+
+ def reset(self):
+ self.content.reset()
+
+ #: Scrolling position of the main content.
+ self.vertical_scroll = 0
+ self.horizontal_scroll = 0
+
# Vertical scroll 2: this is the vertical offset that a line is
# scrolled if a single line (the one that contains the cursor) consumes
# all of the vertical space.
self.vertical_scroll_2 = 0
- #: Keep render information (mappings between buffer input and render
- #: output.)
- self.render_info = None
-
+ #: Keep render information (mappings between buffer input and render
+ #: output.)
+ self.render_info = None
+
def _get_margin_width(self, cli, margin):
"""
Return the width for this margin.
@@ -970,70 +970,70 @@ class Window(Container):
key = (margin, cli.render_counter)
return self._margin_width_cache.get(key, get_width)
- def preferred_width(self, cli, max_available_width):
+ def preferred_width(self, cli, max_available_width):
# Calculate the width of the margin.
total_margin_width = sum(self._get_margin_width(cli, m) for m in
- self.left_margins + self.right_margins)
-
+ self.left_margins + self.right_margins)
+
# Window of the content. (Can be `None`.)
- preferred_width = self.content.preferred_width(
- cli, max_available_width - total_margin_width)
-
- if preferred_width is not None:
+ preferred_width = self.content.preferred_width(
+ cli, max_available_width - total_margin_width)
+
+ if preferred_width is not None:
# Include width of the margins.
- preferred_width += total_margin_width
-
- # Merge.
- return self._merge_dimensions(
- dimension=self._width(cli),
- preferred=preferred_width,
- dont_extend=self.dont_extend_width)
-
+ preferred_width += total_margin_width
+
+ # Merge.
+ return self._merge_dimensions(
+ dimension=self._width(cli),
+ preferred=preferred_width,
+ dont_extend=self.dont_extend_width)
+
def preferred_height(self, cli, width, max_available_height):
total_margin_width = sum(self._get_margin_width(cli, m) for m in
self.left_margins + self.right_margins)
wrap_lines = self.wrap_lines(cli)
- return self._merge_dimensions(
- dimension=self._height(cli),
+ return self._merge_dimensions(
+ dimension=self._height(cli),
preferred=self.content.preferred_height(
cli, width - total_margin_width, max_available_height, wrap_lines),
- dont_extend=self.dont_extend_height)
-
- @staticmethod
- def _merge_dimensions(dimension, preferred=None, dont_extend=False):
- """
- Take the LayoutDimension from this `Window` class and the received
- preferred size from the `UIControl` and return a `LayoutDimension` to
- report to the parent container.
- """
- dimension = dimension or LayoutDimension()
-
- # When a preferred dimension was explicitly given to the Window,
- # ignore the UIControl.
- if dimension.preferred_specified:
- preferred = dimension.preferred
-
- # When a 'preferred' dimension is given by the UIControl, make sure
- # that it stays within the bounds of the Window.
- if preferred is not None:
- if dimension.max:
- preferred = min(preferred, dimension.max)
-
- if dimension.min:
- preferred = max(preferred, dimension.min)
-
- # When a `dont_extend` flag has been given, use the preferred dimension
- # also as the max dimension.
- if dont_extend and preferred is not None:
- max_ = min(dimension.max, preferred)
- else:
- max_ = dimension.max
-
+ dont_extend=self.dont_extend_height)
+
+ @staticmethod
+ def _merge_dimensions(dimension, preferred=None, dont_extend=False):
+ """
+ Take the LayoutDimension from this `Window` class and the received
+ preferred size from the `UIControl` and return a `LayoutDimension` to
+ report to the parent container.
+ """
+ dimension = dimension or LayoutDimension()
+
+ # When a preferred dimension was explicitly given to the Window,
+ # ignore the UIControl.
+ if dimension.preferred_specified:
+ preferred = dimension.preferred
+
+ # When a 'preferred' dimension is given by the UIControl, make sure
+ # that it stays within the bounds of the Window.
+ if preferred is not None:
+ if dimension.max:
+ preferred = min(preferred, dimension.max)
+
+ if dimension.min:
+ preferred = max(preferred, dimension.min)
+
+ # When a `dont_extend` flag has been given, use the preferred dimension
+ # also as the max dimension.
+ if dont_extend and preferred is not None:
+ max_ = min(dimension.max, preferred)
+ else:
+ max_ = dimension.max
+
return LayoutDimension(
min=dimension.min, max=max_,
preferred=preferred, weight=dimension.weight)
-
+
def _get_ui_content(self, cli, width, height):
"""
Create a `UIContent` instance.
@@ -1054,28 +1054,28 @@ class Window(Container):
return '?'
return False
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- """
- Write window to screen. This renders the user control, the margins and
- copies everything over to the absolute position at the given screen.
- """
- # Calculate margin sizes.
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ """
+ Write window to screen. This renders the user control, the margins and
+ copies everything over to the absolute position at the given screen.
+ """
+ # Calculate margin sizes.
left_margin_widths = [self._get_margin_width(cli, m) for m in self.left_margins]
right_margin_widths = [self._get_margin_width(cli, m) for m in self.right_margins]
- total_margin_width = sum(left_margin_widths + right_margin_widths)
-
- # Render UserControl.
+ total_margin_width = sum(left_margin_widths + right_margin_widths)
+
+ # Render UserControl.
ui_content = self.content.create_content(
- cli, write_position.width - total_margin_width, write_position.height)
+ cli, write_position.width - total_margin_width, write_position.height)
assert isinstance(ui_content, UIContent)
-
- # Scroll content.
+
+ # Scroll content.
wrap_lines = self.wrap_lines(cli)
scroll_func = self._scroll_when_linewrapping if wrap_lines else self._scroll_without_linewrapping
-
+
scroll_func(
ui_content, write_position.width - total_margin_width, write_position.height, cli)
-
+
# Write body
visible_line_to_row_col, rowcol_to_yx = self._copy_body(
cli, ui_content, screen, write_position,
@@ -1086,37 +1086,37 @@ class Window(Container):
vertical_scroll_2=self.vertical_scroll_2,
always_hide_cursor=self.always_hide_cursor(cli))
- # Remember render info. (Set before generating the margins. They need this.)
+ # Remember render info. (Set before generating the margins. They need this.)
x_offset=write_position.xpos + sum(left_margin_widths)
y_offset=write_position.ypos
- self.render_info = WindowRenderInfo(
+ self.render_info = WindowRenderInfo(
ui_content=ui_content,
- horizontal_scroll=self.horizontal_scroll,
- vertical_scroll=self.vertical_scroll,
+ horizontal_scroll=self.horizontal_scroll,
+ vertical_scroll=self.vertical_scroll,
window_width=write_position.width - total_margin_width,
- window_height=write_position.height,
- configured_scroll_offsets=self.scroll_offsets,
+ window_height=write_position.height,
+ configured_scroll_offsets=self.scroll_offsets,
visible_line_to_row_col=visible_line_to_row_col,
rowcol_to_yx=rowcol_to_yx,
x_offset=x_offset,
y_offset=y_offset,
wrap_lines=wrap_lines)
-
- # Set mouse handlers.
- def mouse_handler(cli, mouse_event):
- """ Wrapper around the mouse_handler of the `UIControl` that turns
+
+ # Set mouse handlers.
+ def mouse_handler(cli, mouse_event):
+ """ Wrapper around the mouse_handler of the `UIControl` that turns
screen coordinates into line coordinates. """
# Find row/col position first.
yx_to_rowcol = dict((v, k) for k, v in rowcol_to_yx.items())
y = mouse_event.position.y
x = mouse_event.position.x
-
+
# If clicked below the content area, look for a position in the
# last line instead.
max_y = write_position.ypos + len(visible_line_to_row_col) - 1
y = min(max_y, y)
-
+
while x >= 0:
try:
row, col = yx_to_rowcol[y, x]
@@ -1139,72 +1139,72 @@ class Window(Container):
cli, MouseEvent(position=Point(x=0, y=0),
event_type=mouse_event.event_type))
- # If it returns NotImplemented, handle it here.
- if result == NotImplemented:
- return self._mouse_handler(cli, mouse_event)
-
- return result
-
- mouse_handlers.set_mouse_handler_for_range(
- x_min=write_position.xpos + sum(left_margin_widths),
- x_max=write_position.xpos + write_position.width - total_margin_width,
- y_min=write_position.ypos,
- y_max=write_position.ypos + write_position.height,
- handler=mouse_handler)
-
- # Render and copy margins.
- move_x = 0
-
- def render_margin(m, width):
- " Render margin. Return `Screen`. "
- # Retrieve margin tokens.
- tokens = m.create_margin(cli, self.render_info, width, write_position.height)
-
+ # If it returns NotImplemented, handle it here.
+ if result == NotImplemented:
+ return self._mouse_handler(cli, mouse_event)
+
+ return result
+
+ mouse_handlers.set_mouse_handler_for_range(
+ x_min=write_position.xpos + sum(left_margin_widths),
+ x_max=write_position.xpos + write_position.width - total_margin_width,
+ y_min=write_position.ypos,
+ y_max=write_position.ypos + write_position.height,
+ handler=mouse_handler)
+
+ # Render and copy margins.
+ move_x = 0
+
+ def render_margin(m, width):
+ " Render margin. Return `Screen`. "
+ # Retrieve margin tokens.
+ tokens = m.create_margin(cli, self.render_info, width, write_position.height)
+
# Turn it into a UIContent object.
- # already rendered those tokens using this size.)
+ # already rendered those tokens using this size.)
return TokenListControl.static(tokens).create_content(
cli, width + 1, write_position.height)
-
- for m, width in zip(self.left_margins, left_margin_widths):
- # Create screen for margin.
- margin_screen = render_margin(m, width)
-
- # Copy and shift X.
+
+ for m, width in zip(self.left_margins, left_margin_widths):
+ # Create screen for margin.
+ margin_screen = render_margin(m, width)
+
+ # Copy and shift X.
self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
- move_x += width
-
- move_x = write_position.width - sum(right_margin_widths)
-
- for m, width in zip(self.right_margins, right_margin_widths):
- # Create screen for margin.
- margin_screen = render_margin(m, width)
-
- # Copy and shift X.
+ move_x += width
+
+ move_x = write_position.width - sum(right_margin_widths)
+
+ for m, width in zip(self.right_margins, right_margin_widths):
+ # Create screen for margin.
+ margin_screen = render_margin(m, width)
+
+ # Copy and shift X.
self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
- move_x += width
-
+ move_x += width
+
def _copy_body(self, cli, ui_content, new_screen, write_position, move_x,
width, vertical_scroll=0, horizontal_scroll=0,
has_focus=False, wrap_lines=False, highlight_lines=False,
vertical_scroll_2=0, always_hide_cursor=False):
- """
+ """
Copy the UIContent into the output screen.
- """
- xpos = write_position.xpos + move_x
- ypos = write_position.ypos
+ """
+ xpos = write_position.xpos + move_x
+ ypos = write_position.ypos
line_count = ui_content.line_count
- new_buffer = new_screen.data_buffer
+ new_buffer = new_screen.data_buffer
empty_char = _CHAR_CACHE['', Token]
ZeroWidthEscape = Token.ZeroWidthEscape
-
+
# Map visible line number to (row, col) of input.
# 'col' will always be zero if line wrapping is off.
visible_line_to_row_col = {}
rowcol_to_yx = {} # Maps (row, col) from the input to (y, x) screen coordinates.
-
+
# Fill background with default_char first.
default_char = ui_content.default_char
-
+
if default_char:
for y in range(ypos, ypos + write_position.height):
new_buffer_row = new_buffer[y]
@@ -1295,33 +1295,33 @@ class Window(Container):
# 'Invalid position. row=%r col=%r, vertical_scroll=%r, '
# 'horizontal_scroll=%r, height=%r' %
# (row, col, vertical_scroll, horizontal_scroll, write_position.height))
- else:
+ else:
return Point(y=y, x=x)
-
+
# Set cursor and menu positions.
if ui_content.cursor_position:
screen_cursor_position = cursor_pos_to_screen_pos(
ui_content.cursor_position.y, ui_content.cursor_position.x)
-
+
if has_focus:
new_screen.cursor_position = screen_cursor_position
-
+
if always_hide_cursor:
new_screen.show_cursor = False
else:
new_screen.show_cursor = ui_content.show_cursor
-
+
self._highlight_digraph(cli, new_screen)
-
+
if highlight_lines:
self._highlight_cursorlines(
cli, new_screen, screen_cursor_position, xpos, ypos, width,
write_position.height)
-
+
# Draw input characters from the input processor queue.
if has_focus and ui_content.cursor_position:
self._show_input_processor_key_buffer(cli, new_screen)
-
+
# Set menu position.
if not new_screen.menu_position and ui_content.menu_position:
new_screen.menu_position = cursor_pos_to_screen_pos(
@@ -1333,7 +1333,7 @@ class Window(Container):
return visible_line_to_row_col, rowcol_to_yx
def _highlight_digraph(self, cli, new_screen):
- """
+ """
When we are in Vi digraph mode, put a question mark underneath the
cursor.
"""
@@ -1403,24 +1403,24 @@ class Window(Container):
def _copy_margin(self, cli, lazy_screen, new_screen, write_position, move_x, width):
"""
- Copy characters from the margin screen to the real screen.
- """
- xpos = write_position.xpos + move_x
- ypos = write_position.ypos
-
+ Copy characters from the margin screen to the real screen.
+ """
+ xpos = write_position.xpos + move_x
+ ypos = write_position.ypos
+
margin_write_position = WritePosition(xpos, ypos, width, write_position.height)
self._copy_body(cli, lazy_screen, new_screen, margin_write_position, 0, width)
-
+
def _scroll_when_linewrapping(self, ui_content, width, height, cli):
"""
Scroll to make sure the cursor position is visible and that we maintain
the requested scroll offset.
-
+
Set `self.horizontal_scroll/vertical_scroll`.
"""
scroll_offsets_bottom = self.scroll_offsets.bottom
scroll_offsets_top = self.scroll_offsets.top
-
+
# We don't have horizontal scrolling.
self.horizontal_scroll = 0
@@ -1506,12 +1506,12 @@ class Window(Container):
self.vertical_scroll = min(self.vertical_scroll, topmost_visible)
def _scroll_without_linewrapping(self, ui_content, width, height, cli):
- """
+ """
Scroll to make sure the cursor position is visible and that we maintain
the requested scroll offset.
Set `self.horizontal_scroll/vertical_scroll`.
- """
+ """
cursor_position = ui_content.cursor_position or Point(0, 0)
# Without line wrapping, we will never have to scroll vertically inside
@@ -1525,141 +1525,141 @@ class Window(Container):
else:
current_line_text = token_list_to_text(ui_content.get_line(cursor_position.y))
- def do_scroll(current_scroll, scroll_offset_start, scroll_offset_end,
- cursor_pos, window_size, content_size):
- " Scrolling algorithm. Used for both horizontal and vertical scrolling. "
- # Calculate the scroll offset to apply.
- # This can obviously never be more than have the screen size. Also, when the
- # cursor appears at the top or bottom, we don't apply the offset.
- scroll_offset_start = int(min(scroll_offset_start, window_size / 2, cursor_pos))
- scroll_offset_end = int(min(scroll_offset_end, window_size / 2,
- content_size - 1 - cursor_pos))
-
- # Prevent negative scroll offsets.
- if current_scroll < 0:
- current_scroll = 0
-
- # Scroll back if we scrolled to much and there's still space to show more of the document.
- if (not self.allow_scroll_beyond_bottom(cli) and
- current_scroll > content_size - window_size):
- current_scroll = max(0, content_size - window_size)
-
- # Scroll up if cursor is before visible part.
- if current_scroll > cursor_pos - scroll_offset_start:
- current_scroll = max(0, cursor_pos - scroll_offset_start)
-
- # Scroll down if cursor is after visible part.
- if current_scroll < (cursor_pos + 1) - window_size + scroll_offset_end:
- current_scroll = (cursor_pos + 1) - window_size + scroll_offset_end
-
+ def do_scroll(current_scroll, scroll_offset_start, scroll_offset_end,
+ cursor_pos, window_size, content_size):
+ " Scrolling algorithm. Used for both horizontal and vertical scrolling. "
+ # Calculate the scroll offset to apply.
+ # This can obviously never be more than have the screen size. Also, when the
+ # cursor appears at the top or bottom, we don't apply the offset.
+ scroll_offset_start = int(min(scroll_offset_start, window_size / 2, cursor_pos))
+ scroll_offset_end = int(min(scroll_offset_end, window_size / 2,
+ content_size - 1 - cursor_pos))
+
+ # Prevent negative scroll offsets.
+ if current_scroll < 0:
+ current_scroll = 0
+
+ # Scroll back if we scrolled to much and there's still space to show more of the document.
+ if (not self.allow_scroll_beyond_bottom(cli) and
+ current_scroll > content_size - window_size):
+ current_scroll = max(0, content_size - window_size)
+
+ # Scroll up if cursor is before visible part.
+ if current_scroll > cursor_pos - scroll_offset_start:
+ current_scroll = max(0, cursor_pos - scroll_offset_start)
+
+ # Scroll down if cursor is after visible part.
+ if current_scroll < (cursor_pos + 1) - window_size + scroll_offset_end:
+ current_scroll = (cursor_pos + 1) - window_size + scroll_offset_end
+
return current_scroll
-
- # When a preferred scroll is given, take that first into account.
- if self.get_vertical_scroll:
- self.vertical_scroll = self.get_vertical_scroll(self)
- assert isinstance(self.vertical_scroll, int)
- if self.get_horizontal_scroll:
- self.horizontal_scroll = self.get_horizontal_scroll(self)
- assert isinstance(self.horizontal_scroll, int)
-
- # Update horizontal/vertical scroll to make sure that the cursor
- # remains visible.
- offsets = self.scroll_offsets
-
+
+ # When a preferred scroll is given, take that first into account.
+ if self.get_vertical_scroll:
+ self.vertical_scroll = self.get_vertical_scroll(self)
+ assert isinstance(self.vertical_scroll, int)
+ if self.get_horizontal_scroll:
+ self.horizontal_scroll = self.get_horizontal_scroll(self)
+ assert isinstance(self.horizontal_scroll, int)
+
+ # Update horizontal/vertical scroll to make sure that the cursor
+ # remains visible.
+ offsets = self.scroll_offsets
+
self.vertical_scroll = do_scroll(
- current_scroll=self.vertical_scroll,
- scroll_offset_start=offsets.top,
- scroll_offset_end=offsets.bottom,
+ current_scroll=self.vertical_scroll,
+ scroll_offset_start=offsets.top,
+ scroll_offset_end=offsets.bottom,
cursor_pos=ui_content.cursor_position.y,
- window_size=height,
+ window_size=height,
content_size=ui_content.line_count)
-
+
self.horizontal_scroll = do_scroll(
- current_scroll=self.horizontal_scroll,
- scroll_offset_start=offsets.left,
- scroll_offset_end=offsets.right,
+ current_scroll=self.horizontal_scroll,
+ scroll_offset_start=offsets.left,
+ scroll_offset_end=offsets.right,
cursor_pos=get_cwidth(current_line_text[:ui_content.cursor_position.x]),
- window_size=width,
+ window_size=width,
# We can only analyse the current line. Calculating the width off
# all the lines is too expensive.
content_size=max(get_cwidth(current_line_text), self.horizontal_scroll + width))
-
- def _mouse_handler(self, cli, mouse_event):
- """
- Mouse handler. Called when the UI control doesn't handle this
- particular event.
- """
+
+ def _mouse_handler(self, cli, mouse_event):
+ """
+ Mouse handler. Called when the UI control doesn't handle this
+ particular event.
+ """
if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- self._scroll_down(cli)
+ self._scroll_down(cli)
elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- self._scroll_up(cli)
-
- def _scroll_down(self, cli):
- " Scroll window down. "
- info = self.render_info
-
- if self.vertical_scroll < info.content_height - info.window_height:
- if info.cursor_position.y <= info.configured_scroll_offsets.top:
- self.content.move_cursor_down(cli)
-
- self.vertical_scroll += 1
-
- def _scroll_up(self, cli):
- " Scroll window up. "
- info = self.render_info
-
- if info.vertical_scroll > 0:
+ self._scroll_up(cli)
+
+ def _scroll_down(self, cli):
+ " Scroll window down. "
+ info = self.render_info
+
+ if self.vertical_scroll < info.content_height - info.window_height:
+ if info.cursor_position.y <= info.configured_scroll_offsets.top:
+ self.content.move_cursor_down(cli)
+
+ self.vertical_scroll += 1
+
+ def _scroll_up(self, cli):
+ " Scroll window up. "
+ info = self.render_info
+
+ if info.vertical_scroll > 0:
# TODO: not entirely correct yet in case of line wrapping and long lines.
- if info.cursor_position.y >= info.window_height - 1 - info.configured_scroll_offsets.bottom:
- self.content.move_cursor_up(cli)
-
- self.vertical_scroll -= 1
-
- def walk(self, cli):
- # Only yield self. A window doesn't have children.
- yield self
-
-
-class ConditionalContainer(Container):
- """
- Wrapper around any other container that can change the visibility. The
- received `filter` determines whether the given container should be
- displayed or not.
-
- :param content: :class:`.Container` instance.
- :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
- """
- def __init__(self, content, filter):
- assert isinstance(content, Container)
-
- self.content = content
- self.filter = to_cli_filter(filter)
-
+ if info.cursor_position.y >= info.window_height - 1 - info.configured_scroll_offsets.bottom:
+ self.content.move_cursor_up(cli)
+
+ self.vertical_scroll -= 1
+
+ def walk(self, cli):
+ # Only yield self. A window doesn't have children.
+ yield self
+
+
+class ConditionalContainer(Container):
+ """
+ Wrapper around any other container that can change the visibility. The
+ received `filter` determines whether the given container should be
+ displayed or not.
+
+ :param content: :class:`.Container` instance.
+ :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
+ """
+ def __init__(self, content, filter):
+ assert isinstance(content, Container)
+
+ self.content = content
+ self.filter = to_cli_filter(filter)
+
def __repr__(self):
return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter)
- def reset(self):
- self.content.reset()
-
- def preferred_width(self, cli, max_available_width):
- if self.filter(cli):
- return self.content.preferred_width(cli, max_available_width)
- else:
- return LayoutDimension.exact(0)
-
+ def reset(self):
+ self.content.reset()
+
+ def preferred_width(self, cli, max_available_width):
+ if self.filter(cli):
+ return self.content.preferred_width(cli, max_available_width)
+ else:
+ return LayoutDimension.exact(0)
+
def preferred_height(self, cli, width, max_available_height):
- if self.filter(cli):
+ if self.filter(cli):
return self.content.preferred_height(cli, width, max_available_height)
- else:
- return LayoutDimension.exact(0)
-
- def write_to_screen(self, cli, screen, mouse_handlers, write_position):
- if self.filter(cli):
- return self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
-
- def walk(self, cli):
- return self.content.walk(cli)
-
-
-# Deprecated alias for 'Container'.
-Layout = Container
+ else:
+ return LayoutDimension.exact(0)
+
+ def write_to_screen(self, cli, screen, mouse_handlers, write_position):
+ if self.filter(cli):
+ return self.content.write_to_screen(cli, screen, mouse_handlers, write_position)
+
+ def walk(self, cli):
+ return self.content.walk(cli)
+
+
+# Deprecated alias for 'Container'.
+Layout = Container
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
index 59107c7e5e..ca74931dbc 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
@@ -1,99 +1,99 @@
-"""
-User interface Controls for the layout.
-"""
-from __future__ import unicode_literals
-
-from abc import ABCMeta, abstractmethod
+"""
+User interface Controls for the layout.
+"""
+from __future__ import unicode_literals
+
+from abc import ABCMeta, abstractmethod
from collections import namedtuple
-from six import with_metaclass
+from six import with_metaclass
from six.moves import range
-
+
from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
-from prompt_toolkit.filters import to_cli_filter
+from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
+from prompt_toolkit.filters import to_cli_filter
from prompt_toolkit.mouse_events import MouseEventType
-from prompt_toolkit.search_state import SearchState
-from prompt_toolkit.selection import SelectionType
+from prompt_toolkit.search_state import SearchState
+from prompt_toolkit.selection import SelectionType
from prompt_toolkit.token import Token
from prompt_toolkit.utils import get_cwidth
-
-from .lexers import Lexer, SimpleLexer
+
+from .lexers import Lexer, SimpleLexer
from .processors import Processor
from .screen import Char, Point
from .utils import token_list_width, split_lines, token_list_to_text
-
+
import six
-import time
-
-
-__all__ = (
- 'BufferControl',
- 'FillControl',
- 'TokenListControl',
- 'UIControl',
+import time
+
+
+__all__ = (
+ 'BufferControl',
+ 'FillControl',
+ 'TokenListControl',
+ 'UIControl',
'UIContent',
-)
-
-
-class UIControl(with_metaclass(ABCMeta, object)):
- """
- Base class for all user interface controls.
- """
- def reset(self):
- # Default reset. (Doesn't have to be implemented.)
- pass
-
- def preferred_width(self, cli, max_available_width):
- return None
-
+)
+
+
+class UIControl(with_metaclass(ABCMeta, object)):
+ """
+ Base class for all user interface controls.
+ """
+ def reset(self):
+ # Default reset. (Doesn't have to be implemented.)
+ pass
+
+ def preferred_width(self, cli, max_available_width):
+ return None
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
- return None
-
- def has_focus(self, cli):
- """
- Return ``True`` when this user control has the focus.
-
- If so, the cursor will be displayed according to the cursor position
+ return None
+
+ def has_focus(self, cli):
+ """
+ Return ``True`` when this user control has the focus.
+
+ If so, the cursor will be displayed according to the cursor position
reported by :meth:`.UIControl.create_content`. If the created content
has the property ``show_cursor=False``, the cursor will be hidden from
the output.
- """
- return False
-
- @abstractmethod
+ """
+ return False
+
+ @abstractmethod
def create_content(self, cli, width, height):
- """
+ """
Generate the content for this user control.
-
+
Returns a :class:`.UIContent` instance.
- """
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events.
-
- When `NotImplemented` is returned, it means that the given event is not
- handled by the `UIControl` itself. The `Window` or key bindings can
- decide to handle this event as scrolling or changing focus.
-
- :param cli: `CommandLineInterface` instance.
- :param mouse_event: `MouseEvent` instance.
- """
- return NotImplemented
-
- def move_cursor_down(self, cli):
- """
- Request to move the cursor down.
- This happens when scrolling down and the cursor is completely at the
- top.
- """
-
- def move_cursor_up(self, cli):
- """
- Request to move the cursor up.
- """
-
-
+ """
+
+ def mouse_handler(self, cli, mouse_event):
+ """
+ Handle mouse events.
+
+ When `NotImplemented` is returned, it means that the given event is not
+ handled by the `UIControl` itself. The `Window` or key bindings can
+ decide to handle this event as scrolling or changing focus.
+
+ :param cli: `CommandLineInterface` instance.
+ :param mouse_event: `MouseEvent` instance.
+ """
+ return NotImplemented
+
+ def move_cursor_down(self, cli):
+ """
+ Request to move the cursor down.
+ This happens when scrolling down and the cursor is completely at the
+ top.
+ """
+
+ def move_cursor_up(self, cli):
+ """
+ Request to move the cursor up.
+ """
+
+
class UIContent(object):
"""
Content generated by a user control. This content consists of a list of
@@ -166,135 +166,135 @@ class UIContent(object):
return max(1, quotient)
-class TokenListControl(UIControl):
- """
- Control that displays a list of (Token, text) tuples.
- (It's mostly optimized for rather small widgets, like toolbars, menus, etc...)
-
- Mouse support:
-
- The list of tokens can also contain tuples of three items, looking like:
- (Token, text, handler). When mouse support is enabled and the user
- clicks on this token, then the given handler is called. That handler
- should accept two inputs: (CommandLineInterface, MouseEvent) and it
- should either handle the event or return `NotImplemented` in case we
- want the containing Window to handle this event.
-
- :param get_tokens: Callable that takes a `CommandLineInterface` instance
- and returns the list of (Token, text) tuples to be displayed right now.
- :param default_char: default :class:`.Char` (character and Token) to use
- for the background when there is more space available than `get_tokens`
- returns.
- :param get_default_char: Like `default_char`, but this is a callable that
- takes a :class:`prompt_toolkit.interface.CommandLineInterface` and
- returns a :class:`.Char` instance.
- :param has_focus: `bool` or `CLIFilter`, when this evaluates to `True`,
- this UI control will take the focus. The cursor will be shown in the
- upper left corner of this control, unless `get_token` returns a
- ``Token.SetCursorPosition`` token somewhere in the token list, then the
- cursor will be shown there.
- """
- def __init__(self, get_tokens, default_char=None, get_default_char=None,
+class TokenListControl(UIControl):
+ """
+ Control that displays a list of (Token, text) tuples.
+ (It's mostly optimized for rather small widgets, like toolbars, menus, etc...)
+
+ Mouse support:
+
+ The list of tokens can also contain tuples of three items, looking like:
+ (Token, text, handler). When mouse support is enabled and the user
+ clicks on this token, then the given handler is called. That handler
+ should accept two inputs: (CommandLineInterface, MouseEvent) and it
+ should either handle the event or return `NotImplemented` in case we
+ want the containing Window to handle this event.
+
+ :param get_tokens: Callable that takes a `CommandLineInterface` instance
+ and returns the list of (Token, text) tuples to be displayed right now.
+ :param default_char: default :class:`.Char` (character and Token) to use
+ for the background when there is more space available than `get_tokens`
+ returns.
+ :param get_default_char: Like `default_char`, but this is a callable that
+ takes a :class:`prompt_toolkit.interface.CommandLineInterface` and
+ returns a :class:`.Char` instance.
+ :param has_focus: `bool` or `CLIFilter`, when this evaluates to `True`,
+ this UI control will take the focus. The cursor will be shown in the
+ upper left corner of this control, unless `get_token` returns a
+ ``Token.SetCursorPosition`` token somewhere in the token list, then the
+ cursor will be shown there.
+ """
+ def __init__(self, get_tokens, default_char=None, get_default_char=None,
align_right=False, align_center=False, has_focus=False):
assert callable(get_tokens)
- assert default_char is None or isinstance(default_char, Char)
- assert get_default_char is None or callable(get_default_char)
- assert not (default_char and get_default_char)
-
- self.align_right = to_cli_filter(align_right)
- self.align_center = to_cli_filter(align_center)
- self._has_focus_filter = to_cli_filter(has_focus)
-
- self.get_tokens = get_tokens
-
- # Construct `get_default_char` callable.
- if default_char:
- get_default_char = lambda _: default_char
- elif not get_default_char:
+ assert default_char is None or isinstance(default_char, Char)
+ assert get_default_char is None or callable(get_default_char)
+ assert not (default_char and get_default_char)
+
+ self.align_right = to_cli_filter(align_right)
+ self.align_center = to_cli_filter(align_center)
+ self._has_focus_filter = to_cli_filter(has_focus)
+
+ self.get_tokens = get_tokens
+
+ # Construct `get_default_char` callable.
+ if default_char:
+ get_default_char = lambda _: default_char
+ elif not get_default_char:
get_default_char = lambda _: Char(' ', Token.Transparent)
-
- self.get_default_char = get_default_char
-
+
+ self.get_default_char = get_default_char
+
#: Cache for the content.
self._content_cache = SimpleCache(maxsize=18)
self._token_cache = SimpleCache(maxsize=1)
- # Only cache one token list. We don't need the previous item.
-
- # Render info for the mouse support.
+ # Only cache one token list. We don't need the previous item.
+
+ # Render info for the mouse support.
self._tokens = None
-
+
def reset(self):
self._tokens = None
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
-
- def _get_tokens_cached(self, cli):
- """
- Get tokens, but only retrieve tokens once during one render run.
- (This function is called several times during one rendering, because
- we also need those for calculating the dimensions.)
- """
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
+
+ def _get_tokens_cached(self, cli):
+ """
+ Get tokens, but only retrieve tokens once during one render run.
+ (This function is called several times during one rendering, because
+ we also need those for calculating the dimensions.)
+ """
return self._token_cache.get(
- cli.render_counter, lambda: self.get_tokens(cli))
-
- def has_focus(self, cli):
- return self._has_focus_filter(cli)
-
- def preferred_width(self, cli, max_available_width):
- """
- Return the preferred width for this control.
- That is the width of the longest line.
- """
+ cli.render_counter, lambda: self.get_tokens(cli))
+
+ def has_focus(self, cli):
+ return self._has_focus_filter(cli)
+
+ def preferred_width(self, cli, max_available_width):
+ """
+ Return the preferred width for this control.
+ That is the width of the longest line.
+ """
text = token_list_to_text(self._get_tokens_cached(cli))
- line_lengths = [get_cwidth(l) for l in text.split('\n')]
- return max(line_lengths)
-
+ line_lengths = [get_cwidth(l) for l in text.split('\n')]
+ return max(line_lengths)
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
content = self.create_content(cli, width, None)
return content.line_count
-
+
def create_content(self, cli, width, height):
- # Get tokens
- tokens_with_mouse_handlers = self._get_tokens_cached(cli)
-
- default_char = self.get_default_char(cli)
-
- # Wrap/align right/center parameters.
- right = self.align_right(cli)
- center = self.align_center(cli)
-
- def process_line(line):
- " Center or right align a single line. "
- used_width = token_list_width(line)
- padding = width - used_width
- if center:
- padding = int(padding / 2)
+ # Get tokens
+ tokens_with_mouse_handlers = self._get_tokens_cached(cli)
+
+ default_char = self.get_default_char(cli)
+
+ # Wrap/align right/center parameters.
+ right = self.align_right(cli)
+ center = self.align_center(cli)
+
+ def process_line(line):
+ " Center or right align a single line. "
+ used_width = token_list_width(line)
+ padding = width - used_width
+ if center:
+ padding = int(padding / 2)
return [(default_char.token, default_char.char * padding)] + line
-
- if right or center:
+
+ if right or center:
token_lines_with_mouse_handlers = []
- for line in split_lines(tokens_with_mouse_handlers):
+ for line in split_lines(tokens_with_mouse_handlers):
token_lines_with_mouse_handlers.append(process_line(line))
else:
token_lines_with_mouse_handlers = list(split_lines(tokens_with_mouse_handlers))
-
- # Strip mouse handlers from tokens.
+
+ # Strip mouse handlers from tokens.
token_lines = [
[tuple(item[:2]) for item in line]
for line in token_lines_with_mouse_handlers
]
-
+
# Keep track of the tokens with mouse handler, for later use in
# `mouse_handler`.
- self._tokens = tokens_with_mouse_handlers
-
+ self._tokens = tokens_with_mouse_handlers
+
# If there is a `Token.SetCursorPosition` in the token list, set the
# cursor position here.
def get_cursor_position():
SetCursorPosition = Token.SetCursorPosition
-
+
for y, line in enumerate(token_lines):
x = 0
for token, text in line:
@@ -302,38 +302,38 @@ class TokenListControl(UIControl):
return Point(x=x, y=y)
x += len(text)
return None
-
+
# Create content, or take it from the cache.
key = (default_char.char, default_char.token,
tuple(tokens_with_mouse_handlers), width, right, center)
-
+
def get_content():
return UIContent(get_line=lambda i: token_lines[i],
line_count=len(token_lines),
default_char=default_char,
cursor_position=get_cursor_position())
-
+
return self._content_cache.get(key, get_content)
- @classmethod
- def static(cls, tokens):
- def get_static_tokens(cli):
- return tokens
- return cls(get_static_tokens)
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events.
-
- (When the token list contained mouse handlers and the user clicked on
- on any of these, the matching handler is called. This handler can still
- return `NotImplemented` in case we want the `Window` to handle this
- particular event.)
- """
+ @classmethod
+ def static(cls, tokens):
+ def get_static_tokens(cli):
+ return tokens
+ return cls(get_static_tokens)
+
+ def mouse_handler(self, cli, mouse_event):
+ """
+ Handle mouse events.
+
+ (When the token list contained mouse handlers and the user clicked on
+ on any of these, the matching handler is called. This handler can still
+ return `NotImplemented` in case we want the `Window` to handle this
+ particular event.)
+ """
if self._tokens:
# Read the generator.
tokens_for_line = list(split_lines(self._tokens))
-
+
try:
tokens = tokens_for_line[mouse_event.position.y]
except IndexError:
@@ -342,38 +342,38 @@ class TokenListControl(UIControl):
# Find position in the token list.
xpos = mouse_event.position.x
- # Find mouse handler for this character.
- count = 0
+ # Find mouse handler for this character.
+ count = 0
for item in tokens:
- count += len(item[1])
+ count += len(item[1])
if count >= xpos:
- if len(item) >= 3:
- # Handler found. Call it.
+ if len(item) >= 3:
+ # Handler found. Call it.
# (Handler can return NotImplemented, so return
# that result.)
- handler = item[2]
+ handler = item[2]
return handler(cli, mouse_event)
- else:
- break
-
- # Otherwise, don't handle here.
- return NotImplemented
-
-
-class FillControl(UIControl):
- """
- Fill whole control with characters with this token.
- (Also helpful for debugging.)
+ else:
+ break
+
+ # Otherwise, don't handle here.
+ return NotImplemented
+
+
+class FillControl(UIControl):
+ """
+ Fill whole control with characters with this token.
+ (Also helpful for debugging.)
:param char: :class:`.Char` instance to use for filling.
:param get_char: A callable that takes a CommandLineInterface and returns a
:class:`.Char` object.
- """
+ """
def __init__(self, character=None, token=Token, char=None, get_char=None): # 'character' and 'token' parameters are deprecated.
assert char is None or isinstance(char, Char)
assert get_char is None or callable(get_char)
assert not (char and get_char)
-
+
self.char = char
if character:
@@ -391,110 +391,110 @@ class FillControl(UIControl):
self.get_char = lambda cli: self.char
self.char = char
- def __repr__(self):
+ def __repr__(self):
if self.char:
return '%s(char=%r)' % (self.__class__.__name__, self.char)
else:
return '%s(get_char=%r)' % (self.__class__.__name__, self.get_char)
-
- def reset(self):
- pass
-
- def has_focus(self, cli):
- return False
-
+
+ def reset(self):
+ pass
+
+ def has_focus(self, cli):
+ return False
+
def create_content(self, cli, width, height):
def get_line(i):
return []
-
+
return UIContent(
get_line=get_line,
line_count=100 ** 100, # Something very big.
default_char=self.get_char(cli))
-
+
_ProcessedLine = namedtuple('_ProcessedLine', 'tokens source_to_display display_to_source')
-class BufferControl(UIControl):
- """
- Control for visualising the content of a `Buffer`.
-
- :param input_processors: list of :class:`~prompt_toolkit.layout.processors.Processor`.
- :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` instance for syntax highlighting.
- :param preview_search: `bool` or `CLIFilter`: Show search while typing.
- :param get_search_state: Callable that takes a CommandLineInterface and
- returns the SearchState to be used. (If not CommandLineInterface.search_state.)
- :param buffer_name: String representing the name of the buffer to display.
- :param default_char: :class:`.Char` instance to use to fill the background. This is
- transparent by default.
- :param focus_on_click: Focus this buffer when it's click, but not yet focussed.
- """
- def __init__(self,
- buffer_name=DEFAULT_BUFFER,
- input_processors=None,
- lexer=None,
- preview_search=False,
- search_buffer_name=SEARCH_BUFFER,
- get_search_state=None,
- menu_position=None,
- default_char=None,
- focus_on_click=False):
- assert input_processors is None or all(isinstance(i, Processor) for i in input_processors)
- assert menu_position is None or callable(menu_position)
- assert lexer is None or isinstance(lexer, Lexer)
- assert get_search_state is None or callable(get_search_state)
+class BufferControl(UIControl):
+ """
+ Control for visualising the content of a `Buffer`.
+
+ :param input_processors: list of :class:`~prompt_toolkit.layout.processors.Processor`.
+ :param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` instance for syntax highlighting.
+ :param preview_search: `bool` or `CLIFilter`: Show search while typing.
+ :param get_search_state: Callable that takes a CommandLineInterface and
+ returns the SearchState to be used. (If not CommandLineInterface.search_state.)
+ :param buffer_name: String representing the name of the buffer to display.
+ :param default_char: :class:`.Char` instance to use to fill the background. This is
+ transparent by default.
+ :param focus_on_click: Focus this buffer when it's click, but not yet focussed.
+ """
+ def __init__(self,
+ buffer_name=DEFAULT_BUFFER,
+ input_processors=None,
+ lexer=None,
+ preview_search=False,
+ search_buffer_name=SEARCH_BUFFER,
+ get_search_state=None,
+ menu_position=None,
+ default_char=None,
+ focus_on_click=False):
+ assert input_processors is None or all(isinstance(i, Processor) for i in input_processors)
+ assert menu_position is None or callable(menu_position)
+ assert lexer is None or isinstance(lexer, Lexer)
+ assert get_search_state is None or callable(get_search_state)
assert default_char is None or isinstance(default_char, Char)
-
- self.preview_search = to_cli_filter(preview_search)
- self.get_search_state = get_search_state
- self.focus_on_click = to_cli_filter(focus_on_click)
-
- self.input_processors = input_processors or []
- self.buffer_name = buffer_name
- self.menu_position = menu_position
- self.lexer = lexer or SimpleLexer()
- self.default_char = default_char or Char(token=Token.Transparent)
- self.search_buffer_name = search_buffer_name
-
+
+ self.preview_search = to_cli_filter(preview_search)
+ self.get_search_state = get_search_state
+ self.focus_on_click = to_cli_filter(focus_on_click)
+
+ self.input_processors = input_processors or []
+ self.buffer_name = buffer_name
+ self.menu_position = menu_position
+ self.lexer = lexer or SimpleLexer()
+ self.default_char = default_char or Char(token=Token.Transparent)
+ self.search_buffer_name = search_buffer_name
+
#: Cache for the lexer.
- #: Often, due to cursor movement, undo/redo and window resizing
- #: operations, it happens that a short time, the same document has to be
- #: lexed. This is a faily easy way to cache such an expensive operation.
+ #: Often, due to cursor movement, undo/redo and window resizing
+ #: operations, it happens that a short time, the same document has to be
+ #: lexed. This is a faily easy way to cache such an expensive operation.
self._token_cache = SimpleCache(maxsize=8)
-
- self._xy_to_cursor_position = None
- self._last_click_timestamp = None
+
+ self._xy_to_cursor_position = None
+ self._last_click_timestamp = None
self._last_get_processed_line = None
-
- def _buffer(self, cli):
- """
- The buffer object that contains the 'main' content.
- """
- return cli.buffers[self.buffer_name]
-
- def has_focus(self, cli):
- # This control gets the focussed if the actual `Buffer` instance has the
- # focus or when any of the `InputProcessor` classes tells us that it
- # wants the focus. (E.g. in case of a reverse-search, where the actual
- # search buffer may not be displayed, but the "reverse-i-search" text
- # should get the focus.)
- return cli.current_buffer_name == self.buffer_name or \
- any(i.has_focus(cli) for i in self.input_processors)
-
- def preferred_width(self, cli, max_available_width):
+
+ def _buffer(self, cli):
+ """
+ The buffer object that contains the 'main' content.
+ """
+ return cli.buffers[self.buffer_name]
+
+ def has_focus(self, cli):
+ # This control gets the focussed if the actual `Buffer` instance has the
+ # focus or when any of the `InputProcessor` classes tells us that it
+ # wants the focus. (E.g. in case of a reverse-search, where the actual
+ # search buffer may not be displayed, but the "reverse-i-search" text
+ # should get the focus.)
+ return cli.current_buffer_name == self.buffer_name or \
+ any(i.has_focus(cli) for i in self.input_processors)
+
+ def preferred_width(self, cli, max_available_width):
"""
This should return the preferred width.
-
+
Note: We don't specify a preferred width according to the content,
because it would be too expensive. Calculating the preferred
width can be done by calculating the longest line, but this would
require applying all the processors to each line. This is
unfeasible for a larger document, and doing it for small
documents only would result in inconsistent behaviour.
- """
+ """
return None
-
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
# Calculate the content height, if it was drawn on a screen with the
# given width.
@@ -520,15 +520,15 @@ class BufferControl(UIControl):
return height
def _get_tokens_for_line_func(self, cli, document):
- """
+ """
Create a function that returns the tokens for a given line.
"""
# Cache using `document.text`.
def get_tokens_for_line():
return self.lexer.lex_document(cli, document)
-
+
return self._token_cache.get(document.text, get_tokens_for_line)
-
+
def _create_get_processed_line_func(self, cli, document):
"""
Create a function that takes a line number of the current document and
@@ -537,15 +537,15 @@ class BufferControl(UIControl):
"""
def transform(lineno, tokens):
" Transform the tokens for a given line number. "
- source_to_display_functions = []
- display_to_source_functions = []
-
+ source_to_display_functions = []
+ display_to_source_functions = []
+
# Get cursor position at this line.
if document.cursor_position_row == lineno:
cursor_column = document.cursor_position_col
else:
cursor_column = None
-
+
def source_to_display(i):
""" Translate x position from the buffer to the x position in the
processed token list. """
@@ -554,28 +554,28 @@ class BufferControl(UIControl):
return i
# Apply each processor.
- for p in self.input_processors:
+ for p in self.input_processors:
transformation = p.apply_transformation(
cli, document, lineno, source_to_display, tokens)
- tokens = transformation.tokens
-
+ tokens = transformation.tokens
+
if cursor_column:
cursor_column = transformation.source_to_display(cursor_column)
-
+
display_to_source_functions.append(transformation.display_to_source)
source_to_display_functions.append(transformation.source_to_display)
-
+
def display_to_source(i):
- for f in reversed(display_to_source_functions):
+ for f in reversed(display_to_source_functions):
i = f(i)
return i
-
+
return _ProcessedLine(tokens, source_to_display, display_to_source)
-
+
def create_func():
get_line = self._get_tokens_for_line_func(cli, document)
cache = {}
-
+
def get_processed_line(i):
try:
return cache[i]
@@ -584,48 +584,48 @@ class BufferControl(UIControl):
cache[i] = processed_line
return processed_line
return get_processed_line
-
+
return create_func()
-
+
def create_content(self, cli, width, height):
"""
Create a UIContent.
"""
- buffer = self._buffer(cli)
-
- # Get the document to be shown. If we are currently searching (the
- # search buffer has focus, and the preview_search filter is enabled),
- # then use the search document, which has possibly a different
- # text/cursor position.)
- def preview_now():
- """ True when we should preview a search. """
- return bool(self.preview_search(cli) and
- cli.buffers[self.search_buffer_name].text)
-
- if preview_now():
- if self.get_search_state:
- ss = self.get_search_state(cli)
- else:
- ss = cli.search_state
-
- document = buffer.document_for_search(SearchState(
- text=cli.current_buffer.text,
- direction=ss.direction,
- ignore_case=ss.ignore_case))
- else:
- document = buffer.document
-
+ buffer = self._buffer(cli)
+
+ # Get the document to be shown. If we are currently searching (the
+ # search buffer has focus, and the preview_search filter is enabled),
+ # then use the search document, which has possibly a different
+ # text/cursor position.)
+ def preview_now():
+ """ True when we should preview a search. """
+ return bool(self.preview_search(cli) and
+ cli.buffers[self.search_buffer_name].text)
+
+ if preview_now():
+ if self.get_search_state:
+ ss = self.get_search_state(cli)
+ else:
+ ss = cli.search_state
+
+ document = buffer.document_for_search(SearchState(
+ text=cli.current_buffer.text,
+ direction=ss.direction,
+ ignore_case=ss.ignore_case))
+ else:
+ document = buffer.document
+
get_processed_line = self._create_get_processed_line_func(cli, document)
self._last_get_processed_line = get_processed_line
-
+
def translate_rowcol(row, col):
" Return the content column for this coordinate. "
return Point(y=row, x=get_processed_line(row).source_to_display(col))
-
+
def get_line(i):
" Return the tokens for a given line number. "
tokens = get_processed_line(i).tokens
-
+
# Add a space at the end, because that is a possible cursor
# position. (When inserting after the input.) We should do this on
# all the lines, not just the line containing the cursor. (Because
@@ -633,60 +633,60 @@ class BufferControl(UIControl):
# cursor around.)
tokens = tokens + [(self.default_char.token, ' ')]
return tokens
-
+
content = UIContent(
get_line=get_line,
line_count=document.line_count,
cursor_position=translate_rowcol(document.cursor_position_row,
document.cursor_position_col),
default_char=self.default_char)
-
- # If there is an auto completion going on, use that start point for a
- # pop-up menu position. (But only when this buffer has the focus --
- # there is only one place for a menu, determined by the focussed buffer.)
- if cli.current_buffer_name == self.buffer_name:
- menu_position = self.menu_position(cli) if self.menu_position else None
- if menu_position is not None:
- assert isinstance(menu_position, int)
+
+ # If there is an auto completion going on, use that start point for a
+ # pop-up menu position. (But only when this buffer has the focus --
+ # there is only one place for a menu, determined by the focussed buffer.)
+ if cli.current_buffer_name == self.buffer_name:
+ menu_position = self.menu_position(cli) if self.menu_position else None
+ if menu_position is not None:
+ assert isinstance(menu_position, int)
menu_row, menu_col = buffer.document.translate_index_to_position(menu_position)
content.menu_position = translate_rowcol(menu_row, menu_col)
- elif buffer.complete_state:
- # Position for completion menu.
- # Note: We use 'min', because the original cursor position could be
- # behind the input string when the actual completion is for
- # some reason shorter than the text we had before. (A completion
- # can change and shorten the input.)
+ elif buffer.complete_state:
+ # Position for completion menu.
+ # Note: We use 'min', because the original cursor position could be
+ # behind the input string when the actual completion is for
+ # some reason shorter than the text we had before. (A completion
+ # can change and shorten the input.)
menu_row, menu_col = buffer.document.translate_index_to_position(
- min(buffer.cursor_position,
- buffer.complete_state.original_document.cursor_position))
+ min(buffer.cursor_position,
+ buffer.complete_state.original_document.cursor_position))
content.menu_position = translate_rowcol(menu_row, menu_col)
- else:
+ else:
content.menu_position = None
-
+
return content
-
- def mouse_handler(self, cli, mouse_event):
- """
- Mouse handler for this control.
- """
- buffer = self._buffer(cli)
- position = mouse_event.position
-
- # Focus buffer when clicked.
- if self.has_focus(cli):
+
+ def mouse_handler(self, cli, mouse_event):
+ """
+ Mouse handler for this control.
+ """
+ buffer = self._buffer(cli)
+ position = mouse_event.position
+
+ # Focus buffer when clicked.
+ if self.has_focus(cli):
if self._last_get_processed_line:
processed_line = self._last_get_processed_line(position.y)
- # Translate coordinates back to the cursor position of the
- # original input.
+ # Translate coordinates back to the cursor position of the
+ # original input.
xpos = processed_line.display_to_source(position.x)
index = buffer.document.translate_row_col_to_index(position.y, xpos)
-
- # Set the cursor position.
+
+ # Set the cursor position.
if mouse_event.event_type == MouseEventType.MOUSE_DOWN:
buffer.exit_selection()
buffer.cursor_position = index
-
+
elif mouse_event.event_type == MouseEventType.MOUSE_UP:
# When the cursor was moved to another place, select the text.
# (The >1 is actually a small but acceptable workaround for
@@ -696,12 +696,12 @@ class BufferControl(UIControl):
if abs(buffer.cursor_position - index) > 1:
buffer.start_selection(selection_type=SelectionType.CHARACTERS)
buffer.cursor_position = index
-
+
# Select word around cursor on double click.
# Two MOUSE_UP events in a short timespan are considered a double click.
double_click = self._last_click_timestamp and time.time() - self._last_click_timestamp < .3
self._last_click_timestamp = time.time()
-
+
if double_click:
start, end = buffer.document.find_boundaries_of_current_word()
buffer.cursor_position += start
@@ -710,21 +710,21 @@ class BufferControl(UIControl):
else:
# Don't handle scroll events here.
return NotImplemented
-
- # Not focussed, but focussing on click events.
- else:
+
+ # Not focussed, but focussing on click events.
+ else:
if self.focus_on_click(cli) and mouse_event.event_type == MouseEventType.MOUSE_UP:
- # Focus happens on mouseup. (If we did this on mousedown, the
- # up event will be received at the point where this widget is
- # focussed and be handled anyway.)
- cli.focus(self.buffer_name)
- else:
- return NotImplemented
-
- def move_cursor_down(self, cli):
- b = self._buffer(cli)
- b.cursor_position += b.document.get_cursor_down_position()
-
- def move_cursor_up(self, cli):
- b = self._buffer(cli)
- b.cursor_position += b.document.get_cursor_up_position()
+ # Focus happens on mouseup. (If we did this on mousedown, the
+ # up event will be received at the point where this widget is
+ # focussed and be handled anyway.)
+ cli.focus(self.buffer_name)
+ else:
+ return NotImplemented
+
+ def move_cursor_down(self, cli):
+ b = self._buffer(cli)
+ b.cursor_position += b.document.get_cursor_down_position()
+
+ def move_cursor_up(self, cli):
+ b = self._buffer(cli)
+ b.cursor_position += b.document.get_cursor_up_position()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py
index 82d2bb82f1..717ad7a81f 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/dimension.py
@@ -1,92 +1,92 @@
-"""
-Layout dimensions are used to give the minimum, maximum and preferred
-dimensions for containers and controls.
-"""
-from __future__ import unicode_literals
-
-__all__ = (
- 'LayoutDimension',
- 'sum_layout_dimensions',
- 'max_layout_dimensions',
-)
-
-
-class LayoutDimension(object):
- """
- Specified dimension (width/height) of a user control or window.
-
- The layout engine tries to honor the preferred size. If that is not
- possible, because the terminal is larger or smaller, it tries to keep in
- between min and max.
-
- :param min: Minimum size.
- :param max: Maximum size.
- :param weight: For a VSplit/HSplit, the actual size will be determined
- by taking the proportion of weights from all the children.
- E.g. When there are two children, one width a weight of 1,
- and the other with a weight of 2. The second will always be
- twice as big as the first, if the min/max values allow it.
- :param preferred: Preferred size.
- """
- def __init__(self, min=None, max=None, weight=1, preferred=None):
- assert isinstance(weight, int) and weight > 0 # Cannot be a float.
-
- self.min_specified = min is not None
- self.max_specified = max is not None
- self.preferred_specified = preferred is not None
-
- if min is None:
- min = 0 # Smallest possible value.
- if max is None: # 0-values are allowed, so use "is None"
- max = 1000 ** 10 # Something huge.
- if preferred is None:
- preferred = min
-
- self.min = min
- self.max = max
- self.preferred = preferred
- self.weight = weight
-
- # Make sure that the 'preferred' size is always in the min..max range.
- if self.preferred < self.min:
- self.preferred = self.min
-
- if self.preferred > self.max:
- self.preferred = self.max
-
- @classmethod
- def exact(cls, amount):
- """
- Return a :class:`.LayoutDimension` with an exact size. (min, max and
- preferred set to ``amount``).
- """
- return cls(min=amount, max=amount, preferred=amount)
-
- def __repr__(self):
- return 'LayoutDimension(min=%r, max=%r, preferred=%r, weight=%r)' % (
- self.min, self.max, self.preferred, self.weight)
-
- def __add__(self, other):
- return sum_layout_dimensions([self, other])
-
-
-def sum_layout_dimensions(dimensions):
- """
- Sum a list of :class:`.LayoutDimension` instances.
- """
- min = sum([d.min for d in dimensions if d.min is not None])
- max = sum([d.max for d in dimensions if d.max is not None])
- preferred = sum([d.preferred for d in dimensions])
-
- return LayoutDimension(min=min, max=max, preferred=preferred)
-
-
-def max_layout_dimensions(dimensions):
- """
- Take the maximum of a list of :class:`.LayoutDimension` instances.
- """
- min_ = max([d.min for d in dimensions if d.min is not None])
- max_ = max([d.max for d in dimensions if d.max is not None])
- preferred = max([d.preferred for d in dimensions])
-
- return LayoutDimension(min=min_, max=max_, preferred=preferred)
+"""
+Layout dimensions are used to give the minimum, maximum and preferred
+dimensions for containers and controls.
+"""
+from __future__ import unicode_literals
+
+__all__ = (
+ 'LayoutDimension',
+ 'sum_layout_dimensions',
+ 'max_layout_dimensions',
+)
+
+
+class LayoutDimension(object):
+ """
+ Specified dimension (width/height) of a user control or window.
+
+ The layout engine tries to honor the preferred size. If that is not
+ possible, because the terminal is larger or smaller, it tries to keep in
+ between min and max.
+
+ :param min: Minimum size.
+ :param max: Maximum size.
+ :param weight: For a VSplit/HSplit, the actual size will be determined
+ by taking the proportion of weights from all the children.
+ E.g. When there are two children, one width a weight of 1,
+ and the other with a weight of 2. The second will always be
+ twice as big as the first, if the min/max values allow it.
+ :param preferred: Preferred size.
+ """
+ def __init__(self, min=None, max=None, weight=1, preferred=None):
+ assert isinstance(weight, int) and weight > 0 # Cannot be a float.
+
+ self.min_specified = min is not None
+ self.max_specified = max is not None
+ self.preferred_specified = preferred is not None
+
+ if min is None:
+ min = 0 # Smallest possible value.
+ if max is None: # 0-values are allowed, so use "is None"
+ max = 1000 ** 10 # Something huge.
+ if preferred is None:
+ preferred = min
+
+ self.min = min
+ self.max = max
+ self.preferred = preferred
+ self.weight = weight
+
+ # Make sure that the 'preferred' size is always in the min..max range.
+ if self.preferred < self.min:
+ self.preferred = self.min
+
+ if self.preferred > self.max:
+ self.preferred = self.max
+
+ @classmethod
+ def exact(cls, amount):
+ """
+ Return a :class:`.LayoutDimension` with an exact size. (min, max and
+ preferred set to ``amount``).
+ """
+ return cls(min=amount, max=amount, preferred=amount)
+
+ def __repr__(self):
+ return 'LayoutDimension(min=%r, max=%r, preferred=%r, weight=%r)' % (
+ self.min, self.max, self.preferred, self.weight)
+
+ def __add__(self, other):
+ return sum_layout_dimensions([self, other])
+
+
+def sum_layout_dimensions(dimensions):
+ """
+ Sum a list of :class:`.LayoutDimension` instances.
+ """
+ min = sum([d.min for d in dimensions if d.min is not None])
+ max = sum([d.max for d in dimensions if d.max is not None])
+ preferred = sum([d.preferred for d in dimensions])
+
+ return LayoutDimension(min=min, max=max, preferred=preferred)
+
+
+def max_layout_dimensions(dimensions):
+ """
+ Take the maximum of a list of :class:`.LayoutDimension` instances.
+ """
+ min_ = max([d.min for d in dimensions if d.min is not None])
+ max_ = max([d.max for d in dimensions if d.max is not None])
+ preferred = max([d.preferred for d in dimensions])
+
+ return LayoutDimension(min=min_, max=max_, preferred=preferred)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
index 8f3f36e2e2..a928fd8226 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
@@ -1,12 +1,12 @@
-"""
-Lexer interface and implementation.
-Used for syntax highlighting.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
+"""
+Lexer interface and implementation.
+Used for syntax highlighting.
+"""
+from __future__ import unicode_literals
+from abc import ABCMeta, abstractmethod
+from six import with_metaclass
from six.moves import range
-
+
from prompt_toolkit.token import Token
from prompt_toolkit.filters import to_cli_filter
from .utils import split_lines
@@ -14,44 +14,44 @@ from .utils import split_lines
import re
import six
-__all__ = (
- 'Lexer',
- 'SimpleLexer',
- 'PygmentsLexer',
+__all__ = (
+ 'Lexer',
+ 'SimpleLexer',
+ 'PygmentsLexer',
'SyntaxSync',
'SyncFromStart',
'RegexSync',
-)
-
-
-class Lexer(with_metaclass(ABCMeta, object)):
- """
- Base class for all lexers.
- """
- @abstractmethod
+)
+
+
+class Lexer(with_metaclass(ABCMeta, object)):
+ """
+ Base class for all lexers.
+ """
+ @abstractmethod
def lex_document(self, cli, document):
- """
+ """
Takes a :class:`~prompt_toolkit.document.Document` and returns a
callable that takes a line number and returns the tokens for that line.
- """
-
-
-class SimpleLexer(Lexer):
- """
+ """
+
+
+class SimpleLexer(Lexer):
+ """
Lexer that doesn't do any tokenizing and returns the whole input as one token.
:param token: The `Token` for this lexer.
- """
+ """
# `default_token` parameter is deprecated!
def __init__(self, token=Token, default_token=None):
self.token = token
-
+
if default_token is not None:
self.token = default_token
-
+
def lex_document(self, cli, document):
lines = document.lines
-
+
def get_line(lineno):
" Return the tokens for the given line. "
try:
@@ -146,9 +146,9 @@ class RegexSync(SyntaxSync):
return cls(p)
-class PygmentsLexer(Lexer):
- """
- Lexer that calls a pygments lexer.
+class PygmentsLexer(Lexer):
+ """
+ Lexer that calls a pygments lexer.
Example::
@@ -169,7 +169,7 @@ class PygmentsLexer(Lexer):
recommended to disable this for inputs that are expected to be more
than 1,000 lines.
:param syntax_sync: `SyntaxSync` object.
- """
+ """
# Minimum amount of lines to go backwards when starting the parser.
# This is important when the lines are retrieved in reverse order, or when
# scrolling upwards. (Due to the complexity of calculating the vertical
@@ -185,15 +185,15 @@ class PygmentsLexer(Lexer):
def __init__(self, pygments_lexer_cls, sync_from_start=True, syntax_sync=None):
assert syntax_sync is None or isinstance(syntax_sync, SyntaxSync)
- self.pygments_lexer_cls = pygments_lexer_cls
+ self.pygments_lexer_cls = pygments_lexer_cls
self.sync_from_start = to_cli_filter(sync_from_start)
-
- # Instantiate the Pygments lexer.
- self.pygments_lexer = pygments_lexer_cls(
- stripnl=False,
- stripall=False,
- ensurenl=False)
-
+
+ # Instantiate the Pygments lexer.
+ self.pygments_lexer = pygments_lexer_cls(
+ stripnl=False,
+ stripall=False,
+ ensurenl=False)
+
# Create syntax sync instance.
self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
index 5b3e116f65..2934dfc9a7 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
@@ -1,166 +1,166 @@
-"""
-Margin implementations for a :class:`~prompt_toolkit.layout.containers.Window`.
-"""
-from __future__ import unicode_literals
-
+"""
+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 import with_metaclass
from six.moves import range
-
-from prompt_toolkit.filters import to_cli_filter
+
+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',
+
+__all__ = (
+ 'Margin',
+ 'NumberredMargin',
+ 'ScrollbarMargin',
+ 'ConditionalMargin',
'PromptMargin',
-)
-
-
-class Margin(with_metaclass(ABCMeta, object)):
- """
- Base interface for a margin.
- """
- @abstractmethod
+)
+
+
+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.
+ """
+ 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.
-
+ """
+ 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 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.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.
+
+ 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 = []
+
+ # 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.
+ # Current line.
+ if relative:
+ # Left align current number in relative mode.
result.append((token_current, '%i' % (lineno + 1)))
- else:
+ else:
result.append((token_current, ('%i ' % (lineno + 1)).rjust(width)))
- else:
- # Other lines.
- if relative:
+ 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'))
-
+ 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)
-
+ 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):
+ 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.
+ 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
+ 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:
@@ -170,7 +170,7 @@ class ScrollbarMargin(Margin):
" 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:
@@ -178,7 +178,7 @@ class ScrollbarMargin(Margin):
(Token.Scrollbar.Arrow, '^'),
(Token.Scrollbar, '\n')
])
-
+
# Scrollbar body.
for i in range(window_height):
if is_scroll_button(i):
@@ -186,7 +186,7 @@ class ScrollbarMargin(Margin):
else:
result.append((Token.Scrollbar, ' '))
result.append((Token, '\n'))
-
+
# Down arrow
if display_arrows:
result.append((Token.Scrollbar.Arrow, 'v'))
@@ -246,8 +246,8 @@ class PromptMargin(Margin):
if show_numbers:
if y != last_y:
tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width)))
- else:
+ else:
tokens.extend(tokens2)
last_y = y
-
+
return tokens
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
index 01e2a8358b..a916846e45 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
@@ -1,496 +1,496 @@
-from __future__ import unicode_literals
-
+from __future__ import unicode_literals
+
from six.moves import zip_longest, range
from prompt_toolkit.filters import HasCompletions, IsDone, Condition, to_cli_filter
from prompt_toolkit.mouse_events import MouseEventType
from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-
+from prompt_toolkit.utils import get_cwidth
+
from .containers import Window, HSplit, ConditionalContainer, ScrollOffsets
from .controls import UIControl, UIContent
-from .dimension import LayoutDimension
+from .dimension import LayoutDimension
from .margins import ScrollbarMargin
from .screen import Point, Char
-
-import math
-
-__all__ = (
- 'CompletionsMenu',
- 'MultiColumnCompletionsMenu',
-)
-
-
-class CompletionsMenuControl(UIControl):
- """
- Helper for drawing the complete menu to the screen.
-
- :param scroll_offset: Number (integer) representing the preferred amount of
- completions to be displayed before and after the current one. When this
- is a very high number, the current completion will be shown in the
- middle most of the time.
- """
+
+import math
+
+__all__ = (
+ 'CompletionsMenu',
+ 'MultiColumnCompletionsMenu',
+)
+
+
+class CompletionsMenuControl(UIControl):
+ """
+ Helper for drawing the complete menu to the screen.
+
+ :param scroll_offset: Number (integer) representing the preferred amount of
+ completions to be displayed before and after the current one. When this
+ is a very high number, the current completion will be shown in the
+ middle most of the time.
+ """
# Preferred minimum size of the menu control.
# The CompletionsMenu class defines a width of 8, and there is a scrollbar
# of 1.)
MIN_WIDTH = 7
-
+
def __init__(self):
- self.token = Token.Menu.Completions
-
- def has_focus(self, cli):
- return False
-
- def preferred_width(self, cli, max_available_width):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- menu_width = self._get_menu_width(500, complete_state)
- menu_meta_width = self._get_menu_meta_width(500, complete_state)
-
+ self.token = Token.Menu.Completions
+
+ def has_focus(self, cli):
+ return False
+
+ def preferred_width(self, cli, max_available_width):
+ complete_state = cli.current_buffer.complete_state
+ if complete_state:
+ menu_width = self._get_menu_width(500, complete_state)
+ menu_meta_width = self._get_menu_meta_width(500, complete_state)
+
return menu_width + menu_meta_width
- else:
- return 0
-
+ else:
+ return 0
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- return len(complete_state.current_completions)
- else:
- return 0
-
+ complete_state = cli.current_buffer.complete_state
+ if complete_state:
+ return len(complete_state.current_completions)
+ else:
+ return 0
+
def create_content(self, cli, width, height):
- """
+ """
Create a UIContent object for this control.
- """
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- completions = complete_state.current_completions
- index = complete_state.complete_index # Can be None!
-
- # Calculate width of completions menu.
+ """
+ complete_state = cli.current_buffer.complete_state
+ if complete_state:
+ completions = complete_state.current_completions
+ index = complete_state.complete_index # Can be None!
+
+ # Calculate width of completions menu.
menu_width = self._get_menu_width(width, complete_state)
menu_meta_width = self._get_menu_meta_width(width - menu_width, complete_state)
- show_meta = self._show_meta(complete_state)
-
+ show_meta = self._show_meta(complete_state)
+
def get_line(i):
c = completions[i]
is_current_completion = (i == index)
result = self._get_menu_item_tokens(c, is_current_completion, menu_width)
-
+
if show_meta:
result += self._get_menu_item_meta_tokens(c, is_current_completion, menu_meta_width)
return result
-
+
return UIContent(get_line=get_line,
cursor_position=Point(x=0, y=index or 0),
line_count=len(completions),
default_char=Char(' ', self.token))
-
+
return UIContent()
-
- def _show_meta(self, complete_state):
- """
- Return ``True`` if we need to show a column with meta information.
- """
- return any(c.display_meta for c in complete_state.current_completions)
-
- def _get_menu_width(self, max_width, complete_state):
- """
- Return the width of the main column.
- """
+
+ def _show_meta(self, complete_state):
+ """
+ Return ``True`` if we need to show a column with meta information.
+ """
+ return any(c.display_meta for c in complete_state.current_completions)
+
+ def _get_menu_width(self, max_width, complete_state):
+ """
+ Return the width of the main column.
+ """
return min(max_width, max(self.MIN_WIDTH, max(get_cwidth(c.display)
for c in complete_state.current_completions) + 2))
-
- def _get_menu_meta_width(self, max_width, complete_state):
- """
- Return the width of the meta column.
- """
- if self._show_meta(complete_state):
- return min(max_width, max(get_cwidth(c.display_meta)
- for c in complete_state.current_completions) + 2)
- else:
- return 0
-
- def _get_menu_item_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Completion.Current
- else:
- token = self.token.Completion
-
- text, tw = _trim_text(completion.display, width - 2)
- padding = ' ' * (width - 2 - tw)
- return [(token, ' %s%s ' % (text, padding))]
-
- def _get_menu_item_meta_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Meta.Current
- else:
- token = self.token.Meta
-
- text, tw = _trim_text(completion.display_meta, width - 2)
- padding = ' ' * (width - 2 - tw)
- return [(token, ' %s%s ' % (text, padding))]
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle mouse events: clicking and scrolling.
- """
- b = cli.current_buffer
-
+
+ def _get_menu_meta_width(self, max_width, complete_state):
+ """
+ Return the width of the meta column.
+ """
+ if self._show_meta(complete_state):
+ return min(max_width, max(get_cwidth(c.display_meta)
+ for c in complete_state.current_completions) + 2)
+ else:
+ return 0
+
+ def _get_menu_item_tokens(self, completion, is_current_completion, width):
+ if is_current_completion:
+ token = self.token.Completion.Current
+ else:
+ token = self.token.Completion
+
+ text, tw = _trim_text(completion.display, width - 2)
+ padding = ' ' * (width - 2 - tw)
+ return [(token, ' %s%s ' % (text, padding))]
+
+ def _get_menu_item_meta_tokens(self, completion, is_current_completion, width):
+ if is_current_completion:
+ token = self.token.Meta.Current
+ else:
+ token = self.token.Meta
+
+ text, tw = _trim_text(completion.display_meta, width - 2)
+ padding = ' ' * (width - 2 - tw)
+ return [(token, ' %s%s ' % (text, padding))]
+
+ def mouse_handler(self, cli, mouse_event):
+ """
+ Handle mouse events: clicking and scrolling.
+ """
+ b = cli.current_buffer
+
if mouse_event.event_type == MouseEventType.MOUSE_UP:
- # Select completion.
+ # Select completion.
b.go_to_completion(mouse_event.position.y)
- b.complete_state = None
-
+ b.complete_state = None
+
elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- # Scroll up.
- b.complete_next(count=3, disable_wrap_around=True)
-
+ # Scroll up.
+ b.complete_next(count=3, disable_wrap_around=True)
+
elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- # Scroll down.
- b.complete_previous(count=3, disable_wrap_around=True)
-
-
-def _trim_text(text, max_width):
- """
- Trim the text to `max_width`, append dots when the text is too long.
- Returns (text, width) tuple.
- """
- width = get_cwidth(text)
-
- # When the text is too wide, trim it.
- if width > max_width:
- # When there are no double width characters, just use slice operation.
- if len(text) == width:
- trimmed_text = (text[:max(1, max_width-3)] + '...')[:max_width]
- return trimmed_text, len(trimmed_text)
-
- # Otherwise, loop until we have the desired width. (Rather
- # inefficient, but ok for now.)
- else:
- trimmed_text = ''
- for c in text:
- if get_cwidth(trimmed_text + c) <= max_width - 3:
- trimmed_text += c
- trimmed_text += '...'
-
- return (trimmed_text, get_cwidth(trimmed_text))
- else:
- return text, width
-
-
-class CompletionsMenu(ConditionalContainer):
+ # Scroll down.
+ b.complete_previous(count=3, disable_wrap_around=True)
+
+
+def _trim_text(text, max_width):
+ """
+ Trim the text to `max_width`, append dots when the text is too long.
+ Returns (text, width) tuple.
+ """
+ width = get_cwidth(text)
+
+ # When the text is too wide, trim it.
+ if width > max_width:
+ # When there are no double width characters, just use slice operation.
+ if len(text) == width:
+ trimmed_text = (text[:max(1, max_width-3)] + '...')[:max_width]
+ return trimmed_text, len(trimmed_text)
+
+ # Otherwise, loop until we have the desired width. (Rather
+ # inefficient, but ok for now.)
+ else:
+ trimmed_text = ''
+ for c in text:
+ if get_cwidth(trimmed_text + c) <= max_width - 3:
+ trimmed_text += c
+ trimmed_text += '...'
+
+ return (trimmed_text, get_cwidth(trimmed_text))
+ else:
+ return text, width
+
+
+class CompletionsMenu(ConditionalContainer):
def __init__(self, max_height=None, scroll_offset=0, extra_filter=True, display_arrows=False):
extra_filter = to_cli_filter(extra_filter)
display_arrows = to_cli_filter(display_arrows)
- super(CompletionsMenu, self).__init__(
- content=Window(
+ super(CompletionsMenu, self).__init__(
+ content=Window(
content=CompletionsMenuControl(),
- width=LayoutDimension(min=8),
+ width=LayoutDimension(min=8),
height=LayoutDimension(min=1, max=max_height),
scroll_offsets=ScrollOffsets(top=scroll_offset, bottom=scroll_offset),
right_margins=[ScrollbarMargin(display_arrows=display_arrows)],
dont_extend_width=True,
),
- # Show when there are completions but not at the point we are
- # returning the input.
- filter=HasCompletions() & ~IsDone() & extra_filter)
-
-
-class MultiColumnCompletionMenuControl(UIControl):
- """
- Completion menu that displays all the completions in several columns.
- When there are more completions than space for them to be displayed, an
- arrow is shown on the left or right side.
-
- `min_rows` indicates how many rows will be available in any possible case.
- When this is langer than one, in will try to use less columns and more
- rows until this value is reached.
- Be careful passing in a too big value, if less than the given amount of
- rows are available, more columns would have been required, but
- `preferred_width` doesn't know about that and reports a too small value.
- This results in less completions displayed and additional scrolling.
- (It's a limitation of how the layout engine currently works: first the
- widths are calculated, then the heights.)
-
- :param suggested_max_column_width: The suggested max width of a column.
- The column can still be bigger than this, but if there is place for two
- columns of this width, we will display two columns. This to avoid that
- if there is one very wide completion, that it doesn't significantly
- reduce the amount of columns.
- """
- _required_margin = 3 # One extra padding on the right + space for arrows.
-
- def __init__(self, min_rows=3, suggested_max_column_width=30):
- assert isinstance(min_rows, int) and min_rows >= 1
-
- self.min_rows = min_rows
- self.suggested_max_column_width = suggested_max_column_width
- self.token = Token.Menu.Completions
- self.scroll = 0
-
- # Info of last rendering.
- self._rendered_rows = 0
- self._rendered_columns = 0
- self._total_columns = 0
- self._render_pos_to_completion = {}
- self._render_left_arrow = False
- self._render_right_arrow = False
- self._render_width = 0
-
- def reset(self):
- self.scroll = 0
-
- def has_focus(self, cli):
- return False
-
- def preferred_width(self, cli, max_available_width):
- """
- Preferred width: prefer to use at least min_rows, but otherwise as much
- as possible horizontally.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- result = int(column_width * math.ceil(len(complete_state.current_completions) / float(self.min_rows)))
-
- # When the desired width is still more than the maximum available,
- # reduce by removing columns until we are less than the available
- # width.
- while result > column_width and result > max_available_width - self._required_margin:
- result -= column_width
- return result + self._required_margin
-
+ # Show when there are completions but not at the point we are
+ # returning the input.
+ filter=HasCompletions() & ~IsDone() & extra_filter)
+
+
+class MultiColumnCompletionMenuControl(UIControl):
+ """
+ Completion menu that displays all the completions in several columns.
+ When there are more completions than space for them to be displayed, an
+ arrow is shown on the left or right side.
+
+ `min_rows` indicates how many rows will be available in any possible case.
+ When this is langer than one, in will try to use less columns and more
+ rows until this value is reached.
+ Be careful passing in a too big value, if less than the given amount of
+ rows are available, more columns would have been required, but
+ `preferred_width` doesn't know about that and reports a too small value.
+ This results in less completions displayed and additional scrolling.
+ (It's a limitation of how the layout engine currently works: first the
+ widths are calculated, then the heights.)
+
+ :param suggested_max_column_width: The suggested max width of a column.
+ The column can still be bigger than this, but if there is place for two
+ columns of this width, we will display two columns. This to avoid that
+ if there is one very wide completion, that it doesn't significantly
+ reduce the amount of columns.
+ """
+ _required_margin = 3 # One extra padding on the right + space for arrows.
+
+ def __init__(self, min_rows=3, suggested_max_column_width=30):
+ assert isinstance(min_rows, int) and min_rows >= 1
+
+ self.min_rows = min_rows
+ self.suggested_max_column_width = suggested_max_column_width
+ self.token = Token.Menu.Completions
+ self.scroll = 0
+
+ # Info of last rendering.
+ self._rendered_rows = 0
+ self._rendered_columns = 0
+ self._total_columns = 0
+ self._render_pos_to_completion = {}
+ self._render_left_arrow = False
+ self._render_right_arrow = False
+ self._render_width = 0
+
+ def reset(self):
+ self.scroll = 0
+
+ def has_focus(self, cli):
+ return False
+
+ def preferred_width(self, cli, max_available_width):
+ """
+ Preferred width: prefer to use at least min_rows, but otherwise as much
+ as possible horizontally.
+ """
+ complete_state = cli.current_buffer.complete_state
+ column_width = self._get_column_width(complete_state)
+ result = int(column_width * math.ceil(len(complete_state.current_completions) / float(self.min_rows)))
+
+ # When the desired width is still more than the maximum available,
+ # reduce by removing columns until we are less than the available
+ # width.
+ while result > column_width and result > max_available_width - self._required_margin:
+ result -= column_width
+ return result + self._required_margin
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
- """
- Preferred height: as much as needed in order to display all the completions.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- column_count = max(1, (width - self._required_margin) // column_width)
-
- return int(math.ceil(len(complete_state.current_completions) / float(column_count)))
-
+ """
+ Preferred height: as much as needed in order to display all the completions.
+ """
+ complete_state = cli.current_buffer.complete_state
+ column_width = self._get_column_width(complete_state)
+ column_count = max(1, (width - self._required_margin) // column_width)
+
+ return int(math.ceil(len(complete_state.current_completions) / float(column_count)))
+
def create_content(self, cli, width, height):
- """
+ """
Create a UIContent object for this menu.
- """
- complete_state = cli.current_buffer.complete_state
- column_width = self._get_column_width(complete_state)
- self._render_pos_to_completion = {}
-
- def grouper(n, iterable, fillvalue=None):
- " grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx "
- args = [iter(iterable)] * n
- return zip_longest(fillvalue=fillvalue, *args)
-
- def is_current_completion(completion):
- " Returns True when this completion is the currently selected one. "
- return complete_state.complete_index is not None and c == complete_state.current_completion
-
- # Space required outside of the regular columns, for displaying the
- # left and right arrow.
- HORIZONTAL_MARGIN_REQUIRED = 3
-
- if complete_state:
- # There should be at least one column, but it cannot be wider than
- # the available width.
- column_width = min(width - HORIZONTAL_MARGIN_REQUIRED, column_width)
-
- # However, when the columns tend to be very wide, because there are
- # some very wide entries, shrink it anyway.
- if column_width > self.suggested_max_column_width:
- # `column_width` can still be bigger that `suggested_max_column_width`,
- # but if there is place for two columns, we divide by two.
- column_width //= (column_width // self.suggested_max_column_width)
-
- visible_columns = max(1, (width - self._required_margin) // column_width)
-
- columns_ = list(grouper(height, complete_state.current_completions))
- rows_ = list(zip(*columns_))
-
- # Make sure the current completion is always visible: update scroll offset.
- selected_column = (complete_state.complete_index or 0) // height
- self.scroll = min(selected_column, max(self.scroll, selected_column - visible_columns + 1))
-
- render_left_arrow = self.scroll > 0
- render_right_arrow = self.scroll < len(rows_[0]) - visible_columns
-
- # Write completions to screen.
+ """
+ complete_state = cli.current_buffer.complete_state
+ column_width = self._get_column_width(complete_state)
+ self._render_pos_to_completion = {}
+
+ def grouper(n, iterable, fillvalue=None):
+ " grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx "
+ args = [iter(iterable)] * n
+ return zip_longest(fillvalue=fillvalue, *args)
+
+ def is_current_completion(completion):
+ " Returns True when this completion is the currently selected one. "
+ return complete_state.complete_index is not None and c == complete_state.current_completion
+
+ # Space required outside of the regular columns, for displaying the
+ # left and right arrow.
+ HORIZONTAL_MARGIN_REQUIRED = 3
+
+ if complete_state:
+ # There should be at least one column, but it cannot be wider than
+ # the available width.
+ column_width = min(width - HORIZONTAL_MARGIN_REQUIRED, column_width)
+
+ # However, when the columns tend to be very wide, because there are
+ # some very wide entries, shrink it anyway.
+ if column_width > self.suggested_max_column_width:
+ # `column_width` can still be bigger that `suggested_max_column_width`,
+ # but if there is place for two columns, we divide by two.
+ column_width //= (column_width // self.suggested_max_column_width)
+
+ visible_columns = max(1, (width - self._required_margin) // column_width)
+
+ columns_ = list(grouper(height, complete_state.current_completions))
+ rows_ = list(zip(*columns_))
+
+ # Make sure the current completion is always visible: update scroll offset.
+ selected_column = (complete_state.complete_index or 0) // height
+ self.scroll = min(selected_column, max(self.scroll, selected_column - visible_columns + 1))
+
+ render_left_arrow = self.scroll > 0
+ render_right_arrow = self.scroll < len(rows_[0]) - visible_columns
+
+ # Write completions to screen.
tokens_for_line = []
-
- for row_index, row in enumerate(rows_):
+
+ for row_index, row in enumerate(rows_):
tokens = []
- middle_row = row_index == len(rows_) // 2
-
- # Draw left arrow if we have hidden completions on the left.
- if render_left_arrow:
+ middle_row = row_index == len(rows_) // 2
+
+ # Draw left arrow if we have hidden completions on the left.
+ if render_left_arrow:
tokens += [(Token.Scrollbar, '<' if middle_row else ' ')]
-
- # Draw row content.
- for column_index, c in enumerate(row[self.scroll:][:visible_columns]):
- if c is not None:
- tokens += self._get_menu_item_tokens(c, is_current_completion(c), column_width)
-
- # Remember render position for mouse click handler.
- for x in range(column_width):
- self._render_pos_to_completion[(column_index * column_width + x, row_index)] = c
- else:
- tokens += [(self.token.Completion, ' ' * column_width)]
-
- # Draw trailing padding. (_get_menu_item_tokens only returns padding on the left.)
- tokens += [(self.token.Completion, ' ')]
-
- # Draw right arrow if we have hidden completions on the right.
- if render_right_arrow:
+
+ # Draw row content.
+ for column_index, c in enumerate(row[self.scroll:][:visible_columns]):
+ if c is not None:
+ tokens += self._get_menu_item_tokens(c, is_current_completion(c), column_width)
+
+ # Remember render position for mouse click handler.
+ for x in range(column_width):
+ self._render_pos_to_completion[(column_index * column_width + x, row_index)] = c
+ else:
+ tokens += [(self.token.Completion, ' ' * column_width)]
+
+ # Draw trailing padding. (_get_menu_item_tokens only returns padding on the left.)
+ tokens += [(self.token.Completion, ' ')]
+
+ # Draw right arrow if we have hidden completions on the right.
+ if render_right_arrow:
tokens += [(Token.Scrollbar, '>' if middle_row else ' ')]
-
- # Newline.
+
+ # Newline.
tokens_for_line.append(tokens)
-
+
else:
tokens = []
-
- self._rendered_rows = height
- self._rendered_columns = visible_columns
- self._total_columns = len(columns_)
- self._render_left_arrow = render_left_arrow
- self._render_right_arrow = render_right_arrow
- self._render_width = column_width * visible_columns + render_left_arrow + render_right_arrow + 1
-
+
+ self._rendered_rows = height
+ self._rendered_columns = visible_columns
+ self._total_columns = len(columns_)
+ self._render_left_arrow = render_left_arrow
+ self._render_right_arrow = render_right_arrow
+ self._render_width = column_width * visible_columns + render_left_arrow + render_right_arrow + 1
+
def get_line(i):
return tokens_for_line[i]
-
+
return UIContent(get_line=get_line, line_count=len(rows_))
- def _get_column_width(self, complete_state):
- """
- Return the width of each column.
- """
- return max(get_cwidth(c.display) for c in complete_state.current_completions) + 1
-
- def _get_menu_item_tokens(self, completion, is_current_completion, width):
- if is_current_completion:
- token = self.token.Completion.Current
- else:
- token = self.token.Completion
-
- text, tw = _trim_text(completion.display, width)
- padding = ' ' * (width - tw - 1)
-
- return [(token, ' %s%s' % (text, padding))]
-
- def mouse_handler(self, cli, mouse_event):
- """
- Handle scoll and click events.
- """
- b = cli.current_buffer
-
- def scroll_left():
- b.complete_previous(count=self._rendered_rows, disable_wrap_around=True)
- self.scroll = max(0, self.scroll - 1)
-
- def scroll_right():
- b.complete_next(count=self._rendered_rows, disable_wrap_around=True)
- self.scroll = min(self._total_columns - self._rendered_columns, self.scroll + 1)
-
+ def _get_column_width(self, complete_state):
+ """
+ Return the width of each column.
+ """
+ return max(get_cwidth(c.display) for c in complete_state.current_completions) + 1
+
+ def _get_menu_item_tokens(self, completion, is_current_completion, width):
+ if is_current_completion:
+ token = self.token.Completion.Current
+ else:
+ token = self.token.Completion
+
+ text, tw = _trim_text(completion.display, width)
+ padding = ' ' * (width - tw - 1)
+
+ return [(token, ' %s%s' % (text, padding))]
+
+ def mouse_handler(self, cli, mouse_event):
+ """
+ Handle scoll and click events.
+ """
+ b = cli.current_buffer
+
+ def scroll_left():
+ b.complete_previous(count=self._rendered_rows, disable_wrap_around=True)
+ self.scroll = max(0, self.scroll - 1)
+
+ def scroll_right():
+ b.complete_next(count=self._rendered_rows, disable_wrap_around=True)
+ self.scroll = min(self._total_columns - self._rendered_columns, self.scroll + 1)
+
if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
- scroll_right()
-
+ scroll_right()
+
elif mouse_event.event_type == MouseEventType.SCROLL_UP:
- scroll_left()
-
+ scroll_left()
+
elif mouse_event.event_type == MouseEventType.MOUSE_UP:
- x = mouse_event.position.x
- y = mouse_event.position.y
-
- # Mouse click on left arrow.
- if x == 0:
- if self._render_left_arrow:
- scroll_left()
-
- # Mouse click on right arrow.
- elif x == self._render_width - 1:
- if self._render_right_arrow:
- scroll_right()
-
- # Mouse click on completion.
- else:
- completion = self._render_pos_to_completion.get((x, y))
- if completion:
- b.apply_completion(completion)
-
-
-class MultiColumnCompletionsMenu(HSplit):
- """
- Container that displays the completions in several columns.
- When `show_meta` (a :class:`~prompt_toolkit.filters.CLIFilter`) evaluates
- to True, it shows the meta information at the bottom.
- """
- def __init__(self, min_rows=3, suggested_max_column_width=30, show_meta=True, extra_filter=True):
- show_meta = to_cli_filter(show_meta)
- extra_filter = to_cli_filter(extra_filter)
-
- # Display filter: show when there are completions but not at the point
- # we are returning the input.
- full_filter = HasCompletions() & ~IsDone() & extra_filter
-
- any_completion_has_meta = Condition(lambda cli:
- any(c.display_meta for c in cli.current_buffer.complete_state.current_completions))
-
- # Create child windows.
- completions_window = ConditionalContainer(
- content=Window(
- content=MultiColumnCompletionMenuControl(
- min_rows=min_rows, suggested_max_column_width=suggested_max_column_width),
- width=LayoutDimension(min=8),
- height=LayoutDimension(min=1)),
- filter=full_filter)
-
- meta_window = ConditionalContainer(
- content=Window(content=_SelectedCompletionMetaControl()),
- filter=show_meta & full_filter & any_completion_has_meta)
-
- # Initialise split.
- super(MultiColumnCompletionsMenu, self).__init__([
- completions_window,
- meta_window
- ])
-
-
-class _SelectedCompletionMetaControl(UIControl):
- """
- Control that shows the meta information of the selected token.
- """
- def preferred_width(self, cli, max_available_width):
- """
- Report the width of the longest meta text as the preferred width of this control.
-
- It could be that we use less width, but this way, we're sure that the
- layout doesn't change when we select another completion (E.g. that
- completions are suddenly shown in more or fewer columns.)
- """
- if cli.current_buffer.complete_state:
- state = cli.current_buffer.complete_state
- return 2 + max(get_cwidth(c.display_meta) for c in state.current_completions)
- else:
- return 0
-
+ x = mouse_event.position.x
+ y = mouse_event.position.y
+
+ # Mouse click on left arrow.
+ if x == 0:
+ if self._render_left_arrow:
+ scroll_left()
+
+ # Mouse click on right arrow.
+ elif x == self._render_width - 1:
+ if self._render_right_arrow:
+ scroll_right()
+
+ # Mouse click on completion.
+ else:
+ completion = self._render_pos_to_completion.get((x, y))
+ if completion:
+ b.apply_completion(completion)
+
+
+class MultiColumnCompletionsMenu(HSplit):
+ """
+ Container that displays the completions in several columns.
+ When `show_meta` (a :class:`~prompt_toolkit.filters.CLIFilter`) evaluates
+ to True, it shows the meta information at the bottom.
+ """
+ def __init__(self, min_rows=3, suggested_max_column_width=30, show_meta=True, extra_filter=True):
+ show_meta = to_cli_filter(show_meta)
+ extra_filter = to_cli_filter(extra_filter)
+
+ # Display filter: show when there are completions but not at the point
+ # we are returning the input.
+ full_filter = HasCompletions() & ~IsDone() & extra_filter
+
+ any_completion_has_meta = Condition(lambda cli:
+ any(c.display_meta for c in cli.current_buffer.complete_state.current_completions))
+
+ # Create child windows.
+ completions_window = ConditionalContainer(
+ content=Window(
+ content=MultiColumnCompletionMenuControl(
+ min_rows=min_rows, suggested_max_column_width=suggested_max_column_width),
+ width=LayoutDimension(min=8),
+ height=LayoutDimension(min=1)),
+ filter=full_filter)
+
+ meta_window = ConditionalContainer(
+ content=Window(content=_SelectedCompletionMetaControl()),
+ filter=show_meta & full_filter & any_completion_has_meta)
+
+ # Initialise split.
+ super(MultiColumnCompletionsMenu, self).__init__([
+ completions_window,
+ meta_window
+ ])
+
+
+class _SelectedCompletionMetaControl(UIControl):
+ """
+ Control that shows the meta information of the selected token.
+ """
+ def preferred_width(self, cli, max_available_width):
+ """
+ Report the width of the longest meta text as the preferred width of this control.
+
+ It could be that we use less width, but this way, we're sure that the
+ layout doesn't change when we select another completion (E.g. that
+ completions are suddenly shown in more or fewer columns.)
+ """
+ if cli.current_buffer.complete_state:
+ state = cli.current_buffer.complete_state
+ return 2 + max(get_cwidth(c.display_meta) for c in state.current_completions)
+ else:
+ return 0
+
def preferred_height(self, cli, width, max_available_height, wrap_lines):
- return 1
-
+ return 1
+
def create_content(self, cli, width, height):
tokens = self._get_tokens(cli)
-
+
def get_line(i):
return tokens
return UIContent(get_line=get_line, line_count=1 if tokens else 0)
- def _get_tokens(self, cli):
- token = Token.Menu.Completions.MultiColumnMeta
- state = cli.current_buffer.complete_state
-
- if state and state.current_completion and state.current_completion.display_meta:
- return [(token, ' %s ' % state.current_completion.display_meta)]
-
- return []
+ def _get_tokens(self, cli):
+ token = Token.Menu.Completions.MultiColumnMeta
+ state = cli.current_buffer.complete_state
+
+ if state and state.current_completion and state.current_completion.display_meta:
+ return [(token, ' %s ' % state.current_completion.display_meta)]
+
+ return []
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py
index 57e4125b6d..d443bf8315 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/mouse_handlers.py
@@ -1,29 +1,29 @@
-from __future__ import unicode_literals
-
-from itertools import product
-from collections import defaultdict
-
-__all__ = (
- 'MouseHandlers',
-)
-
-
-class MouseHandlers(object):
- """
- Two dimentional raster of callbacks for mouse events.
- """
- def __init__(self):
- def dummy_callback(cli, mouse_event):
- """
- :param mouse_event: `MouseEvent` instance.
- """
-
- # Map (x,y) tuples to handlers.
- self.mouse_handlers = defaultdict(lambda: dummy_callback)
-
- def set_mouse_handler_for_range(self, x_min, x_max, y_min, y_max, handler=None):
- """
- Set mouse handler for a region.
- """
- for x, y in product(range(x_min, x_max), range(y_min, y_max)):
- self.mouse_handlers[x,y] = handler
+from __future__ import unicode_literals
+
+from itertools import product
+from collections import defaultdict
+
+__all__ = (
+ 'MouseHandlers',
+)
+
+
+class MouseHandlers(object):
+ """
+ Two dimentional raster of callbacks for mouse events.
+ """
+ def __init__(self):
+ def dummy_callback(cli, mouse_event):
+ """
+ :param mouse_event: `MouseEvent` instance.
+ """
+
+ # Map (x,y) tuples to handlers.
+ self.mouse_handlers = defaultdict(lambda: dummy_callback)
+
+ def set_mouse_handler_for_range(self, x_min, x_max, y_min, y_max, handler=None):
+ """
+ Set mouse handler for a region.
+ """
+ for x, y in product(range(x_min, x_max), range(y_min, y_max)):
+ self.mouse_handlers[x,y] = handler
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
index 6054fc3caf..0b8bc9c223 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
@@ -1,55 +1,55 @@
-"""
-Processors are little transformation blocks that transform the token list from
-a buffer before the BufferControl will render it to the screen.
-
-They can insert tokens before or after, or highlight fragments by replacing the
-token types.
-"""
-from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
-from six import with_metaclass
+"""
+Processors are little transformation blocks that transform the token list from
+a buffer before the BufferControl will render it to the screen.
+
+They can insert tokens before or after, or highlight fragments by replacing the
+token types.
+"""
+from __future__ import unicode_literals
+from abc import ABCMeta, abstractmethod
+from six import with_metaclass
from six.moves import range
-
+
from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.document import Document
-from prompt_toolkit.enums import SEARCH_BUFFER
+from prompt_toolkit.document import Document
+from prompt_toolkit.enums import SEARCH_BUFFER
from prompt_toolkit.filters import to_cli_filter, ViInsertMultipleMode
-from prompt_toolkit.layout.utils import token_list_to_text
+from prompt_toolkit.layout.utils import token_list_to_text
from prompt_toolkit.reactive import Integer
from prompt_toolkit.token import Token
-
+
from .utils import token_list_len, explode_tokens
-
+
import re
-__all__ = (
- 'Processor',
- 'Transformation',
-
- 'HighlightSearchProcessor',
- 'HighlightSelectionProcessor',
- 'PasswordProcessor',
+__all__ = (
+ 'Processor',
+ 'Transformation',
+
+ 'HighlightSearchProcessor',
+ 'HighlightSelectionProcessor',
+ 'PasswordProcessor',
'HighlightMatchingBracketProcessor',
'DisplayMultipleCursors',
- 'BeforeInput',
- 'AfterInput',
- 'AppendAutoSuggestion',
- 'ConditionalProcessor',
- 'ShowLeadingWhiteSpaceProcessor',
- 'ShowTrailingWhiteSpaceProcessor',
+ 'BeforeInput',
+ 'AfterInput',
+ 'AppendAutoSuggestion',
+ 'ConditionalProcessor',
+ 'ShowLeadingWhiteSpaceProcessor',
+ 'ShowTrailingWhiteSpaceProcessor',
'TabsProcessor',
-)
-
-
-class Processor(with_metaclass(ABCMeta, object)):
- """
+)
+
+
+class Processor(with_metaclass(ABCMeta, object)):
+ """
Manipulate the tokens for a given line in a
- :class:`~prompt_toolkit.layout.controls.BufferControl`.
- """
- @abstractmethod
+ :class:`~prompt_toolkit.layout.controls.BufferControl`.
+ """
+ @abstractmethod
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- """
- Apply transformation. Returns a :class:`.Transformation` instance.
+ """
+ Apply transformation. Returns a :class:`.Transformation` instance.
:param cli: :class:`.CommandLineInterface` instance.
:param lineno: The number of the line to which we apply the processor.
@@ -58,114 +58,114 @@ class Processor(with_metaclass(ABCMeta, object)):
previous processors into account.)
:param tokens: List of tokens that we can transform. (Received from the
previous processor.)
- """
+ """
return Transformation(tokens)
-
- def has_focus(self, cli):
- """
- Processors can override the focus.
- (Used for the reverse-i-search prefix in DefaultPrompt.)
- """
- return False
-
-
-class Transformation(object):
- """
- Transformation result, as returned by :meth:`.Processor.apply_transformation`.
-
- Important: Always make sure that the length of `document.text` is equal to
- the length of all the text in `tokens`!
-
- :param tokens: The transformed tokens. To be displayed, or to pass to the
- next processor.
- :param source_to_display: Cursor position transformation from original string to
- transformed string.
- :param display_to_source: Cursor position transformed from source string to
- original string.
- """
+
+ def has_focus(self, cli):
+ """
+ Processors can override the focus.
+ (Used for the reverse-i-search prefix in DefaultPrompt.)
+ """
+ return False
+
+
+class Transformation(object):
+ """
+ Transformation result, as returned by :meth:`.Processor.apply_transformation`.
+
+ Important: Always make sure that the length of `document.text` is equal to
+ the length of all the text in `tokens`!
+
+ :param tokens: The transformed tokens. To be displayed, or to pass to the
+ next processor.
+ :param source_to_display: Cursor position transformation from original string to
+ transformed string.
+ :param display_to_source: Cursor position transformed from source string to
+ original string.
+ """
def __init__(self, tokens, source_to_display=None, display_to_source=None):
- self.tokens = tokens
- self.source_to_display = source_to_display or (lambda i: i)
- self.display_to_source = display_to_source or (lambda i: i)
-
-
+ self.tokens = tokens
+ self.source_to_display = source_to_display or (lambda i: i)
+ self.display_to_source = display_to_source or (lambda i: i)
+
+
class HighlightSearchProcessor(Processor):
- """
- Processor that highlights search matches in the document.
+ """
+ Processor that highlights search matches in the document.
Note that this doesn't support multiline search matches yet.
-
- :param preview_search: A Filter; when active it indicates that we take
- the search text in real time while the user is typing, instead of the
- last active search state.
- """
+
+ :param preview_search: A Filter; when active it indicates that we take
+ the search text in real time while the user is typing, instead of the
+ last active search state.
+ """
def __init__(self, preview_search=False, search_buffer_name=SEARCH_BUFFER,
get_search_state=None):
- self.preview_search = to_cli_filter(preview_search)
- self.search_buffer_name = search_buffer_name
+ self.preview_search = to_cli_filter(preview_search)
+ self.search_buffer_name = search_buffer_name
self.get_search_state = get_search_state or (lambda cli: cli.search_state)
-
- def _get_search_text(self, cli):
- """
- The text we are searching for.
- """
- # When the search buffer has focus, take that text.
- if self.preview_search(cli) and cli.buffers[self.search_buffer_name].text:
- return cli.buffers[self.search_buffer_name].text
- # Otherwise, take the text of the last active search.
- else:
+
+ def _get_search_text(self, cli):
+ """
+ The text we are searching for.
+ """
+ # When the search buffer has focus, take that text.
+ if self.preview_search(cli) and cli.buffers[self.search_buffer_name].text:
+ return cli.buffers[self.search_buffer_name].text
+ # Otherwise, take the text of the last active search.
+ else:
return self.get_search_state(cli).text
-
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- search_text = self._get_search_text(cli)
+ search_text = self._get_search_text(cli)
searchmatch_current_token = (':', ) + Token.SearchMatch.Current
searchmatch_token = (':', ) + Token.SearchMatch
-
- if search_text and not cli.is_returning:
- # For each search match, replace the Token.
+
+ if search_text and not cli.is_returning:
+ # For each search match, replace the Token.
line_text = token_list_to_text(tokens)
tokens = explode_tokens(tokens)
-
+
flags = re.IGNORECASE if cli.is_ignoring_case else 0
-
+
# Get cursor column.
if document.cursor_position_row == lineno:
cursor_column = source_to_display(document.cursor_position_col)
else:
cursor_column = None
-
+
for match in re.finditer(re.escape(search_text), line_text, flags=flags):
if cursor_column is not None:
on_cursor = match.start() <= cursor_column < match.end()
else:
on_cursor = False
-
+
for i in range(match.start(), match.end()):
old_token, text = tokens[i]
if on_cursor:
tokens[i] = (old_token + searchmatch_current_token, tokens[i][1])
else:
tokens[i] = (old_token + searchmatch_token, tokens[i][1])
-
+
return Transformation(tokens)
-
-
+
+
class HighlightSelectionProcessor(Processor):
- """
- Processor that highlights the selection in the document.
- """
+ """
+ Processor that highlights the selection in the document.
+ """
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
selected_token = (':', ) + Token.SelectedText
- # In case of selection, highlight all matches.
+ # In case of selection, highlight all matches.
selection_at_line = document.selection_range_at_line(lineno)
-
+
if selection_at_line:
from_, to = selection_at_line
from_ = source_to_display(from_)
to = source_to_display(to)
-
+
tokens = explode_tokens(tokens)
-
+
if from_ == 0 and to == 0 and len(tokens) == 0:
# When this is an empty line, insert a space in order to
# visualiase the selection.
@@ -175,43 +175,43 @@ class HighlightSelectionProcessor(Processor):
if i < len(tokens):
old_token, old_text = tokens[i]
tokens[i] = (old_token + selected_token, old_text)
-
+
return Transformation(tokens)
-
-
-class PasswordProcessor(Processor):
- """
- Processor that turns masks the input. (For passwords.)
-
- :param char: (string) Character to be used. "*" by default.
- """
- def __init__(self, char='*'):
- self.char = char
-
+
+
+class PasswordProcessor(Processor):
+ """
+ Processor that turns masks the input. (For passwords.)
+
+ :param char: (string) Character to be used. "*" by default.
+ """
+ def __init__(self, char='*'):
+ self.char = char
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
tokens = [(token, self.char * len(text)) for token, text in tokens]
return Transformation(tokens)
-
-
+
+
class HighlightMatchingBracketProcessor(Processor):
- """
- When the cursor is on or right after a bracket, it highlights the matching
- bracket.
+ """
+ When the cursor is on or right after a bracket, it highlights the matching
+ bracket.
:param max_cursor_distance: Only highlight matching brackets when the
cursor is within this distance. (From inside a `Processor`, we can't
know which lines will be visible on the screen. But we also don't want
to scan the whole document for matching brackets on each key press, so
we limit to this value.)
- """
- _closing_braces = '])}>'
-
+ """
+ _closing_braces = '])}>'
+
def __init__(self, chars='[](){}<>', max_cursor_distance=1000):
- self.chars = chars
+ self.chars = chars
self.max_cursor_distance = max_cursor_distance
-
+
self._positions_cache = SimpleCache(maxsize=8)
-
+
def _get_positions_to_highlight(self, document):
"""
Return a list of (row, col) tuples that need to be highlighted.
@@ -221,18 +221,18 @@ class HighlightMatchingBracketProcessor(Processor):
pos = document.find_matching_bracket_position(
start_pos=document.cursor_position - self.max_cursor_distance,
end_pos=document.cursor_position + self.max_cursor_distance)
-
+
# Try for the character before the cursor.
elif (document.char_before_cursor and document.char_before_cursor in
self._closing_braces and document.char_before_cursor in self.chars):
document = Document(document.text, document.cursor_position - 1)
-
+
pos = document.find_matching_bracket_position(
start_pos=document.cursor_position - self.max_cursor_distance,
end_pos=document.cursor_position + self.max_cursor_distance)
else:
pos = None
-
+
# Return a list of (row, col) tuples that need to be highlighted.
if pos:
pos += document.cursor_position # pos is relative.
@@ -240,13 +240,13 @@ class HighlightMatchingBracketProcessor(Processor):
return [(row, col), (document.cursor_position_row, document.cursor_position_col)]
else:
return []
-
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
# Get the highlight positions.
key = (cli.render_counter, document.text, document.cursor_position)
positions = self._positions_cache.get(
key, lambda: self._get_positions_to_highlight(document))
-
+
# Apply if positions were found at this line.
if positions:
for row, col in positions:
@@ -254,172 +254,172 @@ class HighlightMatchingBracketProcessor(Processor):
col = source_to_display(col)
tokens = explode_tokens(tokens)
token, text = tokens[col]
-
+
if col == document.cursor_position_col:
token += (':', ) + Token.MatchingBracket.Cursor
else:
token += (':', ) + Token.MatchingBracket.Other
-
+
tokens[col] = (token, text)
-
+
return Transformation(tokens)
class DisplayMultipleCursors(Processor):
- """
+ """
When we're in Vi block insert mode, display all the cursors.
- """
+ """
_insert_multiple = ViInsertMultipleMode()
-
+
def __init__(self, buffer_name):
self.buffer_name = buffer_name
-
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
buff = cli.buffers[self.buffer_name]
-
+
if self._insert_multiple(cli):
positions = buff.multiple_cursor_positions
tokens = explode_tokens(tokens)
-
+
# If any cursor appears on the current line, highlight that.
start_pos = document.translate_row_col_to_index(lineno, 0)
end_pos = start_pos + len(document.lines[lineno])
-
+
token_suffix = (':', ) + Token.MultipleCursors.Cursor
-
+
for p in positions:
if start_pos <= p < end_pos:
column = source_to_display(p - start_pos)
-
+
# Replace token.
token, text = tokens[column]
token += token_suffix
tokens[column] = (token, text)
elif p == end_pos:
tokens.append((token_suffix, ' '))
-
+
return Transformation(tokens)
else:
return Transformation(tokens)
-class BeforeInput(Processor):
- """
- Insert tokens before the input.
-
- :param get_tokens: Callable that takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
- list of tokens to be inserted.
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
+class BeforeInput(Processor):
+ """
+ Insert tokens before the input.
+
+ :param get_tokens: Callable that takes a
+ :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
+ list of tokens to be inserted.
+ """
+ def __init__(self, get_tokens):
+ assert callable(get_tokens)
+ self.get_tokens = get_tokens
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
if lineno == 0:
tokens_before = self.get_tokens(cli)
tokens = tokens_before + tokens
-
+
shift_position = token_list_len(tokens_before)
source_to_display = lambda i: i + shift_position
display_to_source = lambda i: i - shift_position
else:
source_to_display = None
display_to_source = None
-
+
return Transformation(tokens, source_to_display=source_to_display,
display_to_source=display_to_source)
- @classmethod
- def static(cls, text, token=Token):
- """
- Create a :class:`.BeforeInput` instance that always inserts the same
- text.
- """
- def get_static_tokens(cli):
- return [(token, text)]
- return cls(get_static_tokens)
-
- def __repr__(self):
- return '%s(get_tokens=%r)' % (
- self.__class__.__name__, self.get_tokens)
-
-
-class AfterInput(Processor):
- """
- Insert tokens after the input.
-
- :param get_tokens: Callable that takes a
- :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
- list of tokens to be appended.
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
+ @classmethod
+ def static(cls, text, token=Token):
+ """
+ Create a :class:`.BeforeInput` instance that always inserts the same
+ text.
+ """
+ def get_static_tokens(cli):
+ return [(token, text)]
+ return cls(get_static_tokens)
+
+ def __repr__(self):
+ return '%s(get_tokens=%r)' % (
+ self.__class__.__name__, self.get_tokens)
+
+
+class AfterInput(Processor):
+ """
+ Insert tokens after the input.
+
+ :param get_tokens: Callable that takes a
+ :class:`~prompt_toolkit.interface.CommandLineInterface` and returns the
+ list of tokens to be appended.
+ """
+ def __init__(self, get_tokens):
+ assert callable(get_tokens)
+ self.get_tokens = get_tokens
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
# Insert tokens after the last line.
if lineno == document.line_count - 1:
return Transformation(tokens=tokens + self.get_tokens(cli))
else:
return Transformation(tokens=tokens)
-
- @classmethod
- def static(cls, text, token=Token):
- """
- Create a :class:`.AfterInput` instance that always inserts the same
- text.
- """
- def get_static_tokens(cli):
- return [(token, text)]
- return cls(get_static_tokens)
-
- def __repr__(self):
- return '%s(get_tokens=%r)' % (
- self.__class__.__name__, self.get_tokens)
-
-
-class AppendAutoSuggestion(Processor):
- """
- Append the auto suggestion to the input.
- (The user can then press the right arrow the insert the suggestion.)
-
- :param buffer_name: The name of the buffer from where we should take the
- auto suggestion. If not given, we take the current buffer.
- """
- def __init__(self, buffer_name=None, token=Token.AutoSuggestion):
- self.buffer_name = buffer_name
- self.token = token
-
- def _get_buffer(self, cli):
- if self.buffer_name:
- return cli.buffers[self.buffer_name]
- else:
- return cli.current_buffer
-
+
+ @classmethod
+ def static(cls, text, token=Token):
+ """
+ Create a :class:`.AfterInput` instance that always inserts the same
+ text.
+ """
+ def get_static_tokens(cli):
+ return [(token, text)]
+ return cls(get_static_tokens)
+
+ def __repr__(self):
+ return '%s(get_tokens=%r)' % (
+ self.__class__.__name__, self.get_tokens)
+
+
+class AppendAutoSuggestion(Processor):
+ """
+ Append the auto suggestion to the input.
+ (The user can then press the right arrow the insert the suggestion.)
+
+ :param buffer_name: The name of the buffer from where we should take the
+ auto suggestion. If not given, we take the current buffer.
+ """
+ def __init__(self, buffer_name=None, token=Token.AutoSuggestion):
+ self.buffer_name = buffer_name
+ self.token = token
+
+ def _get_buffer(self, cli):
+ if self.buffer_name:
+ return cli.buffers[self.buffer_name]
+ else:
+ return cli.current_buffer
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
# Insert tokens after the last line.
if lineno == document.line_count - 1:
buffer = self._get_buffer(cli)
-
+
if buffer.suggestion and buffer.document.is_cursor_at_the_end:
suggestion = buffer.suggestion.text
else:
suggestion = ''
return Transformation(tokens=tokens + [(self.token, suggestion)])
- else:
+ else:
return Transformation(tokens=tokens)
-
-
-class ShowLeadingWhiteSpaceProcessor(Processor):
- """
- Make leading whitespace visible.
+
+
+class ShowLeadingWhiteSpaceProcessor(Processor):
+ """
+ Make leading whitespace visible.
:param get_char: Callable that takes a :class:`CommandLineInterface`
instance and returns one character.
:param token: Token to be used.
- """
+ """
def __init__(self, get_char=None, token=Token.LeadingWhiteSpace):
assert get_char is None or callable(get_char)
@@ -430,32 +430,32 @@ class ShowLeadingWhiteSpaceProcessor(Processor):
else:
return '\xb7'
- self.token = token
+ self.token = token
self.get_char = get_char
-
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Walk through all te tokens.
+ # Walk through all te tokens.
if tokens and token_list_to_text(tokens).startswith(' '):
t = (self.token, self.get_char(cli))
tokens = explode_tokens(tokens)
-
+
for i in range(len(tokens)):
if tokens[i][1] == ' ':
tokens[i] = t
else:
break
-
+
return Transformation(tokens)
-
-
-class ShowTrailingWhiteSpaceProcessor(Processor):
- """
- Make trailing whitespace visible.
+
+
+class ShowTrailingWhiteSpaceProcessor(Processor):
+ """
+ Make trailing whitespace visible.
:param get_char: Callable that takes a :class:`CommandLineInterface`
instance and returns one character.
:param token: Token to be used.
- """
+ """
def __init__(self, get_char=None, token=Token.TrailingWhiteSpace):
assert get_char is None or callable(get_char)
@@ -466,10 +466,10 @@ class ShowTrailingWhiteSpaceProcessor(Processor):
else:
return '\xb7'
- self.token = token
+ self.token = token
self.get_char = get_char
-
-
+
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
if tokens and tokens[-1][1].endswith(' '):
t = (self.token, self.get_char(cli))
@@ -535,16 +535,16 @@ class TabsProcessor(Processor):
result_tokens.append((token, separator1))
result_tokens.append((token, separator2 * (count - 1)))
pos += count
- else:
+ else:
result_tokens.append(token_and_text)
pos += 1
-
+
position_mappings[len(tokens)] = pos
-
+
def source_to_display(from_position):
" Maps original cursor position to the new one. "
return position_mappings[from_position]
-
+
def display_to_source(display_pos):
" Maps display cursor position to the original one. "
position_mappings_reversed = dict((v, k) for k, v in position_mappings.items())
@@ -562,44 +562,44 @@ class TabsProcessor(Processor):
display_to_source=display_to_source)
-class ConditionalProcessor(Processor):
- """
- Processor that applies another processor, according to a certain condition.
- Example::
-
- # Create a function that returns whether or not the processor should
- # currently be applied.
- def highlight_enabled(cli):
- return true_or_false
-
- # Wrapt it in a `ConditionalProcessor` for usage in a `BufferControl`.
- BufferControl(input_processors=[
- ConditionalProcessor(HighlightSearchProcessor(),
- Condition(highlight_enabled))])
-
- :param processor: :class:`.Processor` instance.
- :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
- """
- def __init__(self, processor, filter):
- assert isinstance(processor, Processor)
-
- self.processor = processor
- self.filter = to_cli_filter(filter)
-
+class ConditionalProcessor(Processor):
+ """
+ Processor that applies another processor, according to a certain condition.
+ Example::
+
+ # Create a function that returns whether or not the processor should
+ # currently be applied.
+ def highlight_enabled(cli):
+ return true_or_false
+
+ # Wrapt it in a `ConditionalProcessor` for usage in a `BufferControl`.
+ BufferControl(input_processors=[
+ ConditionalProcessor(HighlightSearchProcessor(),
+ Condition(highlight_enabled))])
+
+ :param processor: :class:`.Processor` instance.
+ :param filter: :class:`~prompt_toolkit.filters.CLIFilter` instance.
+ """
+ def __init__(self, processor, filter):
+ assert isinstance(processor, Processor)
+
+ self.processor = processor
+ self.filter = to_cli_filter(filter)
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Run processor when enabled.
- if self.filter(cli):
+ # Run processor when enabled.
+ if self.filter(cli):
return self.processor.apply_transformation(
cli, document, lineno, source_to_display, tokens)
- else:
+ else:
return Transformation(tokens)
-
- def has_focus(self, cli):
- if self.filter(cli):
- return self.processor.has_focus(cli)
- else:
- return False
-
- def __repr__(self):
- return '%s(processor=%r, filter=%r)' % (
- self.__class__.__name__, self.processor, self.filter)
+
+ def has_focus(self, cli):
+ if self.filter(cli):
+ return self.processor.has_focus(cli)
+ else:
+ return False
+
+ def __repr__(self):
+ return '%s(processor=%r, filter=%r)' % (
+ self.__class__.__name__, self.processor, self.filter)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
index d6c6a3c838..7d00ec513e 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
@@ -1,111 +1,111 @@
-from __future__ import unicode_literals
-
-from six import text_type
-
-from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER
+from __future__ import unicode_literals
+
+from six import text_type
+
+from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER
from prompt_toolkit.token import Token
-
-from .utils import token_list_len
-from .processors import Processor, Transformation
-
-__all__ = (
- 'DefaultPrompt',
-)
-
-
-class DefaultPrompt(Processor):
- """
- Default prompt. This one shows the 'arg' and reverse search like
- Bash/readline normally do.
-
- There are two ways to instantiate a ``DefaultPrompt``. For a prompt
- with a static message, do for instance::
-
- prompt = DefaultPrompt.from_message('prompt> ')
-
- For a dynamic prompt, generated from a token list function::
-
- def get_tokens(cli):
- return [(Token.A, 'text'), (Token.B, 'text2')]
-
- prompt = DefaultPrompt(get_tokens)
- """
- def __init__(self, get_tokens):
- assert callable(get_tokens)
- self.get_tokens = get_tokens
-
- @classmethod
- def from_message(cls, message='> '):
- """
- Create a default prompt with a static message text.
- """
- assert isinstance(message, text_type)
-
- def get_message_tokens(cli):
- return [(Token.Prompt, message)]
- return cls(get_message_tokens)
-
+
+from .utils import token_list_len
+from .processors import Processor, Transformation
+
+__all__ = (
+ 'DefaultPrompt',
+)
+
+
+class DefaultPrompt(Processor):
+ """
+ Default prompt. This one shows the 'arg' and reverse search like
+ Bash/readline normally do.
+
+ There are two ways to instantiate a ``DefaultPrompt``. For a prompt
+ with a static message, do for instance::
+
+ prompt = DefaultPrompt.from_message('prompt> ')
+
+ For a dynamic prompt, generated from a token list function::
+
+ def get_tokens(cli):
+ return [(Token.A, 'text'), (Token.B, 'text2')]
+
+ prompt = DefaultPrompt(get_tokens)
+ """
+ def __init__(self, get_tokens):
+ assert callable(get_tokens)
+ self.get_tokens = get_tokens
+
+ @classmethod
+ def from_message(cls, message='> '):
+ """
+ Create a default prompt with a static message text.
+ """
+ assert isinstance(message, text_type)
+
+ def get_message_tokens(cli):
+ return [(Token.Prompt, message)]
+ return cls(get_message_tokens)
+
def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- # Get text before cursor.
- if cli.is_searching:
- before = _get_isearch_tokens(cli)
-
- elif cli.input_processor.arg is not None:
- before = _get_arg_tokens(cli)
-
- else:
- before = self.get_tokens(cli)
-
- # Insert before buffer text.
- shift_position = token_list_len(before)
-
+ # Get text before cursor.
+ if cli.is_searching:
+ before = _get_isearch_tokens(cli)
+
+ elif cli.input_processor.arg is not None:
+ before = _get_arg_tokens(cli)
+
+ else:
+ before = self.get_tokens(cli)
+
+ # Insert before buffer text.
+ shift_position = token_list_len(before)
+
# Only show the prompt before the first line. For the following lines,
# only indent using spaces.
if lineno != 0:
before = [(Token.Prompt, ' ' * shift_position)]
- return Transformation(
- tokens=before + tokens,
- source_to_display=lambda i: i + shift_position,
- display_to_source=lambda i: i - shift_position)
-
- def has_focus(self, cli):
- # Obtain focus when the CLI is searching.
-
- # Usually, when using this `DefaultPrompt`, we don't have a
- # `BufferControl` instance that displays the content of the search
- # buffer. Instead the search text is displayed before the current text.
- # So, we can still show the cursor here, while it's actually not this
- # buffer that's focussed.
- return cli.is_searching
-
-
-def _get_isearch_tokens(cli):
- def before():
- if cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
- text = 'reverse-i-search'
- else:
- text = 'i-search'
-
- return [(Token.Prompt.Search, '(%s)`' % text)]
-
- def text():
- return [(Token.Prompt.Search.Text, cli.buffers[SEARCH_BUFFER].text)]
-
- def after():
- return [(Token.Prompt.Search, '`: ')]
-
- return before() + text() + after()
-
-
-def _get_arg_tokens(cli):
- """
- Tokens for the arg-prompt.
- """
- arg = cli.input_processor.arg
-
- return [
- (Token.Prompt.Arg, '(arg: '),
- (Token.Prompt.Arg.Text, str(arg)),
- (Token.Prompt.Arg, ') '),
- ]
+ return Transformation(
+ tokens=before + tokens,
+ source_to_display=lambda i: i + shift_position,
+ display_to_source=lambda i: i - shift_position)
+
+ def has_focus(self, cli):
+ # Obtain focus when the CLI is searching.
+
+ # Usually, when using this `DefaultPrompt`, we don't have a
+ # `BufferControl` instance that displays the content of the search
+ # buffer. Instead the search text is displayed before the current text.
+ # So, we can still show the cursor here, while it's actually not this
+ # buffer that's focussed.
+ return cli.is_searching
+
+
+def _get_isearch_tokens(cli):
+ def before():
+ if cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
+ text = 'reverse-i-search'
+ else:
+ text = 'i-search'
+
+ return [(Token.Prompt.Search, '(%s)`' % text)]
+
+ def text():
+ return [(Token.Prompt.Search.Text, cli.buffers[SEARCH_BUFFER].text)]
+
+ def after():
+ return [(Token.Prompt.Search, '`: ')]
+
+ return before() + text() + after()
+
+
+def _get_arg_tokens(cli):
+ """
+ Tokens for the arg-prompt.
+ """
+ arg = cli.input_processor.arg
+
+ return [
+ (Token.Prompt.Arg, '(arg: '),
+ (Token.Prompt.Arg.Text, str(arg)),
+ (Token.Prompt.Arg, ') '),
+ ]
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
index 8926f66d9b..95561f5de7 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
@@ -1,151 +1,151 @@
-from __future__ import unicode_literals
-
+from __future__ import unicode_literals
+
from prompt_toolkit.cache import FastDictCache
from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-
-from collections import defaultdict, namedtuple
-
-__all__ = (
- 'Point',
- 'Size',
- 'Screen',
- 'Char',
-)
-
-
-Point = namedtuple('Point', 'y x')
-Size = namedtuple('Size', 'rows columns')
-
-
-class Char(object):
- """
- Represent a single character in a :class:`.Screen`.
-
- This should be considered immutable.
- """
- __slots__ = ('char', 'token', 'width')
-
- # If we end up having one of these special control sequences in the input string,
- # we should display them as follows:
- # Usually this happens after a "quoted insert".
- display_mappings = {
- '\x00': '^@', # Control space
- '\x01': '^A',
- '\x02': '^B',
- '\x03': '^C',
- '\x04': '^D',
- '\x05': '^E',
- '\x06': '^F',
- '\x07': '^G',
- '\x08': '^H',
- '\x09': '^I',
- '\x0a': '^J',
- '\x0b': '^K',
- '\x0c': '^L',
- '\x0d': '^M',
- '\x0e': '^N',
- '\x0f': '^O',
- '\x10': '^P',
- '\x11': '^Q',
- '\x12': '^R',
- '\x13': '^S',
- '\x14': '^T',
- '\x15': '^U',
- '\x16': '^V',
- '\x17': '^W',
- '\x18': '^X',
- '\x19': '^Y',
- '\x1a': '^Z',
- '\x1b': '^[', # Escape
- '\x1c': '^\\',
- '\x1d': '^]',
- '\x1f': '^_',
+from prompt_toolkit.utils import get_cwidth
+
+from collections import defaultdict, namedtuple
+
+__all__ = (
+ 'Point',
+ 'Size',
+ 'Screen',
+ 'Char',
+)
+
+
+Point = namedtuple('Point', 'y x')
+Size = namedtuple('Size', 'rows columns')
+
+
+class Char(object):
+ """
+ Represent a single character in a :class:`.Screen`.
+
+ This should be considered immutable.
+ """
+ __slots__ = ('char', 'token', 'width')
+
+ # If we end up having one of these special control sequences in the input string,
+ # we should display them as follows:
+ # Usually this happens after a "quoted insert".
+ display_mappings = {
+ '\x00': '^@', # Control space
+ '\x01': '^A',
+ '\x02': '^B',
+ '\x03': '^C',
+ '\x04': '^D',
+ '\x05': '^E',
+ '\x06': '^F',
+ '\x07': '^G',
+ '\x08': '^H',
+ '\x09': '^I',
+ '\x0a': '^J',
+ '\x0b': '^K',
+ '\x0c': '^L',
+ '\x0d': '^M',
+ '\x0e': '^N',
+ '\x0f': '^O',
+ '\x10': '^P',
+ '\x11': '^Q',
+ '\x12': '^R',
+ '\x13': '^S',
+ '\x14': '^T',
+ '\x15': '^U',
+ '\x16': '^V',
+ '\x17': '^W',
+ '\x18': '^X',
+ '\x19': '^Y',
+ '\x1a': '^Z',
+ '\x1b': '^[', # Escape
+ '\x1c': '^\\',
+ '\x1d': '^]',
+ '\x1f': '^_',
'\x7f': '^?', # Backspace
- }
-
- def __init__(self, char=' ', token=Token):
- # If this character has to be displayed otherwise, take that one.
- char = self.display_mappings.get(char, char)
-
- self.char = char
- self.token = token
-
- # Calculate width. (We always need this, so better to store it directly
- # as a member for performance.)
- self.width = get_cwidth(char)
-
- def __eq__(self, other):
- return self.char == other.char and self.token == other.token
-
- def __ne__(self, other):
- # Not equal: We don't do `not char.__eq__` here, because of the
- # performance of calling yet another function.
- return self.char != other.char or self.token != other.token
-
- def __repr__(self):
- return '%s(%r, %r)' % (self.__class__.__name__, self.char, self.token)
-
-
+ }
+
+ def __init__(self, char=' ', token=Token):
+ # If this character has to be displayed otherwise, take that one.
+ char = self.display_mappings.get(char, char)
+
+ self.char = char
+ self.token = token
+
+ # Calculate width. (We always need this, so better to store it directly
+ # as a member for performance.)
+ self.width = get_cwidth(char)
+
+ def __eq__(self, other):
+ return self.char == other.char and self.token == other.token
+
+ def __ne__(self, other):
+ # Not equal: We don't do `not char.__eq__` here, because of the
+ # performance of calling yet another function.
+ return self.char != other.char or self.token != other.token
+
+ def __repr__(self):
+ return '%s(%r, %r)' % (self.__class__.__name__, self.char, self.token)
+
+
_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000)
-Transparent = Token.Transparent
-
-
-class Screen(object):
- """
- Two dimentional buffer of :class:`.Char` instances.
- """
- def __init__(self, default_char=None, initial_width=0, initial_height=0):
- if default_char is None:
+Transparent = Token.Transparent
+
+
+class Screen(object):
+ """
+ Two dimentional buffer of :class:`.Char` instances.
+ """
+ def __init__(self, default_char=None, initial_width=0, initial_height=0):
+ if default_char is None:
default_char = _CHAR_CACHE[' ', Transparent]
-
- self.data_buffer = defaultdict(lambda: defaultdict(lambda: default_char))
-
+
+ self.data_buffer = defaultdict(lambda: defaultdict(lambda: default_char))
+
#: Escape sequences to be injected.
self.zero_width_escapes = defaultdict(lambda: defaultdict(lambda: ''))
- #: Position of the cursor.
- self.cursor_position = Point(y=0, x=0)
-
- #: Visibility of the cursor.
- self.show_cursor = True
-
- #: (Optional) Where to position the menu. E.g. at the start of a completion.
- #: (We can't use the cursor position, because we don't want the
- #: completion menu to change its position when we browse through all the
- #: completions.)
- self.menu_position = None
-
- #: Currently used width/height of the screen. This will increase when
- #: data is written to the screen.
- self.width = initial_width or 0
- self.height = initial_height or 0
-
- def replace_all_tokens(self, token):
- """
- For all the characters in the screen. Set the token to the given `token`.
- """
- b = self.data_buffer
-
- for y, row in b.items():
- for x, char in row.items():
- b[y][x] = _CHAR_CACHE[char.char, token]
-
-
-class WritePosition(object):
- def __init__(self, xpos, ypos, width, height, extended_height=None):
- assert height >= 0
- assert extended_height is None or extended_height >= 0
- assert width >= 0
- # xpos and ypos can be negative. (A float can be partially visible.)
-
- self.xpos = xpos
- self.ypos = ypos
- self.width = width
- self.height = height
- self.extended_height = extended_height or height
-
- def __repr__(self):
- return '%s(%r, %r, %r, %r, %r)' % (
- self.__class__.__name__,
- self.xpos, self.ypos, self.width, self.height, self.extended_height)
+ #: Position of the cursor.
+ self.cursor_position = Point(y=0, x=0)
+
+ #: Visibility of the cursor.
+ self.show_cursor = True
+
+ #: (Optional) Where to position the menu. E.g. at the start of a completion.
+ #: (We can't use the cursor position, because we don't want the
+ #: completion menu to change its position when we browse through all the
+ #: completions.)
+ self.menu_position = None
+
+ #: Currently used width/height of the screen. This will increase when
+ #: data is written to the screen.
+ self.width = initial_width or 0
+ self.height = initial_height or 0
+
+ def replace_all_tokens(self, token):
+ """
+ For all the characters in the screen. Set the token to the given `token`.
+ """
+ b = self.data_buffer
+
+ for y, row in b.items():
+ for x, char in row.items():
+ b[y][x] = _CHAR_CACHE[char.char, token]
+
+
+class WritePosition(object):
+ def __init__(self, xpos, ypos, width, height, extended_height=None):
+ assert height >= 0
+ assert extended_height is None or extended_height >= 0
+ assert width >= 0
+ # xpos and ypos can be negative. (A float can be partially visible.)
+
+ self.xpos = xpos
+ self.ypos = ypos
+ self.width = width
+ self.height = height
+ self.extended_height = extended_height or height
+
+ def __repr__(self):
+ return '%s(%r, %r, %r, %r, %r)' % (
+ self.__class__.__name__,
+ self.xpos, self.ypos, self.width, self.height, self.extended_height)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
index aafa2e6245..2e77c2fa16 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
@@ -1,209 +1,209 @@
-from __future__ import unicode_literals
-
-from ..enums import IncrementalSearchDirection
-
-from .processors import BeforeInput
-
+from __future__ import unicode_literals
+
+from ..enums import IncrementalSearchDirection
+
+from .processors import BeforeInput
+
from .lexers import SimpleLexer
-from .dimension import LayoutDimension
+from .dimension import LayoutDimension
from .controls import BufferControl, TokenListControl, UIControl, UIContent
-from .containers import Window, ConditionalContainer
+from .containers import Window, ConditionalContainer
from .screen import Char
-from .utils import token_list_len
+from .utils import token_list_len
from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER
-from prompt_toolkit.filters import HasFocus, HasArg, HasCompletions, HasValidationError, HasSearch, Always, IsDone
+from prompt_toolkit.filters import HasFocus, HasArg, HasCompletions, HasValidationError, HasSearch, Always, IsDone
from prompt_toolkit.token import Token
-
-__all__ = (
- 'TokenListToolbar',
- 'ArgToolbar',
- 'CompletionsToolbar',
- 'SearchToolbar',
- 'SystemToolbar',
- 'ValidationToolbar',
-)
-
-
-class TokenListToolbar(ConditionalContainer):
- def __init__(self, get_tokens, filter=Always(), **kw):
- super(TokenListToolbar, self).__init__(
- content=Window(
- TokenListControl(get_tokens, **kw),
- height=LayoutDimension.exact(1)),
- filter=filter)
-
-
-class SystemToolbarControl(BufferControl):
- def __init__(self):
+
+__all__ = (
+ 'TokenListToolbar',
+ 'ArgToolbar',
+ 'CompletionsToolbar',
+ 'SearchToolbar',
+ 'SystemToolbar',
+ 'ValidationToolbar',
+)
+
+
+class TokenListToolbar(ConditionalContainer):
+ def __init__(self, get_tokens, filter=Always(), **kw):
+ super(TokenListToolbar, self).__init__(
+ content=Window(
+ TokenListControl(get_tokens, **kw),
+ height=LayoutDimension.exact(1)),
+ filter=filter)
+
+
+class SystemToolbarControl(BufferControl):
+ def __init__(self):
token = Token.Toolbar.System
- super(SystemToolbarControl, self).__init__(
- buffer_name=SYSTEM_BUFFER,
+ super(SystemToolbarControl, self).__init__(
+ buffer_name=SYSTEM_BUFFER,
default_char=Char(token=token),
lexer=SimpleLexer(token=token.Text),
input_processors=[BeforeInput.static('Shell command: ', token)],)
-
-
-class SystemToolbar(ConditionalContainer):
- def __init__(self):
- super(SystemToolbar, self).__init__(
- content=Window(
- SystemToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasFocus(SYSTEM_BUFFER) & ~IsDone())
-
-
-class ArgToolbarControl(TokenListControl):
- def __init__(self):
- def get_tokens(cli):
+
+
+class SystemToolbar(ConditionalContainer):
+ def __init__(self):
+ super(SystemToolbar, self).__init__(
+ content=Window(
+ SystemToolbarControl(),
+ height=LayoutDimension.exact(1)),
+ filter=HasFocus(SYSTEM_BUFFER) & ~IsDone())
+
+
+class ArgToolbarControl(TokenListControl):
+ def __init__(self):
+ def get_tokens(cli):
arg = cli.input_processor.arg
if arg == '-':
arg = '-1'
- return [
- (Token.Toolbar.Arg, 'Repeat: '),
+ return [
+ (Token.Toolbar.Arg, 'Repeat: '),
(Token.Toolbar.Arg.Text, arg),
- ]
-
- super(ArgToolbarControl, self).__init__(get_tokens)
-
-
-class ArgToolbar(ConditionalContainer):
- def __init__(self):
- super(ArgToolbar, self).__init__(
- content=Window(
- ArgToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasArg())
-
-
-class SearchToolbarControl(BufferControl):
- """
- :param vi_mode: Display '/' and '?' instead of I-search.
- """
- def __init__(self, vi_mode=False):
- token = Token.Toolbar.Search
-
- def get_before_input(cli):
- if not cli.is_searching:
- text = ''
- elif cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
- text = ('?' if vi_mode else 'I-search backward: ')
- else:
- text = ('/' if vi_mode else 'I-search: ')
-
- return [(token, text)]
-
- super(SearchToolbarControl, self).__init__(
- buffer_name=SEARCH_BUFFER,
- input_processors=[BeforeInput(get_before_input)],
+ ]
+
+ super(ArgToolbarControl, self).__init__(get_tokens)
+
+
+class ArgToolbar(ConditionalContainer):
+ def __init__(self):
+ super(ArgToolbar, self).__init__(
+ content=Window(
+ ArgToolbarControl(),
+ height=LayoutDimension.exact(1)),
+ filter=HasArg())
+
+
+class SearchToolbarControl(BufferControl):
+ """
+ :param vi_mode: Display '/' and '?' instead of I-search.
+ """
+ def __init__(self, vi_mode=False):
+ token = Token.Toolbar.Search
+
+ def get_before_input(cli):
+ if not cli.is_searching:
+ text = ''
+ elif cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
+ text = ('?' if vi_mode else 'I-search backward: ')
+ else:
+ text = ('/' if vi_mode else 'I-search: ')
+
+ return [(token, text)]
+
+ super(SearchToolbarControl, self).__init__(
+ buffer_name=SEARCH_BUFFER,
+ input_processors=[BeforeInput(get_before_input)],
default_char=Char(token=token),
lexer=SimpleLexer(token=token.Text))
-
-
-class SearchToolbar(ConditionalContainer):
- def __init__(self, vi_mode=False):
- super(SearchToolbar, self).__init__(
- content=Window(
- SearchToolbarControl(vi_mode=vi_mode),
- height=LayoutDimension.exact(1)),
- filter=HasSearch() & ~IsDone())
-
-
-class CompletionsToolbarControl(UIControl):
- token = Token.Toolbar.Completions
-
+
+
+class SearchToolbar(ConditionalContainer):
+ def __init__(self, vi_mode=False):
+ super(SearchToolbar, self).__init__(
+ content=Window(
+ SearchToolbarControl(vi_mode=vi_mode),
+ height=LayoutDimension.exact(1)),
+ filter=HasSearch() & ~IsDone())
+
+
+class CompletionsToolbarControl(UIControl):
+ token = Token.Toolbar.Completions
+
def create_content(self, cli, width, height):
- complete_state = cli.current_buffer.complete_state
- if complete_state:
- completions = complete_state.current_completions
- index = complete_state.complete_index # Can be None!
-
- # Width of the completions without the left/right arrows in the margins.
- content_width = width - 6
-
- # Booleans indicating whether we stripped from the left/right
- cut_left = False
- cut_right = False
-
- # Create Menu content.
- tokens = []
-
- for i, c in enumerate(completions):
- # When there is no more place for the next completion
- if token_list_len(tokens) + len(c.display) >= content_width:
- # If the current one was not yet displayed, page to the next sequence.
- if i <= (index or 0):
- tokens = []
- cut_left = True
- # If the current one is visible, stop here.
- else:
- cut_right = True
- break
-
- tokens.append((self.token.Completion.Current if i == index else self.token.Completion, c.display))
- tokens.append((self.token, ' '))
-
- # Extend/strip until the content width.
- tokens.append((self.token, ' ' * (content_width - token_list_len(tokens))))
- tokens = tokens[:content_width]
-
- # Return tokens
- all_tokens = [
- (self.token, ' '),
- (self.token.Arrow, '<' if cut_left else ' '),
- (self.token, ' '),
- ] + tokens + [
- (self.token, ' '),
- (self.token.Arrow, '>' if cut_right else ' '),
- (self.token, ' '),
- ]
- else:
- all_tokens = []
-
+ complete_state = cli.current_buffer.complete_state
+ if complete_state:
+ completions = complete_state.current_completions
+ index = complete_state.complete_index # Can be None!
+
+ # Width of the completions without the left/right arrows in the margins.
+ content_width = width - 6
+
+ # Booleans indicating whether we stripped from the left/right
+ cut_left = False
+ cut_right = False
+
+ # Create Menu content.
+ tokens = []
+
+ for i, c in enumerate(completions):
+ # When there is no more place for the next completion
+ if token_list_len(tokens) + len(c.display) >= content_width:
+ # If the current one was not yet displayed, page to the next sequence.
+ if i <= (index or 0):
+ tokens = []
+ cut_left = True
+ # If the current one is visible, stop here.
+ else:
+ cut_right = True
+ break
+
+ tokens.append((self.token.Completion.Current if i == index else self.token.Completion, c.display))
+ tokens.append((self.token, ' '))
+
+ # Extend/strip until the content width.
+ tokens.append((self.token, ' ' * (content_width - token_list_len(tokens))))
+ tokens = tokens[:content_width]
+
+ # Return tokens
+ all_tokens = [
+ (self.token, ' '),
+ (self.token.Arrow, '<' if cut_left else ' '),
+ (self.token, ' '),
+ ] + tokens + [
+ (self.token, ' '),
+ (self.token.Arrow, '>' if cut_right else ' '),
+ (self.token, ' '),
+ ]
+ else:
+ all_tokens = []
+
def get_line(i):
return all_tokens
-
+
return UIContent(get_line=get_line, line_count=1)
-
-
-class CompletionsToolbar(ConditionalContainer):
- def __init__(self, extra_filter=Always()):
- super(CompletionsToolbar, self).__init__(
- content=Window(
- CompletionsToolbarControl(),
- height=LayoutDimension.exact(1)),
- filter=HasCompletions() & ~IsDone() & extra_filter)
-
-
-class ValidationToolbarControl(TokenListControl):
- def __init__(self, show_position=False):
- token = Token.Toolbar.Validation
-
- def get_tokens(cli):
- buffer = cli.current_buffer
-
- if buffer.validation_error:
- row, column = buffer.document.translate_index_to_position(
- buffer.validation_error.cursor_position)
-
- if show_position:
- text = '%s (line=%s column=%s)' % (
- buffer.validation_error.message, row + 1, column + 1)
- else:
- text = buffer.validation_error.message
-
- return [(token, text)]
- else:
- return []
-
- super(ValidationToolbarControl, self).__init__(get_tokens)
-
-
-class ValidationToolbar(ConditionalContainer):
- def __init__(self, show_position=False):
- super(ValidationToolbar, self).__init__(
- content=Window(
- ValidationToolbarControl(show_position=show_position),
- height=LayoutDimension.exact(1)),
- filter=HasValidationError() & ~IsDone())
+
+
+class CompletionsToolbar(ConditionalContainer):
+ def __init__(self, extra_filter=Always()):
+ super(CompletionsToolbar, self).__init__(
+ content=Window(
+ CompletionsToolbarControl(),
+ height=LayoutDimension.exact(1)),
+ filter=HasCompletions() & ~IsDone() & extra_filter)
+
+
+class ValidationToolbarControl(TokenListControl):
+ def __init__(self, show_position=False):
+ token = Token.Toolbar.Validation
+
+ def get_tokens(cli):
+ buffer = cli.current_buffer
+
+ if buffer.validation_error:
+ row, column = buffer.document.translate_index_to_position(
+ buffer.validation_error.cursor_position)
+
+ if show_position:
+ text = '%s (line=%s column=%s)' % (
+ buffer.validation_error.message, row + 1, column + 1)
+ else:
+ text = buffer.validation_error.message
+
+ return [(token, text)]
+ else:
+ return []
+
+ super(ValidationToolbarControl, self).__init__(get_tokens)
+
+
+class ValidationToolbar(ConditionalContainer):
+ def __init__(self, show_position=False):
+ super(ValidationToolbar, self).__init__(
+ content=Window(
+ ValidationToolbarControl(show_position=show_position),
+ height=LayoutDimension.exact(1)),
+ filter=HasValidationError() & ~IsDone())
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
index 5fdfe4eb43..a4fb7ed0f5 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
@@ -1,112 +1,112 @@
-from __future__ import unicode_literals
-
-from prompt_toolkit.utils import get_cwidth
+from __future__ import unicode_literals
+
+from prompt_toolkit.utils import get_cwidth
from prompt_toolkit.token import Token
-
-__all__ = (
- 'token_list_len',
- 'token_list_width',
- 'token_list_to_text',
- 'explode_tokens',
+
+__all__ = (
+ 'token_list_len',
+ 'token_list_width',
+ 'token_list_to_text',
+ 'explode_tokens',
'split_lines',
- 'find_window_for_buffer_name',
-)
-
-
-def token_list_len(tokenlist):
- """
- Return the amount of characters in this token list.
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
+ 'find_window_for_buffer_name',
+)
+
+
+def token_list_len(tokenlist):
+ """
+ Return the amount of characters in this token list.
+
+ :param tokenlist: List of (token, text) or (token, text, mouse_handler)
+ tuples.
+ """
ZeroWidthEscape = Token.ZeroWidthEscape
return sum(len(item[1]) for item in tokenlist if item[0] != ZeroWidthEscape)
-
-
-def token_list_width(tokenlist):
- """
- Return the character width of this token list.
- (Take double width characters into account.)
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
+
+
+def token_list_width(tokenlist):
+ """
+ Return the character width of this token list.
+ (Take double width characters into account.)
+
+ :param tokenlist: List of (token, text) or (token, text, mouse_handler)
+ tuples.
+ """
ZeroWidthEscape = Token.ZeroWidthEscape
return sum(get_cwidth(c) for item in tokenlist for c in item[1] if item[0] != ZeroWidthEscape)
-
-
-def token_list_to_text(tokenlist):
- """
- Concatenate all the text parts again.
- """
+
+
+def token_list_to_text(tokenlist):
+ """
+ Concatenate all the text parts again.
+ """
ZeroWidthEscape = Token.ZeroWidthEscape
return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape)
-
-
-def iter_token_lines(tokenlist):
- """
- Iterator that yields tokenlists for each line.
- """
- line = []
- for token, c in explode_tokens(tokenlist):
- line.append((token, c))
-
- if c == '\n':
- yield line
- line = []
-
- yield line
-
-
-def split_lines(tokenlist):
- """
- Take a single list of (Token, text) tuples and yield one such list for each
+
+
+def iter_token_lines(tokenlist):
+ """
+ Iterator that yields tokenlists for each line.
+ """
+ line = []
+ for token, c in explode_tokens(tokenlist):
+ line.append((token, c))
+
+ if c == '\n':
+ yield line
+ line = []
+
+ yield line
+
+
+def split_lines(tokenlist):
+ """
+ Take a single list of (Token, text) tuples and yield one such list for each
line. Just like str.split, this will yield at least one item.
-
- :param tokenlist: List of (token, text) or (token, text, mouse_handler)
- tuples.
- """
- line = []
-
- for item in tokenlist:
- # For (token, text) tuples.
- if len(item) == 2:
- token, string = item
- parts = string.split('\n')
-
- for part in parts[:-1]:
- if part:
- line.append((token, part))
- yield line
- line = []
-
- line.append((token, parts[-1]))
+
+ :param tokenlist: List of (token, text) or (token, text, mouse_handler)
+ tuples.
+ """
+ line = []
+
+ for item in tokenlist:
+ # For (token, text) tuples.
+ if len(item) == 2:
+ token, string = item
+ parts = string.split('\n')
+
+ for part in parts[:-1]:
+ if part:
+ line.append((token, part))
+ yield line
+ line = []
+
+ line.append((token, parts[-1]))
# Note that parts[-1] can be empty, and that's fine. It happens
# in the case of [(Token.SetCursorPosition, '')].
-
- # For (token, text, mouse_handler) tuples.
- # I know, partly copy/paste, but understandable and more efficient
- # than many tests.
- else:
- token, string, mouse_handler = item
- parts = string.split('\n')
-
- for part in parts[:-1]:
- if part:
- line.append((token, part, mouse_handler))
- yield line
- line = []
-
- line.append((token, parts[-1], mouse_handler))
-
+
+ # For (token, text, mouse_handler) tuples.
+ # I know, partly copy/paste, but understandable and more efficient
+ # than many tests.
+ else:
+ token, string, mouse_handler = item
+ parts = string.split('\n')
+
+ for part in parts[:-1]:
+ if part:
+ line.append((token, part, mouse_handler))
+ yield line
+ line = []
+
+ line.append((token, parts[-1], mouse_handler))
+
# Always yield the last line, even when this is an empty line. This ensures
# that when `tokenlist` ends with a newline character, an additional empty
# line is yielded. (Otherwise, there's no way to differentiate between the
# cases where `tokenlist` does and doesn't end with a newline.)
yield line
-
-
+
+
class _ExplodedList(list):
"""
Wrapper around a list, that marks it as 'exploded'.
@@ -140,42 +140,42 @@ class _ExplodedList(list):
super(_ExplodedList, self).__setitem__(index, value)
-def explode_tokens(tokenlist):
- """
- Turn a list of (token, text) tuples into another list where each string is
- exactly one character.
-
+def explode_tokens(tokenlist):
+ """
+ Turn a list of (token, text) tuples into another list where each string is
+ exactly one character.
+
It should be fine to call this function several times. Calling this on a
list that is already exploded, is a null operation.
- :param tokenlist: List of (token, text) tuples.
- """
+ :param tokenlist: List of (token, text) tuples.
+ """
# When the tokenlist is already exploded, don't explode again.
if getattr(tokenlist, 'exploded', False):
return tokenlist
- result = []
-
- for token, string in tokenlist:
- for c in string:
- result.append((token, c))
-
+ result = []
+
+ for token, string in tokenlist:
+ for c in string:
+ result.append((token, c))
+
return _ExplodedList(result)
-
-
-def find_window_for_buffer_name(cli, buffer_name):
- """
- Look for a :class:`~prompt_toolkit.layout.containers.Window` in the Layout
- that contains the :class:`~prompt_toolkit.layout.controls.BufferControl`
- for the given buffer and return it. If no such Window is found, return None.
- """
- from prompt_toolkit.interface import CommandLineInterface
- assert isinstance(cli, CommandLineInterface)
-
- from .containers import Window
- from .controls import BufferControl
-
- for l in cli.layout.walk(cli):
- if isinstance(l, Window) and isinstance(l.content, BufferControl):
- if l.content.buffer_name == buffer_name:
- return l
+
+
+def find_window_for_buffer_name(cli, buffer_name):
+ """
+ Look for a :class:`~prompt_toolkit.layout.containers.Window` in the Layout
+ that contains the :class:`~prompt_toolkit.layout.controls.BufferControl`
+ for the given buffer and return it. If no such Window is found, return None.
+ """
+ from prompt_toolkit.interface import CommandLineInterface
+ assert isinstance(cli, CommandLineInterface)
+
+ from .containers import Window
+ from .controls import BufferControl
+
+ for l in cli.layout.walk(cli):
+ if isinstance(l, Window) and isinstance(l.content, BufferControl):
+ if l.content.buffer_name == buffer_name:
+ return l