Compare commits
8 commits
06b9d2384e
...
91d2131dac
| Author | SHA1 | Date | |
|---|---|---|---|
| 91d2131dac | |||
| 65414d2d73 | |||
| f90d486eae | |||
| 8f1375745d | |||
| 2867fc9a8e | |||
| 0f560ed3bc | |||
| 757096bfb3 | |||
| dfdb82ca20 |
4 changed files with 138 additions and 183 deletions
|
|
@ -333,21 +333,21 @@ const Node = union(enum) {
|
|||
};
|
||||
}
|
||||
|
||||
fn collect(self: *const Node, l: *ArrayList(*const Node)) !void {
|
||||
fn collect(self: *const Node, allocator: Allocator, l: *ArrayList(*const Node)) !void {
|
||||
switch (self.*) {
|
||||
.node => |*node| {
|
||||
try node.left.collect(l);
|
||||
try node.right.collect(l);
|
||||
try node.left.collect(allocator, l);
|
||||
try node.right.collect(allocator, l);
|
||||
},
|
||||
.leaf => (try l.addOne()).* = self,
|
||||
.leaf => (try l.addOne(allocator)).* = self,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_leaves(self: *const Node, allocator: Allocator) ![]*const Node {
|
||||
var leaves = ArrayList(*const Node).init(allocator);
|
||||
try leaves.ensureTotalCapacity(self.lines());
|
||||
try self.collect(&leaves);
|
||||
return leaves.toOwnedSlice();
|
||||
var leaves: ArrayList(*const Node) = .empty;
|
||||
try leaves.ensureTotalCapacity(allocator, self.lines());
|
||||
try self.collect(allocator, &leaves);
|
||||
return leaves.toOwnedSlice(allocator);
|
||||
}
|
||||
|
||||
fn walk_const(self: *const Node, f: Walker.F, ctx: *anyopaque, metrics: Metrics) Walker {
|
||||
|
|
@ -751,12 +751,12 @@ const Node = union(enum) {
|
|||
return Node.new(allocator, try merge_in_place(leaves[0..mid], allocator), try merge_in_place(leaves[mid..], allocator));
|
||||
}
|
||||
|
||||
pub fn get_line(self: *const Node, line: usize, result: *ArrayList(u8), metrics: Metrics) !void {
|
||||
pub fn get_line(self: *const Node, line: usize, result: *std.Io.Writer, metrics: Metrics) !void {
|
||||
const Ctx = struct {
|
||||
line: *ArrayList(u8),
|
||||
line: *std.Io.Writer,
|
||||
fn walker(ctx_: *anyopaque, leaf: *const Leaf, _: Metrics) Walker {
|
||||
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
|
||||
ctx.line.appendSlice(leaf.buf) catch |e| return .{ .err = e };
|
||||
ctx.line.writeAll(leaf.buf) catch |e| return .{ .err = e };
|
||||
return if (!leaf.eol) Walker.keep_walking else Walker.stop;
|
||||
}
|
||||
};
|
||||
|
|
@ -1039,53 +1039,34 @@ const Node = union(enum) {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn get_byte_pos(self: *const Node, pos_: Cursor, metrics_: Metrics, eol_mode: EolMode) !usize {
|
||||
const Ctx = struct {
|
||||
pub fn get_byte_pos(self: *const Node, pos_: Cursor, metrics: Metrics, eol_mode: EolMode) !usize {
|
||||
const ctx_ = struct {
|
||||
pos: usize = 0,
|
||||
line: usize = 0,
|
||||
abs_col: usize = 0,
|
||||
pos: Cursor,
|
||||
byte_pos: usize = 0,
|
||||
metrics: Metrics,
|
||||
const Ctx = @This();
|
||||
const Writer = std.io.Writer(*Ctx, error{Stop}, write);
|
||||
fn write(ctx: *Ctx, bytes: []const u8) error{Stop}!usize {
|
||||
if (ctx.line >= ctx.pos.row) {
|
||||
return ctx.get_col_bytes(bytes, bytes.len);
|
||||
} else for (bytes, 1..) |char, i| {
|
||||
ctx.byte_pos += 1;
|
||||
if (char == '\n') {
|
||||
col: usize = 0,
|
||||
target_line: usize,
|
||||
target_col: usize,
|
||||
eol_mode: EolMode,
|
||||
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrics) Walker {
|
||||
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
|
||||
if (ctx.line == ctx.target_line and ctx.col == ctx.target_col) return Walker.stop;
|
||||
if (egc[0] == '\n') {
|
||||
ctx.pos += switch (ctx.eol_mode) {
|
||||
.lf => 1,
|
||||
.crlf => 2,
|
||||
};
|
||||
ctx.line += 1;
|
||||
if (ctx.line >= ctx.pos.row)
|
||||
return ctx.get_col_bytes(bytes[i..], bytes.len);
|
||||
ctx.col = 0;
|
||||
} else {
|
||||
ctx.pos += egc.len;
|
||||
ctx.col += wcwidth;
|
||||
}
|
||||
}
|
||||
return bytes.len;
|
||||
}
|
||||
fn get_col_bytes(ctx: *Ctx, bytes: []const u8, result: usize) error{Stop}!usize {
|
||||
var buf: []const u8 = bytes;
|
||||
while (buf.len > 0) {
|
||||
if (ctx.abs_col >= ctx.pos.col) return error.Stop;
|
||||
if (buf[0] == '\n') return error.Stop;
|
||||
var cols: c_int = undefined;
|
||||
const egc_bytes = ctx.metrics.egc_length(ctx.metrics, buf, &cols, ctx.abs_col);
|
||||
ctx.abs_col += @intCast(cols);
|
||||
ctx.byte_pos += egc_bytes;
|
||||
buf = buf[egc_bytes..];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
fn writer(ctx: *Ctx) Writer {
|
||||
return .{ .context = ctx };
|
||||
return Walker.keep_walking;
|
||||
}
|
||||
};
|
||||
var ctx: Ctx = .{
|
||||
.pos = pos_,
|
||||
.metrics = metrics_,
|
||||
};
|
||||
self.store(ctx.writer(), eol_mode) catch |e| switch (e) {
|
||||
error.Stop => return ctx.byte_pos,
|
||||
};
|
||||
return error.NotFound;
|
||||
var ctx: ctx_ = .{ .target_line = pos_.row, .target_col = pos_.col, .eol_mode = eol_mode };
|
||||
self.walk_egc_forward(0, ctx_.walker, &ctx, metrics) catch {};
|
||||
return ctx.pos;
|
||||
}
|
||||
|
||||
pub fn debug_render_chunks(self: *const Node, allocator: std.mem.Allocator, line: usize, metrics_: Metrics) ![]const u8 {
|
||||
|
|
@ -1119,6 +1100,49 @@ const Node = union(enum) {
|
|||
break :blk l.toOwnedSlice();
|
||||
} else error.NotFound;
|
||||
}
|
||||
|
||||
pub fn write_range(
|
||||
self: *const Node,
|
||||
sel: Selection,
|
||||
writer: *std.Io.Writer,
|
||||
wcwidth_: ?*usize,
|
||||
metrics: Metrics,
|
||||
) std.Io.Writer.Error!void {
|
||||
const Ctx = struct {
|
||||
col: usize = 0,
|
||||
sel: Selection,
|
||||
writer: *std.Io.Writer,
|
||||
wcwidth: usize = 0,
|
||||
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrics) Walker {
|
||||
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
|
||||
if (ctx.col < ctx.sel.begin.col) {
|
||||
ctx.col += wcwidth;
|
||||
return Walker.keep_walking;
|
||||
}
|
||||
_ = ctx.writer.write(egc) catch |e| return Walker{ .err = e };
|
||||
ctx.wcwidth += wcwidth;
|
||||
if (egc[0] == '\n') {
|
||||
ctx.col = 0;
|
||||
ctx.sel.begin.col = 0;
|
||||
ctx.sel.begin.row += 1;
|
||||
} else {
|
||||
ctx.col += wcwidth;
|
||||
ctx.sel.begin.col += wcwidth;
|
||||
}
|
||||
return if (ctx.sel.begin.eql(ctx.sel.end))
|
||||
Walker.stop
|
||||
else
|
||||
Walker.keep_walking;
|
||||
}
|
||||
};
|
||||
|
||||
var ctx: Ctx = .{ .sel = sel, .writer = writer };
|
||||
ctx.sel.normalize();
|
||||
if (sel.begin.eql(sel.end))
|
||||
return;
|
||||
self.walk_egc_forward(sel.begin.row, Ctx.walker, &ctx, metrics) catch return error.WriteFailed;
|
||||
if (wcwidth_) |p| p.* = ctx.wcwidth;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn create(allocator: Allocator) error{OutOfMemory}!*Self {
|
||||
|
|
@ -1346,8 +1370,8 @@ pub fn refresh_from_file(self: *Self) LoadFromFileError!void {
|
|||
}
|
||||
|
||||
pub fn store_to_string(self: *const Self, allocator: Allocator, eol_mode: EolMode) ![]u8 {
|
||||
var s = try ArrayList(u8).initCapacity(allocator, self.root.weights_sum().len);
|
||||
try self.root.store(s.writer(), eol_mode);
|
||||
var s: std.Io.Writer.Allocating = try .initCapacity(allocator, self.root.weights_sum().len);
|
||||
try self.root.store(&s.writer, eol_mode);
|
||||
return s.toOwnedSlice();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -804,7 +804,7 @@ test "parse" {
|
|||
const actual: []const KeyEvent = parsed;
|
||||
try expectEqual(expected.len, actual.len);
|
||||
for (expected, 0..) |expected_event, i| {
|
||||
try std.testing.expectFmt(expected_event, "{}", .{actual[i]});
|
||||
try std.testing.expectFmt(expected_event, "{f}", .{actual[i]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -820,10 +820,10 @@ pub const Editor = struct {
|
|||
fn update_buf_and_eol_mode(self: *Self, root: Buffer.Root, eol_mode: Buffer.EolMode, utf8_sanitized: bool) !void {
|
||||
const b = self.buffer orelse return error.Stop;
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
const sfa_allocator = sfa.get();
|
||||
if (!self.pause_undo) {
|
||||
const meta = try self.store_undo_meta(allocator);
|
||||
defer allocator.free(meta);
|
||||
const meta = try self.store_undo_meta(sfa_allocator);
|
||||
defer sfa_allocator.free(meta);
|
||||
try b.store_undo(meta);
|
||||
}
|
||||
b.update(root);
|
||||
|
|
@ -850,9 +850,9 @@ pub const Editor = struct {
|
|||
try self.send_editor_jump_source();
|
||||
self.cancel_all_matches();
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
const redo_metadata = try self.store_current_undo_meta(allocator);
|
||||
defer allocator.free(redo_metadata);
|
||||
const sfa_allocator = sfa.get();
|
||||
const redo_metadata = try self.store_current_undo_meta(sfa_allocator);
|
||||
defer sfa_allocator.free(redo_metadata);
|
||||
const meta = b_mut.undo(redo_metadata) catch |e| switch (e) {
|
||||
error.Stop => {
|
||||
self.logger.print("nothing to undo", .{});
|
||||
|
|
@ -893,9 +893,9 @@ pub const Editor = struct {
|
|||
self.pause_undo = false;
|
||||
const b = self.buffer orelse return;
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
const meta = try self.store_undo_meta(allocator);
|
||||
defer allocator.free(meta);
|
||||
const sfa_allocator = sfa.get();
|
||||
const meta = try self.store_undo_meta(sfa_allocator);
|
||||
defer sfa_allocator.free(meta);
|
||||
const root = self.buf_root() catch return;
|
||||
if (self.pause_undo_root) |paused_root| b.update(paused_root);
|
||||
try b.store_undo(meta);
|
||||
|
|
@ -947,49 +947,6 @@ pub const Editor = struct {
|
|||
return ctx.col;
|
||||
}
|
||||
|
||||
fn write_range(
|
||||
self: *const Self,
|
||||
root: Buffer.Root,
|
||||
sel: Selection,
|
||||
writer: *std.Io.Writer,
|
||||
wcwidth_: ?*usize,
|
||||
) std.Io.Writer.Error!void {
|
||||
const Ctx = struct {
|
||||
col: usize = 0,
|
||||
sel: Selection,
|
||||
writer: *std.Io.Writer,
|
||||
wcwidth: usize = 0,
|
||||
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Buffer.Metrics) Buffer.Walker {
|
||||
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
|
||||
if (ctx.col < ctx.sel.begin.col) {
|
||||
ctx.col += wcwidth;
|
||||
return Buffer.Walker.keep_walking;
|
||||
}
|
||||
_ = ctx.writer.write(egc) catch |e| return Buffer.Walker{ .err = e };
|
||||
ctx.wcwidth += wcwidth;
|
||||
if (egc[0] == '\n') {
|
||||
ctx.col = 0;
|
||||
ctx.sel.begin.col = 0;
|
||||
ctx.sel.begin.row += 1;
|
||||
} else {
|
||||
ctx.col += wcwidth;
|
||||
ctx.sel.begin.col += wcwidth;
|
||||
}
|
||||
return if (ctx.sel.begin.eql(ctx.sel.end))
|
||||
Buffer.Walker.stop
|
||||
else
|
||||
Buffer.Walker.keep_walking;
|
||||
}
|
||||
};
|
||||
|
||||
var ctx: Ctx = .{ .sel = sel, .writer = writer };
|
||||
ctx.sel.normalize();
|
||||
if (sel.begin.eql(sel.end))
|
||||
return;
|
||||
root.walk_egc_forward(sel.begin.row, Ctx.walker, &ctx, self.metrics) catch return error.WriteFailed;
|
||||
if (wcwidth_) |p| p.* = ctx.wcwidth;
|
||||
}
|
||||
|
||||
pub fn update(self: *Self) void {
|
||||
self.update_scroll();
|
||||
self.update_event() catch {};
|
||||
|
|
@ -3617,8 +3574,9 @@ pub const Editor = struct {
|
|||
const saved = cursel.*;
|
||||
const sel = cursel.expand_selection_to_line(root, self.metrics) catch return error.Stop;
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(cut_text);
|
||||
const sfa_allocator = sfa.get();
|
||||
const cut_text = copy_selection(root, sel.*, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(cut_text);
|
||||
root = try self.delete_selection(root, cursel, allocator);
|
||||
try cursel.cursor.move_up(root, self.metrics);
|
||||
root = self.insert(root, cursel, cut_text, allocator) catch return error.Stop;
|
||||
|
|
@ -3644,8 +3602,9 @@ pub const Editor = struct {
|
|||
const saved = cursel.*;
|
||||
const sel = cursel.expand_selection_to_line(root, self.metrics) catch return error.Stop;
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(cut_text);
|
||||
const sfa_allocator = sfa.get();
|
||||
const cut_text = copy_selection(root, sel.*, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(cut_text);
|
||||
root = try self.delete_selection(root, cursel, allocator);
|
||||
try cursel.cursor.move_down(root, self.metrics);
|
||||
root = self.insert(root, cursel, cut_text, allocator) catch return error.Stop;
|
||||
|
|
@ -3671,8 +3630,9 @@ pub const Editor = struct {
|
|||
const sel: Selection = if (cursel.selection) |sel_| sel_ else Selection.line_from_cursor(cursel.cursor, root, self.metrics);
|
||||
cursel.disable_selection(root, self.metrics);
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const text = copy_selection(root, sel, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(text);
|
||||
const sfa_allocator = sfa.get();
|
||||
const text = copy_selection(root, sel, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(text);
|
||||
cursel.cursor = sel.begin;
|
||||
root = self.insert(root, cursel, text, allocator) catch return error.Stop;
|
||||
cursel.selection = .{ .begin = sel.begin, .end = sel.end };
|
||||
|
|
@ -3693,8 +3653,9 @@ pub const Editor = struct {
|
|||
const sel: Selection = if (cursel.selection) |sel_| sel_ else Selection.line_from_cursor(cursel.cursor, root, self.metrics);
|
||||
cursel.disable_selection(root, self.metrics);
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const text = copy_selection(root, sel, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(text);
|
||||
const sfa_allocator = sfa.get();
|
||||
const text = copy_selection(root, sel, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(text);
|
||||
cursel.cursor = sel.end;
|
||||
root = self.insert(root, cursel, text, allocator) catch return error.Stop;
|
||||
cursel.selection = .{ .begin = sel.end, .end = cursel.cursor };
|
||||
|
|
@ -3714,11 +3675,12 @@ pub const Editor = struct {
|
|||
const saved = cursel.*;
|
||||
const sel = cursel.expand_selection_to_line(root, self.metrics) catch return error.Stop;
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const alloc = sfa.get();
|
||||
const text = copy_selection(root, sel.*, alloc, self.metrics) catch return error.Stop;
|
||||
defer allocator.free(text);
|
||||
const sfa_allocator = sfa.get();
|
||||
const text = copy_selection(root, sel.*, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(text);
|
||||
root = try self.delete_selection(root, cursel, allocator);
|
||||
const new_text = text_manip.toggle_prefix_in_text(self.prefix, text, alloc) catch return error.Stop;
|
||||
const new_text = text_manip.toggle_prefix_in_text(self.prefix, text, sfa_allocator) catch return error.Stop;
|
||||
defer sfa_allocator.free(new_text);
|
||||
root = self.insert(root, cursel, new_text, allocator) catch return error.Stop;
|
||||
cursel.* = saved;
|
||||
cursel.cursor.clamp_to_buffer(root, self.metrics);
|
||||
|
|
@ -4514,8 +4476,8 @@ pub const Editor = struct {
|
|||
const row = cursel.cursor.row;
|
||||
const leading_ws = @min(find_first_non_ws(root, row, self.metrics), cursel.cursor.col);
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(allocator);
|
||||
const sfa_allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(sfa_allocator);
|
||||
defer stream.deinit();
|
||||
const writer = &stream.writer;
|
||||
_ = try writer.write("\n");
|
||||
|
|
@ -4591,8 +4553,8 @@ pub const Editor = struct {
|
|||
const row = cursel.cursor.row;
|
||||
try move_cursor_left(root, &cursel.cursor, self.metrics);
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(allocator);
|
||||
const sfa_allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(sfa_allocator);
|
||||
defer stream.deinit();
|
||||
try self.generate_leading_ws(&stream.writer, leading_ws);
|
||||
if (stream.written().len > 0)
|
||||
|
|
@ -4624,8 +4586,8 @@ pub const Editor = struct {
|
|||
const row = cursel.cursor.row;
|
||||
try move_cursor_end(root, &cursel.cursor, self.metrics);
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(allocator);
|
||||
const sfa_allocator = sfa.get();
|
||||
var stream: std.Io.Writer.Allocating = .init(sfa_allocator);
|
||||
defer stream.deinit();
|
||||
try stream.writer.writeAll("\n");
|
||||
try self.generate_leading_ws(&stream.writer, leading_ws);
|
||||
|
|
@ -5840,7 +5802,7 @@ pub const Editor = struct {
|
|||
}
|
||||
var sp_buf: [tp.subprocess.max_chunk_size]u8 = undefined;
|
||||
var writer = sp.writer(&sp_buf);
|
||||
try self.write_range(state.before_root, sel, &writer.interface, null);
|
||||
try state.before_root.write_range(sel, &writer.interface, null, self.metrics);
|
||||
try writer.interface.flush();
|
||||
self.logger.print("filter: sent", .{});
|
||||
state.work_root = try state.work_root.delete_range(sel, buf_a_, null, self.metrics);
|
||||
|
|
@ -5930,10 +5892,11 @@ pub const Editor = struct {
|
|||
break :ret sel;
|
||||
};
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(cut_text);
|
||||
const ucased = Buffer.unicode.get_letter_casing().toUpperStr(allocator, cut_text) catch return error.Stop;
|
||||
defer allocator.free(ucased);
|
||||
const sfa_allocator = sfa.get();
|
||||
const cut_text = copy_selection(root, sel.*, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(cut_text);
|
||||
const ucased = Buffer.unicode.get_letter_casing().toUpperStr(sfa_allocator, cut_text) catch return error.Stop;
|
||||
defer sfa_allocator.free(ucased);
|
||||
root = try self.delete_selection(root, cursel, allocator);
|
||||
root = self.insert(root, cursel, ucased, allocator) catch return error.Stop;
|
||||
cursel.* = saved;
|
||||
|
|
@ -5958,10 +5921,11 @@ pub const Editor = struct {
|
|||
break :ret sel;
|
||||
};
|
||||
var sfa = std.heap.stackFallback(4096, self.allocator);
|
||||
const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop;
|
||||
defer allocator.free(cut_text);
|
||||
const ucased = Buffer.unicode.get_letter_casing().toLowerStr(allocator, cut_text) catch return error.Stop;
|
||||
defer allocator.free(ucased);
|
||||
const sfa_allocator = sfa.get();
|
||||
const cut_text = copy_selection(root, sel.*, sfa_allocator, self.metrics) catch return error.Stop;
|
||||
defer sfa_allocator.free(cut_text);
|
||||
const ucased = Buffer.unicode.get_letter_casing().toLowerStr(sfa_allocator, cut_text) catch return error.Stop;
|
||||
defer sfa_allocator.free(ucased);
|
||||
root = try self.delete_selection(root, cursel, allocator);
|
||||
root = self.insert(root, cursel, ucased, allocator) catch return error.Stop;
|
||||
cursel.* = saved;
|
||||
|
|
@ -5987,7 +5951,7 @@ pub const Editor = struct {
|
|||
};
|
||||
var range: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
defer range.deinit();
|
||||
self.write_range(root, sel.*, &range.writer, null) catch return error.Stop;
|
||||
root.write_range(sel.*, &range.writer, null, self.metrics) catch return error.Stop;
|
||||
|
||||
const bytes = range.written();
|
||||
const letter_casing = Buffer.unicode.get_letter_casing();
|
||||
|
|
|
|||
|
|
@ -28,51 +28,18 @@ fn metrics() Buffer.Metrics {
|
|||
}
|
||||
|
||||
fn get_big_doc(eol_mode: *Buffer.EolMode) !*Buffer {
|
||||
const BigDocGen = struct {
|
||||
line_num: usize = 0,
|
||||
lines: usize = 10000,
|
||||
const nl_lines = 10000;
|
||||
|
||||
buf: [128]u8 = undefined,
|
||||
line_buf: []u8 = "",
|
||||
read_count: usize = 0,
|
||||
|
||||
const Self = @This();
|
||||
const Reader = std.io.Reader(*Self, Err, read);
|
||||
const Err = error{NoSpaceLeft};
|
||||
|
||||
fn gen_line(self: *Self) Err!void {
|
||||
var stream = std.io.fixedBufferStream(&self.buf);
|
||||
const writer = stream.writer();
|
||||
try writer.print("this is line {d}\n", .{self.line_num});
|
||||
self.line_buf = stream.getWritten();
|
||||
self.read_count = 0;
|
||||
self.line_num += 1;
|
||||
}
|
||||
|
||||
fn read(self: *Self, buffer: []u8) Err!usize {
|
||||
if (self.line_num > self.lines)
|
||||
return 0;
|
||||
if (self.line_buf.len == 0 or self.line_buf.len - self.read_count == 0)
|
||||
try self.gen_line();
|
||||
const read_count = self.read_count;
|
||||
const bytes_to_read = @min(self.line_buf.len - read_count, buffer.len);
|
||||
@memcpy(buffer[0..bytes_to_read], self.line_buf[read_count .. read_count + bytes_to_read]);
|
||||
self.read_count += bytes_to_read;
|
||||
return bytes_to_read;
|
||||
}
|
||||
|
||||
fn reader(self: *Self) Reader {
|
||||
return .{ .context = self };
|
||||
}
|
||||
};
|
||||
var gen: BigDocGen = .{};
|
||||
var doc = ArrayList(u8).init(a);
|
||||
var doc: std.Io.Writer.Allocating = .init(a);
|
||||
defer doc.deinit();
|
||||
try gen.reader().readAllArrayList(&doc, std.math.maxInt(usize));
|
||||
|
||||
for (0..nl_lines) |line_num| {
|
||||
try doc.writer.print("this is line {d}\n", .{line_num});
|
||||
}
|
||||
|
||||
var buf = try Buffer.create(a);
|
||||
var fis = std.io.fixedBufferStream(doc.items);
|
||||
var sanitized: bool = false;
|
||||
buf.update(try buf.load(fis.reader(), doc.items.len, eol_mode, &sanitized));
|
||||
buf.update(try buf.load_from_string(doc.written(), eol_mode, &sanitized));
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
@ -108,8 +75,8 @@ test "buffer" {
|
|||
}
|
||||
|
||||
fn get_line(buf: *const Buffer, line: usize) ![]const u8 {
|
||||
var result = ArrayList(u8).init(a);
|
||||
try buf.root.get_line(line, &result, metrics());
|
||||
var result: std.Io.Writer.Allocating = .init(a);
|
||||
try buf.root.get_line(line, &result.writer, metrics());
|
||||
return result.toOwnedSlice();
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +86,7 @@ test "walk_from_line" {
|
|||
defer buffer.deinit();
|
||||
|
||||
const lines = buffer.root.lines();
|
||||
try std.testing.expectEqual(lines, 10002);
|
||||
try std.testing.expectEqual(lines, 10001);
|
||||
|
||||
const line0 = try get_line(buffer, 0);
|
||||
defer a.free(line0);
|
||||
|
|
@ -135,7 +102,7 @@ test "walk_from_line" {
|
|||
|
||||
const line9999 = try get_line(buffer, 9999);
|
||||
defer a.free(line9999);
|
||||
try std.testing.expect(std.mem.eql(u8, line9999, "this is line 9999"));
|
||||
try std.testing.expectEqualDeep("this is line 9999", line9999);
|
||||
}
|
||||
|
||||
test "line_len" {
|
||||
|
|
@ -394,7 +361,7 @@ test "get_from_pos" {
|
|||
defer buffer.deinit();
|
||||
|
||||
const lines = buffer.root.lines();
|
||||
try std.testing.expectEqual(lines, 10002);
|
||||
try std.testing.expectEqual(lines, 10001);
|
||||
|
||||
const line0 = try get_line(buffer, 0);
|
||||
defer a.free(line0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue