Skip to content

Commit a35fcaf

Browse files
authored
Merge pull request #304 from DunetsNM/open-doc-on-hackage
add "Reopen on Hackage (beta)" hyperlink to doc window
2 parents f09ce86 + 7c830ae commit a35fcaf

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

src/docsBrowser.ts

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
CompletionItem,
77
CompletionList,
88
Disposable,
9+
env,
910
Hover,
1011
MarkdownString,
1112
MarkedString,
@@ -23,24 +24,48 @@ export namespace DocsBrowser {
2324

2425
// registers the browser in VSCode infrastructure
2526
export function registerDocsBrowser(): Disposable {
26-
return commands.registerCommand('haskell.showDocumentation', ({ title, path }: { title: string; path: string }) => {
27-
const arr = path.match(/([^\/]+)\.[^.]+$/);
28-
const ttl = arr !== null && arr.length === 2 ? arr[1].replace(/-/gi, '.') : title;
29-
const documentationDirectory = dirname(path);
30-
let panel;
31-
try {
32-
// Make sure to use Uri.parse here, as path will already have 'file:///' in it
33-
panel = window.createWebviewPanel('haskell.showDocumentationPanel', ttl, ViewColumn.Beside, {
34-
localResourceRoots: [Uri.parse(documentationDirectory)],
35-
enableFindWidget: true,
36-
});
37-
const uri = panel.webview.asWebviewUri(Uri.parse(path));
38-
panel.webview.html = `<iframe src="${uri}" frameBorder = "0" style = "background: white; width: 100%; height: 100%; position:absolute; left: 0; right: 0; bottom: 0; top: 0px;" /> `;
39-
} catch (e) {
40-
window.showErrorMessage(e);
27+
return commands.registerCommand(
28+
'haskell.showDocumentation',
29+
async ({ title, localPath, hackageUri }: { title: string; localPath: string; hackageUri: string }) => {
30+
const arr = localPath.match(/([^\/]+)\.[^.]+$/);
31+
const ttl = arr !== null && arr.length === 2 ? arr[1].replace(/-/gi, '.') : title;
32+
const documentationDirectory = dirname(localPath);
33+
let panel;
34+
try {
35+
// Make sure to use Uri.parse here, as path will already have 'file:///' in it
36+
panel = window.createWebviewPanel('haskell.showDocumentationPanel', ttl, ViewColumn.Beside, {
37+
localResourceRoots: [Uri.parse(documentationDirectory)],
38+
enableFindWidget: true,
39+
enableCommandUris: true,
40+
});
41+
const uri = panel.webview.asWebviewUri(Uri.parse(localPath));
42+
43+
const encoded = encodeURIComponent(JSON.stringify({ hackageUri }));
44+
const hackageCmd = 'command:haskell.openDocumentationOnHackage?' + encoded;
45+
46+
panel.webview.html = `<div><a href="${hackageCmd}">Reopen on Hackage</a></div>
47+
<div><iframe src="${uri}" frameBorder = "0" style = "background: white; width: 100%; height: 100%; position:absolute; left: 0; right: 0; bottom: 0; top: 30px;"/></div>`;
48+
} catch (e) {
49+
await window.showErrorMessage(e);
50+
}
51+
return panel;
4152
}
42-
return panel;
43-
});
53+
);
54+
}
55+
56+
export function registerDocsOpenOnHackage(): Disposable {
57+
return commands.registerCommand(
58+
'haskell.openDocumentationOnHackage',
59+
async ({ hackageUri }: { hackageUri: string }) => {
60+
try {
61+
// open on Hackage and close the original webview in VS code
62+
await env.openExternal(Uri.parse(hackageUri));
63+
await commands.executeCommand('workbench.action.closeActiveEditor');
64+
} catch (e) {
65+
await window.showErrorMessage(e);
66+
}
67+
}
68+
);
4469
}
4570

4671
export function hoverLinksMiddlewareHook(
@@ -85,11 +110,18 @@ export namespace DocsBrowser {
85110

86111
function processLink(ms: MarkedString): string | MarkdownString {
87112
function transform(s: string): string {
88-
return s.replace(/\[(.+)\]\((file:.+\/doc\/.+\.html#?.*)\)/gi, (all, title, path) => {
89-
const encoded = encodeURIComponent(JSON.stringify({ title, path }));
90-
const cmd = 'command:haskell.showDocumentation?' + encoded;
91-
return `[${title}](${cmd})`;
92-
});
113+
return s.replace(
114+
/\[(.+)\]\((file:.+\/doc\/(?:.*html\/libraries\/)?([^\/]+)\/(src\/)?(.+\.html#?.*))\)/gi,
115+
(all, title, localPath, packageName, maybeSrcDir, fileAndAnchor) => {
116+
if (!maybeSrcDir) {
117+
maybeSrcDir = '';
118+
}
119+
const hackageUri = `https://hackage.haskell.org/package/${packageName}/docs/${maybeSrcDir}${fileAndAnchor}`;
120+
const encoded = encodeURIComponent(JSON.stringify({ title, localPath, hackageUri }));
121+
const cmd = 'command:haskell.showDocumentation?' + encoded;
122+
return `[${title}](${cmd})`;
123+
}
124+
);
93125
}
94126
if (typeof ms === 'string') {
95127
return transform(ms as string);

src/extension.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ export async function activate(context: ExtensionContext) {
6565
// Set up the documentation browser.
6666
const docsDisposable = DocsBrowser.registerDocsBrowser();
6767
context.subscriptions.push(docsDisposable);
68+
69+
const openOnHackageDisposable = DocsBrowser.registerDocsOpenOnHackage();
70+
context.subscriptions.push(openOnHackageDisposable);
6871
}
6972

7073
function findManualExecutable(uri: Uri, folder?: WorkspaceFolder): string | null {

0 commit comments

Comments
 (0)