开发背景与最终功能
需要维护一些老项目,同时开发新项目时,切换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() {}