diff --git a/src/tui/mode/helix.zig b/src/tui/mode/helix.zig index 5187425..dcd3289 100644 --- a/src/tui/mode/helix.zig +++ b/src/tui/mode/helix.zig @@ -484,11 +484,11 @@ fn select_cursel_till_char_left_helix(root: Buffer.Root, cursel: *CurSel, ctx: c var moving_cursor: Cursor = cursel.*.cursor; var begin = cursel.*.cursor; move_cursor_till_char_left_beyond_eol(root, &moving_cursor, metrics, ctx) catch return; + + // Character found, selecting Editor.move_cursor_right(root, &begin, metrics) catch { //At end of file, it's ok }; - - // Character found, selecting moving_cursor.target = moving_cursor.col; const sel = try cursel.enable_selection(root, metrics); sel.begin = begin; diff --git a/src/tui/mode/mini/move_to_char.zig b/src/tui/mode/mini/move_to_char.zig index d32f00c..1d76631 100644 --- a/src/tui/mode/mini/move_to_char.zig +++ b/src/tui/mode/mini/move_to_char.zig @@ -29,6 +29,7 @@ const Direction = enum { const Operation = enum { move, select, + extend, }; pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tui.MiniMode } { @@ -36,7 +37,18 @@ pub fn create(allocator: Allocator, ctx: command.Context) !struct { tui.Mode, tu _ = ctx.args.match(.{tp.extract(&operation_command)}) catch return error.InvalidMoveToCharArgument; const direction: Direction = if (std.mem.indexOf(u8, operation_command, "_left")) |_| .left else .right; - const operation: Operation = if (tui.get_active_editor()) |editor| if (editor.get_primary().selection) |_| .select else .move else .move; + var operation: Operation = undefined; + if (std.mem.indexOf(u8, operation_command, "extend_")) |_| { + operation = .extend; + } else if (std.mem.indexOf(u8, operation_command, "select_")) |_| { + operation = .select; + } else if (tui.get_active_editor()) |editor| if (editor.get_primary().selection) |_| { + operation = .select; + } else { + operation = .move; + } else { + operation = .move; + } const self = try allocator.create(Self); errdefer allocator.destroy(self); @@ -70,6 +82,10 @@ fn name(self: *Self) []const u8 { .left => "󰒅 ↶ select", .right => "󰒅 ↷ select", }, + .extend => switch (self.direction) { + .left => "󰒅 ↶ extend", + .right => "󰒅 ↷ extend", + }, }; } diff --git a/test/tests_helix.zig b/test/tests_helix.zig index f94e63a..a69501f 100644 --- a/test/tests_helix.zig +++ b/test/tests_helix.zig @@ -2,6 +2,7 @@ const std = @import("std"); const Buffer = @import("Buffer"); const Cursor = @import("Buffer").Cursor; const Result = @import("command").Result; +const fmt_command = @import("command").fmt; const helix = @import("tui").exports.mode.helix; const Editor = @import("tui").exports.editor.Editor; @@ -156,3 +157,62 @@ test "long_words_movement" { try apply_movements(move.moves, root, &the_cursor, metrics(), move.row, move.col); } } + +test "to_char_right_beyond_eol" { + const buffer = try Buffer.create(a); + defer buffer.deinit(); + buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized)); + const root: Buffer.Root = buffer.root; + the_cursor.col = 0; + the_cursor.row = 0; + const expected_error = error.Stop; + + // Not found to begin of file + var result = helix.test_internal.move_cursor_to_char_left_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"a"})); + try std.testing.expectError(expected_error, result); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(0, the_cursor.col); + + // Move found in the next line + try helix.test_internal.move_cursor_to_char_right_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"T"})); + try std.testing.expectEqual(1, the_cursor.row); + try std.testing.expectEqual(11, the_cursor.col); + + // Move found in the previous line + try helix.test_internal.move_cursor_to_char_left_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"t"})); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(51, the_cursor.col); + + // Not found to end of buffer, cursor not moved + result = helix.test_internal.move_cursor_to_char_right_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"Z"})); + try std.testing.expectError(expected_error, result); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(51, the_cursor.col); + + // Not found to begin of buffer + result = helix.test_internal.move_cursor_to_char_left_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"Z"})); + try std.testing.expectError(expected_error, result); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(51, the_cursor.col); + + // till char difference + // Move found in the next line + try helix.test_internal.move_cursor_till_char_right_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"T"})); + try std.testing.expectEqual(1, the_cursor.row); + try std.testing.expectEqual(10, the_cursor.col); + + // Move found in the previous line + try helix.test_internal.move_cursor_till_char_left_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"t"})); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(52, the_cursor.col); + + // Move found in the same line + try helix.test_internal.move_cursor_till_char_left_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"x"})); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(46, the_cursor.col); + + // Move found in the same line + try helix.test_internal.move_cursor_till_char_right_beyond_eol(root, &the_cursor, metrics(), fmt_command(.{"t"})); + try std.testing.expectEqual(0, the_cursor.row); + try std.testing.expectEqual(50, the_cursor.col); +}