diff --git a/extensions/positron-python/src/client/positron/extension.ts b/extensions/positron-python/src/client/positron/extension.ts index 78daf96047b..de50ad93ee4 100644 --- a/extensions/positron-python/src/client/positron/extension.ts +++ b/extensions/positron-python/src/client/positron/extension.ts @@ -4,6 +4,7 @@ // eslint-disable-next-line import/no-unresolved import * as positron from 'positron'; +import * as vscode from 'vscode'; import { PythonExtension } from '../api/types'; import { IDisposableRegistry } from '../common/types'; import { IInterpreterService } from '../interpreter/contracts'; @@ -11,13 +12,7 @@ import { IServiceContainer } from '../ioc/types'; import { traceError, traceInfo } from '../logging'; import { PythonRuntimeManager } from './manager'; import { createPythonRuntimeMetadata } from './runtime'; -import * as vscode from 'vscode'; - -export const UrlRegex = /(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+)|(localhost))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/gi; - -interface CustomTerminalLink extends vscode.TerminalLink { - data: string; -} +import { provider } from './linkProvider'; export async function activatePositron( activatedPromise: Promise, @@ -36,35 +31,7 @@ export async function activatePositron( traceInfo('activatePositron: awaiting extension activation'); await activatedPromise; - vscode.window.registerTerminalLinkProvider({ - provideTerminalLinks: (context: vscode.TerminalLinkContext, _token: vscode.CancellationToken) => { - // Detect the first instance of the word "link" if it exists and linkify it - const matches = [...context.line.matchAll(UrlRegex)]; - if (matches.length === 0) { - return []; - } - - return matches.map((match) => { - const line = context.line; - - const startIndex = line.indexOf(match[0]); - - const uri = vscode.Uri.parse(match[0]); - positron.window.previewUrl(uri); - - return { - startIndex, - length: match[0].length, - tooltip: 'Open in Viewer', - data: match[0], - }; - }); - }, - handleTerminalLink: (link: CustomTerminalLink) => { - const uri = vscode.Uri.parse(link.data); - positron.window.previewUrl(uri); - }, - }); + vscode.window.registerTerminalLinkProvider(provider); const registerRuntime = async (interpreterPath: string) => { if (!manager.registeredPythonRuntimes.has(interpreterPath)) { diff --git a/extensions/positron-python/src/client/positron/linkProvider.ts b/extensions/positron-python/src/client/positron/linkProvider.ts new file mode 100644 index 00000000000..8b3075f314d --- /dev/null +++ b/extensions/positron-python/src/client/positron/linkProvider.ts @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2023 Posit Software, PBC. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +// eslint-disable-next-line import/no-unresolved +import * as positron from 'positron'; +import * as vscode from 'vscode'; + +const UrlRegex = /(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+)|(localhost))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/gi; + +interface PositronTerminalLink extends vscode.TerminalLink { + data: string; +} + +const _links: string[] = []; + +export const provider = { + provideTerminalLinks: (context: vscode.TerminalLinkContext, _token: vscode.CancellationToken) => { + const matches = [...context.line.matchAll(UrlRegex)]; + if (matches.length === 0) { + return []; + } + + return matches.map((match) => { + const startIndex = context.line.indexOf(match[0]); + + if (!_links.includes(match[0])) { + const uri = vscode.Uri.parse(match[0]); + positron.window.previewUrl(uri); + } + // fix, people will want to open the same link multiple times + // are we able to get context of the viewer? + // or use some sort of other context from link/application/process lifespan? + _links.push(match[0]); + + return { + startIndex, + length: match[0].length, + tooltip: 'Open in Viewer', + data: match[0], + } as PositronTerminalLink; + }); + }, + handleTerminalLink: (link: PositronTerminalLink) => { + const uri = vscode.Uri.parse(link.data); + positron.window.previewUrl(uri); + }, +};