diff --git a/src/terminal/ansi.zig b/src/terminal/ansi.zig index 27f9971aa..43c2a9a1c 100644 --- a/src/terminal/ansi.zig +++ b/src/terminal/ansi.zig @@ -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, diff --git a/src/terminal/main.zig b/src/terminal/main.zig index 1ca385c27..0ce4610b5 100644 --- a/src/terminal/main.zig +++ b/src/terminal/main.zig @@ -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"); diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index da8dfa606..f33f52942 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -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,36 +638,63 @@ 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 => { - log.warn("invalid device status report command: {}", .{action}); - return; - }, - }, - ) else log.warn("unimplemented CSI callback: {}", .{action}), + 'n' => { + // Handle deviceStatusReport first + if (action.intermediates.len == 0 or + action.intermediates[0] == '?') + { + if (!@hasDecl(T, "deviceStatusReport")) { + log.warn("unimplemented CSI callback: {}", .{action}); + return; + } - 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}), + if (action.params.len != 1) { + log.warn("invalid device status report command: {}", .{action}); + return; + } + + 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")) { + // 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( - "unknown CSI n with intermediate: {}", - .{action.intermediates[0]}, + "ignoring unimplemented CSI n with intermediates: {s}", + .{action.intermediates}, ), - }, - - else => log.warn( - "ignoring unimplemented CSI n with intermediates: {s}", - .{action.intermediates}, - ), + } }, // DECRQM - Request Mode diff --git a/src/termio/Exec.zig b/src/termio/Exec.zig index e98365fd8..37c61a8aa 100644 --- a/src/termio/Exec.zig +++ b/src/termio/Exec.zig @@ -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 => {}, } }