an experimental irc client
at 811894e376b4de7f6c75fa08b7afd0d6315e8d1d 129 lines 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 me, 70 msg, 71 query, 72 @"next-channel", 73 @"prev-channel", 74 quit, 75 who, 76 names, 77 part, 78 close, 79 redraw, 80 version, 81 lua_function: i32, 82 83 pub var user_commands: std.StringHashMap(i32) = undefined; 84 85 /// only contains void commands 86 const map = std.StaticStringMap(Command).initComptime(.{ 87 .{ "quote", .quote }, 88 .{ "join", .join }, 89 .{ "me", .me }, 90 .{ "msg", .msg }, 91 .{ "query", .query }, 92 .{ "next-channel", .@"next-channel" }, 93 .{ "prev-channel", .@"prev-channel" }, 94 .{ "quit", .quit }, 95 .{ "who", .who }, 96 .{ "names", .names }, 97 .{ "part", .part }, 98 .{ "close", .close }, 99 .{ "redraw", .redraw }, 100 .{ "version", .version }, 101 }); 102 103 pub fn fromString(str: []const u8) ?Command { 104 return map.get(str); 105 } 106 107 /// if we should append a space when completing 108 pub fn appendSpace(self: Command) bool { 109 return switch (self) { 110 .quote, 111 .join, 112 .me, 113 .msg, 114 .part, 115 .close, 116 => true, 117 else => false, 118 }; 119 } 120}; 121 122/// An event our write thread will handle 123pub const WriteEvent = union(enum) { 124 write: struct { 125 client: *irc.Client, 126 msg: []const u8, 127 }, 128 join, 129};