Merge pull request #1267 from mitchellh/keypad

input: manage application keypad state with mode 1035
This commit is contained in:
Mitchell Hashimoto
2024-01-09 12:07:25 -08:00
committed by GitHub
4 changed files with 89 additions and 1 deletions

View File

@ -1322,6 +1322,7 @@ pub fn keyCallback(
.alt_esc_prefix = t.modes.get(.alt_esc_prefix),
.cursor_key_application = t.modes.get(.cursor_keys),
.keypad_key_application = t.modes.get(.keypad_keys),
.ignore_keypad_with_numlock = t.modes.get(.ignore_keypad_with_numlock),
.modify_other_keys_state_2 = t.flags.modify_other_keys_2,
.kitty_flags = t.screen.kitty_keyboard.current(),
};

View File

@ -26,6 +26,7 @@ macos_option_as_alt: config.OptionAsAlt = .false,
alt_esc_prefix: bool = false,
cursor_key_application: bool = false,
keypad_key_application: bool = false,
ignore_keypad_with_numlock: bool = false,
modify_other_keys_state_2: bool = false,
kitty_flags: KittyFlags = .{},
@ -245,6 +246,7 @@ fn legacy(
all_mods,
self.cursor_key_application,
self.keypad_key_application,
self.ignore_keypad_with_numlock,
self.modify_other_keys_state_2,
)) |sequence| pc_style: {
// If we're pressing enter and have UTF-8 text, we probably are
@ -416,7 +418,8 @@ fn pcStyleFunctionKey(
keyval: key.Key,
mods: key.Mods,
cursor_key_application: bool,
keypad_key_application: bool,
keypad_key_application_req: bool,
ignore_keypad_with_numlock: bool,
modify_other_keys: bool, // True if state 2
) ?[]const u8 {
// We only want binding-sensitive mods because lock keys
@ -424,6 +427,24 @@ fn pcStyleFunctionKey(
// pc-style function keys.
const mods_int = mods.binding().int();
// Keypad application keymode isn't super straightforward.
// On xterm, in VT220 mode, numlock alone is enough to trigger
// application mode. But in more modern modes, numlock is
// ignored by default via mode 1035 (default true). If mode
// 1035 is on, we always are in numerical keypad mode. If
// mode 1035 is off, we are in application mode if the
// proper numlock state is pressed. The numlock state is implicitly
// determined based on the keycode sent (i.e. 1 with numlock
// on will be kp_end).
const keypad_key_application = keypad: {
// If we're ignoring keypad then this is always false.
// In other words, we're always in numerical keypad mode.
if (ignore_keypad_with_numlock) break :keypad false;
// If we're not ignoring then we enable the desired state.
break :keypad keypad_key_application_req;
};
for (function_keys.keys.get(keyval)) |entry| {
switch (entry.cursor) {
.any => {},
@ -1677,6 +1698,70 @@ test "legacy: keypad enter" {
try testing.expectEqualStrings("\r", actual);
}
test "legacy: keypad 1" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.mods = .{},
.consumed_mods = .{},
.utf8 = "1",
},
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("1", actual);
}
test "legacy: keypad 1 with application keypad" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.mods = .{},
.consumed_mods = .{},
.utf8 = "1",
},
.keypad_key_application = true,
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("\x1bOq", actual);
}
test "legacy: keypad 1 with application keypad and numlock" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.mods = .{ .num_lock = true },
.consumed_mods = .{},
.utf8 = "1",
},
.keypad_key_application = true,
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("\x1bOq", actual);
}
test "legacy: keypad 1 with application keypad and numlock ignore" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.mods = .{ .num_lock = false },
.consumed_mods = .{},
.utf8 = "1",
},
.keypad_key_application = true,
.ignore_keypad_with_numlock = true,
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("1", actual);
}
test "legacy: f1" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{

View File

@ -121,6 +121,7 @@ pub const keys = keys: {
result.set(.kp_down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
result.set(.kp_right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
result.set(.kp_left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
result.set(.kp_begin, pcStyle("\x1b[1;{}E") ++ cursorKey("\x1b[E", "\x1bOE"));
result.set(.kp_home, pcStyle("\x1b[1;{}H") ++ cursorKey("\x1b[H", "\x1bOH"));
result.set(.kp_end, pcStyle("\x1b[1;{}F") ++ cursorKey("\x1b[F", "\x1bOF"));
result.set(.kp_insert, pcStyle("\x1b[2;{}~") ++ .{.{ .sequence = "\x1B[2~" }});

View File

@ -206,6 +206,7 @@ const entries: []const ModeEntry = &.{
.{ .name = "mouse_alternate_scroll", .value = 1007, .default = true },
.{ .name = "mouse_format_urxvt", .value = 1015 },
.{ .name = "mouse_format_sgr_pixels", .value = 1016 },
.{ .name = "ignore_keypad_with_numlock", .value = 1035, .default = true },
.{ .name = "alt_esc_prefix", .value = 1036, .default = true },
.{ .name = "alt_sends_escape", .value = 1039 },
.{ .name = "reverse_wrap_extended", .value = 1045 },