╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │127 // the url-encoded ref name `kind`'s column windows from ("" = the│ │128 // first window; the other column always shows its first window). │ │129 from: Array(ref_route_max_len) = .{}, │ │130 + // the url-encoded prefix both columns are narrowed to ("" = none)│ │131 + search: Array(search_route_max_len) = .{}, │ │132 }, │ │133 repo_issues: struct { │ │134 name: Array(repo_route_max_len), │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │611 const search = Array(search_route_max_len).from(value) orelse return null;│ │612 switch (route) { │ │613 .repo_commits => |*c| c.search = search, │ │614 + .repo_refs => |*r| r.search = search, │ │615 .repo_issues => |*i| i.search = search, │ │616 .repo_patches => |*p| p.search = search, │ │617 .repo_discussions => |*d| d.search = search, │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1052 break :blk out.written(); │ │1053 }, │ │1054 .repo_refs => |r| blk: { │ │1052 - const prefix = try repoUrlPrefix(arena, r.name.slice()); │ │1053 - break :blk if (r.from.len == 0) │ │1054 - try std.fmt.allocPrint(arena.allocator(), "{s}/refs", .{prefix}) │ │1055 - else │ │1056 - try std.fmt.allocPrint(arena.allocator(), "{s}/refs/{s}:{s}", .{ prefix, @tagName(r.kind), r.from.slice() });│ │1055 + var out: std.Io.Writer.Allocating = .init(arena.allocator()); │ │1056 + try out.writer.print("{s}/refs", .{try repoUrlPrefix(arena, r.name.slice())}); │ │1057 + if (r.from.len != 0) try out.writer.print("/{s}:{s}", .{ @tagName(r.kind), r.from.slice() }); │ │1058 + if (r.search.len != 0) try out.writer.print("/" ++ search_seg ++ "{s}", .{r.search.slice()}); │ │1059 + break :blk out.written(); │ │1060 }, │ │1061 .repo_issues => |i| blk: { │ │1062 const prefix = try repoUrlPrefix(arena, i.name.slice()); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1416 if (std.mem.eql(u8, tab, "auth")) return if (segments.next() == null) .{ .repo_auth = Array(repo_route_max_len).from(pair) orelse return null } else null;│ │1417 if (std.mem.eql(u8, tab, "refs")) { │ │1418 const word = params.scanTail(&segments) catch return null; │ │1416 - if (word != null or !params.only(&.{ .branch, .tag })) return null; │ │1417 - const ref = (params.ref() catch return null) orelse return repoRefsRoute(pair, .branch, ""); │ │1418 - const kind = std.meta.stringToEnum(RefKind, @tagName(ref.kind)) orelse return null; │ │1419 - return repoRefsRoute(pair, kind, ref.value); │ │1419 + if (word != null or !params.only(&.{ .branch, .tag, .search })) return null; │ │1420 + const ref = params.ref() catch return null; │ │1421 + const kind: RefKind = if (ref) |r| std.meta.stringToEnum(RefKind, @tagName(r.kind)) orelse return null else .branch; │ │1422 + const from = if (ref) |r| r.value else ""; │ │1423 + return withEncodedSearch(repoRefsRoute(pair, kind, from), params.values.get(.search) orelse ""); │ │1424 } │ │1425 if (std.mem.startsWith(u8, tab, issue_seg)) { │ │1426 const issue_id = tab[issue_seg.len..]; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1693 std.mem.eql(u8, a_d.base_oid.slice(), b.repo_diff.base_oid.slice()) and │ │1694 std.mem.eql(u8, a_d.patchrev_id.slice(), b.repo_diff.patchrev_id.slice()) and │ │1695 a_d.start == b.repo_diff.start and std.mem.eql(u8, a_d.path.slice(), b.repo_diff.path.slice()), │ │1692 - .repo_refs => |a_r| std.mem.eql(u8, a_r.name.slice(), b.repo_refs.name.slice()) and a_r.kind == b.repo_refs.kind and std.mem.eql(u8, a_r.from.slice(), b.repo_refs.from.slice()), │ │1696 + .repo_refs => |a_r| std.mem.eql(u8, a_r.name.slice(), b.repo_refs.name.slice()) and a_r.kind == b.repo_refs.kind and std.mem.eql(u8, a_r.from.slice(), b.repo_refs.from.slice()) and std.mem.eql(u8, a_r.search.slice(), b.repo_refs.search.slice()),│ │1697 .repo_issues => |a_i| std.mem.eql(u8, a_i.name.slice(), b.repo_issues.name.slice()) and │ │1698 std.mem.eql(u8, a_i.tag.slice(), b.repo_issues.tag.slice()) and │ │1699 std.mem.eql(u8, a_i.search.slice(), b.repo_issues.search.slice()) and │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │119 .repo_refs => |*r| r.from.slice(), │ │120 else => "", │ │121 }; │ │122 + const refs_search: []const u8 = switch (route) { │ │123 + .repo_refs => |*r| r.search.slice(), │ │124 + else => "", │ │125 + }; │ │126 // the issues tab's tag filter, the issue its window is rooted at, and the│ │127 // view it shows. │ │128 const issues_tag: []const u8 = switch (route) { │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │309 break :blk .{ │ │310 files_data, │ │311 changes_data, │ │308 - try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, refs_kind, refs_from), │ │312 + try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, refs_kind, refs_from, refs_search), │ │313 try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, issues_tag, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view), │ │314 try Patches.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, session, repo_id_maybe, repo_identity.identity, target_branch, patches_tag, patches_search, patches_selected, patches_comment, patches_comments_start, patches_theirs, patches_view),│ │315 try Discussions.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, discussions_tag, discussions_search, discussions_selected, discussions_comment, discussions_comments_start, discussions_view), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │324 break :blk .{ │ │325 try Files.emptyResult(aa, location, requested_ref_or_oid orelse .branch, requested_ref_value, files_dir), │ │326 Changes{ .commits = try Commits.emptyResult(aa, location, requested_ref_or_oid orelse .branch, requested_ref_value, commits_content, commits_base_oid) }, │ │323 - try Refs.emptyResult(arena, repo_identity.identity, refs_kind, refs_from), │ │327 + try Refs.emptyResult(arena, repo_identity.identity, refs_kind, refs_from, refs_search), │ │328 try Issues.emptyResult(aa, repo_identity.identity, issues_tag, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view), │ │329 try Patches.emptyResult(aa, repo_identity.identity, patches_tag, patches_search, patches_selected, patches_comment, patches_comments_start, patches_theirs, patches_view), │ │330 try Discussions.emptyResult(aa, repo_identity.identity, discussions_tag, discussions_search, discussions_selected, discussions_comment, discussions_comments_start, discussions_view),│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │523 if (stack.getSelected()) |selected_widget| switch (selected_widget.*) {│ │524 .repo_files => |*v| if (v.focusHeader(root_focus)) return, │ │525 .repo_commits => |*v| if (v.focusHeader(root_focus)) return, │ │526 + .repo_refs => |*v| if (v.focusHeader(root_focus)) return, │ │527 .repo_events => |*v| if (v.focusHeader(root_focus)) return, │ │528 .repo_undo => |*v| if (v.focusHeader(root_focus)) return, │ │529 else => {}, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/Repo/Refs.zig│ ╰────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │20 // first window) roots `kind`'s column; the other always shows its first window.│ │21 kind: ui.RoutablePage.RefKind, │ │22 from: []const u8, │ │23 +// the prefix both columns are narrowed to (decoded; null = no search) │ │24 +search: ?[]const u8, │ │25 branches: Column, │ │26 tags: Column, │ │27 │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯