本文整理汇总了Python中prompt_toolkit.cache.SimpleCache类的典型用法代码示例。如果您正苦于以下问题:Python SimpleCache类的具体用法?Python SimpleCache怎么用?Python SimpleCache使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了SimpleCache类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: __init__
def __init__(self, get_tokens, default_char=None, get_default_char=None,
align_right=False, align_center=False, has_focus=False):
assert default_char is None or isinstance(default_char, Char)
assert get_default_char is None or callable(get_default_char)
assert not (default_char and get_default_char)
self.align_right = to_cli_filter(align_right)
self.align_center = to_cli_filter(align_center)
self._has_focus_filter = to_cli_filter(has_focus)
self.get_tokens = get_tokens
# Construct `get_default_char` callable.
if default_char:
get_default_char = lambda _: default_char
elif not get_default_char:
get_default_char = lambda _: Char(' ', Token)
self.get_default_char = get_default_char
#: Cache for the content.
self._content_cache = SimpleCache(maxsize=18)
self._token_cache = SimpleCache(maxsize=1)
# Only cache one token list. We don't need the previous item.
# Render info for the mouse support.
self._tokens = None
示例2: __init__
def __init__(self, get_tokens, default_char=None, get_default_char=None,
align_right=False, align_center=False,
has_focus=False, wrap_lines=True):
assert default_char is None or isinstance(default_char, Char)
assert get_default_char is None or callable(get_default_char)
assert not (default_char and get_default_char)
self.align_right = to_cli_filter(align_right)
self.align_center = to_cli_filter(align_center)
self._has_focus_filter = to_cli_filter(has_focus)
self.wrap_lines = to_cli_filter(wrap_lines)
self.get_tokens = get_tokens
# Construct `get_default_char` callable.
if default_char:
get_default_char = lambda _: default_char
elif not get_default_char:
get_default_char = lambda _: Char(' ', Token)
self.get_default_char = get_default_char
#: Cache for rendered screens.
self._screen_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 # The last rendered tokens.
self._pos_to_indexes = None # Mapping from mouse positions (x,y) to
示例3: _MergedStyle
class _MergedStyle(BaseStyle):
"""
Merge multiple `Style` objects into one.
This is supposed to ensure consistency: if any of the given styles changes,
then this style will be updated.
"""
# NOTE: previously, we used an algorithm where we did not generate the
# combined style. Instead this was a proxy that called one style
# after the other, passing the outcome of the previous style as the
# default for the next one. This did not work, because that way, the
# priorities like described in the `Style` class don't work.
# 'class:aborted' was for instance never displayed in gray, because
# the next style specified a default color for any text. (The
# explicit styling of class:aborted should have taken priority,
# because it was more precise.)
def __init__(self, styles):
assert all(isinstance(style, BaseStyle) for style in styles)
self.styles = styles
self._style = SimpleCache(maxsize=1)
@property
def _merged_style(self):
" The `Style` object that has the other styles merged together. "
def get():
return Style(self.style_rules)
return self._style.get(self.invalidation_hash(), get)
@property
def style_rules(self):
style_rules = []
for s in self.styles:
style_rules.extend(s.style_rules)
return style_rules
def get_attrs_for_style_str(self, style_str, default=DEFAULT_ATTRS):
return self._merged_style.get_attrs_for_style_str(style_str, default)
def invalidation_hash(self):
return tuple(s.invalidation_hash() for s in self.styles)
示例4: __init__
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,
get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False):
assert isinstance(content, UIControl)
assert width is None or isinstance(width, LayoutDimension)
assert height is None or isinstance(height, LayoutDimension)
assert get_width is None or callable(get_width)
assert get_height is None or callable(get_height)
assert width is None or get_width is None
assert height is None or get_height is None
assert scroll_offsets is None or isinstance(scroll_offsets, ScrollOffsets)
assert left_margins is None or all(isinstance(m, Margin) for m in left_margins)
assert right_margins is None or all(isinstance(m, Margin) for m in right_margins)
assert get_vertical_scroll is None or callable(get_vertical_scroll)
assert get_horizontal_scroll is None or callable(get_horizontal_scroll)
self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom)
self.always_hide_cursor = to_cli_filter(always_hide_cursor)
self.content = content
self.dont_extend_width = dont_extend_width
self.dont_extend_height = dont_extend_height
self.left_margins = left_margins or []
self.right_margins = right_margins or []
self.scroll_offsets = scroll_offsets or ScrollOffsets()
self.get_vertical_scroll = get_vertical_scroll
self.get_horizontal_scroll = get_horizontal_scroll
self._width = get_width or (lambda cli: width)
self._height = get_height or (lambda cli: height)
# Cache for the screens generated by the margin.
self._margin_cache = SimpleCache(maxsize=8)
self.reset()
示例5: __init__
def __init__(self, styles):
assert all(isinstance(style, BaseStyle) for style in styles)
self.styles = styles
self._style = SimpleCache(maxsize=1)
示例6: __init__
def __init__(self, chars='[](){}<>', max_cursor_distance=1000):
self.chars = chars
self.max_cursor_distance = max_cursor_distance
self._positions_cache = SimpleCache(maxsize=8)
示例7: HighlightMatchingBracketProcessor
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.)
"""
_closing_braces = '])}>'
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 foun at this line.
if positions:
for row, col in positions:
if row == lineno:
col = source_to_display(col)
tokens = explode_tokens(tokens)
tokens[col] = (Token.MatchingBracket, tokens[col][1])
return Transformation(tokens)
示例8: __init__
def __init__(self, app):
self.app = app
self._cache = SimpleCache()
示例9: __init__
def __init__(self):
self.bindings = []
self._get_bindings_for_keys_cache = SimpleCache(maxsize=10000)
self._get_bindings_starting_with_keys_cache = SimpleCache(maxsize=1000)
self.__version = 0 # For cache invalidation.
示例10: Registry
class Registry(object):
"""
Key binding registry.
::
r = Registry()
@r.add_binding(Keys.ControlX, Keys.ControlC, filter=INSERT)
def handler(event):
# Handle ControlX-ControlC key sequence.
pass
"""
def __init__(self):
self.key_bindings = []
self._get_bindings_for_keys_cache = SimpleCache(maxsize=10000)
self._get_bindings_starting_with_keys_cache = SimpleCache(maxsize=1000)
def _clear_cache(self):
self._get_bindings_for_keys_cache.clear()
self._get_bindings_starting_with_keys_cache.clear()
def add_binding(self, *keys, **kwargs):
"""
Decorator for annotating key bindings.
:param filter: :class:`~prompt_toolkit.filters.CLIFilter` to determine
when this key binding is active.
:param eager: :class:`~prompt_toolkit.filters.CLIFilter` or `bool`.
When True, ignore potential longer matches when this key binding is
hit. E.g. when there is an active eager key binding for Ctrl-X,
execute the handler immediately and ignore the key binding for
Ctrl-X Ctrl-E of which it is a prefix.
:param save_before: Callable that takes an `Event` and returns True if
we should save the current buffer, before handling the event.
(That's the default.)
"""
filter = to_cli_filter(kwargs.pop('filter', True))
eager = to_cli_filter(kwargs.pop('eager', False))
save_before = kwargs.pop('save_before', lambda e: True)
to_cli_filter(kwargs.pop('invalidate_ui', True)) # Deprecated! (ignored.)
assert not kwargs
assert keys
assert all(isinstance(k, (Key, text_type)) for k in keys), \
'Key bindings should consist of Key and string (unicode) instances.'
assert callable(save_before)
if isinstance(filter, Never):
# When a filter is Never, it will always stay disabled, so in that case
# don't bother putting it in the registry. It will slow down every key
# press otherwise.
def decorator(func):
return func
else:
def decorator(func):
self.key_bindings.append(
_Binding(keys, func, filter=filter, eager=eager,
save_before=save_before))
self._clear_cache()
return func
return decorator
def remove_binding(self, function):
"""
Remove a key binding.
This expects a function that was given to `add_binding` method as
parameter. Raises `ValueError` when the given function was not
registered before.
"""
assert callable(function)
for b in self.key_bindings:
if b.handler == function:
self.key_bindings.remove(b)
self._clear_cache()
return
# No key binding found for this function. Raise ValueError.
raise ValueError('Binding not found: %r' % (function, ))
def get_bindings_for_keys(self, keys):
"""
Return a list of key bindings that can handle this key.
(This return also inactive bindings, so the `filter` still has to be
called, for checking it.)
:param keys: tuple of keys.
"""
def get():
result = []
for b in self.key_bindings:
if len(keys) == len(b.keys):
match = True
any_count = 0
for i, j in zip(b.keys, keys):
if i != j and i != Keys.Any:
#.........这里部分代码省略.........
示例11: BufferControl
class BufferControl(UIControl):
"""
Control for visualising the content of a `Buffer`.
:param input_processors: list of :class:`~prompt_toolkit.layout.processors.Processor`.
:param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` instance for syntax highlighting.
:param preview_search: `bool` or `CLIFilter`: Show search while typing.
:param get_search_state: Callable that takes a CommandLineInterface and
returns the SearchState to be used. (If not CommandLineInterface.search_state.)
:param wrap_lines: `bool` or `CLIFilter`: Wrap long lines.
:param buffer_name: String representing the name of the buffer to display.
:param default_char: :class:`.Char` instance to use to fill the background. This is
transparent by default.
:param focus_on_click: Focus this buffer when it's click, but not yet focussed.
"""
def __init__(self,
buffer_name=DEFAULT_BUFFER,
input_processors=None,
highlighters=None,
lexer=None,
preview_search=False,
search_buffer_name=SEARCH_BUFFER,
get_search_state=None,
wrap_lines=True,
menu_position=None,
default_char=None,
focus_on_click=False):
assert input_processors is None or all(isinstance(i, Processor) for i in input_processors)
assert highlighters is None or all(isinstance(i, Highlighter) for i in highlighters)
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)
self.preview_search = to_cli_filter(preview_search)
self.get_search_state = get_search_state
self.wrap_lines = to_cli_filter(wrap_lines)
self.focus_on_click = to_cli_filter(focus_on_click)
self.input_processors = input_processors or []
self.highlighters = highlighters or []
self.buffer_name = buffer_name
self.menu_position = menu_position
self.lexer = lexer or SimpleLexer()
self.default_char = default_char or Char(token=Token.Transparent)
self.search_buffer_name = search_buffer_name
#: Cache for the lexer.
#: Often, due to cursor movement, undo/redo and window resizing
#: operations, it happens that a short time, the same document has to be
#: lexed. This is a faily easy way to cache such an expensive operation.
self._token_cache = SimpleCache(maxsize=8)
#: Keep a similar cache for rendered screens. (when we scroll up/down
#: through the screen, or when we change another buffer, we don't want
#: to recreate the same screen again.)
self._screen_cache = SimpleCache(maxsize=8)
#: Highlight Cache.
#: When nothing of the buffer content or processors has changed, but
#: the highlighting of the selection/search changes,
self._highlight_cache = SimpleCache(maxsize=8)
self._xy_to_cursor_position = None
self._last_click_timestamp = None
def _buffer(self, cli):
"""
The buffer object that contains the 'main' content.
"""
return cli.buffers[self.buffer_name]
def has_focus(self, cli):
# This control gets the focussed if the actual `Buffer` instance has the
# focus or when any of the `InputProcessor` classes tells us that it
# wants the focus. (E.g. in case of a reverse-search, where the actual
# search buffer may not be displayed, but the "reverse-i-search" text
# should get the focus.)
return cli.current_buffer_name == self.buffer_name or \
any(i.has_focus(cli) for i in self.input_processors)
def preferred_width(self, cli, max_available_width):
# Return the length of the longest line.
return max(map(len, self._buffer(cli).document.lines))
def preferred_height(self, cli, width):
# Draw content on a screen using this width. Measure the height of the
# result.
screen, highlighters = self.create_screen(cli, width, None)
return screen.height
def _get_input_tokens(self, cli, document):
"""
Tokenize input text for highlighting.
Return (tokens, source_to_display, display_to_source) tuple.
:param document: The document to be shown. This can be `buffer.document`
but could as well be a different one, in case we are
searching through the history. (Buffer.document_for_search)
"""
def get():
#.........这里部分代码省略.........
示例12: BufferControl
class BufferControl(UIControl):
"""
Control for visualising the content of a `Buffer`.
:param input_processors: list of :class:`~prompt_toolkit.layout.processors.Processor`.
:param lexer: :class:`~prompt_toolkit.layout.lexers.Lexer` instance for syntax highlighting.
:param preview_search: `bool` or `CLIFilter`: Show search while typing.
:param get_search_state: Callable that takes a CommandLineInterface and
returns the SearchState to be used. (If not CommandLineInterface.search_state.)
:param buffer_name: String representing the name of the buffer to display.
:param default_char: :class:`.Char` instance to use to fill the background. This is
transparent by default.
:param focus_on_click: Focus this buffer when it's click, but not yet focussed.
"""
def __init__(self,
buffer_name=DEFAULT_BUFFER,
input_processors=None,
lexer=None,
preview_search=False,
search_buffer_name=SEARCH_BUFFER,
get_search_state=None,
menu_position=None,
default_char=None,
focus_on_click=False):
assert input_processors is None or all(isinstance(i, Processor) for i in input_processors)
assert menu_position is None or callable(menu_position)
assert lexer is None or isinstance(lexer, Lexer)
assert get_search_state is None or callable(get_search_state)
assert default_char is None or isinstance(default_char, Char)
self.preview_search = to_cli_filter(preview_search)
self.get_search_state = get_search_state
self.focus_on_click = to_cli_filter(focus_on_click)
self.input_processors = input_processors or []
self.buffer_name = buffer_name
self.menu_position = menu_position
self.lexer = lexer or SimpleLexer()
self.default_char = default_char or Char(token=Token.Transparent)
self.search_buffer_name = search_buffer_name
#: 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._processed_token_cache = SimpleCache(maxsize=8)
self._xy_to_cursor_position = None
self._last_click_timestamp = None
self._last_get_processed_line = None
def _buffer(self, cli):
"""
The buffer object that contains the 'main' content.
"""
return cli.buffers[self.buffer_name]
def has_focus(self, cli):
# This control gets the focussed if the actual `Buffer` instance has the
# focus or when any of the `InputProcessor` classes tells us that it
# wants the focus. (E.g. in case of a reverse-search, where the actual
# search buffer may not be displayed, but the "reverse-i-search" text
# should get the focus.)
return cli.current_buffer_name == self.buffer_name or \
any(i.has_focus(cli) for i in self.input_processors)
def preferred_width(self, cli, max_available_width):
"""
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:
#.........这里部分代码省略.........
示例13: TokenListControl
class TokenListControl(UIControl):
"""
Control that displays a list of (Token, text) tuples.
(It's mostly optimized for rather small widgets, like toolbars, menus, etc...)
Mouse support:
The list of tokens can also contain tuples of three items, looking like:
(Token, text, handler). When mouse support is enabled and the user
clicks on this token, then the given handler is called. That handler
should accept two inputs: (CommandLineInterface, MouseEvent) and it
should either handle the event or return `NotImplemented` in case we
want the containing Window to handle this event.
:param get_tokens: Callable that takes a `CommandLineInterface` instance
and returns the list of (Token, text) tuples to be displayed right now.
:param default_char: default :class:`.Char` (character and Token) to use
for the background when there is more space available than `get_tokens`
returns.
:param get_default_char: Like `default_char`, but this is a callable that
takes a :class:`prompt_toolkit.interface.CommandLineInterface` and
returns a :class:`.Char` instance.
:param has_focus: `bool` or `CLIFilter`, when this evaluates to `True`,
this UI control will take the focus. The cursor will be shown in the
upper left corner of this control, unless `get_token` returns a
``Token.SetCursorPosition`` token somewhere in the token list, then the
cursor will be shown there.
"""
def __init__(self, get_tokens, default_char=None, get_default_char=None,
align_right=False, align_center=False, has_focus=False):
assert default_char is None or isinstance(default_char, Char)
assert get_default_char is None or callable(get_default_char)
assert not (default_char and get_default_char)
self.align_right = to_cli_filter(align_right)
self.align_center = to_cli_filter(align_center)
self._has_focus_filter = to_cli_filter(has_focus)
self.get_tokens = get_tokens
# Construct `get_default_char` callable.
if default_char:
get_default_char = lambda _: default_char
elif not get_default_char:
get_default_char = lambda _: Char(' ', Token)
self.get_default_char = get_default_char
#: Cache for the content.
self._content_cache = SimpleCache(maxsize=18)
self._token_cache = SimpleCache(maxsize=1)
# Only cache one token list. We don't need the previous item.
# Render info for the mouse support.
self._tokens = None
def reset(self):
self._tokens = None
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
def _get_tokens_cached(self, cli):
"""
Get tokens, but only retrieve tokens once during one render run.
(This function is called several times during one rendering, because
we also need those for calculating the dimensions.)
"""
return self._token_cache.get(
cli.render_counter, lambda: self.get_tokens(cli))
def has_focus(self, cli):
return self._has_focus_filter(cli)
def preferred_width(self, cli, max_available_width):
"""
Return the preferred width for this control.
That is the width of the longest line.
"""
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 create_content(self, cli, width, height):
# Get tokens
tokens_with_mouse_handlers = self._get_tokens_cached(cli)
default_char = self.get_default_char(cli)
# Wrap/align right/center parameters.
right = self.align_right(cli)
center = self.align_center(cli)
def process_line(line):
" Center or right align a single line. "
used_width = token_list_width(line)
#.........这里部分代码省略.........
示例14: Window
class Window(Container):
"""
Container that holds a control.
:param content: :class:`~prompt_toolkit.layout.controls.UIControl` instance.
:param width: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
:param height: :class:`~prompt_toolkit.layout.dimension.LayoutDimension` instance.
:param get_width: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
:param get_height: callable which takes a `CommandLineInterface` and returns a `LayoutDimension`.
:param dont_extend_width: When `True`, don't take up more width then the
preferred width reported by the control.
:param dont_extend_height: When `True`, don't take up more width then the
preferred height reported by the control.
:param left_margins: A list of :class:`~prompt_toolkit.layout.margins.Margin`
instance to be displayed on the left. For instance:
:class:`~prompt_toolkit.layout.margins.NumberredMargin` can be one of
them in order to show line numbers.
:param right_margins: Like `left_margins`, but on the other side.
:param scroll_offsets: :class:`.ScrollOffsets` instance, representing the
preferred amount of lines/columns to be always visible before/after the
cursor. When both top and bottom are a very high number, the cursor
will be centered vertically most of the time.
:param allow_scroll_beyond_bottom: A `bool` or
:class:`~prompt_toolkit.filters.CLIFilter` instance. When True, allow
scrolling so far, that the top part of the content is not visible
anymore, while there is still empty space available at the bottom of
the window. In the Vi editor for instance, this is possible. You will
see tildes while the top part of the body is hidden.
:param get_vertical_scroll: Callable that takes this window
instance as input and returns a preferred vertical scroll.
(When this is `None`, the scroll is only determined by the last and
current cursor position.)
:param get_horizontal_scroll: Callable that takes this window
instance as input and returns a preferred vertical scroll.
:param always_hide_cursor: A `bool` or
:class:`~prompt_toolkit.filters.CLIFilter` instance. When True, never
display the cursor, even when the user control specifies a cursor
position.
"""
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,
get_vertical_scroll=None, get_horizontal_scroll=None, always_hide_cursor=False):
assert isinstance(content, UIControl)
assert width is None or isinstance(width, LayoutDimension)
assert height is None or isinstance(height, LayoutDimension)
assert get_width is None or callable(get_width)
assert get_height is None or callable(get_height)
assert width is None or get_width is None
assert height is None or get_height is None
assert scroll_offsets is None or isinstance(scroll_offsets, ScrollOffsets)
assert left_margins is None or all(isinstance(m, Margin) for m in left_margins)
assert right_margins is None or all(isinstance(m, Margin) for m in right_margins)
assert get_vertical_scroll is None or callable(get_vertical_scroll)
assert get_horizontal_scroll is None or callable(get_horizontal_scroll)
self.allow_scroll_beyond_bottom = to_cli_filter(allow_scroll_beyond_bottom)
self.always_hide_cursor = to_cli_filter(always_hide_cursor)
self.content = content
self.dont_extend_width = dont_extend_width
self.dont_extend_height = dont_extend_height
self.left_margins = left_margins or []
self.right_margins = right_margins or []
self.scroll_offsets = scroll_offsets or ScrollOffsets()
self.get_vertical_scroll = get_vertical_scroll
self.get_horizontal_scroll = get_horizontal_scroll
self._width = get_width or (lambda cli: width)
self._height = get_height or (lambda cli: height)
# Cache for the screens generated by the margin.
self._margin_cache = SimpleCache(maxsize=8)
self.reset()
def __repr__(self):
return 'Window(content=%r)' % self.content
def reset(self):
self.content.reset()
#: Scrolling position of the main content.
self.vertical_scroll = 0
self.horizontal_scroll = 0
#: Keep render information (mappings between buffer input and render
#: output.)
self.render_info = None
def preferred_width(self, cli, max_available_width):
# Width of the margins.
total_margin_width = sum(m.get_width(cli) for m in
self.left_margins + self.right_margins)
# Window of the content.
preferred_width = self.content.preferred_width(
cli, max_available_width - total_margin_width)
if preferred_width is not None:
#.........这里部分代码省略.........
示例15: TokenListControl
class TokenListControl(UIControl):
"""
Control that displays a list of (Token, text) tuples.
(It's mostly optimized for rather small widgets, like toolbars, menus, etc...)
Mouse support:
The list of tokens can also contain tuples of three items, looking like:
(Token, text, handler). When mouse support is enabled and the user
clicks on this token, then the given handler is called. That handler
should accept two inputs: (CommandLineInterface, MouseEvent) and it
should either handle the event or return `NotImplemented` in case we
want the containing Window to handle this event.
:param get_tokens: Callable that takes a `CommandLineInterface` instance
and returns the list of (Token, text) tuples to be displayed right now.
:param default_char: default :class:`.Char` (character and Token) to use
for the background when there is more space available than `get_tokens`
returns.
:param get_default_char: Like `default_char`, but this is a callable that
takes a :class:`prompt_toolkit.interface.CommandLineInterface` and
returns a :class:`.Char` instance.
:param has_focus: `bool` or `CLIFilter`, when this evaluates to `True`,
this UI control will take the focus. The cursor will be shown in the
upper left corner of this control, unless `get_token` returns a
``Token.SetCursorPosition`` token somewhere in the token list, then the
cursor will be shown there.
:param wrap_lines: `bool` or `CLIFilter`: Wrap long lines.
"""
def __init__(self, get_tokens, default_char=None, get_default_char=None,
align_right=False, align_center=False,
has_focus=False, wrap_lines=True):
assert default_char is None or isinstance(default_char, Char)
assert get_default_char is None or callable(get_default_char)
assert not (default_char and get_default_char)
self.align_right = to_cli_filter(align_right)
self.align_center = to_cli_filter(align_center)
self._has_focus_filter = to_cli_filter(has_focus)
self.wrap_lines = to_cli_filter(wrap_lines)
self.get_tokens = get_tokens
# Construct `get_default_char` callable.
if default_char:
get_default_char = lambda _: default_char
elif not get_default_char:
get_default_char = lambda _: Char(' ', Token)
self.get_default_char = get_default_char
#: Cache for rendered screens.
self._screen_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 # The last rendered tokens.
self._pos_to_indexes = None # Mapping from mouse positions (x,y) to
# positions in the token list.
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.get_tokens)
def _get_tokens_cached(self, cli):
"""
Get tokens, but only retrieve tokens once during one render run.
(This function is called several times during one rendering, because
we also need those for calculating the dimensions.)
"""
return self._token_cache.get(
cli.render_counter, lambda: self.get_tokens(cli))
def has_focus(self, cli):
return self._has_focus_filter(cli)
def preferred_width(self, cli, max_available_width):
"""
Return the preferred width for this control.
That is the width of the longest line.
"""
text = ''.join(t[1] for t in 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):
screen = self.create_screen(cli, width, None)
return screen.height
def create_screen(self, cli, width, height):
# Get tokens
tokens_with_mouse_handlers = self._get_tokens_cached(cli)
default_char = self.get_default_char(cli)
# Wrap/align right/center parameters.
wrap_lines = self.wrap_lines(cli)
right = self.align_right(cli)
center = self.align_center(cli)
#.........这里部分代码省略.........