mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
fix(cli): allow scrolling keys in copy mode (Ctrl+S selection mode) (#19933)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
@@ -2770,7 +2770,7 @@ describe('AppContainer State Management', () => {
|
|||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exit copy mode on any key press', async () => {
|
it('should exit copy mode on non-scroll key press', async () => {
|
||||||
await setupCopyModeTest(isAlternateMode);
|
await setupCopyModeTest(isAlternateMode);
|
||||||
|
|
||||||
// Enter copy mode
|
// Enter copy mode
|
||||||
@@ -2792,6 +2792,61 @@ describe('AppContainer State Management', () => {
|
|||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not exit copy mode on PageDown and should pass it through', async () => {
|
||||||
|
const childHandler = vi.fn().mockReturnValue(false);
|
||||||
|
await setupCopyModeTest(true, childHandler);
|
||||||
|
|
||||||
|
// Enter copy mode
|
||||||
|
act(() => {
|
||||||
|
stdin.write('\x13'); // Ctrl+S
|
||||||
|
});
|
||||||
|
rerender();
|
||||||
|
expect(disableMouseEvents).toHaveBeenCalled();
|
||||||
|
|
||||||
|
childHandler.mockClear();
|
||||||
|
(enableMouseEvents as Mock).mockClear();
|
||||||
|
|
||||||
|
// PageDown should be passed through to lower-priority handlers.
|
||||||
|
act(() => {
|
||||||
|
stdin.write('\x1b[6~');
|
||||||
|
});
|
||||||
|
rerender();
|
||||||
|
|
||||||
|
expect(enableMouseEvents).not.toHaveBeenCalled();
|
||||||
|
expect(childHandler).toHaveBeenCalled();
|
||||||
|
expect(childHandler).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ name: 'pagedown' }),
|
||||||
|
);
|
||||||
|
unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not exit copy mode on Shift+Down and should pass it through', async () => {
|
||||||
|
const childHandler = vi.fn().mockReturnValue(false);
|
||||||
|
await setupCopyModeTest(true, childHandler);
|
||||||
|
|
||||||
|
// Enter copy mode
|
||||||
|
act(() => {
|
||||||
|
stdin.write('\x13'); // Ctrl+S
|
||||||
|
});
|
||||||
|
rerender();
|
||||||
|
expect(disableMouseEvents).toHaveBeenCalled();
|
||||||
|
|
||||||
|
childHandler.mockClear();
|
||||||
|
(enableMouseEvents as Mock).mockClear();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
stdin.write('\x1b[1;2B'); // Shift+Down
|
||||||
|
});
|
||||||
|
rerender();
|
||||||
|
|
||||||
|
expect(enableMouseEvents).not.toHaveBeenCalled();
|
||||||
|
expect(childHandler).toHaveBeenCalled();
|
||||||
|
expect(childHandler).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ name: 'down', shift: true }),
|
||||||
|
);
|
||||||
|
unmount();
|
||||||
|
});
|
||||||
|
|
||||||
it('should have higher priority than other priority listeners when enabled', async () => {
|
it('should have higher priority than other priority listeners when enabled', async () => {
|
||||||
// 1. Initial state with a child component's priority listener (already subscribed)
|
// 1. Initial state with a child component's priority listener (already subscribed)
|
||||||
// It should NOT handle Ctrl+S so we can enter copy mode.
|
// It should NOT handle Ctrl+S so we can enter copy mode.
|
||||||
|
|||||||
@@ -1864,7 +1864,18 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
|||||||
useKeypress(handleGlobalKeypress, { isActive: true, priority: true });
|
useKeypress(handleGlobalKeypress, { isActive: true, priority: true });
|
||||||
|
|
||||||
useKeypress(
|
useKeypress(
|
||||||
() => {
|
(key: Key) => {
|
||||||
|
if (
|
||||||
|
keyMatchers[Command.SCROLL_UP](key) ||
|
||||||
|
keyMatchers[Command.SCROLL_DOWN](key) ||
|
||||||
|
keyMatchers[Command.PAGE_UP](key) ||
|
||||||
|
keyMatchers[Command.PAGE_DOWN](key) ||
|
||||||
|
keyMatchers[Command.SCROLL_HOME](key) ||
|
||||||
|
keyMatchers[Command.SCROLL_END](key)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
setCopyModeEnabled(false);
|
setCopyModeEnabled(false);
|
||||||
enableMouseEvents();
|
enableMouseEvents();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ describe('CopyModeWarning', () => {
|
|||||||
const { lastFrame, waitUntilReady, unmount } = render(<CopyModeWarning />);
|
const { lastFrame, waitUntilReady, unmount } = render(<CopyModeWarning />);
|
||||||
await waitUntilReady();
|
await waitUntilReady();
|
||||||
expect(lastFrame()).toContain('In Copy Mode');
|
expect(lastFrame()).toContain('In Copy Mode');
|
||||||
expect(lastFrame()).toContain('Press any key to exit');
|
expect(lastFrame()).toContain('Use Page Up/Down to scroll');
|
||||||
|
expect(lastFrame()).toContain('Press Ctrl+S or any other key to exit');
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export const CopyModeWarning: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Text color={theme.status.warning}>
|
<Text color={theme.status.warning}>
|
||||||
In Copy Mode. Press any key to exit.
|
In Copy Mode. Use Page Up/Down to scroll. Press Ctrl+S or any other key
|
||||||
|
to exit.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user