summaryrefslogtreecommitdiff
path: root/src/Messages.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Messages.zig')
-rw-r--r--src/Messages.zig48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/Messages.zig b/src/Messages.zig
index a316377a..366445c7 100644
--- a/src/Messages.zig
+++ b/src/Messages.zig
@@ -486,13 +486,53 @@ pub fn reportError(p: *Pardes, id: usize, operation: []const u8, err: anyerror)
p.fs.no_pane_slot_len = @intCast(w.buffered().len);
return reportFailure(p, id, w.buffered());
}
- for (@errorName(err), 0..) |c, i| {
- if (std.ascii.isUpper(c) and i > 0) w.writeByte(' ') catch break;
- w.writeByte(std.ascii.toLower(c)) catch break;
- }
+ var words: [128]u8 = undefined;
+ w.writeAll(errorWords(err, &words)) catch {};
reportFailure(p, id, w.buffered());
}
+/// An error in a person's words, never its Zig name: the few that read
+/// badly spaced out said plainly, the rest spaced and lower case
+/// (`FileNotFound`, "file not found").
+pub fn errorWords(err: anyerror, buf: []u8) []const u8 {
+ return switch (err) {
+ error.FileTooLarge => "too large",
+ error.NotAFile => "not a regular file",
+ error.ReadFailed => "could not be read",
+ error.ParseZon => "not valid ZON",
+ error.ThemeFileTooLarge => "too large: a theme file is at most 1 MiB",
+ error.InvalidThemeName => "its name is empty or over 255 bytes",
+ else => {
+ var w = std.Io.Writer.fixed(buf);
+ for (@errorName(err), 0..) |c, i| {
+ if (std.ascii.isUpper(c) and i > 0) w.writeByte(' ') catch break;
+ w.writeByte(std.ascii.toLower(c)) catch break;
+ }
+ return w.buffered();
+ },
+ };
+}
+
+/// A ZON parse failure in a person's words: the first error the parser
+/// found and its line, `line 3: expected ','`.
+pub fn zonWhy(diag: *const std.zon.parse.Diagnostics, buf: []u8) []const u8 {
+ var errors = diag.iterateErrors();
+ const first = errors.next() orelse return "not valid ZON";
+ const loc = first.getLocation(diag);
+ return std.fmt.bufPrint(buf, "line {d}: {f}", .{ loc.line + 1, first.fmtMessage(diag) }) catch "not valid ZON";
+}
+
+test "errors are said in words, and a ZON failure names its line" {
+ var buf: [128]u8 = undefined;
+ try std.testing.expectEqualStrings("file not found", errorWords(error.FileNotFound, &buf));
+ try std.testing.expectEqualStrings("too large", errorWords(error.FileTooLarge, &buf));
+ var diag: std.zon.parse.Diagnostics = .{};
+ defer diag.deinit(std.testing.allocator);
+ const T = struct { a: u8 };
+ try std.testing.expectError(error.ParseZon, std.zon.parse.fromSliceAlloc(T, std.testing.allocator, ".{\n .a = 1,\n .b = 2 }", &diag, .{}));
+ try std.testing.expect(std.mem.startsWith(u8, zonWhy(&diag, &buf), "line 3: "));
+}
+
/// The longest start of `text` that fits `max` bytes and ends between
/// words (or, with no space to cut at, between characters).
pub fn clip(text: []const u8, max: usize) []const u8 {