diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/terminal/c/osc.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/c/osc.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/terminal/c/osc.zig | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/terminal/c/osc.zig b/vendor/libghostty-vt/src/terminal/c/osc.zig new file mode 100644 index 00000000..7ba32300 --- /dev/null +++ b/vendor/libghostty-vt/src/terminal/c/osc.zig @@ -0,0 +1,140 @@ +const std = @import("std"); +const lib = @import("../lib.zig"); +const CAllocator = lib.alloc.Allocator; +const osc = @import("../osc.zig"); +const Result = @import("result.zig").Result; + +const log = std.log.scoped(.osc); + +/// C: GhosttyOscParser +pub const Parser = ?*osc.Parser; + +/// C: GhosttyOscCommand +pub const Command = ?*osc.Command; + +pub fn new( + alloc_: ?*const CAllocator, + result: *Parser, +) callconv(lib.calling_conv) Result { + const alloc = lib.alloc.default(alloc_); + const ptr = alloc.create(osc.Parser) catch + return .out_of_memory; + ptr.* = .init(alloc); + result.* = ptr; + return .success; +} + +pub fn free(parser_: Parser) callconv(lib.calling_conv) void { + // C-built parsers always have an associated allocator. + const parser = parser_ orelse return; + const alloc = parser.alloc.?; + parser.deinit(); + alloc.destroy(parser); +} + +pub fn reset(parser_: Parser) callconv(lib.calling_conv) void { + parser_.?.reset(); +} + +pub fn next(parser_: Parser, byte: u8) callconv(lib.calling_conv) void { + parser_.?.next(byte); +} + +pub fn end(parser_: Parser, terminator: u8) callconv(lib.calling_conv) Command { + return parser_.?.end(terminator); +} + +pub fn commandType(command_: Command) callconv(lib.calling_conv) osc.Command.Key { + const command = command_ orelse return .invalid; + return command.*; +} + +/// C: GhosttyOscCommandData +pub const CommandData = enum(c_int) { + invalid = 0, + change_window_title_str = 1, + + /// Output type expected for querying the data of the given kind. + pub fn OutType(comptime self: CommandData) type { + return switch (self) { + .invalid => void, + .change_window_title_str => [*:0]const u8, + }; + } +}; + +pub fn commandData( + command_: Command, + data: CommandData, + out: ?*anyopaque, +) callconv(lib.calling_conv) bool { + if (comptime std.debug.runtime_safety) { + _ = std.meta.intToEnum(CommandData, @intFromEnum(data)) catch { + log.warn("commandData invalid data value={d}", .{@intFromEnum(data)}); + return false; + }; + } + + return switch (data) { + .invalid => false, + inline else => |comptime_data| commandDataTyped( + command_, + comptime_data, + @ptrCast(@alignCast(out)), + ), + }; +} + +fn commandDataTyped( + command_: Command, + comptime data: CommandData, + out: *data.OutType(), +) bool { + const command = command_.?; + switch (data) { + .invalid => return false, + .change_window_title_str => switch (command.*) { + .change_window_title => |v| out.* = v.ptr, + else => return false, + }, + } + + return true; +} + +test "alloc" { + const testing = std.testing; + var p: Parser = undefined; + try testing.expectEqual(Result.success, new( + &lib.alloc.test_allocator, + &p, + )); + free(p); +} + +test "command type null" { + const testing = std.testing; + try testing.expectEqual(.invalid, commandType(null)); +} + +test "change window title" { + const testing = std.testing; + var p: Parser = undefined; + try testing.expectEqual(Result.success, new( + &lib.alloc.test_allocator, + &p, + )); + defer free(p); + + // Parse it + next(p, '0'); + next(p, ';'); + next(p, 'a'); + const cmd = end(p, 0); + try testing.expectEqual(.change_window_title, commandType(cmd)); + + // Extract the title + var title: [*:0]const u8 = undefined; + try testing.expect(commandData(cmd, .change_window_title_str, @ptrCast(&title))); + try testing.expectEqualStrings("a", std.mem.span(title)); +} |
