feat: Vim mode: till_char (#224)

This commit is contained in:
Levi 2025-04-08 15:05:09 -03:00 committed by GitHub
parent 3ce4aaf33a
commit 5199dcdd27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 71 additions and 0 deletions

View file

@ -87,6 +87,8 @@
["F", "move_to_char", "move_to_char_left"], ["F", "move_to_char", "move_to_char_left"],
["f", "move_to_char", "move_to_char_right"], ["f", "move_to_char", "move_to_char_right"],
["T", "move_to_char", "move_till_char_left"],
["t", "move_to_char", "move_till_char_right"],
["<C-CR>", ["move_down"], ["move_begin"]], ["<C-CR>", ["move_down"], ["move_begin"]],
["<CR>", ["move_down"], ["move_begin"]], ["<CR>", ["move_down"], ["move_begin"]],
@ -131,6 +133,8 @@
["f", "move_to_char", "select_to_char_right"], ["f", "move_to_char", "select_to_char_right"],
["F", "move_to_char", "select_to_char_left_vim"], ["F", "move_to_char", "select_to_char_left_vim"],
["t", "move_to_char", "select_till_char_right"],
["T", "move_to_char", "select_till_char_left_vim"],
["p", ["paste_internal_vim"], ["enter_mode", "normal"]], ["p", ["paste_internal_vim"], ["enter_mode", "normal"]],
["P", ["paste_internal_vim"], ["enter_mode", "normal"]], ["P", ["paste_internal_vim"], ["enter_mode", "normal"]],

View file

@ -3103,6 +3103,42 @@ pub const Editor = struct {
} }
} }
fn move_cursor_till_char_left(root: Buffer.Root, cursor: *Cursor, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void {
var egc: []const u8 = undefined;
if (!(ctx.args.match(.{tp.extract(&egc)}) catch return error.Stop))
return error.Stop;
try move_cursor_left(root, cursor, metrics);
var prev = cursor.*;
try move_cursor_left(root, &prev, metrics);
while (true) {
const prev_egc, _, _ = root.egc_at(prev.row, prev.col, metrics) catch return error.Stop;
if (std.mem.eql(u8, prev_egc, egc))
return;
if (is_eol_left(root, cursor, metrics))
return;
move_cursor_left(root, cursor, metrics) catch return error.Stop;
move_cursor_left(root, &prev, metrics) catch return error.Stop;
}
}
pub fn move_cursor_till_char_right(root: Buffer.Root, cursor: *Cursor, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void {
var egc: []const u8 = undefined;
if (!(ctx.args.match(.{tp.extract(&egc)}) catch return error.Stop))
return error.Stop;
try move_cursor_right(root, cursor, metrics);
var next = cursor.*;
try move_cursor_right(root, &next, metrics);
while (true) {
const next_egc, _, _ = root.egc_at(next.row, next.col, metrics) catch return error.Stop;
if (std.mem.eql(u8, next_egc, egc))
return;
if (is_eol_right(root, cursor, metrics))
return;
move_cursor_right(root, cursor, metrics) catch return error.Stop;
move_cursor_right(root, &next, metrics) catch return error.Stop;
}
}
pub fn move_to_char_left(self: *Self, ctx: Context) Result { pub fn move_to_char_left(self: *Self, ctx: Context) Result {
const root = try self.buf_root(); const root = try self.buf_root();
self.with_cursors_const_arg(root, move_cursor_to_char_left, ctx) catch {}; self.with_cursors_const_arg(root, move_cursor_to_char_left, ctx) catch {};
@ -3117,6 +3153,20 @@ pub const Editor = struct {
} }
pub const move_to_char_right_meta: Meta = .{ .arguments = &.{.integer} }; pub const move_to_char_right_meta: Meta = .{ .arguments = &.{.integer} };
pub fn move_till_char_left(self: *Self, ctx: Context) Result {
const root = try self.buf_root();
self.with_cursors_const_arg(root, move_cursor_till_char_left, ctx) catch {};
self.clamp();
}
pub const move_till_char_left_meta: Meta = .{ .arguments = &.{.integer} };
pub fn move_till_char_right(self: *Self, ctx: Context) Result {
const root = try self.buf_root();
self.with_cursors_const_arg(root, move_cursor_till_char_right, ctx) catch {};
self.clamp();
}
pub const move_till_char_right_meta: Meta = .{ .arguments = &.{.integer} };
pub fn move_or_select_to_char_left(self: *Self, ctx: Context) Result { pub fn move_or_select_to_char_left(self: *Self, ctx: Context) Result {
const selected = if (self.get_primary().selection) |_| true else false; const selected = if (self.get_primary().selection) |_| true else false;
if (selected) try self.select_to_char_left(ctx) else try self.move_to_char_left(ctx); if (selected) try self.select_to_char_left(ctx) else try self.move_to_char_left(ctx);
@ -3771,6 +3821,16 @@ pub const Editor = struct {
} }
pub const select_to_char_left_vim_meta: Meta = .{ .arguments = &.{.integer} }; pub const select_to_char_left_vim_meta: Meta = .{ .arguments = &.{.integer} };
pub fn select_till_char_left_vim(self: *Self, ctx: Context) Result {
const root = try self.buf_root();
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
if (cursel.selection) |*sel| try sel.begin.move_right(root, self.metrics);
};
self.with_selections_const_arg(root, move_cursor_till_char_left, ctx) catch {};
self.clamp();
}
pub const select_till_char_left_vim_meta: Meta = .{ .arguments = &.{.integer} };
pub fn select_to_char_right(self: *Self, ctx: Context) Result { pub fn select_to_char_right(self: *Self, ctx: Context) Result {
const root = try self.buf_root(); const root = try self.buf_root();
self.with_selections_const_arg(root, move_cursor_to_char_right, ctx) catch {}; self.with_selections_const_arg(root, move_cursor_to_char_right, ctx) catch {};
@ -3778,6 +3838,13 @@ pub const Editor = struct {
} }
pub const select_to_char_right_meta: Meta = .{ .arguments = &.{.integer} }; pub const select_to_char_right_meta: Meta = .{ .arguments = &.{.integer} };
pub fn select_till_char_right(self: *Self, ctx: Context) Result {
const root = try self.buf_root();
self.with_selections_const_arg(root, move_cursor_till_char_right, ctx) catch {};
self.clamp();
}
pub const select_till_char_right_meta: Meta = .{ .arguments = &.{.integer} };
pub fn select_begin(self: *Self, ctx: Context) Result { pub fn select_begin(self: *Self, ctx: Context) Result {
const root = try self.buf_root(); const root = try self.buf_root();
try self.with_selections_const_repeat(root, move_cursor_begin, ctx); try self.with_selections_const_repeat(root, move_cursor_begin, ctx);