Merge pull request #4482 from Felixoid/fix-wezterm-kitty-esc
Address edge-case with kitty protocol in wezterm
This commit is contained in:
@@ -205,6 +205,29 @@ function extractCompleteSequences(buffer: string): { sequences: string[]; remain
|
|||||||
const status = isCompleteSequence(candidate);
|
const status = isCompleteSequence(candidate);
|
||||||
|
|
||||||
if (status === "complete") {
|
if (status === "complete") {
|
||||||
|
// WezTerm with enable_kitty_keyboard sends the Escape key press as a
|
||||||
|
// raw '\x1b' byte (simple text path in encode_kitty, ignoring
|
||||||
|
// DISAMBIGUATE_ESCAPE_CODES) and the release as a full Kitty CSI-u
|
||||||
|
// sequence. These arrive concatenated as '\x1b\x1b[27;...u'.
|
||||||
|
// The buffer would normally treat '\x1b\x1b' as a complete meta-key
|
||||||
|
// sequence (ESC + single char), leaving '[27;...u' to be typed as
|
||||||
|
// plain text. If the character immediately following '\x1b\x1b'
|
||||||
|
// would begin a new escape sequence, emit only the first ESC and
|
||||||
|
// restart from the second.
|
||||||
|
if (candidate === "\x1b\x1b") {
|
||||||
|
const nextChar = remaining[seqEnd];
|
||||||
|
if (
|
||||||
|
nextChar === "[" || // CSI
|
||||||
|
nextChar === "]" || // OSC
|
||||||
|
nextChar === "O" || // SS3
|
||||||
|
nextChar === "P" || // DCS
|
||||||
|
nextChar === "_" // APC
|
||||||
|
) {
|
||||||
|
sequences.push(ESC);
|
||||||
|
pos += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
sequences.push(candidate);
|
sequences.push(candidate);
|
||||||
pos += seqEnd;
|
pos += seqEnd;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -198,6 +198,26 @@ describe("StdinBuffer", () => {
|
|||||||
assert.deepStrictEqual(emittedSequences, ["\x1b[3;1:3~"]);
|
assert.deepStrictEqual(emittedSequences, ["\x1b[3;1:3~"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should split ESC+ESC+CSI into standalone ESC and the CSI sequence (WezTerm Escape key regression)", () => {
|
||||||
|
// WezTerm with enable_kitty_keyboard sends Escape key press as raw \x1b
|
||||||
|
// and the release as a full Kitty CSI-u sequence, concatenated.
|
||||||
|
// The buffer must not treat \x1b\x1b as a complete meta-key when the
|
||||||
|
// following byte starts a new escape sequence.
|
||||||
|
processInput("\x1b\x1b[27;129:3u");
|
||||||
|
assert.deepStrictEqual(emittedSequences, ["\x1b", "\x1b[27;129:3u"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should split ESC+ESC+CSI with no modifier (no num_lock)", () => {
|
||||||
|
processInput("\x1b\x1b[27;1:3u");
|
||||||
|
assert.deepStrictEqual(emittedSequences, ["\x1b", "\x1b[27;1:3u"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should still emit ESC+ESC as a single sequence when not followed by a new escape", () => {
|
||||||
|
// \x1b\x1b alone (no following CSI) stays as-is — e.g. ctrl+alt+[
|
||||||
|
processInput("\x1b\x1b");
|
||||||
|
assert.deepStrictEqual(emittedSequences, ["\x1b\x1b"]);
|
||||||
|
});
|
||||||
|
|
||||||
it("should handle plain characters mixed with Kitty sequences", () => {
|
it("should handle plain characters mixed with Kitty sequences", () => {
|
||||||
// Plain 'a' followed by Kitty release
|
// Plain 'a' followed by Kitty release
|
||||||
processInput("a\x1b[97;1:3u");
|
processInput("a\x1b[97;1:3u");
|
||||||
|
|||||||
Reference in New Issue
Block a user