an experimental irc client
at main 3.3 kB view raw
1const std = @import("std"); 2const app = @import("app.zig"); 3const completer = @import("completer.zig"); 4const vaxis = @import("vaxis"); 5pub const irc = @import("irc.zig"); 6pub const lua = @import("lua.zig"); 7const ziglua = @import("ziglua"); 8 9pub const App = app.App; 10pub const Completer = completer.Completer; 11pub const WriteQueue = vaxis.Queue(WriteEvent, 32); 12 13pub const Bind = struct { 14 key: vaxis.Key, 15 command: Command, 16}; 17 18pub const Config = struct { 19 markread_on_focus: bool = false, 20 21 pub fn Fields() type { 22 const config_fields = std.meta.fieldNames(Config); 23 var fields: [config_fields.len]std.builtin.Type.EnumField = undefined; 24 25 for (config_fields, 0..) |f, i| { 26 fields[i] = .{ 27 .name = f, 28 .value = i, 29 }; 30 } 31 32 return @Type(.{ 33 .@"enum" = .{ 34 .decls = &.{}, 35 .tag_type = u16, 36 .fields = &fields, 37 .is_exhaustive = true, 38 }, 39 }); 40 } 41 42 pub fn fieldToLuaType(field: []const u8) ziglua.LuaType { 43 const fields = std.meta.fields(Config); 44 inline for (fields) |f| { 45 if (std.mem.eql(u8, field, f.name)) { 46 switch (@typeInfo(f.type)) { 47 .bool => return .boolean, 48 .int, .comptime_int => return .number, 49 .pointer => |ptr_info| { 50 switch (ptr_info.size) { 51 .slice => { 52 if (ptr_info.child == u8) return .string; 53 }, 54 else => {}, 55 } 56 }, 57 else => return .nil, 58 } 59 } 60 } 61 return .nil; 62 } 63}; 64 65pub const Command = union(enum) { 66 /// a raw irc command. Sent verbatim 67 quote, 68 join, 69 list, 70 me, 71 msg, 72 query, 73 @"next-channel", 74 @"prev-channel", 75 quit, 76 who, 77 names, 78 part, 79 close, 80 redraw, 81 version, 82 lua_function: i32, 83 84 pub var user_commands: std.StringHashMap(i32) = undefined; 85 86 /// only contains void commands 87 const map = std.StaticStringMap(Command).initComptime(.{ 88 .{ "quote", .quote }, 89 .{ "join", .join }, 90 .{ "list", .list }, 91 .{ "me", .me }, 92 .{ "msg", .msg }, 93 .{ "query", .query }, 94 .{ "next-channel", .@"next-channel" }, 95 .{ "prev-channel", .@"prev-channel" }, 96 .{ "quit", .quit }, 97 .{ "who", .who }, 98 .{ "names", .names }, 99 .{ "part", .part }, 100 .{ "close", .close }, 101 .{ "redraw", .redraw }, 102 .{ "version", .version }, 103 }); 104 105 pub fn fromString(str: []const u8) ?Command { 106 return map.get(str); 107 } 108 109 /// if we should append a space when completing 110 pub fn appendSpace(self: Command) bool { 111 return switch (self) { 112 .quote, 113 .join, 114 .me, 115 .msg, 116 .part, 117 .close, 118 => true, 119 else => false, 120 }; 121 } 122}; 123 124/// An event our write thread will handle 125pub const WriteEvent = union(enum) { 126 write: struct { 127 client: *irc.Client, 128 msg: []const u8, 129 }, 130 join, 131};