diff --git a/README.md b/README.md index 21934a2..95a0c02 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Contributions are welcome. | Styled Underlines | ✅ | ✅ | ✅ | | Mouse Shapes (OSC 22) | ✅ | planned | ❌ | | System Clipboard (OSC 52) | ✅ | planned | ❌ | -| System Notifications (OSC 9) | ✅ | planned | ❌ | -| System Notifications (OSC 777) | ✅ | planned | ❌ | +| System Notifications (OSC 9) | ✅ | ✅ | ❌ | +| System Notifications (OSC 777) | ✅ | ✅ | ❌ | | Synchronized Output (DEC 2026) | ✅ | ✅ | ✅ | | Unicode Core (DEC 2027) | ✅ | ✅ | ❌ | | Color Mode Updates (DEC 2031) | ✅ | planned | ❌ | diff --git a/examples/text_input.zig b/examples/text_input.zig index 626c27a..7ef5597 100644 --- a/examples/text_input.zig +++ b/examples/text_input.zig @@ -71,6 +71,8 @@ pub fn main() !void { break :outer; } else if (key.matches('l', .{ .ctrl = true })) { vx.queueRefresh(); + } else if (key.matches('n', .{ .ctrl = true })) { + try vx.notify("vaxis", "hello from vaxis"); } else { try text_input.update(.{ .key_press = key }); } diff --git a/src/cell.zig b/src/cell.zig index 7c3daef..c8c7b8e 100644 --- a/src/cell.zig +++ b/src/cell.zig @@ -22,6 +22,8 @@ pub const Style = struct { bg: Color = .default, ul: Color = .default, ul_style: Underline = .off, + // TODO: url should maybe go outside of style. We'll need to allocate these + // in the internal screen url: ?[]const u8 = null, url_params: ?[]const u8 = null, diff --git a/src/ctlseqs.zig b/src/ctlseqs.zig index faf2b7d..f4e6cea 100644 --- a/src/ctlseqs.zig +++ b/src/ctlseqs.zig @@ -76,3 +76,5 @@ pub const strikethrough_reset = "\x1b[29m"; // OSC sequences pub const osc8 = "\x1b]8;{s};{s}\x1b\\"; pub const osc8_clear = "\x1b]8;;\x1b\\"; +pub const osc9_notify = "\x1b]9;{s}\x1b\\"; +pub const osc777_notify = "\x1b]777;notify;{s};{s}\x1b\\"; diff --git a/src/vaxis.zig b/src/vaxis.zig index 332b390..915a2be 100644 --- a/src/vaxis.zig +++ b/src/vaxis.zig @@ -472,6 +472,24 @@ pub fn Vaxis(comptime T: type) type { ); try self.tty.?.flush(); } + + /// send a system notification + pub fn notify(self: *Self, title: ?[]const u8, body: []const u8) !void { + if (self.tty == null) return; + if (title) |t| { + try std.fmt.format( + self.tty.?.buffered_writer.writer(), + ctlseqs.osc777_notify, + .{ t, body }, + ); + } else { + try std.fmt.format( + self.tty.?.buffered_writer.writer(), + ctlseqs.osc9_notify, + .{body}, + ); + } + } }; }