Beispiel #1
0
def determine_position(
        logria: 'Logria',
        messages_pointer: List[str]) -> Tuple[int, int]:  # type: ignore
    """
    Determine the start and end positions for a screen render
    """
    if logria.stick_to_top:
        end = 0
        rows = 0
        for i in messages_pointer:
            if messages_pointer is logria.messages:
                # No processing needed for normal messages
                item: str = i
            elif messages_pointer is logria.matched_rows:
                # Grab the matched message
                item = logria.messages[i]  # type: ignore
            # Determine if the message will fit in the window
            msg_lines = ceil(get_real_length(item) / logria.width)
            rows += msg_lines
            # If we can fit, increment the last row number
            if rows < logria.last_row and end < len(messages_pointer) - 1:
                end += 1
            else:
                break
        logria.current_end = end  # Save this row so we know where we are
        # When iterating backwards, we need to end at 0, so we must create a range
        # object like range(10, -1, -1) to generate a list that ends at 0
        # If there are no messages, we want to not iterate later, so we change the
        # -1 to 0 so that we do not iterate at all
        return -1 if messages_pointer else 0, end  # Early escape
    elif logria.stick_to_bottom:
        end = len(messages_pointer) - 1
    elif logria.manually_controlled_line:
        if len(messages_pointer) < logria.last_row:
            # If have fewer messages than lines, just render it all
            end = len(messages_pointer) - 1
        elif logria.current_end < logria.last_row:
            # If the last row we rendered comes before the last row we can render,
            # use all of the available rows
            end = logria.current_end
        elif logria.current_end < len(messages_pointer):
            # If we are looking at a valid line, render ends there
            end = logria.current_end
        else:
            # If we have over-scrolled, go back
            if logria.current_end > len(messages_pointer):
                logria.current_end = len(messages_pointer)
            # Since current_end can be zero, we have to use the number of messages
            end = len(messages_pointer)
    else:
        end = len(messages_pointer)
    logria.current_end = end  # Save this row so we know where we are
    # Last index of a list is length - 1
    start = max(-1, end - logria.last_row - 1)
    return start, end
Beispiel #2
0
    def render_text_in_output(self) -> None:
        """
        Renders stream content in the output window

        If filters are inactive, we use `messages`. If they are active, we pull from `matched_rows`

        We write the whole message, regardless of length, because slicing a string allocates a new string
        """
        # Store a pointer to the buffer of messages
        if self.func_handle is None:
            messages_pointer = self.messages
        else:
            # Ignore typing because we use different values depending on what this pointer is
            messages_pointer = self.matched_rows  # type: ignore

        # Determine the start and end position of the render
        start, end = determine_position(self, messages_pointer)
        # Don't do anything if nothing changed; start at index 0
        if not self.analytics_enabled and self.previous_render == (max(
                start, 0), end):
            return  # Early escape
        self.previous_render = (max(start, 0), end)
        self.outwin.erase()
        current_row = self.last_row  # The row we are currently rendering
        for i in range(end, start, -1):
            if messages_pointer is self.messages:
                # No processing needed for normal messages
                item = messages_pointer[i]
            elif messages_pointer is self.matched_rows:
                # Grab the matched message and optionally highlight it
                messages_idx = self.matched_rows[i]
                item = self.messages[messages_idx]
                if self.highlight_match:
                    # Remove all color codes before applying highlighter
                    item = re.sub(constants.ANSI_COLOR_PATTERN, '', item)
                    match = re.search(self.regex_pattern, item)
                    if match:
                        start, end = match.span()
                        matched_str = item[start:end]
                        item = item.replace(
                            matched_str, f'\u001b[35m{matched_str}\u001b[0m')
            # Find the correct start position
            current_row -= ceil(get_real_length(item) / self.width)
            if current_row < 0:
                break
            # Instead of window.addstr, handle colors
            color_handler.addstr(self.outwin, current_row, 0, item.rstrip())
        self.outwin.refresh()
Beispiel #3
0
    def render_text_in_output(self) -> None:
        """
        Renders stream content in the output window

        If filters are inactive, we use `messages`. If they are active, we pull from `matched_rows`

        We write the whole message, regardless of length, because slicing a string allocates a new string
        """
        # Store a pointer to the buffer of messages
        if self.func_handle is None:
            messages_pointer = self.messages
        else:
            messages_pointer = self.matched_rows

        # Determine the start and end position of the render
        start, end = self.determine_render_position(messages_pointer)
        # Don't do anything if nothing changed; start at index 0
        if self.previous_render == messages_pointer[max(start, 0):end]:
            return
        self.previous_render = messages_pointer[max(start, 0):end]
        self.outwin.erase()
        current_row = self.last_row  # The row we are currently rendering
        for i in range(end, start, -1):
            if messages_pointer is self.messages:
                # No processing needed for normal messages
                item = messages_pointer[i]
            elif messages_pointer is self.matched_rows:
                # Grab the matched message and optionally highlight it
                messages_idx = self.matched_rows[i]
                item = self.messages[messages_idx]
                if self.highlight_match:
                    # Remove all color codes before applying highlighter
                    item = re.sub(constants.ANSI_COLOR_PATTERN, '', item)
                    item = re.sub(self.regex_pattern,
                                  f'\u001b[35m{self.regex_pattern}\u001b[0m',
                                  item.rstrip())
            # Find the correct start position
            current_row -= ceil(get_real_length(item) / self.width)
            if current_row < 0:
                break
            # Instead of window.addstr, handle colors
            color_handler.addstr(self.outwin, current_row, 0, item.rstrip())
        self.outwin.refresh()
Beispiel #4
0
 def test_get_real_length_with_color_code(self):
     """
     Test that we get the real length of a string with escape codes
     """
     self.assertEqual(
         regex_generator.get_real_length('\u001b[0m word \u001b[32m'), 6)
Beispiel #5
0
 def test_get_real_length(self):
     """
     Test that we get the real length of a string
     """
     self.assertEqual(regex_generator.get_real_length('word'), 4)