terminal: implement CSI = u for setting kitty keyboard flags

This commit is contained in:
Mitchell Hashimoto
2023-08-15 21:50:24 -07:00
parent a9d7e0eb7f
commit af4ede40f1
3 changed files with 84 additions and 1 deletions

View File

@ -19,6 +19,24 @@ pub const KeyFlagStack = struct {
return self.flags[self.idx];
}
/// Perform the "set" operation as described in the spec for
/// the CSI = u sequence.
pub fn set(
self: *KeyFlagStack,
mode: KeySetMode,
v: KeyFlags,
) void {
switch (mode) {
.set => self.flags[self.idx] = v,
.@"or" => self.flags[self.idx] = @bitCast(
self.flags[self.idx].int() | v.int(),
),
.not => self.flags[self.idx] = @bitCast(
self.flags[self.idx].int() & ~v.int(),
),
}
}
/// Push a new set of flags onto the stack. If the stack is full
/// then the oldest entry is evicted.
pub fn push(self: *KeyFlagStack, flags: KeyFlags) void {
@ -87,6 +105,9 @@ pub const KeyFlags = packed struct(u5) {
}
};
/// The possible modes for setting the key flags.
pub const KeySetMode = enum { set, @"or", not };
test "KeyFlagStack: push pop" {
const testing = std.testing;
var stack: KeyFlagStack = .{};
@ -106,3 +127,28 @@ test "KeyFlagStack: pop big number" {
stack.pop(100);
try testing.expectEqual(KeyFlags{}, stack.current());
}
test "KeyFlagStack: set" {
const testing = std.testing;
var stack: KeyFlagStack = .{};
stack.set(.set, .{ .disambiguate = true });
try testing.expectEqual(
KeyFlags{ .disambiguate = true },
stack.current(),
);
stack.set(.@"or", .{ .report_events = true });
try testing.expectEqual(
KeyFlags{
.disambiguate = true,
.report_events = true,
},
stack.current(),
);
stack.set(.not, .{ .report_events = true });
try testing.expectEqual(
KeyFlags{ .disambiguate = true },
stack.current(),
);
}

View File

@ -673,7 +673,35 @@ pub fn Stream(comptime Handler: type) type {
try self.handler.popKittyKeyboard(number);
},
'=' => @panic("TODO! DO NOT MERGE"),
'=' => if (@hasDecl(T, "setKittyKeyboard")) set: {
const flags: u5 = if (action.params.len >= 1)
std.math.cast(u5, action.params[0]) orelse {
log.warn("invalid setKittyKeyboard command: {}", .{action});
break :set;
}
else
0;
const number: u16 = if (action.params.len >= 2)
action.params[1]
else
1;
const mode: kitty.KeySetMode = switch (number) {
0 => .set,
1 => .@"or",
2 => .not,
else => {
log.warn("invalid setKittyKeyboard command: {}", .{action});
break :set;
},
};
try self.handler.setKittyKeyboard(
mode,
@bitCast(flags),
);
},
else => log.warn(
"unknown CSI s with intermediate: {}",

View File

@ -1435,6 +1435,15 @@ const StreamHandler = struct {
self.terminal.screen.kitty_keyboard.pop(@intCast(n));
}
pub fn setKittyKeyboard(
self: *StreamHandler,
mode: terminal.kitty.KeySetMode,
flags: terminal.kitty.KeyFlags,
) !void {
// log.debug("setting kitty keyboard mode: {} {}", .{mode, flags});
self.terminal.screen.kitty_keyboard.set(mode, flags);
}
//-------------------------------------------------------------------------
// OSC