From 828be4c486ee6098a69a9759805992a9a60b0304 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Wed, 5 Apr 2023 12:30:52 +0100 Subject: [PATCH] Added 'open in vscode' for TT --- apps/vscode/package.json | 8 +- apps/vscode/src/extension.ts | 2 + apps/vscode/src/totalTypeScriptCommands.ts | 123 +++++++++++++++++++++ 3 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 apps/vscode/src/totalTypeScriptCommands.ts diff --git a/apps/vscode/package.json b/apps/vscode/package.json index f26e63c..b67f1f1 100644 --- a/apps/vscode/package.json +++ b/apps/vscode/package.json @@ -25,13 +25,7 @@ "Linters" ], "activationEvents": [ - "onLanguage:typescript", - "onLanguage:typescriptreact", - "onLanguage:javascript", - "onLanguage:javascriptreact", - "onLanguage:vue", - "onLanguage:svelte", - "onLanguage:astro" + "*" ], "main": "./out/extension.js", "browser": "./out/extension.js", diff --git a/apps/vscode/src/extension.ts b/apps/vscode/src/extension.ts index c09028e..92cd5d8 100644 --- a/apps/vscode/src/extension.ts +++ b/apps/vscode/src/extension.ts @@ -9,6 +9,7 @@ import { defaultOptions } from './defaultOptions'; import { initDiagnostics } from './initDiagnostics'; import { showBeginnerQuestion } from './showBeginnerQuestion'; import { showTipsQuestion } from './showTipsQuestion'; +import { initTotalTypeScriptCommands } from './totalTypeScriptCommands'; const languages = [ 'typescript', @@ -80,6 +81,7 @@ const isTipComplete = (tipType: Tip['type']) => { export async function activate(context: vscode.ExtensionContext) { initDiagnostics(context); + await initTotalTypeScriptCommands(context); const updateHiddenTips = () => { updateOptions(); diff --git a/apps/vscode/src/totalTypeScriptCommands.ts b/apps/vscode/src/totalTypeScriptCommands.ts new file mode 100644 index 0000000..4860774 --- /dev/null +++ b/apps/vscode/src/totalTypeScriptCommands.ts @@ -0,0 +1,123 @@ +import * as vscode from 'vscode'; + +class UriEventHandler + extends vscode.EventEmitter + implements vscode.UriHandler +{ + public handleUri(uri: vscode.Uri): vscode.ProviderResult { + this.fire(uri); + } +} + +const terminals = new Set(); + +const uriHandler = new UriEventHandler(); + +export const initTotalTypeScriptCommands = async ( + context: vscode.ExtensionContext, +) => { + const openFileAndRunTests = async (config: { + script: string; + fileUri: vscode.Uri; + }) => { + await vscode.window.showTextDocument(config.fileUri); + + terminals.forEach((terminal) => { + try { + terminal.dispose(); + } catch (e) {} + }); + + terminals.clear(); + + const terminal = vscode.window.createTerminal(); + + terminals.add(terminal); + + terminal.sendText(config.script); + terminal.show(true); + }; + + context.subscriptions.push( + vscode.window.registerUriHandler(uriHandler), + uriHandler.event(async (uri) => { + const info = parseQuery<{ + filename: string; + repo: string; + script: string; + }>(uri); + + for (const folder of vscode.workspace.workspaceFolders || []) { + if (folder.name === info.repo) { + await openFileAndRunTests({ + fileUri: vscode.Uri.joinPath(folder.uri, info.filename), + script: info.script, + }); + return; + } + } + + // Tries scanning other workspaces at the same level for the right folder + + const candidateRepos = await vscode.workspace.fs.readDirectory( + vscode.Uri.joinPath( + vscode.Uri.parse(vscode.workspace.rootPath!), + '../', + ), + ); + + const candidateRepo = candidateRepos.find(([name]) => name === info.repo); + + console.log(candidateRepo, info.repo); + + if (candidateRepo) { + const rootUri = vscode.Uri.joinPath( + vscode.Uri.parse(vscode.workspace.rootPath!), + '../', + candidateRepo[0], + ); + + await vscode.workspace.updateWorkspaceFolders( + vscode.workspace.workspaceFolders?.length || 0, + 0, + { + uri: rootUri, + }, + ); + + await openFileAndRunTests({ + fileUri: vscode.Uri.joinPath(rootUri, info.filename), + script: info.script, + }); + return; + } + + vscode.window + .showErrorMessage( + `Could not find the right file in this repository.`, + { + detail: `Looks like this isn't total-typescript/${info.repo}. Would you like to clone it?`, + modal: true, + }, + 'Clone from GitHub', + ) + .then((action) => { + if (action === 'Clone from GitHub') { + vscode.env.openExternal( + vscode.Uri.parse( + `https://github.com/total-typescript/${info.repo}`, + ), + ); + } + }); + }), + ); +}; + +function parseQuery(uri: vscode.Uri): T { + return uri.query.split('&').reduce((prev: any, current) => { + const queryString = current.split('='); + prev[queryString[0]] = queryString[1]; + return prev; + }, {}); +}