an experimental irc client
1const std = @import("std");
2const options = @import("build_options");
3const builtin = @import("builtin");
4const comlink = @import("comlink.zig");
5const vaxis = @import("vaxis");
6const ziglua = @import("ziglua");
7
8const Lua = ziglua.Lua;
9
10const log = std.log.scoped(.main);
11
12pub const panic = vaxis.panic_handler;
13
14pub const std_options: std.Options = .{
15 .log_scope_levels = &.{
16 .{ .scope = .vaxis, .level = .warn },
17 .{ .scope = .vaxis_parser, .level = .warn },
18 },
19};
20
21pub const version = options.version;
22
23/// Called after receiving a terminating signal
24fn cleanUp(sig: c_int) callconv(.C) void {
25 if (vaxis.Tty.global_tty) |gty| {
26 const reset: []const u8 = vaxis.ctlseqs.csi_u_pop ++
27 vaxis.ctlseqs.mouse_reset ++
28 vaxis.ctlseqs.bp_reset ++
29 vaxis.ctlseqs.rmcup;
30
31 gty.anyWriter().writeAll(reset) catch {};
32
33 gty.deinit();
34 }
35 if (sig < 255 and sig >= 0)
36 std.process.exit(@as(u8, @intCast(sig)))
37 else
38 std.process.exit(1);
39}
40
41pub fn main() !void {
42 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
43 defer {
44 if (builtin.mode == .Debug) {
45 const deinit_status = gpa.deinit();
46 if (deinit_status == .leak) {
47 std.log.err("memory leak", .{});
48 }
49 }
50 }
51 const alloc = gpa.allocator();
52
53 var args = try std.process.argsWithAllocator(alloc);
54 while (args.next()) |arg| {
55 if (argMatch("-v", "--version", arg)) {
56 const stdout = std.io.getStdOut();
57 try stdout.writer().print("comlink {s}\n", .{version});
58 return;
59 }
60 }
61
62 // Handle termination signals
63 switch (builtin.os.tag) {
64 .windows => {},
65 else => {
66 var action: std.posix.Sigaction = .{
67 .handler = .{ .handler = cleanUp },
68 .mask = switch (builtin.os.tag) {
69 .macos => 0,
70 else => std.posix.empty_sigset,
71 },
72 .flags = 0,
73 };
74 try std.posix.sigaction(std.posix.SIG.INT, &action, null);
75 try std.posix.sigaction(std.posix.SIG.TERM, &action, null);
76 },
77 }
78
79 comlink.Command.user_commands = std.StringHashMap(i32).init(alloc);
80 defer comlink.Command.user_commands.deinit();
81
82 const lua = try Lua.init(&alloc);
83 defer lua.deinit();
84
85 var app = try comlink.App.init(alloc);
86 defer app.deinit();
87
88 app.run(lua) catch |err| {
89 switch (err) {
90 // ziglua errors
91 error.LuaError => {
92 const msg = lua.toString(-1) catch "";
93 const duped = alloc.dupe(u8, msg) catch "";
94 app.deinit();
95 defer alloc.free(duped);
96 log.err("{s}", .{duped});
97 return err;
98 },
99 else => return err,
100 }
101 };
102}
103
104fn argMatch(maybe_short: ?[]const u8, maybe_long: ?[]const u8, arg: [:0]const u8) bool {
105 if (maybe_short) |short| {
106 if (std.mem.eql(u8, short, arg)) return true;
107 }
108 if (maybe_long) |long| {
109 if (std.mem.eql(u8, long, arg)) return true;
110 }
111 return false;
112}
113
114test {
115 _ = @import("format.zig");
116 _ = @import("irc.zig");
117}