diff options
Diffstat (limited to 'src/Buffer.zig')
-rw-r--r-- | src/Buffer.zig | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/src/Buffer.zig b/src/Buffer.zig index faee5c4..b1aacaf 100644 --- a/src/Buffer.zig +++ b/src/Buffer.zig @@ -27,7 +27,8 @@ const initial_gap_size = std.atomic.cache_line; const Buffer = @This(); /// File content with gap, owned by Janet runtime. -data: []u8, +data: []const u8, +file: []const u8, gap_position: u32 = 0, gap_size: u32 = initial_gap_size, parser: *Parser, @@ -53,10 +54,11 @@ fn read(payload: ?*anyopaque, byte_index: u32, _: Point, } } -pub fn open(text: []u8) !Buffer { +pub fn open(text: []const u8, file: []const u8) !Buffer { const data = gap: { + const unsafe_ptr: *anyopaque = @constCast(@ptrCast(text.ptr)); const n: i32 = @intCast(text.len); - const buffer = janet.pointerBufferUnsafe(@ptrCast(text.ptr), n, n); + const buffer = janet.pointerBufferUnsafe(unsafe_ptr, n, n); const capacity: usize = @intCast(n + initial_gap_size); if (janet.realloc(buffer.*.data, capacity)) |data| { janet.gcpressure(initial_gap_size); @@ -78,6 +80,7 @@ pub fn open(text: []u8) !Buffer { try parser.setLanguage(language); var result = Buffer{ .data = data, + .file = file, .parser = parser, .tree = undefined, .selection = undefined, @@ -86,10 +89,8 @@ pub fn open(text: []u8) !Buffer { .payload = &result, .read = Buffer.read, }, null).?; - result.selection = .{ - .head = .{ .node = result.tree.rootNode() }, - .tail = .{ .node = result.tree.rootNode() }, - }; + const span0 = Selection.Unit{ .span = .{ .tree = result.tree } }; + result.selection = .{ .head = span0, .tail = span0 }; return result; } @@ -99,11 +100,37 @@ pub fn close(buffer: Buffer) void { buffer.parser.destroy(); } +pub fn length(buffer: Buffer) u32 { + return @intCast(buffer.data.len - buffer.gap_size); +} + +pub fn graphemeAt(buffer: Buffer, n: u32) Grapheme { + const text = if (n < buffer.gap_position) + buffer.data[n..buffer.gap_position] + else + buffer.data[buffer.gap_size..][n..]; + var iterator = graphemes.iterator(text); + return .{ .offset = n, .len = iterator.peek().?.len }; +} + +pub fn graphemeBefore(buffer: Buffer, n: u32) ?Grapheme { + if (n == 0) + return null; + const text = if (n <= buffer.gap_position) + buffer.data[0..n] + else + buffer.data[buffer.gap_size..][buffer.gap_position..n]; + var iterator = graphemes.reverseIterator(text); + const len = iterator.peek().?.len; + return .{ .offset = n - len, .len = len }; +} + fn skipLines(text: []const u8, from: u32, n: u32) union(enum) { done: u32, left: u32, } { - assert(n > 0); + if (n == 0) + return .{ .done = from }; var lines: u32 = 0; for (text[from..], 1..) |c, i| if (c == '\n') { @@ -138,20 +165,28 @@ pub fn iterate(buffer: Buffer) struct { } else return null; } } { - const root_node = buffer.tree.rootNode(); const point = Point{ .row = buffer.scroll_row, .column = 0 }; - const node = root_node.descendantForPointRange(point, point).?; - const start_point = node.startPoint(); - assert(start_point.row < point.row or eql(start_point, point)); - - const start_byte = node.startByte(); - const start = if (eql(start_point, point)) - start_byte - else if (start_byte >= buffer.gap_position) - skipLines(buffer.data[buffer.gap_size..], start_byte, - point.row - start_point.row).done - else switch (skipLines(buffer.data[0..buffer.gap_position], start_byte, - point.row - start_point.row)) { + const root_node = buffer.tree.rootNode(); + const root_start = root_node.startPoint(); + const start = if (root_start.row < point.row + or eql(root_start, point)) skip: { + const node = root_node.descendantForPointRange(point, point).?; + const start_point = node.startPoint(); + const start_byte = node.startByte(); + if (eql(start_point, point)) + break :skip start_byte; + assert(start_point.row < point.row); + break :skip if (start_byte >= buffer.gap_position) + skipLines(buffer.data[buffer.gap_size..], + start_byte, point.row - start_point.row).done + else switch (skipLines(buffer.data[0..buffer.gap_position], + start_byte, point.row - start_point.row)) { + .done => |offset| offset, + .left => |left| skipLines(buffer.data[buffer.gap_size..], + buffer.gap_position, left).done, + }; + } else switch (skipLines(buffer.data[0..buffer.gap_position], 0, + point.row)) { .done => |offset| offset, .left => |left| skipLines(buffer.data[buffer.gap_size..], buffer.gap_position, left).done, @@ -172,7 +207,7 @@ pub fn iterate(buffer: Buffer) struct { .graphemes_iterator = graphemes.iterator(buffer.data[offset..]), .data = undefined, .offset = start, - .before_gap = true, + .before_gap = false, .gap_start = undefined, .gap_end = undefined, }; |