terminal: request mode

pull/9342/head
Mitchell Hashimoto 2025-10-23 20:17:23 -07:00
parent b6ac4c764f
commit 25eee9379d
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 39 additions and 11 deletions

View File

@ -73,6 +73,8 @@ pub const Action = union(Key) {
reset_mode: Mode,
save_mode: Mode,
restore_mode: Mode,
request_mode: Mode,
request_mode_unknown: RawMode,
modify_key_format: ansi.ModifyKeyFormat,
pub const Key = lib.Enum(
@ -121,6 +123,8 @@ pub const Action = union(Key) {
"reset_mode",
"save_mode",
"restore_mode",
"request_mode",
"request_mode_unknown",
"modify_key_format",
},
);
@ -180,6 +184,11 @@ pub const Action = union(Key) {
return @bitCast(self.mode);
}
};
pub const RawMode = extern struct {
mode: u16,
ansi: bool,
};
};
/// Returns a type that can process a stream of tty control characters.
@ -1242,9 +1251,16 @@ pub fn Stream(comptime Handler: type) type {
break :decrqm;
}
if (@hasDecl(T, "requestMode")) {
try self.handler.requestMode(input.params[0], ansi_mode);
} else log.warn("unimplemented DECRQM callback: {f}", .{input});
const mode_raw = input.params[0];
const mode = modes.modeFromInt(mode_raw, ansi_mode);
if (mode) |m| {
try self.handler.vt(.request_mode, .{ .mode = m });
} else {
try self.handler.vt(.request_mode_unknown, .{
.mode = mode_raw,
.ansi = ansi_mode,
});
}
},
else => log.warn(

View File

@ -253,6 +253,8 @@ pub const StreamHandler = struct {
const v = self.terminal.modes.restore(value.mode);
try self.setMode(value.mode, v);
},
.request_mode => try self.requestMode(value.mode),
.request_mode_unknown => try self.requestModeUnknown(value.mode, value.ansi),
.modify_key_format => try self.setModifyKeyFormat(value),
}
}
@ -456,22 +458,32 @@ pub const StreamHandler = struct {
}
}
pub fn requestMode(self: *StreamHandler, mode_raw: u16, ansi: bool) !void {
// Get the mode value and respond.
const code: u8 = code: {
const mode = terminal.modes.modeFromInt(mode_raw, ansi) orelse break :code 0;
if (self.terminal.modes.get(mode)) break :code 1;
break :code 2;
};
fn requestMode(self: *StreamHandler, mode: terminal.Mode) !void {
const tag: terminal.modes.ModeTag = @bitCast(@intFromEnum(mode));
const code: u8 = if (self.terminal.modes.get(mode)) 1 else 2;
var msg: termio.Message = .{ .write_small = .{} };
const resp = try std.fmt.bufPrint(
&msg.write_small.data,
"\x1B[{s}{};{}$y",
.{
if (tag.ansi) "" else "?",
tag.value,
code,
},
);
msg.write_small.len = @intCast(resp.len);
self.messageWriter(msg);
}
fn requestModeUnknown(self: *StreamHandler, mode_raw: u16, ansi: bool) !void {
var msg: termio.Message = .{ .write_small = .{} };
const resp = try std.fmt.bufPrint(
&msg.write_small.data,
"\x1B[{s}{};0$y",
.{
if (ansi) "" else "?",
mode_raw,
code,
},
);
msg.write_small.len = @intCast(resp.len);