diff --git a/src/prompt_toolkit/document.py b/src/prompt_toolkit/document.py index ba34c0c52..c4c43f74e 100644 --- a/src/prompt_toolkit/document.py +++ b/src/prompt_toolkit/document.py @@ -14,6 +14,16 @@ from .filters import vi_mode from .selection import PasteMode, SelectionState, SelectionType +branch_coverage_next = { + "find_next_1": False, + "find_next_2": False, +} + +branch_coverage_prev = { + "find_prev_1": False, + "find_prev_2": False +} + branch_coverage_translate = { "translate_1": False, # Branch for successful try block execution "translate_2": False, # Branch for entering except block @@ -26,7 +36,6 @@ "Document", ] - # Regex for finding "words" in documents. (We consider a group of alnum # characters a word, but also a group of special characters a word, as long as # it doesn't contain a space.) @@ -672,7 +681,7 @@ def find_previous_word_ending( except StopIteration: pass return None - + def find_next_matching_line( self, match_func: Callable[[str], bool], count: int = 1 ) -> int | None: @@ -684,10 +693,12 @@ def find_next_matching_line( for index, line in enumerate(self.lines[self.cursor_position_row + 1 :]): if match_func(line): + branch_coverage_next["find_next_1"] = True result = 1 + index count -= 1 if count == 0: + branch_coverage_next["find_next_2"] = True break return result @@ -703,14 +714,16 @@ def find_previous_matching_line( for index, line in enumerate(self.lines[: self.cursor_position_row][::-1]): if match_func(line): + branch_coverage_prev["find_prev_1"] = True result = -1 - index count -= 1 if count == 0: + branch_coverage_prev["find_prev_2"] = True break return result - + def get_cursor_left_position(self, count: int = 1) -> int: """ Relative position for cursor left. @@ -1200,3 +1213,4 @@ def insert_before(self, text: str) -> Document: cursor_position=self.cursor_position + len(text), selection=selection_state, ) + diff --git a/tests/test_find_next_matching_line.py b/tests/test_find_next_matching_line.py new file mode 100644 index 000000000..7795d2b26 --- /dev/null +++ b/tests/test_find_next_matching_line.py @@ -0,0 +1,53 @@ +from prompt_toolkit.document import Document, branch_coverage_next + +def print_coverage(): + print("\nCoverage report:") + hit_branches = sum(branch_coverage_next.values()) + total_branches = len(branch_coverage_next) + coverage_percentage = (hit_branches / total_branches) * 100 + for branch, hit in branch_coverage_next.items(): + print(f"{branch} was {'hit' if hit else 'not hit'}") + print(f"Coverage: {hit_branches}/{total_branches} branches hit ({coverage_percentage:.2f}%)\n") + +test_cases = [ + { + "description": "Find the second next empty line", + "text": "line 1\n\nline 3\n\nline 5", + "cursor_position": 0, + "match_func": lambda line: line.strip() == "", + "count": 2, + "expected_result": 3 + }, + { + "description": "No match found", + "text": "line 1\nline 2\nline 3\nline 4", + "cursor_position": 0, + "match_func": lambda line: line.strip() == "", + "count": 1, + "expected_result": None + }, + { + "description": "Match after cursor position", + "text": "line 1\nline 2\n\nline 4", + "cursor_position": 7, + "match_func": lambda line: line.strip() == "", + "count": 1, + "expected_result": 1 + } +] + +for case in test_cases: + document = Document(text=case["text"], cursor_position=case["cursor_position"]) + result = document.find_next_matching_line(case["match_func"], case["count"]) + assert result == case["expected_result"], f"Test failed for: {case['description']}" + + print("\n") + print(f"Test case: {case['description']}") + print(f"Expected result: {case['expected_result']}") + print(f"Actual result: {result}") + print("Branches hit:") + for branch, hit in branch_coverage_next.items(): + if hit: + print(f" {branch}") + +print_coverage() \ No newline at end of file diff --git a/tests/test_find_prev_matching_line.py b/tests/test_find_prev_matching_line.py new file mode 100644 index 000000000..ba2f875b6 --- /dev/null +++ b/tests/test_find_prev_matching_line.py @@ -0,0 +1,53 @@ +from prompt_toolkit.document import Document, branch_coverage_prev + +def print_coverage(): + print("\nCoverage report:") + hit_branches = sum(branch_coverage_prev.values()) + total_branches = len(branch_coverage_prev) + coverage_percentage = (hit_branches / total_branches) * 100 + for branch, hit in branch_coverage_prev.items(): + print(f"{branch} was {'hit' if hit else 'not hit'}") + print(f"Coverage: {hit_branches}/{total_branches} branches hit ({coverage_percentage:.2f}%)\n") + +test_cases = [ + { + "description": "Find the second previous empty line", + "text": "line 1\n\nline 3\n\nline 5", + "cursor_position": 18, + "match_func": lambda line: line.strip() == "", + "count": 2, + "expected_result": -3 + }, + { + "description": "No match found", + "text": "line 1\nline 2\nline 3\nline 4", + "cursor_position": 10, + "match_func": lambda line: line.strip() == "", + "count": 1, + "expected_result": None + }, + { + "description": "Match before cursor position", + "text": "line 1\n\nline 3\nline 4", + "cursor_position": 18, + "match_func": lambda line: line.strip() == "", + "count": 1, + "expected_result": -2 + } +] + +for case in test_cases: + document = Document(text=case["text"], cursor_position=case["cursor_position"]) + result = document.find_previous_matching_line(case["match_func"], case["count"]) + assert result == case["expected_result"], f"Test failed for: {case['description']}" + + print("\n") + print(f"Test case: {case['description']}") + print(f"Expected result: {case['expected_result']}") + print(f"Actual result: {result}") + print("Branches hit:") + for branch, hit in branch_coverage_prev.items(): + if hit: + print(f" {branch}") + +print_coverage() \ No newline at end of file