feat(cli): add setting to hide shortcuts hint UI (#18562)

This commit is contained in:
Dmitry Lyalin
2026-02-10 21:46:20 -05:00
committed by GitHub
parent 9c11ff2d58
commit 7a02d7261a
9 changed files with 87 additions and 2 deletions
+2 -1
View File
@@ -131,7 +131,8 @@ available combinations.
- `!` on an empty prompt: Enter or exit shell mode. - `!` on an empty prompt: Enter or exit shell mode.
- `?` on an empty prompt: Toggle the shortcuts panel above the input. Press - `?` on an empty prompt: Toggle the shortcuts panel above the input. Press
`Esc`, `Backspace`, or any printable key to close it. Press `?` again to close `Esc`, `Backspace`, or any printable key to close it. Press `?` again to close
the panel and insert a `?` into the prompt. the panel and insert a `?` into the prompt. You can hide only the hint text
via `ui.showShortcutsHint`, without changing this keyboard behavior.
- `\` (at end of a line) + `Enter`: Insert a newline without leaving single-line - `\` (at end of a line) + `Enter`: Insert a newline without leaving single-line
mode. mode.
- `Esc` pressed twice quickly: Clear the input prompt if it is not empty, - `Esc` pressed twice quickly: Clear the input prompt if it is not empty,
+1
View File
@@ -49,6 +49,7 @@ they appear in the UI.
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` | | Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` | | Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` | | Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` | | Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` | | Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` | | Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
+4
View File
@@ -220,6 +220,10 @@ their corresponding top-level category object in your `settings.json` file.
- **Description:** Hide helpful tips in the UI - **Description:** Hide helpful tips in the UI
- **Default:** `false` - **Default:** `false`
- **`ui.showShortcutsHint`** (boolean):
- **Description:** Show the "? for shortcuts" hint above the input.
- **Default:** `true`
- **`ui.hideBanner`** (boolean): - **`ui.hideBanner`** (boolean):
- **Description:** Hide the application banner - **Description:** Hide the application banner
- **Default:** `false` - **Default:** `false`
@@ -186,6 +186,9 @@ describe('SettingsSchema', () => {
expect(getSettingsSchema().ui.properties.hideTips.showInDialog).toBe( expect(getSettingsSchema().ui.properties.hideTips.showInDialog).toBe(
true, true,
); );
expect(
getSettingsSchema().ui.properties.showShortcutsHint.showInDialog,
).toBe(true);
expect(getSettingsSchema().ui.properties.hideBanner.showInDialog).toBe( expect(getSettingsSchema().ui.properties.hideBanner.showInDialog).toBe(
true, true,
); );
@@ -328,6 +331,28 @@ describe('SettingsSchema', () => {
).toBe('Enable debug logging of keystrokes to the console.'); ).toBe('Enable debug logging of keystrokes to the console.');
}); });
it('should have showShortcutsHint setting in schema', () => {
expect(getSettingsSchema().ui.properties.showShortcutsHint).toBeDefined();
expect(getSettingsSchema().ui.properties.showShortcutsHint.type).toBe(
'boolean',
);
expect(getSettingsSchema().ui.properties.showShortcutsHint.category).toBe(
'UI',
);
expect(getSettingsSchema().ui.properties.showShortcutsHint.default).toBe(
true,
);
expect(
getSettingsSchema().ui.properties.showShortcutsHint.requiresRestart,
).toBe(false);
expect(
getSettingsSchema().ui.properties.showShortcutsHint.showInDialog,
).toBe(true);
expect(
getSettingsSchema().ui.properties.showShortcutsHint.description,
).toBe('Show the "? for shortcuts" hint above the input.');
});
it('should have enableAgents setting in schema', () => { it('should have enableAgents setting in schema', () => {
const setting = getSettingsSchema().experimental.properties.enableAgents; const setting = getSettingsSchema().experimental.properties.enableAgents;
expect(setting).toBeDefined(); expect(setting).toBeDefined();
@@ -462,6 +462,15 @@ const SETTINGS_SCHEMA = {
description: 'Hide helpful tips in the UI', description: 'Hide helpful tips in the UI',
showInDialog: true, showInDialog: true,
}, },
showShortcutsHint: {
type: 'boolean',
label: 'Show Shortcuts Hint',
category: 'UI',
requiresRestart: false,
default: true,
description: 'Show the "? for shortcuts" hint above the input.',
showInDialog: true,
},
hideBanner: { hideBanner: {
type: 'boolean', type: 'boolean',
label: 'Hide Banner', label: 'Hide Banner',
@@ -650,6 +650,19 @@ describe('Composer', () => {
}); });
describe('Shortcuts Hint', () => { describe('Shortcuts Hint', () => {
it('hides shortcuts hint when showShortcutsHint setting is false', () => {
const uiState = createMockUIState();
const settings = createMockSettings({
ui: {
showShortcutsHint: false,
},
});
const { lastFrame } = renderComposer(uiState, settings);
expect(lastFrame()).not.toContain('ShortcutsHint');
});
it('hides shortcuts hint when a action is required (e.g. dialog is open)', () => { it('hides shortcuts hint when a action is required (e.g. dialog is open)', () => {
const uiState = createMockUIState({ const uiState = createMockUIState({
customDialog: ( customDialog: (
+2 -1
View File
@@ -133,7 +133,8 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
flexDirection="column" flexDirection="column"
alignItems={isNarrow ? 'flex-start' : 'flex-end'} alignItems={isNarrow ? 'flex-start' : 'flex-end'}
> >
{!hasPendingActionRequired && <ShortcutsHint />} {settings.merged.ui.showShortcutsHint &&
!hasPendingActionRequired && <ShortcutsHint />}
</Box> </Box>
</Box> </Box>
{uiState.shortcutsHelpVisible && <ShortcutsHelp />} {uiState.shortcutsHelpVisible && <ShortcutsHelp />}
@@ -4296,6 +4296,30 @@ describe('InputPrompt', () => {
}); });
describe('shortcuts help visibility', () => { describe('shortcuts help visibility', () => {
it('opens shortcuts help with ? on empty prompt even when showShortcutsHint is false', async () => {
const setShortcutsHelpVisible = vi.fn();
const settings = createMockSettings({
ui: { showShortcutsHint: false },
});
const { stdin, unmount } = renderWithProviders(
<InputPrompt {...props} />,
{
settings,
uiActions: { setShortcutsHelpVisible },
},
);
await act(async () => {
stdin.write('?');
});
await waitFor(() => {
expect(setShortcutsHelpVisible).toHaveBeenCalledWith(true);
});
unmount();
});
it.each([ it.each([
{ {
name: 'terminal paste event occurs', name: 'terminal paste event occurs',
+7
View File
@@ -245,6 +245,13 @@
"default": false, "default": false,
"type": "boolean" "type": "boolean"
}, },
"showShortcutsHint": {
"title": "Show Shortcuts Hint",
"description": "Show the \"? for shortcuts\" hint above the input.",
"markdownDescription": "Show the \"? for shortcuts\" hint above the input.\n\n- Category: `UI`\n- Requires restart: `no`\n- Default: `true`",
"default": true,
"type": "boolean"
},
"hideBanner": { "hideBanner": {
"title": "Hide Banner", "title": "Hide Banner",
"description": "Hide the application banner", "description": "Hide the application banner",