╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Refs.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
290 .arrow_left => try self.switchColumn(root_focus, left_col), 291 .arrow_right => try self.switchColumn(root_focus, right_col), 292 else => {}, 293 } 294 } 295 296 // the active column's row count, used as a clamp-to-end delta for home/end. 297 fn columnRowCount(self: *View) isize { 298 const col = self.activeColumn() orelse return 0; 299 return @intCast(col.children.count()); 300 } 301 302 fn activeScroll(self: *View) ?*wgt.Scroll(ui.Widget) { 303 const id = self.box.getFocus().child_id orelse return null; 304 const index = self.box.children.getIndex(id) orelse return null; 305 return columnScroll(&self.box.children.values()[index].widget.box); 306 } 307 308 fn activeColumn(self: *View) ?*wgt.Box(ui.Widget) { 309 return &(self.activeScroll() orelse return null).child.box; 310 } 311 312 fn switchColumn(self: *View, root_focus: *Focus, target: usize) !void { 313 if (target >= self.box.children.count()) return; 314 const cur_col = self.activeColumn() orelse return; 315 const target_scroll = columnScroll(&self.box.children.values()[target].widget.box); 316 const target_col = &target_scroll.child.box; 317 // an empty column has nothing to select; ignore. 318 if (target_col.children.count() == 0) return; 319 // keep the same row offset, clamped to the target column's last row. 320 const cur_id = cur_col.getFocus().child_id orelse return; 321 const cur = cur_col.children.getIndex(cur_id) orelse return; 322 const last = target_col.children.count() - 1; 323 const next = @min(cur, last); 324 root_focus.setFocus(target_col.children.keys()[next]); 325 if (target_col.children.values()[next].rect) |rect| target_scroll.scrollToRect(rect); 326 } 327 328 pub fn clearGrid(self: *View) void { 329 self.box.clearGrid(); 330 } 331 332 pub fn getGrid(self: View) ?Grid { 333 return self.box.getGrid(); 334 } 335 336 pub fn getFocus(self: *View) *Focus { 337 return self.box.getFocus(); 338 } 339 340 pub fn atTop(self: *View) bool { 341 const col = self.activeColumn() orelse return false; 342 const cur_id = col.getFocus().child_id orelse return false; 343 return col.children.getIndex(cur_id) == 0; 344 } 345 }; 346 347 // the "a:" link to `kind`'s column windowed from ref `name` (raw; "" = the 348 // first window) within `identity` ("owner/name"). the other column resets to 349 // its first window. 350 fn windowLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, kind: ui.RoutablePage.RefKind, name: []const u8) ![]const u8 { 351 const encoded = try ui.urlEncodeRef(page_arena.allocator(), name); 352 const route = ui.RoutablePage.repoRefsRoute(identity, kind, encoded) orelse return error.RouteTooLong; 353 const url = try route.toUrl(page_arena); 354 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); 355 } 356 357 // the "a:" link to the files tab at ref `name` (a branch or tag) within 358 // `identity` ("owner/name"), at its root directory. the name is percent-encoded 359 // since it can contain a '/'. 360 fn refLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, kind: ui.RoutablePage.RefKind, name: []const u8) ![]const u8 { 361 const aa = page_arena.allocator(); 362 const ref_or_oid: ui.RoutablePage.RefOrOid = switch (kind) { 363 .branch => .branch, 364 .tag => .tag, 365 }; 366 const value = try ui.urlEncodeRef(aa, name); 367 const route = ui.RoutablePage.repoFilesRoute(identity, ref_or_oid, value, "", 0) orelse return error.RouteTooLong; 368 const url = try route.toUrl(page_arena); 369 return std.fmt.allocPrint(aa, "a:{s}", .{url}); 370 } 371