场景
上一个例子: 自定义侧边栏+面板虽然可以实现我们的功能,但是还是有些缺点的,毕竟我们需要根据文件路径来动态生成我们的面板内容。
以下面例子为例:根据 vscode
工作目录,读取目录中 package.json
文件的 scripts 字段,筛选出符合规范的脚本命令,动态生成我们的按钮
首先需要明确的是:vscode有一个 vscode.workspace.rootPath
,由于后来vscode支持multipleRoot模式,所以这个字段已经过时作废了。我们只能通过 vscode.workspace.workspaceFolders
获取当前工作区所有根文件夹数组;
注意:是得到的跟文件夹数组路径,也就是说,下面这种情况,得到是路径内容是这样的
├── A_Folder
│ ├── B_Folder
│ │ ├── D_Folder
│ │ └──
│ │
│ ├── C_Folder
│ └──
└──
上面得到的只会是 : A_Folder 的路径,得不到下面的 B、C、D路径。
还需要注意的一点是:很难划分这个文件夹是不是属于一个前端工程或者Node工程,这边我是以该文件夹下有没有 package.json
来划分,也就是如果 A下面存在 package.json
,我就认为它是一个完整的工程项目(不把它当作文件夹)
真想得到 A 下面的所有文件夹?
如果你真的想得,我的想法是:只能通过 Node 的 fs 模块去获取 A 文件夹下的文件目录,然后递归,一路找下去,办法总会有的。
OK,扯远了,来看看大概的一个思路
代码展示
先注册一下侧边栏面板
// extension.ts
import * as vscode from 'vscode'
export function activate(context: vscode.ExtensionContext) {
console.log('插件已启动,忙去吧~')
require('./container/commandSet')(context)
}
export function deactivate() {}
不要忘记 package.json
也需要添加
{
"contributes": {
"commands": [],
"viewsWelcome": [
{
"view": "BeeHive-Command",
"contents": "提高你的效率,释放你的双手~"
}
],
"viewsContainers": {
"activitybar": [
{
"id": "sugar",
"title": "Sugar-BeeHive",
"icon": "./assets/logo_default.svg"
}
],
"panel": [
{
"id": "sugar",
"title": "Package Explorer",
"icon": "./assets/logo_default.svg"
}
]
},
"views": {
"sugar": [
{
"id": "BeeHive-Command",
"name": "01.命令集"
},
{
"id": "BeeHive-Package",
"name": "02.包分析"
}
]
}
},
}
接下来就是我们的重头戏了,我们看看 require
进来的 commandSet 怎么写的~
// commandSet.ts
import * as vscode from 'vscode'
import SideBarCommand from './SideBarCommand'
import { PREFIX } from '../../constants'
import { ShellType } from '../../type/common'
import { getWorkSpaceFolderList } from '../../utils'
module.exports = function (context: vscode.ExtensionContext) {
// 1. 得到vscode所有工程项目
const folderList = getWorkSpaceFolderList()
// 2. 注册侧边栏面板
const sideBar = new SideBarCommand(folderList)
vscode.window.registerTreeDataProvider('BeeHive-Command', sideBar)
// 3. 注册命令
vscode.commands.registerCommand(
'BeeHive-Command.openChild',
(args: { title: string; shell: ShellType; [key: string]: any }) => {
const { title, shell = null, path = '' } = args
const reg = new RegExp(`${PREFIX}`)
if (reg.test(title)) {
vscode.window.showInformationMessage(title)
} else {
// 4. 复制到剪切板
vscode.env.clipboard.writeText(`cd ${path} \n npm run ${shell?.key}`)
vscode.window.showInformationMessage(
`ok, fine ! shell copied to clipboard ~`
);
}
}
)
}
接下来的重头戏就是,我们实现的这个 SideBarCommand
了,这里主要重写了 getChildren
方法,通过动态去生成面板内容
// SideBarCommand.ts
/**
* @description 命令集侧边栏实例
*/
import * as vscode from 'vscode'
import { PREFIX } from '../../constants'
import { FolderType, ShellType } from '../../type/common'
import { isExist, read, getShellFromScripts } from '../../utils/package'
import { SideBarEntryItem, SideBarEntryListImplements,} from '../../factory/SideBar'
function getNode(
title: string,
description?: string,
args?: { [key: string]: any }
) {
let node = new SideBarEntryItem(title, vscode.TreeItemCollapsibleState.None, description)
node.command = {
command: 'BeeHive-Command.openChild', //命令id
title: title,
arguments: [{ title, ...args }], //命令接收的参数
}
return node
}
export default class SideBarCommand extends SideBarEntryListImplements {
constructor(private folderPathList: FolderType[] | undefined) {
super()
}
getChildren(
element: SideBarEntryItem | undefined
): vscode.ProviderResult<SideBarEntryItem[]> {
if (element) {
var childrenList: any = []
if (isExist(`${element.path}/package.json`)) {
const packageValues = read(`${element.path}/package.json`)
if (packageValues && packageValues.scripts) {
const eggShell = getShellFromScripts(packageValues.scripts, 'server')
const webpackShell = getShellFromScripts(packageValues.scripts, 'webpack')
const shellList = [...webpackShell, ...eggShell]
if (!!shellList.length) {
shellList.forEach((shell: ShellType, index: number) => {
const node = getNode(shell.key, `[${shell.environment}]`, { shell, path: element.path })
childrenList[index] = node
})
} else {
const noneNode = getNode(`[${PREFIX}]: scripts 脚本命令不符合规则`)
childrenList = [noneNode]
}
} else {
const noneNode = getNode(`[${PREFIX}]: 不存在 scripts 脚本命令`)
childrenList = [noneNode]
}
} else {
const noneNode = getNode(`[${PREFIX}]: 工程项目不存在package.json`)
childrenList = [noneNode]
}
return childrenList
} else {
const folderNode = this.folderPathList?.map((folder: FolderType) => {
return new SideBarEntryItem(
folder.name,
vscode.TreeItemCollapsibleState.Collapsed,
'',
folder.path
)
})
return folderNode
}
}
}
上面的例子来自实战: vscode-beehive-extension
图片展示
具体关于业务代码,就不展示了~
源码阅读