an experimental irc client

app: draw client list

+54 -2
+34 -2
src/app.zig
··· 85 85 86 86 lhs: vxfw.SplitView, 87 87 rhs: vxfw.SplitView, 88 + buffer_list: vxfw.ListView, 88 89 89 90 /// initialize vaxis, lua state 90 91 pub fn init(self: *App, gpa: std.mem.Allocator) !void { ··· 101 102 .write_thread = undefined, 102 103 .lhs = .{ 103 104 .width = self.state.buffers.width, 104 - .lhs = self.bufferWidget(), 105 + .lhs = self.buffer_list.widget(), 105 106 .rhs = self.rhs.widget(), 106 107 }, 107 108 .rhs = .{ ··· 115 116 .deinited = false, 116 117 .completer = null, 117 118 .should_quit = false, 119 + .buffer_list = .{ 120 + .children = .{ 121 + .builder = .{ 122 + .userdata = self, 123 + .buildFn = App.bufferBuilderFn, 124 + }, 125 + }, 126 + .draw_cursor = false, 127 + }, 118 128 }; 119 129 120 130 self.lua = try Lua.init(&self.alloc); ··· 259 269 }; 260 270 } 261 271 272 + fn bufferBuilderFn(ptr: *const anyopaque, idx: usize, cursor: usize) ?vxfw.Widget { 273 + const self: *const App = @ptrCast(@alignCast(ptr)); 274 + var i: usize = 0; 275 + for (self.clients.items) |client| { 276 + if (i == idx and i == cursor) { 277 + return .{ 278 + .userdata = client, 279 + .drawFn = irc.Client.typeErasedNameSelectedDrawFn, 280 + }; 281 + } 282 + if (i == idx) { 283 + return .{ 284 + .userdata = client, 285 + .drawFn = irc.Client.typeErasedNameDrawFn, 286 + }; 287 + } 288 + i += 1; 289 + } 290 + return null; 291 + } 292 + 262 293 fn typeErasedBufferDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 263 - _ = ptr; 294 + const self: *App = @ptrCast(@alignCast(ptr)); 295 + _ = self; 264 296 const text: vxfw.Text = .{ .text = "buffers" }; 265 297 return text.draw(ctx); 266 298 }
+20
src/irc.zig
··· 8 8 9 9 const testing = std.testing; 10 10 const mem = std.mem; 11 + const vxfw = vaxis.vxfw; 11 12 12 13 const Allocator = std.mem.Allocator; 13 14 const Base64Encoder = std.base64.standard.Encoder; ··· 563 564 } 564 565 batches.deinit(); 565 566 self.fifo.deinit(); 567 + } 568 + 569 + pub fn typeErasedNameDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 570 + const self: *Client = @ptrCast(@alignCast(ptr)); 571 + const text: vxfw.Text = .{ 572 + .text = self.config.name orelse self.config.server, 573 + .softwrap = false, 574 + }; 575 + return text.draw(ctx); 576 + } 577 + 578 + pub fn typeErasedNameSelectedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 579 + const self: *Client = @ptrCast(@alignCast(ptr)); 580 + const text: vxfw.Text = .{ 581 + .text = self.config.name orelse self.config.server, 582 + .softwrap = false, 583 + .style = .{ .reverse = true }, 584 + }; 585 + return text.draw(ctx); 566 586 } 567 587 568 588 pub fn drainFifo(self: *Client) void {