╭ changed ───╮ │src/main.zig│ ╰────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │114 .is_terminal = true, │ │115 .data = .{ │ │116 // the files root; local routes carry no identity │ │117 - .current_page = .{ .repo_files = .{} }, │ │117 + .current_page = .{ .repo_files = .{ .name = .{} } },│ │118 .is_local = true, │ │119 }, │ │120 }; │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/main_wasm.zig│ ╰─────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │69 const should_push = if (last_pushed_page_maybe) |lp| !lp.eql(current_page) else true;│ │70 if (should_push) { │ │71 last_pushed_page_maybe = current_page; │ │72 - const url = try current_page.urlAlloc(&page_arena); │ │72 + const url = try current_page.toUrl(&page_arena); │ │73 _replaceState(url.ptr, @intCast(url.len)); │ │74 } │ │75 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │129 if (root_ptr.getFocus().grandchild_id) |gid| { │ │130 // follow a cross-page link │ │131 if (ui.crossPageLink(root_ptr.getFocus(), gid, session.data)) |route| {│ │132 - const url = try route.urlAlloc(&page_arena); │ │132 + const url = try route.toUrl(&page_arena); │ │133 _navigate(url.ptr, @intCast(url.len)); │ │134 return; │ │135 } │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │143 const root_ptr = if (root) |*root_value| root_value else return error.NotStarted;│ │144 // follow a cross-page link │ │145 if (ui.crossPageLink(root_ptr.getFocus(), focus_id, session.data)) |route| { │ │146 - const url = try route.urlAlloc(&page_arena); │ │146 + const url = try route.toUrl(&page_arena); │ │147 _navigate(url.ptr, @intCast(url.len)); │ │148 return; │ │149 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/test/ui.zig│ ╰───────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │57 │ │58 // the route layer holds the value already url-encoded ("feature%2Ffoo"). │ │59 const route = RP.repoCommitsRoute("alice/ziglings", .branch, "feature%2Ffoo", 0).?; │ │60 - const url = try route.urlAlloc(&arena); │ │60 + const url = try route.toUrl(&arena); │ │61 try std.testing.expectEqualStrings("/repo/alice/ziglings/commits/branch:feature%2Ffoo", url);│ │62 │ │63 // parsing it back yields the same route, and the ref splits out intact. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │64 const parsed = RP.fromUrl(url); │ │65 try std.testing.expect(parsed != null); │ │66 - const ref = RP.repoCommitsRef(parsed.?.repo_commits.slice()); │ │67 - try std.testing.expectEqual(RP.RefOrOid.branch, ref.ref_or_oid.?); │ │68 - try std.testing.expectEqualStrings("feature%2Ffoo", ref.value); │ │66 + const parsed_route = parsed.?.repo_commits; │ │67 + try std.testing.expectEqual(RP.RefOrOid.branch, parsed_route.ref_or_oid.?); │ │68 + try std.testing.expectEqualStrings("feature%2Ffoo", parsed_route.value.slice());│ │69 } │ │70 │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │76 user_repos: struct { name: Array(evt.User.name_max_len), start: usize = 0 },│ │77 user_settings: Array(evt.User.name_max_len), │ │78 user_auth: Array(evt.User.name_max_len), │ │79 - repo_files: Array(repo_route_max_len), │ │80 - repo_commits: Array(repo_route_max_len), │ │79 + repo_files: RepoFilesRoute, │ │80 + repo_commits: RepoCommitsRoute, │ │81 repo_refs: struct { │ │82 name: Array(repo_route_max_len), │ │83 kind: RefKind = .branch, │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │188 // pair means the default branch's files root. a local session's routes │ │189 // elide the identity: "" at the bare root, else starting at the tail's "/". │ │190 pub const repo_route_max_len = 1024; │ │191 + pub const repo_identity_max_len = evt.User.name_max_len + 1 + evt.Repo.name_max_len;│ │192 │ │193 // true when a repo route's stored string elides its identity (local mode). │ │194 // unambiguous because a full string always starts with its owner segment. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │202 // caps a url-encoded ref name in a route (a longer name doesn't route). │ │203 pub const ref_route_max_len = 512; │ │204 │ │204 - // the parts of a `.repo_files` route. all slices point into the route's │ │205 - // stored string. ref_kind is null (and ref_value/dir empty) for the bare│ │206 - // default-branch root; dir is "" at a ref's root. │ │207 - pub const RepoFiles = struct { │ │205 + // the identity stored by every repo route. Local routes elide it. │ │206 + pub const RepoIdentity = struct { │ │207 identity: []const u8, // "owner/name" │ │208 owner: []const u8, │ │209 name: []const u8, │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │211 - start: usize, // the content window's first line, 0 = the first window│ │212 - ref_kind: ?RefOrOid, │ │213 - ref_value: []const u8, │ │214 - dir: []const u8, │ │210 │ │216 - // parse a `.repo_files` route's stored string. a malformed tail reads│ │217 - // as the bare default-branch root. │ │218 - pub fn parse(s: []const u8) ?RepoFiles { │ │219 - var result: RepoFiles = .{ │ │211 + pub fn parse(s: []const u8) ?RepoIdentity { │ │212 + var result: RepoIdentity = .{ │ │213 .identity = "", │ │214 .owner = "", │ │215 .name = "", │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯