<commit_before># -*- coding: utf-8 -*-
"""This module implements a multi line editing text box"""
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
from builtins import chr
from builtins import str
from copy import copy
from asciimatics.event import KeyboardEvent, MouseEvent
from asciimatics.screen import Screen
from asciimatics.strings import ColouredText
from asciimatics.widgets.widget import Widget
from asciimatics.widgets.utilities import _find_min_start, _enforce_width, logger, _get_offset


class TextBox(Widget):
    """
    A TextBox is a widget for multi-line text editing.

    It consists of a framed box with option label.
    """

    __slots__ = ["_label", "_line", "_column", "_start_line", "_start_column", "_required_height",
                 "_as_string", "_line_wrap", "_on_change", "_reflowed_text_cache", "_parser",
                 "_readonly", "_hide_cursor", "_auto_scroll"]

    def __init__(self, height, label=None, name=None, as_string=False, line_wrap=False, parser=None,
                 on_change=None, readonly=False, **kwargs):
        """
        :param height: The required number of input lines for this TextBox.
        :param label: An optional label for the widget.
        :param name: The name for the TextBox.
        :param as_string: Use string with newline separator instead of a list
            for the value of this widget.
        :param line_wrap: Whether to wrap at the end of the line.
        :param parser: Optional parser to colour text.
        :param on_change: Optional function to call when text changes.
        :param readonly: Whether the widget prevents user input to change values.  Default is False.

        Also see the common keyword arguments in :py:obj:`.Widget`.
        """
        super(TextBox, self).__init__(name, **kwargs)
        self._label = label
        self._line = 0
        self._column = 0
        self._start_line = 0
        self._start_column = 0
        self._required_height = height
        self._as_string = as_string
        self._line_wrap = line_wrap
        self._parser = parser
        self._on_change = on_change
        self._reflowed_text_cache = None
        self._readonly = readonly
        self._hide_cursor = False
        self._auto_scroll = True

    def update(self, frame_no):
        self._draw_label()

        # Calculate new visible limits if needed.
        height = self._h
        if not self._line_wrap:
            self._start_column = min(self._start_column, self._column)
            self._start_column += _find_min_start(
                str(self._value[self._line][self._start_column:self._column + 1]),
                self.width,
                self._frame.canvas.unicode_aware,
                self._column >= self.string_len(str(self._value[self._line])))

        # Clear out the existing box content
        (colour, attr, background) = self._pick_colours("readonly" if self._readonly else "edit_text")
        self._frame.canvas.clear_buffer(
            colour, attr, background, self._x + self._offset, self._y, self.width, height)

        # Convert value offset to display offsets
        # NOTE: _start_column is always in display coordinates.
        display_text = self._reflowed_text
        display_start_column = self._start_column
        display_line, display_column = 0, 0
        for i, (_, line, col) in enumerate(display_text):
            if line < self._line or (line == self._line and col <= self._column):
                display_line = i
                display_column = self._column - col

        # Restrict to visible/valid content.
        self._start_line = max(0, max(display_line - height + 1,
                                      min(self._start_line, display_line)))

        # Render visible portion of the text.
        for line, (text, _, _) in enumerate(display_text):
            if self._start_line <= line < self._start_line + height:
                paint_text = _enforce_width(
                    text[display_start_column:], self.width, self._frame.canvas.unicode_aware)
                self._frame.canvas.paint(
                    str(paint_text),
                    self._x + self._offset,
                    self._y + line - self._start_line,
                    colour, attr, background,
                    colour_map=paint_text.colour_map if hasattr(paint_text, "colour_map") else None)

        # Since we switch off the standard cursor, we need to emulate our own
        # if we have the input focus.
        if self._has_focus:
            line = str(display_text[display_line][0])
#            logger.debug("Cursor: %d,%d", display_start_column, display_column)
            text_width = self.string_len(line[display_start_column:display_column])
            self._draw_cursor(
                " " if display_column >= len(line) else line[display_column],
                frame_no,
                self._x + self._offset + text_width,
                self._y + display_line - self._start_line)

    def reset(self):
        # Reset to original data and move to end of the text.
        self._start_line = 0
        self._start_column = 0
        if self._auto_scroll or self._line > len(self._value) - 1:
            self._line = len(self._value) - 1

        self._column = 0 if self._is_disabled else len(self._value[self._line])
        self._reflowed_text_cache = None

    def _draw_cursor(self, char, frame_no, x, y):
        if not self._hide_cursor:
            super()._draw_cursor(char, frame_no, x, y)

    def _change_line(self, delta):
        """
        Move the cursor up/down the specified number of lines.

        :param delta: The number of lines to move (-ve is up, +ve is down).
        """
        if self._hide_cursor:
            # Cursor is hidden, move entire box

            if delta > 0:<commit_msg>Change to Py27 compatible call to super()<commit_after># -*- coding: utf-8 -*-
"""This module implements a multi line editing text box"""
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
from builtins import chr
from builtins import str
from copy import copy
from asciimatics.event import KeyboardEvent, MouseEvent
from asciimatics.screen import Screen
from asciimatics.strings import ColouredText
from asciimatics.widgets.widget import Widget
from asciimatics.widgets.utilities import _find_min_start, _enforce_width, logger, _get_offset


class TextBox(Widget):
    """
    A TextBox is a widget for multi-line text editing.

    It consists of a framed box with option label.
    """

    __slots__ = ["_label", "_line", "_column", "_start_line", "_start_column", "_required_height",
                 "_as_string", "_line_wrap", "_on_change", "_reflowed_text_cache", "_parser",
                 "_readonly", "_hide_cursor", "_auto_scroll"]

    def __init__(self, height, label=None, name=None, as_string=False, line_wrap=False, parser=None,
                 on_change=None, readonly=False, **kwargs):
        """
        :param height: The required number of input lines for this TextBox.
        :param label: An optional label for the widget.
        :param name: The name for the TextBox.
        :param as_string: Use string with newline separator instead of a list
            for the value of this widget.
        :param line_wrap: Whether to wrap at the end of the line.
        :param parser: Optional parser to colour text.
        :param on_change: Optional function to call when text changes.
        :param readonly: Whether the widget prevents user input to change values.  Default is False.

        Also see the common keyword arguments in :py:obj:`.Widget`.
        """
        super(TextBox, self).__init__(name, **kwargs)
        self._label = label
        self._line = 0
        self._column = 0
        self._start_line = 0
        self._start_column = 0
        self._required_height = height
        self._as_string = as_string
        self._line_wrap = line_wrap
        self._parser = parser
        self._on_change = on_change
        self._reflowed_text_cache = None
        self._readonly = readonly
        self._hide_cursor = False
        self._auto_scroll = True

    def update(self, frame_no):
        self._draw_label()

        # Calculate new visible limits if needed.
        height = self._h
        if not self._line_wrap:
            self._start_column = min(self._start_column, self._column)
            self._start_column += _find_min_start(
                str(self._value[self._line][self._start_column:self._column + 1]),
                self.width,
                self._frame.canvas.unicode_aware,
                self._column >= self.string_len(str(self._value[self._line])))

        # Clear out the existing box content
        (colour, attr, background) = self._pick_colours("readonly" if self._readonly else "edit_text")
        self._frame.canvas.clear_buffer(
            colour, attr, background, self._x + self._offset, self._y, self.width, height)

        # Convert value offset to display offsets
        # NOTE: _start_column is always in display coordinates.
        display_text = self._reflowed_text
        display_start_column = self._start_column
        display_line, display_column = 0, 0
        for i, (_, line, col) in enumerate(display_text):
            if line < self._line or (line == self._line and col <= self._column):
                display_line = i
                display_column = self._column - col

        # Restrict to visible/valid content.
        self._start_line = max(0, max(display_line - height + 1,
                                      min(self._start_line, display_line)))

        # Render visible portion of the text.
        for line, (text, _, _) in enumerate(display_text):
            if self._start_line <= line < self._start_line + height:
                paint_text = _enforce_width(
                    text[display_start_column:], self.width, self._frame.canvas.unicode_aware)
                self._frame.canvas.paint(
                    str(paint_text),
                    self._x + self._offset,
                    self._y + line - self._start_line,
                    colour, attr, background,
                    colour_map=paint_text.colour_map if hasattr(paint_text, "colour_map") else None)

        # Since we switch off the standard cursor, we need to emulate our own
        # if we have the input focus.
        if self._has_focus:
            line = str(display_text[display_line][0])
#            logger.debug("Cursor: %d,%d", display_start_column, display_column)
            text_width = self.string_len(line[display_start_column:display_column])
            self._draw_cursor(
                " " if display_column >= len(line) else line[display_column],
                frame_no,
                self._x + self._offset + text_width,
                self._y + display_line - self._start_line)

    def reset(self):
        # Reset to original data and move to end of the text.
        self._start_line = 0
        self._start_column = 0
        if self._auto_scroll or self._line > len(self._value) - 1:
            self._line = len(self._value) - 1

        self._column = 0 if self._is_disabled else len(self._value[self._line])
        self._reflowed_text_cache = None

    def _draw_cursor(self, char, frame_no, x, y):
        if not self._hide_cursor:
            super(TextBox, self)._draw_cursor(char, frame_no, x, y)

    def _change_line(self, delta):
        """
        Move the cursor up/down the specified number of lines.

        :param delta: The number of lines to move (-ve is up, +ve is down).
        """
        if self._hide_cursor:
            # Cursor is hidden, move entire box

            if delta > 0:
{'fraction_non_alphanumeric': 0.08526218331790253, 'fraction_numerical': 0.003030047975759616, 'mean_word_length': 2.293237250554324, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1337989', 'n_tokens_mistral': 3342, 'n_tokens_neox': 3206, 'n_words': 1000}