summaryrefslogtreecommitdiff
path: root/src/fonts.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/fonts.zig')
-rw-r--r--src/fonts.zig46
1 files changed, 14 insertions, 32 deletions
diff --git a/src/fonts.zig b/src/fonts.zig
index 1e82956e..4cfba44c 100644
--- a/src/fonts.zig
+++ b/src/fonts.zig
@@ -58,29 +58,6 @@ const max_depth = 8;
pub const Font = struct { name: []const u8, path: []const u8 };
-/// The font the shell should be wearing, as a PATH — written by the Font
-/// builtin, taken by the shell on its next pass through the loop. Exactly the
-/// shape Pardes.restore_req has, including the buffer behind it: the request
-/// outlives the scratch arena the walk found the path in.
-///
-/// A module var rather than a field on Pardes because the core does not have a
-/// font, has no opinion about one, and on every other platform does not have
-/// this file either — a field would be state the tty build carries around to
-/// never touch.
-pub var want_buf: [4096]u8 = undefined;
-pub var want: ?[]const u8 = null;
-
-/// ...and the same request as a NAME, for the Debug overlay to show. A slice
-/// of `want_buf` rather than a second buffer: the stem of the path IS the name
-/// the picker listed, and the only writer of one is the writer of the other.
-///
-/// What was CHOSEN, not what is worn: the shell may turn a file down (gui.zig
-/// keeps the face that works when FreeType refuses one) and it alone knows
-/// what it booted in — embedded Adwaita Mono under SDL, the system monospace
-/// face under AppKit. Empty means nothing has been chosen and the shell is
-/// still wearing whichever of those it is.
-pub var chosen: []const u8 = "";
-
/// Optional fallback faces, in preference order after the always-available
/// embedded Adwaita Mono face. Keep text faces before symbol faces so ordinary
/// letters retain terminal-like metrics; DejaVu Sans is the final broad,
@@ -99,22 +76,27 @@ pub const fallback_names = [_][]const u8{
pub fn list(arena: std.mem.Allocator, want_name: ?[]const u8) []const Font {
if (want_name) |name| {
const wanted = [1][]const u8{name};
- return scan(arena, &wanted);
+ return scan(arena, &wanted, true);
}
- return scan(arena, null);
+ return scan(arena, null, true);
}
/// Installed members of `fallback_names`, returned in preference order. This
/// is runtime discovery only: no local font path or exploration result enters
/// the build, and a machine with none simply uses embedded Adwaita Mono.
pub fn fallbacks(arena: std.mem.Allocator) []const Font {
- return scan(arena, &fallback_names);
+ return scan(arena, &fallback_names, false);
}
/// One bounded directory walk for the picker, one named font, or the fallback
-/// chain. `wanted == null` means every monospace face; named scans accept
-/// proportional symbol/general faces and preserve the requested priority.
-fn scan(arena: std.mem.Allocator, wanted: ?[]const []const u8) []const Font {
+/// chain. User-facing lists always require a fixed-pitch face, including an
+/// exact `Font <name>` request. The fallback chain opts out deliberately so a
+/// broad symbol face may fill glyphs the primary grid face does not contain.
+fn scan(
+ arena: std.mem.Allocator,
+ wanted: ?[]const []const u8,
+ require_monospaced: bool,
+) []const Font {
// ...from the arena, not the stack: 4096 faces of {name, path} is 128 KiB,
// which is a fine thing to hand back to an arena that resets at the end of
// the keystroke and not a thing to put on a call stack. An allocator that
@@ -123,8 +105,8 @@ fn scan(arena: std.mem.Allocator, wanted: ?[]const []const u8) []const Font {
const found = arena.alloc(Font, max_fonts) catch return &.{};
var found_len: usize = 0;
// Zig 0.16 moved the filesystem behind std.Io; the blocking
- // single-threaded implementation is the synchronous walk a sans-IO core
- // wants, the same one look.find uses.
+ // single-threaded implementation is the synchronous walk the core uses,
+ // the same one look.find uses.
const io = std.Io.Threaded.global_single_threaded.io();
const home: []const u8 = if (libc.getenv("HOME")) |h| std.mem.span(h) else "";
var root_buf: [512]u8 = undefined;
@@ -179,7 +161,7 @@ fn scan(arena: std.mem.Allocator, wanted: ?[]const []const u8) []const Font {
// e.path points into the walker's own buffer and dies at the next
// next(), so the path is spelled out here and copied below
const path = std.fmt.bufPrintSentinel(&path_buf, "{s}/{s}", .{ root, e.path }, 0) catch continue;
- if (wanted == null and !monospaced(path)) continue;
+ if (require_monospaced and !monospaced(path)) continue;
found[found_len] = .{
.name = arena.dupe(u8, name) catch break,
.path = arena.dupe(u8, path) catch break,