Separate first nonblank line motion
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user