diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84280cd..5e9b7da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,6 @@ jobs: check: uses: fizzyedit/plugin-build-action/.github/workflows/check.yml@v7 with: - zig-version: "0.16.0" + zig-version: "0.17.0" # secrets: # build_env: ${{ secrets.MY_BUILD_ENV }} # as in release.yml, if the build needs one diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d0b531..655448f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,4 +14,4 @@ jobs: permissions: contents: write with: - zig-version: "0.16.0" + zig-version: "0.17.0" diff --git a/.github/workflows/sdk-repin.yml b/.github/workflows/sdk-repin.yml index e1a776c..28a0fd0 100644 --- a/.github/workflows/sdk-repin.yml +++ b/.github/workflows/sdk-repin.yml @@ -31,4 +31,4 @@ jobs: with: sdk-version: ${{ github.event.client_payload.version || inputs.sdk-version || '' }} force: ${{ inputs.force == true }} - zig-version: "0.16.0" + zig-version: "0.17.0" diff --git a/build.zig b/build.zig index a63a96f..556d6d5 100644 --- a/build.zig +++ b/build.zig @@ -269,7 +269,7 @@ pub fn build(b: *std.Build) void { }); bench.root_module.addImport("content_graph", cg_for_bench); const run_bench = b.addRunArtifact(bench); - if (b.args) |a| run_bench.addArgs(a); + run_bench.addPassthruArgs(); b.step("bench", "Scan/resolve timings, --stats, --world, --shapes, --stability").dependOn(&run_bench.step); } @@ -286,7 +286,7 @@ pub fn build(b: *std.Build) void { }), }); const run_wiki = b.addRunArtifact(wiki); - if (b.args) |a| run_wiki.addArgs(a); + run_wiki.addPassthruArgs(); b.step("wiki-import", "MediaWiki XML dump -> markdown vault").dependOn(&run_wiki.step); } diff --git a/build.zig.zon b/build.zig.zon index 4cbbfef..6267b7a 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .atlas, .version = "0.0.1", - .minimum_zig_version = "0.16.0", + .minimum_zig_version = "0.17.0", .paths = .{ "build.zig", "build.zig.zon", @@ -21,8 +21,8 @@ // The published SDK, not a path into a checkout: a release has to build from a // clean clone, and the release asset (never the tag's git archive) is the SDK // package alone — the monorepo root zon carries the app's own dependencies. - .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.29/fizzy-sdk-v0.2.29.tar.gz", - .hash = "fizzy-0.2.29-SGBwY2sxJgCLLSPt4HLdlMSg7WtcP4K0fdtXI5WwJl2d", + .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.30/fizzy-sdk-v0.2.30.tar.gz", + .hash = "fizzy-0.2.30-SGBwY1QnJwDznUMVnSLATxXgH2e8_Vz7eMwLj9UQ0sVU", }, }, } diff --git a/plugin.zig.zon b/plugin.zig.zon index e79c73c..fac3942 100644 --- a/plugin.zig.zon +++ b/plugin.zig.zon @@ -1,8 +1,8 @@ .{ .id = "atlas", .name = "Atlas", - .version = "0.0.24", - .min_sdk_version = "0.2.29", + .version = "0.0.25", + .min_sdk_version = "0.2.30", .description = "Wiki-style notes for fizzy: [[wikilinks]], backlinks, and a graph of how your markdown connects.", .tags = .{ "notes", "markdown", "wiki" }, .author = "foxnne", diff --git a/src/batch2d/SoftAtlas.zig b/src/batch2d/SoftAtlas.zig index 1b09391..b385610 100644 --- a/src/batch2d/SoftAtlas.zig +++ b/src/batch2d/SoftAtlas.zig @@ -60,7 +60,7 @@ pub fn deinit(self: *SoftAtlas, gpa: std.mem.Allocator) void { /// neighbouring atlas cell (kinds sit in one horizontal strip). pub fn uv(self: *const SoftAtlas, kind: Kind) UvRect { _ = self; - const i: u32 = @intFromEnum(kind); + const i: u32 = @backingInt(kind); const size: f32 = @floatFromInt(atlas_w); const h: f32 = @floatFromInt(pad_px); const x0: f32 = @floatFromInt(i * cell_px); @@ -255,7 +255,7 @@ const testing = std.testing; test "atlas cells are non-empty and non-overlapping in alpha mass" { var a = try SoftAtlas.init(testing.allocator); defer a.deinit(testing.allocator); - var mass: [cells]u32 = .{0} ** cells; + var mass: [cells]u32 = @splat(0); for (0..cells) |c| { const ox = c * cell_px; for (0..cell_px) |y| { @@ -287,8 +287,8 @@ test "dash ring has less alpha mass than solid ring" { defer a.deinit(testing.allocator); var solid: u32 = 0; var dashed: u32 = 0; - const ox_r = @intFromEnum(Kind.ring) * cell_px; - const ox_d = @intFromEnum(Kind.dash_ring) * cell_px; + const ox_r = @backingInt(Kind.ring) * cell_px; + const ox_d = @backingInt(Kind.dash_ring) * cell_px; for (0..cell_px) |y| { for (0..cell_px) |x| { solid += a.pixels[y * atlas_w + ox_r + x].a; diff --git a/src/bench_main.zig b/src/bench_main.zig index 22f4c43..93346dc 100644 --- a/src/bench_main.zig +++ b/src/bench_main.zig @@ -303,7 +303,7 @@ pub fn main(init: std.process.Init) !void { "{s:<22}{s:>7}{s:>8}{s:>9}{s:>8}{s:>10}{s:>8}{s:>9}{s:>8}{s:>8}{s:>9}{s:>11}\n", .{ "vault", "notes", "edges", "read", "scan", "resolve", "hop2", "force", "pack", "relax", "snap+ref", "LAYOUT" }, ); - std.debug.print("{s}\n", .{"-" ** 117}); + std.debug.print("{s}\n", .{&@as([117]u8, @splat('-'))}); } var i: usize = 1; @@ -1100,9 +1100,9 @@ fn linkSpreadReport( // The same sample, split by the busier endpoint's degree. const cuts = [_]u32{ 8, 32, 128, 512, std.math.maxInt(u32) }; - var b_sum: [cuts.len]f64 = .{0} ** cuts.len; - var b_far: [cuts.len]usize = .{0} ** cuts.len; - var b_n: [cuts.len]usize = .{0} ** cuts.len; + var b_sum: [cuts.len]f64 = @splat(0); + var b_far: [cuts.len]usize = @splat(0); + var b_n: [cuts.len]usize = @splat(0); var ei: usize = 0; while (ei < edges.len) : (ei += stride) { const e = edges[ei]; @@ -1464,7 +1464,7 @@ fn layoutReport( // blank annulus the reader sees around the giant component is a trailing zero. { const rings = 8; - var hist: [rings]usize = .{0} ** rings; + var hist: [rings]usize = @splat(0); var total: usize = 0; const n_notes = w.lad.leaf_cell.len; const stride = @max(1, n_notes / sample_cap); @@ -2271,7 +2271,7 @@ fn printStabilityHeader() void { "fine p50/p90/max", "region p50/p90/max", "fine%", "region%", }, ); - std.debug.print("{s}\n", .{"-" ** 120}); + std.debug.print("{s}\n", .{&@as([120]u8, @splat('-'))}); } fn printStabilityRow(label: []const u8, n: usize, e: usize, s: louvain.Stability) void { diff --git a/src/index/query.zig b/src/index/query.zig index a9f4270..8731a97 100644 --- a/src/index/query.zig +++ b/src/index/query.zig @@ -190,7 +190,7 @@ pub fn noteContentGraph( }); try heading_rows.append(arena, .{ .line = h.line, .level = level }); } - for (n.blocks) |b| try block_rows.append(arena, .{ .kind = @intFromEnum(b.kind), .line_start = b.line_start, .line_end = b.line_end, .weight = b.weight }); + for (n.blocks) |b| try block_rows.append(arena, .{ .kind = @backingInt(b.kind), .line_start = b.line_start, .line_end = b.line_end, .weight = b.weight }); for (n.tags) |t| try tag_rows.append(arena, .{ .tag = try arena.dupe(u8, t.tag), .line = t.line }); // Embeds are kept apart from the same-note cross-reference edges below rather than // merged into them. @@ -254,7 +254,7 @@ pub fn noteContentGraph( }, .block => { const b = block_rows.items[m.idx]; - const kind: content_graph.ItemKind = switch (@as(schema.BlockKind, @enumFromInt(b.kind))) { + const kind: content_graph.ItemKind = switch (@as(schema.BlockKind, @fromBackingInt(@intCast(b.kind)))) { .paragraph => .paragraph, .list => .list, .code => .code, @@ -335,7 +335,7 @@ fn appendBodyItem( } fn ordinalKey(parent_id: i64, kind: content_graph.ItemKind) u64 { - return (@as(u64, @bitCast(parent_id)) *% 1099511628211) ^ @as(u64, @intFromEnum(kind)); + return (@as(u64, @bitCast(parent_id)) *% 1099511628211) ^ @as(u64, @backingInt(kind)); } /// Identity for a non-heading item: unstable across edits that reorder or insert siblings under @@ -343,7 +343,7 @@ fn ordinalKey(parent_id: i64, kind: content_graph.ItemKind) u64 { fn contentItemId(kind: content_graph.ItemKind, parent_id: i64, ordinal: u32) i64 { var h = std.hash.Wyhash.init(ordinal); h.update(std.mem.asBytes(&parent_id)); - h.update(&[_]u8{@intFromEnum(kind)}); + h.update(&[_]u8{@backingInt(kind)}); const v: i64 = @intCast(h.final() & 0x7fff_ffff_ffff_ffff); return if (v == 0) 1 else v; } @@ -513,7 +513,7 @@ pub fn vaultRelative(vault: []const u8, abs: []const u8, buf: []u8) ?[]const u8 if (rest.len == 0 or rest.len > buf.len) return null; const out = buf[0..rest.len]; @memcpy(out, rest); - if (builtin.os.tag == .windows) { + if (builtin.target.os.tag == .windows) { std.mem.replaceScalar(u8, out, std.fs.path.sep_windows, std.fs.path.sep_posix); } return out; @@ -528,7 +528,7 @@ const sep_any = &[_]u8{ std.fs.path.sep_posix, std.fs.path.sep_windows }; fn hasPathPrefix(abs: []const u8, vault: []const u8) bool { if (abs.len < vault.len) return false; if (std.mem.eql(u8, abs[0..vault.len], vault)) return true; - if (builtin.os.tag != .windows) return false; + if (builtin.target.os.tag != .windows) return false; for (abs[0..vault.len], vault) |a, v| { const an = if (a == std.fs.path.sep_windows) std.fs.path.sep_posix else std.ascii.toLower(a); const vn = if (v == std.fs.path.sep_windows) std.fs.path.sep_posix else std.ascii.toLower(v); diff --git a/src/ui/containment.zig b/src/ui/containment.zig index 4d535f0..c4e5cfb 100644 --- a/src/ui/containment.zig +++ b/src/ui/containment.zig @@ -338,9 +338,9 @@ pub const Field = struct { // memoised in `expanded` — the relaxation is paid on the frame a cell first opens and never // again, which is the same budget the permutation search lived in. const n = kids.len; - var p: [8]Vec2 = .{Vec2{ .x = 0, .y = 0 }} ** 8; - var sep_r: [8]f32 = .{0} ** 8; - var mass: [8]f32 = .{1} ** 8; + var p: [8]Vec2 = @splat(Vec2{ .x = 0, .y = 0 }); + var sep_r: [8]f32 = @splat(0); + var mass: [8]f32 = @splat(1); var big: usize = 0; for (kids, 0..) |k, i| { sep_r[i] = self.separationRadius(lad, k); @@ -351,8 +351,8 @@ pub const Field = struct { } // Where each child's out-of-cell neighbours lie, as one unit direction per child. - var ext_dir: [8]Vec2 = .{Vec2{ .x = 0, .y = 0 }} ** 8; - var ext_mag: [8]f32 = .{0} ** 8; + var ext_dir: [8]Vec2 = @splat(Vec2{ .x = 0, .y = 0 }); + var ext_mag: [8]f32 = @splat(0); if (self.opts.ext_k != 0) { for (lad.extOf(cell)) |e| { if (e.child >= n or e.toward >= self.pos.len) continue; @@ -484,7 +484,7 @@ pub const Field = struct { } // Which bodies were touching someone on the previous step. Cohesion skips them. - var crowded: [8]bool = .{false} ** 8; + var crowded: [8]bool = @splat(false); var step: usize = 0; while (step < relax_steps) : (step += 1) { @@ -518,7 +518,7 @@ pub const Field = struct { } // separation — last, and it wins - crowded = .{false} ** 8; + crowded = @splat(false); for (0..n) |i| { for (i + 1..n) |j| { var dx = p[j].x - p[i].x; @@ -635,10 +635,10 @@ pub const Field = struct { ) void { const n = kids.len; const r_parent = self.estimatedRadius(lad, cell); - var p: [8]Vec2 = .{Vec2{ .x = 0, .y = 0 }} ** 8; - var sep_r: [8]f32 = .{0} ** 8; - var mass: [8]f32 = .{1} ** 8; - var sib_deg: [8]f32 = .{1} ** 8; + var p: [8]Vec2 = @splat(Vec2{ .x = 0, .y = 0 }); + var sep_r: [8]f32 = @splat(0); + var mass: [8]f32 = @splat(1); + var sib_deg: [8]f32 = @splat(1); for (kids, 0..) |k, i| { sep_r[i] = self.separationRadius(lad, k); mass[i] = 1 + lad.cells[k].weight + self.bodyMass(lad.cells[k].body); @@ -649,8 +649,8 @@ pub const Field = struct { sib_deg[sp.j] += sp.w; } - var ext_dir: [8]Vec2 = .{Vec2{ .x = 0, .y = 0 }} ** 8; - var ext_mag: [8]f32 = .{0} ** 8; + var ext_dir: [8]Vec2 = @splat(Vec2{ .x = 0, .y = 0 }); + var ext_mag: [8]f32 = @splat(0); if (self.opts.ext_k != 0) { for (lad.extOf(cell)) |e| { if (e.child >= n or e.toward >= self.pos.len) continue; diff --git a/src/ui/fold.zig b/src/ui/fold.zig index 6466ab7..84cae19 100644 --- a/src/ui/fold.zig +++ b/src/ui/fold.zig @@ -45,7 +45,7 @@ pub const Arity = enum(u8) { seven = 7, pub fn n(self: Arity) usize { - return @intFromEnum(self); + return @backingInt(self); } }; diff --git a/src/ui/graph.zig b/src/ui/graph.zig index 18b398a..2bb93fe 100644 --- a/src/ui/graph.zig +++ b/src/ui/graph.zig @@ -550,7 +550,7 @@ fn freeReuse(gpa: std.mem.Allocator, r: layout.Reuse) void { const LayoutJob = struct { arena: std.heap.ArenaAllocator, - phase: std.atomic.Value(u8) = .init(@intFromEnum(JobPhase.solving)), + phase: std.atomic.Value(u8) = .init(@backingInt(JobPhase.solving)), /// Set by `shutdownPanel` so the worker can abandon a long build instead of making teardown /// wait for it. The join itself is not optional — the worker is executing code inside a dylib /// that is about to be unloaded — so the only way to make closing the app prompt is to give @@ -662,7 +662,7 @@ const LayoutJob = struct { // remaining hitch on a prose save. return; } - job.phase.store(@intFromEnum(JobPhase.building_map), .release); + job.phase.store(@backingInt(JobPhase.building_map), .release); const gpa = sdk.allocator(); const a = job.arena.allocator(); @@ -999,7 +999,7 @@ pub const Panel = struct { interior: Interior, - touches: [10]Touch = [_]Touch{.{}} ** 10, + touches: [10]Touch = @as([10]Touch, @splat(.{})), gesture_active: bool = false, last_centroid: dvui.Point.Physical = .{}, last_pinch: f32 = 0, @@ -1387,7 +1387,7 @@ pub fn drawPanel(p: *Panel, st: anytype) !void { // wait it reports. if ((p.job != null or p.rebuild_waiting) and p.nodes.len == 0) { const building_map = if (p.job) |j| - j.phase.load(.acquire) == @intFromEnum(JobPhase.building_map) + j.phase.load(.acquire) == @backingInt(JobPhase.building_map) else false; if (building_map) { @@ -6470,7 +6470,7 @@ fn updateTouchGesture(p: *Panel, pane: *dvui.WidgetData) void { if (e.evt != .mouse) continue; const me = e.evt.mouse; if (!me.button.touch()) continue; - const slot_signed = @intFromEnum(me.button) - @intFromEnum(dvui.enums.Button.touch0); + const slot_signed = @backingInt(me.button) - @backingInt(dvui.enums.Button.touch0); if (slot_signed < 0 or slot_signed >= p.touches.len) continue; const slot: usize = @intCast(slot_signed); const inside = pane.rectScale().r.contains(me.p); diff --git a/src/ui/layout_full.zig b/src/ui/layout_full.zig index cdd32fe..aa4e94e 100644 --- a/src/ui/layout_full.zig +++ b/src/ui/layout_full.zig @@ -2045,8 +2045,8 @@ test "every slot lands on the hex lattice and is unique" { const n = 24; const snap = snapSpacingFor(n); var out: [n]dvui.Point = undefined; - var seeds: [n]?dvui.Point = .{null} ** n; - var deg: [n]u32 = .{0} ** n; + var seeds: [n]?dvui.Point = @splat(null); + var deg: [n]u32 = @splat(0); // A path so the force layout has something to pull on. var edges: [n - 1]Edge = undefined; for (0..n - 1) |i| edges[i] = .{ .a = i, .b = i + 1 }; @@ -2073,7 +2073,7 @@ test "linked nodes end up closer than unrelated ones" { // and meaningfully so: the snap lattice is half a packing slot, and springs are tuned so // a link settles near one snap cell while islands sit a packing slot apart. var out: [4]dvui.Point = undefined; - var seeds: [4]?dvui.Point = .{null} ** 4; + var seeds: [4]?dvui.Point = @splat(null); var deg: [4]u32 = .{ 1, 1, 1, 1 }; const edges = [_]Edge{ .{ .a = 0, .b = 1 }, .{ .a = 2, .b = 3 } }; try targets(testing.allocator, 4, &edges, &seeds, °, .{}, &out); @@ -2094,8 +2094,8 @@ test "survivors keep their cell when nothing changed" { const n = 8; const slot = slotSpacingFor(n); var out1: [n]dvui.Point = undefined; - var seeds: [n]?dvui.Point = .{null} ** n; - var deg: [n]u32 = .{0} ** n; + var seeds: [n]?dvui.Point = @splat(null); + var deg: [n]u32 = @splat(0); var edges: [n - 1]Edge = undefined; for (0..n - 1) |i| { edges[i] = .{ .a = i, .b = i + 1 }; @@ -2120,7 +2120,7 @@ test "adding a link pulls the endpoints closer" { const n = 5; const slot = slotSpacingFor(n); var out1: [n]dvui.Point = undefined; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var deg: [n]u32 = .{ 1, 2, 2, 2, 1 }; const path = [_]Edge{ .{ .a = 0, .b = 1 }, @@ -2154,8 +2154,8 @@ test "anchoring everything makes a reindex a no-op" { const n = 10; const slot = slotSpacingFor(n); var out1: [n]dvui.Point = undefined; - var seeds: [n]?dvui.Point = .{null} ** n; - var deg: [n]u32 = .{0} ** n; + var seeds: [n]?dvui.Point = @splat(null); + var deg: [n]u32 = @splat(0); var edges: [6]Edge = undefined; for (0..6) |i| { edges[i] = .{ .a = i, .b = i + 1 }; @@ -2166,7 +2166,7 @@ test "anchoring everything makes a reindex a no-op" { var seeds2: [n]?dvui.Point = undefined; for (0..n) |i| seeds2[i] = out1[i]; - const all_anchored: [n]bool = .{true} ** n; + const all_anchored: [n]bool = @splat(true); var out2: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds2, °, .{ .anchored = &all_anchored, .prior_slot = slot }, &out2); @@ -2190,7 +2190,7 @@ test "a new link moves its endpoints and leaves the rest of the vault alone" { .{ .a = 5, .b = 6 }, .{ .a = 6, .b = 7 }, }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out1: [n]dvui.Point = undefined; try targets(testing.allocator, n, &before, &seeds, °, .{}, &out1); const gap_before = dist(out1[3], out1[4]); @@ -2200,7 +2200,7 @@ test "a new link moves its endpoints and leaves the rest of the vault alone" { const after = before ++ [_]Edge{.{ .a = 3, .b = 4 }}; var deg2: [n]u32 = .{ 1, 2, 2, 2, 2, 2, 2, 1 }; // Only the two endpoints of the new link have a changed neighbour set. - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[3] = false; anchored[4] = false; var out2: [n]dvui.Point = undefined; @@ -2234,14 +2234,14 @@ test "restoring a node's pre-change cell honours it exactly" { .{ .a = 5, .b = 6 }, .{ .a = 6, .b = 7 }, }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var start: [n]dvui.Point = undefined; try targets(testing.allocator, n, &plain, &seeds, °, .{}, &start); // Link 3—4: only those two are mobile. const linked = plain ++ [_]Edge{.{ .a = 3, .b = 4 }}; var deg_linked: [n]u32 = .{ 1, 2, 2, 2, 2, 2, 2, 1 }; - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[3] = false; anchored[4] = false; var seeds_linked: [n]?dvui.Point = undefined; @@ -2255,7 +2255,7 @@ test "restoring a node's pre-change cell honours it exactly" { for (0..n) |i| seeds_back[i] = mid[i]; seeds_back[3] = start[3]; seeds_back[4] = start[4]; - var all_anchored: [n]bool = .{true} ** n; + var all_anchored: [n]bool = @splat(true); var back: [n]dvui.Point = undefined; try targets(testing.allocator, n, &plain, &seeds_back, °, .{ .anchored = &all_anchored, .prior_slot = slot }, &back); @@ -2278,14 +2278,14 @@ test "a node that loses its only link stays put instead of being flung out" { .{ .a = 2, .b = 3 }, .{ .a = 3, .b = 4 }, }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out1: [n]dvui.Point = undefined; try targets(testing.allocator, n, &chain, &seeds, °, .{}, &out1); // Drop 4's only link, leaving it isolated. const cut = chain[0..3]; var deg2: [n]u32 = .{ 1, 2, 2, 1, 0 }; - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[3] = false; anchored[4] = false; var seeds2: [n]?dvui.Point = undefined; @@ -2309,7 +2309,7 @@ test "an anchored node yields its cell to nobody" { .{ .a = 0, .b = 2 }, .{ .a = 0, .b = 3 }, }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out1: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{}, &out1); @@ -2317,7 +2317,7 @@ test "an anchored node yields its cell to nobody" { var seeds2: [n]?dvui.Point = undefined; for (0..n) |i| seeds2[i] = out1[i]; seeds2[0] = out1[1]; - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[0] = false; var out2: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds2, °, .{ .anchored = &anchored, .prior_slot = slot }, &out2); @@ -2344,12 +2344,12 @@ test "a vault of mostly-unlinked notes packs densely" { // near the lattice minimum instead. const n = 33; const slot = slotSpacingFor(n); - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); deg[0] = 1; deg[1] = 2; deg[2] = 1; const edges = [_]Edge{ .{ .a = 0, .b = 1 }, .{ .a = 1, .b = 2 } }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{}, &out); @@ -2365,9 +2365,9 @@ test "packing follows the panel's proportions" { // A disc fits a wide short panel badly: the fit is height-limited and most of the width goes to // margin. Packing to the panel's shape spends that width on zoom instead. const n = 40; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var round: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &seeds, °, .{}, &round); @@ -2392,9 +2392,9 @@ test "a reshape repacks a cloud that is already laid out" { // themselves to their old seed here, which both froze them and tripped `any_fixed` in // `packComponents` — so `aspect` was thrown away and a resize reshaped nothing. const n = 40; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; - var no_seeds: [n]?dvui.Point = .{null} ** n; + var no_seeds: [n]?dvui.Point = @splat(null); var round: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &no_seeds, °, .{}, &round); @@ -2402,7 +2402,7 @@ test "a reshape repacks a cloud that is already laid out" { // Now reshape *that* arrangement, exactly as `rebuildIfNeeded` does on a bucket change. var seeds: [n]?dvui.Point = undefined; for (round, 0..) |p, i| seeds[i] = p; - const anchored: [n]bool = .{false} ** n; + const anchored: [n]bool = @splat(false); var wide: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &seeds, °, .{ .anchored = &anchored, @@ -2419,9 +2419,9 @@ test "the whole range a panel can ask for produces distinct shapes" { // number and gave a byte-identical layout — so dragging the panel reshaped nothing at all, and // the shaping looked broken when it was only saturated. const n = 40; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); const ratios = [_]f32{ 1.0, 2.0, 3.0, 4.0 }; var spans: [ratios.len]f32 = undefined; @@ -2440,11 +2440,11 @@ test "a cluster keeps its own shape through a reshape" { // line with its nodes sitting on top of their own connecting edges. Proportions belong to where // islands are *placed*, never to the coordinates inside one. const n = 24; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); // A triangle, and 21 loose notes for the packer to spread around it. const edges = [_]Edge{ .{ .a = 0, .b = 1 }, .{ .a = 1, .b = 2 }, .{ .a = 2, .b = 0 } }; for (0..3) |i| deg[i] = 2; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var square: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{ .aspect = 1 }, &square); @@ -2452,7 +2452,7 @@ test "a cluster keeps its own shape through a reshape" { // Reshape hard, the way dragging a bottom panel wide does. var carried: [n]?dvui.Point = undefined; for (square, 0..) |q, i| carried[i] = q; - const anchored: [n]bool = .{false} ** n; + const anchored: [n]bool = @splat(false); var wide: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &carried, °, .{ .anchored = &anchored, @@ -2488,7 +2488,7 @@ test "one dominant cluster does not pin the cloud's shape" { // own, an area-preserving stretch only widened the island ring by √a, so a 3.5:1 panel gave a // ~1.9:1 cloud and pulling the panel wider did almost nothing visible. const n = 90; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var el: [44]Edge = undefined; // Half the vault in one cluster, half loose — the loose ones are what carry the shape. for (1..45) |i| { @@ -2497,7 +2497,7 @@ test "one dominant cluster does not pin the cloud's shape" { deg[parent] += 1; deg[i] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var prev: f32 = 0; for ([_]f32{ 1.0, 2.0, 3.5, 5.0, 8.0 }) |asp| { @@ -2517,18 +2517,18 @@ test "an incremental rebuild still holds link-less notes still" { // The flip side of the reshape fix: when the caller *is* anchoring, a note with no links has // nothing to solve for it and must not be carried off by the packer. const n = 12; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); deg[0] = 1; deg[1] = 1; const edges = [_]Edge{.{ .a = 0, .b = 1 }}; - var no_seeds: [n]?dvui.Point = .{null} ** n; + var no_seeds: [n]?dvui.Point = @splat(null); var base: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &no_seeds, °, .{}, &base); var seeds: [n]?dvui.Point = undefined; for (base, 0..) |p, i| seeds[i] = p; // Everything anchored except one loose note, which carries a seed but no say-so of its own. - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[n - 1] = false; var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{ .anchored = &anchored }, &out); @@ -2542,16 +2542,16 @@ test "a settle reshape parks islands into new proportions without reshaping clus // a fresh ellipse for the new aspect. Clusters stay rigid (triangle side lengths hold); // loners carry the wide/tall outline. const n = 24; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); const edges = [_]Edge{ .{ .a = 0, .b = 1 }, .{ .a = 1, .b = 2 }, .{ .a = 2, .b = 0 } }; for (0..3) |i| deg[i] = 2; - var no_seeds: [n]?dvui.Point = .{null} ** n; + var no_seeds: [n]?dvui.Point = @splat(null); var square: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &no_seeds, °, .{ .aspect = 1 }, &square); var seeds: [n]?dvui.Point = undefined; for (0..n) |i| seeds[i] = square[i]; - const free: [n]bool = .{false} ** n; + const free: [n]bool = @splat(false); var wide: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{ .anchored = &free, @@ -2589,15 +2589,15 @@ test "a settle reshape into the same aspect is idempotent" { // Two packs at the same aspect with the same seeds must agree. Otherwise a settle that // fires twice (or a chattering end-of-drag) hands the ease two homes to thrash between. const n = 20; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; - var no_seeds: [n]?dvui.Point = .{null} ** n; + var no_seeds: [n]?dvui.Point = @splat(null); var base: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &no_seeds, °, .{ .aspect = 1.5 }, &base); var seeds: [n]?dvui.Point = undefined; for (0..n) |i| seeds[i] = base[i]; - const free: [n]bool = .{false} ** n; + const free: [n]bool = @splat(false); var a: [n]dvui.Point = undefined; var b: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &seeds, °, .{ @@ -2624,20 +2624,20 @@ test "a single connected component still takes the pane aspect on reshape" { // to the pane and re-relaxes springs. Without that, a fully-linked vault could never become // wide or tall — only zoom with the camera. const n = 12; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: [n - 1]Edge = undefined; for (0..n - 1) |i| { edges[i] = .{ .a = i, .b = i + 1 }; deg[i] += 1; deg[i + 1] += 1; } - var no_seeds: [n]?dvui.Point = .{null} ** n; + var no_seeds: [n]?dvui.Point = @splat(null); var base: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &no_seeds, °, .{ .aspect = 1 }, &base); var seeds: [n]?dvui.Point = undefined; for (0..n) |i| seeds[i] = base[i]; - const free: [n]bool = .{false} ** n; + const free: [n]bool = @splat(false); var wide: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{ .anchored = &free, @@ -2681,13 +2681,13 @@ test "same-folder notes huddle closer than cross-folder peers" { // Three notes in `proj/` and three in `other/`, no wikilinks. Folder kinship alone should // pull each cohort together — without it they scatter like any other loners. const n = 6; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; const paths = [_][]const u8{ "proj/a.md", "proj/b.md", "proj/c.md", "other/x.md", "other/y.md", "other/z.md", }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &seeds, °, .{ .paths = &paths }, &out); @@ -2720,10 +2720,10 @@ test "a linked pair sits tighter than neighbouring loners" { // spacing of unlinked ones. Same packing slot for everyone used to put both at one lattice // step, which is why clusters never looked tighter than the loners around them. const n = 18; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); const edges = [_]Edge{ .{ .a = 0, .b = 1 }, .{ .a = 1, .b = 2 }, .{ .a = 2, .b = 0 } }; for (0..3) |i| deg[i] = 2; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{}, &out); @@ -2742,7 +2742,7 @@ test "a linked pair sits tighter than neighbouring loners" { test "a cluster sits nearer the middle than the loose notes do" { // Clusters in, singles out — the reading the user gets from the shape of the board. const n = 24; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); for (0..6) |i| deg[i] = 2; const edges = [_]Edge{ .{ .a = 0, .b = 1 }, @@ -2752,7 +2752,7 @@ test "a cluster sits nearer the middle than the loose notes do" { .{ .a = 4, .b = 5 }, .{ .a = 5, .b = 0 }, }; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, &edges, &seeds, °, .{}, &out); @@ -2769,9 +2769,9 @@ test "a newly linked pair is parked near itself, not out past the vault" { // board — so two notes finding each other threw them both to the rim. const n = 20; const slot = slotSpacingFor(n); - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var no_edges: [0]Edge = .{}; - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out1: [n]dvui.Point = undefined; try targets(testing.allocator, n, &no_edges, &seeds, °, .{}, &out1); @@ -2780,10 +2780,10 @@ test "a newly linked pair is parked near itself, not out past the vault" { // Link 4—5, anchor everyone else. const linked = [_]Edge{.{ .a = 4, .b = 5 }}; - var deg2: [n]u32 = .{0} ** n; + var deg2: [n]u32 = @splat(0); deg2[4] = 1; deg2[5] = 1; - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[4] = false; anchored[5] = false; var seeds2: [n]?dvui.Point = undefined; @@ -2809,7 +2809,7 @@ test "a triangle inside a cluster does not snap into a straight line" { // makes them contend for cells at snap time. Displacing every contender the same fixed // direction is what lined them up. See `findFreeCell`. const n = 12; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: std.ArrayList(Edge) = .empty; defer edges.deinit(testing.allocator); try edges.appendSlice(testing.allocator, &.{ @@ -2826,7 +2826,7 @@ test "a triangle inside a cluster does not snap into a straight line" { deg[e.b] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(testing.allocator, n, edges.items, &seeds, °, .{ .aspect = 2 }, &out); @@ -2893,7 +2893,7 @@ test "a group's links stay near the tightest the lattice allows" { // A chain of triangles: nothing forces a long link, so nothing should be long. { - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: std.ArrayList(Edge) = .empty; defer edges.deinit(gpa); var k: usize = 0; @@ -2907,7 +2907,7 @@ test "a group's links stay near the tightest the lattice allows" { deg[e.a] += 1; deg[e.b] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(gpa, n, edges.items, &seeds, °, .{ .aspect = 1.6 }, &out); @@ -2928,7 +2928,7 @@ test "a group's links stay near the tightest the lattice allows" { // that is geometry rather than slack — so this only guards against the mean drifting well // past what a disc of that many cells measures (~1.7 cells). { - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: std.ArrayList(Edge) = .empty; defer edges.deinit(gpa); for (1..24) |k| try edges.append(gpa, .{ .a = 0, .b = k }); @@ -2937,7 +2937,7 @@ test "a group's links stay near the tightest the lattice allows" { deg[e.a] += 1; deg[e.b] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var out: [n]dvui.Point = undefined; try targets(gpa, n, edges.items, &seeds, °, .{ .aspect = 1.6 }, &out); @@ -2962,7 +2962,7 @@ test "a reshape leaves the vault on the lattice" { // that was stretched. const gpa = testing.allocator; const n = 30; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: std.ArrayList(Edge) = .empty; defer edges.deinit(gpa); for ([_]usize{ 0, 5, 10 }) |b| { @@ -2980,13 +2980,13 @@ test "a reshape leaves the vault on the lattice" { deg[e.b] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var cur: [n]dvui.Point = undefined; try targets(gpa, n, edges.items, &seeds, °, .{ .aspect = 3.0 }, &cur); const snap = snapSpacingFor(n); var carried: [n]?dvui.Point = undefined; - const free: [n]bool = .{false} ** n; + const free: [n]bool = @splat(false); // Drag the pane from wide through square to tall, carrying each result into the next the way // the panel does. for ([_]f32{ 1.6, 1.0, 0.6 }) |a| { @@ -3024,7 +3024,7 @@ test "files added to a hub one at a time do not end up behind each other" { // them, and those are both shorter and clear. const gpa = testing.allocator; const n = 24; - var deg: [n]u32 = .{0} ** n; + var deg: [n]u32 = @splat(0); var edges: std.ArrayList(Edge) = .empty; defer edges.deinit(gpa); try edges.append(gpa, .{ .a = 20, .b = 21 }); @@ -3032,7 +3032,7 @@ test "files added to a hub one at a time do not end up behind each other" { deg[e.a] += 1; deg[e.b] += 1; } - var seeds: [n]?dvui.Point = .{null} ** n; + var seeds: [n]?dvui.Point = @splat(null); var cur: [n]dvui.Point = undefined; try targets(gpa, n, edges.items, &seeds, °, .{ .aspect = 2.2 }, &cur); @@ -3044,7 +3044,7 @@ test "files added to a hub one at a time do not end up behind each other" { // The anchoring `graph.zig` hands over: the two endpoints of the new link, plus the // immediate neighbours of both. - var anchored: [n]bool = .{true} ** n; + var anchored: [n]bool = @splat(true); anchored[0] = false; anchored[k] = false; for (edges.items) |e| { diff --git a/src/ui/radix.zig b/src/ui/radix.zig index c11ff67..47b1df3 100644 --- a/src/ui/radix.zig +++ b/src/ui/radix.zig @@ -47,7 +47,7 @@ pub fn sortByKey( var dst = scratch[0..items.len]; var shift: u6 = 0; while (true) { - var counts = [_]u32{0} ** 256; + var counts = @as([256]u32, @splat(0)); for (src) |it| counts[@as(u8, @truncate(keyOf(it) >> shift))] += 1; // Every element in one bucket means this digit orders nothing, and moving them all would be diff --git a/src/ui/shape_metrics.zig b/src/ui/shape_metrics.zig index 57b95eb..f9ab5fa 100644 --- a/src/ui/shape_metrics.zig +++ b/src/ui/shape_metrics.zig @@ -60,10 +60,10 @@ pub const Kind = enum { }; pub const CommHist = struct { - counts: [std.meta.fields(Kind).len]u32 = .{0} ** std.meta.fields(Kind).len, + counts: [std.meta.fieldNames(Kind).len]u32 = @splat(0), fn add(self: *CommHist, k: Kind) void { - self.counts[@intFromEnum(k)] += 1; + self.counts[@backingInt(k)] += 1; } pub fn total(self: CommHist) u32 { @@ -84,7 +84,7 @@ pub const CommHist = struct { n += 1; } first = false; - const k: Kind = @enumFromInt(i); + const k: Kind = @fromBackingInt(@intCast(i)); const w = std.fmt.bufPrint(buf[n..], "{d}{c}", .{ c, k.letter() }) catch break; n += w.len; } @@ -133,7 +133,7 @@ pub fn printHeader() void { "ovlp", "penet", "leaf", "hwy", "d-p50", "d-p99", "graph", "communities", }, ); - std.debug.print("{s}\n", .{"-" ** 148}); + std.debug.print("{s}\n", .{&@as([148]u8, @splat('-'))}); } pub fn printRow(label: []const u8, r: Report) void { @@ -444,7 +444,7 @@ fn radial(gpa: std.mem.Allocator, r: *Report, pos: []const Vec2, ext: f64) !void cy /= nf; const rings = 8; - var hist: [rings]usize = .{0} ** rings; + var hist: [rings]usize = @splat(0); const radii = try gpa.alloc(f32, pos.len); defer gpa.free(radii); diff --git a/src/ui/vault_synth.zig b/src/ui/vault_synth.zig index 04fdce2..623e219 100644 --- a/src/ui/vault_synth.zig +++ b/src/ui/vault_synth.zig @@ -1649,10 +1649,10 @@ test "synthContentGraph produces a well-formed document graph" { try testing.expect(g.items.len > 1); try testing.expectEqual(content_graph.ItemKind.root, g.items[0].kind); - var counts = [_]usize{0} ** 9; // indexed by @intFromEnum(ItemKind) - for (g.items) |it| counts[@intFromEnum(it.kind)] += 1; - try testing.expect(counts[@intFromEnum(content_graph.ItemKind.heading)] > 0); - try testing.expect(counts[@intFromEnum(content_graph.ItemKind.paragraph)] > 0); + var counts = @as([9]usize, @splat(0)); // indexed by @intFromEnum(ItemKind) + for (g.items) |it| counts[@backingInt(it.kind)] += 1; + try testing.expect(counts[@backingInt(content_graph.ItemKind.heading)] > 0); + try testing.expect(counts[@backingInt(content_graph.ItemKind.paragraph)] > 0); // Only .outline edges in this pass. for (g.edges) |e| try testing.expect(e.kind == .outline);