From 989dcf395be7280240fc501ba1f07f75bacf91a3 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Wed, 30 Sep 2026 22:33:15 -0300 Subject: The cheatsheet draws mouse buttons as a mouse, keys as chips, and pairs as tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #btn and #chord draw a mouse (left button, wheel, right button) with the pressed part filled; the wheel is a narrow slot on a paper halo, hollow or filled, so it never reads as a button. A chord is the held button, then for each click the held one and that one down, with arrows between; #btn(.., shift: true) adds a ⇧. HTML gets a span with an aria-label. A key is one soft pill with no border: a combination (Ctrl-w) reads Ctrl + w and a sequence (g g, SPC f c) g › g, separators muted inside it; #keys("h", "j", ...) sets alternatives as separate pills. The drift test reads every key a #keys call names. #pairs sets key | meaning content as a two-column table on alternating tints; split: 2 sets the leader map as two such tables side by side. The mouse chords get their own table: cut, paste, copy (B1-B2 then B1-B3, one B1 hold, as mouse.zig says), 2-1 with an argument, 2-3 cancelling. The A4 page draws its own title and drops the content's level-1 heading. docs/typ/README is the function contract for content files. Co-Authored-By: Claude Opus 5.5 --- src/config.zig | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config.zig b/src/config.zig index 53def6a1..7908774b 100644 --- a/src/config.zig +++ b/src/config.zig @@ -2030,14 +2030,21 @@ test { /// The docs in docs/typ name words, keys and tags; each must still be here. const doc_typ = struct { - /// The string argument of every `name("...")` call in a source. + /// The leading string arguments of every `name("...", "...")` call in a + /// source: one for word, key and tag, each of them for keys. fn calls(gpa: std.mem.Allocator, source: []const u8, comptime name: []const u8, out: *std.ArrayList([]const u8)) !void { var at: usize = 0; while (std.mem.indexOfPos(u8, source, at, name ++ "(\"")) |i| { at = i + name.len + 2; if (i > 0 and (std.ascii.isAlphanumeric(source[i - 1]) or source[i - 1] == '-')) continue; - const end = std.mem.indexOfScalarPos(u8, source, at, '"') orelse return error.Unterminated; - try out.append(gpa, source[at..end]); + while (true) { + const end = std.mem.indexOfScalarPos(u8, source, at, '"') orelse return error.Unterminated; + try out.append(gpa, source[at..end]); + at = end + 1; + while (at < source.len and (source[at] == ',' or source[at] == ' ')) at += 1; + if (at >= source.len or source[at] != '"') break; + at += 1; + } } } @@ -2139,6 +2146,7 @@ test "docs/typ names only words, keys and default tags that exist" { while (try it.next(io)) |entry| if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".typ")) { const source = try dir.readFileAlloc(io, entry.name, gpa, .limited(1 << 20)); inline for (.{ "word", "key", "tag" }, &found) |name, *list| try doc_typ.calls(gpa, source, name, list); + try doc_typ.calls(gpa, source, "keys", &found[1]); // alternatives, each a key }; inline for (.{ "word", "key", "tag" }, found) |name, list| { try std.testing.expect(list.items.len >= 5); -- cgit v1.3