|
1 | 1 | // The module 'vscode' contains the VS Code extensibility API
|
2 |
| -// Import the module and reference it with the alias vscode in your code below |
3 |
| -import * as vscode from 'vscode'; |
| 2 | +import * as util from 'util'; |
| 3 | +import * as cp from 'child_process'; |
| 4 | +import { workspace, window, commands, Uri, ExtensionContext, QuickPickItem } from 'vscode'; |
| 5 | +import { setupDevContainerFiles, readDevboxJson } from './devcontainer'; |
4 | 6 |
|
5 | 7 | // This method is called when your extension is activated
|
6 | 8 | // Your extension is activated the very first time the command is executed
|
7 |
| -export function activate(context: vscode.ExtensionContext) { |
8 |
| - |
9 |
| - // Use the console to output diagnostic information (console.log) and errors (console.error) |
| 9 | +export function activate(context: ExtensionContext) { |
10 | 10 | // This line of code will only be executed once when your extension is activated
|
11 |
| - vscode.window.onDidOpenTerminal(async (event) => { |
12 |
| - runDevboxShell(); |
| 11 | + initialCheckDevboxJSON(); |
| 12 | + // Creating file watchers to watch for events on devbox.json |
| 13 | + const fswatcher = workspace.createFileSystemWatcher("**/devbox.json", false, false, false); |
| 14 | + fswatcher.onDidDelete(e => commands.executeCommand('setContext', 'devbox.configFileExists', false)); |
| 15 | + fswatcher.onDidCreate(e => commands.executeCommand('setContext', 'devbox.configFileExists', true)); |
| 16 | + fswatcher.onDidChange(e => initialCheckDevboxJSON()); |
| 17 | + |
| 18 | + // Check for devbox.json when a new folder is opened |
| 19 | + workspace.onDidChangeWorkspaceFolders(async (e) => initialCheckDevboxJSON()); |
| 20 | + |
| 21 | + // run devbox shell when terminal is opened |
| 22 | + window.onDidOpenTerminal(async (e) => { |
| 23 | + if (workspace.getConfiguration("devbox").get("autoShellOnTerminal")) { |
| 24 | + await runInTerminal('devbox shell'); |
| 25 | + } |
| 26 | + }); |
| 27 | + |
| 28 | + const devboxAdd = commands.registerCommand('devbox.add', async () => { |
| 29 | + const result = await window.showInputBox({ |
| 30 | + value: '', |
| 31 | + placeHolder: 'Package to add to devbox. E.g., python39', |
| 32 | + }); |
| 33 | + await runInTerminal(`devbox add ${result}`); |
| 34 | + }); |
| 35 | + |
| 36 | + const devboxRun = commands.registerCommand('devbox.run', async () => { |
| 37 | + const items = await getDevboxScripts(); |
| 38 | + if (items.length > 0) { |
| 39 | + const result = await window.showQuickPick(items); |
| 40 | + await runInTerminal(`devbox run ${result}`); |
| 41 | + } else { |
| 42 | + window.showInformationMessage("No scripts found in devbox.json"); |
| 43 | + } |
| 44 | + }); |
| 45 | + |
| 46 | + const devboxShell = commands.registerCommand('devbox.shell', async () => { |
| 47 | + // todo: add support for --config path to devbox.json |
| 48 | + await runInTerminal('devbox shell'); |
| 49 | + }); |
| 50 | + |
| 51 | + const devboxRemove = commands.registerCommand('devbox.remove', async () => { |
| 52 | + const items = await getDevboxPackages(); |
| 53 | + if (items.length > 0) { |
| 54 | + const result = await window.showQuickPick(items); |
| 55 | + await runInTerminal(`devbox rm ${result}`); |
| 56 | + } else { |
| 57 | + window.showInformationMessage("No packages found in devbox.json"); |
| 58 | + } |
| 59 | + }); |
| 60 | + |
| 61 | + const devboxInit = commands.registerCommand('devbox.init', async () => { |
| 62 | + await runInTerminal('devbox init'); |
| 63 | + commands.executeCommand('setContext', 'devbox.configFileExists', true); |
13 | 64 | });
|
| 65 | + |
| 66 | + const setupDevcontainer = commands.registerCommand('devbox.setupDevContainer', async () => { |
| 67 | + const exec = util.promisify(cp.exec); |
| 68 | + // determining cpu architecture - needed for devcontainer dockerfile |
| 69 | + const { stdout, stderr } = await exec("uname -m"); |
| 70 | + let cpuArch = stdout; |
| 71 | + if (stderr) { |
| 72 | + console.log(stderr); |
| 73 | + const response = await window.showErrorMessage( |
| 74 | + "Could not determine the CPU architecture type. Is your architecture type Apple M1/arm64?", |
| 75 | + "Yes", |
| 76 | + "No", |
| 77 | + ); |
| 78 | + cpuArch = response === "Yes" ? "arm64" : "undefined"; |
| 79 | + } |
| 80 | + await setupDevContainerFiles(cpuArch); |
| 81 | + |
| 82 | + }); |
| 83 | + |
| 84 | + context.subscriptions.push(devboxAdd); |
| 85 | + context.subscriptions.push(devboxRun); |
| 86 | + context.subscriptions.push(devboxInit); |
| 87 | + context.subscriptions.push(devboxShell); |
| 88 | + context.subscriptions.push(devboxInstall); |
| 89 | + context.subscriptions.push(setupDevcontainer); |
14 | 90 | }
|
15 | 91 |
|
16 |
| -async function runDevboxShell() { |
| 92 | +async function initialCheckDevboxJSON() { |
| 93 | + // check if there is a workspace folder open |
| 94 | + if (workspace.workspaceFolders) { |
| 95 | + const workspaceUri = workspace.workspaceFolders[0].uri; |
| 96 | + try { |
| 97 | + // check if the folder has devbox.json in it |
| 98 | + await workspace.fs.stat(Uri.joinPath(workspaceUri, "devbox.json")); |
| 99 | + // devbox.json exists setcontext for devbox commands to be available |
| 100 | + commands.executeCommand('setContext', 'devbox.configFileExists', true); |
| 101 | + |
| 102 | + } catch (err) { |
| 103 | + console.log(err); |
| 104 | + // devbox.json does not exist |
| 105 | + commands.executeCommand('setContext', 'devbox.configFileExists', false); |
| 106 | + console.log("devbox.json does not exist"); |
| 107 | + } |
| 108 | + } |
| 109 | +} |
17 | 110 |
|
18 |
| - const result = await vscode.workspace.findFiles('devbox.json'); |
19 |
| - if (result.length > 0) { |
20 |
| - vscode.commands.executeCommand('workbench.action.terminal.sendSequence', { |
21 |
| - 'text': 'devbox shell \r\n' |
| 111 | +async function runInTerminal(cmd: string) { |
| 112 | + // ensure a terminal is open |
| 113 | + // This check has to exist since there is no way for extension to run code in |
| 114 | + // the terminal, unless a terminal session is already open. |
| 115 | + if ((<any>window).terminals.length === 0) { |
| 116 | + window.showErrorMessage('No active terminals. Re-run the command without closing the opened terminal.'); |
| 117 | + window.createTerminal({ name: `Terminal` }).show(); |
| 118 | + } else { // A terminal is open |
| 119 | + // run the given cmd in terminal |
| 120 | + await commands.executeCommand('workbench.action.terminal.sendSequence', { |
| 121 | + 'text': `${cmd}\r\n` |
22 | 122 | });
|
23 | 123 | }
|
24 | 124 | }
|
25 | 125 |
|
| 126 | +async function getDevboxScripts(): Promise<string[]> { |
| 127 | + try { |
| 128 | + if (!workspace.workspaceFolders) { |
| 129 | + window.showInformationMessage('No folder or workspace opened'); |
| 130 | + return []; |
| 131 | + } |
| 132 | + const workspaceUri = workspace.workspaceFolders[0].uri; |
| 133 | + const devboxJson = await readDevboxJson(workspaceUri); |
| 134 | + return Object.keys(devboxJson['shell']['scripts']); |
| 135 | + } catch (error) { |
| 136 | + console.error('Error processing devbox.json - ', error); |
| 137 | + return []; |
| 138 | + } |
| 139 | +} |
| 140 | + |
| 141 | +async function getDevboxPackages(): Promise<string[]> { |
| 142 | + try { |
| 143 | + if (!workspace.workspaceFolders) { |
| 144 | + window.showInformationMessage('No folder or workspace opened'); |
| 145 | + return []; |
| 146 | + } |
| 147 | + const workspaceUri = workspace.workspaceFolders[0].uri; |
| 148 | + const devboxJson = await readDevboxJson(workspaceUri); |
| 149 | + return devboxJson['packages']; |
| 150 | + } catch (error) { |
| 151 | + console.error('Error processing devbox.json - ', error); |
| 152 | + return []; |
| 153 | + } |
| 154 | +} |
| 155 | + |
26 | 156 | // This method is called when your extension is deactivated
|
27 | 157 | export function deactivate() { }
|
0 commit comments