From aec6c0861e8244cdaefda14840844e922705c8fa Mon Sep 17 00:00:00 2001
From: DeWitt Clinton <dclinton@gmail.com>
Date: Wed, 14 May 2025 17:33:37 -0700
Subject: Add readline-like keybindings to the input prompts. (#354)

New keybindings in the main input prompt (when auto-suggestions are not active):

  - `Ctrl+L`: Clears the entire screen.
  - `Ctrl+A`: Moves the cursor to the beginning of the current input line.
  - `Ctrl+E`: Moves the cursor to the end of the current input line.
  - `Ctrl+P`: Navigates to the previous command in the input history.
  - `Ctrl+N`: Navigates to the next command in the input history.

In the multiline text editor (e.g., when editing a previous message):
   - `Ctrl+K`: Deletes text from the current cursor position to the end of the line ("kill line right").
---
 .../src/ui/components/shared/multiline-editor.tsx  | 26 ++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

(limited to 'packages/cli/src/ui/components/shared/multiline-editor.tsx')

diff --git a/packages/cli/src/ui/components/shared/multiline-editor.tsx b/packages/cli/src/ui/components/shared/multiline-editor.tsx
index bd49efcb..e1e21fff 100644
--- a/packages/cli/src/ui/components/shared/multiline-editor.tsx
+++ b/packages/cli/src/ui/components/shared/multiline-editor.tsx
@@ -43,7 +43,12 @@ export interface MultilineTextEditorProps {
 
   // Called on all key events to allow the caller. Returns true if the
   // event was handled and should not be passed to the editor.
-  readonly inputPreprocessor?: (input: string, key: Key) => boolean;
+  readonly inputPreprocessor?: (
+    input: string,
+    key: Key,
+    currentText: string,
+    cursorOffset: number,
+  ) => boolean;
 
   // Optional initial cursor position (character offset)
   readonly initialCursorOffset?: number;
@@ -92,7 +97,24 @@ export const MultilineTextEditor = ({
         return;
       }
 
-      if (inputPreprocessor?.(input, key) === true) {
+      // Calculate cursorOffset for inputPreprocessor
+      let charOffset = 0;
+      for (let i = 0; i < buffer.cursor[0]; i++) {
+        charOffset += buffer.lines[i].length + 1; // +1 for newline
+      }
+      charOffset += buffer.cursor[1];
+
+      if (inputPreprocessor?.(input, key, buffer.text, charOffset) === true) {
+        return;
+      }
+
+      if (key.ctrl && input === 'k') {
+        buffer.killLineRight();
+        return;
+      }
+
+      if (key.ctrl && input === 'u') {
+        buffer.killLineLeft();
         return;
       }
 
-- 
cgit v1.2.3

