diff --git a/examples/direct.zig b/examples/direct.zig index f85aa84..3aba856 100644 --- a/examples/direct.zig +++ b/examples/direct.zig @@ -46,6 +46,7 @@ const Prompt = struct { }; } + // NOTE size hint is not required as the `.size = .{ .dim = .{..} }` property is set accordingly which denotes the minimal size // fn minSize(ctx: *anyopaque, _: *const App.Model, _: zterm.Point) zterm.Point { // const this: *@This() = @ptrCast(@alignCast(ctx)); // return .{ .x = this.len, .y = 1 }; @@ -140,9 +141,8 @@ pub fn main() !void { switch (event) { // NOTE maybe I want to decouple the `key`s from the user input too? i.e. this only makes sense if the output is not echoed! // otherwise just use gnu's `readline`? - .key => |key| { - // if (key.eql(.{ .cp = 'q' })) app.quit(); - _ = key; + .line => |line| { + log.debug("{s}", .{line}); }, // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), diff --git a/src/app.zig b/src/app.zig index 7137c7f..1a95c7f 100644 --- a/src/app.zig +++ b/src/app.zig @@ -30,7 +30,7 @@ pub fn App(comptime M: type, comptime E: type) type { thread: ?Thread = null, quit_event: Thread.ResetEvent, termios: ?posix.termios = null, - winch_registered: bool = false, + handler_registered: bool = false, config: TerminalConfiguration, pub const TerminalConfiguration = struct { @@ -63,6 +63,13 @@ pub fn App(comptime M: type, comptime E: type) type { // -> the signal might not work correctly when hosting the application over ssh! this.postEvent(.resize); } + /// registered CONT handler to force a complete redraw + fn handleCont(_: i32) callconv(.c) void { + const this: *@This() = @ptrCast(@alignCast(handler_ctx)); + // NOTE this does not have to be done if in-band resize events are supported + // -> the signal might not work correctly when hosting the application over ssh! + this.postEvent(.resize); + } pub fn init(io: std.Io, model: Model) @This() { return .{ @@ -81,15 +88,19 @@ pub fn App(comptime M: type, comptime E: type) type { // post init event (as the very first element to be in the queue - event loop) this.postEvent(.init); - if (!this.winch_registered) { + if (!this.handler_registered) { handler_ctx = this; - var act = posix.Sigaction{ + posix.sigaction(posix.SIG.WINCH, &.{ .handler = .{ .handler = handleWinch }, .mask = posix.sigemptyset(), .flags = 0, - }; - posix.sigaction(posix.SIG.WINCH, &act, null); - this.winch_registered = true; + }, null); + posix.sigaction(posix.SIG.CONT, &.{ + .handler = .{ .handler = handleCont }, + .mask = posix.sigemptyset(), + .flags = 0, + }, null); + this.handler_registered = true; } this.quit_event.reset(); @@ -437,9 +448,14 @@ pub fn App(comptime M: type, comptime E: type) type { var len = read_bytes; while (!std.unicode.utf8ValidateSlice(buf[0..len])) len -= 1; remaining_bytes = read_bytes - len; - var iter: std.unicode.Utf8Iterator = .{ .bytes = buf[0..len], .i = 0 }; - while (iter.nextCodepoint()) |cp| this.postEvent(.{ .key = .{ .cp = cp } }); - continue; + if (this.config.rawMode) { + var iter: std.unicode.Utf8Iterator = .{ .bytes = buf[0..len], .i = 0 }; + while (iter.nextCodepoint()) |cp| this.postEvent(.{ .key = .{ .cp = cp } }); + continue; + } else { + this.postEvent(.{ .line = buf[0..len] }); + continue; + } }, }; this.postEvent(.{ .key = key }); diff --git a/src/event.zig b/src/event.zig index e97cb67..ed0d1f6 100644 --- a/src/event.zig +++ b/src/event.zig @@ -23,6 +23,8 @@ pub const SystemEvent = union(enum) { /// associated error message msg: []const u8, }, + /// Input line event received in non *raw mode* (instead of individual `key` events) + line: []const u8, /// Input key event received from the user key: Key, /// Mouse input event