Add coding symbol rail
This commit is contained in:
@@ -17,10 +17,16 @@ pub const Selection = struct {
|
||||
cursor: usize,
|
||||
};
|
||||
|
||||
pub const Pair = struct {
|
||||
open: []const u8,
|
||||
close: []const u8,
|
||||
};
|
||||
|
||||
pub const Command = union(enum) {
|
||||
move_left,
|
||||
move_right,
|
||||
insert: []const u8,
|
||||
insert_pair: Pair,
|
||||
delete_backward,
|
||||
};
|
||||
|
||||
@@ -62,6 +68,7 @@ pub const Buffer = struct {
|
||||
.move_left => self.moveLeft(),
|
||||
.move_right => self.moveRight(),
|
||||
.insert => |text| try self.insert(text),
|
||||
.insert_pair => |pair| try self.insertPair(pair),
|
||||
.delete_backward => self.deleteBackward(),
|
||||
}
|
||||
}
|
||||
@@ -84,6 +91,16 @@ pub const Buffer = struct {
|
||||
self.selection = null;
|
||||
}
|
||||
|
||||
pub fn insertPair(self: *Buffer, pair: Pair) !void {
|
||||
if (!std.unicode.utf8ValidateSlice(pair.open) or !std.unicode.utf8ValidateSlice(pair.close)) return error.InvalidUtf8Insertion;
|
||||
const combined = try std.mem.concat(self.allocator, u8, &.{ pair.open, pair.close });
|
||||
defer self.allocator.free(combined);
|
||||
try self.bytes.insertSlice(self.allocator, self.cursor.byte, combined);
|
||||
self.cursor.byte += pair.open.len;
|
||||
self.refreshCell();
|
||||
self.selection = null;
|
||||
}
|
||||
|
||||
pub fn deleteBackward(self: *Buffer) void {
|
||||
if (self.cursor.byte == 0) return;
|
||||
const start = previousBoundary(self.bytes.items, self.cursor.byte);
|
||||
@@ -265,3 +282,29 @@ test "adversarial: dispatch requires an open buffer" {
|
||||
try std.testing.expectError(error.NoBufferOpen, session.dispatch(.move_right));
|
||||
try std.testing.expectError(error.NoBufferOpen, session.snapshot());
|
||||
}
|
||||
|
||||
test "regular: pair insertion places cursor between delimiters" {
|
||||
var buffer = try Buffer.openFromBytes(std.testing.allocator, "call");
|
||||
defer buffer.deinit();
|
||||
|
||||
buffer.moveRight();
|
||||
buffer.moveRight();
|
||||
buffer.moveRight();
|
||||
buffer.moveRight();
|
||||
try buffer.insertPair(.{ .open = "(", .close = ")" });
|
||||
|
||||
const snap = buffer.snapshot();
|
||||
try std.testing.expectEqualStrings("call()", snap.bytes);
|
||||
try std.testing.expectEqual(@as(usize, 5), snap.cursor_byte);
|
||||
try std.testing.expectEqual(@as(usize, 5), snap.cursor_cell);
|
||||
}
|
||||
|
||||
test "adversarial: invalid UTF-8 pair insertion is rejected and existing bytes are preserved" {
|
||||
var buffer = try Buffer.openFromBytes(std.testing.allocator, "safe");
|
||||
defer buffer.deinit();
|
||||
|
||||
const bad = [_]u8{ 0xc3, 0x28 };
|
||||
try std.testing.expectError(error.InvalidUtf8Insertion, buffer.insertPair(.{ .open = &bad, .close = ")" }));
|
||||
try std.testing.expectEqualStrings("safe", buffer.snapshot().bytes);
|
||||
try std.testing.expectEqual(@as(usize, 0), buffer.snapshot().cursor_byte);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user