this repo has no description
3
fork

Configure Feed

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

irc: use custom casemap instead of zg

The zg casefolding requires allocations for data, and this bumps our ram
usage from ~7MB to ~60MB. We only need to map a subset of ascii as
lowercase, so create a custom casemap function to lowercase based on the
supported algorithms

+55 -37
-6
build.zig
··· 9 9 .optimize = optimize, 10 10 .lang = .luajit, 11 11 }); 12 - const zg_dep = b.dependency("zg", .{ 13 - .target = target, 14 - .optimize = optimize, 15 - }); 16 12 17 13 const vaxis_dep = b.dependency("vaxis", .{ 18 14 .target = target, ··· 33 29 exe.root_module.addImport("ziglua", ziglua_dep.module("ziglua")); 34 30 exe.root_module.addImport("vaxis", vaxis_dep.module("vaxis")); 35 31 exe.root_module.addImport("zeit", zeit_dep.module("zeit")); 36 - exe.root_module.addImport("Normalize", zg_dep.module("Normalize")); 37 - exe.root_module.addImport("CaseFold", zg_dep.module("CaseFold")); 38 32 39 33 b.installArtifact(exe); 40 34
-4
build.zig.zon
··· 13 13 .url = "git+https://github.com/rockorager/zeit#d5ce6b6b6336b4dc9c0d1d67339dea81fb4d2e77", 14 14 .hash = "1220242e2867feae2cc8a6a07fa65bdef586f7d9d58a6c7c432abfb53db276973f55", 15 15 }, 16 - .zg = .{ 17 - .url = "git+https://codeberg.org/dude_the_builder/zg#16735685fcc3410de361ba3411788ad1fb4fe188", 18 - .hash = "1220fe9ac5cdb41833d327a78745614e67d472469f8666567bd8cf9f5847a52b1c51", 19 - }, 20 16 }, 21 17 .paths = .{""}, 22 18 }
+12 -20
src/App.zig
··· 3 3 const zeit = @import("zeit"); 4 4 const ziglua = @import("ziglua"); 5 5 6 - const Normalize = @import("Normalize"); 7 - const CaseFold = @import("CaseFold"); 8 - 9 6 const assert = std.debug.assert; 10 7 const base64 = std.base64.standard.Encoder; 11 8 const mem = std.mem; ··· 92 89 93 90 input: vaxis.widgets.TextInput = undefined, 94 91 95 - norm_data: Normalize.NormData, 96 - fold_data: CaseFold.FoldData, 97 - 98 92 const State = struct { 99 93 mouse: ?vaxis.Mouse = null, 100 94 members: struct { ··· 125 119 /// initialize vaxis, lua state 126 120 pub fn init(alloc: std.mem.Allocator) !App { 127 121 const vx = try vaxis.init(alloc, .{}); 128 - var norm_data: Normalize.NormData = undefined; 129 - try Normalize.NormData.init(&norm_data, alloc); 130 122 var app: App = .{ 131 123 .alloc = alloc, 132 124 .clients = std.ArrayList(*Client).init(alloc), ··· 136 128 .binds = try std.ArrayList(Bind).initCapacity(alloc, 16), 137 129 .paste_buffer = std.ArrayList(u8).init(alloc), 138 130 .input = vaxis.widgets.TextInput.init(alloc, &vx.unicode), 139 - .norm_data = norm_data, 140 - .fold_data = try CaseFold.FoldData.init(alloc), 141 131 }; 142 132 143 133 try app.binds.append(.{ ··· 203 193 if (self.completer) |*completer| completer.deinit(); 204 194 self.binds.deinit(); 205 195 self.paste_buffer.deinit(); 206 - self.norm_data.deinit(); 207 - self.fold_data.deinit(); 208 196 } 209 197 210 198 /// push a write request into the queue. The request should include the trailing ··· 265 253 const home = std.posix.getenv("HOME") orelse return error.EnvironmentVariableNotFound; 266 254 var buf: [std.posix.PATH_MAX]u8 = undefined; 267 255 const path = try std.fmt.bufPrintZ(&buf, "{s}/.config/zircon/init.lua", .{home}); 268 - self.lua.loadFile(path) catch return error.LuaError; 256 + switch (ziglua.lang) { 257 + .luajit, .lua51 => self.lua.loadFile(path) catch return error.LuaError, 258 + else => self.lua.loadFile(path, .binary_text) catch return error.LuaError, 259 + } 269 260 self.lua.protectedCall(0, ziglua.mult_return, 0) catch return error.luaError; 270 261 } 271 262 ··· 1706 1697 item.style.bg = .{ .index = 8 }; 1707 1698 } 1708 1699 } 1700 + const content = iter.next() orelse continue; 1701 + if (std.mem.indexOf(u8, content, client.config.nick)) |_| { 1702 + for (self.content_segments.items) |*item| { 1703 + if (item.style.fg == .default) 1704 + item.style.fg = .{ .index = 3 }; 1705 + } 1706 + } 1709 1707 _ = try content_win.print( 1710 1708 self.content_segments.items, 1711 1709 .{ ··· 1719 1717 .width = .{ .limit = 6 }, 1720 1718 }); 1721 1719 1722 - const content = iter.next() orelse continue; 1723 - 1724 1720 if (message.time_buf) |buf| { 1725 - const fg: vaxis.Color = if (std.mem.indexOf(u8, content, client.config.nick)) |_| 1726 - .{ .index = 3 } 1727 - else 1728 - .{ .index = 8 }; 1729 1721 var time_seg = [_]vaxis.Segment{ 1730 1722 .{ 1731 1723 .text = buf, 1732 - .style = .{ .fg = fg }, 1724 + .style = .{ .fg = .{ .index = 8 } }, 1733 1725 }, 1734 1726 }; 1735 1727 _ = try gutter.print(&time_seg, .{});
+43 -7
src/irc.zig
··· 3 3 const testing = std.testing; 4 4 const tls = std.crypto.tls; 5 5 6 - const CaseFold = @import("CaseFold"); 7 - const Normalize = @import("Normalize"); 8 6 const vaxis = @import("vaxis"); 9 7 const zeit = @import("zeit"); 10 8 ··· 676 674 } 677 675 678 676 pub fn getOrCreateChannel(self: *Client, name: []const u8) !*Channel { 679 - const norm = Normalize{ .norm_data = &self.app.norm_data }; 680 - const cf = CaseFold{ .fold_data = &self.app.fold_data }; 677 + const name_lower = try self.alloc.alloc(u8, name.len); 678 + defer self.alloc.free(name_lower); 679 + try caseMap(name_lower, name, .rfc1459); 681 680 for (self.channels.items) |*channel| { 682 - if (try cf.canonCaselessMatch(self.alloc, &norm, name, channel.name)) { 683 - return channel; 684 - } 681 + const chan_lower = try self.alloc.alloc(u8, channel.name.len); 682 + defer self.alloc.free(chan_lower); 683 + try caseMap(chan_lower, channel.name, .rfc1459); 684 + if (std.mem.eql(u8, name_lower, chan_lower)) return channel; 685 685 } 686 686 const channel: Channel = .{ 687 687 .name = try self.alloc.dupe(u8, name), ··· 768 768 else => .{ .index = irc }, 769 769 }; 770 770 } 771 + 772 + const CaseMapAlgo = enum { 773 + ascii, 774 + rfc1459, 775 + rfc1459_strict, 776 + }; 777 + 778 + pub fn caseMap(out: []u8, str: []const u8, algo: CaseMapAlgo) !void { 779 + assert(out.len == str.len); 780 + switch (algo) { 781 + .ascii => { 782 + for (str, 0..) |b, i| { 783 + switch (b) { 784 + 'A'...'Z' => out[i] = b + 0x20, 785 + else => out[i] = b, 786 + } 787 + } 788 + }, 789 + .rfc1459 => { 790 + for (str, 0..) |b, i| { 791 + switch (b) { 792 + 'A'...'^' => out[i] = b + 0x20, 793 + else => out[i] = b, 794 + } 795 + } 796 + }, 797 + .rfc1459_strict => { 798 + for (str, 0..) |b, i| { 799 + switch (b) { 800 + 'A'...']' => out[i] = b + 0x20, 801 + else => out[i] = b, 802 + } 803 + } 804 + }, 805 + } 806 + }