diff --git a/ly-core/src/SharedError.zig b/ly-core/src/SharedError.zig index 9e5de3b..ba3656e 100644 --- a/ly-core/src/SharedError.zig +++ b/ly-core/src/SharedError.zig @@ -10,11 +10,20 @@ const ErrorHandler = packed struct { const SharedError = @This(); data: []align(std.heap.page_size_min) u8, +write_error_event_fn: ?*const fn (anyerror, *anyopaque) anyerror!void, +ctx: ?*anyopaque, -pub fn init() !SharedError { +pub fn init( + write_error_event_fn: ?*const fn (anyerror, *anyopaque) anyerror!void, + ctx: ?*anyopaque, +) !SharedError { const data = try std.posix.mmap(null, @sizeOf(ErrorHandler), std.posix.PROT.READ | std.posix.PROT.WRITE, .{ .TYPE = .SHARED, .ANONYMOUS = true }, -1, 0); - return .{ .data = data }; + return .{ + .data = data, + .write_error_event_fn = write_error_event_fn, + .ctx = ctx, + }; } pub fn deinit(self: *SharedError) void { @@ -25,6 +34,10 @@ pub fn writeError(self: SharedError, err: anyerror) void { var buf_stream = std.io.fixedBufferStream(self.data); const writer = buf_stream.writer(); writer.writeStruct(ErrorHandler{ .has_error = true, .err_int = @intFromError(err) }) catch {}; + + if (self.write_error_event_fn) |write_error_event_fn| { + @call(.auto, write_error_event_fn, .{ err, self.ctx.? }) catch {}; + } } pub fn readError(self: SharedError) ?anyerror { diff --git a/src/auth.zig b/src/auth.zig index b87965c..2dd3393 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -105,7 +105,7 @@ pub fn authenticate(allocator: std.mem.Allocator, log_file: *LogFile, options: A try log_file.info("auth/passwd", "setting user shell", .{}); if (user_entry.shell == null) interop.setUserShell(&user_entry); - var shared_err = try SharedError.init(); + var shared_err = try SharedError.init(null, null); defer shared_err.deinit(); log_file.deinit(); diff --git a/src/main.zig b/src/main.zig index a79ce00..21b07d6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1054,6 +1054,7 @@ pub fn main() !void { try state.buffer.registerKeybind("Ctrl+C", &quit, &state); + // TODO: Make this generic for any Text widget present in the UI try state.buffer.registerKeybind("Ctrl+U", &clearPassword, &state); try state.buffer.registerKeybind("K", &viMoveCursorUp, &state); @@ -1093,7 +1094,6 @@ pub fn main() !void { ); } - // Position components and place cursor accordingly if (state.is_autologin) _ = try authenticate(&state); const active_widget = switch (default_input) { @@ -1103,7 +1103,7 @@ pub fn main() !void { .password => state.password_widget, }; - var shared_error = try SharedError.init(); + var shared_error = try SharedError.init(&uiErrorHandler, &state); defer shared_error.deinit(); try state.buffer.runEventLoop( @@ -1119,6 +1119,35 @@ pub fn main() !void { ); } +fn uiErrorHandler(err: anyerror, ctx: *anyopaque) anyerror!void { + var state: *UiState = @ptrCast(@alignCast(ctx)); + + switch (err) { + error.SetCursorFailed => { + try state.info_line.addMessage( + state.lang.err_alloc, + state.config.error_bg, + state.config.error_fg, + ); + }, + error.WidgetReallocationFailed => { + try state.info_line.addMessage( + state.lang.err_alloc, + state.config.error_bg, + state.config.error_fg, + ); + }, + error.CurrentWidgetHandlingFailed => { + try state.info_line.addMessage( + state.lang.err_alloc, + state.config.error_bg, + state.config.error_fg, + ); + }, + else => unreachable, + } +} + fn disableInsertMode(ptr: *anyopaque) !bool { var state: *UiState = @ptrCast(@alignCast(ptr)); @@ -1256,7 +1285,7 @@ fn authenticate(ptr: *anyopaque) !bool { } } - var shared_err = try SharedError.init(); + var shared_err = try SharedError.init(null, null); defer shared_err.deinit(); {