terminal: OSC133 options parse from raw string

This changes our OSC133 parser to parse options lazily. We do this for
multiple reasons:

1. Parsing all our options ahead of time balloons our required
   osc.Command tagged union type which has C ABI implications. Adding
   all supported options (including Kitty extensions) today already
   breaks our C ABI.

2. Invalid options are allowed by the specification and should be 
   explicitly ignored, so we don't need to validate options at all
   during parse time.

3. Semantic prompt markers don't need to be high throughput, so we
   can afford to do some extra work at processing time to gather
   the options. They're also rather short usually.
This commit is contained in:
Mitchell Hashimoto
2026-01-24 13:30:06 -08:00
parent f479210daf
commit c9e60b322b
3 changed files with 251 additions and 210 deletions

View File

@@ -1072,11 +1072,13 @@ pub const StreamHandler = struct {
) void {
switch (cmd.action) {
.fresh_line_new_prompt => {
const kind = cmd.options.prompt_kind orelse .initial;
const kind = cmd.readOption(.prompt_kind) orelse .initial;
switch (kind) {
.initial, .right => {
self.terminal.markSemanticPrompt(.prompt);
self.terminal.flags.shell_redraws_prompt = cmd.options.redraw;
if (cmd.readOption(.redraw)) |redraw| {
self.terminal.flags.shell_redraws_prompt = redraw;
}
},
.continuation, .secondary => {
self.terminal.markSemanticPrompt(.prompt_continuation);
@@ -1094,7 +1096,7 @@ pub const StreamHandler = struct {
// other terminals accept 32-bits, but exit codes are really
// bytes, so we just do our best here.
const code: u8 = code: {
const raw: i32 = cmd.options.exit_code orelse 0;
const raw: i32 = cmd.readOption(.exit_code) orelse 0;
break :code std.math.cast(u8, raw) orelse 1;
};