aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/terminal/osc.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/terminal/osc.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/osc.zig')
-rw-r--r--vendor/libghostty-vt/src/terminal/osc.zig826
1 files changed, 826 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/terminal/osc.zig b/vendor/libghostty-vt/src/terminal/osc.zig
new file mode 100644
index 00000000..36cfd7f8
--- /dev/null
+++ b/vendor/libghostty-vt/src/terminal/osc.zig
@@ -0,0 +1,826 @@
+//! OSC (Operating System Command) related functions and types.
+//!
+//! OSC is another set of control sequences for terminal programs that start with
+//! "ESC ]". Unlike CSI or standard ESC sequences, they may contain strings
+//! and other irregular formatting so a dedicated parser is created to handle it.
+const osc = @This();
+
+const std = @import("std");
+const builtin = @import("builtin");
+const build_options = @import("terminal_options");
+const mem = std.mem;
+const assert = @import("../quirks.zig").inlineAssert;
+const Allocator = mem.Allocator;
+const lib = @import("lib.zig");
+const LibEnum = lib.Enum;
+const kitty_color = @import("kitty/color.zig");
+const parsers = @import("osc/parsers.zig");
+const encoding = @import("osc/encoding.zig");
+
+pub const color = parsers.color;
+pub const semantic_prompt = parsers.semantic_prompt;
+
+const log = std.log.scoped(.osc);
+
+pub const Command = union(Key) {
+ /// This generally shouldn't ever be set except as an initial zero value.
+ /// Ignore it.
+ invalid,
+
+ /// Set the window title of the terminal
+ ///
+ /// If title mode 0 is set text is expect to be hex encoded (i.e. utf-8
+ /// with each code unit further encoded with two hex digits).
+ ///
+ /// If title mode 2 is set or the terminal is setup for unconditional
+ /// utf-8 titles text is interpreted as utf-8. Else text is interpreted
+ /// as latin1.
+ change_window_title: [:0]const u8,
+
+ /// Set the icon of the terminal window. The name of the icon is not
+ /// well defined, so this is currently ignored by Ghostty at the time
+ /// of writing this. We just parse it so that we don't get parse errors
+ /// in the log.
+ change_window_icon: [:0]const u8,
+
+ /// Semantic prompt command: https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md
+ semantic_prompt: SemanticPrompt,
+
+ /// Set or get clipboard contents. If data is null, then the current
+ /// clipboard contents are sent to the pty. If data is set, this
+ /// contents is set on the clipboard.
+ clipboard_contents: struct {
+ kind: u8,
+ data: [:0]const u8,
+ },
+
+ /// OSC 7. Reports the current working directory of the shell. This is
+ /// a moderately flawed escape sequence but one that many major terminals
+ /// support so we also support it. To understand the flaws, read through
+ /// this terminal-wg issue: https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/20
+ report_pwd: struct {
+ /// The reported pwd value. This is not checked for validity. It should
+ /// be a file URL but it is up to the caller to utilize this value.
+ value: [:0]const u8,
+ },
+
+ /// OSC 22. Set the mouse shape. There doesn't seem to be a standard
+ /// naming scheme for cursors but it looks like terminals such as Foot
+ /// are moving towards using the W3C CSS cursor names. For OSC parsing,
+ /// we just parse whatever string is given.
+ mouse_shape: struct {
+ value: [:0]const u8,
+ },
+
+ /// OSC color operations to set, reset, or report color settings. Some OSCs
+ /// allow multiple operations to be specified in a single OSC so we need a
+ /// list-like datastructure to manage them. We use std.SegmentedList because
+ /// it minimizes the number of allocations and copies because a large
+ /// majority of the time there will be only one operation per OSC.
+ ///
+ /// Currently, these OSCs are handled by `color_operation`:
+ ///
+ /// 4, 5, 10-19, 104, 105, 110-119
+ color_operation: struct {
+ op: color.Operation,
+ requests: color.List = .{},
+ terminator: Terminator = .st,
+ },
+
+ /// Kitty color protocol, OSC 21
+ /// https://sw.kovidgoyal.net/kitty/color-stack/#id1
+ kitty_color_protocol: kitty_color.OSC,
+
+ /// Show a desktop notification (OSC 9 or OSC 777)
+ show_desktop_notification: struct {
+ title: [:0]const u8,
+ body: [:0]const u8,
+ },
+
+ /// Start a hyperlink (OSC 8)
+ hyperlink_start: struct {
+ id: ?[:0]const u8 = null,
+ uri: [:0]const u8,
+ },
+
+ /// End a hyperlink (OSC 8)
+ hyperlink_end: void,
+
+ /// ConEmu sleep (OSC 9;1)
+ conemu_sleep: struct {
+ duration_ms: u16,
+ },
+
+ /// ConEmu show GUI message box (OSC 9;2)
+ conemu_show_message_box: [:0]const u8,
+
+ /// ConEmu change tab title (OSC 9;3)
+ conemu_change_tab_title: union(enum) {
+ reset,
+ value: [:0]const u8,
+ },
+
+ /// ConEmu progress report (OSC 9;4)
+ conemu_progress_report: ProgressReport,
+
+ /// ConEmu wait input (OSC 9;5)
+ conemu_wait_input,
+
+ /// ConEmu GUI macro (OSC 9;6)
+ conemu_guimacro: [:0]const u8,
+
+ /// ConEmu run process (OSC 9;7)
+ conemu_run_process: [:0]const u8,
+
+ /// ConEmu output environment variable (OSC 9;8)
+ conemu_output_environment_variable: [:0]const u8,
+
+ /// ConEmu XTerm keyboard and output emulation (OSC 9;10)
+ /// https://conemu.github.io/en/TerminalModes.html
+ conemu_xterm_emulation: struct {
+ /// null => do not change
+ /// false => turn off
+ /// true => turn on
+ keyboard: ?bool,
+ /// null => do not change
+ /// false => turn off
+ /// true => turn on
+ output: ?bool,
+ },
+
+ /// ConEmu comment (OSC 9;11)
+ conemu_comment: [:0]const u8,
+
+ /// Kitty text sizing protocol (OSC 66)
+ kitty_text_sizing: parsers.kitty_text_sizing.OSC,
+
+ kitty_clipboard_protocol: KittyClipboardProtocol,
+
+ /// OSC 3008. Hierarchical context signalling (UAPI spec).
+ /// https://uapi-group.org/specifications/specs/osc_context/
+ context_signal: parsers.context_signal.Command,
+
+ pub const SemanticPrompt = parsers.semantic_prompt.Command;
+
+ pub const KittyClipboardProtocol = parsers.kitty_clipboard_protocol.OSC;
+
+ pub const Key = LibEnum(
+ lib.target,
+ // NOTE: Order matters, see LibEnum documentation.
+ &.{
+ "invalid",
+ "change_window_title",
+ "change_window_icon",
+ "semantic_prompt",
+ "clipboard_contents",
+ "report_pwd",
+ "mouse_shape",
+ "color_operation",
+ "kitty_color_protocol",
+ "show_desktop_notification",
+ "hyperlink_start",
+ "hyperlink_end",
+ "conemu_sleep",
+ "conemu_show_message_box",
+ "conemu_change_tab_title",
+ "conemu_progress_report",
+ "conemu_wait_input",
+ "conemu_guimacro",
+ "conemu_run_process",
+ "conemu_output_environment_variable",
+ "conemu_xterm_emulation",
+ "conemu_comment",
+ "kitty_text_sizing",
+ "kitty_clipboard_protocol",
+ "context_signal",
+ },
+ );
+
+ pub const ProgressReport = struct {
+ pub const State = enum(c_int) {
+ remove,
+ set,
+ @"error",
+ indeterminate,
+ pause,
+
+ test "ghostty.h Command.ProgressReport.State" {
+ if (comptime build_options.artifact == .lib) return error.SkipZigTest;
+ try lib.checkGhosttyHEnum(State, "GHOSTTY_PROGRESS_STATE_");
+ }
+ };
+
+ state: State,
+ progress: ?u8 = null,
+
+ // sync with ghostty_action_progress_report_s
+ pub const C = extern struct {
+ state: c_int,
+ progress: i8,
+ };
+
+ pub fn cval(self: ProgressReport) C {
+ return .{
+ .state = @intFromEnum(self.state),
+ .progress = if (self.progress) |progress| @intCast(std.math.clamp(
+ progress,
+ 0,
+ 100,
+ )) else -1,
+ };
+ }
+ };
+
+ comptime {
+ assert(@sizeOf(Command) == switch (@sizeOf(usize)) {
+ 4 => 44,
+ 8 => 64,
+ else => unreachable,
+ });
+ }
+};
+
+/// The terminator used to end an OSC command. For OSC commands that demand
+/// a response, we try to match the terminator used in the request since that
+/// is most likely to be accepted by the calling program.
+pub const Terminator = enum {
+ /// The preferred string terminator is ESC followed by \
+ st,
+
+ /// Some applications and terminals use BELL (0x07) as the string terminator.
+ bel,
+
+ pub const C = LibEnum(.c, &.{ "st", "bel" });
+
+ /// Initialize the terminator based on the last byte seen. If the
+ /// last byte is a BEL then we use BEL, otherwise we just assume ST.
+ pub fn init(ch: ?u8) Terminator {
+ return switch (ch orelse return .st) {
+ 0x07 => .bel,
+ else => .st,
+ };
+ }
+
+ /// The terminator as a string. This is static memory so it doesn't
+ /// need to be freed.
+ pub fn string(self: Terminator) []const u8 {
+ return switch (self) {
+ .st => "\x1b\\",
+ .bel => "\x07",
+ };
+ }
+
+ pub fn cval(self: Terminator) C {
+ return switch (self) {
+ .st => .st,
+ .bel => .bel,
+ };
+ }
+
+ pub fn format(
+ self: Terminator,
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: *std.Io.Writer,
+ ) !void {
+ try writer.writeAll(self.string());
+ }
+};
+
+pub const Parser = struct {
+ /// Maximum size of a "normal" OSC.
+ pub const MAX_BUF = 2048;
+
+ /// Optional allocator used to accept data longer than MAX_BUF.
+ /// This only applies to some commands (e.g. OSC 52) that can
+ /// reasonably exceed MAX_BUF.
+ alloc: ?Allocator,
+
+ /// Current state of the parser.
+ state: State,
+
+ /// Buffer for temporary storage of OSC data
+ buffer: [MAX_BUF]u8,
+
+ /// Capture state. If this is set then we're actively capturing the
+ /// bytes coming into the parser.
+ capture: ?Capture,
+
+ /// The command that is the result of parsing.
+ command: Command,
+
+ pub const State = enum {
+ start,
+ invalid,
+
+ // OSC command prefixes. Not all of these are valid OSCs, but may be
+ // needed to "bridge" to a valid OSC (e.g. to support OSC 777 we need to
+ // have a state "77" even though there is no OSC 77).
+ @"0",
+ @"1",
+ @"2",
+ @"3",
+ @"4",
+ @"5",
+ @"6",
+ @"7",
+ @"8",
+ @"9",
+ @"30",
+ @"300",
+ @"3008",
+ @"10",
+ @"11",
+ @"12",
+ @"13",
+ @"14",
+ @"15",
+ @"16",
+ @"17",
+ @"18",
+ @"19",
+ @"21",
+ @"22",
+ @"52",
+ @"55",
+ @"66",
+ @"77",
+ @"104",
+ @"110",
+ @"111",
+ @"112",
+ @"113",
+ @"114",
+ @"115",
+ @"116",
+ @"117",
+ @"118",
+ @"119",
+ @"133",
+ @"552",
+ @"777",
+ @"1337",
+ @"5522",
+ };
+
+ pub fn init(alloc: ?Allocator) Parser {
+ var result: Parser = .{
+ .alloc = alloc,
+ .state = .start,
+ .capture = null,
+ .command = .invalid,
+
+ // Keeping all our undefined values together so we can
+ // visually easily duplicate them in the Valgrind check below.
+ .buffer = undefined,
+ };
+ if (std.valgrind.runningOnValgrind() > 0) {
+ // Initialize our undefined fields so Valgrind can catch it.
+ // https://github.com/ziglang/zig/issues/19148
+ result.buffer = undefined;
+ }
+
+ return result;
+ }
+
+ /// This must be called to clean up any allocated memory.
+ pub fn deinit(self: *Parser) void {
+ self.reset();
+ }
+
+ /// Reset the parser state.
+ pub fn reset(self: *Parser) void {
+ // If we're capturing, then stop it.
+ if (self.capture) |*cap| cap.deinit();
+
+ // Handle any cleanup that individual OSCs require.
+ switch (self.command) {
+ .kitty_color_protocol => |*v| kitty_color_protocol: {
+ v.deinit(self.alloc orelse break :kitty_color_protocol);
+ },
+ .change_window_icon,
+ .change_window_title,
+ .clipboard_contents,
+ .color_operation,
+ .conemu_change_tab_title,
+ .conemu_comment,
+ .conemu_guimacro,
+ .conemu_output_environment_variable,
+ .conemu_progress_report,
+ .conemu_run_process,
+ .conemu_show_message_box,
+ .conemu_sleep,
+ .conemu_wait_input,
+ .conemu_xterm_emulation,
+ .hyperlink_end,
+ .hyperlink_start,
+ .invalid,
+ .mouse_shape,
+ .report_pwd,
+ .semantic_prompt,
+ .show_desktop_notification,
+ .kitty_text_sizing,
+ .kitty_clipboard_protocol,
+ .context_signal,
+ => {},
+ }
+
+ self.state = .start;
+ self.capture = null;
+ self.command = .invalid;
+
+ if (std.valgrind.runningOnValgrind() > 0) {
+ // Initialize our undefined fields so Valgrind can catch it.
+ // https://github.com/ziglang/zig/issues/19148
+ self.buffer = undefined;
+ }
+ }
+
+ /// Make sure that we have an allocator. If we don't, set the state to
+ /// invalid so that any additional OSC data is discarded.
+ inline fn ensureAllocator(self: *Parser) bool {
+ if (self.alloc != null) return true;
+ log.warn("An allocator is required to process OSC {t} but none was provided.", .{self.state});
+ self.state = .invalid;
+ return false;
+ }
+
+ const Capture = struct {
+ writer: *std.Io.Writer,
+ backing: Backing,
+
+ const Backing = union(enum) {
+ fixed: std.Io.Writer,
+ allocating: std.Io.Writer.Allocating,
+ };
+
+ const Mode = enum {
+ fixed,
+ allocating,
+ };
+
+ pub inline fn fixed(new: *?Capture, buf: []u8) void {
+ new.* = .{
+ .backing = .{ .fixed = .fixed(buf) },
+ .writer = &new.*.?.backing.fixed,
+ };
+ }
+
+ pub inline fn allocating(
+ new: *?Capture,
+ alloc: Allocator,
+ ) error{OutOfMemory}!void {
+ new.* = .{
+ .backing = .{ .allocating = try std.Io.Writer.Allocating.initCapacity(
+ alloc,
+ 2048,
+ ) },
+ .writer = &new.*.?.backing.allocating.writer,
+ };
+ }
+
+ pub fn deinit(self: *Capture) void {
+ switch (self.backing) {
+ .fixed => {},
+ .allocating => |*w| w.deinit(),
+ }
+ }
+
+ /// Return the captured trailing data. This is the data from the
+ /// point that trailing data capture was requested.
+ pub inline fn trailing(self: *Capture) []u8 {
+ return self.writer.buffered();
+ }
+ };
+
+ /// Begin capturing trailing data. All inputs to next from this point
+ /// forward will be captured into the `self.capture.writer` buffer
+ /// which may be backed by either a fixed size or allocating buffer
+ /// depending on mode.
+ ///
+ /// Get the trailing data using `capture.trailing()`. Do not access
+ /// the writer directly.
+ inline fn captureTrailing(
+ self: *Parser,
+ comptime mode: Capture.Mode,
+ ) void {
+ assert(self.capture == null);
+ switch (mode) {
+ .fixed => Capture.fixed(
+ &self.capture,
+ &self.buffer,
+ ),
+
+ .allocating => {
+ const alloc = self.alloc orelse {
+ // We don't have an allocator - fall back to a fixed buffer and hope
+ // that it's big enough.
+ self.captureTrailing(.fixed);
+ return;
+ };
+
+ Capture.allocating(
+ &self.capture,
+ alloc,
+ ) catch {
+ // The allocator failed for some reason, fall back to a fixed buffer
+ // and hope that it's big enough.
+ self.captureTrailing(.fixed);
+ return;
+ };
+ },
+ }
+ }
+
+ /// Consume the next character c and advance the parser state.
+ pub fn next(self: *Parser, c: u8) void {
+ // If the state becomes invalid for any reason, just discard
+ // any further input.
+ if (self.state == .invalid) return;
+
+ // If a writer has been initialized, we just accumulate the rest of the
+ // OSC sequence in the writer's buffer and skip the state machine.
+ if (self.capture) |*cap| {
+ cap.writer.writeByte(c) catch |err| switch (err) {
+ // We have overflowed our buffer or had some other error, set the
+ // state to invalid so that we discard any further input.
+ error.WriteFailed => self.state = .invalid,
+ };
+ return;
+ }
+
+ switch (self.state) {
+ // handled above, so should never be here
+ .invalid => unreachable,
+
+ .start => switch (c) {
+ '0' => self.state = .@"0",
+ '1' => self.state = .@"1",
+ '2' => self.state = .@"2",
+ '3' => self.state = .@"3",
+ '4' => self.state = .@"4",
+ '5' => self.state = .@"5",
+ '6' => self.state = .@"6",
+ '7' => self.state = .@"7",
+ '8' => self.state = .@"8",
+ '9' => self.state = .@"9",
+ else => self.state = .invalid,
+ },
+
+ .@"3" => switch (c) {
+ '0' => self.state = .@"30",
+ else => self.state = .invalid,
+ },
+
+ .@"30" => switch (c) {
+ '0' => self.state = .@"300",
+ else => self.state = .invalid,
+ },
+
+ .@"300" => switch (c) {
+ '8' => self.state = .@"3008",
+ else => self.state = .invalid,
+ },
+
+ .@"3008" => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ else => self.state = .invalid,
+ },
+
+ .@"1" => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ '0' => self.state = .@"10",
+ '1' => self.state = .@"11",
+ '2' => self.state = .@"12",
+ '3' => self.state = .@"13",
+ '4' => self.state = .@"14",
+ '5' => self.state = .@"15",
+ '6' => self.state = .@"16",
+ '7' => self.state = .@"17",
+ '8' => self.state = .@"18",
+ '9' => self.state = .@"19",
+ else => self.state = .invalid,
+ },
+
+ .@"10" => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ '4' => self.state = .@"104",
+ else => self.state = .invalid,
+ },
+
+ .@"104" => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ else => self.state = .invalid,
+ },
+
+ .@"11" => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ '0' => self.state = .@"110",
+ '1' => self.state = .@"111",
+ '2' => self.state = .@"112",
+ '3' => self.state = .@"113",
+ '4' => self.state = .@"114",
+ '5' => self.state = .@"115",
+ '6' => self.state = .@"116",
+ '7' => self.state = .@"117",
+ '8' => self.state = .@"118",
+ '9' => self.state = .@"119",
+ else => self.state = .invalid,
+ },
+
+ .@"4",
+ .@"12",
+ .@"14",
+ .@"15",
+ .@"16",
+ .@"17",
+ .@"18",
+ .@"19",
+ .@"21",
+ .@"110",
+ .@"111",
+ .@"112",
+ .@"113",
+ .@"114",
+ .@"115",
+ .@"116",
+ .@"117",
+ .@"118",
+ .@"119",
+ => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ else => self.state = .invalid,
+ },
+
+ .@"13" => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ '3' => self.state = .@"133",
+ else => self.state = .invalid,
+ },
+
+ .@"2" => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ '1' => self.state = .@"21",
+ '2' => self.state = .@"22",
+ else => self.state = .invalid,
+ },
+
+ .@"5" => switch (c) {
+ ';' => if (self.ensureAllocator()) self.captureTrailing(.fixed),
+ '2' => self.state = .@"52",
+ '5' => self.state = .@"55",
+ else => self.state = .invalid,
+ },
+
+ .@"6" => switch (c) {
+ '6' => self.state = .@"66",
+ else => self.state = .invalid,
+ },
+
+ .@"52",
+ .@"66",
+ => switch (c) {
+ ';' => self.captureTrailing(.allocating),
+ else => self.state = .invalid,
+ },
+
+ .@"55" => switch (c) {
+ '2' => self.state = .@"552",
+ else => self.state = .invalid,
+ },
+
+ .@"7" => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ '7' => self.state = .@"77",
+ else => self.state = .invalid,
+ },
+
+ .@"77" => switch (c) {
+ '7' => self.state = .@"777",
+ else => self.state = .invalid,
+ },
+
+ .@"133",
+ => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ '7' => self.state = .@"1337",
+ else => self.state = .invalid,
+ },
+
+ .@"552" => switch (c) {
+ '2' => self.state = .@"5522",
+ else => self.state = .invalid,
+ },
+
+ .@"1337",
+ => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ else => self.state = .invalid,
+ },
+
+ .@"5522",
+ => switch (c) {
+ ';' => self.captureTrailing(.allocating),
+ else => self.state = .invalid,
+ },
+
+ .@"0",
+ .@"22",
+ .@"777",
+ .@"8",
+ .@"9",
+ => switch (c) {
+ ';' => self.captureTrailing(.fixed),
+ else => self.state = .invalid,
+ },
+ }
+ }
+
+ /// End the sequence and return the command, if any. If the return value
+ /// is null, then no valid command was found. The optional terminator_ch
+ /// is the final character in the OSC sequence. This is used to determine
+ /// the response terminator.
+ ///
+ /// The returned pointer is only valid until the next call to the parser.
+ /// Callers should copy out any data they wish to retain across calls.
+ pub fn end(self: *Parser, terminator_ch: ?u8) ?*Command {
+ return switch (self.state) {
+ .start => null,
+
+ .invalid => null,
+
+ .@"0",
+ .@"2",
+ => parsers.change_window_title.parse(self, terminator_ch),
+
+ .@"1" => parsers.change_window_icon.parse(self, terminator_ch),
+
+ .@"4",
+ .@"5",
+ .@"10",
+ .@"11",
+ .@"12",
+ .@"13",
+ .@"14",
+ .@"15",
+ .@"16",
+ .@"17",
+ .@"18",
+ .@"19",
+ .@"104",
+ .@"110",
+ .@"111",
+ .@"112",
+ .@"113",
+ .@"114",
+ .@"115",
+ .@"116",
+ .@"117",
+ .@"118",
+ .@"119",
+ => parsers.color.parse(self, terminator_ch),
+
+ .@"7" => parsers.report_pwd.parse(self, terminator_ch),
+
+ .@"8" => parsers.hyperlink.parse(self, terminator_ch),
+
+ .@"9" => parsers.osc9.parse(self, terminator_ch),
+
+ .@"21" => parsers.kitty_color.parse(self, terminator_ch),
+
+ .@"22" => parsers.mouse_shape.parse(self, terminator_ch),
+
+ .@"52" => parsers.clipboard_operation.parse(self, terminator_ch),
+
+ .@"55" => null,
+
+ .@"3",
+ .@"30",
+ .@"300",
+ => null,
+
+ .@"3008" => parsers.context_signal.parse(self, terminator_ch),
+
+ .@"6" => null,
+
+ .@"66" => parsers.kitty_text_sizing.parse(self, terminator_ch),
+
+ .@"77" => null,
+
+ .@"133" => parsers.semantic_prompt.parse(self, terminator_ch),
+
+ .@"552" => null,
+
+ .@"777" => parsers.rxvt_extension.parse(self, terminator_ch),
+
+ .@"1337" => parsers.iterm2.parse(self, terminator_ch),
+
+ .@"5522" => parsers.kitty_clipboard_protocol.parse(self, terminator_ch),
+ };
+ }
+};
+
+test {
+ _ = parsers;
+ _ = encoding;
+}