From faf846601236640bc6a7dccebe2563216eba1916 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 20:20:29 +0000 Subject: [PATCH 1/3] Initial plan From cd6a37a777a89a28db756abe2dc85e28df3d2eac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 20:24:56 +0000 Subject: [PATCH 2/3] Add URI-based programmatic launch for file viewer --- README.md | 23 ++++++++++++++++++++ out/extension.js | 30 ++++++++++++++++++++++++-- out/extension.js.map | 2 +- out/test/suite/uri-handler.test.js | 20 +++++++++++++++++ out/test/suite/uri-handler.test.js.map | 1 + package.json | 3 ++- src/extension.ts | 28 +++++++++++++++++++++++- src/test/suite/uri-handler.test.ts | 19 ++++++++++++++++ 8 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 out/test/suite/uri-handler.test.js create mode 100644 out/test/suite/uri-handler.test.js.map create mode 100644 src/test/suite/uri-handler.test.ts diff --git a/README.md b/README.md index 218cd6efd..50cb3103c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,29 @@ Open the command palette (`⌘ + ⇧ + p`) and simply call the `Start Protein Vi Right-click on the file or selection of files in the file editor and select `Launch Protein Viewer from File(s)` +You can also launch programmatically (for example from bash or Python) via a VS Code URI: + +`vscode://ArianJamasb.protein-viewer/open?file=/absolute/path/to/first.pdb&file=/absolute/path/to/second.cif` + +The `file` query parameter can be repeated for multiple files. + +Example from bash: + +```bash +xdg-open "vscode://ArianJamasb.protein-viewer/open?file=$(python -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' /abs/a.pdb)&file=$(python -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' /abs/b.pdb)" +``` + +Example from Python: + +```python +import urllib.parse +import webbrowser + +files = ["/abs/a.pdb", "/abs/b.cif"] +query = "&".join(f"file={urllib.parse.quote(f)}" for f in files) +webbrowser.open(f"vscode://ArianJamasb.protein-viewer/open?{query}") +``` + **✅ Supported Formats** * `.pdb` diff --git a/out/extension.js b/out/extension.js index c2029b792..a9e8b7624 100644 --- a/out/extension.js +++ b/out/extension.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.activate = void 0; +exports.getFilesFromLaunchUri = exports.activate = void 0; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const node_fetch_1 = require("node-fetch"); @@ -17,7 +17,10 @@ async function activate(context) { const activateFromFiles = vscode.commands.registerCommand("protein-viewer.activateFromFiles", (file_uri, selectedFiles) => { console.log(file_uri); console.log(selectedFiles); - ProteinViewerPanel_1.ProteinViewerPanel.renderFromFiles(context.extensionUri, selectedFiles); + const filesToOpen = selectedFiles?.length ? selectedFiles : (file_uri ? [file_uri] : []); + if (filesToOpen.length > 0) { + ProteinViewerPanel_1.ProteinViewerPanel.renderFromFiles(context.extensionUri, filesToOpen); + } }); const activateFromFolder = vscode.commands.registerCommand("protein-viewer.activateFromFolder", (folder_uri) => { vscode.workspace.findFiles(`${vscode.workspace.asRelativePath(folder_uri)}/*.pdb`).then((files_uri) => { @@ -34,11 +37,22 @@ async function activate(context) { }); }); }); + const uriHandler = vscode.window.registerUriHandler({ + handleUri(uri) { + const filesToOpen = getFilesFromLaunchUri(uri); + if (filesToOpen.length === 0) { + vscode.window.showErrorMessage("Protein Viewer: no files were provided in URI. Use ?file=/abs/path/to/file.pdb (repeat file for multiple files)."); + return; + } + ProteinViewerPanel_1.ProteinViewerPanel.renderFromFiles(context.extensionUri, filesToOpen); + } + }); //context.subscriptions.push(...[helloCommand, activateFromFile]); context.subscriptions.push(helloCommand); context.subscriptions.push(activateFromFiles); context.subscriptions.push(activateFromFolder); context.subscriptions.push(ESMFold); + context.subscriptions.push(uriHandler); } exports.activate = activate; // this method is called when your extension is deactivated @@ -83,4 +97,16 @@ async function getfold(sequence) { const body = await response.text(); return body; } +function getFilesFromLaunchUri(uri) { + if (uri.path !== "/open") { + return []; + } + const params = new URLSearchParams(uri.query); + const files = params.getAll("file") + .map(file => file.trim()) + .filter(file => file.length > 0) + .map(file => file.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); + return files; +} +exports.getFilesFromLaunchUri = getFilesFromLaunchUri; //# sourceMappingURL=extension.js.map \ No newline at end of file diff --git a/out/extension.js.map b/out/extension.js.map index cfd8963dd..b231ee936 100644 --- a/out/extension.js.map +++ b/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/out/test/suite/uri-handler.test.js b/out/test/suite/uri-handler.test.js new file mode 100644 index 000000000..ee043e094 --- /dev/null +++ b/out/test/suite/uri-handler.test.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert = require("assert"); +const vscode = require("vscode"); +const extension_1 = require("../../extension"); +suite('URI Handler Test Suite', () => { + test('parses repeated file params from launch uri', () => { + const launchUri = vscode.Uri.parse('vscode://ArianJamasb.protein-viewer/open?file=%2Ftmp%2Fa.pdb&file=%2Ftmp%2Fb.cif'); + const files = (0, extension_1.getFilesFromLaunchUri)(launchUri); + assert.strictEqual(files.length, 2); + assert.strictEqual(files[0].fsPath, '/tmp/a.pdb'); + assert.strictEqual(files[1].fsPath, '/tmp/b.cif'); + }); + test('ignores non-open uri path', () => { + const launchUri = vscode.Uri.parse('vscode://ArianJamasb.protein-viewer/other?file=%2Ftmp%2Fa.pdb'); + const files = (0, extension_1.getFilesFromLaunchUri)(launchUri); + assert.strictEqual(files.length, 0); + }); +}); +//# sourceMappingURL=uri-handler.test.js.map \ No newline at end of file diff --git a/out/test/suite/uri-handler.test.js.map b/out/test/suite/uri-handler.test.js.map new file mode 100644 index 000000000..30cbbda7b --- /dev/null +++ b/out/test/suite/uri-handler.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"uri-handler.test.js","sourceRoot":"","sources":["../../../src/test/suite/uri-handler.test.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AACjC,iCAAiC;AACjC,+CAAwD;AAExD,KAAK,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACpC,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,kFAAkF,CAAC,CAAC;QACvH,MAAM,KAAK,GAAG,IAAA,iCAAqB,EAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACtC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACpG,MAAM,KAAK,GAAG,IAAA,iCAAqB,EAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/package.json b/package.json index 726f6c2f1..e35e63a3a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "onCommand:protein-viewer.start", "onCommand:protein-viewer.activateFromFiles", "onCommand:protein-viewer.activateFromFolder", - "onCommand:protein-viewer.ESMFold" + "onCommand:protein-viewer.ESMFold", + "onUri" ], "main": "./out/extension.js", "contributes": { diff --git a/src/extension.ts b/src/extension.ts index bea71387d..87f305c1b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,7 +17,10 @@ export async function activate(context: vscode.ExtensionContext) { const activateFromFiles = vscode.commands.registerCommand("protein-viewer.activateFromFiles", (file_uri: vscode.Uri, selectedFiles: vscode.Uri[]) => { console.log(file_uri); console.log(selectedFiles); - ProteinViewerPanel.renderFromFiles(context.extensionUri, selectedFiles); + const filesToOpen = selectedFiles?.length ? selectedFiles : (file_uri ? [file_uri] : []); + if (filesToOpen.length > 0) { + ProteinViewerPanel.renderFromFiles(context.extensionUri, filesToOpen); + } }); const activateFromFolder = vscode.commands.registerCommand("protein-viewer.activateFromFolder", (folder_uri: vscode.Uri) => { @@ -39,11 +42,22 @@ export async function activate(context: vscode.ExtensionContext) { }); }); + const uriHandler = vscode.window.registerUriHandler({ + handleUri(uri: vscode.Uri) { + const filesToOpen = getFilesFromLaunchUri(uri); + if (filesToOpen.length === 0) { + vscode.window.showErrorMessage("Protein Viewer: no files were provided in URI. Use ?file=/abs/path/to/file.pdb (repeat file for multiple files)."); + return; + } + ProteinViewerPanel.renderFromFiles(context.extensionUri, filesToOpen); + } + }); //context.subscriptions.push(...[helloCommand, activateFromFile]); context.subscriptions.push(helloCommand); context.subscriptions.push(activateFromFiles); context.subscriptions.push(activateFromFolder); context.subscriptions.push(ESMFold); + context.subscriptions.push(uriHandler); } // this method is called when your extension is deactivated @@ -97,3 +111,15 @@ async function getfold(sequence: string | undefined) { const body = await response.text(); return body } + +export function getFilesFromLaunchUri(uri: vscode.Uri): vscode.Uri[] { + if (uri.path !== "/open") { + return []; + } + const params = new URLSearchParams(uri.query); + const files = params.getAll("file") + .map(file => file.trim()) + .filter(file => file.length > 0) + .map(file => file.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); + return files; +} diff --git a/src/test/suite/uri-handler.test.ts b/src/test/suite/uri-handler.test.ts new file mode 100644 index 000000000..86fec2a55 --- /dev/null +++ b/src/test/suite/uri-handler.test.ts @@ -0,0 +1,19 @@ +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { getFilesFromLaunchUri } from '../../extension'; + +suite('URI Handler Test Suite', () => { + test('parses repeated file params from launch uri', () => { + const launchUri = vscode.Uri.parse('vscode://ArianJamasb.protein-viewer/open?file=%2Ftmp%2Fa.pdb&file=%2Ftmp%2Fb.cif'); + const files = getFilesFromLaunchUri(launchUri); + assert.strictEqual(files.length, 2); + assert.strictEqual(files[0].fsPath, '/tmp/a.pdb'); + assert.strictEqual(files[1].fsPath, '/tmp/b.cif'); + }); + + test('ignores non-open uri path', () => { + const launchUri = vscode.Uri.parse('vscode://ArianJamasb.protein-viewer/other?file=%2Ftmp%2Fa.pdb'); + const files = getFilesFromLaunchUri(launchUri); + assert.strictEqual(files.length, 0); + }); +}); From 2b2ad20c150a3e59386518cc02fffcf5c85900f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 20:27:00 +0000 Subject: [PATCH 3/3] Refine URI launch docs and handler parsing cleanup --- README.md | 10 ++++++++-- out/extension.js | 3 ++- out/extension.js.map | 2 +- src/extension.ts | 3 ++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 50cb3103c..a7e84adbe 100644 --- a/README.md +++ b/README.md @@ -33,10 +33,16 @@ You can also launch programmatically (for example from bash or Python) via a VS The `file` query parameter can be repeated for multiple files. -Example from bash: +Example from bash (using Python for URL encoding): ```bash -xdg-open "vscode://ArianJamasb.protein-viewer/open?file=$(python -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' /abs/a.pdb)&file=$(python -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' /abs/b.pdb)" +python - <<'PY' +import urllib.parse +import webbrowser +files = ["/abs/a.pdb", "/abs/b.cif"] +query = "&".join(f"file={urllib.parse.quote(f)}" for f in files) +webbrowser.open(f"vscode://ArianJamasb.protein-viewer/open?{query}") +PY ``` Example from Python: diff --git a/out/extension.js b/out/extension.js index a9e8b7624..9864291db 100644 --- a/out/extension.js +++ b/out/extension.js @@ -7,6 +7,7 @@ const node_fetch_1 = require("node-fetch"); const vscode = require("vscode"); const ProteinViewerPanel_1 = require("./panels/ProteinViewerPanel"); const path = require('node:path'); +const URI_SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*:/; async function activate(context) { const helloCommand = vscode.commands.registerCommand("protein-viewer.start", () => { showInputBox().then((accession) => { @@ -105,7 +106,7 @@ function getFilesFromLaunchUri(uri) { const files = params.getAll("file") .map(file => file.trim()) .filter(file => file.length > 0) - .map(file => file.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); + .map(file => file.match(URI_SCHEME_PATTERN) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); return files; } exports.getFilesFromLaunchUri = getFilesFromLaunchUri; diff --git a/out/extension.js.map b/out/extension.js.map index b231ee936..c19d411f4 100644 --- a/out/extension.js.map +++ b/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 87f305c1b..d43cfdc80 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,6 +4,7 @@ import fetch from 'node-fetch'; import * as vscode from 'vscode'; import { ProteinViewerPanel } from "./panels/ProteinViewerPanel"; const path = require('node:path'); +const URI_SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*:/; export async function activate(context: vscode.ExtensionContext) { @@ -120,6 +121,6 @@ export function getFilesFromLaunchUri(uri: vscode.Uri): vscode.Uri[] { const files = params.getAll("file") .map(file => file.trim()) .filter(file => file.length > 0) - .map(file => file.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); + .map(file => file.match(URI_SCHEME_PATTERN) ? vscode.Uri.parse(file, true) : vscode.Uri.file(file)); return files; }