diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index c298c4b9b..dd3443ed7 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -480,6 +480,13 @@ pub const Surface = struct { // If we aren't composing, then we set our preedit to // empty no matter what. self.core_surface.preeditCallback(null) catch {}; + + // If the text is just a single non-printable ASCII character + // then we clear the text. We handle non-printables in the + // key encoder manual (such as tab, ctrl+c, etc.) + if (result.text.len == 1 and result.text[0] < 0x20) { + break :translate .{ .composing = false, .text = "" }; + } } break :translate result; diff --git a/src/input/KeyEncoder.zig b/src/input/KeyEncoder.zig index bff47bb80..0bcb198fa 100644 --- a/src/input/KeyEncoder.zig +++ b/src/input/KeyEncoder.zig @@ -15,6 +15,8 @@ const KittyEntry = @import("kitty.zig").Entry; const kitty_entries = @import("kitty.zig").entries; const KittyFlags = terminal.kitty.KeyFlags; +const log = std.log.scoped(.key_encoder); + event: key.KeyEvent, /// The state of various modes of a terminal that impact encoding. @@ -29,6 +31,8 @@ pub fn encode( self: *const KeyEncoder, buf: []u8, ) ![]const u8 { + // log.debug("encode {}", .{self.*}); + if (self.kitty_flags.int() != 0) return try self.kitty(buf); return try self.legacy(buf); } @@ -863,6 +867,22 @@ test "kitty: up arrow with utf8" { try testing.expectEqualStrings("\x1b[A", actual); } +test "kitty: shift+tab" { + var buf: [128]u8 = undefined; + var enc: KeyEncoder = .{ + .event = .{ + .key = .tab, + .mods = .{ .shift = true }, + .utf8 = "", // tab + }, + + .kitty_flags = .{ .disambiguate = true, .report_alternates = true }, + }; + + const actual = try enc.kitty(&buf); + try testing.expectEqualStrings("\x1b[9;2u", actual); +} + test "legacy: ctrl+alt+c" { var buf: [128]u8 = undefined; var enc: KeyEncoder = .{