terminal: modify_other_keys

pull/9342/head
Mitchell Hashimoto 2025-10-23 20:15:05 -07:00
parent 94a8fa05cb
commit b6ac4c764f
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
3 changed files with 35 additions and 24 deletions

View File

@ -1,3 +1,7 @@
const build_options = @import("terminal_options");
const lib = @import("../lib/main.zig");
const lib_target: lib.Target = if (build_options.c_abi) .c else .zig;
/// C0 (7-bit) control characters from ANSI.
///
/// This is not complete, control characters are only added to this
@ -95,12 +99,17 @@ pub const StatusDisplay = enum(u16) {
/// The possible modify key formats to ESC[>{a};{b}m
/// Note: this is not complete, we should add more as we support more
pub const ModifyKeyFormat = union(enum) {
legacy: void,
cursor_keys: void,
function_keys: void,
other_keys: enum { none, numeric_except, numeric },
};
pub const ModifyKeyFormat = lib.Enum(
lib_target,
&.{
"legacy",
"cursor_keys",
"function_keys",
"other_keys_none",
"other_keys_numeric_except",
"other_keys_numeric",
},
);
/// The protection modes that can be set for the terminal. See DECSCA and
/// ESC V, W.

View File

@ -73,6 +73,7 @@ pub const Action = union(Key) {
reset_mode: Mode,
save_mode: Mode,
restore_mode: Mode,
modify_key_format: ansi.ModifyKeyFormat,
pub const Key = lib.Enum(
lib_target,
@ -120,6 +121,7 @@ pub const Action = union(Key) {
"reset_mode",
"save_mode",
"restore_mode",
"modify_key_format",
},
);
@ -1094,18 +1096,18 @@ pub fn Stream(comptime Handler: type) type {
} else log.warn("unimplemented CSI callback: {f}", .{input}),
1 => switch (input.intermediates[0]) {
'>' => if (@hasDecl(T, "setModifyKeyFormat")) blk: {
'>' => blk: {
if (input.params.len == 0) {
// Reset
try self.handler.setModifyKeyFormat(.{ .legacy = {} });
try self.handler.vt(.modify_key_format, .legacy);
break :blk;
}
var format: ansi.ModifyKeyFormat = switch (input.params[0]) {
0 => .{ .legacy = {} },
1 => .{ .cursor_keys = {} },
2 => .{ .function_keys = {} },
4 => .{ .other_keys = .none },
0 => .legacy,
1 => .cursor_keys,
2 => .function_keys,
4 => .other_keys_none,
else => {
log.warn("invalid setModifyKeyFormat: {f}", .{input});
break :blk;
@ -1125,15 +1127,17 @@ pub fn Stream(comptime Handler: type) type {
.function_keys => {},
// We only support the numeric form.
.other_keys => |*v| switch (input.params[1]) {
2 => v.* = .numeric,
else => v.* = .none,
.other_keys_none => switch (input.params[1]) {
2 => format = .other_keys_numeric,
else => {},
},
.other_keys_numeric_except => {},
.other_keys_numeric => {},
}
}
try self.handler.setModifyKeyFormat(format);
} else log.warn("unimplemented setModifyKeyFormat: {f}", .{input}),
try self.handler.vt(.modify_key_format, format);
},
else => log.warn(
"unknown CSI m with intermediate: {}",
@ -1194,13 +1198,13 @@ pub fn Stream(comptime Handler: type) type {
0 => unreachable, // handled above
1 => switch (input.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: {f}", .{input}),
try self.handler.vt(.modify_key_format, .other_keys_numeric_except);
},
else => log.warn(
"unknown CSI n with intermediate: {}",

View File

@ -253,6 +253,7 @@ pub const StreamHandler = struct {
const v = self.terminal.modes.restore(value.mode);
try self.setMode(value.mode, v);
},
.modify_key_format => try self.setModifyKeyFormat(value),
}
}
@ -450,10 +451,7 @@ pub const StreamHandler = struct {
pub fn setModifyKeyFormat(self: *StreamHandler, format: terminal.ModifyKeyFormat) !void {
self.terminal.flags.modify_other_keys_2 = false;
switch (format) {
.other_keys => |v| switch (v) {
.numeric => self.terminal.flags.modify_other_keys_2 = true,
else => {},
},
.other_keys_numeric => self.terminal.flags.modify_other_keys_2 = true,
else => {},
}
}