fix(tui): honor tui.input.submit remap onto ctrl+enter
The multiline editor's key dispatch checked a hardcoded Ctrl/Shift+Enter -> newline branch before the config-driven tui.input.submit branch, so a user remap of submit onto Ctrl+Enter was swallowed as a newline and never submitted. Gate the hardcoded newline fallbacks behind an explicit submit binding; the bare-LF (iTerm2 Shift+Enter) case stays exempt because its canonical form is indistinguishable from plain Enter. Fixes #8906
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
### Fixed
|
||||
|
||||
- Fixed images rendering as the `[Image: …]` text card on SIXEL terminals that expose no identifying environment variable (foot, xterm, contour): the graphics probe no longer requires Windows Terminal, and no longer reads an XTSMGRAPHICS success reply as a failure.
|
||||
- Fixed the multiline editor ignoring a `tui.input.submit` remap onto Ctrl+Enter: the hardcoded Ctrl/Shift+Enter → newline fallbacks now yield to an explicit submit binding, so Ctrl+Enter can be used to submit ([#8906](https://github.com/can1357/oh-my-pi/issues/8906)).
|
||||
|
||||
## [17.3.5] - 2026-08-16
|
||||
|
||||
|
||||
@@ -1458,14 +1458,19 @@ export class Editor implements Component, Focusable {
|
||||
this.#addNewLine();
|
||||
}
|
||||
}
|
||||
// New line
|
||||
// New line. A key the user explicitly bound to `tui.input.submit` wins
|
||||
// over these hardcoded newline fallbacks, so Ctrl/Shift+Enter can be
|
||||
// remapped to submit (#8906). The bare-LF case is exempt: its canonical
|
||||
// form is "enter" (indistinguishable from plain Enter), so gating it
|
||||
// would hijack the default Enter=submit binding.
|
||||
else if (
|
||||
(data.charCodeAt(0) === 10 && data.length > 1) || // Ctrl+Enter with modifiers
|
||||
matchesKey(data, "ctrl+enter") || // Ctrl+Enter (Kitty/modifyOtherKeys, including lock bits/keypad Enter)
|
||||
data === "\x1b\r" || // Option+Enter in some terminals (legacy)
|
||||
data === "\x1b[13;2~" || // Shift+Enter in some terminals (legacy format)
|
||||
kb.matchesCanonical(canonical, "tui.input.newLine") || // Shift+Enter (Kitty protocol, handles lock bits)
|
||||
(data.length > 1 && data.includes("\x1b") && data.includes("\r")) ||
|
||||
(!kb.matchesCanonical(canonical, "tui.input.submit") &&
|
||||
((data.charCodeAt(0) === 10 && data.length > 1) || // Ctrl+Enter with modifiers
|
||||
matchesKey(data, "ctrl+enter") || // Ctrl+Enter (Kitty/modifyOtherKeys, including lock bits/keypad Enter)
|
||||
data === "\x1b\r" || // Option+Enter in some terminals (legacy)
|
||||
data === "\x1b[13;2~" || // Shift+Enter in some terminals (legacy format)
|
||||
kb.matchesCanonical(canonical, "tui.input.newLine") || // Shift+Enter (Kitty protocol, handles lock bits)
|
||||
(data.length > 1 && data.includes("\x1b") && data.includes("\r")))) ||
|
||||
(data === "\n" && data.length === 1) // Shift+Enter from iTerm2 mapping
|
||||
) {
|
||||
if (this.#shouldSubmitOnBackslashEnter(data, kb)) {
|
||||
|
||||
@@ -164,6 +164,38 @@ describe("Editor component", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Submit/newline keybindings", () => {
|
||||
it("submits on Ctrl+Enter when tui.input.submit is remapped to it (#8906)", () => {
|
||||
setKeybindings(
|
||||
new KeybindingsManager(TUI_KEYBINDINGS, {
|
||||
"tui.input.submit": "ctrl+enter",
|
||||
"tui.input.newLine": "enter",
|
||||
}),
|
||||
);
|
||||
const editor = new Editor(defaultEditorTheme);
|
||||
editor.setText("hello");
|
||||
let submitted: string | undefined;
|
||||
editor.onSubmit = text => {
|
||||
submitted = text;
|
||||
};
|
||||
editor.handleInput("\x1b[13;5u"); // kitty CSI-u Ctrl+Enter
|
||||
expect(submitted).toBe("hello");
|
||||
expect(editor.getText()).toBe("");
|
||||
});
|
||||
|
||||
it("still inserts a newline on Ctrl+Enter under the default bindings", () => {
|
||||
const editor = new Editor(defaultEditorTheme);
|
||||
editor.setText("hello");
|
||||
let submitted: string | undefined;
|
||||
editor.onSubmit = text => {
|
||||
submitted = text;
|
||||
};
|
||||
editor.handleInput("\x1b[13;5u"); // kitty CSI-u Ctrl+Enter
|
||||
expect(submitted).toBeUndefined();
|
||||
expect(editor.getText()).toBe("hello\n");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Prompt history navigation", () => {
|
||||
it("does nothing on Up arrow when history is empty", () => {
|
||||
const editor = new Editor(defaultEditorTheme);
|
||||
|
||||
Reference in New Issue
Block a user