Fix line-based editing behavior for cut and duplicate commands

- Cut to temp buffer:
  - Respect selections by expanding to full line boundaries
  - Normalize end iterator to include full line + newline
  - Ensure consistent newline handling for last line
  - Preserve cursor position after delete
  - Prevent line merging when accumulating cut buffer

- Duplicate line:
  - Simplify logic using line-based iter APIs
  - Fix incorrect selection handling and off-by-one issues
  - Ensure full-line duplication for both selection and cursor cases
  - Correct cursor/selection restoration after duplication
This commit is contained in:
2026-04-15 23:05:05 -05:00
parent 383db1270e
commit 7ab919f925
3 changed files with 74 additions and 48 deletions

View File

@@ -14,31 +14,44 @@ from .helpers import clear_temp_cut_buffer_delayed, set_temp_cut_buffer_delayed
class Handler:
@staticmethod
def execute(
view: GtkSource.View,
*args,
**kwargs
):
def execute(view: GtkSource.View, *args, **kwargs):
logger.debug("Command: Cut to Temp Buffer")
clear_temp_cut_buffer_delayed(view)
buffer = view.get_buffer()
itr = buffer.get_iter_at_mark(buffer.get_insert())
start_itr = itr.copy()
start_itr.set_line_offset(0)
if buffer.get_has_selection():
start_itr, end_itr = buffer.get_selection_bounds()
end_itr = start_itr.copy()
if not end_itr.forward_line():
end_itr = buffer.get_end_iter()
start_itr.set_line_offset(0)
if not end_itr.ends_line():
end_itr.forward_to_line_end()
if not end_itr.is_end():
end_itr.forward_char()
else:
itr = buffer.get_iter_at_mark(buffer.get_insert())
start_itr = itr.copy()
start_itr.set_line_offset(0)
end_itr = start_itr.copy()
if not end_itr.forward_line():
end_itr = buffer.get_end_iter()
if not hasattr(view, "_cut_buffer"):
view._cut_buffer = ""
line_str = buffer.get_text(start_itr, end_itr, True)
view._cut_buffer += line_str
text = buffer.get_text(start_itr, end_itr, True)
if not text.endswith("\n"):
text += "\n"
view._cut_buffer += text
buffer.delete(start_itr, end_itr)
buffer.place_cursor(start_itr)
set_temp_cut_buffer_delayed(view)
set_temp_cut_buffer_delayed(view)