开发背景与最终功能
需要维护一些老项目,同时开发新项目时,切换nvm很烦人
最终实现vscode插件:每个vscode实例打开一个项目,切换vscode实例时能自动切换版本(需要项目根目录有一个.nvmrc文件)
插件下载
vscode插件市场搜索vscode-nvmrc
设计思路
项目根目录新建.nvmrc
文件,这是nvm的官方文件,当使用nvm use
时会自动查找这个文件,而windows系统一般使用的是nvm-for-windows
,它是由另一个开发者维护的windows版本,并不支持nvm use
查找.nvmrc
不过这并不影响vscode插件中实现nvm use
功能,只不过了解下.nvmrc
是nvm的官方文件
话不多说,上代码,很简单,vscode插件方法vscode.window.onDidChangeWindowState
中读取下.nvmrc
文件,e.focused
表示当vscode窗口显示时触发,切换vscode实例时能够触发,然后调用child_process.exec
运行nvm use
import * as vscode from "vscode";
import { exec } from "child_process";
import { readFile } from "fs";
import { resolve } from "path";let statusBar: vscode.StatusBarItem | undefined;
let timeout: NodeJS.Timeout;enum Status {error = "error",
}
function customStatusBar(text: string, type?: Status, time = 4000) {if (statusBar) {statusBar.dispose();}if (timeout) {clearTimeout(timeout);}statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);statusBar.color = "#ffffff";if (type === Status.error) {statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");}if (!type) {statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.warningBackground");}statusBar.text = "vscode-nvmrc: " + text;statusBar.show();timeout = setTimeout(() => {if (statusBar) {statusBar.dispose();}}, time);return;
}function execute(cmd: string) {exec(cmd, (error, stdout, stderr) => {if (error) {customStatusBar(`${error}`);} else {if (stderr) {customStatusBar(stderr);} else {customStatusBar(stdout);}}});
}function nvmuse(url: string) {readFile(url, { encoding: "utf8" }, (err, data) => {if (err) {customStatusBar(".nvmrc file not found.");return;}execute("nvm use " + data);});
}function resolveRootPathAndNvmuse() {const workspaceFolders = vscode.workspace.workspaceFolders;if (workspaceFolders && workspaceFolders.length > 0) {const rootPath = workspaceFolders[0].uri.fsPath;if (rootPath) {const url = resolve(rootPath, ".nvmrc");nvmuse(url);}}
}export function activate(context: vscode.ExtensionContext) {resolveRootPathAndNvmuse();const disposable = vscode.window.onDidChangeWindowState((e) => {if (e.focused) {resolveRootPathAndNvmuse();}});context.subscriptions.push(disposable);
}export function deactivate() {}