this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 4e5a065940825f147fa5ce0df54d1ef0d50ecee7 353 lines 16 kB view raw
1const std = @import("std"); 2const fmt = std.fmt; 3const heap = std.heap; 4const mem = std.mem; 5const meta = std.meta; 6 7const vaxis = @import("vaxis"); 8 9const log = std.log.scoped(.main); 10 11const ActiveSection = enum { 12 top, 13 mid, 14 btm, 15}; 16 17pub fn main(init: std.process.Init) !void { 18 const io = init.io; 19 const alloc = init.gpa; 20 21 // Users set up below the main function 22 const users_buf = try alloc.dupe(User, users[0..]); 23 defer alloc.free(users_buf); 24 25 var buffer: [1024]u8 = undefined; 26 var tty: vaxis.Tty = try .init(io, &buffer); 27 defer tty.deinit(); 28 const tty_writer = tty.writer(); 29 var vx = try vaxis.init(io, alloc, init.environ_map, .{ 30 .kitty_keyboard_flags = .{ .report_events = true }, 31 }); 32 defer vx.deinit(alloc, tty.writer()); 33 34 var loop: vaxis.Loop(union(enum) { 35 key_press: vaxis.Key, 36 winsize: vaxis.Winsize, 37 table_upd, 38 }) = .init(io, &tty, &vx); 39 try loop.start(); 40 defer loop.stop(); 41 try vx.enterAltScreen(tty.writer()); 42 try vx.queryTerminal(tty.writer(), .fromMilliseconds(250)); 43 44 const logo = 45 \\░█░█░█▀█░█░█░▀█▀░█▀▀░░░▀█▀░█▀█░█▀▄░█░░░█▀▀░ 46 \\░▀▄▀░█▀█░▄▀▄░░█░░▀▀█░░░░█░░█▀█░█▀▄░█░░░█▀▀░ 47 \\░░▀░░▀░▀░▀░▀░▀▀▀░▀▀▀░░░░▀░░▀░▀░▀▀░░▀▀▀░▀▀▀░ 48 ; 49 const title_logo = vaxis.Cell.Segment{ 50 .text = logo, 51 .style = .{}, 52 }; 53 const title_info = vaxis.Cell.Segment{ 54 .text = "===A Demo of the the Vaxis Table Widget!===", 55 .style = .{}, 56 }; 57 const title_disclaimer = vaxis.Cell.Segment{ 58 .text = "(All data is non-sensical & LLM generated.)", 59 .style = .{}, 60 }; 61 var title_segs = [_]vaxis.Cell.Segment{ title_logo, title_info, title_disclaimer }; 62 63 var cmd_input = vaxis.widgets.TextInput.init(alloc); 64 defer cmd_input.deinit(); 65 66 // Colors 67 const active_bg: vaxis.Cell.Color = .{ .rgb = .{ 64, 128, 255 } }; 68 const selected_bg: vaxis.Cell.Color = .{ .rgb = .{ 32, 64, 255 } }; 69 const other_bg: vaxis.Cell.Color = .{ .rgb = .{ 32, 32, 48 } }; 70 71 // Table Context 72 var demo_tbl: vaxis.widgets.Table.TableContext = .{ 73 .active_bg = active_bg, 74 .active_fg = .{ .rgb = .{ 0, 0, 0 } }, 75 .row_bg_1 = .{ .rgb = .{ 8, 8, 8 } }, 76 .selected_bg = selected_bg, 77 .header_names = .{ .custom = &.{ "First", "Last", "Username", "Phone#", "Email" } }, 78 //.header_align = .left, 79 .col_indexes = .{ .by_idx = &.{ 0, 1, 2, 4, 3 } }, 80 //.col_align = .{ .by_idx = &.{ .left, .left, .center, .center, .left } }, 81 //.col_align = .{ .all = .center }, 82 //.header_borders = true, 83 //.col_borders = true, 84 //.col_width = .{ .static_all = 15 }, 85 //.col_width = .{ .dynamic_header_len = 3 }, 86 //.col_width = .{ .static_individual = &.{ 10, 20, 15, 25, 15 } }, 87 //.col_width = .dynamic_fill, 88 //.y_off = 10, 89 }; 90 defer if (demo_tbl.sel_rows) |rows| alloc.free(rows); 91 92 // TUI State 93 var active: ActiveSection = .mid; 94 var moving = false; 95 var see_content = false; 96 97 // Create an Arena Allocator for easy allocations on each Event. 98 var event_arena: heap.ArenaAllocator = .init(alloc); 99 defer event_arena.deinit(); 100 while (true) { 101 defer _ = event_arena.reset(.retain_capacity); 102 defer tty_writer.flush() catch {}; 103 const event_alloc = event_arena.allocator(); 104 const event = try loop.nextEvent(); 105 106 switch (event) { 107 .key_press => |key| keyEvt: { 108 // Close the Program 109 if (key.matches('c', .{ .ctrl = true })) { 110 break; 111 } 112 // Refresh the Screen 113 if (key.matches('l', .{ .ctrl = true })) { 114 vx.queueRefresh(); 115 break :keyEvt; 116 } 117 // Enter Moving State 118 if (key.matches('w', .{ .ctrl = true })) { 119 moving = !moving; 120 break :keyEvt; 121 } 122 // Command State 123 if (active != .btm and 124 key.matchesAny(&.{ ':', '/', 'g', 'G' }, .{})) 125 { 126 active = .btm; 127 cmd_input.clearAndFree(); 128 try cmd_input.update(.{ .key_press = key }); 129 break :keyEvt; 130 } 131 132 switch (active) { 133 .top => { 134 if (key.matchesAny(&.{ vaxis.Key.down, 'j' }, .{}) and moving) active = .mid; 135 }, 136 .mid => midEvt: { 137 if (moving) { 138 if (key.matchesAny(&.{ vaxis.Key.up, 'k' }, .{})) active = .top; 139 if (key.matchesAny(&.{ vaxis.Key.down, 'j' }, .{})) active = .btm; 140 break :midEvt; 141 } 142 // Change Row 143 if (key.matchesAny(&.{ vaxis.Key.up, 'k' }, .{})) demo_tbl.row -|= 1; 144 if (key.matchesAny(&.{ vaxis.Key.down, 'j' }, .{})) demo_tbl.row +|= 1; 145 // Change Column 146 if (key.matchesAny(&.{ vaxis.Key.left, 'h' }, .{})) demo_tbl.col -|= 1; 147 if (key.matchesAny(&.{ vaxis.Key.right, 'l' }, .{})) demo_tbl.col +|= 1; 148 // Select/Unselect Row 149 if (key.matches(vaxis.Key.space, .{})) { 150 const rows = demo_tbl.sel_rows orelse createRows: { 151 demo_tbl.sel_rows = try alloc.alloc(u16, 1); 152 break :createRows demo_tbl.sel_rows.?; 153 }; 154 var rows_list = std.ArrayList(u16).fromOwnedSlice(rows); 155 for (rows_list.items, 0..) |row, idx| { 156 if (row != demo_tbl.row) continue; 157 _ = rows_list.orderedRemove(idx); 158 break; 159 } else try rows_list.append(alloc, demo_tbl.row); 160 demo_tbl.sel_rows = try rows_list.toOwnedSlice(alloc); 161 } 162 // See Row Content 163 if (key.matches(vaxis.Key.enter, .{}) or key.matches('j', .{ .ctrl = true })) see_content = !see_content; 164 }, 165 .btm => { 166 if (key.matchesAny(&.{ vaxis.Key.up, 'k' }, .{}) and moving) active = .mid 167 // Run Command and Clear Command Bar 168 else if (key.matchExact(vaxis.Key.enter, .{}) or key.matchExact('j', .{ .ctrl = true })) { 169 const cmd = try cmd_input.toOwnedSlice(); 170 defer alloc.free(cmd); 171 if (mem.eql(u8, ":q", cmd) or 172 mem.eql(u8, ":quit", cmd) or 173 mem.eql(u8, ":exit", cmd)) return; 174 if (mem.eql(u8, "G", cmd)) { 175 demo_tbl.row = @intCast(users_buf.len - 1); 176 active = .mid; 177 } 178 if (cmd.len >= 2 and mem.eql(u8, "gg", cmd[0..2])) { 179 const goto_row = fmt.parseInt(u16, cmd[2..], 0) catch 0; 180 demo_tbl.row = goto_row; 181 active = .mid; 182 } 183 } else try cmd_input.update(.{ .key_press = key }); 184 }, 185 } 186 moving = false; 187 }, 188 .winsize => |ws| try vx.resize(alloc, tty.writer(), ws), 189 else => {}, 190 } 191 192 // Content 193 seeRow: { 194 if (!see_content) { 195 demo_tbl.active_content_fn = null; 196 demo_tbl.active_ctx = &{}; 197 break :seeRow; 198 } 199 const RowContext = struct { 200 row: []const u8, 201 bg: vaxis.Color, 202 }; 203 const row_ctx = RowContext{ 204 .row = try fmt.allocPrint(event_alloc, "Row #: {d}", .{demo_tbl.row}), 205 .bg = demo_tbl.active_bg, 206 }; 207 demo_tbl.active_ctx = &row_ctx; 208 demo_tbl.active_content_fn = struct { 209 fn see(win: *vaxis.Window, ctx_raw: *const anyopaque) !u16 { 210 const ctx: *const RowContext = @ptrCast(@alignCast(ctx_raw)); 211 win.height = 5; 212 const see_win = win.child(.{ 213 .x_off = 0, 214 .y_off = 1, 215 .width = win.width, 216 .height = 4, 217 }); 218 see_win.fill(.{ .style = .{ .bg = ctx.bg } }); 219 const content_logo = 220 \\ 221 \\░█▀▄░█▀█░█░█░░░█▀▀░█▀█░█▀█░▀█▀░█▀▀░█▀█░▀█▀ 222 \\░█▀▄░█░█░█▄█░░░█░░░█░█░█░█░░█░░█▀▀░█░█░░█░ 223 \\░▀░▀░▀▀▀░▀░▀░░░▀▀▀░▀▀▀░▀░▀░░▀░░▀▀▀░▀░▀░░▀░ 224 ; 225 const content_segs: []const vaxis.Cell.Segment = &.{ 226 .{ 227 .text = ctx.row, 228 .style = .{ .bg = ctx.bg }, 229 }, 230 .{ 231 .text = content_logo, 232 .style = .{ .bg = ctx.bg }, 233 }, 234 }; 235 _ = see_win.print(content_segs, .{}); 236 return see_win.height; 237 } 238 }.see; 239 try loop.postEvent(.table_upd); 240 } 241 242 // Sections 243 // - Window 244 const win = vx.window(); 245 win.clear(); 246 247 // - Top 248 const top_div = 6; 249 const top_bar = win.child(.{ 250 .x_off = 0, 251 .y_off = 0, 252 .width = win.width, 253 .height = win.height / top_div, 254 }); 255 for (title_segs[0..]) |*title_seg| 256 title_seg.style.bg = if (active == .top) selected_bg else other_bg; 257 top_bar.fill(.{ .style = .{ 258 .bg = if (active == .top) selected_bg else other_bg, 259 } }); 260 const logo_bar = vaxis.widgets.alignment.center( 261 top_bar, 262 44, 263 top_bar.height - (top_bar.height / 3), 264 ); 265 _ = logo_bar.print(title_segs[0..], .{ .wrap = .word }); 266 267 // - Middle 268 const middle_bar = win.child(.{ 269 .x_off = 0, 270 .y_off = win.height / top_div, 271 .width = win.width, 272 .height = win.height - (top_bar.height + 1), 273 }); 274 if (users_buf.len > 0) { 275 demo_tbl.active = active == .mid; 276 try vaxis.widgets.Table.drawTable( 277 null, 278 // event_alloc, 279 middle_bar, 280 //users_buf[0..], 281 //user_list, 282 users_buf, 283 &demo_tbl, 284 ); 285 } 286 287 // - Bottom 288 const bottom_bar = win.child(.{ 289 .x_off = 0, 290 .y_off = win.height - 1, 291 .width = win.width, 292 .height = 1, 293 }); 294 if (active == .btm) bottom_bar.fill(.{ .style = .{ .bg = active_bg } }); 295 cmd_input.draw(bottom_bar); 296 297 // Render the screen 298 try vx.render(tty_writer); 299 } 300} 301 302/// User Struct 303pub const User = struct { 304 first: []const u8, 305 last: []const u8, 306 user: []const u8, 307 email: ?[]const u8 = null, 308 phone: ?[]const u8 = null, 309}; 310 311// Users Array 312const users = [_]User{ 313 .{ .first = "Nancy", .last = "Dudley", .user = "angela73", .email = "brian47@rodriguez.biz", .phone = null }, 314 .{ .first = "Emily", .last = "Thornton", .user = "mrogers", .email = null, .phone = "(558)888-8604x094" }, 315 .{ .first = "Kyle", .last = "Huff", .user = "xsmith", .email = null, .phone = "301.127.0801x12398" }, 316 .{ .first = "Christine", .last = "Dodson", .user = "amandabradley", .email = "cheryl21@sullivan.com", .phone = null }, 317 .{ .first = "Nathaniel", .last = "Kennedy", .user = "nrobinson", .email = null, .phone = null }, 318 .{ .first = "Laura", .last = "Leon", .user = "dawnjones", .email = "fjenkins@patel.com", .phone = "1833013180" }, 319 .{ .first = "Patrick", .last = "Landry", .user = "michaelhutchinson", .email = "daniel17@medina-wallace.net", .phone = "+1-634-486-6444x964" }, 320 .{ .first = "Tammy", .last = "Hall", .user = "jamessmith", .email = null, .phone = "(926)810-3385x22059" }, 321 .{ .first = "Stephanie", .last = "Anderson", .user = "wgillespie", .email = "campbelljaime@yahoo.com", .phone = null }, 322 .{ .first = "Jennifer", .last = "Williams", .user = "shawn60", .email = null, .phone = "611-385-4771x97523" }, 323 .{ .first = "Elizabeth", .last = "Ortiz", .user = "jennifer76", .email = "johnbradley@delgado.info", .phone = null }, 324 .{ .first = "Stacy", .last = "Mays", .user = "scottgonzalez", .email = "kramermatthew@gmail.com", .phone = null }, 325 .{ .first = "Jennifer", .last = "Smith", .user = "joseph75", .email = "masseyalexander@hill-moore.net", .phone = null }, 326 .{ .first = "Gary", .last = "Hammond", .user = "brittany26", .email = null, .phone = null }, 327 .{ .first = "Lisa", .last = "Johnson", .user = "tina28", .email = null, .phone = "850-606-2978x1081" }, 328 .{ .first = "Zachary", .last = "Hopkins", .user = "vargasmichael", .email = null, .phone = null }, 329 .{ .first = "Joshua", .last = "Kidd", .user = "ghanna", .email = "jbrown@yahoo.com", .phone = null }, 330 .{ .first = "Dawn", .last = "Jones", .user = "alisonlindsey", .email = null, .phone = null }, 331 .{ .first = "Monica", .last = "Berry", .user = "barbara40", .email = "michael00@hotmail.com", .phone = "(295)346-6453x343" }, 332 .{ .first = "Shannon", .last = "Roberts", .user = "krystal37", .email = null, .phone = "980-920-9386x454" }, 333 .{ .first = "Thomas", .last = "Mitchell", .user = "williamscorey", .email = "richardduncan@roberts.com", .phone = null }, 334 .{ .first = "Nicole", .last = "Shaffer", .user = "rogerstroy", .email = null, .phone = "(570)128-5662" }, 335 .{ .first = "Edward", .last = "Bennett", .user = "andersonchristina", .email = null, .phone = null }, 336 .{ .first = "Duane", .last = "Howard", .user = "pcarpenter", .email = "griffithwayne@parker.net", .phone = null }, 337 .{ .first = "Mary", .last = "Brown", .user = "kimberlyfrost", .email = "perezsara@anderson-andrews.net", .phone = null }, 338 .{ .first = "Pamela", .last = "Sloan", .user = "kvelez", .email = "huynhlacey@moore-bell.biz", .phone = "001-359-125-1393x8716" }, 339 .{ .first = "Timothy", .last = "Charles", .user = "anthony04", .email = "morrissara@hawkins.info", .phone = "+1-619-369-9572" }, 340 .{ .first = "Sydney", .last = "Torres", .user = "scott42", .email = "asnyder@mitchell.net", .phone = null }, 341 .{ .first = "John", .last = "Jones", .user = "anthonymoore", .email = null, .phone = "701.236.0571x99622" }, 342 .{ .first = "Erik", .last = "Johnson", .user = "allisonsanders", .email = null, .phone = null }, 343 .{ .first = "Donna", .last = "Kirk", .user = "laurie81", .email = null, .phone = null }, 344 .{ .first = "Karina", .last = "White", .user = "uperez", .email = null, .phone = null }, 345 .{ .first = "Jesse", .last = "Schwartz", .user = "ryan60", .email = "latoyawilliams@gmail.com", .phone = null }, 346 .{ .first = "Cindy", .last = "Romero", .user = "christopher78", .email = "faulknerchristina@gmail.com", .phone = "780.288.2319x583" }, 347 .{ .first = "Tyler", .last = "Sanders", .user = "bennettjessica", .email = null, .phone = "1966269423" }, 348 .{ .first = "Pamela", .last = "Carter", .user = "zsnyder", .email = null, .phone = "125-062-9130x58413" }, 349}; 350 351test { 352 std.testing.refAllDecls(@This()); 353}