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, // = 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) /// Possible cursor styles (ESC [ q)
pub const CursorStyle = enum(u16) { pub const CursorStyle = enum(u16) {
default = 0, default = 0,

View File

@ -12,6 +12,7 @@ pub const dcs = @import("dcs.zig");
pub const osc = @import("osc.zig"); pub const osc = @import("osc.zig");
pub const point = @import("point.zig"); pub const point = @import("point.zig");
pub const color = @import("color.zig"); pub const color = @import("color.zig");
pub const device_status = @import("device_status.zig");
pub const kitty = @import("kitty.zig"); pub const kitty = @import("kitty.zig");
pub const modes = @import("modes.zig"); pub const modes = @import("modes.zig");
pub const parse_table = @import("parse_table.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 Parser = @import("Parser.zig");
const ansi = @import("ansi.zig"); const ansi = @import("ansi.zig");
const charsets = @import("charsets.zig"); const charsets = @import("charsets.zig");
const device_status = @import("device_status.zig");
const csi = @import("csi.zig"); const csi = @import("csi.zig");
const kitty = @import("kitty.zig"); const kitty = @import("kitty.zig");
const modes = @import("modes.zig"); const modes = @import("modes.zig");
@ -637,36 +638,63 @@ pub fn Stream(comptime Handler: type) type {
}, },
// TODO: test // TODO: test
'n' => switch (action.intermediates.len) { 'n' => {
0 => if (@hasDecl(T, "deviceStatusReport")) try self.handler.deviceStatusReport( // Handle deviceStatusReport first
switch (action.params.len) { if (action.intermediates.len == 0 or
1 => @enumFromInt(action.params[0]), action.intermediates[0] == '?')
else => { {
log.warn("invalid device status report command: {}", .{action}); if (!@hasDecl(T, "deviceStatusReport")) {
return; log.warn("unimplemented CSI callback: {}", .{action});
}, return;
}, }
) else log.warn("unimplemented CSI callback: {}", .{action}),
1 => switch (action.intermediates[0]) { if (action.params.len != 1) {
'>' => if (@hasDecl(T, "setModifyKeyFormat")) { log.warn("invalid device status report command: {}", .{action});
// This isn't strictly correct. CSI > n has parameters that return;
// control what exactly is being disabled. However, we }
// only support reverting back to modify other keys in
// numeric except format. const question = question: {
try self.handler.setModifyKeyFormat(.{ .other_keys = .numeric_except }); if (action.intermediates.len == 0) break :question false;
} else log.warn("unimplemented setModifyKeyFormat: {}", .{action}), 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")) {
// This isn't strictly correct. CSI > n has parameters that
// control what exactly is being disabled. However, we
// only support reverting back to modify other keys in
// numeric except format.
try self.handler.setModifyKeyFormat(.{ .other_keys = .numeric_except });
} else log.warn("unimplemented setModifyKeyFormat: {}", .{action}),
else => log.warn(
"unknown CSI n with intermediate: {}",
.{action.intermediates[0]},
),
},
else => log.warn( else => log.warn(
"unknown CSI n with intermediate: {}", "ignoring unimplemented CSI n with intermediates: {s}",
.{action.intermediates[0]}, .{action.intermediates},
), ),
}, }
else => log.warn(
"ignoring unimplemented CSI n with intermediates: {s}",
.{action.intermediates},
),
}, },
// DECRQM - Request Mode // DECRQM - Request Mode

View File

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