如标题所言, 废话不多说先来个祖传的 hello world
hello world
先安装项目生成器
npm install -g yo generator-code
然后生成项目
yo code
先选一下模板的类型(这里以TypeScript为例)
然后是填一下项目名, 项目描述, 扩展标识符, 是否初始化git, 选择包管理器等信息(嫌麻烦可以指定项目名然后一路回车即可)
然后就会创建一些文件并下载依赖, 安装完依赖会出现如下提示, 问要不要用vscode打开这个项目, 回车即可
打开vscode后按F5
启动调试, 稍等会打开一个扩展开发宿主的新窗口, 按F1
输入hello world然后回车, 会看到有下角的信息提示, 如下所示:
如果发现
F1
没有hello world
命令, 可以检查一下package.json
中的engines.vscode
字段指定的版本是不是大于你使用的vscode的版本, 该字段是配置兼容vscode的最低版本
项目结构
生成的项目基本结构如下:
.
│ .eslintrc.json
├─ .git
│ ...
│ .gitignore
│ .vscodeignore
│ CHANGELOG.md // 更新日志
│ package-lock.json
│ package.json // 配置文件
│ README.md
│ tsconfig.json
│ vsc-extension-quickstart.md // 快速上手
├─.vscode
│ ...
└─src
│ extension.ts // 扩展的主文件
└─test
│ runTest.ts
└─suite
extension.test.ts
index.ts
目录结构中的文件都是项目中常见的, 有两个文件是比较重要的那就是package.json
和src/extension.ts
, 如下:
package.json
: 不用说, 本身就很重要, 不过在vscode的扩展开发中, 该文件还可以指定相关的配置, 比如: 声明扩展激活的事件集合, 声明扩展的贡献点(Contribution Points)等等src/extension.ts
: 这个文件是扩展的入口文件, 默认会暴露两个函数activate
和deactivate
, 前者是当扩展被激活时触发而后者是当扩展被停用时触发
命令
有关命令的可以先看一下hello world的例子, 先来看一下package.json
命令相关的配置, 如下:
{
// ...
"activationEvents": [ // 声明扩展的事件集合
// onCommand:xxx 表示接受到指定的命令时激活事件, 下面的就是 learn-vscode-extends.helloWorld
"onCommand:learn-vscode-extends.helloWorld"
],
"contributes": { // 贡献点配置
"commands": [ // 命令配置(出现在`F1`的命令栏中)
{
"command": "learn-vscode-extends.helloWorld", // 当此命令执行是触发对应命令id的事件
"title": "Hello World" // 显示的文本, 会在`F1`命令栏显示(可以是中文)
}
]
}
// ...
}
再来看看src/extension.ts
文件内容, 如下:
// vscode 模块包含 vscode 扩展的相关 API
import * as vscode from "vscode";
// 当扩展被激活时触发
export function activate(context: vscode.ExtensionContext) {
// 此代码行仅在激活扩展时执行一次
console.log("active 函数运行了");
// 注册一个 learn-vscode-extends.helloWorld 事件
const disposable = vscode.commands.registerCommand("learn-vscode-extends.helloWorld", () => {
// 触发此事件会显示一段 Info 类型的 message
vscode.window.showInformationMessage("这是我的第一个 vscode 插件");
});
// 将注册的事件添加到上下文对象中
context.subscriptions.push(disposable);
}
// 当扩展被停用时触发
export function deactivate() {}
梳理一下相关的配置: package.json
的contributes.commands
中声明的是在F1
命令栏中出现的命令, 当指定的命令被执行时, 就会去触发对应命令id的事件, 也就是在activationEvents
集合中声明为命令相关的onCommand:xxx
配置, 然后需要为vscode注册相关的命令回调, 也就是src/extension.ts
里的vscode.commands.registerCommand("命令id", 回调函数)
对应的回调函数(注意这些三者注册或配置的命令id(标识符)必须是要保持一致的不然就会报找不到对应命令的错误)
命令的其他配置
命令还可以添加分组和icon, 如下:
"contributes": {
"commands": [
{
"command": "learn-vscode-extends.helloWorld1", // 绑定的命令id
"title": "Hello World",
"category": "分组1", // 指定分组
// "icon": "$(book)" // 指定 icon, 这个icon会在该命令绑定给编辑器标题菜单栏时显示
},
{
"command": "learn-vscode-extends.helloWorld2",
"title": "Hello World",
"category": "分组2"
}
]
}
对应的命令栏ui如下:
icon的显示需要用到
menu
配置, 这个之后会介绍
执行内置命令
使用vscode.commands.executeCommand
可以执行一些内置的命令, 修改hello
的例子如下:
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand("learn-vscode-extends.helloWorld", () => {
// 执行vscode内置的命令, 查看发行说明
vscode.commands.executeCommand("update.showCurrentReleaseNotes");
});
context.subscriptions.push(disposable);
}
export function deactivate() {}
F5
然后F1
输入hello world
就可以看到vscode的发行说明页了
具体的命令id获取可以从键盘快捷方式中查看, 如下:
也可以通过vscode.commands.getCommands
来获取所有的命令
// 获取所有命令
vscode.commands.getCommands().then(allCommands => {
console.log("所有的命令", allCommands);
});
注意: 有一些比较复杂的内置命令是需要传递参数, 具体的可以查看官方的指南
通知和状态栏
通知
vscode提供的通知分别是info
, warning
, error
三种, 基本的使用如下:
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
// 注册一个 learn-vscode-extends.message 命令
const disposable = vscode.commands.registerCommand("learn-vscode-extends.message", () => {
// 右下角三种不同的通知提示
vscode.window.showInformationMessage("info message");
vscode.window.showWarningMessage("warning message");
vscode.window.showErrorMessage("error message");
});
context.subscriptions.push(disposable);
}
export function deactivate() { }
别忘了在package.json
中注册对应的命令
"activationEvents": [
"onCommand:learn-vscode-extends.message"
],
"contributes": {
"commands": [
{
"command": "learn-vscode-extends.message",
"title": "测试通知"
}
]
},
效果如下:
带按钮的通知
如果需要通知有对应的按钮只需要, 再传递对应的按钮文本参数即可, 如下所示:
// 第一个参数是信息, 后续的参数会生成对应的按钮, then 回调收到点击的按钮文本
vscode.window.showInformationMessage("是否要打开文件选择", "是", "否", "不再提示")
.then(result => {
switch (result) {
case "是":
vscode.window.showOpenDialog()
.then((value: vscode.Uri[] | undefined) => {
if (value) {
// 选中的文件路径(默认单选)
const filePath = value[0].fsPath;
vscode.window.showInformationMessage(filePath);
}
});
break;
case "不再提示":
// ...
break;
default:
break;
}
});
效果如下:
带进度的通知
使用vscode.window.withProgress
即可实现带通知的回调, 如下:
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand("learn-vscode-extends.message", () => {
vscode.window.withProgress({
// 进度显示类型, Notification(右下角通知和进度) | Window(状态栏转圈) | SourceControl(源代码控制栏图标和进度)
location: vscode.ProgressLocation.Notification,
title: "获取网络资源", // 标题
cancellable: true // 显示取消按钮
}, (progress, token) => {
// 取消按钮回调
token.onCancellationRequested(() => {
vscode.window.showInformationMessage("取消成功");
});
// 进度0%, 无文本
progress.report({ increment: 0 });
// 修改进度条到10%, 增加文本
setTimeout(() => {
progress.report({ increment: 10, message: "发送请求中.." });
}, 1000);
setTimeout(() => {
progress.report({ increment: 30, message: "请求发送成功..." });
}, 2000);
setTimeout(() => {
progress.report({ increment: 50, message: "请求已到达..." });
}, 3000);
// 4秒后关闭
return new Promise<void>(resolve => {
setTimeout(resolve, 4000);
});
});
});
context.subscriptions.push(disposable);
}
export function deactivate() { }
三种不同的通知效果如下:
vscode.ProgressLocation.Notification
vscode.ProgressLocation.Window
vscode.ProgressLocation.SourceControl
状态栏
状态栏就是类似上面的vscode.ProgressLocation.Window
通知一样, 只不过自定义, 先看一下最简单状态栏使用vscode.window.setStatusBarMessage
皆可创建
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand("learn-vscode-extends.status", () => {
// 添加一个默认的状态栏
const loading = vscode.window.setStatusBarMessage("loading...");
setTimeout(() => {
// 1.5s后释放
loading.dispose();
}, 1500);
});
context.subscriptions.push(disposable);
}
export function deactivate() { }
别忘了要在package.json
里命令注册和声明learn-vscode-extends.status
, 效果如下:
状态栏的文本是可以使用vscdoe提供的一些图标还有指定图标的旋转动画, 图标使用格式为:$(xxx)
, 动画使用格式为$(xxx~动画名称)
, 如下:
const loading = vscode.window.setStatusBarMessage("$(loading~spin) loading... $(book)");
效果为:
需要注意的是, 不是所有图标都支持动画只有这三个图标才支持 sync, loading, gear
自定义状态栏
vscode.window.setStatusBarMessage
只能创建最基本的状态栏, 使用vscode.window.createStatusBarItem
可以创建自定义的状态栏, 如下:
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand("learn-vscode-extends.status", () => {
// 创建一个状态栏对象, 右对应, 优先级 999
const statusBarItem: vscode.StatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 9999);
statusBarItem.text = "$(loading~spin) loading..."; // 文本和图标(动画)
statusBarItem.tooltip = "鼠标的悬浮提示"; // 鼠标的悬浮提示
statusBarItem.backgroundColor = new vscode.ThemeColor("statusBarItem.warningBackground"); // 背景颜色(只支持 warningBackground | errorBackground)
statusBarItem.command = "learn-vscode-extends.statusClick"; // 绑定点击的命令
// 显示
statusBarItem.show();
setTimeout(() => {
// 隐藏
statusBarItem.hide();
// 注销
// statusBarItem.dispose();
}, 5000);
});
context.subscriptions.push(disposable);
// 状态栏点击命令
context.subscriptions.push(vscode.commands.registerCommand("learn-vscode-extends.statusClick", () => {
vscode.window.showInformationMessage("状态栏的点击命令回调");
}));
}
export function deactivate() { }
别忘了注册learn-vscode-extends.statusClick
命令, 效果如下: