@@ -45,6 +45,8 @@ export class TerminalLinkManager extends DisposableStore {
4545 private readonly _externalLinkProviders : IDisposable [ ] = [ ] ;
4646 private readonly _openers : Map < TerminalLinkType , ITerminalLinkOpener > = new Map ( ) ;
4747
48+ externalProvideLinksCb ?: OmitFirstArg < ITerminalExternalLinkProvider [ 'provideLinks' ] > ;
49+
4850 constructor (
4951 private readonly _xterm : Terminal ,
5052 private readonly _processInfo : ITerminalProcessInfo ,
@@ -349,25 +351,30 @@ export class TerminalLinkManager extends DisposableStore {
349351 }
350352
351353 private _registerStandardLinkProviders ( ) : void {
354+ // Forward any external link provider requests to the registered provider if it exists. This
355+ // helps maintain the relative priority of the link providers as it's defined by the order
356+ // in which they're registered in xterm.js.
357+ //
358+ /**
359+ * There's a bit going on here but here's another view:
360+ * - {@link externalProvideLinksCb} The external callback that gives the links (eg. from
361+ * exthost)
362+ * - {@link proxyLinkProvider} A proxy that forwards the call over to
363+ * {@link externalProvideLinksCb}
364+ * - {@link wrappedLinkProvider} Wraps the above in an `TerminalLinkDetectorAdapter`
365+ */
366+ const proxyLinkProvider : OmitFirstArg < ITerminalExternalLinkProvider [ 'provideLinks' ] > = async ( bufferLineNumber ) => {
367+ return this . externalProvideLinksCb ?.( bufferLineNumber ) ;
368+ } ;
369+ const detectorId = `extension-${ this . _externalLinkProviders . length } ` ;
370+ const wrappedLinkProvider = this . _setupLinkDetector ( detectorId , new TerminalExternalLinkDetector ( detectorId , this . _xterm , proxyLinkProvider ) , true ) ;
371+ this . _linkProvidersDisposables . push ( this . _xterm . registerLinkProvider ( wrappedLinkProvider ) ) ;
372+
352373 for ( const p of this . _standardLinkProviders . values ( ) ) {
353374 this . _linkProvidersDisposables . push ( this . _xterm . registerLinkProvider ( p ) ) ;
354375 }
355376 }
356377
357- registerExternalLinkProvider ( provideLinks : OmitFirstArg < ITerminalExternalLinkProvider [ 'provideLinks' ] > ) : void {
358- // Avoid any leaks in case this is already disposed
359- if ( this . isDisposed ) {
360- return ;
361- }
362- // Clear and re-register the standard link providers so they are a lower priority than the new one
363- this . _clearLinkProviders ( ) ;
364- const detectorId = `extension-${ this . _externalLinkProviders . length } ` ;
365- const wrappedLinkProvider = this . _setupLinkDetector ( detectorId , new TerminalExternalLinkDetector ( detectorId , this . _xterm , provideLinks ) , true ) ;
366- const newLinkProvider = this . _xterm . registerLinkProvider ( wrappedLinkProvider ) ;
367- this . _externalLinkProviders . push ( newLinkProvider ) ;
368- this . _registerStandardLinkProviders ( ) ;
369- }
370-
371378 protected _isLinkActivationModifierDown ( event : MouseEvent ) : boolean {
372379 const editorConf = this . _configurationService . getValue < { multiCursorModifier : 'ctrlCmd' | 'alt' } > ( 'editor' ) ;
373380 if ( editorConf . multiCursorModifier === 'ctrlCmd' ) {
0 commit comments