summaryrefslogtreecommitdiff
path: root/src/tag_line.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-11 12:38:56 -0300
committerGabriel Schneider <[email protected]>2026-09-15 17:24:42 -0300
commit682e237df7e8b22f820d14a4adee58e6e2f84268 (patch)
tree5d888cb46f1a49e89fc55e2a4c232d3af0265b1d /src/tag_line.zig
parent6878e1c309172d624c0d7a3555f6f0217ae6770e (diff)
downloadpardes-682e237df7e8b22f820d14a4adee58e6e2f84268.tar.gz
pardes-682e237df7e8b22f820d14a4adee58e6e2f84268.zip
trunk: resume before the Reload experiment
Empty marker on the last pre-Reload change. Keep the Reload experiment on reload (3801914), its first change on reload-start (200a1fc), and the unfinished performance investigation on reload-perf-wip.
Diffstat (limited to 'src/tag_line.zig')
-rw-r--r--src/tag_line.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/tag_line.zig b/src/tag_line.zig
new file mode 100644
index 00000000..d1a9d166
--- /dev/null
+++ b/src/tag_line.zig
@@ -0,0 +1,41 @@
+//! Bounded, single-line editable chrome. Offsets are UTF-8 byte offsets.
+const std = @import("std");
+const modal = @import("modal.zig");
+pub const Line = struct {
+ text: [@import("memory.zig").limits.max_tag_tail]u8 = undefined,
+ len: usize = 0,
+ custom: bool = false,
+
+ pub fn slice(self: *const Line, fallback: []const u8) []const u8 {
+ return if (self.custom) self.text[0..self.len] else fallback;
+ }
+ pub fn set(self: *Line, bytes: []const u8) bool {
+ if (bytes.len > self.text.len or std.mem.indexOfAny(u8, bytes, "\r\n\x00") != null or !std.unicode.utf8ValidateSlice(bytes)) return false;
+ @memcpy(self.text[0..bytes.len], bytes);
+ self.len = bytes.len;
+ self.custom = true;
+ return true;
+ }
+ pub fn replace(self: *Line, fallback: []const u8, lo: usize, hi: usize, bytes: []const u8) bool {
+ const current = self.slice(fallback);
+ if (lo > hi or hi > current.len) return false;
+ var next: [@import("memory.zig").limits.max_tag_tail]u8 = undefined;
+ const size = lo + bytes.len + current.len - hi;
+ if (size > next.len) return false;
+ @memcpy(next[0..lo], current[0..lo]);
+ @memcpy(next[lo..][0..bytes.len], bytes);
+ @memcpy(next[lo + bytes.len ..][0 .. current.len - hi], current[hi..]);
+ return self.set(next[0..size]);
+ }
+};
+
+test "tag replacement is atomic and keeps UTF-8 intact" {
+ var line: Line = .{};
+ try std.testing.expect(line.replace("New Find", 4, 8, "Grep"));
+ try std.testing.expectEqualStrings("New Grep", line.slice(""));
+ try std.testing.expect(!line.replace("", 0, 0, "bad\nline"));
+ try std.testing.expectEqualStrings("New Grep", line.slice(""));
+ try std.testing.expect(line.set("é界"));
+ try std.testing.expect(line.replace("", 0, modal.nextGrapheme(line.slice(""), 0), ""));
+ try std.testing.expectEqualStrings("界", line.slice(""));
+}