Skip to content

Commit a055870

Browse files
committed
Handle link on exthost
1 parent a5b3885 commit a055870

3 files changed

Lines changed: 60 additions & 18 deletions

File tree

src/vs/workbench/api/browser/mainThreadTerminalService.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,14 +424,17 @@ class ExtensionTerminalLinkProvider implements ITerminalExternalLinkProvider {
424424
}
425425

426426
async provideLinks(instance: ITerminalInstance, line: string): Promise<ITerminalLink[] | undefined> {
427-
const extHostLinks = await this._proxy.$provideLinks(instance.id, line);
427+
const proxy = this._proxy;
428+
const extHostLinks = await proxy.$provideLinks(instance.id, line);
429+
console.log('ExtensionTerminalLinkProvider#provideLinks', extHostLinks);
428430
return extHostLinks.map(dto => ({
431+
id: dto.id,
429432
startIndex: dto.startIndex,
430433
length: dto.length,
431434
label: dto.label,
432435
activate(text: string) {
433-
// TODO: Activate on the exthost
434436
console.log('Activated! ' + text);
437+
proxy.$activateLink(instance.id, dto.id);
435438
}
436439
}));
437440
}

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,8 @@ export interface IShellAndArgsDto {
13791379
}
13801380

13811381
export interface ITerminalLinkDto {
1382+
/** The ID of the link to enable activation and disposal. */
1383+
id: number;
13821384
/** The startIndex of the link in the line. */
13831385
startIndex: number;
13841386
/** The length of the link in the line. */
@@ -1414,6 +1416,7 @@ export interface ExtHostTerminalServiceShape {
14141416
$getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
14151417
$handleLink(id: number, link: string): Promise<boolean>;
14161418
$provideLinks(id: number, line: string): Promise<ITerminalLinkDto[]>;
1419+
$activateLink(id: number, linkId: number): void;
14171420
$initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void;
14181421
}
14191422

src/vs/workbench/api/common/extHostTerminalService.ts

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,13 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
294294
}
295295
}
296296

297+
let nextLinkId = 1;
298+
299+
interface ICachedLinkEntry {
300+
provider: vscode.TerminalLinkProvider;
301+
link: vscode.TerminalLink;
302+
}
303+
297304
export abstract class BaseExtHostTerminalService implements IExtHostTerminalService, ExtHostTerminalServiceShape {
298305

299306
readonly _serviceBrand: undefined;
@@ -309,6 +316,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
309316
private readonly _bufferer: TerminalDataBufferer;
310317
private readonly _linkHandlers: Set<vscode.TerminalLinkHandler> = new Set();
311318
private readonly _linkProviders: Set<vscode.TerminalLinkProvider> = new Set();
319+
private readonly _terminalLinkCache: Map<number, Map<number, ICachedLinkEntry>> = new Map();
312320

313321
public get activeTerminal(): ExtHostTerminal | undefined { return this._activeTerminal; }
314322
public get terminals(): ExtHostTerminal[] { return this._terminals; }
@@ -346,8 +354,8 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
346354
return links;
347355
},
348356
handleTerminalLink(link) {
349-
// TODO: Pass provider ID back to ext host so it can trigger activate/handle
350-
return false;
357+
console.log('Handled link on ext host, tooltip=' + link.tooltip);
358+
return true;
351359
}
352360
});
353361
}
@@ -609,35 +617,63 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
609617
return false;
610618
}
611619

612-
public async $provideLinks(id: number, line: string): Promise<ITerminalLinkDto[]> {
613-
const terminal = this._getTerminalById(id);
620+
public async $provideLinks(terminalId: number, line: string): Promise<ITerminalLinkDto[]> {
621+
const terminal = this._getTerminalById(terminalId);
614622
if (!terminal) {
615623
return [];
616624
}
617625

626+
// Discard any cached links the terminal has been holding, currently all links are released
627+
// when new links are provided.
628+
this._terminalLinkCache.delete(terminalId);
629+
618630
// TODO: Store link activate callback
619631
// TODO: Discard of links when appropriate
620632
const result: ITerminalLinkDto[] = [];
621633
const context: vscode.TerminalLinkContext = { terminal, line };
622-
const promises: vscode.ProviderResult<vscode.TerminalLink[]>[] = [];
634+
const promises: vscode.ProviderResult<{ provider: vscode.TerminalLinkProvider, links: vscode.TerminalLink[] }>[] = [];
623635
for (const provider of this._linkProviders) {
624-
promises.push(provider.provideTerminalLinks(context));
625-
}
626-
627-
const allProviderLinks = await Promise.all(promises);
628-
for (const providerLinks of allProviderLinks) {
629-
if (providerLinks && providerLinks.length > 0) {
630-
result.push(...providerLinks.map(l => ({
631-
startIndex: l.startIndex,
632-
length: l.length,
633-
label: l.tooltip
634-
})));
636+
promises.push(new Promise(async r => {
637+
const links = (await provider.provideTerminalLinks(context)) || [];
638+
r({ provider, links });
639+
}));
640+
}
641+
642+
const provideResults = await Promise.all(promises);
643+
const cacheLinkMap = new Map<number, ICachedLinkEntry>();
644+
for (const provideResult of provideResults) {
645+
if (provideResult && provideResult.links.length > 0) {
646+
result.push(...provideResult.links.map(providerLink => {
647+
const link = {
648+
id: nextLinkId++,
649+
startIndex: providerLink.startIndex,
650+
length: providerLink.length,
651+
label: providerLink.tooltip
652+
};
653+
cacheLinkMap.set(link.id, {
654+
provider: provideResult.provider,
655+
link: providerLink
656+
});
657+
return link;
658+
}));
635659
}
636660
}
637661

662+
this._terminalLinkCache.set(terminalId, cacheLinkMap);
663+
638664
return result;
639665
}
640666

667+
$activateLink(terminalId: number, linkId: number): void {
668+
const cachedLink = this._terminalLinkCache.get(terminalId)?.get(linkId);
669+
if (!cachedLink) {
670+
return;
671+
}
672+
cachedLink.provider.handleTerminalLink(cachedLink.link);
673+
674+
// TODO: Handle when result is false
675+
}
676+
641677
private _onProcessExit(id: number, exitCode: number | undefined): void {
642678
this._bufferer.stopBuffering(id);
643679

0 commit comments

Comments
 (0)