Skip to content

Commit 86df90f

Browse files
authored
refactor: adjust attachByLaunchConfig params (#811)
* refactor: adjust attachByLaunchConfig params * chore: update comments * test: fix test case * chore: make params optional * chore: add missing typing * test: fix test case
1 parent 1e571c8 commit 86df90f

File tree

10 files changed

+47
-190
lines changed

10 files changed

+47
-190
lines changed

packages/terminal-next/__tests__/browser/inject.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,6 @@ export const injector = new Injector([
188188
$resolveUnixShellPath(p) {
189189
return p;
190190
},
191-
$resolvePotentialUnixShellPath() {
192-
return 'detectedBash';
193-
},
194191
},
195192
},
196193
]);

packages/terminal-next/__tests__/browser/terminal.service.test.ts

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ describe('terminal service test cases', () => {
9393
$resolveUnixShellPath(p) {
9494
return p;
9595
},
96-
$resolvePotentialUnixShellPath() {
97-
return 'detectedBash';
98-
},
9996
},
10097
});
10198

@@ -123,38 +120,24 @@ describe('terminal service test cases', () => {
123120
expect(windowClientId).toMatch(/^test-window-client-id.*/);
124121
});
125122

126-
it('[attach] should be valid launchConfig with a valid shell path and ignore type', async () => {
127-
await terminalService.attach(
123+
it('[attachByLaunchConfig] should be valid launchConfig with a valid shell path and ignore type', async () => {
124+
await terminalService.attachByLaunchConfig(
128125
sessionId,
129-
{} as any,
130126
200,
131127
200,
132128
{
133-
shellPath,
129+
executable: shellPath,
134130
},
135-
'asdasd',
131+
{} as any,
136132
);
137133
expect(launchConfig?.executable).toEqual(shellPath);
138134
});
139-
it('[attach] should be valid launchConfig with empty type or default', async () => {
140-
await terminalService.attach(sessionId, {} as any, 200, 200, {}, '');
141-
expect(launchConfig?.executable).toEqual('detectedBash');
142-
await terminalService.attach(sessionId, {} as any, 200, 200, {}, 'default');
143-
expect(launchConfig?.executable).toEqual('detectedBash');
144-
});
145-
146-
it('[attach] should be valid launchConfig with specific type', async () => {
147-
await terminalService.attach(sessionId, {} as any, 200, 200, {}, 'bash');
148-
expect(launchConfig?.executable).toEqual('bash');
149-
await terminalService.attach(sessionId, {} as any, 200, 200, {}, 'asdasdasdasd');
150-
expect(launchConfig?.executable).toEqual('asdasdasdasd');
151-
});
152135

153136
it('[attachByLaunchConfig] can launch valid config', async () => {
154137
const launchConfig: IShellLaunchConfig = {
155138
executable: shellPath,
156139
};
157-
await terminalService.attachByLaunchConfig(sessionId, 200, 200, launchConfig);
140+
await terminalService.attachByLaunchConfig(sessionId, 200, 200, launchConfig, {} as any);
158141
expect(launchConfig?.executable).toEqual(shellPath);
159142
});
160143

@@ -163,7 +146,7 @@ describe('terminal service test cases', () => {
163146
const launchConfig: IShellLaunchConfig = {
164147
executable: shellPath,
165148
};
166-
terminalService.attachByLaunchConfig(sessionId, 200, 200, launchConfig);
149+
terminalService.attachByLaunchConfig(sessionId, 200, 200, launchConfig, {} as any);
167150
terminalService.onProcessChange((e) => {
168151
expect(e.sessionId).toBe(sessionId);
169152
expect(e.processName).toBe('zsh');

packages/terminal-next/src/browser/terminal.client.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,13 @@ export class TerminalClient extends Disposable implements ITerminalClient {
586586
this.logger.log('attach terminal by launchConfig: ', this._launchConfig);
587587

588588
try {
589-
connection = await this.internalService.attachByLaunchConfig(sessionId, cols, rows, this._launchConfig);
589+
connection = await this.internalService.attachByLaunchConfig(
590+
sessionId,
591+
cols,
592+
rows,
593+
this._launchConfig,
594+
this.xterm,
595+
);
590596
} catch (e) {
591597
this.logger.error(`attach ${sessionId} terminal failed, _launchConfig`, JSON.stringify(this._launchConfig), e);
592598
}

packages/terminal-next/src/browser/terminal.internal.service.ts

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import {
1010
ITerminalError,
1111
IPtyExitEvent,
1212
ITerminalController,
13-
TerminalOptions,
1413
ITerminalProfile,
1514
IShellLaunchConfig,
1615
ITerminalConnection,
1716
IPtyProcessChangeEvent,
1817
} from '../common';
18+
import { IXTerm } from '../common/xterm';
1919

2020
import { TerminalProcessExtHostProxy } from './terminal.ext.host.proxy';
2121

@@ -45,32 +45,6 @@ export class TerminalInternalService implements ITerminalInternalService {
4545
return this._processExtHostProxies.get(id);
4646
}
4747

48-
async attach(
49-
sessionId: string,
50-
xterm: XTermTerminal,
51-
rows: number,
52-
cols: number,
53-
options: TerminalOptions = {},
54-
type: string,
55-
) {
56-
if (options.isExtensionTerminal) {
57-
const proxy = new TerminalProcessExtHostProxy(sessionId, cols, rows, this.controller);
58-
proxy.start();
59-
proxy.onProcessExit(() => {
60-
this._processExtHostProxies.delete(sessionId);
61-
});
62-
this._processExtHostProxies.set(sessionId, proxy);
63-
return {
64-
name: options.name || 'ExtensionTerminal-' + sessionId,
65-
readonly: false,
66-
onData: proxy.onProcessData.bind(proxy),
67-
sendData: proxy.input.bind(proxy),
68-
onExit: proxy.onProcessExit.bind(proxy),
69-
};
70-
}
71-
return this.service.attach(sessionId, xterm, rows, cols, options, type);
72-
}
73-
7448
async sendText(sessionId: string, message: string) {
7549
const proxy = this._getExtHostProxy(sessionId);
7650
if (proxy) {
@@ -137,6 +111,7 @@ export class TerminalInternalService implements ITerminalInternalService {
137111
cols: number,
138112
rows: number,
139113
launchConfig: IShellLaunchConfig,
114+
xterm: IXTerm,
140115
): Promise<ITerminalConnection | undefined> {
141116
if (launchConfig.customPtyImplementation) {
142117
const proxy = launchConfig.customPtyImplementation(sessionId, cols, rows) as TerminalProcessExtHostProxy;
@@ -153,6 +128,6 @@ export class TerminalInternalService implements ITerminalInternalService {
153128
onExit: proxy.onProcessExit.bind(proxy),
154129
};
155130
}
156-
return await this.service.attachByLaunchConfig(sessionId, cols, rows, launchConfig);
131+
return await this.service.attachByLaunchConfig(sessionId, cols, rows, launchConfig, xterm);
157132
}
158133
}

packages/terminal-next/src/browser/terminal.service.ts

Lines changed: 6 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626
import { CodeTerminalSettingPrefix } from '../common/preference';
2727
import { ShellType, WindowsShellType } from '../common/shell';
2828

29+
import { XTerm } from './xterm';
30+
2931
export interface EventMessage {
3032
data: string;
3133
}
@@ -100,93 +102,13 @@ export class NodePtyTerminalService implements ITerminalService {
100102
ptyInstance: pty,
101103
});
102104

103-
/**
104-
*
105-
* @param sessionId
106-
* @param _
107-
* @param rows
108-
* @param cols
109-
* @param options
110-
* @param shellType
111-
* @returns
112-
*/
113-
async attach(
105+
async attachByLaunchConfig(
114106
sessionId: string,
115-
_: Terminal,
116-
rows: number,
117107
cols: number,
118-
options: TerminalOptions = {},
119-
shellType?: ShellType,
108+
rows: number,
109+
launchConfig: IShellLaunchConfig,
110+
_xterm: XTerm,
120111
) {
121-
let shellPath = options.shellPath;
122-
const shellArgs = typeof options.shellArgs === 'string' ? [options.shellArgs] : options.shellArgs || [];
123-
const platformKey = await this.getCodePlatformKey();
124-
const terminalOs = await this.getOs();
125-
if (!shellPath) {
126-
// if terminal options.shellPath is not set, we should resolve the shell path from preference: `terminal.type`
127-
if (shellType && shellType !== 'default') {
128-
if (terminalOs === OperatingSystem.Windows) {
129-
shellPath = await this.serviceClientRPC.$resolveWindowsShellPath(shellType as WindowsShellType);
130-
} else {
131-
shellPath = await this.serviceClientRPC.$resolveUnixShellPath(shellType);
132-
}
133-
134-
if (!shellPath) {
135-
// TODO: we can show error message here
136-
// "the shell you want to launch is not exists"
137-
}
138-
}
139-
140-
// and now, we have the following two situations:
141-
if (!shellPath) {
142-
if (!shellType || shellType === 'default') {
143-
// 1. `terminal.type` is set to a falsy value, or set to `default`
144-
if (terminalOs === OperatingSystem.Windows) {
145-
// in windows, at least we can launch the cmd.exe
146-
const { type: _type, path } = await this.serviceClientRPC.$resolvePotentialWindowsShellPath();
147-
shellType = _type;
148-
shellPath = path;
149-
} else {
150-
// in unix, at least we can launch the sh
151-
shellPath = await this.serviceClientRPC.$resolvePotentialUnixShellPath();
152-
}
153-
} else {
154-
// 2. `terminal.type` is set to a truthy value, but the shell path is not resolved, for example cannot resolve 'git-bash'
155-
// but in this situation, we preserve the user settings, launch the type as shell path
156-
// on PtyService we also have a fallback to check the shellPath is valid
157-
shellPath = shellType;
158-
}
159-
}
160-
161-
// if we still can not find the shell path, we use shellType as the target shell path
162-
if (!shellPath && shellType !== 'default') {
163-
shellPath = shellType;
164-
}
165-
166-
const platformSpecificArgs = this.preferenceService.get<string[]>(
167-
`${CodeTerminalSettingPrefix.ShellArgs}${platformKey}`,
168-
[],
169-
);
170-
171-
shellArgs.push(...platformSpecificArgs);
172-
173-
if (shellType === WindowsShellType['git-bash']) {
174-
shellArgs.push('--login');
175-
}
176-
}
177-
178-
const launchConfig: IShellLaunchConfig = {
179-
executable: shellPath,
180-
cwd: options.cwd,
181-
args: shellArgs,
182-
env: options.env,
183-
name: options.name,
184-
strictEnv: options.strictEnv,
185-
};
186-
return this.attachByLaunchConfig(sessionId, cols, rows, launchConfig);
187-
}
188-
189-
async attachByLaunchConfig(sessionId: string, cols: number, rows: number, launchConfig: IShellLaunchConfig) {
190112
// If code runs to here, it means that we want to create a real terminal.
191113
// So if `launchConfig.executable` is not set, we should use the default shell.
192114
if (!launchConfig.executable) {

packages/terminal-next/src/browser/xterm.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { WorkbenchThemeService } from '@opensumi/ide-theme/lib/browser/workbench
1010
import { IThemeService } from '@opensumi/ide-theme/lib/common/theme.service';
1111

1212
import { SupportedOptions } from '../common/preference';
13+
import { IXTerm } from '../common/xterm';
1314

1415
import styles from './component/terminal.module.less';
1516
import {
@@ -30,7 +31,7 @@ export interface XTermOptions {
3031
}
3132

3233
@Injectable({ multiple: true })
33-
export class XTerm extends Disposable {
34+
export class XTerm extends Disposable implements IXTerm {
3435
@Autowired(INJECTOR_TOKEN)
3536
protected readonly injector: Injector;
3637

packages/terminal-next/src/common/pty.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,6 @@ export interface ITerminalServiceClient {
228228
ensureTerminal(terminalIdArr: string[]): boolean;
229229
$resolveWindowsShellPath(type: WindowsShellType): Promise<string | undefined>;
230230
$resolveUnixShellPath(type: string): Promise<string | undefined>;
231-
$resolvePotentialUnixShellPath(): Promise<string | undefined>;
232-
$resolvePotentialWindowsShellPath(): Promise<{ path: string; type: WindowsShellType }>;
233231
$resolveShellPath(paths: string[]): Promise<string | undefined>;
234232
detectAvailableProfiles(options: IDetectProfileOptions): Promise<ITerminalProfile[]>;
235233
getDefaultSystemShell(os: OperatingSystem): Promise<string>;

packages/terminal-next/src/common/service.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ITerminalConnection } from './client';
77
import { ITerminalError } from './error';
88
import { ITerminalProfile } from './profile';
99
import { IShellLaunchConfig, TerminalOptions } from './pty';
10+
import { IXTerm } from './xterm';
1011

1112
export interface IPtyExitEvent {
1213
sessionId: string;
@@ -37,28 +38,20 @@ export interface ITerminalService {
3738
* @param sessionIds
3839
*/
3940
check?(sessionIds: string[]): Promise<boolean>;
41+
4042
/**
41-
* @deprecated will remove on 2.17.0, please use `attachByLaunchConfig` instead
4243
* @param sessionId 会话唯一标识
43-
* @param xterm 返回的 Xterm 终端实例
4444
* @param rows 终端初始化使用的列数
4545
* @param cols 终端初始化使用的行数
46-
* @param options 创建一个新终端的进程选项
47-
* @param shellType 终端类型
46+
* @param launchConfig 创建一个新终端的进程选项
47+
* @param xterm 创建的 xterm 实例
4848
*/
49-
attach(
50-
sessionId: string,
51-
xterm: Terminal,
52-
cols: number,
53-
rows: number,
54-
options?: TerminalOptions,
55-
shellType?: string,
56-
): Promise<ITerminalConnection | undefined>;
5749
attachByLaunchConfig(
5850
sessionId: string,
5951
cols: number,
6052
rows: number,
6153
launchConfig: IShellLaunchConfig,
54+
xterm?: IXTerm,
6255
): Promise<ITerminalConnection | undefined>;
6356
/**
6457
*
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ITerminalOptions, ITheme, Terminal } from 'xterm';
2+
3+
import { SupportedOptions } from './preference';
4+
5+
export interface IXTerm {
6+
raw: Terminal;
7+
container: HTMLDivElement;
8+
xtermOptions: ITerminalOptions & SupportedOptions;
9+
10+
copySelection(): Promise<void>;
11+
onSelectionChange(): Promise<void>;
12+
open(): void;
13+
fit(): void;
14+
findNext(text: string): boolean;
15+
closeSearch(): void;
16+
updatePreferences(options: SupportedOptions): void;
17+
updateTheme(theme: ITheme | undefined): void;
18+
}

packages/terminal-next/src/node/terminal.service.client.ts

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -129,42 +129,6 @@ export class TerminalServiceClientImpl extends RPCService<IRPCTerminalService> i
129129
return await findShellExecutableAsync(paths);
130130
}
131131

132-
async $resolvePotentialUnixShellPath(): Promise<string | undefined> {
133-
if (process.env.SHELL) {
134-
return process.env.SHELL;
135-
}
136-
137-
const candidates = ['zsh', 'bash', 'sh'];
138-
for (const candidate of candidates) {
139-
const path = await this.$resolveUnixShellPath(candidate);
140-
if (path) {
141-
return path;
142-
}
143-
}
144-
}
145-
146-
async $resolvePotentialWindowsShellPath(): Promise<{ path: string; type: WindowsShellType }> {
147-
let path = await findShellExecutableAsync(WINDOWS_GIT_BASH_PATHS);
148-
if (path) {
149-
return {
150-
path,
151-
type: WindowsShellType['git-bash'],
152-
};
153-
}
154-
path = await findExecutable(WINDOWS_DEFAULT_SHELL_PATH_MAPS.powershell);
155-
if (path) {
156-
return {
157-
path,
158-
type: WindowsShellType.powershell,
159-
};
160-
}
161-
162-
return {
163-
path: WINDOWS_DEFAULT_SHELL_PATH_MAPS.cmd,
164-
type: WindowsShellType.cmd,
165-
};
166-
}
167-
168132
async detectAvailableProfiles(options: IDetectProfileOptions): Promise<ITerminalProfile[]> {
169133
return await this.terminalProfileService.detectAvailableProfiles(options);
170134
}

0 commit comments

Comments
 (0)