//! Help Widget Demo - Shows keybinding help in different modes //! //! Run with: zig build help-demo const std = @import("std"); const zcatui = @import("zcatui"); const Terminal = zcatui.Terminal; const Rect = zcatui.Rect; const Buffer = zcatui.Buffer; const Style = zcatui.Style; const Color = zcatui.Color; const Block = zcatui.widgets.Block; const Borders = zcatui.widgets.Borders; const Help = zcatui.widgets.Help; const KeyBinding = zcatui.widgets.KeyBinding; const HelpMode = zcatui.widgets.HelpMode; const bindings = [_]KeyBinding{ .{ .key = "q", .description = "Quit", .group = "General" }, .{ .key = "?", .description = "Toggle help", .group = "General" }, .{ .key = "up/k", .description = "Move up", .group = "Navigation" }, .{ .key = "down/j", .description = "Move down", .group = "Navigation" }, .{ .key = "left/h", .description = "Move left", .group = "Navigation" }, .{ .key = "right/l", .description = "Move right", .group = "Navigation" }, .{ .key = "PgUp", .description = "Page up", .group = "Navigation" }, .{ .key = "PgDn", .description = "Page down", .group = "Navigation" }, .{ .key = "Home", .description = "Go to start", .group = "Navigation" }, .{ .key = "End", .description = "Go to end", .group = "Navigation" }, .{ .key = "Enter", .description = "Select item", .group = "Actions" }, .{ .key = "Space", .description = "Toggle selection", .group = "Actions" }, .{ .key = "Tab", .description = "Next panel", .group = "Actions" }, .{ .key = "Ctrl+C", .description = "Copy", .group = "Edit" }, .{ .key = "Ctrl+V", .description = "Paste", .group = "Edit" }, .{ .key = "Ctrl+Z", .description = "Undo", .group = "Edit" }, }; const modes = [_]HelpMode{ .single_line, .compact, .multi_line, .full }; const mode_names = [_][]const u8{ "Single Line", "Compact", "Multi Line", "Full" }; /// State for the demo const State = struct { current_mode: usize = 0, running: bool = true, }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); var term = try Terminal.init(allocator); defer term.deinit(); var state = State{}; while (state.running) { try term.drawWithContext(&state, render); if (try term.pollEvent(100)) |event| { switch (event) { .key => |key| { switch (key.code) { .char => |c| { if (c == 'q') state.running = false; if (c >= '1' and c <= '4') { state.current_mode = c - '1'; } }, .left => { if (state.current_mode > 0) state.current_mode -= 1; }, .right => { if (state.current_mode < modes.len - 1) state.current_mode += 1; }, .esc => state.running = false, else => {}, } }, else => {}, } } } } fn render(state: *State, area: Rect, buf: *Buffer) void { // Main border const block = Block.init() .title(" Help Widget Demo ") .setBorders(Borders.all) .borderStyle((Style{}).fg(Color.cyan)); block.render(area, buf); // Mode tabs var x: u16 = 2; for (mode_names, 0..) |name, i| { const style = if (i == state.current_mode) (Style{}).fg(Color.black).bg(Color.cyan).bold() else (Style{}).fg(Color.white); _ = buf.setString(x, 1, " ", style); _ = buf.setString(x + 1, 1, name, style); _ = buf.setString(x + 1 + @as(u16, @intCast(name.len)), 1, " ", style); x += @as(u16, @intCast(name.len)) + 3; } // Help content area const content_area = Rect.init(1, 3, area.width -| 2, area.height -| 5); const help_block = Block.init() .setBorders(Borders.all) .title(" Keybindings ") .borderStyle((Style{}).fg(Color.rgb(80, 80, 80))); help_block.render(content_area, buf); const inner = Rect.init(2, 4, area.width -| 4, area.height -| 7); // Help widget const key_style = (Style{}).fg(Color.yellow).bold(); const help = Help.init(&bindings) .setMode(modes[state.current_mode]) .setKeyStyle(key_style); help.render(inner, buf); // Footer _ = buf.setString( 2, area.height -| 1, "Press 1-4 or left/right to change mode, q to quit", (Style{}).fg(Color.rgb(100, 100, 100)), ); }