mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat: add support for Trae editor (#1037)
This commit is contained in:
@@ -17,7 +17,7 @@ import { terminalSetup } from '../utils/terminalSetup.js';
|
|||||||
export const terminalSetupCommand: SlashCommand = {
|
export const terminalSetupCommand: SlashCommand = {
|
||||||
name: 'terminal-setup',
|
name: 'terminal-setup',
|
||||||
description:
|
description:
|
||||||
'Configure terminal keybindings for multiline input (VS Code, Cursor, Windsurf)',
|
'Configure terminal keybindings for multiline input (VS Code, Cursor, Windsurf, Trae)',
|
||||||
kind: CommandKind.BUILT_IN,
|
kind: CommandKind.BUILT_IN,
|
||||||
|
|
||||||
action: async (): Promise<MessageActionReturn> => {
|
action: async (): Promise<MessageActionReturn> => {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const EDITOR_DISPLAY_NAMES: Record<EditorType, string> = {
|
|||||||
vscodium: 'VSCodium',
|
vscodium: 'VSCodium',
|
||||||
windsurf: 'Windsurf',
|
windsurf: 'Windsurf',
|
||||||
zed: 'Zed',
|
zed: 'Zed',
|
||||||
|
trae: 'Trae',
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorSettingsManager {
|
class EditorSettingsManager {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export interface TerminalSetupResult {
|
|||||||
requiresRestart?: boolean;
|
requiresRestart?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type SupportedTerminal = 'vscode' | 'cursor' | 'windsurf';
|
type SupportedTerminal = 'vscode' | 'cursor' | 'windsurf' | 'trae';
|
||||||
|
|
||||||
// Terminal detection
|
// Terminal detection
|
||||||
async function detectTerminal(): Promise<SupportedTerminal | null> {
|
async function detectTerminal(): Promise<SupportedTerminal | null> {
|
||||||
@@ -68,6 +68,11 @@ async function detectTerminal(): Promise<SupportedTerminal | null> {
|
|||||||
) {
|
) {
|
||||||
return 'windsurf';
|
return 'windsurf';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env['TERM_PRODUCT']?.toLowerCase().includes('trae')) {
|
||||||
|
return 'trae';
|
||||||
|
}
|
||||||
|
|
||||||
// Check VS Code last since forks may also set VSCODE env vars
|
// Check VS Code last since forks may also set VSCODE env vars
|
||||||
if (termProgram === 'vscode' || process.env['VSCODE_GIT_IPC_HANDLE']) {
|
if (termProgram === 'vscode' || process.env['VSCODE_GIT_IPC_HANDLE']) {
|
||||||
return 'vscode';
|
return 'vscode';
|
||||||
@@ -86,6 +91,8 @@ async function detectTerminal(): Promise<SupportedTerminal | null> {
|
|||||||
return 'cursor';
|
return 'cursor';
|
||||||
if (parentName.includes('code') || parentName.includes('Code'))
|
if (parentName.includes('code') || parentName.includes('Code'))
|
||||||
return 'vscode';
|
return 'vscode';
|
||||||
|
if (parentName.includes('trae') || parentName.includes('Trae'))
|
||||||
|
return 'trae';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Continue detection even if process check fails
|
// Continue detection even if process check fails
|
||||||
console.debug('Parent process detection failed:', error);
|
console.debug('Parent process detection failed:', error);
|
||||||
@@ -287,6 +294,10 @@ async function configureWindsurf(): Promise<TerminalSetupResult> {
|
|||||||
return configureVSCodeStyle('Windsurf', 'Windsurf');
|
return configureVSCodeStyle('Windsurf', 'Windsurf');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function configureTrae(): Promise<TerminalSetupResult> {
|
||||||
|
return configureVSCodeStyle('Trae', 'Trae');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main terminal setup function that detects and configures the current terminal.
|
* Main terminal setup function that detects and configures the current terminal.
|
||||||
*
|
*
|
||||||
@@ -333,6 +344,8 @@ export async function terminalSetup(): Promise<TerminalSetupResult> {
|
|||||||
return configureCursor();
|
return configureCursor();
|
||||||
case 'windsurf':
|
case 'windsurf':
|
||||||
return configureWindsurf();
|
return configureWindsurf();
|
||||||
|
case 'trae':
|
||||||
|
return configureTrae();
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ describe('editor utils', () => {
|
|||||||
{ editor: 'neovim', commands: ['nvim'], win32Commands: ['nvim'] },
|
{ editor: 'neovim', commands: ['nvim'], win32Commands: ['nvim'] },
|
||||||
{ editor: 'zed', commands: ['zed', 'zeditor'], win32Commands: ['zed'] },
|
{ editor: 'zed', commands: ['zed', 'zeditor'], win32Commands: ['zed'] },
|
||||||
{ editor: 'emacs', commands: ['emacs'], win32Commands: ['emacs.exe'] },
|
{ editor: 'emacs', commands: ['emacs'], win32Commands: ['emacs.exe'] },
|
||||||
|
{ editor: 'trae', commands: ['trae'], win32Commands: ['trae'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { editor, commands, win32Commands } of testCases) {
|
for (const { editor, commands, win32Commands } of testCases) {
|
||||||
@@ -171,6 +172,7 @@ describe('editor utils', () => {
|
|||||||
},
|
},
|
||||||
{ editor: 'cursor', commands: ['cursor'], win32Commands: ['cursor'] },
|
{ editor: 'cursor', commands: ['cursor'], win32Commands: ['cursor'] },
|
||||||
{ editor: 'zed', commands: ['zed', 'zeditor'], win32Commands: ['zed'] },
|
{ editor: 'zed', commands: ['zed', 'zeditor'], win32Commands: ['zed'] },
|
||||||
|
{ editor: 'trae', commands: ['trae'], win32Commands: ['trae'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { editor, commands, win32Commands } of guiEditors) {
|
for (const { editor, commands, win32Commands } of guiEditors) {
|
||||||
@@ -321,6 +323,7 @@ describe('editor utils', () => {
|
|||||||
'windsurf',
|
'windsurf',
|
||||||
'cursor',
|
'cursor',
|
||||||
'zed',
|
'zed',
|
||||||
|
'trae',
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const editor of guiEditors) {
|
for (const editor of guiEditors) {
|
||||||
@@ -430,6 +433,7 @@ describe('editor utils', () => {
|
|||||||
'windsurf',
|
'windsurf',
|
||||||
'cursor',
|
'cursor',
|
||||||
'zed',
|
'zed',
|
||||||
|
'trae',
|
||||||
];
|
];
|
||||||
for (const editor of guiEditors) {
|
for (const editor of guiEditors) {
|
||||||
it(`should not call onEditorClose for ${editor}`, async () => {
|
it(`should not call onEditorClose for ${editor}`, async () => {
|
||||||
@@ -481,6 +485,7 @@ describe('editor utils', () => {
|
|||||||
'windsurf',
|
'windsurf',
|
||||||
'cursor',
|
'cursor',
|
||||||
'zed',
|
'zed',
|
||||||
|
'trae',
|
||||||
];
|
];
|
||||||
for (const editor of guiEditors) {
|
for (const editor of guiEditors) {
|
||||||
it(`should not allow ${editor} in sandbox mode`, () => {
|
it(`should not allow ${editor} in sandbox mode`, () => {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ export type EditorType =
|
|||||||
| 'vim'
|
| 'vim'
|
||||||
| 'neovim'
|
| 'neovim'
|
||||||
| 'zed'
|
| 'zed'
|
||||||
| 'emacs';
|
| 'emacs'
|
||||||
|
| 'trae';
|
||||||
|
|
||||||
function isValidEditorType(editor: string): editor is EditorType {
|
function isValidEditorType(editor: string): editor is EditorType {
|
||||||
return [
|
return [
|
||||||
@@ -26,6 +27,7 @@ function isValidEditorType(editor: string): editor is EditorType {
|
|||||||
'neovim',
|
'neovim',
|
||||||
'zed',
|
'zed',
|
||||||
'emacs',
|
'emacs',
|
||||||
|
'trae',
|
||||||
].includes(editor);
|
].includes(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ const editorCommands: Record<
|
|||||||
neovim: { win32: ['nvim'], default: ['nvim'] },
|
neovim: { win32: ['nvim'], default: ['nvim'] },
|
||||||
zed: { win32: ['zed'], default: ['zed', 'zeditor'] },
|
zed: { win32: ['zed'], default: ['zed', 'zeditor'] },
|
||||||
emacs: { win32: ['emacs.exe'], default: ['emacs'] },
|
emacs: { win32: ['emacs.exe'], default: ['emacs'] },
|
||||||
|
trae: { win32: ['trae'], default: ['trae'] },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function checkHasEditorType(editor: EditorType): boolean {
|
export function checkHasEditorType(editor: EditorType): boolean {
|
||||||
@@ -73,7 +76,9 @@ export function checkHasEditorType(editor: EditorType): boolean {
|
|||||||
|
|
||||||
export function allowEditorTypeInSandbox(editor: EditorType): boolean {
|
export function allowEditorTypeInSandbox(editor: EditorType): boolean {
|
||||||
const notUsingSandbox = !process.env['SANDBOX'];
|
const notUsingSandbox = !process.env['SANDBOX'];
|
||||||
if (['vscode', 'vscodium', 'windsurf', 'cursor', 'zed'].includes(editor)) {
|
if (
|
||||||
|
['vscode', 'vscodium', 'windsurf', 'cursor', 'zed', 'trae'].includes(editor)
|
||||||
|
) {
|
||||||
return notUsingSandbox;
|
return notUsingSandbox;
|
||||||
}
|
}
|
||||||
// For terminal-based editors like vim and emacs, allow in sandbox.
|
// For terminal-based editors like vim and emacs, allow in sandbox.
|
||||||
@@ -115,6 +120,7 @@ export function getDiffCommand(
|
|||||||
case 'windsurf':
|
case 'windsurf':
|
||||||
case 'cursor':
|
case 'cursor':
|
||||||
case 'zed':
|
case 'zed':
|
||||||
|
case 'trae':
|
||||||
return { command, args: ['--wait', '--diff', oldPath, newPath] };
|
return { command, args: ['--wait', '--diff', oldPath, newPath] };
|
||||||
case 'vim':
|
case 'vim':
|
||||||
case 'neovim':
|
case 'neovim':
|
||||||
|
|||||||
Reference in New Issue
Block a user