def testRegexFindOnPrependedLinesWorks(self): rich_lines = debugger_cli_common.RichTextLines(["Violets are blue"]) rich_lines.prepend(["Roses are red"]) searched_rich_lines = debugger_cli_common.regex_find( rich_lines, "red", "bold") self.assertEqual({0: [(10, 13, "bold")]}, searched_rich_lines.font_attr_segs) rich_lines = debugger_cli_common.RichTextLines(["Violets are blue"]) rich_lines.prepend(["A poem"], font_attr_segs=[(0, 1, "underline")]) searched_rich_lines = debugger_cli_common.regex_find( rich_lines, "poem", "italic") self.assertEqual({0: [(0, 1, "underline"), (2, 6, "italic")]}, searched_rich_lines.font_attr_segs)
def testRegexFindOnPrependedLinesWorks(self): rich_lines = debugger_cli_common.RichTextLines(["Violets are blue"]) rich_lines.prepend(["Roses are red"]) searched_rich_lines = debugger_cli_common.regex_find( rich_lines, "red", "bold") self.assertEqual( {0: [(10, 13, "bold")]}, searched_rich_lines.font_attr_segs) rich_lines = debugger_cli_common.RichTextLines(["Violets are blue"]) rich_lines.prepend(["A poem"], font_attr_segs=[(0, 1, "underline")]) searched_rich_lines = debugger_cli_common.regex_find( rich_lines, "poem", "italic") self.assertEqual( {0: [(0, 1, "underline"), (2, 6, "italic")]}, searched_rich_lines.font_attr_segs)
def testRegexFindWithoutExistingFontAttrSegs(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow")], new_screen_output.font_attr_segs[0]) self.assertEqual([(8, 11, "yellow")], new_screen_output.font_attr_segs[1])
def testRegexFindWithNoMatches(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "infrared", "yellow") self.assertEqual({}, new_screen_output.font_attr_segs) self.assertEqual([], new_screen_output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY])
def testRegexFindWithoutExistingFontAttrSegs(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow")], new_screen_output.font_attr_segs[0]) self.assertEqual([(8, 11, "yellow")], new_screen_output.font_attr_segs[1])
def testRegexFindWithNoMatches(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "infrared", "yellow") self.assertEqual({}, new_screen_output.font_attr_segs) self.assertEqual([], new_screen_output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY])
def testRegexFindWithoutExistingFontAttrSegs(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow")], new_screen_output.font_attr_segs[0]) self.assertEqual([(8, 11, "yellow")], new_screen_output.font_attr_segs[1]) # Check field in annotations carrying a list of matching line indices. self.assertEqual([0, 1], new_screen_output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY])
def testRegexFindWithExistingFontAttrSegs(self): # Add a font attribute segment first. self._orig_screen_output.font_attr_segs[0] = [(9, 12, "red")] self.assertEqual(1, len(self._orig_screen_output.font_attr_segs)) new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow"), (9, 12, "red")], new_screen_output.font_attr_segs[0])
def testRegexFindWithExistingFontAttrSegs(self): # Add a font attribute segment first. self._orig_screen_output.font_attr_segs[0] = [(9, 12, "red")] self.assertEqual(1, len(self._orig_screen_output.font_attr_segs)) new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow"), (9, 12, "red")], new_screen_output.font_attr_segs[0])
def testRegexFindWithoutExistingFontAttrSegs(self): new_screen_output = debugger_cli_common.regex_find(self._orig_screen_output, "are", "yellow") self.assertEqual(2, len(new_screen_output.font_attr_segs)) self.assertEqual([(6, 9, "yellow")], new_screen_output.font_attr_segs[0]) self.assertEqual([(8, 11, "yellow")], new_screen_output.font_attr_segs[1]) # Check field in annotations carrying a list of matching line indices. self.assertEqual([0, 1], new_screen_output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY])
def _display_output(self, output, is_refresh=False, highlight_regex=None): """Display text output in a scrollable text pad. Args: output: A RichTextLines object that is the screen output text. is_refresh: (bool) Is this a refreshing display with existing output. highlight_regex: (str) Optional string representing the regex used to search and highlight in the current screen output. """ if highlight_regex: output = debugger_cli_common.regex_find( output, highlight_regex, font_attr=self._search_highlight_font_attr) else: self._curr_unwrapped_output = output self._curr_wrapped_output = debugger_cli_common.wrap_rich_text_lines( output, self._max_x - 1) # Limit number of lines displayed to avoid curses overflow problems. if self._curr_wrapped_output.num_lines() > self.max_output_lines: self._curr_wrapped_output = self._curr_wrapped_output.slice( 0, self.max_output_lines) self._curr_wrapped_output.lines.append( "Output cut off at %d lines!" % self.max_output_lines) self._curr_wrapped_output.font_attr_segs[self.max_output_lines] = [ (0, len(output.lines[-1]), "magenta") ] (self._output_pad, self._output_pad_height, self._output_pad_width) = self._display_lines( self._curr_wrapped_output, self._output_num_rows) # Size of view port on screen, which is always smaller or equal to the # screen size. self._output_pad_screen_height = self._output_num_rows - 1 self._output_pad_screen_width = self._max_x - 1 self._output_pad_screen_location = self.rectangle( top=self._output_top_row, left=0, bottom=self._output_top_row + self._output_num_rows, right=self._output_pad_screen_width) if is_refresh: self._scroll_output(self._SCROLL_REFRESH) else: self._output_pad_row = 0 self._scroll_output(self._SCROLL_HOME)
def _display_output(self, output, is_refresh=False, highlight_regex=None): """Display text output in a scrollable text pad. Args: output: A RichTextLines object that is the screen output text. is_refresh: (bool) Is this a refreshing display with existing output. highlight_regex: (str) Optional string representing the regex used to search and highlight in the current screen output. """ if highlight_regex: output = debugger_cli_common.regex_find( output, highlight_regex, font_attr=self._search_highlight_font_attr) else: self._curr_unwrapped_output = output self._curr_wrapped_output = debugger_cli_common.wrap_rich_text_lines( output, self._max_x - 1) # Limit number of lines displayed to avoid curses overflow problems. if self._curr_wrapped_output.num_lines() > self.max_output_lines: self._curr_wrapped_output = self._curr_wrapped_output.slice( 0, self.max_output_lines) self._curr_wrapped_output.lines.append("Output cut off at %d lines!" % self.max_output_lines) self._curr_wrapped_output.font_attr_segs[self.max_output_lines] = [ (0, len(output.lines[-1]), "magenta") ] (self._output_pad, self._output_pad_height, self._output_pad_width) = self._display_lines(self._curr_wrapped_output, self._output_num_rows) # Size of view port on screen, which is always smaller or equal to the # screen size. self._output_pad_screen_height = self._output_num_rows - 1 self._output_pad_screen_width = self._max_x - 1 self._output_pad_screen_location = self.rectangle( top=self._output_top_row, left=0, bottom=self._output_top_row + self._output_num_rows, right=self._output_pad_screen_width) if is_refresh: self._scroll_output(self._SCROLL_REFRESH) else: self._output_pad_row = 0 self._scroll_output(self._SCROLL_HOME)
def _display_output(self, output, is_refresh=False, highlight_regex=None): """Display text output in a scrollable text pad. Args: output: A RichTextLines object that is the screen output text. is_refresh: (bool) Is this a refreshing display with existing output. highlight_regex: (str) Optional string representing the regex used to search and highlight in the current screen output. """ if highlight_regex: output = debugger_cli_common.regex_find( output, highlight_regex, font_attr=self._search_highlight_font_attr) else: self._curr_unwrapped_output = output self._curr_wrapped_output = debugger_cli_common.wrap_rich_text_lines( output, self._max_x - 1) (self._output_pad, self._output_pad_height, self._output_pad_width) = self._display_lines(self._curr_wrapped_output, self._output_num_rows) # Size of view port on screen, which is always smaller or equal to the # screen size. self._output_pad_screen_height = self._output_num_rows - 1 self._output_pad_screen_width = self._max_x - 1 self._output_pad_screen_location = self.rectangle( top=self._output_top_row, left=0, bottom=self._output_top_row + self._output_num_rows, right=self._output_pad_screen_width) if is_refresh: self._scroll_output(self._SCROLL_REFRESH) else: self._output_pad_row = 0 self._scroll_output(self._SCROLL_HOME)
def _display_output(self, output, is_refresh=False, highlight_regex=None): """Display text output in a scrollable text pad. This method does some preprocessing on the text lines, render them on the screen and scroll to the appropriate line. These are done according to regex highlighting requests (if any), scroll-to-next-match requests (if any), and screen refresh requests (if any). TODO(cais): Separate these unrelated request to increase clarity and maintainability. Args: output: A RichTextLines object that is the screen output text. is_refresh: (bool) Is this a refreshing display with existing output. highlight_regex: (str) Optional string representing the regex used to search and highlight in the current screen output. """ if highlight_regex: try: output = debugger_cli_common.regex_find( output, highlight_regex, font_attr=self._SEARCH_HIGHLIGHT_FONT_ATTR) except ValueError as e: self._error_toast(str(e)) return if not is_refresh: # Perform new regex search on the current output. self._unwrapped_regex_match_lines = output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY] else: # Continue scrolling down. self._output_pad_row += 1 else: self._curr_unwrapped_output = output self._unwrapped_regex_match_lines = [] # Display output on the screen. wrapped_regex_match_lines = self._screen_display_output(output) # Now that the text lines are displayed on the screen scroll to the # appropriate line according to previous scrolling state and regex search # and highlighting state. if highlight_regex: next_match_line = -1 for match_line in wrapped_regex_match_lines: if match_line >= self._output_pad_row: next_match_line = match_line break if next_match_line >= 0: self._scroll_output( self._SCROLL_TO_LINE_INDEX, line_index=next_match_line) else: # Regex search found no match >= current line number. Display message # stating as such. self._toast("Pattern not found", color=self._ERROR_TOAST_COLOR_PAIR) elif is_refresh: self._scroll_output(self._SCROLL_REFRESH) else: self._output_pad_row = 0 self._scroll_output(self._SCROLL_HOME)
def _display_output(self, output, is_refresh=False, highlight_regex=None): """Display text output in a scrollable text pad. This method does some preprocessing on the text lines, render them on the screen and scroll to the appropriate line. These are done according to regex highlighting requests (if any), scroll-to-next-match requests (if any), and screen refresh requests (if any). TODO(cais): Separate these unrelated request to increase clarity and maintainability. Args: output: A RichTextLines object that is the screen output text. is_refresh: (bool) Is this a refreshing display with existing output. highlight_regex: (str) Optional string representing the regex used to search and highlight in the current screen output. """ if not output: return if highlight_regex: try: output = debugger_cli_common.regex_find( output, highlight_regex, font_attr=self._SEARCH_HIGHLIGHT_FONT_ATTR) except ValueError as e: self._error_toast(str(e)) return if not is_refresh: # Perform new regex search on the current output. self._unwrapped_regex_match_lines = output.annotations[ debugger_cli_common.REGEX_MATCH_LINES_KEY] else: # Continue scrolling down. self._output_pad_row += 1 else: self._curr_unwrapped_output = output self._unwrapped_regex_match_lines = [] # Display output on the screen. wrapped_regex_match_lines = self._screen_display_output(output) # Now that the text lines are displayed on the screen scroll to the # appropriate line according to previous scrolling state and regex search # and highlighting state. if highlight_regex: next_match_line = -1 for match_line in wrapped_regex_match_lines: if match_line >= self._output_pad_row: next_match_line = match_line break if next_match_line >= 0: self._scroll_output(self._SCROLL_TO_LINE_INDEX, line_index=next_match_line) else: # Regex search found no match >= current line number. Display message # stating as such. self._toast("Pattern not found", color=self._ERROR_TOAST_COLOR_PAIR) elif is_refresh: self._scroll_output(self._SCROLL_REFRESH) else: self._output_pad_row = 0 self._scroll_output(self._SCROLL_HOME)
def testInvalidRegex(self): with self.assertRaisesRegexp(ValueError, "Invalid regular expression"): debugger_cli_common.regex_find(self._orig_screen_output, "[", "yellow")
def testInvalidRegex(self): with self.assertRaisesRegexp(ValueError, "Invalid regular expression"): debugger_cli_common.regex_find(self._orig_screen_output, "[", "yellow")