From 0dea7233b65b480466e4da62db9127205b57a6d0 Mon Sep 17 00:00:00 2001
From: fuyou <imshuazi@126.com>
Date: Sun, 10 Aug 2025 06:26:43 +0800
Subject: feat(cli) - enhance input UX with double ESC clear (#4453)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
---
 .../cli/src/ui/components/InputPrompt.test.tsx     | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)

(limited to 'packages/cli/src/ui/components/InputPrompt.test.tsx')

diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx
index f050ba07..a29a095a 100644
--- a/packages/cli/src/ui/components/InputPrompt.test.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.test.tsx
@@ -1191,6 +1191,106 @@ describe('InputPrompt', () => {
     });
   });
 
+  describe('enhanced input UX - double ESC clear functionality', () => {
+    it('should clear buffer on second ESC press', async () => {
+      const onEscapePromptChange = vi.fn();
+      props.onEscapePromptChange = onEscapePromptChange;
+      props.buffer.setText('text to clear');
+
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      expect(props.buffer.setText).toHaveBeenCalledWith('');
+      expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
+      unmount();
+    });
+
+    it('should reset escape state on any non-ESC key', async () => {
+      const onEscapePromptChange = vi.fn();
+      props.onEscapePromptChange = onEscapePromptChange;
+      props.buffer.setText('some text');
+
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      expect(onEscapePromptChange).toHaveBeenCalledWith(true);
+
+      stdin.write('a');
+      await wait();
+
+      expect(onEscapePromptChange).toHaveBeenCalledWith(false);
+      unmount();
+    });
+
+    it('should handle ESC in shell mode by disabling shell mode', async () => {
+      props.shellModeActive = true;
+
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      expect(props.setShellModeActive).toHaveBeenCalledWith(false);
+      unmount();
+    });
+
+    it('should handle ESC when completion suggestions are showing', async () => {
+      mockedUseCommandCompletion.mockReturnValue({
+        ...mockCommandCompletion,
+        showSuggestions: true,
+        suggestions: [{ label: 'suggestion', value: 'suggestion' }],
+      });
+
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
+      unmount();
+    });
+
+    it('should not call onEscapePromptChange when not provided', async () => {
+      props.onEscapePromptChange = undefined;
+      props.buffer.setText('some text');
+
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x1B');
+      await wait();
+
+      unmount();
+    });
+
+    it('should not interfere with existing keyboard shortcuts', async () => {
+      const { stdin, unmount } = render(<InputPrompt {...props} />);
+      await wait();
+
+      stdin.write('\x0C');
+      await wait();
+
+      expect(props.onClearScreen).toHaveBeenCalled();
+
+      stdin.write('\x01');
+      await wait();
+
+      expect(props.buffer.move).toHaveBeenCalledWith('home');
+      unmount();
+    });
+  });
+
   describe('reverse search', () => {
     beforeEach(async () => {
       props.shellModeActive = true;
-- 
cgit v1.2.3

