╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────────────────────────────────────────╮ │ 8 const xitui = xit.xitui; │ │ 9 const wgt = xitui.widget; │ │10 const layout = xitui.layout; │ │11 -const inp = xitui.input; │ │11 +const Key = xitui.input.Key; │ │12 const Grid = xitui.grid.Grid; │ │13 const Focus = xitui.focus.Focus; │ │14 +const inp = @import("../input.zig"); │ │15 │ │16 const SubHeader = @import("SubHeader.zig");│ │17 │ ╰───────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │518 self.detailScrollFrame().options.border_style = if (!has_content) null else if (content_focused) .double else .single;│ │519 │ │520 // same for the "next" link above the content. │ │520 - const nav = self.navBox(); │ │521 - for (nav.children.keys(), nav.children.values()) |id, *child| { │ │521 + const nav_box = self.navBox(); │ │522 + for (nav_box.children.keys(), nav_box.children.values()) |id, *child| { │ │523 switch (child.widget) { │ │523 - .text_box => |*tb| tb.options.border_style = if (nav.getFocus().child_id == id) .single else .hidden, │ │524 + .text_box => |*tb| tb.options.border_style = if (nav_box.getFocus().child_id == id) .single else .hidden, │ │525 else => {}, │ │526 } │ │527 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │565 } │ │566 │ │567 fn populateDetail(self: *View, allocator: std.mem.Allocator) !void { │ │567 - const nav = self.navBox(); │ │568 + const nav_box = self.navBox(); │ │569 const inner = self.detailInner(); │ │570 │ │570 - for (nav.children.values()) |*child| child.widget.deinit(allocator); │ │571 - nav.children.clearAndFree(allocator); │ │572 - nav.getFocus().child_id = null; │ │571 + for (nav_box.children.values()) |*child| child.widget.deinit(allocator);│ │572 + nav_box.children.clearAndFree(allocator); │ │573 + nav_box.getFocus().child_id = null; │ │574 for (inner.children.values()) |*child| child.widget.deinit(allocator); │ │575 inner.children.clearAndFree(allocator); │ │576 inner.getFocus().child_id = null; │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │581 if (!entry.is_dir) { │ │582 // the "next" window link sits above the scroll, so it stays put │ │583 // while the content scrolls. │ │583 - if (entry.has_more) try self.addNavLink(allocator, nav, "next lines →", entry, entry.window_start + file_page); │ │584 + if (entry.has_more) try self.addNavLink(allocator, nav_box, "next lines →", entry, entry.window_start + file_page);│ │585 if (entry.is_binary) { │ │586 try self.addContentBox(allocator, inner, "(binary file)"); │ │587 } else { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │591 } │ │592 } │ │593 // point each box at its first child so focus can descend into it. │ │593 - if (nav.children.count() > 0) nav.getFocus().child_id = nav.children.keys()[0]; │ │594 + if (nav_box.children.count() > 0) nav_box.getFocus().child_id = nav_box.children.keys()[0];│ │595 if (inner.children.count() > 0) inner.getFocus().child_id = inner.children.keys()[0]; │ │596 │ │597 // reset the scroll to the top for the newly-shown file: directly on the │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │618 try box.children.put(allocator, tb.getFocus().id, .{ .widget = .{ .text_box = tb }, .rect = null, .min_size = null });│ │619 } │ │620 │ │620 - pub fn input(self: *View, allocator: std.mem.Allocator, key: inp.Key, root_focus: *Focus) !void { │ │621 + pub fn input(self: *View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { │ │622 _ = allocator; │ │623 if (self.detailActive()) { │ │624 try self.detailInput(key, root_focus); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │627 } │ │628 } │ │629 │ │629 - fn listInput(self: *View, key: inp.Key, root_focus: *Focus) !void { │ │630 + fn listInput(self: *View, key: Key, root_focus: *Focus) !void { │ │631 // up/down (and the scroll wheel) move the selection; page up/down jump a │ │632 // fixed amount. right/Enter cross into the detail pane. Enter/clicks on a│ │633 // directory (or "..") row are turned into navigation by the host │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │634 // (crossPageLink) before reaching here. │ │635 + if (inp.rowDelta(key, @intCast(self.listBox().children.count()))) |delta| { │ │636 + return self.moveSelection(root_focus, delta); │ │637 + } │ │638 switch (key) { │ │639 .enter, .arrow_right => try self.focusDetail(root_focus), │ │636 - .arrow_down => try self.moveSelection(root_focus, 1), │ │637 - .arrow_up => try self.moveSelection(root_focus, -1), │ │638 - .page_down => try self.moveSelection(root_focus, 10), │ │639 - .page_up => try self.moveSelection(root_focus, -10), │ │640 - .end => try self.moveSelection(root_focus, @intCast(self.listBox().children.count())), │ │641 - .home => try self.moveSelection(root_focus, -@as(isize, @intCast(self.listBox().children.count()))),│ │642 - .mouse => |mouse| switch (mouse.action) { │ │643 - .scroll => |dir| try self.moveSelection(root_focus, if (dir == .up) -1 else 1), │ │644 - else => {}, │ │645 - }, │ │640 else => {}, │ │641 } │ │642 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │647 return self.detailInner().children.contains(g); │ │648 } │ │649 │ │656 - fn detailInput(self: *View, key: inp.Key, root_focus: *Focus) !void { │ │650 + fn detailInput(self: *View, key: Key, root_focus: *Focus) !void { │ │651 const sc = self.detailScroll(); │ │652 const on_content = self.focusOnContent(root_focus); │ │653 // the "next" link sits above the content scroll. on the link, left returns│ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │718 // focus the first (left-most) nav link; a no-op when there are none, leaving│ │719 // focus on the content. │ │720 fn focusNav(self: *View, root_focus: *Focus) void { │ │727 - const nav = self.navBox(); │ │728 - if (nav.children.count() == 0) return; │ │729 - root_focus.setFocus(nav.children.keys()[0]); │ │721 + const nav_box = self.navBox(); │ │722 + if (nav_box.children.count() == 0) return; │ │723 + root_focus.setFocus(nav_box.children.keys()[0]); │ │724 } │ │725 │ │726 fn focusContent(self: *View, root_focus: *Focus) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯