Separate first nonblank line motion

This commit is contained in:
slhx agent
2026-06-21 22:34:51 +02:00
parent d5c31a92c5
commit d7bf5edc1f
6 changed files with 65 additions and 5 deletions
+40
View File
@@ -31,6 +31,7 @@ pub const Command = union(enum) {
move_word_forward,
move_word_back,
move_word_end,
move_line_first_nonblank,
insert: []const u8,
insert_pair: Pair,
delete_backward,
@@ -95,6 +96,7 @@ pub const Buffer = struct {
.move_word_forward => self.moveWordForward(),
.move_word_back => self.moveWordBack(),
.move_word_end => self.moveWordEnd(),
.move_line_first_nonblank => self.moveLineFirstNonblank(),
.insert => |text| try self.insert(text),
.insert_pair => |pair| try self.insertPair(pair),
.delete_backward => self.deleteBackward(),
@@ -267,6 +269,14 @@ pub const Buffer = struct {
self.refreshCellResetPreferred();
}
pub fn moveLineFirstNonblank(self: *Buffer) void {
const range = self.currentLineRange(false);
var at = range.start;
while (at < range.end and (self.bytes.items[at] == ' ' or self.bytes.items[at] == '\t')) : (at += 1) {}
self.cursor.byte = at;
self.refreshCellResetPreferred();
}
pub fn moveDocumentStart(self: *Buffer) void {
self.cursor.byte = 0;
self.refreshCellResetPreferred();
@@ -795,3 +805,33 @@ test "regular: document motions jump to top and bottom line" {
try std.testing.expectEqual(@as(usize, 0), snap.cursor_byte);
try std.testing.expectEqual(@as(usize, 0), snap.cursor_cell);
}
test "regular: line first-nonblank is distinct from absolute line start" {
var buffer = try Buffer.openFromBytes(std.testing.allocator, "top\n \talpha\nend");
defer buffer.deinit();
buffer.moveDown();
buffer.moveLineEnd();
try std.testing.expectEqual(@as(usize, 12), buffer.cursor.byte);
buffer.moveLineStart();
try std.testing.expectEqual(@as(usize, 4), buffer.cursor.byte);
buffer.moveLineEnd();
buffer.moveLineFirstNonblank();
try std.testing.expectEqual(@as(usize, 7), buffer.cursor.byte);
try std.testing.expectEqual(@as(usize, 2), buffer.cursor.cell);
}
test "adversarial: line first-nonblank on blank or whitespace-only line goes to line end" {
var buffer = try Buffer.openFromBytes(std.testing.allocator, "a\n \n\t\tb");
defer buffer.deinit();
buffer.moveDown();
buffer.moveLineFirstNonblank();
try std.testing.expectEqual(@as(usize, 4), buffer.cursor.byte);
buffer.moveDown();
buffer.moveLineFirstNonblank();
try std.testing.expectEqual(@as(usize, 7), buffer.cursor.byte);
}