╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────╮ │src/ui/Repo/Diff.zig│ ╰────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │227 - while (start < text.len) { │ │231 + for (hunk.prefixes) |prefix| { │ │232 // each span keeps its trailing newline so the text box still breaks there │ │229 - const end = if (std.mem.indexOfScalarPos(u8, text, start, '\n')) |nl| nl + 1 else text.len; │ │230 - const line = text[start..end]; │ │231 - const num = std.mem.trimStart(u8, line, " "); │ │232 - const digits = std.mem.indexOfNone(u8, num, "0123456789") orelse num.len; │ │233 - const prefix: u8 = if (digits + 1 < num.len) num[digits + 1] else ' '; │ │233 + const end = if (std.mem.indexOfScalarPos(u8, hunk.text, start, '\n')) |nl| nl + 1 else hunk.text.len;│ │234 const style: wgt.Style = switch (prefix) { │ │235 '+' => .{ .fg = .{ .ansi = .green } }, │ │236 '-' => .{ .fg = .{ .ansi = .red } }, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │237 else => .{}, │ │238 }; │ │239 - try spans.append(allocator, .{ .text = line, .style = style }); │ │239 + try spans.append(allocator, .{ .text = hunk.text[start..end], .style = style });│ │240 start = end; │ │241 } │ │242 try addSpans(allocator, box, spans.items, ""); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Events.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │510 │ │511 const list = self.listBox(); │ │512 for (list.children.keys(), list.children.values()) |id, *child| switch (child.widget) { │ │513 - .text_box => |*text_box| { │ │514 - const selected = list.getFocus().child_id == id; │ │515 - text_box.options.border_style = if (selected) .single else .hidden; │ │516 - text_box.options.inverted = selected; │ │517 - }, │ │513 + .text_box => |*text_box| ui.widget.markSelected(text_box, list.getFocus().child_id == id),│ │514 else => {}, │ │515 }; │ │516 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │716 .text_box => |*text_box| text_box, │ │717 else => continue, │ │718 }; │ │723 - const selected = self.box.getFocus().child_id == id; │ │724 - tab.options.border_style = if (selected) .single else .hidden; │ │725 - tab.options.inverted = selected; │ │719 + ui.widget.markSelected(tab, self.box.getFocus().child_id == id);│ │720 } │ │721 try self.box.build(allocator, constraint, root_focus); │ │722 } │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │585 const lb = self.listBox(); │ │586 for (lb.children.keys(), lb.children.values()) |id, *child| { │ │587 switch (child.widget) { │ │588 - .text_box => |*tb| { │ │589 - const selected = lb.getFocus().child_id == id; │ │590 - tb.options.border_style = if (selected) .single else .hidden; │ │591 - tb.options.inverted = selected; │ │592 - }, │ │588 + .text_box => |*tb| ui.widget.markSelected(tb, lb.getFocus().child_id == id),│ │589 else => {}, │ │590 } │ │591 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │405 }, │ │406 else => null, │ │407 }; │ │408 - if (tb) |t| { │ │409 - t.options.border_style = if (selected_tab == id) .single else .hidden; │ │410 - t.options.inverted = selected_tab == id; │ │411 - } │ │408 + if (tb) |t| ui.widget.markSelected(t, selected_tab == id); │ │409 tabs_width += if (child.min_size) |min_size| min_size.width orelse 0 else 0;│ │410 } │ │411 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │92 const selected = self.selectedKind(); │ │93 for (self.box.children.keys(), self.box.children.values()) |id, *child| switch (child.widget) { │ │94 .text_input => child.hidden = selected == .fork, │ │95 - .text_box => |*selector| { │ │96 - const is_selected = id == self.selectors.get(selected); │ │97 - selector.options.border_style = if (is_selected) .single else .hidden; │ │98 - selector.options.inverted = is_selected; │ │99 - }, │ │95 + .text_box => |*selector| ui.widget.markSelected(selector, id == self.selectors.get(selected)),│ │96 else => {}, │ │97 }; │ │98 try self.box.build(allocator, constraint, root_focus); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/Repo/Undo.zig│ ╰────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │585 try rows.children.values()[0].widget.text_box.setContent(allocator, message); │ │586 self.shown_failure = failure; │ │587 } │ │588 - } │ │589 - for (rows.children.keys(), rows.children.values()) |id, *child| { │ │590 - const is_selected = rows.getFocus().child_id == id; │ │591 - child.widget.text_box.options.border_style = if (is_selected) .single else .hidden; │ │592 - child.widget.text_box.options.inverted = is_selected; │ │588 } │ │589 + for (rows.children.keys(), rows.children.values()) |id, *child| ui.widget.markSelected(&child.widget.text_box, rows.getFocus().child_id == id);│ │590 const both_fit = if (constraint.max_size.width) |width| width >= list_max_width + detail_min_width else true; │ │591 self.contentBox().children.values()[0].max_size = if (both_fit) .{ .width = list_max_width, .height = null } else null; │ │592 const width = if (constraint.max_size.width) |value| if (both_fit) value - list_max_width else value else detail_min_width; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/User/Header.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │219 }, │ │220 else => null, │ │221 }; │ │222 - if (tb) |t| { │ │223 - const selected = self.getFocus().child_id == id; │ │224 - t.options.border_style = if (selected) .single else .hidden; │ │225 - t.options.inverted = selected; │ │226 - } │ │222 + if (tb) |t| ui.widget.markSelected(t, self.getFocus().child_id == id); │ │223 } │ │224 var scroll_constraint = constraint; │ │225 scroll_constraint.min_size.width = constraint.max_size.width orelse constraint.min_size.width;│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/ui/widget.zig│ ╰─────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │117 pub const back_button_width = 3; │ │118 const back_button_height = 3; │ │119 const back_kind = "back"; │ │120 + │ │121 +// draw a text box as the selected one of its group: bordered and inverted, │ │122 +// while the rest stay borderless │ │123 +pub fn markSelected(text_box: *wgt.TextBox, selected: bool) void { │ │124 + text_box.options.border_style = if (selected) .single else .hidden; │ │125 + text_box.options.inverted = selected; │ │126 +} │ │127 │ │128 pub fn addBackButton(allocator: std.mem.Allocator, box: *wgt.Box(Widget), session: *ui.Session) !void {│ │129 if (!session.is_terminal) return; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯