提交 5f0eaf63 编写于 作者: D Daniel Imms

Fix file scheme folder links in terminal

Fixes #129457
上级 e9fba4fc
......@@ -61,7 +61,12 @@ export class TerminalLinkManager extends DisposableStore {
// Protocol links
const wrappedActivateCallback = this._wrapLinkHandler((_, link) => this._handleProtocolLink(link));
const protocolProvider = this._instantiationService.createInstance(TerminalProtocolLinkProvider, this._xterm, wrappedActivateCallback, this._tooltipCallback.bind(this));
const protocolProvider = this._instantiationService.createInstance(TerminalProtocolLinkProvider,
this._xterm,
wrappedActivateCallback,
this._wrapLinkHandler.bind(this),
this._tooltipCallback.bind(this),
async (link, cb) => cb(await this._resolvePath(link)));
this._standardLinkProviders.push(protocolProvider);
// Validated local links
......
......@@ -6,11 +6,15 @@
import type { Terminal, IViewportRange, IBufferLine } from 'xterm';
import { ILinkComputerTarget, LinkComputer } from 'vs/editor/common/modes/linkComputer';
import { getXtermLineContent, convertLinkRangeToBuffer } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers';
import { TerminalLink, OPEN_FILE_LABEL } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
import { TerminalLink, OPEN_FILE_LABEL, FOLDER_IN_WORKSPACE_LABEL, FOLDER_NOT_IN_WORKSPACE_LABEL } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
import { TerminalBaseLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalBaseLinkProvider';
import { Schemas } from 'vs/base/common/network';
import { XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
export class TerminalProtocolLinkProvider extends TerminalBaseLinkProvider {
private _linkComputerTarget: ILinkComputerTarget | undefined;
......@@ -18,13 +22,19 @@ export class TerminalProtocolLinkProvider extends TerminalBaseLinkProvider {
constructor(
private readonly _xterm: Terminal,
private readonly _activateCallback: (event: MouseEvent | undefined, uri: string) => void,
private readonly _wrapLinkHandler: (handler: (event: MouseEvent | undefined, link: string) => void) => XtermLinkMatcherHandler,
private readonly _tooltipCallback: (link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) => void,
@IInstantiationService private readonly _instantiationService: IInstantiationService
private readonly _validationCallback: (link: string, callback: (result: { uri: URI, isDirectory: boolean } | undefined) => void) => void,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ICommandService private readonly _commandService: ICommandService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IHostService private readonly _hostService: IHostService,
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService
) {
super();
}
protected _provideLinks(y: number): TerminalLink[] {
protected async _provideLinks(y: number): Promise<TerminalLink[]> {
let startLine = y - 1;
let endLine = startLine;
......@@ -45,16 +55,74 @@ export class TerminalProtocolLinkProvider extends TerminalBaseLinkProvider {
this._linkComputerTarget = new TerminalLinkAdapter(this._xterm, startLine, endLine);
const links = LinkComputer.computeLinks(this._linkComputerTarget);
return links.map(link => {
const range = convertLinkRangeToBuffer(lines, this._xterm.cols, link.range, startLine);
const result: TerminalLink[] = [];
for (const link of links) {
const bufferRange = convertLinkRangeToBuffer(lines, this._xterm.cols, link.range, startLine);
// Check if the link is within the mouse position
const uri = link.url
? (typeof link.url === 'string' ? URI.parse(link.url) : link.url)
: undefined;
const label = (uri?.scheme === Schemas.file) ? OPEN_FILE_LABEL : undefined;
return this._instantiationService.createInstance(TerminalLink, this._xterm, range, link.url?.toString() || '', this._xterm.buffer.active.viewportY, this._activateCallback, this._tooltipCallback, true, label);
});
if (!uri) {
continue;
}
const validatedLink = await new Promise<TerminalLink | undefined>(r => {
this._validationCallback(uri.fsPath, (result) => {
if (result) {
const label = result.isDirectory
? (this._isDirectoryInsideWorkspace(result.uri) ? FOLDER_IN_WORKSPACE_LABEL : FOLDER_NOT_IN_WORKSPACE_LABEL)
: OPEN_FILE_LABEL;
const activateCallback = this._wrapLinkHandler((event: MouseEvent | undefined, text: string) => {
if (result.isDirectory) {
this._handleLocalFolderLink(result.uri);
} else {
this._activateCallback(event, result.uri.path);
}
});
r(this._instantiationService.createInstance(
TerminalLink,
this._xterm,
bufferRange,
uri.fsPath,
this._xterm.buffer.active.viewportY,
activateCallback,
this._tooltipCallback,
true,
label
));
} else {
r(undefined);
}
});
});
if (validatedLink) {
result.push(validatedLink);
}
}
return result;
}
private async _handleLocalFolderLink(uri: URI): Promise<void> {
// If the folder is within one of the window's workspaces, focus it in the explorer
if (this._isDirectoryInsideWorkspace(uri)) {
await this._commandService.executeCommand('revealInExplorer', uri);
return;
}
// Open a new window for the folder
this._hostService.openWindow([{ folderUri: uri }], { forceNewWindow: true });
}
private _isDirectoryInsideWorkspace(uri: URI) {
const folders = this._workspaceContextService.getWorkspace().folders;
for (let i = 0; i < folders.length; i++) {
if (this._uriIdentityService.extUri.isEqualOrParent(uri, folders[i].uri)) {
return true;
}
}
return false;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册