diff options
author | Nikita Slyusarev <nslus@yandex-team.com> | 2022-02-10 16:46:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:52 +0300 |
commit | cd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch) | |
tree | 1308e0bae862d52e0020d881fe758080437fe389 /contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py | |
parent | cdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff) | |
download | ydb-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/processors.py')
-rw-r--r-- | contrib/python/prompt-toolkit/py2/prompt_toolkit/layout/processors.py | 676 |
1 files changed, 338 insertions, 338 deletions
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 0b8bc9c223d..fc3e29a089c 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): |