From 9c7fb870c1a7c80741fafdfc6837d4b92e373b2d Mon Sep 17 00:00:00 2001 From: Deepankar Sharma Date: Wed, 13 Aug 2025 13:32:54 -0400 Subject: Add terminal setup command for Shift+Enter and Ctrl+Enter support (#3289) Co-authored-by: jacob314 --- .../src/ui/commands/terminalSetupCommand.test.ts | 85 ++++++++++++++++++++++ .../cli/src/ui/commands/terminalSetupCommand.ts | 45 ++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 packages/cli/src/ui/commands/terminalSetupCommand.test.ts create mode 100644 packages/cli/src/ui/commands/terminalSetupCommand.ts (limited to 'packages/cli/src/ui/commands') diff --git a/packages/cli/src/ui/commands/terminalSetupCommand.test.ts b/packages/cli/src/ui/commands/terminalSetupCommand.test.ts new file mode 100644 index 00000000..85f8735e --- /dev/null +++ b/packages/cli/src/ui/commands/terminalSetupCommand.test.ts @@ -0,0 +1,85 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { terminalSetupCommand } from './terminalSetupCommand.js'; +import * as terminalSetupModule from '../utils/terminalSetup.js'; +import { CommandContext } from './types.js'; + +vi.mock('../utils/terminalSetup.js'); + +describe('terminalSetupCommand', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should have correct metadata', () => { + expect(terminalSetupCommand.name).toBe('terminal-setup'); + expect(terminalSetupCommand.description).toContain('multiline input'); + expect(terminalSetupCommand.kind).toBe('built-in'); + }); + + it('should return success message when terminal setup succeeds', async () => { + vi.spyOn(terminalSetupModule, 'terminalSetup').mockResolvedValue({ + success: true, + message: 'Terminal configured successfully', + }); + + const result = await terminalSetupCommand.action({} as CommandContext, ''); + + expect(result).toEqual({ + type: 'message', + content: 'Terminal configured successfully', + messageType: 'info', + }); + }); + + it('should append restart message when terminal setup requires restart', async () => { + vi.spyOn(terminalSetupModule, 'terminalSetup').mockResolvedValue({ + success: true, + message: 'Terminal configured successfully', + requiresRestart: true, + }); + + const result = await terminalSetupCommand.action({} as CommandContext, ''); + + expect(result).toEqual({ + type: 'message', + content: + 'Terminal configured successfully\n\nPlease restart your terminal for the changes to take effect.', + messageType: 'info', + }); + }); + + it('should return error message when terminal setup fails', async () => { + vi.spyOn(terminalSetupModule, 'terminalSetup').mockResolvedValue({ + success: false, + message: 'Failed to detect terminal', + }); + + const result = await terminalSetupCommand.action({} as CommandContext, ''); + + expect(result).toEqual({ + type: 'message', + content: 'Failed to detect terminal', + messageType: 'error', + }); + }); + + it('should handle exceptions from terminal setup', async () => { + vi.spyOn(terminalSetupModule, 'terminalSetup').mockRejectedValue( + new Error('Unexpected error'), + ); + + const result = await terminalSetupCommand.action({} as CommandContext, ''); + + expect(result).toEqual({ + type: 'message', + content: 'Failed to configure terminal: Error: Unexpected error', + messageType: 'error', + }); + }); +}); diff --git a/packages/cli/src/ui/commands/terminalSetupCommand.ts b/packages/cli/src/ui/commands/terminalSetupCommand.ts new file mode 100644 index 00000000..11520c0e --- /dev/null +++ b/packages/cli/src/ui/commands/terminalSetupCommand.ts @@ -0,0 +1,45 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { MessageActionReturn, SlashCommand, CommandKind } from './types.js'; +import { terminalSetup } from '../utils/terminalSetup.js'; + +/** + * Command to configure terminal keybindings for multiline input support. + * + * This command automatically detects and configures VS Code, Cursor, and Windsurf + * to support Shift+Enter and Ctrl+Enter for multiline input. + */ +export const terminalSetupCommand: SlashCommand = { + name: 'terminal-setup', + description: + 'Configure terminal keybindings for multiline input (VS Code, Cursor, Windsurf)', + kind: CommandKind.BUILT_IN, + + action: async (): Promise => { + try { + const result = await terminalSetup(); + + let content = result.message; + if (result.requiresRestart) { + content += + '\n\nPlease restart your terminal for the changes to take effect.'; + } + + return { + type: 'message', + content, + messageType: result.success ? 'info' : 'error', + }; + } catch (error) { + return { + type: 'message', + content: `Failed to configure terminal: ${error}`, + messageType: 'error', + }; + } + }, +}; -- cgit v1.2.3