diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/colors.zig | 23 | ||||
| -rw-r--r-- | src/exec.zig | 8 |
2 files changed, 27 insertions, 4 deletions
diff --git a/src/colors.zig b/src/colors.zig index aa69fe6d..72e25aed 100644 --- a/src/colors.zig +++ b/src/colors.zig @@ -718,7 +718,7 @@ pub fn themesNear(buf: []u8, name: []const u8) []const u8 { var w = std.Io.Writer.fixed(buf); for (themes) |t| { if (name.len > 0 and std.ascii.toLower(t.name[0]) != std.ascii.toLower(name[0])) continue; - w.print("{s}{s}", .{ if (w.buffered().len > 0) " " else "", t.name }) catch break; + if (!putName(&w, buf.len, t.name)) break; } else if (w.buffered().len > 0) return w.buffered(); // The nearest, most alike first: ponytail, a plain score (shared // prefix, the name inside, its letters in order), no edit distance. @@ -741,10 +741,29 @@ pub fn themesNear(buf: []u8, name: []const u8) []const u8 { n = @min(n + 1, best.len); } w = std.Io.Writer.fixed(buf); - for (best[0..n]) |i| w.print("{s}{s}", .{ if (w.buffered().len > 0) " " else "", themes[i].name }) catch break; + for (best[0..n]) |i| if (!putName(&w, buf.len, themes[i].name)) break; return w.buffered(); } +/// One more name on the line, whole, or none: false when it would not fit. +fn putName(w: *std.Io.Writer, cap: usize, name: []const u8) bool { + const sep: []const u8 = if (w.buffered().len > 0) " " else ""; + if (w.buffered().len + sep.len + name.len > cap) return false; + w.print("{s}{s}", .{ sep, name }) catch return false; + return true; +} + +test "a theme hint drops whole names to fit, never cutting one" { + var buf: [23]u8 = undefined; + const said = themesNear(&buf, "9dracula"); + var words = std.mem.tokenizeScalar(u8, said, ' '); + while (words.next()) |word| { + var whole = false; + for (themes) |t| whole = whole or std.mem.eql(u8, t.name, word); + try std.testing.expect(whole); + } +} + fn likeness(theme_name: []const u8, name: []const u8) usize { var prefix: usize = 0; while (prefix < @min(theme_name.len, name.len) and std.ascii.toLower(theme_name[prefix]) == std.ascii.toLower(name[prefix])) prefix += 1; diff --git a/src/exec.zig b/src/exec.zig index cf4e01ab..88c0705d 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -918,9 +918,13 @@ pub fn applySettingBuiltin(p: *Pardes, setting: config.Runtime.Setting, arg: ?[] // A config line is not answered on screen (applyStartupConfig // runs with announce off); a click or a ctl write is. if (!p.announce) return; - var near: [170]u8 = undefined; + // All of it within the 128 bytes a 9P error carries, so a write + // failing with it is cut nowhere: the names get what is left. + const shown = want[0..@min(want.len, 40)]; + const room = 128 -| ("Theme: no theme \"\"; like it: ; Themes lists all".len + shown.len); + var near: [128]u8 = undefined; var text: [256]u8 = undefined; - return p.reportFailure(p.active, std.fmt.bufPrint(&text, "Theme: no theme \"{s}\"; like it: {s}; Themes lists all", .{ want[0..@min(want.len, 40)], colors.themesNear(&near, want) }) catch "Theme: no such theme"); + return p.reportFailure(p.active, std.fmt.bufPrint(&text, "Theme: no theme \"{s}\"; like it: {s}; Themes lists all", .{ shown, colors.themesNear(near[0..@min(room, near.len)], want) }) catch "Theme: no such theme"); }, .font => { if (comptime !font_picker) return; |
