From 2feae028dd8f1be8e1199899f8565043c7490e5d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 6 May 2020 04:32:01 -0700 Subject: [PATCH] Convert validated links provider to new model --- .../terminal/browser/links/terminalLink.ts | 6 ++ .../browser/links/terminalLinkManager.ts | 24 ++++---- .../terminalValidatedLocalLinkProvider.ts | 58 +++++++++---------- .../terminal/browser/widgets/hoverWidget.ts | 2 + .../browser/widgets/terminalHoverWidget.ts | 5 ++ .../terminal/browser/widgets/widgetManager.ts | 1 + 6 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts index cd94c13cc1f..995bb7f98e1 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts @@ -56,6 +56,7 @@ export class TerminalLink extends DisposableStore implements ILink { } hover(event: MouseEvent, text: string): void { + console.log('hover ' + this.range.end.y, new Error().stack); // Listen for modifier before handing it off to the hover to handle so it gets disposed correctly this.add(dom.addDisposableListener(document, 'keydown', e => { if (this._isModifierDown(e)) { @@ -70,12 +71,16 @@ export class TerminalLink extends DisposableStore implements ILink { const timeout = this._configurationService.getValue('editor.hover.delay'); this._tooltipScheduler = new RunOnceScheduler(() => { + console.log('tooltip trigger ' + this.range.end.y); this._tooltipCallback( this, convertBufferRangeToViewport(this.range, this._viewportY), this._isHighConfidenceLink ? () => this._enableDecorations() : undefined, this._isHighConfidenceLink ? () => this._disableDecorations() : undefined ); + // Clear out scheduler until next hover event + this._tooltipScheduler?.dispose(); + this._tooltipScheduler = undefined; // this.dispose(); }, timeout); this.add(this._tooltipScheduler); @@ -105,6 +110,7 @@ export class TerminalLink extends DisposableStore implements ILink { this._hoverListeners = undefined; this._tooltipScheduler?.dispose(); this._tooltipScheduler = undefined; + console.log('TerminalLink.onLeave fire (' + this.range.end.y + ')'); this._onLeave.fire(); } diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index fa8cfed1fb7..c8e0235f257 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -301,18 +301,18 @@ export class TerminalLinkManager extends DisposableStore { const protocolProvider = this._instantiationService.createInstance(TerminalProtocolLinkProvider, this._xterm, wrappedActivateCallback, this._tooltipCallback2.bind(this)); this._linkProviders.push(this._xterm.registerLinkProvider(protocolProvider)); - // // Validated local links - // if (this._configurationService.getValue(TERMINAL_CONFIG_SECTION).enableFileLinks) { - // const wrappedTextLinkActivateCallback = this._wrapLinkHandler((_, link) => this._handleLocalLink(link)); - // const validatedProvider = this._instantiationService.createInstance(TerminalValidatedLocalLinkProvider, - // this._xterm, - // this._processManager.os || OS, - // wrappedTextLinkActivateCallback, - // this._wrapLinkHandler.bind(this), - // this._tooltipCallback2.bind(this), - // async (link, cb) => cb(await this._resolvePath(link))); - // this._linkProviders.push(this._xterm.registerLinkProvider(validatedProvider)); - // } + // Validated local links + if (this._configurationService.getValue(TERMINAL_CONFIG_SECTION).enableFileLinks) { + const wrappedTextLinkActivateCallback = this._wrapLinkHandler((_, link) => this._handleLocalLink(link)); + const validatedProvider = this._instantiationService.createInstance(TerminalValidatedLocalLinkProvider, + this._xterm, + this._processManager.os || OS, + wrappedTextLinkActivateCallback, + this._wrapLinkHandler.bind(this), + this._tooltipCallback2.bind(this), + async (link, cb) => cb(await this._resolvePath(link))); + this._linkProviders.push(this._xterm.registerLinkProvider(validatedProvider)); + } // Word links const wordProvider = this._instantiationService.createInstance(TerminalWordLinkProvider, this._xterm, this._wrapLinkHandler.bind(this), this._tooltipCallback2.bind(this)); diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts index 741b60fe434..8f9b10962a4 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Terminal, ILinkProvider, IViewportRange, IBufferCellPosition, ILink, IBufferLine } from 'xterm'; -import { getXtermLineContent, convertLinkRangeToBuffer, positionIsInRange } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers'; +import { Terminal, IViewportRange, IBufferLine } from 'xterm'; +import { getXtermLineContent, convertLinkRangeToBuffer } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkHelpers'; import { OperatingSystem } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { TerminalLink, OPEN_FILE_LABEL, FOLDER_IN_WORKSPACE_LABEL, FOLDER_NOT_IN_WORKSPACE_LABEL } from 'vs/workbench/contrib/terminal/browser/links/terminalLink'; @@ -14,6 +14,7 @@ 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 { XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; +import { TerminalBaseLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalBaseLinkProvider'; const pathPrefix = '(\\.\\.?|\\~)'; const pathSeparatorClause = '\\/'; @@ -41,7 +42,7 @@ const lineAndColumnClause = [ '(([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?)' // (file path):336, (file path):336:9 ].join('|').replace(/ /g, `[${'\u00A0'} ]`); -export class TerminalValidatedLocalLinkProvider implements ILinkProvider { +export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider { constructor( private readonly _xterm: Terminal, private readonly _processOperatingSystem: OperatingSystem, @@ -54,10 +55,12 @@ export class TerminalValidatedLocalLinkProvider implements ILinkProvider { @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IHostService private readonly _hostService: IHostService ) { + super(); } - async provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void) { - let startLine = position.y - 1; + protected async _provideLinks(y: number): Promise { + const result: TerminalLink[] = []; + let startLine = y - 1; let endLine = startLine; const lines: IBufferLine[] = [ @@ -121,34 +124,31 @@ export class TerminalValidatedLocalLinkProvider implements ILinkProvider { endLineNumber: 1 }, startLine); - if (positionIsInRange(position, bufferRange)) { - const validatedLink = await new Promise(r => { - this._validationCallback(link, (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._activateFileCallback(event, text); - } - }); - r(this._instantiationService.createInstance(TerminalLink, bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, true, label)); - } else { - r(undefined); - } - }); + const validatedLink = await new Promise(r => { + this._validationCallback(link, (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._activateFileCallback(event, text); + } + }); + r(this._instantiationService.createInstance(TerminalLink, bufferRange, link, this._xterm.buffer.active.viewportY, activateCallback, this._tooltipCallback, true, label)); + } else { + r(undefined); + } }); - if (validatedLink) { - callback(validatedLink); - return; - } + }); + if (validatedLink) { + result.push(validatedLink); } } - callback(undefined); + return result; } protected get _localLinkRegex(): RegExp { diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts b/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts index 004d554f843..8a58b90c46d 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/hoverWidget.ts @@ -173,6 +173,7 @@ export class HoverWidget extends Widget { } public dispose(): void { + console.log('HoverWidget.dispose'); if (!this._isDisposed) { this._onDispose.fire(); this._containerDomNode.parentElement?.removeChild(this.domNode); @@ -225,6 +226,7 @@ class CompositeMouseTracker extends Widget { private _fireIfMouseOutside(): void { if (!this._isMouseIn) { + console.log('mouse tracker fire mouse out'); this._onMouseOut.fire(); } } diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget.ts b/src/vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget.ts index e4cb092f6ac..55b30c7d434 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget.ts @@ -34,6 +34,11 @@ export class TerminalHover extends Disposable implements ITerminalWidget { super(); } + dispose() { + console.log('TerminalHover.dispose'); + super.dispose(); + } + attach(container: HTMLElement): void { const target = new CellHoverTarget(container, this._targetOptions); this._register(this._instantiationService.createInstance(HoverWidget, container, target, this._text, this._linkHandler, [])); diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/widgetManager.ts b/src/vs/workbench/contrib/terminal/browser/widgets/widgetManager.ts index 032610dbea7..a797cfa3d80 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/widgetManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/widgetManager.ts @@ -29,6 +29,7 @@ export class TerminalWidgetManager implements IDisposable { if (!this._container) { return; } + console.log('attach new widget'); this._attached.get(widget.id)?.dispose(); widget.attach(this._container); this._attached.set(widget.id, widget);