diff options
Diffstat (limited to 'src/Messages.zig')
| -rw-r--r-- | src/Messages.zig | 48 |
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 { |
