refactor: hx paste(before, replace, after)

Code simplification and zig idiomatics to improve code readability.
This commit is contained in:
Igor Támara 2025-10-13 15:19:27 -05:00 committed by CJ van den Berg
parent f288d24e13
commit 7faea783f3
3 changed files with 57 additions and 56 deletions

View file

@ -131,7 +131,7 @@
["g s", "smart_move_begin"],
["g d", "goto_definition"],
["g y", "goto_type_definition"],
["g r", "goto_reference"],
["g r", "references"],
["g i", "goto_implementation"],
["g t", "goto_window_top"],
["g c", "goto_window_center"],
@ -426,7 +426,7 @@
["g s", "smart_move_begin"],
["g d", "goto_definition"],
["g y", "goto_type_definition"],
["g r", "goto_reference"],
["g r", "references"],
["g i", "goto_implementation"],
["g t", "goto_window_top"],
["g c", "goto_window_center"],

View file

@ -2229,7 +2229,7 @@ pub const Editor = struct {
return false;
}
fn is_eol_right(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
pub fn is_eol_right(root: Buffer.Root, cursor: *const Cursor, metrics: Buffer.Metrics) bool {
const line_width = root.line_width(cursor.row, metrics) catch return true;
if (cursor.col >= line_width)
return true;
@ -2252,15 +2252,6 @@ pub const Editor = struct {
return false;
}
pub fn move_cursor_carriage_return(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
if (is_eol_right(root, cursor, metrics)) {
try move_cursor_right(root, cursor, metrics);
} else {
try move_cursor_down(root, cursor, metrics);
try move_cursor_begin(root, cursor, metrics);
}
}
pub fn move_cursor_left(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
try cursor.move_left(root, metrics);
}
@ -2317,7 +2308,7 @@ pub const Editor = struct {
if (is_eol_vim(root, cursor, metrics)) try move_cursor_left_vim(root, cursor, metrics);
}
fn move_cursor_down(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) !void {
pub fn move_cursor_down(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) !void {
cursor.move_down(root, metrics) catch |e| switch (e) {
error.Stop => cursor.move_end(root, metrics),
};

View file

@ -408,7 +408,6 @@ const cmds_ = struct {
pub fn paste_clipboard_before(_: *void, ctx: Ctx) Result {
try paste_helix(ctx, insert_before);
}
pub const paste_clipboard_before_meta: Meta = .{ .description = "Paste from clipboard before selection" };
};
@ -443,85 +442,75 @@ fn move_cursor_word_right_end_helix(root: Buffer.Root, cursor: *Cursor, metrics:
try cursor.move_right(root, metrics);
}
fn insert_before(editor: *Editor, root: Buffer.Root, cursel: *CurSel, s: []const u8, allocator: Allocator) !Buffer.Root {
fn insert_before(editor: *Editor, root: Buffer.Root, cursel: *CurSel, text: []const u8, allocator: Allocator) !Buffer.Root {
var root_: Buffer.Root = root;
const cursor: *Cursor = &cursel.cursor;
cursel.check_selection(root, editor.metrics);
if (s[s.len - 1] == '\n') {
if (cursel.selection) |*sel_| {
sel_.*.normalize();
cursor.move_to(root, sel_.*.begin.row, sel_.*.begin.col, editor.metrics) catch {};
} else {
if (cursel.selection) |sel_| {
var sel = sel_;
sel.normalize();
cursor.move_to(root, sel.begin.row, sel.begin.col, editor.metrics) catch {};
if (text[text.len - 1] == '\n') {
cursor.move_begin();
}
} else {
if (cursel.selection) |*sel_| {
sel_.*.normalize();
cursor.move_to(root, sel_.*.begin.row, sel_.*.begin.col, editor.metrics) catch {};
}
} else if (text[text.len - 1] == '\n') {
cursor.move_begin();
}
cursel.disable_selection_normal();
const begin = cursel.cursor;
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, s, allocator, editor.metrics);
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, text, allocator, editor.metrics);
cursor.target = cursor.col;
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, s.len);
cursel.selection = Selection{ .begin = begin, .end = cursor.* };
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, text.len);
return root_;
}
fn insert_replace_selection(editor: *Editor, root: Buffer.Root, cursel: *CurSel, s: []const u8, allocator: Allocator) !Buffer.Root {
fn insert_replace_selection(editor: *Editor, root: Buffer.Root, cursel: *CurSel, text: []const u8, allocator: Allocator) !Buffer.Root {
// replaces the selection, if no selection, replaces the current
// character and sets the selection to the replacement text
var root_: Buffer.Root = root;
cursel.check_selection(root, editor.metrics);
if (cursel.selection) |_| {
root_ = try editor.delete_selection(root, cursel, allocator);
} else {
// Replace current character when no explicit selection
try Editor.with_selection_const(root, move_noop, cursel, editor.metrics);
root_ = try editor.delete_selection(root, cursel, allocator);
if (cursel.selection == null) {
// Select current character to replace it
Editor.with_selection_const(root, move_noop, cursel, editor.metrics) catch {};
}
root_ = editor.delete_selection(root, cursel, allocator) catch root;
const cursor = &cursel.cursor;
const begin = cursel.cursor;
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, s, allocator, editor.metrics);
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, text, allocator, editor.metrics);
cursor.target = cursor.col;
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, s.len);
cursel.selection = Selection{ .begin = begin, .end = cursor.* };
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, text.len);
return root_;
}
fn insert_after(editor: *Editor, root: Buffer.Root, cursel: *CurSel, s: []const u8, allocator: Allocator) !Buffer.Root {
fn insert_after(editor: *Editor, root: Buffer.Root, cursel: *CurSel, text: []const u8, allocator: Allocator) !Buffer.Root {
var root_: Buffer.Root = root;
const cursor = &cursel.cursor;
cursel.check_selection(root, editor.metrics);
if (s[s.len - 1] == '\n') {
if (cursel.selection) |*sel_| {
sel_.*.normalize();
if (sel_.*.end.row == sel_.*.begin.row or sel_.*.end.col != 0) {
cursel.disable_selection_normal();
Editor.move_cursor_carriage_return(root, cursor, editor.metrics) catch {};
}
} else {
cursel.disable_selection_normal();
Editor.move_cursor_carriage_return(root, cursor, editor.metrics) catch {};
}
if (text[text.len - 1] == '\n') {
move_cursor_carriage_return(root, cursel.*, cursor, editor.metrics) catch {};
} else {
if (cursel.selection) |*sel_| {
sel_.*.normalize();
cursor.move_to(root, sel_.*.end.row, sel_.*.end.col, editor.metrics) catch {};
if (cursel.selection) |sel_| {
var sel = sel_;
sel.normalize();
cursor.move_to(root, sel.end.row, sel.end.col, editor.metrics) catch {};
} else {
cursor.move_right(root_, editor.metrics) catch {};
}
cursel.disable_selection_normal();
}
cursel.disable_selection_normal();
const begin = cursel.cursor;
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, s, allocator, editor.metrics);
cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, text, allocator, editor.metrics);
cursor.target = cursor.col;
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, s.len);
cursel.selection = Selection{ .begin = begin, .end = cursor.* };
editor.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, text.len);
return root_;
}
@ -668,6 +657,7 @@ fn copy_internal_helix() command.Result {
try text.appendSlice(editor.allocator, serial_separator);
}
try text.appendSlice(editor.allocator, copy_text);
editor.allocator.free(copy_text);
}
};
if (text.items.len > 0) {
@ -680,6 +670,26 @@ fn copy_internal_helix() command.Result {
}
}
fn move_cursor_carriage_return(root: Buffer.Root, cursel: CurSel, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
if (is_cursel_from_extend_line_below(cursel)) {
//The cursor is already beginning next line
return;
}
if (!Editor.is_eol_right(root, cursor, metrics)) {
try Editor.move_cursor_end(root, cursor, metrics);
}
try Editor.move_cursor_right(root, cursor, metrics);
}
fn is_cursel_from_extend_line_below(cursel: CurSel) bool {
if (cursel.selection) |sel_| {
var sel = sel_;
sel.normalize();
return sel.end.row != sel.begin.row and sel.end.col == 0;
}
return false;
}
const private = @This();
// exports for unittests
pub const test_internal = struct {