aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout
diff options
context:
space:
mode:
authorNikita Slyusarev <nslus@yandex-team.com>2022-02-10 16:46:52 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:52 +0300
commitcd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch)
tree1308e0bae862d52e0020d881fe758080437fe389 /contrib/python/prompt-toolkit/py2/prompt_toolkit/layout
parentcdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff)
downloadydb-cd77cecfc03a3eaf87816af28a33067c4f0cdb59.tar.gz
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 1 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__.py2
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py1412
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py726
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py542
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py276
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py144
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py676
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py14
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py18
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py44
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py118
11 files changed, 1986 insertions, 1986 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 0dec5ecfaf..25590d8a2e 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/__init__.py
@@ -8,7 +8,7 @@ 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
+ 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.
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 0bdafe18e0..2901461e88 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/containers.py
@@ -6,19 +6,19 @@ from __future__ import unicode_literals
from abc import ABCMeta, abstractmethod
from six import with_metaclass
-from six.moves import range
+from six.moves import range
-from .controls import UIControl, TokenListControl, UIContent
+from .controls import UIControl, TokenListControl, UIContent
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
-from prompt_toolkit.filters import to_cli_filter, ViInsertMode, EmacsInsertMode
-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
+from .screen import Point, WritePosition, _CHAR_CACHE
+from .utils import token_list_to_text, explode_tokens
+from prompt_toolkit.cache import SimpleCache
+from prompt_toolkit.filters import to_cli_filter, ViInsertMode, EmacsInsertMode
+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',
@@ -29,8 +29,8 @@ __all__ = (
'Window',
'WindowRenderInfo',
'ConditionalContainer',
- 'ScrollOffsets',
- 'ColorColumn',
+ 'ScrollOffsets',
+ 'ColorColumn',
)
Transparent = Token.Transparent
@@ -57,7 +57,7 @@ class Container(with_metaclass(ABCMeta, object)):
"""
@abstractmethod
- def preferred_height(self, cli, width, max_available_height):
+ 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.
@@ -124,8 +124,8 @@ class HSplit(Container):
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]
+ 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):
@@ -172,7 +172,7 @@ class HSplit(Container):
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)
+ 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)]
@@ -250,12 +250,12 @@ class VSplit(Container):
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):
+ def preferred_height(self, cli, width, max_available_height):
sizes = self._divide_widths(cli, width)
if sizes is None:
return LayoutDimension()
else:
- dimensions = [c.preferred_height(cli, s, max_available_height)
+ dimensions = [c.preferred_height(cli, s, max_available_height)
for s, c in zip(sizes, self.children)]
return max_layout_dimensions(dimensions)
@@ -336,7 +336,7 @@ class VSplit(Container):
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
+ 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)))
@@ -386,13 +386,13 @@ class FloatContainer(Container):
def preferred_width(self, cli, write_position):
return self.content.preferred_width(cli, write_position)
- def preferred_height(self, cli, width, max_available_height):
+ 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 self.content.preferred_height(cli, width, max_available_height)
+ 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)
@@ -467,8 +467,8 @@ class FloatContainer(Container):
height = fl_height
if height is None:
- height = fl.content.preferred_height(
- cli, width, write_position.extended_height).preferred
+ 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.)
@@ -488,8 +488,8 @@ class FloatContainer(Container):
height = fl_height
# Otherwise, take preferred height from content.
else:
- height = fl.content.preferred_height(
- cli, width, write_position.extended_height).preferred
+ height = fl.content.preferred_height(
+ cli, width, write_position.extended_height).preferred
if fl.top is not None:
ypos = fl.top
@@ -508,28 +508,28 @@ class FloatContainer(Container):
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)
-
- def _area_is_empty(self, screen, write_position):
- """
- Return True when the area below the write position is still empty.
- (For floats that should not hide content underneath.)
- """
- wp = write_position
- Transparent = Token.Transparent
-
- for y in range(wp.ypos, wp.ypos + wp.height):
- if y in screen.data_buffer:
- row = screen.data_buffer[y]
-
- for x in range(wp.xpos, wp.xpos + wp.width):
- c = row[x]
- if c.char != ' ' or c.token != Transparent:
- return False
-
- return True
-
+ if not fl.hide_when_covering_content or self._area_is_empty(screen, wp):
+ fl.content.write_to_screen(cli, screen, mouse_handlers, wp)
+
+ def _area_is_empty(self, screen, write_position):
+ """
+ Return True when the area below the write position is still empty.
+ (For floats that should not hide content underneath.)
+ """
+ wp = write_position
+ Transparent = Token.Transparent
+
+ for y in range(wp.ypos, wp.ypos + wp.height):
+ if y in screen.data_buffer:
+ row = screen.data_buffer[y]
+
+ for x in range(wp.xpos, wp.xpos + wp.width):
+ c = row[x]
+ if c.char != ' ' or c.token != Transparent:
+ return False
+
+ return True
+
def walk(self, cli):
""" Walk through children. """
yield self
@@ -547,12 +547,12 @@ 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.
+ :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,
- xcursor=False, ycursor=False, content=None,
- hide_when_covering_content=False):
+ 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
@@ -572,7 +572,7 @@ class Float(object):
self.ycursor = ycursor
self.content = content
- self.hide_when_covering_content = hide_when_covering_content
+ self.hide_when_covering_content = hide_when_covering_content
def get_width(self, cli):
if self._width:
@@ -600,135 +600,135 @@ class WindowRenderInfo(object):
(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 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 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.
- :param configured_scroll_offsets: The scroll offsets as configured for the
- :class:`Window` instance.
- :param visible_line_to_row_col: Mapping that maps the row numbers on the
- displayed screen (starting from zero for the first visible line) to
- (row, col) tuples pointing to the row and column of the :class:`.UIContent`.
- :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.
+ :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.
+ :param configured_scroll_offsets: The scroll offsets as configured for the
+ :class:`Window` instance.
+ :param visible_line_to_row_col: Mapping that maps the row numbers on the
+ displayed screen (starting from zero for the first visible line) to
+ (row, col) tuples pointing to the row and column of the :class:`.UIContent`.
+ :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,
- visible_line_to_row_col, rowcol_to_yx,
- x_offset, y_offset, wrap_lines):
- assert isinstance(ui_content, UIContent)
- assert isinstance(horizontal_scroll, int)
- assert isinstance(vertical_scroll, int)
- assert isinstance(window_width, int)
- assert isinstance(window_height, int)
- assert isinstance(configured_scroll_offsets, ScrollOffsets)
- assert isinstance(visible_line_to_row_col, dict)
- assert isinstance(rowcol_to_yx, dict)
- assert isinstance(x_offset, int)
- assert isinstance(y_offset, int)
- assert isinstance(wrap_lines, bool)
-
- self.ui_content = ui_content
+ def __init__(self, ui_content, horizontal_scroll, vertical_scroll,
+ window_width, window_height,
+ configured_scroll_offsets,
+ visible_line_to_row_col, rowcol_to_yx,
+ x_offset, y_offset, wrap_lines):
+ assert isinstance(ui_content, UIContent)
+ assert isinstance(horizontal_scroll, int)
+ assert isinstance(vertical_scroll, int)
+ assert isinstance(window_width, int)
+ assert isinstance(window_height, int)
+ assert isinstance(configured_scroll_offsets, ScrollOffsets)
+ assert isinstance(visible_line_to_row_col, dict)
+ assert isinstance(rowcol_to_yx, dict)
+ assert isinstance(x_offset, int)
+ assert isinstance(y_offset, int)
+ assert isinstance(wrap_lines, bool)
+
+ self.ui_content = ui_content
self.vertical_scroll = vertical_scroll
- self.window_width = window_width # Width without margins.
+ self.window_width = window_width # Width without margins.
self.window_height = window_height
-
+
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
-
+ 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
- def visible_line_to_input_line(self):
- return dict(
- (visible_line, rowcol[0])
- for visible_line, rowcol in self.visible_line_to_row_col.items())
-
- @property
- def cursor_position(self):
+ def visible_line_to_input_line(self):
+ return dict(
+ (visible_line, rowcol[0])
+ for visible_line, rowcol in self.visible_line_to_row_col.items())
+
+ @property
+ def cursor_position(self):
"""
- Return the cursor position coordinates, relative to the left/top corner
- of the rendered screen.
+ 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)
+ 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
- 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,
- self.configured_scroll_offsets.bottom),
-
- # For left/right, it probably doesn't make sense to return something.
- # (We would have to calculate the widths of all the lines and keep
- # double width characters in mind.)
- left=0, right=0)
-
+ 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,
+ self.configured_scroll_offsets.bottom),
+
+ # For left/right, it probably doesn't make sense to return something.
+ # (We would have to calculate the widths of all the lines and keep
+ # double width characters in mind.)
+ left=0, right=0)
+
@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):
- """
- Return the dictionary mapping the line numbers of the input buffer to
- the lines of the screen. When a line spans several rows at the screen,
- the first row appears in the dictionary.
- """
- result = {}
- for k, v in self.visible_line_to_input_line.items():
- if v in result:
- result[v] = min(result[v], k)
- else:
- result[v] = k
- return result
-
+ 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):
+ """
+ Return the dictionary mapping the line numbers of the input buffer to
+ the lines of the screen. When a line spans several rows at the screen,
+ the first row appears in the dictionary.
+ """
+ result = {}
+ for k, v in self.visible_line_to_input_line.items():
+ if v in result:
+ result[v] = min(result[v], k)
+ else:
+ 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:
- return self.displayed_lines[self.applied_scroll_offsets.top]
- else:
- return self.displayed_lines[0]
+ 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:
- return self.displayed_lines[-1 - self.applied_scroll_offsets.bottom]
- else:
- return self.displayed_lines[-1]
+ 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):
@@ -737,7 +737,7 @@ class WindowRenderInfo(object):
"""
return (self.first_visible_line(after_scroll_offset) +
(self.last_visible_line(before_scroll_offset) -
- self.first_visible_line(after_scroll_offset)) // 2
+ self.first_visible_line(after_scroll_offset)) // 2
)
@property
@@ -745,14 +745,14 @@ class WindowRenderInfo(object):
"""
The full height of the user control.
"""
- return self.ui_content.line_count
+ return self.ui_content.line_count
@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
+ return self.vertical_scroll == 0 and self.last_visible_line() == self.content_height
@property
def top_visible(self):
@@ -766,7 +766,7 @@ class WindowRenderInfo(object):
"""
True when the bottom of the buffer is visible.
"""
- return self.last_visible_line() == self.content_height - 1
+ return self.last_visible_line() == self.content_height - 1
@property
def vertical_scroll_percentage(self):
@@ -774,22 +774,22 @@ class WindowRenderInfo(object):
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.
- (The height that it would take, if this line became visible.)
- """
- if self.wrap_lines:
- return self.ui_content.get_height_for_line(lineno, self.window_width)
- else:
- return 1
-
-
+ 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.
+ (The height that it would take, if this line became visible.)
+ """
+ if self.wrap_lines:
+ 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.
@@ -797,46 +797,46 @@ class ScrollOffsets(object):
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
- self._right = right
-
- @property
- def top(self):
- return int(self._top)
-
- @property
- def bottom(self):
- return int(self._bottom)
-
- @property
- def left(self):
- return int(self._left)
-
- @property
- def right(self):
- return int(self._right)
-
+ 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
+ self._right = right
+
+ @property
+ def top(self):
+ return int(self._top)
+
+ @property
+ def bottom(self):
+ return int(self._bottom)
+
+ @property
+ def left(self):
+ return int(self._left)
+
+ @property
+ 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)
-class ColorColumn(object):
- def __init__(self, position, token=Token.ColorColumn):
- self.position = position
- self.token = token
-
-
-_in_insert_mode = ViInsertMode() | EmacsInsertMode()
-
-
+class ColorColumn(object):
+ def __init__(self, position, token=Token.ColorColumn):
+ self.position = position
+ self.token = token
+
+
+_in_insert_mode = ViInsertMode() | EmacsInsertMode()
+
+
class Window(Container):
"""
Container that holds a control.
@@ -865,8 +865,8 @@ class Window(Container):
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 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
@@ -877,25 +877,25 @@ class Window(Container):
: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`
- instance. When True, display a cursorcolumn.
- :param get_colorcolumns: A callable that takes a `CommandLineInterface` and
- returns a a list of :class:`.ColorColumn` instances that describe the
- columns to be highlighted.
- :param cursorline_token: The token to be used for highlighting the current line,
- if `cursorline` is True.
- :param cursorcolumn_token: The token to be used for highlighting the current line,
- if `cursorcolumn` is True.
+ :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`
+ instance. When True, display a cursorcolumn.
+ :param get_colorcolumns: A callable that takes a `CommandLineInterface` and
+ returns a a list of :class:`.ColorColumn` instances that describe the
+ columns to be highlighted.
+ :param cursorline_token: The token to be used for highlighting the current line,
+ 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,
- 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):
+ 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)
@@ -908,13 +908,13 @@ class Window(Container):
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)
+ 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.wrap_lines = to_cli_filter(wrap_lines)
- self.cursorline = to_cli_filter(cursorline)
- self.cursorcolumn = to_cli_filter(cursorcolumn)
+ 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
@@ -926,13 +926,13 @@ class Window(Container):
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
+ 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.
- self._ui_content_cache = SimpleCache(maxsize=8)
- self._margin_width_cache = SimpleCache(maxsize=1)
+ self._ui_content_cache = SimpleCache(maxsize=8)
+ self._margin_width_cache = SimpleCache(maxsize=1)
self.reset()
@@ -946,41 +946,41 @@ class Window(Container):
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
-
+ # 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
- def _get_margin_width(self, cli, margin):
- """
- Return the width for this margin.
- (Calculate only once per render time.)
- """
- # Margin.get_width, needs to have a UIContent instance.
- def get_ui_content():
- return self._get_ui_content(cli, width=0, height=0)
-
- def get_width():
- return margin.get_width(cli, get_ui_content)
-
- key = (margin, cli.render_counter)
- return self._margin_width_cache.get(key, get_width)
-
+ def _get_margin_width(self, cli, margin):
+ """
+ Return the width for this margin.
+ (Calculate only once per render time.)
+ """
+ # Margin.get_width, needs to have a UIContent instance.
+ def get_ui_content():
+ return self._get_ui_content(cli, width=0, height=0)
+
+ def get_width():
+ return margin.get_width(cli, get_ui_content)
+
+ key = (margin, cli.render_counter)
+ return self._margin_width_cache.get(key, get_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
+ # 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)
- # Window of the content. (Can be `None`.)
+ # 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:
- # Include width of the margins.
+ # Include width of the margins.
preferred_width += total_margin_width
# Merge.
@@ -989,15 +989,15 @@ class Window(Container):
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)
-
+ 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),
- preferred=self.content.preferred_height(
- cli, width - total_margin_width, max_available_height, wrap_lines),
+ preferred=self.content.preferred_height(
+ cli, width - total_margin_width, max_available_height, wrap_lines),
dont_extend=self.dont_extend_height)
@staticmethod
@@ -1030,115 +1030,115 @@ class Window(Container):
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.
- """
- def get_content():
- return self.content.create_content(cli, width=width, height=height)
-
- key = (cli.render_counter, width, height)
- return self._ui_content_cache.get(key, get_content)
-
- def _get_digraph_char(self, cli):
- " Return `False`, or the Digraph symbol to be used. "
+ return LayoutDimension(
+ min=dimension.min, max=max_,
+ preferred=preferred, weight=dimension.weight)
+
+ def _get_ui_content(self, cli, width, height):
+ """
+ Create a `UIContent` instance.
+ """
+ def get_content():
+ return self.content.create_content(cli, width=width, height=height)
+
+ key = (cli.render_counter, width, height)
+ return self._ui_content_cache.get(key, get_content)
+
+ def _get_digraph_char(self, cli):
+ " Return `False`, or the Digraph symbol to be used. "
if cli.quoted_insert:
return '^'
- if cli.vi_state.waiting_for_digraph:
- if cli.vi_state.digraph_symbol1:
- return cli.vi_state.digraph_symbol1
- return '?'
- return False
-
+ if cli.vi_state.waiting_for_digraph:
+ if cli.vi_state.digraph_symbol1:
+ return cli.vi_state.digraph_symbol1
+ 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.
- 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]
+ 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.
- ui_content = self.content.create_content(
+ ui_content = self.content.create_content(
cli, write_position.width - total_margin_width, write_position.height)
- assert isinstance(ui_content, UIContent)
+ assert isinstance(ui_content, UIContent)
# 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,
- sum(left_margin_widths), write_position.width - total_margin_width,
- self.vertical_scroll, self.horizontal_scroll,
- has_focus=self.content.has_focus(cli),
- wrap_lines=wrap_lines, highlight_lines=True,
- vertical_scroll_2=self.vertical_scroll_2,
- always_hide_cursor=self.always_hide_cursor(cli))
-
+ 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,
+ sum(left_margin_widths), write_position.width - total_margin_width,
+ self.vertical_scroll, self.horizontal_scroll,
+ has_focus=self.content.has_focus(cli),
+ wrap_lines=wrap_lines, highlight_lines=True,
+ 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.)
- x_offset=write_position.xpos + sum(left_margin_widths)
- y_offset=write_position.ypos
-
+ x_offset=write_position.xpos + sum(left_margin_widths)
+ y_offset=write_position.ypos
+
self.render_info = WindowRenderInfo(
- ui_content=ui_content,
+ ui_content=ui_content,
horizontal_scroll=self.horizontal_scroll,
vertical_scroll=self.vertical_scroll,
- window_width=write_position.width - total_margin_width,
+ window_width=write_position.width - total_margin_width,
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)
+ 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
- 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]
- except KeyError:
- # Try again. (When clicking on the right side of double
- # width characters, or on the right side of the input.)
- x -= 1
- else:
- # Found position, call handler of UIControl.
- result = self.content.mouse_handler(
- cli, MouseEvent(position=Point(x=col, y=row),
- event_type=mouse_event.event_type))
- break
- else:
- # nobreak.
- # (No x/y coordinate found for the content. This happens in
- # case of a FillControl, that only specifies a background, but
- # doesn't have a content. Report (0,0) instead.)
- result = self.content.mouse_handler(
- cli, MouseEvent(position=Point(x=0, y=0),
- event_type=mouse_event.event_type))
-
+ 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]
+ except KeyError:
+ # Try again. (When clicking on the right side of double
+ # width characters, or on the right side of the input.)
+ x -= 1
+ else:
+ # Found position, call handler of UIControl.
+ result = self.content.mouse_handler(
+ cli, MouseEvent(position=Point(x=col, y=row),
+ event_type=mouse_event.event_type))
+ break
+ else:
+ # nobreak.
+ # (No x/y coordinate found for the content. This happens in
+ # case of a FillControl, that only specifies a background, but
+ # doesn't have a content. Report (0,0) instead.)
+ result = self.content.mouse_handler(
+ 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)
@@ -1160,17 +1160,17 @@ class Window(Container):
# Retrieve margin tokens.
tokens = m.create_margin(cli, self.render_info, width, write_position.height)
- # Turn it into a UIContent object.
+ # Turn it into a UIContent object.
# already rendered those tokens using this size.)
- return TokenListControl.static(tokens).create_content(
- cli, width + 1, write_position.height)
+ 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.
- self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
+ self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
move_x += width
move_x = write_position.width - sum(right_margin_widths)
@@ -1180,351 +1180,351 @@ class Window(Container):
margin_screen = render_margin(m, width)
# Copy and shift X.
- self._copy_margin(cli, margin_screen, screen, write_position, move_x, width)
+ self._copy_margin(cli, margin_screen, screen, write_position, 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):
+ 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.
+ Copy the UIContent into the output screen.
"""
xpos = write_position.xpos + move_x
ypos = write_position.ypos
- line_count = ui_content.line_count
+ line_count = ui_content.line_count
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]
- for x in range(xpos, xpos + width):
- new_buffer_row[x] = default_char
-
- # Copy content.
- def copy():
- y = - vertical_scroll_2
- lineno = vertical_scroll
-
- while y < write_position.height and lineno < line_count:
- # Take the next line and copy it in the real screen.
- line = ui_content.get_line(lineno)
-
- col = 0
- x = -horizontal_scroll
-
- visible_line_to_row_col[y] = (lineno, horizontal_scroll)
- new_buffer_row = new_buffer[y + ypos]
-
- for token, text in line:
- # Remember raw VT escape sequences. (E.g. FinalTerm's
- # escape sequences.)
- if token == ZeroWidthEscape:
- new_screen.zero_width_escapes[y + ypos][x + xpos] += text
- continue
-
- for c in text:
- char = _CHAR_CACHE[c, token]
- char_width = char.width
-
- # Wrap when the line width is exceeded.
- if wrap_lines and x + char_width > width:
- visible_line_to_row_col[y + 1] = (
- lineno, visible_line_to_row_col[y][1] + x)
- y += 1
- x = -horizontal_scroll # This would be equal to zero.
- # (horizontal_scroll=0 when wrap_lines.)
- new_buffer_row = new_buffer[y + ypos]
-
- if y >= write_position.height:
- return y # Break out of all for loops.
-
- # Set character in screen and shift 'x'.
- if x >= 0 and y >= 0 and x < write_position.width:
- new_buffer_row[x + xpos] = char
-
- # When we print a multi width character, make sure
- # to erase the neighbous positions in the screen.
- # (The empty string if different from everything,
- # so next redraw this cell will repaint anyway.)
- if char_width > 1:
- for i in range(1, char_width):
- new_buffer_row[x + xpos + i] = empty_char
-
- # If this is a zero width characters, then it's
- # probably part of a decomposed unicode character.
- # See: https://en.wikipedia.org/wiki/Unicode_equivalence
- # Merge it in the previous cell.
- elif char_width == 0 and x - 1 >= 0:
- prev_char = new_buffer_row[x + xpos - 1]
- char2 = _CHAR_CACHE[prev_char.char + c, prev_char.token]
- new_buffer_row[x + xpos - 1] = char2
-
- # Keep track of write position for each character.
- rowcol_to_yx[lineno, col] = (y + ypos, x + xpos)
-
- col += 1
- x += char_width
-
- lineno += 1
- y += 1
- return y
-
- y = copy()
-
- def cursor_pos_to_screen_pos(row, col):
- " Translate row/col from UIContent to real Screen coordinates. "
- try:
- y, x = rowcol_to_yx[row, col]
- except KeyError:
- # Normally this should never happen. (It is a bug, if it happens.)
- # But to be sure, return (0, 0)
- return Point(y=0, x=0)
-
- # raise ValueError(
- # 'Invalid position. row=%r col=%r, vertical_scroll=%r, '
- # 'horizontal_scroll=%r, height=%r' %
- # (row, col, vertical_scroll, horizontal_scroll, write_position.height))
+ 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]
+ for x in range(xpos, xpos + width):
+ new_buffer_row[x] = default_char
+
+ # Copy content.
+ def copy():
+ y = - vertical_scroll_2
+ lineno = vertical_scroll
+
+ while y < write_position.height and lineno < line_count:
+ # Take the next line and copy it in the real screen.
+ line = ui_content.get_line(lineno)
+
+ col = 0
+ x = -horizontal_scroll
+
+ visible_line_to_row_col[y] = (lineno, horizontal_scroll)
+ new_buffer_row = new_buffer[y + ypos]
+
+ for token, text in line:
+ # Remember raw VT escape sequences. (E.g. FinalTerm's
+ # escape sequences.)
+ if token == ZeroWidthEscape:
+ new_screen.zero_width_escapes[y + ypos][x + xpos] += text
+ continue
+
+ for c in text:
+ char = _CHAR_CACHE[c, token]
+ char_width = char.width
+
+ # Wrap when the line width is exceeded.
+ if wrap_lines and x + char_width > width:
+ visible_line_to_row_col[y + 1] = (
+ lineno, visible_line_to_row_col[y][1] + x)
+ y += 1
+ x = -horizontal_scroll # This would be equal to zero.
+ # (horizontal_scroll=0 when wrap_lines.)
+ new_buffer_row = new_buffer[y + ypos]
+
+ if y >= write_position.height:
+ return y # Break out of all for loops.
+
+ # Set character in screen and shift 'x'.
+ if x >= 0 and y >= 0 and x < write_position.width:
+ new_buffer_row[x + xpos] = char
+
+ # When we print a multi width character, make sure
+ # to erase the neighbous positions in the screen.
+ # (The empty string if different from everything,
+ # so next redraw this cell will repaint anyway.)
+ if char_width > 1:
+ for i in range(1, char_width):
+ new_buffer_row[x + xpos + i] = empty_char
+
+ # If this is a zero width characters, then it's
+ # probably part of a decomposed unicode character.
+ # See: https://en.wikipedia.org/wiki/Unicode_equivalence
+ # Merge it in the previous cell.
+ elif char_width == 0 and x - 1 >= 0:
+ prev_char = new_buffer_row[x + xpos - 1]
+ char2 = _CHAR_CACHE[prev_char.char + c, prev_char.token]
+ new_buffer_row[x + xpos - 1] = char2
+
+ # Keep track of write position for each character.
+ rowcol_to_yx[lineno, col] = (y + ypos, x + xpos)
+
+ col += 1
+ x += char_width
+
+ lineno += 1
+ y += 1
+ return y
+
+ y = copy()
+
+ def cursor_pos_to_screen_pos(row, col):
+ " Translate row/col from UIContent to real Screen coordinates. "
+ try:
+ y, x = rowcol_to_yx[row, col]
+ except KeyError:
+ # Normally this should never happen. (It is a bug, if it happens.)
+ # But to be sure, return (0, 0)
+ return Point(y=0, x=0)
+
+ # raise ValueError(
+ # 'Invalid position. row=%r col=%r, vertical_scroll=%r, '
+ # 'horizontal_scroll=%r, height=%r' %
+ # (row, col, vertical_scroll, horizontal_scroll, write_position.height))
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(
- ui_content.menu_position.y, ui_content.menu_position.x)
-
- # Update output screne height.
- new_screen.height = max(new_screen.height, ypos + write_position.height)
-
- 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.
- """
- digraph_char = self._get_digraph_char(cli)
- if digraph_char:
- cpos = new_screen.cursor_position
- new_screen.data_buffer[cpos.y][cpos.x] = \
- _CHAR_CACHE[digraph_char, Token.Digraph]
-
- def _show_input_processor_key_buffer(self, cli, new_screen):
- """
- When the user is typing a key binding that consists of several keys,
- display the last pressed key if the user is in insert mode and the key
- is meaningful to be displayed.
- E.g. Some people want to bind 'jj' to escape in Vi insert mode. But the
- first 'j' needs to be displayed in order to get some feedback.
- """
- key_buffer = cli.input_processor.key_buffer
-
- if key_buffer and _in_insert_mode(cli) and not cli.is_done:
- # The textual data for the given key. (Can be a VT100 escape
- # sequence.)
- data = key_buffer[-1].data
-
- # Display only if this is a 1 cell width character.
- if get_cwidth(data) == 1:
- cpos = new_screen.cursor_position
- new_screen.data_buffer[cpos.y][cpos.x] = \
- _CHAR_CACHE[data, Token.PartialKeyBinding]
-
- def _highlight_cursorlines(self, cli, new_screen, cpos, x, y, width, height):
- """
- Highlight cursor row/column.
- """
- cursor_line_token = (':', ) + self.cursorline_token
- cursor_column_token = (':', ) + self.cursorcolumn_token
-
- data_buffer = new_screen.data_buffer
-
- # Highlight cursor line.
- if self.cursorline(cli):
- row = data_buffer[cpos.y]
- for x in range(x, x + width):
- original_char = row[x]
- row[x] = _CHAR_CACHE[
- original_char.char, original_char.token + cursor_line_token]
-
- # Highlight cursor column.
- if self.cursorcolumn(cli):
- for y2 in range(y, y + height):
- row = data_buffer[y2]
- original_char = row[cpos.x]
- row[cpos.x] = _CHAR_CACHE[
- original_char.char, original_char.token + cursor_column_token]
-
- # Highlight color columns
- for cc in self.get_colorcolumns(cli):
- assert isinstance(cc, ColorColumn)
- color_column_token = (':', ) + cc.token
- column = cc.position
-
- for y2 in range(y, y + height):
- row = data_buffer[y2]
- original_char = row[column]
- row[column] = _CHAR_CACHE[
- original_char.char, original_char.token + color_column_token]
-
- def _copy_margin(self, cli, lazy_screen, new_screen, write_position, move_x, width):
- """
+ 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(
+ ui_content.menu_position.y, ui_content.menu_position.x)
+
+ # Update output screne height.
+ new_screen.height = max(new_screen.height, ypos + write_position.height)
+
+ 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.
+ """
+ digraph_char = self._get_digraph_char(cli)
+ if digraph_char:
+ cpos = new_screen.cursor_position
+ new_screen.data_buffer[cpos.y][cpos.x] = \
+ _CHAR_CACHE[digraph_char, Token.Digraph]
+
+ def _show_input_processor_key_buffer(self, cli, new_screen):
+ """
+ When the user is typing a key binding that consists of several keys,
+ display the last pressed key if the user is in insert mode and the key
+ is meaningful to be displayed.
+ E.g. Some people want to bind 'jj' to escape in Vi insert mode. But the
+ first 'j' needs to be displayed in order to get some feedback.
+ """
+ key_buffer = cli.input_processor.key_buffer
+
+ if key_buffer and _in_insert_mode(cli) and not cli.is_done:
+ # The textual data for the given key. (Can be a VT100 escape
+ # sequence.)
+ data = key_buffer[-1].data
+
+ # Display only if this is a 1 cell width character.
+ if get_cwidth(data) == 1:
+ cpos = new_screen.cursor_position
+ new_screen.data_buffer[cpos.y][cpos.x] = \
+ _CHAR_CACHE[data, Token.PartialKeyBinding]
+
+ def _highlight_cursorlines(self, cli, new_screen, cpos, x, y, width, height):
+ """
+ Highlight cursor row/column.
+ """
+ cursor_line_token = (':', ) + self.cursorline_token
+ cursor_column_token = (':', ) + self.cursorcolumn_token
+
+ data_buffer = new_screen.data_buffer
+
+ # Highlight cursor line.
+ if self.cursorline(cli):
+ row = data_buffer[cpos.y]
+ for x in range(x, x + width):
+ original_char = row[x]
+ row[x] = _CHAR_CACHE[
+ original_char.char, original_char.token + cursor_line_token]
+
+ # Highlight cursor column.
+ if self.cursorcolumn(cli):
+ for y2 in range(y, y + height):
+ row = data_buffer[y2]
+ original_char = row[cpos.x]
+ row[cpos.x] = _CHAR_CACHE[
+ original_char.char, original_char.token + cursor_column_token]
+
+ # Highlight color columns
+ for cc in self.get_colorcolumns(cli):
+ assert isinstance(cc, ColorColumn)
+ color_column_token = (':', ) + cc.token
+ column = cc.position
+
+ for y2 in range(y, y + height):
+ row = data_buffer[y2]
+ original_char = row[column]
+ row[column] = _CHAR_CACHE[
+ original_char.char, original_char.token + color_column_token]
+
+ 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
- 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
-
- # If the current line consumes more than the whole window height,
- # then we have to scroll vertically inside this line. (We don't take
- # the scroll offsets into account for this.)
- # Also, ignore the scroll offsets in this case. Just set the vertical
- # scroll to this line.
- if ui_content.get_height_for_line(ui_content.cursor_position.y, width) > height - scroll_offsets_top:
- # Calculate the height of the text before the cursor, with the line
- # containing the cursor included, and the character belowe the
- # cursor included as well.
- line = explode_tokens(ui_content.get_line(ui_content.cursor_position.y))
- text_before_cursor = token_list_to_text(line[:ui_content.cursor_position.x + 1])
- text_before_height = UIContent.get_height_for_text(text_before_cursor, width)
-
- # Adjust scroll offset.
- self.vertical_scroll = ui_content.cursor_position.y
- self.vertical_scroll_2 = min(text_before_height - 1, self.vertical_scroll_2)
- self.vertical_scroll_2 = max(0, text_before_height - height, self.vertical_scroll_2)
- return
- else:
- self.vertical_scroll_2 = 0
-
- # Current line doesn't consume the whole height. Take scroll offsets into account.
- def get_min_vertical_scroll():
- # Make sure that the cursor line is not below the bottom.
- # (Calculate how many lines can be shown between the cursor and the .)
- used_height = 0
- prev_lineno = ui_content.cursor_position.y
-
- for lineno in range(ui_content.cursor_position.y, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
-
- if used_height > height - scroll_offsets_bottom:
- return prev_lineno
- else:
- prev_lineno = lineno
- return 0
-
- def get_max_vertical_scroll():
- # Make sure that the cursor line is not above the top.
- prev_lineno = ui_content.cursor_position.y
- used_height = 0
-
- for lineno in range(ui_content.cursor_position.y - 1, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
-
- if used_height > scroll_offsets_top:
- return prev_lineno
- else:
- prev_lineno = lineno
- return prev_lineno
-
- def get_topmost_visible():
- """
- Calculate the upper most line that can be visible, while the bottom
- is still visible. We should not allow scroll more than this if
- `allow_scroll_beyond_bottom` is false.
- """
- prev_lineno = ui_content.line_count - 1
- used_height = 0
- for lineno in range(ui_content.line_count - 1, -1, -1):
- used_height += ui_content.get_height_for_line(lineno, width)
- if used_height > height:
- return prev_lineno
- else:
- prev_lineno = lineno
- return prev_lineno
-
- # Scroll vertically. (Make sure that the whole line which contains the
- # cursor is visible.
- topmost_visible = get_topmost_visible()
-
- # Note: the `min(topmost_visible, ...)` is to make sure that we
- # don't require scrolling up because of the bottom scroll offset,
- # when we are at the end of the document.
- self.vertical_scroll = max(self.vertical_scroll, min(topmost_visible, get_min_vertical_scroll()))
- self.vertical_scroll = min(self.vertical_scroll, get_max_vertical_scroll())
-
- # Disallow scrolling beyond bottom?
- if not self.allow_scroll_beyond_bottom(cli):
- 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
- # a single line.
- self.vertical_scroll_2 = 0
-
- if ui_content.line_count == 0:
- self.vertical_scroll = 0
- self.horizontal_scroll = 0
- return
- else:
- current_line_text = token_list_to_text(ui_content.get_line(cursor_position.y))
-
+ 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
+
+ # If the current line consumes more than the whole window height,
+ # then we have to scroll vertically inside this line. (We don't take
+ # the scroll offsets into account for this.)
+ # Also, ignore the scroll offsets in this case. Just set the vertical
+ # scroll to this line.
+ if ui_content.get_height_for_line(ui_content.cursor_position.y, width) > height - scroll_offsets_top:
+ # Calculate the height of the text before the cursor, with the line
+ # containing the cursor included, and the character belowe the
+ # cursor included as well.
+ line = explode_tokens(ui_content.get_line(ui_content.cursor_position.y))
+ text_before_cursor = token_list_to_text(line[:ui_content.cursor_position.x + 1])
+ text_before_height = UIContent.get_height_for_text(text_before_cursor, width)
+
+ # Adjust scroll offset.
+ self.vertical_scroll = ui_content.cursor_position.y
+ self.vertical_scroll_2 = min(text_before_height - 1, self.vertical_scroll_2)
+ self.vertical_scroll_2 = max(0, text_before_height - height, self.vertical_scroll_2)
+ return
+ else:
+ self.vertical_scroll_2 = 0
+
+ # Current line doesn't consume the whole height. Take scroll offsets into account.
+ def get_min_vertical_scroll():
+ # Make sure that the cursor line is not below the bottom.
+ # (Calculate how many lines can be shown between the cursor and the .)
+ used_height = 0
+ prev_lineno = ui_content.cursor_position.y
+
+ for lineno in range(ui_content.cursor_position.y, -1, -1):
+ used_height += ui_content.get_height_for_line(lineno, width)
+
+ if used_height > height - scroll_offsets_bottom:
+ return prev_lineno
+ else:
+ prev_lineno = lineno
+ return 0
+
+ def get_max_vertical_scroll():
+ # Make sure that the cursor line is not above the top.
+ prev_lineno = ui_content.cursor_position.y
+ used_height = 0
+
+ for lineno in range(ui_content.cursor_position.y - 1, -1, -1):
+ used_height += ui_content.get_height_for_line(lineno, width)
+
+ if used_height > scroll_offsets_top:
+ return prev_lineno
+ else:
+ prev_lineno = lineno
+ return prev_lineno
+
+ def get_topmost_visible():
+ """
+ Calculate the upper most line that can be visible, while the bottom
+ is still visible. We should not allow scroll more than this if
+ `allow_scroll_beyond_bottom` is false.
+ """
+ prev_lineno = ui_content.line_count - 1
+ used_height = 0
+ for lineno in range(ui_content.line_count - 1, -1, -1):
+ used_height += ui_content.get_height_for_line(lineno, width)
+ if used_height > height:
+ return prev_lineno
+ else:
+ prev_lineno = lineno
+ return prev_lineno
+
+ # Scroll vertically. (Make sure that the whole line which contains the
+ # cursor is visible.
+ topmost_visible = get_topmost_visible()
+
+ # Note: the `min(topmost_visible, ...)` is to make sure that we
+ # don't require scrolling up because of the bottom scroll offset,
+ # when we are at the end of the document.
+ self.vertical_scroll = max(self.vertical_scroll, min(topmost_visible, get_min_vertical_scroll()))
+ self.vertical_scroll = min(self.vertical_scroll, get_max_vertical_scroll())
+
+ # Disallow scrolling beyond bottom?
+ if not self.allow_scroll_beyond_bottom(cli):
+ 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
+ # a single line.
+ self.vertical_scroll_2 = 0
+
+ if ui_content.line_count == 0:
+ self.vertical_scroll = 0
+ self.horizontal_scroll = 0
+ return
+ 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. "
@@ -1552,7 +1552,7 @@ class Window(Container):
if current_scroll < (cursor_pos + 1) - window_size + scroll_offset_end:
current_scroll = (cursor_pos + 1) - window_size + scroll_offset_end
- return current_scroll
+ return current_scroll
# When a preferred scroll is given, take that first into account.
if self.get_vertical_scroll:
@@ -1566,32 +1566,32 @@ class Window(Container):
# remains visible.
offsets = self.scroll_offsets
- self.vertical_scroll = do_scroll(
+ self.vertical_scroll = do_scroll(
current_scroll=self.vertical_scroll,
scroll_offset_start=offsets.top,
scroll_offset_end=offsets.bottom,
- cursor_pos=ui_content.cursor_position.y,
+ cursor_pos=ui_content.cursor_position.y,
window_size=height,
- content_size=ui_content.line_count)
+ content_size=ui_content.line_count)
- self.horizontal_scroll = do_scroll(
+ self.horizontal_scroll = do_scroll(
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]),
+ cursor_pos=get_cwidth(current_line_text[:ui_content.cursor_position.x]),
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))
+ # 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.
"""
- if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
+ if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
self._scroll_down(cli)
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
+ elif mouse_event.event_type == MouseEventType.SCROLL_UP:
self._scroll_up(cli)
def _scroll_down(self, cli):
@@ -1609,7 +1609,7 @@ class Window(Container):
info = self.render_info
if info.vertical_scroll > 0:
- # TODO: not entirely correct yet in case of line wrapping and long lines.
+ # 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)
@@ -1635,9 +1635,9 @@ class ConditionalContainer(Container):
self.content = content
self.filter = to_cli_filter(filter)
- def __repr__(self):
- return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter)
-
+ def __repr__(self):
+ return 'ConditionalContainer(%r, filter=%r)' % (self.content, self.filter)
+
def reset(self):
self.content.reset()
@@ -1647,9 +1647,9 @@ class ConditionalContainer(Container):
else:
return LayoutDimension.exact(0)
- def preferred_height(self, cli, width, max_available_height):
+ def preferred_height(self, cli, width, max_available_height):
if self.filter(cli):
- return self.content.preferred_height(cli, width, max_available_height)
+ return self.content.preferred_height(cli, width, max_available_height)
else:
return LayoutDimension.exact(0)
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 ca74931dbc..951110f82b 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/controls.py
@@ -4,34 +4,34 @@ User interface Controls for the layout.
from __future__ import unicode_literals
from abc import ABCMeta, abstractmethod
-from collections import namedtuple
+from collections import namedtuple
from six import with_metaclass
-from six.moves import range
+from six.moves import range
-from prompt_toolkit.cache import SimpleCache
+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.mouse_events import MouseEventType
+from prompt_toolkit.mouse_events import MouseEventType
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 prompt_toolkit.token import Token
+from prompt_toolkit.utils import get_cwidth
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
+from .processors import Processor
+from .screen import Char, Point
+from .utils import token_list_width, split_lines, token_list_to_text
-import six
+import six
import time
-
+
__all__ = (
'BufferControl',
'FillControl',
'TokenListControl',
'UIControl',
- 'UIContent',
+ 'UIContent',
)
@@ -46,7 +46,7 @@ class UIControl(with_metaclass(ABCMeta, object)):
def preferred_width(self, cli, max_available_width):
return None
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
+ def preferred_height(self, cli, width, max_available_height, wrap_lines):
return None
def has_focus(self, cli):
@@ -54,18 +54,18 @@ class UIControl(with_metaclass(ABCMeta, object)):
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.
+ 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
- def create_content(self, cli, width, height):
+ def create_content(self, cli, width, height):
"""
- Generate the content for this user control.
+ Generate the content for this user control.
- Returns a :class:`.UIContent` instance.
+ Returns a :class:`.UIContent` instance.
"""
def mouse_handler(self, cli, mouse_event):
@@ -94,78 +94,78 @@ class UIControl(with_metaclass(ABCMeta, object)):
"""
-class UIContent(object):
- """
- Content generated by a user control. This content consists of a list of
- lines.
-
- :param get_line: Callable that returns the current line. This is a list of
- (Token, text) tuples.
- :param line_count: The number of lines.
- :param cursor_position: a :class:`.Point` for the cursor position.
- :param menu_position: a :class:`.Point` for the menu position.
- :param show_cursor: Make the cursor visible.
- :param default_char: The default :class:`.Char` for filling the background.
- """
- def __init__(self, get_line=None, line_count=0,
- cursor_position=None, menu_position=None, show_cursor=True,
- default_char=None):
- assert callable(get_line)
- assert isinstance(line_count, six.integer_types)
- assert cursor_position is None or isinstance(cursor_position, Point)
- assert menu_position is None or isinstance(menu_position, Point)
- assert default_char is None or isinstance(default_char, Char)
-
- self.get_line = get_line
- self.line_count = line_count
- self.cursor_position = cursor_position or Point(0, 0)
- self.menu_position = menu_position
- self.show_cursor = show_cursor
- self.default_char = default_char
-
- # Cache for line heights. Maps (lineno, width) -> height.
- self._line_heights = {}
-
- def __getitem__(self, lineno):
- " Make it iterable (iterate line by line). "
- if lineno < self.line_count:
- return self.get_line(lineno)
- else:
- raise IndexError
-
- def get_height_for_line(self, lineno, width):
- """
- Return the height that a given line would need if it is rendered in a
- space with the given width.
- """
- try:
- return self._line_heights[lineno, width]
- except KeyError:
- text = token_list_to_text(self.get_line(lineno))
- result = self.get_height_for_text(text, width)
-
- # Cache and return
- self._line_heights[lineno, width] = result
- return result
-
- @staticmethod
- def get_height_for_text(text, width):
- # Get text width for this line.
- line_width = get_cwidth(text)
-
- # Calculate height.
- try:
- quotient, remainder = divmod(line_width, width)
- except ZeroDivisionError:
- # Return something very big.
- # (This can happen, when the Window gets very small.)
- return 10 ** 10
- else:
- if remainder:
- quotient += 1 # Like math.ceil.
- return max(1, quotient)
-
-
+class UIContent(object):
+ """
+ Content generated by a user control. This content consists of a list of
+ lines.
+
+ :param get_line: Callable that returns the current line. This is a list of
+ (Token, text) tuples.
+ :param line_count: The number of lines.
+ :param cursor_position: a :class:`.Point` for the cursor position.
+ :param menu_position: a :class:`.Point` for the menu position.
+ :param show_cursor: Make the cursor visible.
+ :param default_char: The default :class:`.Char` for filling the background.
+ """
+ def __init__(self, get_line=None, line_count=0,
+ cursor_position=None, menu_position=None, show_cursor=True,
+ default_char=None):
+ assert callable(get_line)
+ assert isinstance(line_count, six.integer_types)
+ assert cursor_position is None or isinstance(cursor_position, Point)
+ assert menu_position is None or isinstance(menu_position, Point)
+ assert default_char is None or isinstance(default_char, Char)
+
+ self.get_line = get_line
+ self.line_count = line_count
+ self.cursor_position = cursor_position or Point(0, 0)
+ self.menu_position = menu_position
+ self.show_cursor = show_cursor
+ self.default_char = default_char
+
+ # Cache for line heights. Maps (lineno, width) -> height.
+ self._line_heights = {}
+
+ def __getitem__(self, lineno):
+ " Make it iterable (iterate line by line). "
+ if lineno < self.line_count:
+ return self.get_line(lineno)
+ else:
+ raise IndexError
+
+ def get_height_for_line(self, lineno, width):
+ """
+ Return the height that a given line would need if it is rendered in a
+ space with the given width.
+ """
+ try:
+ return self._line_heights[lineno, width]
+ except KeyError:
+ text = token_list_to_text(self.get_line(lineno))
+ result = self.get_height_for_text(text, width)
+
+ # Cache and return
+ self._line_heights[lineno, width] = result
+ return result
+
+ @staticmethod
+ def get_height_for_text(text, width):
+ # Get text width for this line.
+ line_width = get_cwidth(text)
+
+ # Calculate height.
+ try:
+ quotient, remainder = divmod(line_width, width)
+ except ZeroDivisionError:
+ # Return something very big.
+ # (This can happen, when the Window gets very small.)
+ return 10 ** 10
+ else:
+ if remainder:
+ quotient += 1 # Like math.ceil.
+ return max(1, quotient)
+
+
class TokenListControl(UIControl):
"""
Control that displays a list of (Token, text) tuples.
@@ -195,8 +195,8 @@ class TokenListControl(UIControl):
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)
+ 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)
@@ -211,21 +211,21 @@ class TokenListControl(UIControl):
if default_char:
get_default_char = lambda _: default_char
elif not get_default_char:
- get_default_char = lambda _: Char(' ', Token.Transparent)
+ get_default_char = lambda _: Char(' ', Token.Transparent)
self.get_default_char = get_default_char
- #: Cache for the content.
- self._content_cache = SimpleCache(maxsize=18)
- self._token_cache = SimpleCache(maxsize=1)
+ #: 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.
- self._tokens = None
-
- def reset(self):
- self._tokens = None
+ self._tokens = None
+ def reset(self):
+ self._tokens = None
+
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
@@ -235,7 +235,7 @@ class TokenListControl(UIControl):
(This function is called several times during one rendering, because
we also need those for calculating the dimensions.)
"""
- return self._token_cache.get(
+ return self._token_cache.get(
cli.render_counter, lambda: self.get_tokens(cli))
def has_focus(self, cli):
@@ -246,15 +246,15 @@ class TokenListControl(UIControl):
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))
+ 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)
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
- content = self.create_content(cli, width, None)
- return content.line_count
+ 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):
+ def create_content(self, cli, width, height):
# Get tokens
tokens_with_mouse_handlers = self._get_tokens_cached(cli)
@@ -270,51 +270,51 @@ class TokenListControl(UIControl):
padding = width - used_width
if center:
padding = int(padding / 2)
- return [(default_char.token, default_char.char * padding)] + line
+ return [(default_char.token, default_char.char * padding)] + line
if right or center:
- token_lines_with_mouse_handlers = []
-
+ token_lines_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))
+ 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.
- token_lines = [
- [tuple(item[:2]) for item in line]
- for line in token_lines_with_mouse_handlers
- ]
+ 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`.
+ # Keep track of the tokens with mouse handler, for later use in
+ # `mouse_handler`.
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:
- if token == SetCursorPosition:
- 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)
-
+ # 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:
+ if token == SetCursorPosition:
+ 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):
@@ -330,29 +330,29 @@ class TokenListControl(UIControl):
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:
- return NotImplemented
- else:
- # Find position in the token list.
- xpos = mouse_event.position.x
-
+ 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:
+ return NotImplemented
+ else:
+ # Find position in the token list.
+ xpos = mouse_event.position.x
+
# Find mouse handler for this character.
count = 0
- for item in tokens:
+ for item in tokens:
count += len(item[1])
- if count >= xpos:
+ if count >= xpos:
if len(item) >= 3:
# Handler found. Call it.
- # (Handler can return NotImplemented, so return
- # that result.)
+ # (Handler can return NotImplemented, so return
+ # that result.)
handler = item[2]
- return handler(cli, mouse_event)
+ return handler(cli, mouse_event)
else:
break
@@ -364,38 +364,38 @@ 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.
+
+ :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:
- # Passing (character=' ', token=token) is deprecated.
- self.character = character
- self.token = token
-
- self.get_char = lambda cli: Char(character, token)
- elif get_char:
- # When 'get_char' is given.
- self.get_char = get_char
- else:
- # When 'char' is given.
- self.char = self.char or Char()
- self.get_char = lambda cli: self.char
- self.char = char
-
+ 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:
+ # Passing (character=' ', token=token) is deprecated.
+ self.character = character
+ self.token = token
+
+ self.get_char = lambda cli: Char(character, token)
+ elif get_char:
+ # When 'get_char' is given.
+ self.get_char = get_char
+ else:
+ # When 'char' is given.
+ self.char = self.char or Char()
+ self.get_char = lambda cli: self.char
+ self.char = char
+
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)
+ 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
@@ -403,19 +403,19 @@ class FillControl(UIControl):
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')
+ 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`.
@@ -444,7 +444,7 @@ class BufferControl(UIControl):
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)
+ 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
@@ -457,15 +457,15 @@ class BufferControl(UIControl):
self.default_char = default_char or Char(token=Token.Transparent)
self.search_buffer_name = search_buffer_name
- #: Cache for the lexer.
+ #: 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.
- self._token_cache = SimpleCache(maxsize=8)
+ self._token_cache = SimpleCache(maxsize=8)
self._xy_to_cursor_position = None
self._last_click_timestamp = None
- self._last_get_processed_line = None
+ self._last_get_processed_line = None
def _buffer(self, cli):
"""
@@ -483,114 +483,114 @@ class BufferControl(UIControl):
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.
"""
- 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.
- height = 0
- content = self.create_content(cli, width, None)
-
- # When line wrapping is off, the height should be equal to the amount
- # of lines.
- if not wrap_lines:
- return content.line_count
-
- # When the number of lines exceeds the max_available_height, just
- # return max_available_height. No need to calculate anything.
- if content.line_count >= max_available_height:
- return max_available_height
-
- for i in range(content.line_count):
- height += content.get_height_for_line(i, width)
-
- if height >= max_available_height:
- return max_available_height
-
- return height
-
- def _get_tokens_for_line_func(self, cli, document):
- """
- Create a function that returns the tokens for a given line.
+ 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.
+ height = 0
+ content = self.create_content(cli, width, None)
+
+ # When line wrapping is off, the height should be equal to the amount
+ # of lines.
+ if not wrap_lines:
+ return content.line_count
+
+ # When the number of lines exceeds the max_available_height, just
+ # return max_available_height. No need to calculate anything.
+ if content.line_count >= max_available_height:
+ return max_available_height
+
+ for i in range(content.line_count):
+ height += content.get_height_for_line(i, width)
+
+ if height >= max_available_height:
+ return max_available_height
+
+ return height
+
+ def _get_tokens_for_line_func(self, cli, document):
"""
- # 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
- returns a _ProcessedLine(processed_tokens, source_to_display, display_to_source)
- tuple.
- """
- def transform(lineno, tokens):
- " Transform the tokens for a given line number. "
+ 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
+ returns a _ProcessedLine(processed_tokens, source_to_display, display_to_source)
+ tuple.
+ """
+ def transform(lineno, tokens):
+ " Transform the tokens for a given line number. "
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. """
- for f in source_to_display_functions:
- i = f(i)
- return i
-
- # Apply each processor.
+ # 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. """
+ for f in source_to_display_functions:
+ i = f(i)
+ return i
+
+ # Apply each processor.
for p in self.input_processors:
- transformation = p.apply_transformation(
- cli, document, lineno, source_to_display, tokens)
+ transformation = p.apply_transformation(
+ cli, document, lineno, source_to_display, tokens)
tokens = transformation.tokens
- if cursor_column:
- cursor_column = transformation.source_to_display(cursor_column)
+ 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)
+ display_to_source_functions.append(transformation.display_to_source)
+ source_to_display_functions.append(transformation.source_to_display)
- def display_to_source(i):
+ def display_to_source(i):
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]
- except KeyError:
- processed_line = transform(i, get_line(i))
- cache[i] = processed_line
- return processed_line
- return get_processed_line
-
- return create_func()
-
- def create_content(self, cli, width, height):
- """
- Create a UIContent.
- """
+ 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]
+ except KeyError:
+ processed_line = transform(i, get_line(i))
+ 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
@@ -615,31 +615,31 @@ class BufferControl(UIControl):
else:
document = buffer.document
- get_processed_line = self._create_get_processed_line_func(cli, document)
- self._last_get_processed_line = get_processed_line
+ 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 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
+ 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
- # otherwise, line wrapping/scrolling could change when moving the
- # cursor around.)
- tokens = tokens + [(self.default_char.token, ' ')]
- return 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
+ # otherwise, line wrapping/scrolling could change when moving the
+ # 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)
+ 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 --
@@ -648,22 +648,22 @@ class BufferControl(UIControl):
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)
+ 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.)
- menu_row, menu_col = buffer.document.translate_index_to_position(
+ menu_row, menu_col = buffer.document.translate_index_to_position(
min(buffer.cursor_position,
buffer.complete_state.original_document.cursor_position))
- content.menu_position = translate_rowcol(menu_row, menu_col)
+ content.menu_position = translate_rowcol(menu_row, menu_col)
else:
- content.menu_position = None
+ content.menu_position = None
- return content
+ return content
def mouse_handler(self, cli, mouse_event):
"""
@@ -674,46 +674,46 @@ class BufferControl(UIControl):
# Focus buffer when clicked.
if self.has_focus(cli):
- if self._last_get_processed_line:
- processed_line = self._last_get_processed_line(position.y)
-
+ 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.
- xpos = processed_line.display_to_source(position.x)
- index = buffer.document.translate_row_col_to_index(position.y, xpos)
+ xpos = processed_line.display_to_source(position.x)
+ index = buffer.document.translate_row_col_to_index(position.y, xpos)
# 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
- # selecting text in Vi navigation mode. In navigation mode,
- # the cursor can never be after the text, so the cursor
- # will be repositioned automatically.)
- 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
- buffer.start_selection(selection_type=SelectionType.CHARACTERS)
- buffer.cursor_position += end - start
- else:
- # Don't handle scroll events here.
- return NotImplemented
+ 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
+ # selecting text in Vi navigation mode. In navigation mode,
+ # the cursor can never be after the text, so the cursor
+ # will be repositioned automatically.)
+ 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
+ buffer.start_selection(selection_type=SelectionType.CHARACTERS)
+ buffer.cursor_position += end - start
+ else:
+ # Don't handle scroll events here.
+ return NotImplemented
# Not focussed, but focussing on click events.
else:
- if self.focus_on_click(cli) and mouse_event.event_type == MouseEventType.MOUSE_UP:
+ 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.)
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 a928fd8226..9808f2edb5 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/lexers.py
@@ -5,22 +5,22 @@ 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
-
-import re
-import six
-
+from six.moves import range
+
+from prompt_toolkit.token import Token
+from prompt_toolkit.filters import to_cli_filter
+from .utils import split_lines
+
+import re
+import six
+
__all__ = (
'Lexer',
'SimpleLexer',
'PygmentsLexer',
- 'SyntaxSync',
- 'SyncFromStart',
- 'RegexSync',
+ 'SyntaxSync',
+ 'SyncFromStart',
+ 'RegexSync',
)
@@ -29,127 +29,127 @@ class Lexer(with_metaclass(ABCMeta, object)):
Base class for all lexers.
"""
@abstractmethod
- def lex_document(self, cli, document):
+ 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.
+ 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):
"""
- 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:
- return [(self.token, lines[lineno])]
- except IndexError:
- return []
- return get_line
-
-
-class SyntaxSync(with_metaclass(ABCMeta, object)):
- """
- Syntax synchroniser. This is a tool that finds a start position for the
- lexer. This is especially important when editing big documents; we don't
- want to start the highlighting by running the lexer from the beginning of
- the file. That is very slow when editing.
- """
- @abstractmethod
- def get_sync_start_position(self, document, lineno):
- """
- Return the position from where we can start lexing as a (row, column)
- tuple.
-
- :param document: `Document` instance that contains all the lines.
- :param lineno: The line that we want to highlight. (We need to return
- this line, or an earlier position.)
- """
-
-class SyncFromStart(SyntaxSync):
- """
- Always start the syntax highlighting from the beginning.
- """
- def get_sync_start_position(self, document, lineno):
- return 0, 0
-
-
-class RegexSync(SyntaxSync):
- """
- Synchronize by starting at a line that matches the given regex pattern.
+ Lexer that doesn't do any tokenizing and returns the whole input as one token.
+
+ :param token: The `Token` for this lexer.
"""
- # Never go more than this amount of lines backwards for synchronisation.
- # That would be too CPU intensive.
- MAX_BACKWARDS = 500
-
- # Start lexing at the start, if we are in the first 'n' lines and no
- # synchronisation position was found.
- FROM_START_IF_NO_SYNC_POS_FOUND = 100
-
- def __init__(self, pattern):
- assert isinstance(pattern, six.text_type)
- self._compiled_pattern = re.compile(pattern)
-
- def get_sync_start_position(self, document, lineno):
- " Scan backwards, and find a possible position to start. "
- pattern = self._compiled_pattern
- lines = document.lines
-
- # Scan upwards, until we find a point where we can start the syntax
- # synchronisation.
- for i in range(lineno, max(-1, lineno - self.MAX_BACKWARDS), -1):
- match = pattern.match(lines[i])
- if match:
- return i, match.start()
-
- # No synchronisation point found. If we aren't that far from the
- # beginning, start at the very beginning, otherwise, just try to start
- # at the current line.
- if lineno < self.FROM_START_IF_NO_SYNC_POS_FOUND:
- return 0, 0
- else:
- return lineno, 0
-
- @classmethod
- def from_pygments_lexer_cls(cls, lexer_cls):
- """
- Create a :class:`.RegexSync` instance for this Pygments lexer class.
- """
- patterns = {
- # For Python, start highlighting at any class/def block.
- 'Python': r'^\s*(class|def)\s+',
- 'Python 3': r'^\s*(class|def)\s+',
-
- # For HTML, start at any open/close tag definition.
- 'HTML': r'<[/a-zA-Z]',
-
- # For javascript, start at a function.
- 'JavaScript': r'\bfunction\b'
-
- # TODO: Add definitions for other languages.
- # By default, we start at every possible line.
- }
- p = patterns.get(lexer_cls.name, '^')
- return cls(p)
-
-
+ # `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:
+ return [(self.token, lines[lineno])]
+ except IndexError:
+ return []
+ return get_line
+
+
+class SyntaxSync(with_metaclass(ABCMeta, object)):
+ """
+ Syntax synchroniser. This is a tool that finds a start position for the
+ lexer. This is especially important when editing big documents; we don't
+ want to start the highlighting by running the lexer from the beginning of
+ the file. That is very slow when editing.
+ """
+ @abstractmethod
+ def get_sync_start_position(self, document, lineno):
+ """
+ Return the position from where we can start lexing as a (row, column)
+ tuple.
+
+ :param document: `Document` instance that contains all the lines.
+ :param lineno: The line that we want to highlight. (We need to return
+ this line, or an earlier position.)
+ """
+
+class SyncFromStart(SyntaxSync):
+ """
+ Always start the syntax highlighting from the beginning.
+ """
+ def get_sync_start_position(self, document, lineno):
+ return 0, 0
+
+
+class RegexSync(SyntaxSync):
+ """
+ Synchronize by starting at a line that matches the given regex pattern.
+ """
+ # Never go more than this amount of lines backwards for synchronisation.
+ # That would be too CPU intensive.
+ MAX_BACKWARDS = 500
+
+ # Start lexing at the start, if we are in the first 'n' lines and no
+ # synchronisation position was found.
+ FROM_START_IF_NO_SYNC_POS_FOUND = 100
+
+ def __init__(self, pattern):
+ assert isinstance(pattern, six.text_type)
+ self._compiled_pattern = re.compile(pattern)
+
+ def get_sync_start_position(self, document, lineno):
+ " Scan backwards, and find a possible position to start. "
+ pattern = self._compiled_pattern
+ lines = document.lines
+
+ # Scan upwards, until we find a point where we can start the syntax
+ # synchronisation.
+ for i in range(lineno, max(-1, lineno - self.MAX_BACKWARDS), -1):
+ match = pattern.match(lines[i])
+ if match:
+ return i, match.start()
+
+ # No synchronisation point found. If we aren't that far from the
+ # beginning, start at the very beginning, otherwise, just try to start
+ # at the current line.
+ if lineno < self.FROM_START_IF_NO_SYNC_POS_FOUND:
+ return 0, 0
+ else:
+ return lineno, 0
+
+ @classmethod
+ def from_pygments_lexer_cls(cls, lexer_cls):
+ """
+ Create a :class:`.RegexSync` instance for this Pygments lexer class.
+ """
+ patterns = {
+ # For Python, start highlighting at any class/def block.
+ 'Python': r'^\s*(class|def)\s+',
+ 'Python 3': r'^\s*(class|def)\s+',
+
+ # For HTML, start at any open/close tag definition.
+ 'HTML': r'<[/a-zA-Z]',
+
+ # For javascript, start at a function.
+ 'JavaScript': r'\bfunction\b'
+
+ # TODO: Add definitions for other languages.
+ # By default, we start at every possible line.
+ }
+ p = patterns.get(lexer_cls.name, '^')
+ return cls(p)
+
+
class PygmentsLexer(Lexer):
"""
Lexer that calls a pygments lexer.
-
+
Example::
from pygments.lexers import HtmlLexer
@@ -161,32 +161,32 @@ class PygmentsLexer(Lexer):
from pygments.styles import get_style_by_name
style = style_from_pygments(get_style_by_name('monokai'))
- :param pygments_lexer_cls: A `Lexer` from Pygments.
- :param sync_from_start: Start lexing at the start of the document. This
- will always give the best results, but it will be slow for bigger
- documents. (When the last part of the document is display, then the
- whole document will be lexed by Pygments on every key stroke.) It is
- recommended to disable this for inputs that are expected to be more
- than 1,000 lines.
- :param syntax_sync: `SyntaxSync` object.
+ :param pygments_lexer_cls: A `Lexer` from Pygments.
+ :param sync_from_start: Start lexing at the start of the document. This
+ will always give the best results, but it will be slow for bigger
+ documents. (When the last part of the document is display, then the
+ whole document will be lexed by Pygments on every key stroke.) It is
+ 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
- # scroll offset in the `Window` class, lines are not always retrieved in
- # order.)
- MIN_LINES_BACKWARDS = 50
-
- # When a parser was started this amount of lines back, read the parser
- # until we get the current line. Otherwise, start a new parser.
- # (This should probably be bigger than MIN_LINES_BACKWARDS.)
- REUSE_GENERATOR_MAX_DISTANCE = 100
-
- def __init__(self, pygments_lexer_cls, sync_from_start=True, syntax_sync=None):
- assert syntax_sync is None or isinstance(syntax_sync, SyntaxSync)
-
+ # 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
+ # scroll offset in the `Window` class, lines are not always retrieved in
+ # order.)
+ MIN_LINES_BACKWARDS = 50
+
+ # When a parser was started this amount of lines back, read the parser
+ # until we get the current line. Otherwise, start a new parser.
+ # (This should probably be bigger than MIN_LINES_BACKWARDS.)
+ REUSE_GENERATOR_MAX_DISTANCE = 100
+
+ 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.sync_from_start = to_cli_filter(sync_from_start)
+ self.sync_from_start = to_cli_filter(sync_from_start)
# Instantiate the Pygments lexer.
self.pygments_lexer = pygments_lexer_cls(
@@ -194,127 +194,127 @@ class PygmentsLexer(Lexer):
stripall=False,
ensurenl=False)
- # Create syntax sync instance.
- self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls)
-
- @classmethod
- def from_filename(cls, filename, sync_from_start=True):
- """
- Create a `Lexer` from a filename.
- """
- # Inline imports: the Pygments dependency is optional!
- from pygments.util import ClassNotFound
- from pygments.lexers import get_lexer_for_filename
-
- try:
- pygments_lexer = get_lexer_for_filename(filename)
- except ClassNotFound:
- return SimpleLexer()
- else:
- return cls(pygments_lexer.__class__, sync_from_start=sync_from_start)
-
- def lex_document(self, cli, document):
- """
- Create a lexer function that takes a line number and returns the list
- of (Token, text) tuples as the Pygments lexer returns for that line.
- """
- # Cache of already lexed lines.
- cache = {}
-
- # Pygments generators that are currently lexing.
- line_generators = {} # Map lexer generator to the line number.
-
- def get_syntax_sync():
- " The Syntax synchronisation objcet that we currently use. "
- if self.sync_from_start(cli):
- return SyncFromStart()
- else:
- return self.syntax_sync
-
- def find_closest_generator(i):
- " Return a generator close to line 'i', or None if none was fonud. "
- for generator, lineno in line_generators.items():
- if lineno < i and i - lineno < self.REUSE_GENERATOR_MAX_DISTANCE:
- return generator
-
- def create_line_generator(start_lineno, column=0):
- """
- Create a generator that yields the lexed lines.
- Each iteration it yields a (line_number, [(token, text), ...]) tuple.
- """
- def get_tokens():
- text = '\n'.join(document.lines[start_lineno:])[column:]
-
- # We call `get_tokens_unprocessed`, because `get_tokens` will
- # still replace \r\n and \r by \n. (We don't want that,
- # Pygments should return exactly the same amount of text, as we
- # have given as input.)
- for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text):
- yield t, v
-
- return enumerate(split_lines(get_tokens()), start_lineno)
-
- def get_generator(i):
- """
- Find an already started generator that is close, or create a new one.
- """
- # Find closest line generator.
- generator = find_closest_generator(i)
- if generator:
- return generator
-
- # No generator found. Determine starting point for the syntax
- # synchronisation first.
-
- # Go at least x lines back. (Make scrolling upwards more
- # efficient.)
- i = max(0, i - self.MIN_LINES_BACKWARDS)
-
- if i == 0:
- row = 0
- column = 0
- else:
- row, column = get_syntax_sync().get_sync_start_position(document, i)
-
- # Find generator close to this point, or otherwise create a new one.
- generator = find_closest_generator(i)
- if generator:
- return generator
- else:
- generator = create_line_generator(row, column)
-
- # If the column is not 0, ignore the first line. (Which is
- # incomplete. This happens when the synchronisation algorithm tells
- # us to start parsing in the middle of a line.)
- if column:
- next(generator)
- row += 1
-
- line_generators[generator] = row
- return generator
-
- def get_line(i):
- " Return the tokens for a given line number. "
- try:
- return cache[i]
- except KeyError:
- generator = get_generator(i)
-
- # Exhaust the generator, until we find the requested line.
- for num, line in generator:
- cache[num] = line
- if num == i:
- line_generators[generator] = i
-
- # Remove the next item from the cache.
- # (It could happen that it's already there, because of
- # another generator that started filling these lines,
- # but we want to synchronise these lines with the
- # current lexer's state.)
- if num + 1 in cache:
- del cache[num + 1]
-
- return cache[num]
- return []
-
- return get_line
+ # Create syntax sync instance.
+ self.syntax_sync = syntax_sync or RegexSync.from_pygments_lexer_cls(pygments_lexer_cls)
+
+ @classmethod
+ def from_filename(cls, filename, sync_from_start=True):
+ """
+ Create a `Lexer` from a filename.
+ """
+ # Inline imports: the Pygments dependency is optional!
+ from pygments.util import ClassNotFound
+ from pygments.lexers import get_lexer_for_filename
+
+ try:
+ pygments_lexer = get_lexer_for_filename(filename)
+ except ClassNotFound:
+ return SimpleLexer()
+ else:
+ return cls(pygments_lexer.__class__, sync_from_start=sync_from_start)
+
+ def lex_document(self, cli, document):
+ """
+ Create a lexer function that takes a line number and returns the list
+ of (Token, text) tuples as the Pygments lexer returns for that line.
+ """
+ # Cache of already lexed lines.
+ cache = {}
+
+ # Pygments generators that are currently lexing.
+ line_generators = {} # Map lexer generator to the line number.
+
+ def get_syntax_sync():
+ " The Syntax synchronisation objcet that we currently use. "
+ if self.sync_from_start(cli):
+ return SyncFromStart()
+ else:
+ return self.syntax_sync
+
+ def find_closest_generator(i):
+ " Return a generator close to line 'i', or None if none was fonud. "
+ for generator, lineno in line_generators.items():
+ if lineno < i and i - lineno < self.REUSE_GENERATOR_MAX_DISTANCE:
+ return generator
+
+ def create_line_generator(start_lineno, column=0):
+ """
+ Create a generator that yields the lexed lines.
+ Each iteration it yields a (line_number, [(token, text), ...]) tuple.
+ """
+ def get_tokens():
+ text = '\n'.join(document.lines[start_lineno:])[column:]
+
+ # We call `get_tokens_unprocessed`, because `get_tokens` will
+ # still replace \r\n and \r by \n. (We don't want that,
+ # Pygments should return exactly the same amount of text, as we
+ # have given as input.)
+ for _, t, v in self.pygments_lexer.get_tokens_unprocessed(text):
+ yield t, v
+
+ return enumerate(split_lines(get_tokens()), start_lineno)
+
+ def get_generator(i):
+ """
+ Find an already started generator that is close, or create a new one.
+ """
+ # Find closest line generator.
+ generator = find_closest_generator(i)
+ if generator:
+ return generator
+
+ # No generator found. Determine starting point for the syntax
+ # synchronisation first.
+
+ # Go at least x lines back. (Make scrolling upwards more
+ # efficient.)
+ i = max(0, i - self.MIN_LINES_BACKWARDS)
+
+ if i == 0:
+ row = 0
+ column = 0
+ else:
+ row, column = get_syntax_sync().get_sync_start_position(document, i)
+
+ # Find generator close to this point, or otherwise create a new one.
+ generator = find_closest_generator(i)
+ if generator:
+ return generator
+ else:
+ generator = create_line_generator(row, column)
+
+ # If the column is not 0, ignore the first line. (Which is
+ # incomplete. This happens when the synchronisation algorithm tells
+ # us to start parsing in the middle of a line.)
+ if column:
+ next(generator)
+ row += 1
+
+ line_generators[generator] = row
+ return generator
+
+ def get_line(i):
+ " Return the tokens for a given line number. "
+ try:
+ return cache[i]
+ except KeyError:
+ generator = get_generator(i)
+
+ # Exhaust the generator, until we find the requested line.
+ for num, line in generator:
+ cache[num] = line
+ if num == i:
+ line_generators[generator] = i
+
+ # Remove the next item from the cache.
+ # (It could happen that it's already there, because of
+ # another generator that started filling these lines,
+ # but we want to synchronise these lines with the
+ # current lexer's state.)
+ if num + 1 in cache:
+ del cache[num + 1]
+
+ return cache[num]
+ return []
+
+ return get_line
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 2934dfc9a7..1c596094d6 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/margins.py
@@ -3,21 +3,21 @@ Margin implementations for a :class:`~prompt_toolkit.layout.containers.Window`.
"""
from __future__ import unicode_literals
-from abc import ABCMeta, abstractmethod
+from abc import ABCMeta, abstractmethod
from six import with_metaclass
-from six.moves import range
+from six.moves import range
from prompt_toolkit.filters import to_cli_filter
-from prompt_toolkit.token import Token
-from prompt_toolkit.utils import get_cwidth
-from .utils import token_list_to_text
+from prompt_toolkit.token import Token
+from prompt_toolkit.utils import get_cwidth
+from .utils import token_list_to_text
__all__ = (
'Margin',
'NumberredMargin',
'ScrollbarMargin',
'ConditionalMargin',
- 'PromptMargin',
+ 'PromptMargin',
)
@@ -26,14 +26,14 @@ class Margin(with_metaclass(ABCMeta, object)):
Base interface for a margin.
"""
@abstractmethod
- def get_width(self, cli, get_ui_content):
+ def get_width(self, cli, get_ui_content):
"""
Return the width that this margin is going to consume.
-
- :param cli: :class:`.CommandLineInterface` instance.
- :param get_ui_content: Callable that asks the user control to create
- a :class:`.UIContent` instance. This can be used for instance to
- obtain the number of lines.
+
+ :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
@@ -43,7 +43,7 @@ class Margin(with_metaclass(ABCMeta, object)):
Creates a margin.
This should return a list of (Token, text) tuples.
- :param cli: :class:`.CommandLineInterface` instance.
+ :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
@@ -63,16 +63,16 @@ class NumberredMargin(Margin):
: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.
+ :param display_tildes: Display tildes after the end of the document, just
+ like Vi does.
"""
- def __init__(self, relative=False, display_tildes=False):
+ def __init__(self, relative=False, display_tildes=False):
self.relative = to_cli_filter(relative)
- self.display_tildes = to_cli_filter(display_tildes)
+ 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 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)
@@ -81,40 +81,40 @@ class NumberredMargin(Margin):
token_current = Token.LineNumber.Current
# Get current line number.
- current_lineno = window_render_info.ui_content.cursor_position.y
+ current_lineno = window_render_info.ui_content.cursor_position.y
# Construct margin.
result = []
- last_lineno = None
-
- for y, lineno in enumerate(window_render_info.displayed_lines):
- # Only display line number if this line is not a continuation of the previous line.
- if lineno != last_lineno:
- if lineno is None:
- pass
- elif lineno == current_lineno:
+ last_lineno = None
+
+ for y, lineno in enumerate(window_render_info.displayed_lines):
+ # Only display line number if this line is not a continuation of the previous line.
+ if lineno != last_lineno:
+ if lineno is None:
+ pass
+ elif lineno == current_lineno:
# Current line.
if relative:
# Left align current number in relative mode.
- result.append((token_current, '%i' % (lineno + 1)))
+ result.append((token_current, '%i' % (lineno + 1)))
else:
- result.append((token_current, ('%i ' % (lineno + 1)).rjust(width)))
+ result.append((token_current, ('%i ' % (lineno + 1)).rjust(width)))
else:
# Other lines.
if relative:
- lineno = abs(lineno - current_lineno) - 1
+ lineno = abs(lineno - current_lineno) - 1
- result.append((token, ('%i ' % (lineno + 1)).rjust(width)))
+ result.append((token, ('%i ' % (lineno + 1)).rjust(width)))
- last_lineno = lineno
+ last_lineno = lineno
result.append((Token, '\n'))
- # Fill with tildes.
- if self.display_tildes(cli):
- while y < window_render_info.window_height:
- result.append((Token.Tilde, '~\n'))
- y += 1
-
+ # Fill with tildes.
+ if self.display_tildes(cli):
+ while y < window_render_info.window_height:
+ result.append((Token.Tilde, '~\n'))
+ y += 1
+
return result
@@ -128,9 +128,9 @@ class ConditionalMargin(Margin):
self.margin = margin
self.filter = to_cli_filter(filter)
- def get_width(self, cli, ui_content):
+ def get_width(self, cli, ui_content):
if self.filter(cli):
- return self.margin.get_width(cli, ui_content)
+ return self.margin.get_width(cli, ui_content)
else:
return 0
@@ -144,110 +144,110 @@ class ConditionalMargin(Margin):
class ScrollbarMargin(Margin):
"""
Margin displaying a scrollbar.
-
- :param display_arrows: Display scroll up/down arrows.
+
+ :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):
+ def __init__(self, display_arrows=False):
+ self.display_arrows = to_cli_filter(display_arrows)
+
+ def get_width(self, cli, ui_content):
return 1
def create_margin(self, cli, window_render_info, width, height):
total_height = window_render_info.content_height
- display_arrows = self.display_arrows(cli)
-
- window_height = window_render_info.window_height
- if display_arrows:
- window_height -= 2
-
- try:
- items_per_row = float(total_height) / min(total_height, window_height)
- except ZeroDivisionError:
- return []
- else:
- def is_scroll_button(row):
- " True if we should display a button on this row. "
- current_row_middle = int((row + .5) * items_per_row)
- return current_row_middle in window_render_info.displayed_lines
-
- # Up arrow.
- result = []
- if display_arrows:
- result.extend([
- (Token.Scrollbar.Arrow, '^'),
- (Token.Scrollbar, '\n')
- ])
-
- # Scrollbar body.
- for i in range(window_height):
- if is_scroll_button(i):
- result.append((Token.Scrollbar.Button, ' '))
- else:
- result.append((Token.Scrollbar, ' '))
- result.append((Token, '\n'))
-
- # Down arrow
- if display_arrows:
- result.append((Token.Scrollbar.Arrow, 'v'))
-
- return result
-
-
-class PromptMargin(Margin):
- """
- Create margin that displays a prompt.
- This can display one prompt at the first line, and a continuation prompt
- (e.g, just dots) on all the following lines.
-
- :param get_prompt_tokens: Callable that takes a CommandLineInterface as
- input and returns a list of (Token, type) tuples to be shown as the
- prompt at the first line.
- :param get_continuation_tokens: Callable that takes a CommandLineInterface
- and a width as input and returns a list of (Token, type) tuples for the
- next lines of the input.
- :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`)
- Display line numbers instead of the continuation prompt.
- """
- def __init__(self, get_prompt_tokens, get_continuation_tokens=None,
- show_numbers=False):
- assert callable(get_prompt_tokens)
- assert get_continuation_tokens is None or callable(get_continuation_tokens)
- show_numbers = to_cli_filter(show_numbers)
-
- self.get_prompt_tokens = get_prompt_tokens
- self.get_continuation_tokens = get_continuation_tokens
- self.show_numbers = show_numbers
-
- def get_width(self, cli, ui_content):
- " Width to report to the `Window`. "
- # Take the width from the first line.
- text = token_list_to_text(self.get_prompt_tokens(cli))
- return get_cwidth(text)
-
- def create_margin(self, cli, window_render_info, width, height):
- # First line.
- tokens = self.get_prompt_tokens(cli)[:]
-
- # Next lines. (Show line numbering when numbering is enabled.)
- if self.get_continuation_tokens:
+ display_arrows = self.display_arrows(cli)
+
+ window_height = window_render_info.window_height
+ if display_arrows:
+ window_height -= 2
+
+ try:
+ items_per_row = float(total_height) / min(total_height, window_height)
+ except ZeroDivisionError:
+ return []
+ else:
+ def is_scroll_button(row):
+ " True if we should display a button on this row. "
+ current_row_middle = int((row + .5) * items_per_row)
+ return current_row_middle in window_render_info.displayed_lines
+
+ # Up arrow.
+ result = []
+ if display_arrows:
+ result.extend([
+ (Token.Scrollbar.Arrow, '^'),
+ (Token.Scrollbar, '\n')
+ ])
+
+ # Scrollbar body.
+ for i in range(window_height):
+ if is_scroll_button(i):
+ result.append((Token.Scrollbar.Button, ' '))
+ else:
+ result.append((Token.Scrollbar, ' '))
+ result.append((Token, '\n'))
+
+ # Down arrow
+ if display_arrows:
+ result.append((Token.Scrollbar.Arrow, 'v'))
+
+ return result
+
+
+class PromptMargin(Margin):
+ """
+ Create margin that displays a prompt.
+ This can display one prompt at the first line, and a continuation prompt
+ (e.g, just dots) on all the following lines.
+
+ :param get_prompt_tokens: Callable that takes a CommandLineInterface as
+ input and returns a list of (Token, type) tuples to be shown as the
+ prompt at the first line.
+ :param get_continuation_tokens: Callable that takes a CommandLineInterface
+ and a width as input and returns a list of (Token, type) tuples for the
+ next lines of the input.
+ :param show_numbers: (bool or :class:`~prompt_toolkit.filters.CLIFilter`)
+ Display line numbers instead of the continuation prompt.
+ """
+ def __init__(self, get_prompt_tokens, get_continuation_tokens=None,
+ show_numbers=False):
+ assert callable(get_prompt_tokens)
+ assert get_continuation_tokens is None or callable(get_continuation_tokens)
+ show_numbers = to_cli_filter(show_numbers)
+
+ self.get_prompt_tokens = get_prompt_tokens
+ self.get_continuation_tokens = get_continuation_tokens
+ self.show_numbers = show_numbers
+
+ def get_width(self, cli, ui_content):
+ " Width to report to the `Window`. "
+ # Take the width from the first line.
+ text = token_list_to_text(self.get_prompt_tokens(cli))
+ return get_cwidth(text)
+
+ def create_margin(self, cli, window_render_info, width, height):
+ # First line.
+ tokens = self.get_prompt_tokens(cli)[:]
+
+ # Next lines. (Show line numbering when numbering is enabled.)
+ if self.get_continuation_tokens:
# Note: we turn this into a list, to make sure that we fail early
# in case `get_continuation_tokens` returns something else,
# like `None`.
tokens2 = list(self.get_continuation_tokens(cli, width))
- else:
- tokens2 = []
-
- show_numbers = self.show_numbers(cli)
- last_y = None
-
- for y in window_render_info.displayed_lines[1:]:
- tokens.append((Token, '\n'))
- if show_numbers:
- if y != last_y:
- tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width)))
+ else:
+ tokens2 = []
+
+ show_numbers = self.show_numbers(cli)
+ last_y = None
+
+ for y in window_render_info.displayed_lines[1:]:
+ tokens.append((Token, '\n'))
+ if show_numbers:
+ if y != last_y:
+ tokens.append((Token.LineNumber, ('%i ' % (y + 1)).rjust(width)))
else:
- tokens.extend(tokens2)
- last_y = y
+ tokens.extend(tokens2)
+ last_y = y
- return tokens
+ 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 a916846e45..8883d0594e 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/menus.py
@@ -1,16 +1,16 @@
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 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 .containers import Window, HSplit, ConditionalContainer, ScrollOffsets
-from .controls import UIControl, UIContent
+from .containers import Window, HSplit, ConditionalContainer, ScrollOffsets
+from .controls import UIControl, UIContent
from .dimension import LayoutDimension
-from .margins import ScrollbarMargin
-from .screen import Point, Char
+from .margins import ScrollbarMargin
+from .screen import Point, Char
import math
@@ -29,12 +29,12 @@ class CompletionsMenuControl(UIControl):
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
+ # 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):
+ def __init__(self):
self.token = Token.Menu.Completions
def has_focus(self, cli):
@@ -46,20 +46,20 @@ class CompletionsMenuControl(UIControl):
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
+ return menu_width + menu_meta_width
else:
return 0
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
+ 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
- def create_content(self, cli, width, height):
+ def create_content(self, cli, width, height):
"""
- Create a UIContent object for this control.
+ Create a UIContent object for this control.
"""
complete_state = cli.current_buffer.complete_state
if complete_state:
@@ -67,25 +67,25 @@ class CompletionsMenuControl(UIControl):
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)
+ 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)
- def get_line(i):
- c = completions[i]
- is_current_completion = (i == index)
- result = self._get_menu_item_tokens(c, is_current_completion, menu_width)
+ 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
+ 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(get_line=get_line,
+ cursor_position=Point(x=0, y=index or 0),
+ line_count=len(completions),
+ default_char=Char(' ', self.token))
- return UIContent()
+ return UIContent()
def _show_meta(self, complete_state):
"""
@@ -97,8 +97,8 @@ class CompletionsMenuControl(UIControl):
"""
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))
+ 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):
"""
@@ -136,16 +136,16 @@ class CompletionsMenuControl(UIControl):
"""
b = cli.current_buffer
- if mouse_event.event_type == MouseEventType.MOUSE_UP:
+ if mouse_event.event_type == MouseEventType.MOUSE_UP:
# Select completion.
- b.go_to_completion(mouse_event.position.y)
+ b.go_to_completion(mouse_event.position.y)
b.complete_state = None
- elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
+ elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
# Scroll up.
b.complete_next(count=3, disable_wrap_around=True)
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
+ elif mouse_event.event_type == MouseEventType.SCROLL_UP:
# Scroll down.
b.complete_previous(count=3, disable_wrap_around=True)
@@ -179,19 +179,19 @@ def _trim_text(text, max_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)
-
+ 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(
- content=CompletionsMenuControl(),
+ content=CompletionsMenuControl(),
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,
- ),
+ 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)
@@ -260,7 +260,7 @@ class MultiColumnCompletionMenuControl(UIControl):
result -= column_width
return result + self._required_margin
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
+ def preferred_height(self, cli, width, max_available_height, wrap_lines):
"""
Preferred height: as much as needed in order to display all the completions.
"""
@@ -270,9 +270,9 @@ class MultiColumnCompletionMenuControl(UIControl):
return int(math.ceil(len(complete_state.current_completions) / float(column_count)))
- def create_content(self, cli, width, height):
+ def create_content(self, cli, width, height):
"""
- Create a UIContent object for this menu.
+ Create a UIContent object for this menu.
"""
complete_state = cli.current_buffer.complete_state
column_width = self._get_column_width(complete_state)
@@ -316,15 +316,15 @@ class MultiColumnCompletionMenuControl(UIControl):
render_right_arrow = self.scroll < len(rows_[0]) - visible_columns
# Write completions to screen.
- tokens_for_line = []
+ tokens_for_line = []
for row_index, row in enumerate(rows_):
- tokens = []
+ tokens = []
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 ' ')]
+ tokens += [(Token.Scrollbar, '<' if middle_row else ' ')]
# Draw row content.
for column_index, c in enumerate(row[self.scroll:][:visible_columns]):
@@ -342,13 +342,13 @@ class MultiColumnCompletionMenuControl(UIControl):
# Draw right arrow if we have hidden completions on the right.
if render_right_arrow:
- tokens += [(Token.Scrollbar, '>' if middle_row else ' ')]
+ tokens += [(Token.Scrollbar, '>' if middle_row else ' ')]
# Newline.
- tokens_for_line.append(tokens)
+ tokens_for_line.append(tokens)
- else:
- tokens = []
+ else:
+ tokens = []
self._rendered_rows = height
self._rendered_columns = visible_columns
@@ -357,11 +357,11 @@ class MultiColumnCompletionMenuControl(UIControl):
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_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.
@@ -393,13 +393,13 @@ class MultiColumnCompletionMenuControl(UIControl):
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:
+ if mouse_event.event_type == MouseEventType.SCROLL_DOWN:
scroll_right()
- elif mouse_event.event_type == MouseEventType.SCROLL_UP:
+ elif mouse_event.event_type == MouseEventType.SCROLL_UP:
scroll_left()
- elif mouse_event.event_type == MouseEventType.MOUSE_UP:
+ elif mouse_event.event_type == MouseEventType.MOUSE_UP:
x = mouse_event.position.x
y = mouse_event.position.y
@@ -475,17 +475,17 @@ class _SelectedCompletionMetaControl(UIControl):
else:
return 0
- def preferred_height(self, cli, width, max_available_height, wrap_lines):
+ def preferred_height(self, cli, width, max_available_height, wrap_lines):
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 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
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 0b8bc9c223..fc3e29a089 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py
@@ -8,20 +8,20 @@ token types.
from __future__ import unicode_literals
from abc import ABCMeta, abstractmethod
from six import with_metaclass
-from six.moves import range
+from six.moves import range
-from prompt_toolkit.cache import SimpleCache
+from prompt_toolkit.cache import SimpleCache
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.filters import to_cli_filter, ViInsertMultipleMode
from prompt_toolkit.layout.utils import token_list_to_text
-from prompt_toolkit.reactive import Integer
-from prompt_toolkit.token import Token
+from prompt_toolkit.reactive import Integer
+from prompt_toolkit.token import Token
-from .utils import token_list_len, explode_tokens
-
-import re
+from .utils import token_list_len, explode_tokens
+import re
+
__all__ = (
'Processor',
'Transformation',
@@ -29,37 +29,37 @@ __all__ = (
'HighlightSearchProcessor',
'HighlightSelectionProcessor',
'PasswordProcessor',
- 'HighlightMatchingBracketProcessor',
- 'DisplayMultipleCursors',
+ 'HighlightMatchingBracketProcessor',
+ 'DisplayMultipleCursors',
'BeforeInput',
'AfterInput',
'AppendAutoSuggestion',
'ConditionalProcessor',
'ShowLeadingWhiteSpaceProcessor',
'ShowTrailingWhiteSpaceProcessor',
- 'TabsProcessor',
+ 'TabsProcessor',
)
class Processor(with_metaclass(ABCMeta, object)):
"""
- Manipulate the tokens for a given line in a
+ Manipulate the tokens for a given line in a
:class:`~prompt_toolkit.layout.controls.BufferControl`.
"""
@abstractmethod
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
"""
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.
- :param source_to_display: A function that returns the position in the
- `tokens` for any position in the source string. (This takes
- previous processors into account.)
- :param tokens: List of tokens that we can transform. (Received from the
- previous processor.)
+
+ :param cli: :class:`.CommandLineInterface` instance.
+ :param lineno: The number of the line to which we apply the processor.
+ :param source_to_display: A function that returns the position in the
+ `tokens` for any position in the source string. (This takes
+ previous processors into account.)
+ :param tokens: List of tokens that we can transform. (Received from the
+ previous processor.)
"""
- return Transformation(tokens)
+ return Transformation(tokens)
def has_focus(self, cli):
"""
@@ -83,26 +83,26 @@ class Transformation(object):
: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):
+ 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)
-class HighlightSearchProcessor(Processor):
+class HighlightSearchProcessor(Processor):
"""
Processor that highlights search matches in the document.
- Note that this doesn't support multiline search matches yet.
+ 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.
"""
- def __init__(self, preview_search=False, search_buffer_name=SEARCH_BUFFER,
- get_search_state=None):
+ 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.get_search_state = get_search_state or (lambda cli: cli.search_state)
+ self.get_search_state = get_search_state or (lambda cli: cli.search_state)
def _get_search_text(self, cli):
"""
@@ -113,70 +113,70 @@ class HighlightSearchProcessor(Processor):
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
+ return self.get_search_state(cli).text
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
search_text = self._get_search_text(cli)
- searchmatch_current_token = (':', ) + Token.SearchMatch.Current
- searchmatch_token = (':', ) + Token.SearchMatch
+ 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.
- line_text = token_list_to_text(tokens)
- tokens = explode_tokens(tokens)
+ line_text = token_list_to_text(tokens)
+ tokens = explode_tokens(tokens)
- flags = re.IGNORECASE if cli.is_ignoring_case else 0
+ 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
+ # 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 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])
+ 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)
+ return Transformation(tokens)
-class HighlightSelectionProcessor(Processor):
+class HighlightSelectionProcessor(Processor):
"""
Processor that highlights the selection in the document.
"""
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- selected_token = (':', ) + Token.SelectedText
-
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ selected_token = (':', ) + Token.SelectedText
+
# In case of selection, highlight all matches.
- selection_at_line = document.selection_range_at_line(lineno)
+ 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)
+ if selection_at_line:
+ from_, to = selection_at_line
+ from_ = source_to_display(from_)
+ to = source_to_display(to)
- tokens = explode_tokens(tokens)
+ 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.
- return Transformation([(Token.SelectedText, ' ')])
- else:
- for i in range(from_, to + 1):
- if i < len(tokens):
- old_token, old_text = tokens[i]
- tokens[i] = (old_token + selected_token, old_text)
+ 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.
+ return Transformation([(Token.SelectedText, ' ')])
+ else:
+ for i in range(from_, to + 1):
+ if i < len(tokens):
+ old_token, old_text = tokens[i]
+ tokens[i] = (old_token + selected_token, old_text)
- return Transformation(tokens)
+ return Transformation(tokens)
class PasswordProcessor(Processor):
@@ -188,121 +188,121 @@ class PasswordProcessor(Processor):
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)
+ 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):
+class HighlightMatchingBracketProcessor(Processor):
"""
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.)
+
+ :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 = '])}>'
- def __init__(self, chars='[](){}<>', max_cursor_distance=1000):
+ def __init__(self, chars='[](){}<>', max_cursor_distance=1000):
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.
- """
- # Try for the character under the cursor.
- if document.current_char and document.current_char in self.chars:
- 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.
- row, col = document.translate_index_to_position(pos)
- 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:
- if row == lineno:
- 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):
+ 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.
+ """
+ # Try for the character under the cursor.
+ if document.current_char and document.current_char in self.chars:
+ 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.
+ row, col = document.translate_index_to_position(pos)
+ 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:
+ if row == lineno:
+ 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.
+ When we're in Vi block insert mode, display all the cursors.
"""
- _insert_multiple = ViInsertMultipleMode()
+ _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]
+ def __init__(self, buffer_name):
+ self.buffer_name = buffer_name
- if self._insert_multiple(cli):
- positions = buff.multiple_cursor_positions
- tokens = explode_tokens(tokens)
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ buff = cli.buffers[self.buffer_name]
- # 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])
+ if self._insert_multiple(cli):
+ positions = buff.multiple_cursor_positions
+ tokens = explode_tokens(tokens)
- token_suffix = (':', ) + Token.MultipleCursors.Cursor
+ # 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])
- for p in positions:
- if start_pos <= p < end_pos:
- column = source_to_display(p - start_pos)
+ token_suffix = (':', ) + Token.MultipleCursors.Cursor
- # 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)
+ 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.
@@ -315,21 +315,21 @@ class BeforeInput(Processor):
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)
-
+ 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):
"""
@@ -357,12 +357,12 @@ class AfterInput(Processor):
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)
+ 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):
@@ -397,171 +397,171 @@ class AppendAutoSuggestion(Processor):
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)])
+ 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:
- return Transformation(tokens=tokens)
+ return Transformation(tokens=tokens)
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.
+
+ :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)
-
- if get_char is None:
- def get_char(cli):
- if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
- return '.'
- else:
- return '\xb7'
-
+ def __init__(self, get_char=None, token=Token.LeadingWhiteSpace):
+ assert get_char is None or callable(get_char)
+
+ if get_char is None:
+ def get_char(cli):
+ if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
+ return '.'
+ else:
+ return '\xb7'
+
self.token = token
- self.get_char = get_char
+ self.get_char = get_char
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ def apply_transformation(self, cli, document, lineno, source_to_display, 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)
+ 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
+ for i in range(len(tokens)):
+ if tokens[i][1] == ' ':
+ tokens[i] = t
+ else:
+ break
- return Transformation(tokens)
+ return Transformation(tokens)
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)
-
- if get_char is None:
- def get_char(cli):
- if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
- return '.'
- else:
- return '\xb7'
-
- 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))
- tokens = explode_tokens(tokens)
-
- # Walk backwards through all te tokens and replace whitespace.
- for i in range(len(tokens) - 1, -1, -1):
- char = tokens[i][1]
- if char == ' ':
- tokens[i] = t
- else:
- break
-
- return Transformation(tokens)
-
-
-class TabsProcessor(Processor):
+
+ :param get_char: Callable that takes a :class:`CommandLineInterface`
+ instance and returns one character.
+ :param token: Token to be used.
"""
- Render tabs as spaces (instead of ^I) or make them visible (for instance,
- by replacing them with dots.)
-
- :param tabstop: (Integer) Horizontal space taken by a tab.
- :param get_char1: Callable that takes a `CommandLineInterface` and return a
- character (text of length one). This one is used for the first space
- taken by the tab.
- :param get_char2: Like `get_char1`, but for the rest of the space.
- """
- def __init__(self, tabstop=4, get_char1=None, get_char2=None, token=Token.Tab):
- assert isinstance(tabstop, Integer)
- assert get_char1 is None or callable(get_char1)
- assert get_char2 is None or callable(get_char2)
-
- self.get_char1 = get_char1 or get_char2 or (lambda cli: '|')
- self.get_char2 = get_char2 or get_char1 or (lambda cli: '\u2508')
- self.tabstop = tabstop
+ def __init__(self, get_char=None, token=Token.TrailingWhiteSpace):
+ assert get_char is None or callable(get_char)
+
+ if get_char is None:
+ def get_char(cli):
+ if '\xb7'.encode(cli.output.encoding(), 'replace') == b'?':
+ return '.'
+ else:
+ return '\xb7'
+
self.token = token
-
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
- tabstop = int(self.tabstop)
- token = self.token
-
- # Create separator for tabs.
- separator1 = self.get_char1(cli)
- separator2 = self.get_char2(cli)
-
- # Transform tokens.
- tokens = explode_tokens(tokens)
-
- position_mappings = {}
- result_tokens = []
- pos = 0
-
- for i, token_and_text in enumerate(tokens):
- position_mappings[i] = pos
-
- if token_and_text[1] == '\t':
- # Calculate how many characters we have to insert.
- count = tabstop - (pos % tabstop)
- if count == 0:
- count = tabstop
-
- # Insert tab.
- result_tokens.append((token, separator1))
- result_tokens.append((token, separator2 * (count - 1)))
- pos += count
+ 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))
+ tokens = explode_tokens(tokens)
+
+ # Walk backwards through all te tokens and replace whitespace.
+ for i in range(len(tokens) - 1, -1, -1):
+ char = tokens[i][1]
+ if char == ' ':
+ tokens[i] = t
+ else:
+ break
+
+ return Transformation(tokens)
+
+
+class TabsProcessor(Processor):
+ """
+ Render tabs as spaces (instead of ^I) or make them visible (for instance,
+ by replacing them with dots.)
+
+ :param tabstop: (Integer) Horizontal space taken by a tab.
+ :param get_char1: Callable that takes a `CommandLineInterface` and return a
+ character (text of length one). This one is used for the first space
+ taken by the tab.
+ :param get_char2: Like `get_char1`, but for the rest of the space.
+ """
+ def __init__(self, tabstop=4, get_char1=None, get_char2=None, token=Token.Tab):
+ assert isinstance(tabstop, Integer)
+ assert get_char1 is None or callable(get_char1)
+ assert get_char2 is None or callable(get_char2)
+
+ self.get_char1 = get_char1 or get_char2 or (lambda cli: '|')
+ self.get_char2 = get_char2 or get_char1 or (lambda cli: '\u2508')
+ self.tabstop = tabstop
+ self.token = token
+
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ tabstop = int(self.tabstop)
+ token = self.token
+
+ # Create separator for tabs.
+ separator1 = self.get_char1(cli)
+ separator2 = self.get_char2(cli)
+
+ # Transform tokens.
+ tokens = explode_tokens(tokens)
+
+ position_mappings = {}
+ result_tokens = []
+ pos = 0
+
+ for i, token_and_text in enumerate(tokens):
+ position_mappings[i] = pos
+
+ if token_and_text[1] == '\t':
+ # Calculate how many characters we have to insert.
+ count = tabstop - (pos % tabstop)
+ if count == 0:
+ count = tabstop
+
+ # Insert tab.
+ result_tokens.append((token, separator1))
+ result_tokens.append((token, separator2 * (count - 1)))
+ pos += count
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())
-
- while display_pos >= 0:
- try:
- return position_mappings_reversed[display_pos]
- except KeyError:
- display_pos -= 1
- return 0
-
- return Transformation(
- result_tokens,
- source_to_display=source_to_display,
- display_to_source=display_to_source)
-
-
+ 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())
+
+ while display_pos >= 0:
+ try:
+ return position_mappings_reversed[display_pos]
+ except KeyError:
+ display_pos -= 1
+ return 0
+
+ return Transformation(
+ result_tokens,
+ source_to_display=source_to_display,
+ display_to_source=display_to_source)
+
+
class ConditionalProcessor(Processor):
"""
Processor that applies another processor, according to a certain condition.
@@ -586,13 +586,13 @@ class ConditionalProcessor(Processor):
self.processor = processor
self.filter = to_cli_filter(filter)
- def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
+ def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
# Run processor when enabled.
if self.filter(cli):
- return self.processor.apply_transformation(
- cli, document, lineno, source_to_display, tokens)
+ return self.processor.apply_transformation(
+ cli, document, lineno, source_to_display, tokens)
else:
- return Transformation(tokens)
+ return Transformation(tokens)
def has_focus(self, cli):
if self.filter(cli):
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 7d00ec513e..2a1373efbb 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/prompt.py
@@ -3,7 +3,7 @@ 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 prompt_toolkit.token import Token
from .utils import token_list_len
from .processors import Processor, Transformation
@@ -45,7 +45,7 @@ class DefaultPrompt(Processor):
return [(Token.Prompt, message)]
return cls(get_message_tokens)
- def apply_transformation(self, cli, document, lineno, source_to_display, 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)
@@ -59,11 +59,11 @@ class DefaultPrompt(Processor):
# 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)]
-
+ # 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,
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 95561f5de7..3e66f26500 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/screen.py
@@ -1,9 +1,9 @@
from __future__ import unicode_literals
-from prompt_toolkit.cache import FastDictCache
-from prompt_toolkit.token import Token
+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__ = (
@@ -61,7 +61,7 @@ class Char(object):
'\x1c': '^\\',
'\x1d': '^]',
'\x1f': '^_',
- '\x7f': '^?', # Backspace
+ '\x7f': '^?', # Backspace
}
def __init__(self, char=' ', token=Token):
@@ -87,7 +87,7 @@ class Char(object):
return '%s(%r, %r)' % (self.__class__.__name__, self.char, self.token)
-_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000)
+_CHAR_CACHE = FastDictCache(Char, size=1000 * 1000)
Transparent = Token.Transparent
@@ -97,13 +97,13 @@ class Screen(object):
"""
def __init__(self, default_char=None, initial_width=0, initial_height=0):
if default_char is None:
- default_char = _CHAR_CACHE[' ', Transparent]
+ default_char = _CHAR_CACHE[' ', Transparent]
self.data_buffer = defaultdict(lambda: defaultdict(lambda: default_char))
- #: Escape sequences to be injected.
- self.zero_width_escapes = defaultdict(lambda: defaultdict(lambda: ''))
-
+ #: 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)
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 2e77c2fa16..573e7db666 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/toolbars.py
@@ -4,15 +4,15 @@ from ..enums import IncrementalSearchDirection
from .processors import BeforeInput
-from .lexers import SimpleLexer
+from .lexers import SimpleLexer
from .dimension import LayoutDimension
-from .controls import BufferControl, TokenListControl, UIControl, UIContent
+from .controls import BufferControl, TokenListControl, UIControl, UIContent
from .containers import Window, ConditionalContainer
-from .screen import Char
+from .screen import Char
from .utils import token_list_len
-from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER
+from prompt_toolkit.enums import SEARCH_BUFFER, SYSTEM_BUFFER
from prompt_toolkit.filters import HasFocus, HasArg, HasCompletions, HasValidationError, HasSearch, Always, IsDone
-from prompt_toolkit.token import Token
+from prompt_toolkit.token import Token
__all__ = (
'TokenListToolbar',
@@ -35,13 +35,13 @@ class TokenListToolbar(ConditionalContainer):
class SystemToolbarControl(BufferControl):
def __init__(self):
- token = Token.Toolbar.System
-
+ token = Token.Toolbar.System
+
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)],)
+ default_char=Char(token=token),
+ lexer=SimpleLexer(token=token.Text),
+ input_processors=[BeforeInput.static('Shell command: ', token)],)
class SystemToolbar(ConditionalContainer):
@@ -56,13 +56,13 @@ class SystemToolbar(ConditionalContainer):
class ArgToolbarControl(TokenListControl):
def __init__(self):
def get_tokens(cli):
- arg = cli.input_processor.arg
- if arg == '-':
- arg = '-1'
-
+ arg = cli.input_processor.arg
+ if arg == '-':
+ arg = '-1'
+
return [
(Token.Toolbar.Arg, 'Repeat: '),
- (Token.Toolbar.Arg.Text, arg),
+ (Token.Toolbar.Arg.Text, arg),
]
super(ArgToolbarControl, self).__init__(get_tokens)
@@ -97,8 +97,8 @@ class SearchToolbarControl(BufferControl):
super(SearchToolbarControl, self).__init__(
buffer_name=SEARCH_BUFFER,
input_processors=[BeforeInput(get_before_input)],
- default_char=Char(token=token),
- lexer=SimpleLexer(token=token.Text))
+ default_char=Char(token=token),
+ lexer=SimpleLexer(token=token.Text))
class SearchToolbar(ConditionalContainer):
@@ -113,7 +113,7 @@ class SearchToolbar(ConditionalContainer):
class CompletionsToolbarControl(UIControl):
token = Token.Toolbar.Completions
- def create_content(self, cli, width, height):
+ def create_content(self, cli, width, height):
complete_state = cli.current_buffer.complete_state
if complete_state:
completions = complete_state.current_completions
@@ -161,12 +161,12 @@ class CompletionsToolbarControl(UIControl):
else:
all_tokens = []
- def get_line(i):
- return all_tokens
-
- return UIContent(get_line=get_line, line_count=1)
+ 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__(
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 a4fb7ed0f5..3fa16de535 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/utils.py
@@ -1,14 +1,14 @@
from __future__ import unicode_literals
from prompt_toolkit.utils import get_cwidth
-from prompt_toolkit.token import Token
+from prompt_toolkit.token import Token
__all__ = (
'token_list_len',
'token_list_width',
'token_list_to_text',
'explode_tokens',
- 'split_lines',
+ 'split_lines',
'find_window_for_buffer_name',
)
@@ -20,8 +20,8 @@ def token_list_len(tokenlist):
: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)
+ ZeroWidthEscape = Token.ZeroWidthEscape
+ return sum(len(item[1]) for item in tokenlist if item[0] != ZeroWidthEscape)
def token_list_width(tokenlist):
@@ -32,16 +32,16 @@ def token_list_width(tokenlist):
: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)
+ 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.
"""
- ZeroWidthEscape = Token.ZeroWidthEscape
- return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape)
+ ZeroWidthEscape = Token.ZeroWidthEscape
+ return ''.join(item[1] for item in tokenlist if item[0] != ZeroWidthEscape)
def iter_token_lines(tokenlist):
@@ -62,7 +62,7 @@ def iter_token_lines(tokenlist):
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.
+ line. Just like str.split, this will yield at least one item.
:param tokenlist: List of (token, text) or (token, text, mouse_handler)
tuples.
@@ -82,8 +82,8 @@ def split_lines(tokenlist):
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, '')].
+ # 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
@@ -100,67 +100,67 @@ def split_lines(tokenlist):
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'.
-
- As soon as items are added or the list is extended, the new items are
- automatically exploded as well.
- """
- def __init__(self, *a, **kw):
- super(_ExplodedList, self).__init__(*a, **kw)
- self.exploded = True
-
- def append(self, item):
- self.extend([item])
-
- def extend(self, lst):
- super(_ExplodedList, self).extend(explode_tokens(lst))
-
- def insert(self, index, item):
- raise NotImplementedError # TODO
-
- # TODO: When creating a copy() or [:], return also an _ExplodedList.
-
- def __setitem__(self, index, value):
- """
- Ensure that when `(Token, 'long string')` is set, the string will be
- exploded.
- """
- if not isinstance(index, slice):
- index = slice(index, index + 1)
- value = explode_tokens([value])
- super(_ExplodedList, self).__setitem__(index, value)
-
-
+ # 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'.
+
+ As soon as items are added or the list is extended, the new items are
+ automatically exploded as well.
+ """
+ def __init__(self, *a, **kw):
+ super(_ExplodedList, self).__init__(*a, **kw)
+ self.exploded = True
+
+ def append(self, item):
+ self.extend([item])
+
+ def extend(self, lst):
+ super(_ExplodedList, self).extend(explode_tokens(lst))
+
+ def insert(self, index, item):
+ raise NotImplementedError # TODO
+
+ # TODO: When creating a copy() or [:], return also an _ExplodedList.
+
+ def __setitem__(self, index, value):
+ """
+ Ensure that when `(Token, 'long string')` is set, the string will be
+ exploded.
+ """
+ if not isinstance(index, slice):
+ index = slice(index, index + 1)
+ value = explode_tokens([value])
+ 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.
- It should be fine to call this function several times. Calling this on a
- list that is already exploded, is a null operation.
-
+ 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.
"""
- # When the tokenlist is already exploded, don't explode again.
- if getattr(tokenlist, 'exploded', False):
- return tokenlist
-
+ # 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))
- return _ExplodedList(result)
+ return _ExplodedList(result)
def find_window_for_buffer_name(cli, buffer_name):