mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-14 16:10:59 -07:00
undo (#18147)
This commit is contained in:
@@ -2,6 +2,38 @@
|
||||
|
||||
exports[`terminalSetup > configureVSCodeStyle > should create new keybindings file if none exists 1`] = `
|
||||
[
|
||||
{
|
||||
"args": {
|
||||
"text": "[122;4u",
|
||||
},
|
||||
"command": "workbench.action.terminal.sendSequence",
|
||||
"key": "shift+alt+z",
|
||||
"when": "terminalFocus",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"text": "[122;10u",
|
||||
},
|
||||
"command": "workbench.action.terminal.sendSequence",
|
||||
"key": "shift+cmd+z",
|
||||
"when": "terminalFocus",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"text": "[122;3u",
|
||||
},
|
||||
"command": "workbench.action.terminal.sendSequence",
|
||||
"key": "alt+z",
|
||||
"when": "terminalFocus",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"text": "[122;9u",
|
||||
},
|
||||
"command": "workbench.action.terminal.sendSequence",
|
||||
"key": "cmd+z",
|
||||
"when": "terminalFocus",
|
||||
},
|
||||
{
|
||||
"args": {
|
||||
"text": "\\
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('terminalSetup', () => {
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
const writtenContent = JSON.parse(mocks.writeFile.mock.calls[0][1]);
|
||||
expect(writtenContent).toHaveLength(2); // Shift+Enter and Ctrl+Enter
|
||||
expect(writtenContent).toHaveLength(6); // Shift+Enter, Ctrl+Enter, Cmd+Z, Alt+Z, Shift+Cmd+Z, Shift+Alt+Z
|
||||
});
|
||||
|
||||
it('should not modify if bindings already exist', async () => {
|
||||
@@ -145,6 +145,26 @@ describe('terminalSetup', () => {
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
args: { text: VSCODE_SHIFT_ENTER_SEQUENCE },
|
||||
},
|
||||
{
|
||||
key: 'cmd+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
args: { text: '\u001b[122;9u' },
|
||||
},
|
||||
{
|
||||
key: 'alt+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
args: { text: '\u001b[122;3u' },
|
||||
},
|
||||
{
|
||||
key: 'shift+cmd+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
args: { text: '\u001b[122;10u' },
|
||||
},
|
||||
{
|
||||
key: 'shift+alt+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
args: { text: '\u001b[122;4u' },
|
||||
},
|
||||
];
|
||||
mocks.readFile.mockResolvedValue(JSON.stringify(existingBindings));
|
||||
|
||||
|
||||
@@ -204,94 +204,105 @@ async function configureVSCodeStyle(
|
||||
// File doesn't exist, will create new one
|
||||
}
|
||||
|
||||
const shiftEnterBinding = {
|
||||
key: 'shift+enter',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: VSCODE_SHIFT_ENTER_SEQUENCE },
|
||||
};
|
||||
const targetBindings = [
|
||||
{
|
||||
key: 'shift+enter',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: VSCODE_SHIFT_ENTER_SEQUENCE },
|
||||
},
|
||||
{
|
||||
key: 'ctrl+enter',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: VSCODE_SHIFT_ENTER_SEQUENCE },
|
||||
},
|
||||
{
|
||||
key: 'cmd+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: '\u001b[122;9u' },
|
||||
},
|
||||
{
|
||||
key: 'alt+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: '\u001b[122;3u' },
|
||||
},
|
||||
{
|
||||
key: 'shift+cmd+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: '\u001b[122;10u' },
|
||||
},
|
||||
{
|
||||
key: 'shift+alt+z',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: '\u001b[122;4u' },
|
||||
},
|
||||
];
|
||||
|
||||
const ctrlEnterBinding = {
|
||||
key: 'ctrl+enter',
|
||||
command: 'workbench.action.terminal.sendSequence',
|
||||
when: 'terminalFocus',
|
||||
args: { text: VSCODE_SHIFT_ENTER_SEQUENCE },
|
||||
};
|
||||
const results = targetBindings.map((target) => {
|
||||
const hasOurBinding = keybindings.some((kb) => {
|
||||
const binding = kb as {
|
||||
command?: string;
|
||||
args?: { text?: string };
|
||||
key?: string;
|
||||
};
|
||||
return (
|
||||
binding.key === target.key &&
|
||||
binding.command === target.command &&
|
||||
binding.args?.text === target.args.text
|
||||
);
|
||||
});
|
||||
|
||||
// Check if our specific bindings already exist
|
||||
const hasOurShiftEnter = keybindings.some((kb) => {
|
||||
const binding = kb as {
|
||||
command?: string;
|
||||
args?: { text?: string };
|
||||
key?: string;
|
||||
const existingBinding = keybindings.find((kb) => {
|
||||
const binding = kb as { key?: string };
|
||||
return binding.key === target.key;
|
||||
});
|
||||
|
||||
return {
|
||||
target,
|
||||
hasOurBinding,
|
||||
conflict: !!existingBinding && !hasOurBinding,
|
||||
conflictMessage: `- ${target.key.charAt(0).toUpperCase() + target.key.slice(1)} binding already exists`,
|
||||
};
|
||||
return (
|
||||
binding.key === 'shift+enter' &&
|
||||
binding.command === 'workbench.action.terminal.sendSequence' &&
|
||||
binding.args?.text === '\\\r\n'
|
||||
);
|
||||
});
|
||||
|
||||
const hasOurCtrlEnter = keybindings.some((kb) => {
|
||||
const binding = kb as {
|
||||
command?: string;
|
||||
args?: { text?: string };
|
||||
key?: string;
|
||||
};
|
||||
return (
|
||||
binding.key === 'ctrl+enter' &&
|
||||
binding.command === 'workbench.action.terminal.sendSequence' &&
|
||||
binding.args?.text === '\\\r\n'
|
||||
);
|
||||
});
|
||||
|
||||
if (hasOurShiftEnter && hasOurCtrlEnter) {
|
||||
if (results.every((r) => r.hasOurBinding)) {
|
||||
return {
|
||||
success: true,
|
||||
message: `${terminalName} keybindings already configured.`,
|
||||
};
|
||||
}
|
||||
|
||||
// Check if ANY shift+enter or ctrl+enter bindings already exist (that are NOT ours)
|
||||
const existingShiftEnter = keybindings.find((kb) => {
|
||||
const binding = kb as { key?: string };
|
||||
return binding.key === 'shift+enter';
|
||||
});
|
||||
|
||||
const existingCtrlEnter = keybindings.find((kb) => {
|
||||
const binding = kb as { key?: string };
|
||||
return binding.key === 'ctrl+enter';
|
||||
});
|
||||
|
||||
if (existingShiftEnter || existingCtrlEnter) {
|
||||
const messages: string[] = [];
|
||||
// Only report conflict if it's not our binding (though we checked above, partial matches might exist)
|
||||
if (existingShiftEnter && !hasOurShiftEnter) {
|
||||
messages.push(`- Shift+Enter binding already exists`);
|
||||
}
|
||||
if (existingCtrlEnter && !hasOurCtrlEnter) {
|
||||
messages.push(`- Ctrl+Enter binding already exists`);
|
||||
}
|
||||
|
||||
if (messages.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
`Existing keybindings detected. Will not modify to avoid conflicts.\n` +
|
||||
messages.join('\n') +
|
||||
'\n' +
|
||||
`Please check and modify manually if needed: ${keybindingsFile}`,
|
||||
};
|
||||
}
|
||||
const conflicts = results.filter((r) => r.conflict);
|
||||
if (conflicts.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
`Existing keybindings detected. Will not modify to avoid conflicts.\n` +
|
||||
conflicts.map((c) => c.conflictMessage).join('\n') +
|
||||
'\n' +
|
||||
`Please check and modify manually if needed: ${keybindingsFile}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (!hasOurShiftEnter) keybindings.unshift(shiftEnterBinding);
|
||||
if (!hasOurCtrlEnter) keybindings.unshift(ctrlEnterBinding);
|
||||
for (const { hasOurBinding, target } of results) {
|
||||
if (!hasOurBinding) {
|
||||
keybindings.unshift(target);
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeFile(keybindingsFile, JSON.stringify(keybindings, null, 4));
|
||||
return {
|
||||
success: true,
|
||||
message: `Added Shift+Enter and Ctrl+Enter keybindings to ${terminalName}.\nModified: ${keybindingsFile}`,
|
||||
message: `Added ${targetBindings
|
||||
.map((b) => b.key.charAt(0).toUpperCase() + b.key.slice(1))
|
||||
.join(
|
||||
', ',
|
||||
)} keybindings to ${terminalName}.\nModified: ${keybindingsFile}`,
|
||||
requiresRestart: true,
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { isITerm2, resetITerm2Cache } from './terminalUtils.js';
|
||||
describe('terminalUtils', () => {
|
||||
beforeEach(() => {
|
||||
vi.stubEnv('TERM_PROGRAM', '');
|
||||
vi.stubEnv('ITERM_SESSION_ID', '');
|
||||
resetITerm2Cache();
|
||||
});
|
||||
|
||||
@@ -24,11 +23,6 @@ describe('terminalUtils', () => {
|
||||
expect(isITerm2()).toBe(true);
|
||||
});
|
||||
|
||||
it('should detect iTerm2 via ITERM_SESSION_ID', () => {
|
||||
vi.stubEnv('ITERM_SESSION_ID', 'w0t0p0:6789...');
|
||||
expect(isITerm2()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if not iTerm2', () => {
|
||||
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
||||
expect(isITerm2()).toBe(false);
|
||||
|
||||
@@ -31,9 +31,7 @@ export function isITerm2(): boolean {
|
||||
return cachedIsITerm2;
|
||||
}
|
||||
|
||||
cachedIsITerm2 =
|
||||
process.env['TERM_PROGRAM'] === 'iTerm.app' ||
|
||||
!!process.env['ITERM_SESSION_ID'];
|
||||
cachedIsITerm2 = process.env['TERM_PROGRAM'] === 'iTerm.app';
|
||||
|
||||
return cachedIsITerm2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user