refactor(Buffer): rename Metrix to Metrics

Metrix was a bit too silly
This commit is contained in:
CJ van den Berg 2024-07-05 20:58:24 +02:00
parent 633cc5a1c1
commit f06a7b3d6a
7 changed files with 211 additions and 211 deletions

View file

@ -16,7 +16,7 @@ pub const View = @import("View.zig");
pub const Selection = @import("Selection.zig");
pub const MetaWriter = std.ArrayList(u8).Writer;
pub const Metrix = struct {
pub const Metrics = struct {
ctx: *const anyopaque,
egc_length: egc_length_func,
egc_chunk_width: egc_chunk_width_func,
@ -58,7 +58,7 @@ pub const WalkerMut = struct {
pub const stop = WalkerMut{ .keep_walking = false };
pub const found = WalkerMut{ .found = true };
const F = *const fn (ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) WalkerMut;
const F = *const fn (ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) WalkerMut;
};
pub const Walker = struct {
@ -70,7 +70,7 @@ pub const Walker = struct {
pub const stop = Walker{ .keep_walking = false };
pub const found = Walker{ .found = true };
const F = *const fn (ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) Walker;
const F = *const fn (ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) Walker;
};
pub const Weights = struct {
@ -152,7 +152,7 @@ pub const Leaf = struct {
return self.buf.len == 0 and !self.bol and !self.eol;
}
fn pos_to_width(self: *const Leaf, pos: *usize, abs_col_: usize, mtrx: Metrix) usize {
fn pos_to_width(self: *const Leaf, pos: *usize, abs_col_: usize, metrics: Metrics) usize {
var col: usize = 0;
var abs_col = abs_col_;
var cols: c_int = 0;
@ -163,7 +163,7 @@ pub const Leaf = struct {
buf = buf[1..];
pos.* -= 1;
} else {
const bytes = mtrx.egc_length(mtrx.ctx, buf, &cols, abs_col);
const bytes = metrics.egc_length(metrics.ctx, buf, &cols, abs_col);
buf = buf[bytes..];
pos.* -= bytes;
}
@ -173,12 +173,12 @@ pub const Leaf = struct {
return col;
}
fn width(self: *const Leaf, abs_col: usize, mtrx: Metrix) usize {
fn width(self: *const Leaf, abs_col: usize, metrics: Metrics) usize {
var pos: usize = std.math.maxInt(usize);
return self.pos_to_width(&pos, abs_col, mtrx);
return self.pos_to_width(&pos, abs_col, metrics);
}
inline fn width_to_pos(self: *const Leaf, col_: usize, abs_col_: usize, mtrx: Metrix) !usize {
inline fn width_to_pos(self: *const Leaf, col_: usize, abs_col_: usize, metrics: Metrics) !usize {
var abs_col = abs_col_;
var col = col_;
var cols: c_int = 0;
@ -186,7 +186,7 @@ pub const Leaf = struct {
return while (buf.len > 0) {
if (col == 0)
break @intFromPtr(buf.ptr) - @intFromPtr(self.buf.ptr);
const bytes = mtrx.egc_length(mtrx.ctx, buf, &cols, abs_col);
const bytes = metrics.egc_length(metrics.ctx, buf, &cols, abs_col);
buf = buf[bytes..];
if (col < cols)
break @intFromPtr(buf.ptr) - @intFromPtr(self.buf.ptr);
@ -195,20 +195,20 @@ pub const Leaf = struct {
} else error.BufferUnderrun;
}
inline fn dump(self: *const Leaf, l: *ArrayList(u8), abs_col: usize, mtrx: Metrix) !void {
inline fn dump(self: *const Leaf, l: *ArrayList(u8), abs_col: usize, metrics: Metrics) !void {
var buf: [16]u8 = undefined;
const wcwidth = try std.fmt.bufPrint(&buf, "{d}", .{self.width(abs_col, mtrx)});
const wcwidth = try std.fmt.bufPrint(&buf, "{d}", .{self.width(abs_col, metrics)});
if (self.bol)
try l.appendSlice("BOL ");
try l.appendSlice(wcwidth);
try l.append('"');
try debug_render_chunk(self.buf, l, mtrx);
try debug_render_chunk(self.buf, l, metrics);
try l.appendSlice("\" ");
if (self.eol)
try l.appendSlice("EOL ");
}
fn debug_render_chunk(chunk: []const u8, l: *ArrayList(u8), mtrx: Metrix) !void {
fn debug_render_chunk(chunk: []const u8, l: *ArrayList(u8), metrics: Metrics) !void {
var cols: c_int = 0;
var buf = chunk;
while (buf.len > 0) {
@ -219,7 +219,7 @@ pub const Leaf = struct {
buf = buf[1..];
},
else => {
const bytes = mtrx.egc_length(mtrx.ctx, buf, &cols, 0);
const bytes = metrics.egc_length(metrics.ctx, buf, &cols, 0);
var buf_: [4096]u8 = undefined;
try l.appendSlice(try std.fmt.bufPrint(&buf_, "{s}", .{std.fmt.fmtSliceEscapeLower(buf[0..bytes])}));
buf = buf[bytes..];
@ -321,27 +321,27 @@ const Node = union(enum) {
return leaves.toOwnedSlice();
}
fn walk_const(self: *const Node, f: Walker.F, ctx: *anyopaque, mtrx: Metrix) Walker {
fn walk_const(self: *const Node, f: Walker.F, ctx: *anyopaque, metrics: Metrics) Walker {
switch (self.*) {
.node => |*node| {
const left = node.left.walk_const(f, ctx, mtrx);
const left = node.left.walk_const(f, ctx, metrics);
if (!left.keep_walking) {
var result = Walker{};
result.err = left.err;
result.found = left.found;
return result;
}
const right = node.right.walk_const(f, ctx, mtrx);
const right = node.right.walk_const(f, ctx, metrics);
return node.merge_results_const(left, right);
},
.leaf => |*l| return f(ctx, l, mtrx),
.leaf => |*l| return f(ctx, l, metrics),
}
}
fn walk(self: *const Node, a: Allocator, f: WalkerMut.F, ctx: *anyopaque, mtrx: Metrix) WalkerMut {
fn walk(self: *const Node, a: Allocator, f: WalkerMut.F, ctx: *anyopaque, metrics: Metrics) WalkerMut {
switch (self.*) {
.node => |*node| {
const left = node.left.walk(a, f, ctx, mtrx);
const left = node.left.walk(a, f, ctx, metrics);
if (!left.keep_walking) {
var result = WalkerMut{};
result.err = left.err;
@ -351,26 +351,26 @@ const Node = union(enum) {
}
return result;
}
const right = node.right.walk(a, f, ctx, mtrx);
const right = node.right.walk(a, f, ctx, metrics);
return node.merge_results(a, left, right);
},
.leaf => |*l| return f(ctx, l, mtrx),
.leaf => |*l| return f(ctx, l, metrics),
}
}
fn walk_from_line_begin_const_internal(self: *const Node, line: usize, f: Walker.F, ctx: *anyopaque, mtrx: Metrix) Walker {
fn walk_from_line_begin_const_internal(self: *const Node, line: usize, f: Walker.F, ctx: *anyopaque, metrics: Metrics) Walker {
switch (self.*) {
.node => |*node| {
const left_bols = node.weights.bols;
if (line >= left_bols)
return node.right.walk_from_line_begin_const_internal(line - left_bols, f, ctx, mtrx);
const left_result = node.left.walk_from_line_begin_const_internal(line, f, ctx, mtrx);
const right_result = if (left_result.found and left_result.keep_walking) node.right.walk_const(f, ctx, mtrx) else Walker{};
return node.right.walk_from_line_begin_const_internal(line - left_bols, f, ctx, metrics);
const left_result = node.left.walk_from_line_begin_const_internal(line, f, ctx, metrics);
const right_result = if (left_result.found and left_result.keep_walking) node.right.walk_const(f, ctx, metrics) else Walker{};
return node.merge_results_const(left_result, right_result);
},
.leaf => |*l| {
if (line == 0) {
var result = f(ctx, l, mtrx);
var result = f(ctx, l, metrics);
if (result.err) |_| return result;
result.found = true;
return result;
@ -380,18 +380,18 @@ const Node = union(enum) {
}
}
pub fn walk_from_line_begin_const(self: *const Node, line: usize, f: Walker.F, ctx: *anyopaque, mtrx: Metrix) !bool {
const result = self.walk_from_line_begin_const_internal(line, f, ctx, mtrx);
pub fn walk_from_line_begin_const(self: *const Node, line: usize, f: Walker.F, ctx: *anyopaque, metrics: Metrics) !bool {
const result = self.walk_from_line_begin_const_internal(line, f, ctx, metrics);
if (result.err) |e| return e;
return result.found;
}
fn walk_from_line_begin_internal(self: *const Node, a: Allocator, line: usize, f: WalkerMut.F, ctx: *anyopaque, mtrx: Metrix) WalkerMut {
fn walk_from_line_begin_internal(self: *const Node, a: Allocator, line: usize, f: WalkerMut.F, ctx: *anyopaque, metrics: Metrics) WalkerMut {
switch (self.*) {
.node => |*node| {
const left_bols = node.weights.bols;
if (line >= left_bols) {
const right_result = node.right.walk_from_line_begin_internal(a, line - left_bols, f, ctx, mtrx);
const right_result = node.right.walk_from_line_begin_internal(a, line - left_bols, f, ctx, metrics);
if (right_result.replace) |p| {
var result = WalkerMut{};
result.err = right_result.err;
@ -406,13 +406,13 @@ const Node = union(enum) {
return right_result;
}
}
const left_result = node.left.walk_from_line_begin_internal(a, line, f, ctx, mtrx);
const right_result = if (left_result.found and left_result.keep_walking) node.right.walk(a, f, ctx, mtrx) else WalkerMut{};
const left_result = node.left.walk_from_line_begin_internal(a, line, f, ctx, metrics);
const right_result = if (left_result.found and left_result.keep_walking) node.right.walk(a, f, ctx, metrics) else WalkerMut{};
return node.merge_results(a, left_result, right_result);
},
.leaf => |*l| {
if (line == 0) {
var result = f(ctx, l, mtrx);
var result = f(ctx, l, metrics);
if (result.err) |_| {
result.replace = null;
return result;
@ -425,8 +425,8 @@ const Node = union(enum) {
}
}
pub fn walk_from_line_begin(self: *const Node, a: Allocator, line: usize, f: WalkerMut.F, ctx: *anyopaque, mtrx: Metrix) !struct { bool, ?Root } {
const result = self.walk_from_line_begin_internal(a, line, f, ctx, mtrx);
pub fn walk_from_line_begin(self: *const Node, a: Allocator, line: usize, f: WalkerMut.F, ctx: *anyopaque, metrics: Metrics) !struct { bool, ?Root } {
const result = self.walk_from_line_begin_internal(a, line, f, ctx, metrics);
if (result.err) |e| return e;
return .{ result.found, result.replace };
}
@ -466,27 +466,27 @@ const Node = union(enum) {
}
}
const EgcF = *const fn (ctx: *anyopaque, egc: []const u8, wcwidth: usize, mtrx: Metrix) Walker;
const EgcF = *const fn (ctx: *anyopaque, egc: []const u8, wcwidth: usize, metrics: Metrics) Walker;
pub fn walk_egc_forward(self: *const Node, line: usize, walker_f: EgcF, walker_ctx: *anyopaque, mtrx_: Metrix) !void {
pub fn walk_egc_forward(self: *const Node, line: usize, walker_f: EgcF, walker_ctx: *anyopaque, metrics_: Metrics) !void {
const Ctx = struct {
walker_f: EgcF,
walker_ctx: @TypeOf(walker_ctx),
abs_col: usize = 0,
fn walker(ctx_: *anyopaque, leaf: *const Self.Leaf, mtrx: Metrix) Walker {
fn walker(ctx_: *anyopaque, leaf: *const Self.Leaf, metrics: Metrics) Walker {
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
var buf: []const u8 = leaf.buf;
while (buf.len > 0) {
var cols: c_int = undefined;
const bytes = mtrx.egc_length(mtrx.ctx, buf, &cols, ctx.abs_col);
const ret = ctx.walker_f(ctx.walker_ctx, buf[0..bytes], @intCast(cols), mtrx);
const bytes = metrics.egc_length(metrics.ctx, buf, &cols, ctx.abs_col);
const ret = ctx.walker_f(ctx.walker_ctx, buf[0..bytes], @intCast(cols), metrics);
if (ret.err) |e| return .{ .err = e };
buf = buf[bytes..];
ctx.abs_col += @intCast(cols);
if (!ret.keep_walking) return Walker.stop;
}
if (leaf.eol) {
const ret = ctx.walker_f(ctx.walker_ctx, "\n", 1, mtrx);
const ret = ctx.walker_f(ctx.walker_ctx, "\n", 1, metrics);
if (ret.err) |e| return .{ .err = e };
if (!ret.keep_walking) return Walker.stop;
ctx.abs_col = 0;
@ -495,16 +495,16 @@ const Node = union(enum) {
}
};
var ctx: Ctx = .{ .walker_f = walker_f, .walker_ctx = walker_ctx };
const found = try self.walk_from_line_begin_const(line, Ctx.walker, &ctx, mtrx_);
const found = try self.walk_from_line_begin_const(line, Ctx.walker, &ctx, metrics_);
if (!found) return error.NotFound;
}
pub fn ecg_at(self: *const Node, line: usize, col: usize, mtrx: Metrix) error{NotFound}!struct { []const u8, usize, usize } {
pub fn ecg_at(self: *const Node, line: usize, col: usize, metrics: Metrics) error{NotFound}!struct { []const u8, usize, usize } {
const ctx_ = struct {
col: usize,
at: ?[]const u8 = null,
wcwidth: usize = 0,
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrix) Walker {
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrics) Walker {
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
ctx.at = egc;
ctx.wcwidth = wcwidth;
@ -515,20 +515,20 @@ const Node = union(enum) {
}
};
var ctx: ctx_ = .{ .col = col };
self.walk_egc_forward(line, ctx_.walker, &ctx, mtrx) catch return .{ "?", 1, 0 };
self.walk_egc_forward(line, ctx_.walker, &ctx, metrics) catch return .{ "?", 1, 0 };
return if (ctx.at) |at| .{ at, ctx.wcwidth, ctx.col } else error.NotFound;
}
pub fn test_at(self: *const Node, pred: *const fn (c: []const u8) bool, line: usize, col: usize, mtrx: Metrix) bool {
const ecg, _, _ = self.ecg_at(line, col, mtrx) catch return false;
pub fn test_at(self: *const Node, pred: *const fn (c: []const u8) bool, line: usize, col: usize, metrics: Metrics) bool {
const ecg, _, _ = self.ecg_at(line, col, metrics) catch return false;
return pred(ecg);
}
pub fn get_line_width_map(self: *const Node, line: usize, map: *ArrayList(usize), mtrx: Metrix) error{ Stop, NoSpaceLeft }!void {
pub fn get_line_width_map(self: *const Node, line: usize, map: *ArrayList(usize), metrics: Metrics) error{ Stop, NoSpaceLeft }!void {
const Ctx = struct {
map: *ArrayList(usize),
wcwidth: usize = 0,
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrix) Walker {
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrics) Walker {
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
var n = egc.len;
while (n > 0) : (n -= 1) {
@ -540,20 +540,20 @@ const Node = union(enum) {
}
};
var ctx: Ctx = .{ .map = map };
self.walk_egc_forward(line, Ctx.walker, &ctx, mtrx) catch |e| return switch (e) {
self.walk_egc_forward(line, Ctx.walker, &ctx, metrics) catch |e| return switch (e) {
error.NoSpaceLeft => error.NoSpaceLeft,
else => error.Stop,
};
}
pub fn get_range(self: *const Node, sel: Selection, copy_buf: ?[]u8, size: ?*usize, wcwidth_: ?*usize, mtrx_: Metrix) error{ Stop, NoSpaceLeft }!?[]u8 {
pub fn get_range(self: *const Node, sel: Selection, copy_buf: ?[]u8, size: ?*usize, wcwidth_: ?*usize, metrics_: Metrics) error{ Stop, NoSpaceLeft }!?[]u8 {
const Ctx = struct {
col: usize = 0,
sel: Selection,
out: ?[]u8,
bytes: usize = 0,
wcwidth: usize = 0,
fn walker(ctx_: *anyopaque, egc: []const u8, wcwidth: usize, _: Metrix) Walker {
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;
@ -586,7 +586,7 @@ const Node = union(enum) {
ctx.sel.normalize();
if (ctx.sel.begin.eql(ctx.sel.end))
return error.Stop;
self.walk_egc_forward(ctx.sel.begin.row, Ctx.walker, &ctx, mtrx_) catch |e| return switch (e) {
self.walk_egc_forward(ctx.sel.begin.row, Ctx.walker, &ctx, metrics_) catch |e| return switch (e) {
error.NoSpaceLeft => error.NoSpaceLeft,
else => error.Stop,
};
@ -595,20 +595,20 @@ const Node = union(enum) {
return if (copy_buf) |buf_| buf_[0..ctx.bytes] else null;
}
pub fn delete_range(self: *const Node, sel: Selection, a: Allocator, size: ?*usize, mtrx: Metrix) error{Stop}!Root {
pub fn delete_range(self: *const Node, sel: Selection, a: Allocator, size: ?*usize, metrics: Metrics) error{Stop}!Root {
var wcwidth: usize = 0;
_ = self.get_range(sel, null, size, &wcwidth, mtrx) catch return error.Stop;
return self.del_chars(sel.begin.row, sel.begin.col, wcwidth, a, mtrx) catch return error.Stop;
_ = self.get_range(sel, null, size, &wcwidth, metrics) catch return error.Stop;
return self.del_chars(sel.begin.row, sel.begin.col, wcwidth, a, metrics) catch return error.Stop;
}
pub fn del_chars(self: *const Node, line: usize, col: usize, count: usize, a: Allocator, mtrx_: Metrix) !Root {
pub fn del_chars(self: *const Node, line: usize, col: usize, count: usize, a: Allocator, metrics_: Metrics) !Root {
const Ctx = struct {
a: Allocator,
col: usize,
abs_col: usize = 0,
count: usize,
delete_next_bol: bool = false,
fn walker(Ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) WalkerMut {
fn walker(Ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) WalkerMut {
const ctx = @as(*@This(), @ptrCast(@alignCast(Ctx)));
var result = WalkerMut.keep_walking;
if (ctx.delete_next_bol and ctx.count == 0) {
@ -617,7 +617,7 @@ const Node = union(enum) {
ctx.delete_next_bol = false;
return result;
}
const leaf_wcwidth = leaf.width(ctx.abs_col, mtrx);
const leaf_wcwidth = leaf.width(ctx.abs_col, metrics);
const leaf_bol = leaf.bol and !ctx.delete_next_bol;
ctx.delete_next_bol = false;
const base_col = ctx.abs_col;
@ -641,7 +641,7 @@ const Node = union(enum) {
result.replace = Leaf.new(ctx.a, "", leaf_bol, leaf.eol) catch |e| return .{ .err = e };
ctx.count = 0;
} else {
const pos = leaf.width_to_pos(ctx.count, base_col, mtrx) catch |e| return .{ .err = e };
const pos = leaf.width_to_pos(ctx.count, base_col, metrics) catch |e| return .{ .err = e };
result.replace = Leaf.new(ctx.a, leaf.buf[pos..], leaf_bol, leaf.eol) catch |e| return .{ .err = e };
ctx.count = 0;
}
@ -655,7 +655,7 @@ const Node = union(enum) {
} else {
if (ctx.col + ctx.count >= leaf_wcwidth) {
ctx.count -= leaf_wcwidth - ctx.col;
const pos = leaf.width_to_pos(ctx.col, base_col, mtrx) catch |e| return .{ .err = e };
const pos = leaf.width_to_pos(ctx.col, base_col, metrics) catch |e| return .{ .err = e };
const leaf_eol = if (leaf.eol and ctx.count > 0) leaf_eol: {
ctx.count -= 1;
ctx.delete_next_bol = true;
@ -664,8 +664,8 @@ const Node = union(enum) {
result.replace = Leaf.new(ctx.a, leaf.buf[0..pos], leaf_bol, leaf_eol) catch |e| return .{ .err = e };
ctx.col = 0;
} else {
const pos = leaf.width_to_pos(ctx.col, base_col, mtrx) catch |e| return .{ .err = e };
const pos_end = leaf.width_to_pos(ctx.col + ctx.count, base_col, mtrx) catch |e| return .{ .err = e };
const pos = leaf.width_to_pos(ctx.col, base_col, metrics) catch |e| return .{ .err = e };
const pos_end = leaf.width_to_pos(ctx.col + ctx.count, base_col, metrics) catch |e| return .{ .err = e };
const left = Leaf.new(ctx.a, leaf.buf[0..pos], leaf_bol, false) catch |e| return .{ .err = e };
const right = Leaf.new(ctx.a, leaf.buf[pos_end..], false, leaf.eol) catch |e| return .{ .err = e };
result.replace = Node.new(ctx.a, left, right) catch |e| return .{ .err = e };
@ -679,7 +679,7 @@ const Node = union(enum) {
}
};
var ctx: Ctx = .{ .a = a, .col = col, .count = count };
const found, const root = try self.walk_from_line_begin(a, line, Ctx.walker, &ctx, mtrx_);
const found, const root = try self.walk_from_line_begin(a, line, Ctx.walker, &ctx, metrics_);
return if (found) (if (root) |r| r else error.Stop) else error.NotFound;
}
@ -695,46 +695,46 @@ const Node = union(enum) {
return Node.new(a, try merge_in_place(leaves[0..mid], a), try merge_in_place(leaves[mid..], a));
}
pub fn get_line(self: *const Node, line: usize, result: *ArrayList(u8), mtrx: Metrix) !void {
pub fn get_line(self: *const Node, line: usize, result: *ArrayList(u8), metrics: Metrics) !void {
const Ctx = struct {
line: *ArrayList(u8),
fn walker(ctx_: *anyopaque, leaf: *const Leaf, _: Metrix) Walker {
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 };
return if (!leaf.eol) Walker.keep_walking else Walker.stop;
}
};
var ctx: Ctx = .{ .line = result };
const found = self.walk_from_line_begin_const(line, Ctx.walker, &ctx, mtrx) catch false;
const found = self.walk_from_line_begin_const(line, Ctx.walker, &ctx, metrics) catch false;
return if (!found) error.NotFound;
}
pub fn line_width(self: *const Node, line: usize, mtrx_: Metrix) !usize {
pub fn line_width(self: *const Node, line: usize, metrics_: Metrics) !usize {
const do = struct {
result: usize = 0,
fn walker(ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) Walker {
fn walker(ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) Walker {
const do = @as(*@This(), @ptrCast(@alignCast(ctx)));
do.result += leaf.width(do.result, mtrx);
do.result += leaf.width(do.result, metrics);
return if (!leaf.eol) Walker.keep_walking else Walker.stop;
}
};
var ctx: do = .{};
const found = self.walk_from_line_begin_const(line, do.walker, &ctx, mtrx_) catch true;
const found = self.walk_from_line_begin_const(line, do.walker, &ctx, metrics_) catch true;
return if (found) ctx.result else error.NotFound;
}
pub fn pos_to_width(self: *const Node, line: usize, pos: usize, mtrx_: Metrix) !usize {
pub fn pos_to_width(self: *const Node, line: usize, pos: usize, metrics_: Metrics) !usize {
const do = struct {
result: usize = 0,
pos: usize,
fn walker(ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) Walker {
fn walker(ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) Walker {
const do = @as(*@This(), @ptrCast(@alignCast(ctx)));
do.result += leaf.pos_to_width(&do.pos, do.result, mtrx);
do.result += leaf.pos_to_width(&do.pos, do.result, metrics);
return if (!(leaf.eol or do.pos == 0)) Walker.keep_walking else Walker.stop;
}
};
var ctx: do = .{ .pos = pos };
const found = self.walk_from_line_begin_const(line, do.walker, &ctx, mtrx_) catch true;
const found = self.walk_from_line_begin_const(line, do.walker, &ctx, metrics_) catch true;
return if (found) ctx.result else error.NotFound;
}
@ -744,7 +744,7 @@ const Node = union(enum) {
col_: usize,
s: []const u8,
a: Allocator,
mtrx_: Metrix,
metrics_: Metrics,
) !struct { usize, usize, Root } {
var self = self_;
const Ctx = struct {
@ -754,9 +754,9 @@ const Node = union(enum) {
s: []const u8,
eol: bool,
fn walker(ctx: *anyopaque, leaf: *const Leaf, mtrx: Metrix) WalkerMut {
fn walker(ctx: *anyopaque, leaf: *const Leaf, metrics: Metrics) WalkerMut {
const Ctx = @as(*@This(), @ptrCast(@alignCast(ctx)));
const leaf_wcwidth = leaf.width(Ctx.abs_col, mtrx);
const leaf_wcwidth = leaf.width(Ctx.abs_col, metrics);
const base_col = Ctx.abs_col;
Ctx.abs_col += leaf_wcwidth;
@ -788,7 +788,7 @@ const Node = union(enum) {
}
if (leaf_wcwidth > Ctx.col) {
const pos = leaf.width_to_pos(Ctx.col, base_col, mtrx) catch |e| return .{ .err = e };
const pos = leaf.width_to_pos(Ctx.col, base_col, metrics) catch |e| return .{ .err = e };
if (Ctx.eol and Ctx.s.len == 0) {
const left = Leaf.new(Ctx.a, leaf.buf[0..pos], leaf.bol, Ctx.eol) catch |e| return .{ .err = e };
const right = Leaf.new(Ctx.a, leaf.buf[pos..], Ctx.eol, leaf.eol) catch |e| return .{ .err = e };
@ -825,14 +825,14 @@ const Node = union(enum) {
need_eol = false;
}
var ctx: Ctx = .{ .a = a, .col = col, .s = chunk, .eol = need_eol };
const found, const replace = try self.walk_from_line_begin(a, line, Ctx.walker, &ctx, mtrx_);
const found, const replace = try self.walk_from_line_begin(a, line, Ctx.walker, &ctx, metrics_);
if (!found) return error.NotFound;
if (replace) |root| self = root;
if (need_eol) {
line += 1;
col = 0;
} else {
col += mtrx_.egc_chunk_width(mtrx_.ctx, chunk, col);
col += metrics_.egc_chunk_width(metrics_.ctx, chunk, col);
}
}
return .{ line, col, self };
@ -925,19 +925,19 @@ const Node = union(enum) {
return self.store(ctx.writer());
}
pub fn debug_render_chunks(self: *const Node, line: usize, output: *ArrayList(u8), mtrx_: Metrix) !void {
pub fn debug_render_chunks(self: *const Node, line: usize, output: *ArrayList(u8), metrics_: Metrics) !void {
const ctx_ = struct {
l: *ArrayList(u8),
wcwidth: usize = 0,
fn walker(ctx_: *anyopaque, leaf: *const Leaf, mtrx: Metrix) Walker {
fn walker(ctx_: *anyopaque, leaf: *const Leaf, metrics: Metrics) Walker {
const ctx = @as(*@This(), @ptrCast(@alignCast(ctx_)));
leaf.dump(ctx.l, ctx.wcwidth, mtrx) catch |e| return .{ .err = e };
ctx.wcwidth += leaf.width(ctx.wcwidth, mtrx);
leaf.dump(ctx.l, ctx.wcwidth, metrics) catch |e| return .{ .err = e };
ctx.wcwidth += leaf.width(ctx.wcwidth, metrics);
return if (!leaf.eol) Walker.keep_walking else Walker.stop;
}
};
var ctx: ctx_ = .{ .l = output };
const found = self.walk_from_line_begin_const(line, ctx_.walker, &ctx, mtrx_) catch true;
const found = self.walk_from_line_begin_const(line, ctx_.walker, &ctx, metrics_) catch true;
if (!found) return error.NotFound;
var buf: [16]u8 = undefined;

View file

@ -3,7 +3,7 @@ const cbor = @import("cbor");
const Buffer = @import("Buffer.zig");
const View = @import("View.zig");
const Selection = @import("Selection.zig");
const Metrix = Buffer.Metrix;
const Metrics = Buffer.Metrics;
row: usize = 0,
col: usize = 0,
@ -27,20 +27,20 @@ pub inline fn right_of(self: Self, other: Self) bool {
return if (self.row > other.row) true else if (self.row == other.row and self.col > other.col) true else false;
}
pub fn clamp_to_buffer(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
pub fn clamp_to_buffer(self: *Self, root: Buffer.Root, metrics: Metrics) void {
self.row = @min(self.row, root.lines() - 1);
self.col = @min(self.col, root.line_width(self.row, mtrx) catch 0);
self.col = @min(self.col, root.line_width(self.row, metrics) catch 0);
}
fn follow_target(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
self.col = @min(self.target, root.line_width(self.row, mtrx) catch 0);
fn follow_target(self: *Self, root: Buffer.Root, metrics: Metrics) void {
self.col = @min(self.target, root.line_width(self.row, metrics) catch 0);
}
fn move_right_no_target(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
fn move_right_no_target(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
const lines = root.lines();
if (lines <= self.row) return error.Stop;
if (self.col < root.line_width(self.row, mtrx) catch 0) {
_, const wcwidth, const offset = root.ecg_at(self.row, self.col, mtrx) catch return error.Stop;
if (self.col < root.line_width(self.row, metrics) catch 0) {
_, const wcwidth, const offset = root.ecg_at(self.row, self.col, metrics) catch return error.Stop;
self.col += wcwidth - offset;
} else if (self.row < lines - 1) {
self.col = 0;
@ -48,73 +48,73 @@ fn move_right_no_target(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
} else return error.Stop;
}
pub fn move_right(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
try self.move_right_no_target(root, mtrx);
pub fn move_right(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
try self.move_right_no_target(root, metrics);
self.target = self.col;
}
fn move_left_no_target(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
fn move_left_no_target(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
if (self.col == 0) {
if (self.row == 0) return error.Stop;
self.row -= 1;
self.col = root.line_width(self.row, mtrx) catch 0;
self.col = root.line_width(self.row, metrics) catch 0;
} else {
_, const wcwidth, _ = root.ecg_at(self.row, self.col - 1, mtrx) catch return error.Stop;
_, const wcwidth, _ = root.ecg_at(self.row, self.col - 1, metrics) catch return error.Stop;
if (self.col > wcwidth) self.col -= wcwidth else self.col = 0;
}
}
pub fn move_left(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
try self.move_left_no_target(root, mtrx);
pub fn move_left(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
try self.move_left_no_target(root, metrics);
self.target = self.col;
}
pub fn move_up(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
pub fn move_up(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
if (self.row > 0) {
self.row -= 1;
self.follow_target(root, mtrx);
self.move_left_no_target(root, mtrx) catch return;
try self.move_right_no_target(root, mtrx);
self.follow_target(root, metrics);
self.move_left_no_target(root, metrics) catch return;
try self.move_right_no_target(root, metrics);
} else return error.Stop;
}
pub fn move_down(self: *Self, root: Buffer.Root, mtrx: Metrix) !void {
pub fn move_down(self: *Self, root: Buffer.Root, metrics: Metrics) !void {
if (self.row < root.lines() - 1) {
self.row += 1;
self.follow_target(root, mtrx);
self.move_left_no_target(root, mtrx) catch return;
try self.move_right_no_target(root, mtrx);
self.follow_target(root, metrics);
self.move_left_no_target(root, metrics) catch return;
try self.move_right_no_target(root, metrics);
} else return error.Stop;
}
pub fn move_page_up(self: *Self, root: Buffer.Root, view: *const View, mtrx: Metrix) void {
pub fn move_page_up(self: *Self, root: Buffer.Root, view: *const View, metrics: Metrics) void {
self.row = if (self.row > view.rows) self.row - view.rows else 0;
self.follow_target(root, mtrx);
self.move_left_no_target(root, mtrx) catch return;
self.move_right_no_target(root, mtrx) catch return;
self.follow_target(root, metrics);
self.move_left_no_target(root, metrics) catch return;
self.move_right_no_target(root, metrics) catch return;
}
pub fn move_page_down(self: *Self, root: Buffer.Root, view: *const View, mtrx: Metrix) void {
pub fn move_page_down(self: *Self, root: Buffer.Root, view: *const View, metrics: Metrics) void {
if (root.lines() > self.row + view.rows) {
self.row += view.rows;
} else self.move_buffer_last(root, mtrx);
self.follow_target(root, mtrx);
self.move_left_no_target(root, mtrx) catch return;
self.move_right_no_target(root, mtrx) catch return;
} else self.move_buffer_last(root, metrics);
self.follow_target(root, metrics);
self.move_left_no_target(root, metrics) catch return;
self.move_right_no_target(root, metrics) catch return;
}
pub fn move_to(self: *Self, root: Buffer.Root, row: usize, col: usize, mtrx: Metrix) !void {
pub fn move_to(self: *Self, root: Buffer.Root, row: usize, col: usize, metrics: Metrics) !void {
if (row < root.lines()) {
self.row = row;
self.col = @min(col, root.line_width(self.row, mtrx) catch return error.Stop);
self.col = @min(col, root.line_width(self.row, metrics) catch return error.Stop);
self.target = self.col;
} else return error.Stop;
}
pub fn move_abs(self: *Self, root: Buffer.Root, v: *View, y: usize, x: usize, mtrx: Metrix) !void {
pub fn move_abs(self: *Self, root: Buffer.Root, v: *View, y: usize, x: usize, metrics: Metrics) !void {
self.row = v.row + y;
self.col = v.col + x;
self.clamp_to_buffer(root, mtrx);
self.clamp_to_buffer(root, metrics);
self.target = self.col;
}
@ -123,8 +123,8 @@ pub fn move_begin(self: *Self) void {
self.target = self.col;
}
pub fn move_end(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
if (self.row < root.lines()) self.col = root.line_width(self.row, mtrx) catch 0;
pub fn move_end(self: *Self, root: Buffer.Root, metrics: Metrics) void {
if (self.row < root.lines()) self.col = root.line_width(self.row, metrics) catch 0;
self.target = std.math.maxInt(u32);
}
@ -134,32 +134,32 @@ pub fn move_buffer_begin(self: *Self) void {
self.target = 0;
}
pub fn move_buffer_end(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
pub fn move_buffer_end(self: *Self, root: Buffer.Root, metrics: Metrics) void {
self.row = root.lines() - 1;
self.move_end(root, mtrx);
self.move_end(root, metrics);
if (self.col == 0) self.target = 0;
}
fn move_buffer_first(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
fn move_buffer_first(self: *Self, root: Buffer.Root, metrics: Metrics) void {
self.row = 0;
self.follow_target(root, mtrx);
self.follow_target(root, metrics);
}
fn move_buffer_last(self: *Self, root: Buffer.Root, mtrx: Metrix) void {
fn move_buffer_last(self: *Self, root: Buffer.Root, metrics: Metrics) void {
self.row = root.lines() - 1;
self.follow_target(root, mtrx);
self.follow_target(root, metrics);
}
fn is_at_begin(self: *const Self) bool {
return self.col == 0;
}
fn is_at_end(self: *const Self, root: Buffer.Root, mtrx: Metrix) bool {
return if (self.row < root.lines()) self.col == root.line_width(self.row, mtrx) catch 0 else true;
fn is_at_end(self: *const Self, root: Buffer.Root, metrics: Metrics) bool {
return if (self.row < root.lines()) self.col == root.line_width(self.row, metrics) catch 0 else true;
}
pub fn test_at(self: *const Self, root: Buffer.Root, pred: *const fn (c: []const u8) bool, mtrx: Metrix) bool {
return root.test_at(pred, self.row, self.col, mtrx);
pub fn test_at(self: *const Self, root: Buffer.Root, pred: *const fn (c: []const u8) bool, metrics: Metrics) bool {
return root.test_at(pred, self.row, self.col, metrics);
}
pub fn write(self: *const Self, writer: Buffer.MetaWriter) !void {

View file

@ -16,7 +16,7 @@ pub fn from_cursor(cursor: *const Cursor) Self {
return .{ .begin = cursor.*, .end = cursor.* };
}
pub fn line_from_cursor(cursor: Cursor, root: Buffer.Root, mtrx: Buffer.Metrix) Self {
pub fn line_from_cursor(cursor: Cursor, root: Buffer.Root, mtrx: Buffer.Metrics) Self {
var begin = cursor;
var end = cursor;
begin.move_begin();