From 03b02316d0e3d6cec2bdfcdb514b433758322c93 Mon Sep 17 00:00:00 2001 From: Silas Kraume Date: Wed, 4 Dec 2024 16:58:32 +0100 Subject: [PATCH] added cursor column preservation in editor --- cat_win/src/service/editor.py | 30 +++++++++++++++++----- cat_win/src/service/helper/editorhelper.py | 2 ++ cat_win/src/service/hexeditor.py | 4 ++- cat_win/tests/src/service/test_editor.py | 10 ++++---- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/cat_win/src/service/editor.py b/cat_win/src/service/editor.py index 74dccaa..b41a21a 100644 --- a/cat_win/src/service/editor.py +++ b/cat_win/src/service/editor.py @@ -75,6 +75,7 @@ def __init__(self, file: Path, display_name: str) -> None: # current cursor position self.cpos = Position(0, 0) + self.snap_pos = Position(0, 0) # window position (top-left) self.wpos = Position(0, 0) # second cursor for selection area @@ -156,7 +157,6 @@ def _get_clipboard(self) -> bool: clipboard = Clipboard.get() if clipboard is None: self.error_bar = 'An error occured pasting the clipboard!' - return None return clipboard def _key_enter(self, _) -> str: @@ -1268,11 +1268,17 @@ def _function_search(self) -> None: return self._action_find(True) + def _function_search_r(self) -> None: + self.error_bar = 'not implemented yet!' + def _function_replace(self) -> None: if not self.search: return self._action_replace(True) + def _function_replace_r(self) -> None: + self.error_bar = 'not implemented yet!' + def _get_new_char(self): """ get next char @@ -1335,17 +1341,27 @@ def _get_color(self, c_id: int) -> int: return 0 return curses.color_pair(c_id) - def _enforce_boundaries(self) -> None: + def _enforce_boundaries(self, key: bytes) -> None: """ - set/enforce the boundaries + Enforce boundary constraints for cursor and window positions. + Adjusts cursor snap position, window position and column boundaries + based on cursor movement and window size. + + Parameters: + key (bytes): + The key that was pressed last """ max_y, max_x = self.getxymax() # fix cursor position (makes movement hotkeys easier) - row = self.window_content[self.cpos.row] if ( + rowlen = len(self.window_content[self.cpos.row]) if( self.cpos.row < len(self.window_content) - ) else None - rowlen = len(row) if row is not None else 0 + ) else 0 + if self.snap_pos.row == self.cpos.row or key not in MOVE_HOTKEYS | SELECT_HOTKEYS: + self.snap_pos.set_pos(self.cpos.get_pos()) + else: + self.snap_pos.row = self.cpos.row + self.cpos.col = min(self.snap_pos.col, rowlen) self.cpos.col = min(self.cpos.col, rowlen) if not self.scrolling: @@ -1520,7 +1536,7 @@ def _run(self) -> None: elif key not in INDENT_HOTKEYS | HISTORY_HOTKEYS: self.selecting = False - self._enforce_boundaries() + self._enforce_boundaries(key) self.history.add(key, self.deleted_line, pre_cpos, self.cpos.get_pos(), diff --git a/cat_win/src/service/helper/editorhelper.py b/cat_win/src/service/helper/editorhelper.py index 64469eb..052934a 100644 --- a/cat_win/src/service/helper/editorhelper.py +++ b/cat_win/src/service/helper/editorhelper.py @@ -181,6 +181,8 @@ def initscr(): b'KEY_F(1)' : b'_function_help', b'KEY_F(2)' : b'_function_replace', b'KEY_F(3)' : b'_function_search', + b'KEY_F(14)' : b'_function_replace_r', + b'KEY_F(15)' : b'_function_search_r', } # translates key-inputs to pre-defined actions/methods KEY_HOTKEYS = set(v for v in UNIFY_HOTKEYS.values() if v.startswith(b'_key' )) diff --git a/cat_win/src/service/hexeditor.py b/cat_win/src/service/hexeditor.py index 64ce2f2..08068d0 100644 --- a/cat_win/src/service/hexeditor.py +++ b/cat_win/src/service/hexeditor.py @@ -181,7 +181,6 @@ def _get_clipboard(self) -> bool: clipboard = Clipboard.get() if clipboard is None: self.error_bar = 'An error occured pasting the clipboard!' - return None return clipboard def _key_dc(self, _) -> None: @@ -825,6 +824,9 @@ def _function_search(self) -> None: return self._action_find(True) + def _function_search_r(self) -> None: + self.error_bar = 'not implemented yet!' + def _get_next_char(self) -> tuple: """ get next char diff --git a/cat_win/tests/src/service/test_editor.py b/cat_win/tests/src/service/test_editor.py index c62ddac..e7a2512 100644 --- a/cat_win/tests/src/service/test_editor.py +++ b/cat_win/tests/src/service/test_editor.py @@ -995,30 +995,30 @@ def test__get_new_char(self): def test__enforce_boundaries(self): editor = Editor('', 'X' * 300) editor.cpos.set_pos((4, 205)) - self.assertEqual(editor._enforce_boundaries(), None) + self.assertEqual(editor._enforce_boundaries(b''), None) self.assertEqual(editor.cpos.get_pos(), (4, 200)) editor.cpos.set_pos((4, 0)) editor.wpos.set_pos((6, 0)) - self.assertEqual(editor._enforce_boundaries(), None) + self.assertEqual(editor._enforce_boundaries(b''), None) self.assertEqual(editor.cpos.get_pos(), (4, 0)) self.assertEqual(editor.wpos.get_pos(), (4, 0)) editor.cpos.set_pos((34, 0)) editor.wpos.set_pos((0, 0)) - self.assertEqual(editor._enforce_boundaries(), None) + self.assertEqual(editor._enforce_boundaries(b''), None) self.assertEqual(editor.cpos.get_pos(), (34, 0)) self.assertEqual(editor.wpos.get_pos(), (5, 0)) editor.cpos.set_pos((7, 4)) editor.wpos.set_pos((5, 6)) - self.assertEqual(editor._enforce_boundaries(), None) + self.assertEqual(editor._enforce_boundaries(b''), None) self.assertEqual(editor.cpos.get_pos(), (7, 4)) self.assertEqual(editor.wpos.get_pos(), (5, 4)) editor.cpos.set_pos((7, 180)) editor.wpos.set_pos((5, 0)) - self.assertEqual(editor._enforce_boundaries(), None) + self.assertEqual(editor._enforce_boundaries(b''), None) self.assertEqual(editor.cpos.get_pos(), (7, 180)) self.assertEqual(editor.wpos.get_pos(), (5, 61))