fix: make helix move_prev_word_start an exact match to real helix
This commit is contained in:
parent
1755ecb3dd
commit
7bf532bdfd
2 changed files with 72 additions and 2 deletions
|
|
@ -2196,7 +2196,7 @@ pub const Editor = struct {
|
|||
const cursor_operator_const_arg = *const fn (root: Buffer.Root, cursor: *Cursor, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void;
|
||||
pub const cursel_operator_mut_once_arg = *const fn (root: Buffer.Root, cursel: *CurSel, ctx: Context, metrics: Buffer.Metrics) error{Stop}!void;
|
||||
const cursor_view_operator_const = *const fn (root: Buffer.Root, cursor: *Cursor, view: *const View, metrics: Buffer.Metrics) error{Stop}!void;
|
||||
const cursel_operator_const = *const fn (root: Buffer.Root, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void;
|
||||
pub const cursel_operator_const = *const fn (root: Buffer.Root, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void;
|
||||
const cursor_operator = *const fn (root: Buffer.Root, cursor: *Cursor, allocator: Allocator) error{Stop}!Buffer.Root;
|
||||
const cursel_operator = *const fn (root: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root;
|
||||
const cursel_operator_mut = *const fn (self: *Self, root: Buffer.Root, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ const Buffer = @import("Buffer");
|
|||
const Cursor = Buffer.Cursor;
|
||||
const Selection = Buffer.Selection;
|
||||
|
||||
const char_class = Editor.char_class;
|
||||
|
||||
const Direction = enum { backwards, forwards };
|
||||
|
||||
var commands: Commands = undefined;
|
||||
|
|
@ -263,12 +265,80 @@ const cmds_ = struct {
|
|||
}
|
||||
pub const extend_next_long_word_start_meta: Meta = .{ .description = "Extend next long word start", .arguments = &.{.integer} };
|
||||
|
||||
fn is_eol(c: []const u8) bool {
|
||||
return char_class(c) == .eol;
|
||||
}
|
||||
|
||||
fn is_whitespace(c: []const u8) bool {
|
||||
return char_class(c) == .whitespace;
|
||||
}
|
||||
|
||||
fn is_word_boundary(root: Buffer.Root, cursor: Cursor, metrics: Buffer.Metrics, comptime direction: enum { left, right }) bool {
|
||||
const nxt = char_class(switch (direction) {
|
||||
.left => cursor.char_left(root, metrics),
|
||||
.right => cursor.char_right(root, metrics),
|
||||
});
|
||||
const cur = char_class(cursor.char_at(root, metrics));
|
||||
if (cur == .eol) return false;
|
||||
return switch (nxt) {
|
||||
.end, .eol => true,
|
||||
.whitespace => cur != .whitespace,
|
||||
else => nxt != cur,
|
||||
};
|
||||
}
|
||||
|
||||
fn move_cursor_prev_word_start(root: Buffer.Root, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
var cursor = cursel.cursor;
|
||||
if (is_word_boundary(root, cursor, metrics, .left))
|
||||
cursor.move_left(root, metrics) catch {};
|
||||
|
||||
var sel = Selection.from_cursor_inclusive(&cursor, root, metrics);
|
||||
defer {
|
||||
sel.begin = cursor;
|
||||
cursel.cursor = cursor;
|
||||
cursel.selection = sel;
|
||||
}
|
||||
|
||||
// Consume whitespace
|
||||
while (cursor.test_at(root, is_whitespace, metrics)) {
|
||||
cursor.move_left(root, metrics) catch return;
|
||||
// Stop at beginning of line
|
||||
if (cursor.test_left(root, is_eol, metrics)) return;
|
||||
}
|
||||
|
||||
// Consume word/non-word chars
|
||||
while (!is_word_boundary(root, cursor, metrics, .left)) {
|
||||
cursor.move_left(root, metrics) catch return;
|
||||
// Stop at beginning of line
|
||||
if (cursor.test_left(root, is_eol, metrics)) return;
|
||||
}
|
||||
}
|
||||
|
||||
fn move_cursor_prev_word_start_extend(root: Buffer.Root, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void {
|
||||
var selection = cursel.selection;
|
||||
// check if we already had a selection and extend it
|
||||
defer if (selection) |*pre_sel| {
|
||||
pre_sel.normalize();
|
||||
if (cursel.selection) |*sel| sel.end = pre_sel.end;
|
||||
};
|
||||
try move_cursor_prev_word_start(root, cursel, metrics);
|
||||
}
|
||||
|
||||
fn move_cursels_const_repeat(move: Editor.cursel_operator_const, ctx: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
const ed = mv.get_active_editor() orelse return;
|
||||
const root = try ed.buf_root();
|
||||
try ed.with_cursels_const_repeat(root, move, ctx);
|
||||
ed.clamp();
|
||||
}
|
||||
|
||||
pub fn move_prev_word_start(_: *void, ctx: Ctx) Result {
|
||||
try move_to_word(ctx, move_cursor_word_left_helix, .backwards);
|
||||
try move_cursels_const_repeat(move_cursor_prev_word_start, ctx);
|
||||
}
|
||||
pub const move_prev_word_start_meta: Meta = .{ .description = "Move previous word start", .arguments = &.{.integer} };
|
||||
|
||||
pub fn extend_prev_word_start(_: *void, ctx: Ctx) Result {
|
||||
try move_cursels_const_repeat(move_cursor_prev_word_start_extend, ctx);
|
||||
try extend_to_word(ctx, move_cursor_word_left_helix, .backwards);
|
||||
}
|
||||
pub const extend_prev_word_start_meta: Meta = .{ .description = "Extend previous word start", .arguments = &.{.integer} };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue