From f3b8d15b0d8dda11e6738b55a2fa8a485870cfd4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 23 May 2019 17:51:45 -0700 Subject: [PATCH] Add DocumentLink.tooltip api proposal For #72824 --- .../src/features/documentLinkProvider.ts | 28 ++++++++++++------- src/vs/editor/common/modes.ts | 1 + src/vs/editor/contrib/links/getLinks.ts | 7 ++++- src/vs/editor/contrib/links/links.ts | 17 +++++++++++ src/vs/monaco.d.ts | 1 + src/vs/vscode.proposed.d.ts | 10 +++++++ .../workbench/api/common/extHost.protocol.ts | 1 + .../api/common/extHostTypeConverters.ts | 3 +- src/vs/workbench/api/common/extHostTypes.ts | 2 ++ .../api/extHostLanguageFeatures.test.ts | 5 +++- 10 files changed, 62 insertions(+), 13 deletions(-) diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index 39190f78a53..548205566af 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -5,17 +5,20 @@ import * as path from 'path'; import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; import { OpenDocumentLinkCommand } from '../commands/openDocumentLink'; import { getUriForLinkWithKnownExternalScheme } from '../util/links'; -function normalizeLink( +const localize = nls.loadMessageBundle(); + +function parseLink( document: vscode.TextDocument, link: string, base: string -): vscode.Uri { +): { uri: vscode.Uri, tooltip?: string } { const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); if (externalSchemeUri) { - return externalSchemeUri; + return { uri: externalSchemeUri }; } // Assume it must be an relative or absolute file path @@ -34,7 +37,10 @@ function normalizeLink( resourcePath = base ? path.join(base, tempUri.path) : tempUri.path; } - return OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment); + return { + uri: OpenDocumentLinkCommand.createCommandUri(resourcePath, tempUri.fragment), + tooltip: localize('documentLink.tooltip', 'follow link') + }; } function matchAll( @@ -61,9 +67,12 @@ function extractDocumentLink( const linkStart = document.positionAt(offset); const linkEnd = document.positionAt(offset + link.length); try { - return new vscode.DocumentLink( + const { uri, tooltip } = parseLink(document, link, base); + const documentLink = new vscode.DocumentLink( new vscode.Range(linkStart, linkEnd), - normalizeLink(document, link, base)); + uri); + documentLink.tooltip = tooltip; + return documentLink; } catch (e) { return undefined; } @@ -144,11 +153,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { } } - for (const definition of Array.from(definitions.values())) { + for (const definition of definitions.values()) { try { - results.push(new vscode.DocumentLink( - definition.linkRange, - normalizeLink(document, definition.link, base))); + const { uri } = parseLink(document, definition.link, base); + results.push(new vscode.DocumentLink(definition.linkRange, uri)); } catch (e) { // noop } diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 90833069146..f5c02abdf05 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1000,6 +1000,7 @@ export interface IInplaceReplaceSupportResult { export interface ILink { range: IRange; url?: URI | string; + tooltip?: string; } export interface ILinksList { diff --git a/src/vs/editor/contrib/links/getLinks.ts b/src/vs/editor/contrib/links/getLinks.ts index 5745767952c..140d1f0ef45 100644 --- a/src/vs/editor/contrib/links/getLinks.ts +++ b/src/vs/editor/contrib/links/getLinks.ts @@ -27,7 +27,8 @@ export class Link implements ILink { toJSON(): ILink { return { range: this.range, - url: this.url + url: this.url, + tooltip: this.tooltip }; } @@ -39,6 +40,10 @@ export class Link implements ILink { return this._link.url; } + get tooltip(): string | undefined { + return this._link.tooltip; + } + resolve(token: CancellationToken): Promise { if (this._link.url) { try { diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index f44dbff1b0b..ed3b65ef042 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -111,6 +111,23 @@ class LinkOccurrence { } private static _getOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions { + const options = { ...this._getBaseOptions(link, useMetaKey, isActive) }; + if (typeof link.tooltip === 'string') { + const message = new MarkdownString().appendText( + platform.isMacintosh + ? useMetaKey + ? nls.localize('links.custom.mac', "Cmd + click to {0}", link.tooltip) + : nls.localize('links.custom.mac.al', "Option + click to {0}", link.tooltip) + : useMetaKey + ? nls.localize('links.custom', "Ctrl + click to {0}", link.tooltip) + : nls.localize('links.custom.al', "Alt + click to {0}", link.tooltip) + ); + options.hoverMessage = message; + } + return options; + } + + private static _getBaseOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions { if (link.url && /^command:/i.test(link.url.toString())) { if (useMetaKey) { return (isActive ? decoration.metaCommandActive : decoration.metaCommand); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index a99de0ecaf3..625a4707015 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5254,6 +5254,7 @@ declare namespace monaco.languages { export interface ILink { range: IRange; url?: Uri | string; + tooltip?: string; } export interface ILinksList { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index c08a3725b07..6ed98933296 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1426,4 +1426,14 @@ declare module 'vscode' { //#endregion + //#region DocumentLink tooltip mjbvz + + interface DocumentLink { + /** + * The tooltip text when you hover over this link. + */ + tooltip?: string; + } + + // #endregion } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 3386015e6c4..acbf689c537 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -996,6 +996,7 @@ export interface LinkDto { cacheId?: ChainedCacheId; range: IRange; url?: string | UriComponents; + tooltip?: string; } export interface CodeLensDto extends ObjectIdentifier { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 2a499df5b16..49c911e2f9c 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -808,7 +808,8 @@ export namespace DocumentLink { export function from(link: vscode.DocumentLink): modes.ILink { return { range: Range.from(link.range), - url: link.target + url: link.target, + tooltip: link.tooltip }; } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index e9cc8187307..9c2bcd503a5 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1440,6 +1440,8 @@ export class DocumentLink { target?: URI; + tooltip?: string; + constructor(range: Range, target: URI | undefined) { if (target && !(target instanceof URI)) { throw illegalArgument('target'); diff --git a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts index a31180c8d3b..d73ba1096ac 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -1041,7 +1041,9 @@ suite('ExtHostLanguageFeatures', function () { disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider { provideDocumentLinks() { - return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))]; + const link = new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3')); + link.tooltip = 'tooltip'; + return [link]; } })); @@ -1051,6 +1053,7 @@ suite('ExtHostLanguageFeatures', function () { let [first] = links; assert.equal(first.url, 'foo:bar#3'); assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 2, endColumn: 2 }); + assert.equal(first.tooltip, 'tooltip'); }); test('Links, evil provider', async () => { -- GitLab