an experimental irc client
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, .ComptimeInt => 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};