From 79375d34b1082e9b5fa6997667c5ddbd1433ffed Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Mon, 29 Dec 2025 02:20:55 -0600 Subject: [PATCH] Added undo, redo, go-to, and duplicate lines commands; updated styles for line highlight color; cleanup --- src/core/widgets/code/commands/buffer_redo.py | 23 ++++++++ src/core/widgets/code/commands/buffer_undo.py | 23 ++++++++ .../widgets/code/commands/duplicate_line.py | 53 +++++++++++++++++++ .../code/commands/focus_left_sibling.py | 1 - .../code/commands/focus_right_sibling.py | 1 - .../widgets/code/commands/get_current_file.py | 20 +++++++ src/core/widgets/code/commands/get_text.py | 21 ++++++++ src/core/widgets/code/commands/go_to.py | 31 +++++++++++ .../code/commands/set_buffer_language.py | 23 ++++++++ .../widgets/code/commands/set_buffer_style.py | 23 ++++++++ src/core/widgets/code/get_filetype.py | 21 ++++++++ src/core/widgets/code/source_file.py | 10 ++-- .../usr/share/app_name/code-key-bindings.json | 12 +++++ .../code_styles/peacocks-in-space.xml | 3 +- .../code_styles/penguins-in-space.xml | 3 +- 15 files changed, 260 insertions(+), 8 deletions(-) create mode 100644 src/core/widgets/code/commands/buffer_redo.py create mode 100644 src/core/widgets/code/commands/buffer_undo.py create mode 100644 src/core/widgets/code/commands/duplicate_line.py create mode 100644 src/core/widgets/code/commands/get_current_file.py create mode 100644 src/core/widgets/code/commands/get_text.py create mode 100644 src/core/widgets/code/commands/go_to.py create mode 100644 src/core/widgets/code/commands/set_buffer_language.py create mode 100644 src/core/widgets/code/commands/set_buffer_style.py create mode 100644 src/core/widgets/code/get_filetype.py diff --git a/src/core/widgets/code/commands/buffer_redo.py b/src/core/widgets/code/commands/buffer_redo.py new file mode 100644 index 0000000..b0c738f --- /dev/null +++ b/src/core/widgets/code/commands/buffer_redo.py @@ -0,0 +1,23 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Buffer Redo Command") + + buffer = view.get_buffer() + undo_manager = buffer.get_undo_manager() + + if undo_manager.can_redo(): + buffer.redo() diff --git a/src/core/widgets/code/commands/buffer_undo.py b/src/core/widgets/code/commands/buffer_undo.py new file mode 100644 index 0000000..87688e2 --- /dev/null +++ b/src/core/widgets/code/commands/buffer_undo.py @@ -0,0 +1,23 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Buffer Undo Command") + + buffer = view.get_buffer() + undo_manager = buffer.get_undo_manager() + + if undo_manager.can_undo(): + buffer.undo() diff --git a/src/core/widgets/code/commands/duplicate_line.py b/src/core/widgets/code/commands/duplicate_line.py new file mode 100644 index 0000000..10e89d9 --- /dev/null +++ b/src/core/widgets/code/commands/duplicate_line.py @@ -0,0 +1,53 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Duplicate Line Command") + + buffer = view.get_buffer() + + if not buffer.get_has_selection(): + had_selection = False + itr = buffer.get_iter_at_mark( buffer.get_insert() ) + start_itr = itr.copy() + end_itr = itr.copy() + start_line = itr.get_line() + 1 + start_char = itr.get_line_offset() + else: + had_selection = True + start_itr, end_itr = buffer.get_selection_bounds() + sline = start_itr.get_line() + eline = end_itr.get_line() + start_line = eline + 1 + start_char = start_itr.get_line_offset() + end_char = end_itr.get_line_offset() + range_line_size = eline - sline + + start_itr.backward_visible_line() + start_itr.forward_line() + end_itr.forward_line() + end_itr.backward_char() + + line_str = buffer.get_slice(start_itr, end_itr, True) + end_itr.forward_char() + buffer.insert(end_itr, f"{line_str}\n", -1) + + if not had_selection: + new_itr = buffer.get_iter_at_line_offset(start_line, start_char) + buffer.place_cursor(new_itr) + else: + new_itr = buffer.get_iter_at_line_offset(start_line, start_char) + new_end_itr = buffer.get_iter_at_line_offset((start_line + range_line_size), end_char) + buffer.select_range(new_itr, new_end_itr) diff --git a/src/core/widgets/code/commands/focus_left_sibling.py b/src/core/widgets/code/commands/focus_left_sibling.py index 1e9df2d..42790c4 100644 --- a/src/core/widgets/code/commands/focus_left_sibling.py +++ b/src/core/widgets/code/commands/focus_left_sibling.py @@ -17,4 +17,3 @@ def execute( logger.debug("Focus Left Sibling Command") if not view.sibling_left: return view.sibling_left.grab_focus() - view.sibling_left.command.exec("set_miniview") diff --git a/src/core/widgets/code/commands/focus_right_sibling.py b/src/core/widgets/code/commands/focus_right_sibling.py index cb723ec..fbfbb48 100644 --- a/src/core/widgets/code/commands/focus_right_sibling.py +++ b/src/core/widgets/code/commands/focus_right_sibling.py @@ -17,4 +17,3 @@ def execute( logger.debug("Focus Right Sibling Command") if not view.sibling_right: return view.sibling_right.grab_focus() - view.sibling_right.command.exec("set_miniview") \ No newline at end of file diff --git a/src/core/widgets/code/commands/get_current_file.py b/src/core/widgets/code/commands/get_current_file.py new file mode 100644 index 0000000..6d28e2b --- /dev/null +++ b/src/core/widgets/code/commands/get_current_file.py @@ -0,0 +1,20 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Get Current File Command") + + buffer = view.get_buffer() + return view.files_manager.get_file(buffer) diff --git a/src/core/widgets/code/commands/get_text.py b/src/core/widgets/code/commands/get_text.py new file mode 100644 index 0000000..4a35bd8 --- /dev/null +++ b/src/core/widgets/code/commands/get_text.py @@ -0,0 +1,21 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Get Text Command") + + buffer = view.get_buffer() + start_itr, end_itr = buffer.get_bounds() + return buffer.get_text(start_itr, end_itr, True) diff --git a/src/core/widgets/code/commands/go_to.py b/src/core/widgets/code/commands/go_to.py new file mode 100644 index 0000000..81f9912 --- /dev/null +++ b/src/core/widgets/code/commands/go_to.py @@ -0,0 +1,31 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Go-To Command") + + file = view.command.exec("get_current_file") + gfile = file.get_location() + uri = gfile.get_uri() + + buffer = view.get_buffer() + iter = buffer.get_iter_at_mark( buffer.get_insert() ) + line = iter.get_line() + offset = iter.get_line_offset() + + event_system.emit( + "textDocument/definition", + (view, file.ftype, uri, line, offset,) + ) diff --git a/src/core/widgets/code/commands/set_buffer_language.py b/src/core/widgets/code/commands/set_buffer_language.py new file mode 100644 index 0000000..299b23c --- /dev/null +++ b/src/core/widgets/code/commands/set_buffer_language.py @@ -0,0 +1,23 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View, + language: str +): + logger.debug("Set Buffer Language Command") + + buffer = editor.get_buffer() + buffer.set_language( + view.language_manager.get_language(language) + ) diff --git a/src/core/widgets/code/commands/set_buffer_style.py b/src/core/widgets/code/commands/set_buffer_style.py new file mode 100644 index 0000000..e12a030 --- /dev/null +++ b/src/core/widgets/code/commands/set_buffer_style.py @@ -0,0 +1,23 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View, + style: str +): + logger.debug("Set Buffer Style Command") + + buffer = editor.get_buffer() + buffer.set_style_scheme( + view.style_scheme_manager.get_scheme(style) + ) diff --git a/src/core/widgets/code/get_filetype.py b/src/core/widgets/code/get_filetype.py new file mode 100644 index 0000000..f19fed0 --- /dev/null +++ b/src/core/widgets/code/get_filetype.py @@ -0,0 +1,21 @@ +# Python imports + +# Lib imports +import gi + +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports + + + +def execute( + view: GtkSource.View = None +): + logger.debug("Get File Type Command") + + buffer = view.get_buffer() + file = view.files_manager.get_file(buffer) + return file.ftype diff --git a/src/core/widgets/code/source_file.py b/src/core/widgets/code/source_file.py index bf9f5e5..2304202 100644 --- a/src/core/widgets/code/source_file.py +++ b/src/core/widgets/code/source_file.py @@ -86,9 +86,8 @@ class SourceFile(GtkSource.File, ObservableMixin): if not gfile: return with open(gfile.get_path(), 'w') as f: - start_itr = self.buffer.get_start_iter() - end_itr = self.buffer.get_end_iter() - text = self.buffer.get_text(start_itr, end_itr, True) + start_itr, end_itr = self.buffer.get_bounds() + text = self.buffer.get_text(start_itr, end_itr, True) f.write(text) @@ -99,9 +98,12 @@ class SourceFile(GtkSource.File, ObservableMixin): if not gfile: return self.set_path(gfile) - data = gfile.load_bytes()[0].get_data().decode("UTF-8") + data = gfile.load_bytes()[0].get_data().decode("UTF-8") + undo_manager = self.buffer.get_undo_manager() + undo_manager.begin_not_undoable_action() self.buffer.insert_at_cursor(data) + undo_manager.end_not_undoable_action() def set_path(self, gfile: Gio.File): if not gfile: return diff --git a/user_config/usr/share/app_name/code-key-bindings.json b/user_config/usr/share/app_name/code-key-bindings.json index bd790a1..e35ca74 100644 --- a/user_config/usr/share/app_name/code-key-bindings.json +++ b/user_config/usr/share/app_name/code-key-bindings.json @@ -18,12 +18,24 @@ "cut_to_temp_buffer": { "held": "k" }, + "duplicate_line": { + "held": "d" + }, + "go_to": { + "released": "g" + }, "paste_temp_buffer": { "held": "u" }, "new_file": { "released": "t" }, + "buffer_undo": { + "held": "z" + }, + "buffer_redo": { + "held": "y" + }, "open_files": { "released": "o" }, diff --git a/user_config/usr/share/app_name/code_styles/peacocks-in-space.xml b/user_config/usr/share/app_name/code_styles/peacocks-in-space.xml index 7128c59..9f10a6b 100644 --- a/user_config/usr/share/app_name/code_styles/peacocks-in-space.xml +++ b/user_config/usr/share/app_name/code_styles/peacocks-in-space.xml @@ -2,7 +2,8 @@ ITDominator An attempted clone of Dayle Rees' Peacocks In Space theme. -