terminal: distinguish between DSRs with "?" and not

This commit is contained in:
Mitchell Hashimoto
2024-02-02 12:42:22 -08:00
parent b43622093c
commit 3c26828a3f
4 changed files with 57 additions and 37 deletions

View File

@ -55,15 +55,6 @@ pub const DeviceAttributeReq = enum {
tertiary, // =
};
/// The device status request type (ESC [ n).
pub const DeviceStatusReq = enum(u16) {
operating_status = 5,
cursor_position = 6,
// Non-exhaustive so that @intToEnum never fails for unsupported modes.
_,
};
/// Possible cursor styles (ESC [ q)
pub const CursorStyle = enum(u16) {
default = 0,

View File

@ -12,6 +12,7 @@ pub const dcs = @import("dcs.zig");
pub const osc = @import("osc.zig");
pub const point = @import("point.zig");
pub const color = @import("color.zig");
pub const device_status = @import("device_status.zig");
pub const kitty = @import("kitty.zig");
pub const modes = @import("modes.zig");
pub const parse_table = @import("parse_table.zig");

View File

@ -3,6 +3,7 @@ const testing = std.testing;
const Parser = @import("Parser.zig");
const ansi = @import("ansi.zig");
const charsets = @import("charsets.zig");
const device_status = @import("device_status.zig");
const csi = @import("csi.zig");
const kitty = @import("kitty.zig");
const modes = @import("modes.zig");
@ -637,16 +638,42 @@ pub fn Stream(comptime Handler: type) type {
},
// TODO: test
'n' => switch (action.intermediates.len) {
0 => if (@hasDecl(T, "deviceStatusReport")) try self.handler.deviceStatusReport(
switch (action.params.len) {
1 => @enumFromInt(action.params[0]),
else => {
'n' => {
// Handle deviceStatusReport first
if (action.intermediates.len == 0 or
action.intermediates[0] == '?')
{
if (!@hasDecl(T, "deviceStatusReport")) {
log.warn("unimplemented CSI callback: {}", .{action});
return;
}
if (action.params.len != 1) {
log.warn("invalid device status report command: {}", .{action});
return;
},
},
) else log.warn("unimplemented CSI callback: {}", .{action}),
}
const question = question: {
if (action.intermediates.len == 0) break :question false;
if (action.intermediates.len == 1 and
action.intermediates[0] == '?') break :question true;
log.warn("invalid set mode command: {}", .{action});
return;
};
const req = device_status.reqFromInt(action.params[0], question) orelse {
log.warn("invalid device status report command: {}", .{action});
return;
};
try self.handler.deviceStatusReport(req);
return;
}
// Handle other forms of CSI n
switch (action.intermediates.len) {
0 => unreachable, // handled above
1 => switch (action.intermediates[0]) {
'>' => if (@hasDecl(T, "setModifyKeyFormat")) {
@ -667,6 +694,7 @@ pub fn Stream(comptime Handler: type) type {
"ignoring unimplemented CSI n with intermediates: {s}",
.{action.intermediates},
),
}
},
// DECRQM - Request Mode

View File

@ -2345,7 +2345,7 @@ const StreamHandler = struct {
pub fn deviceStatusReport(
self: *StreamHandler,
req: terminal.DeviceStatusReq,
req: terminal.device_status.Request,
) !void {
switch (req) {
.operating_status => self.messageWriter(.{ .write_stable = "\x1B[0n" }),
@ -2375,7 +2375,7 @@ const StreamHandler = struct {
self.messageWriter(msg);
},
else => log.warn("unimplemented device status req: {}", .{req}),
.theme => {},
}
}