fix: input keyboard shortcuts (#676)
Fixes keyboard shortcuts: - ctrl+a/e - opt+arrow keys
This commit is contained in:
@@ -106,11 +106,16 @@ export default function TerminalChatInputThinking({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" gap={1}>
|
<Box flexDirection="column" gap={1}>
|
||||||
<Box gap={2}>
|
<Box justifyContent="space-between">
|
||||||
<Text>{frameWithSeconds}</Text>
|
<Box gap={2}>
|
||||||
|
<Text>{frameWithSeconds}</Text>
|
||||||
|
<Text>
|
||||||
|
Thinking
|
||||||
|
{dots}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
<Text>
|
<Text>
|
||||||
Thinking
|
Press <Text bold>Esc</Text> twice to interrupt
|
||||||
{dots}
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
{awaitingConfirm && (
|
{awaitingConfirm && (
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ export default function TerminalChatInput({
|
|||||||
setInput("");
|
setInput("");
|
||||||
openApprovalOverlay();
|
openApprovalOverlay();
|
||||||
return;
|
return;
|
||||||
} else if (inputValue === "exit") {
|
} else if (["exit", "q", ":q"].includes(inputValue)) {
|
||||||
setInput("");
|
setInput("");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
app.exit();
|
app.exit();
|
||||||
@@ -881,20 +881,30 @@ function TerminalChatInputThinking({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" gap={1}>
|
<Box width="100%" flexDirection="column" gap={1}>
|
||||||
<Box gap={2}>
|
<Box
|
||||||
<Text>{frameWithSeconds}</Text>
|
flexDirection="row"
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
paddingRight={1}
|
||||||
|
>
|
||||||
|
<Box gap={2}>
|
||||||
|
<Text>{frameWithSeconds}</Text>
|
||||||
|
<Text>
|
||||||
|
Thinking
|
||||||
|
{dots}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
<Text>
|
<Text>
|
||||||
Thinking
|
<Text dimColor>press</Text> <Text bold>Esc</Text>{" "}
|
||||||
{dots}
|
{awaitingConfirm ? (
|
||||||
|
<Text bold>again</Text>
|
||||||
|
) : (
|
||||||
|
<Text dimColor>twice</Text>
|
||||||
|
)}{" "}
|
||||||
|
<Text dimColor>to interrupt</Text>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
{awaitingConfirm && (
|
|
||||||
<Text dimColor>
|
|
||||||
Press <Text bold>Esc</Text> again to interrupt and enter a new
|
|
||||||
instruction
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const TerminalHeader: React.FC<TerminalHeaderProps> = ({
|
|||||||
</Text>
|
</Text>
|
||||||
<Text dimColor>
|
<Text dimColor>
|
||||||
<Text color="blueBright">↳</Text> approval:{" "}
|
<Text color="blueBright">↳</Text> approval:{" "}
|
||||||
<Text bold color={colorsByPolicy[approvalPolicy]} dimColor>
|
<Text bold color={colorsByPolicy[approvalPolicy]}>
|
||||||
{approvalPolicy}
|
{approvalPolicy}
|
||||||
</Text>
|
</Text>
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -610,6 +610,24 @@ export default class TextBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
* Document-level navigation helpers
|
||||||
|
* ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/** Move caret to *absolute* beginning of the buffer (row-0, col-0). */
|
||||||
|
private moveToStartOfDocument(): void {
|
||||||
|
this.preferredCol = null;
|
||||||
|
this.cursorRow = 0;
|
||||||
|
this.cursorCol = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Move caret to *absolute* end of the buffer (last row, last column). */
|
||||||
|
private moveToEndOfDocument(): void {
|
||||||
|
this.preferredCol = null;
|
||||||
|
this.cursorRow = this.lines.length - 1;
|
||||||
|
this.cursorCol = this.lineLen(this.cursorRow);
|
||||||
|
}
|
||||||
|
|
||||||
/* =====================================================================
|
/* =====================================================================
|
||||||
* Higher‑level helpers
|
* Higher‑level helpers
|
||||||
* =================================================================== */
|
* =================================================================== */
|
||||||
@@ -780,6 +798,18 @@ export default class TextBuffer {
|
|||||||
key["rightArrow"]
|
key["rightArrow"]
|
||||||
) {
|
) {
|
||||||
this.move("wordRight");
|
this.move("wordRight");
|
||||||
|
}
|
||||||
|
// Many terminal/OS combinations (e.g. macOS Terminal.app & iTerm2 with
|
||||||
|
// the default key-bindings) translate ⌥← / ⌥→ into the classic readline
|
||||||
|
// shortcuts ESC-b / ESC-f rather than an ANSI arrow sequence that Ink
|
||||||
|
// would tag with `leftArrow` / `rightArrow`. Ink parses those 2-byte
|
||||||
|
// escape sequences into `input === "b"|"f"` with `key.meta === true`.
|
||||||
|
// Handle this variant explicitly so that Option+Arrow performs word
|
||||||
|
// navigation consistently across environments.
|
||||||
|
else if (key["meta"] && (input === "b" || input === "B")) {
|
||||||
|
this.move("wordLeft");
|
||||||
|
} else if (key["meta"] && (input === "f" || input === "F")) {
|
||||||
|
this.move("wordRight");
|
||||||
} else if (key["home"]) {
|
} else if (key["home"]) {
|
||||||
this.move("home");
|
this.move("home");
|
||||||
} else if (key["end"]) {
|
} else if (key["end"]) {
|
||||||
@@ -823,11 +853,11 @@ export default class TextBuffer {
|
|||||||
|
|
||||||
// Emacs/readline-style shortcuts
|
// Emacs/readline-style shortcuts
|
||||||
else if (key["ctrl"] && (input === "a" || input === "\x01")) {
|
else if (key["ctrl"] && (input === "a" || input === "\x01")) {
|
||||||
// Ctrl+A or ⌥← → start of line
|
// Ctrl+A → start of input (first row, first column)
|
||||||
this.move("home");
|
this.moveToStartOfDocument();
|
||||||
} else if (key["ctrl"] && (input === "e" || input === "\x05")) {
|
} else if (key["ctrl"] && (input === "e" || input === "\x05")) {
|
||||||
// Ctrl+E or ⌥→ → end of line
|
// Ctrl+E → end of input (last row, last column)
|
||||||
this.move("end");
|
this.moveToEndOfDocument();
|
||||||
} else if (key["ctrl"] && (input === "b" || input === "\x02")) {
|
} else if (key["ctrl"] && (input === "b" || input === "\x02")) {
|
||||||
// Ctrl+B → char left
|
// Ctrl+B → char left
|
||||||
this.move("left");
|
this.move("left");
|
||||||
|
|||||||
Reference in New Issue
Block a user