background
📢 blog launch: Hiro’s blog
📢 Team blog: SugarTurboS
🌈 repository source: learn-vscode-extension, ✨ star
Following the previous article [KT] VScode plug-in development example series (a), continue to complete some examples, the following examples are relatively complex and applicable, nonsense not to say, dry!
example
6. Code snippets
scenario
Type in a prefix, get one or more prompts, and return to the car with a lot of code.
The code shown
You need to modify the configuration of snippets in package.json
// package.json
{
"contributes": {
"snippets": [{"language": "html"."path": "./src/snippets/html.json"}}}]Copy the code
Then add an HTML. Json configuration
{
"PDK": {
"prefix": ["PDK"."PD"."PK"."DK"]."body": ["<PDK>"."${1}"."</PDK>"]."description": "Custom Snippets for Dokuan Peng"}}Copy the code
For each field, you can read the official documentation: create-your-own-Snippets
Above we set the language to: HTML, so before running the plugin, and ensure that the plugin is activated, in the specified language HTML, enter the relevant keyword prefix
Results show
The source code to show
- Package configuration in Snippets
7. Customize the sidebar + panel
background
You need to customize the sidebar on the left to do some interactive logic
Code implementation
⚠️ Note: The sidebar button (Tree View Container) and panel View (Tree View) must be configured at the same time. Otherwise, the configuration does not take effect
Display of sidebar
First, let’s look at the official documentation and see how we can add our own custom content to the left sidebar
👉 contribution – points# contributes. ViewsContainers
// package.json
{
"contributes": {
"viewsContainers": {
"activitybar": [{"id": "sugar"."title": "Sugar-BeeHive"."icon": "./src/logo/sugar.svg"}},"views": {
"sugar": [{"id": "BeeHive-Command"."name": "01. Command Set"
},
{
"id": "BeeHive-PackageAnalysis"."name": "02. Packet Analysis"}]}}}Copy the code
⚠️ Note: The key in views must be consistent with the attribute ID in activityBar. For example, the sugar in views is consistent with the sugar in activityBar
Run our plugin: Run Extension, and you’ll see our custom sidebar on the left
On the icon SVG this we pay attention to the path is good, I focus on the icon is not ha ~
After we’ve configured package.json above, we’ll go back to the document and see this: tree-view#activationEvents
If necessary, you can add the following code
{
"activationEvents": ["onView:BeeHive-Command"]}Copy the code
How do YOU define panel content
It shows the sidebar, but we need to show the content. How do we do that? You can use the official document: tree-data-provider to implement a small demo. The following code is also based on the official document
// beehive-sidebar.ts
// Demo7 custom sidebar entry and panel
import * as vscode from 'vscode'
const scripts = [
{
script: 'webpack:dev'}, {script: 'webpack:prod'}, {script: 'server:dev'}, {script: 'server:test'}, {script: 'server:test-1'}, {script: 'server:test-2',},]/ * * *@description Rewrite each node */
export class SideBarEntryItem extends vscode.TreeItem {
constructor(
private version: string.public readonly label: string.public readonly collapsibleState: vscode.TreeItemCollapsibleState
) {
super(label, collapsibleState)
this.tooltip = `The ${this.label}-The ${this.version}`
// this.description = `${this.version}-${Math.ceil(Math.random() * 1000)}`}}/ * * *@description Import file */
export class SideBarBeeHiveCommand
implements vscode.TreeDataProvider<SideBarEntryItem> {
constructor(privateworkspaceRoot? :string) {}
getTreeItem(element: SideBarEntryItem): vscode.TreeItem {
returnelement } getChildren( element? : SideBarEntryItem ): vscode.ProviderResult<SideBarEntryItem[]> {if (element) {
/ / child nodes
var childrenList = []
for (let index = 0; index < scripts.length; index++) {
var item = new SideBarEntryItem(
'1.0.0',
scripts[index].script,
vscode.TreeItemCollapsibleState.None
)
item.command = {
command: 'BeeHive-Command.openChild'./ / command id
title: scripts[index].script,
arguments: [scripts[index].script], // Parameters received by the command
}
childrenList[index] = item
}
return childrenList
} else {
/ / the root node
return [
new SideBarEntryItem(
'1.0.0'.'Item 1',
vscode.TreeItemCollapsibleState.Collapsed
),
new SideBarEntryItem(
'1.0.0'.'Item 2',
vscode.TreeItemCollapsibleState.Collapsed
),
]
}
}
}
export class SideBarBeeHivePackageAnalysis
implements vscode.TreeDataProvider<SideBarEntryItem> {
constructor(privateworkspaceRoot? :string) {}
getTreeItem(element: SideBarEntryItem): vscode.TreeItem {
returnelement } getChildren( element? : SideBarEntryItem ): vscode.ProviderResult<SideBarEntryItem[]> {if (element) {
/ / child nodes
var childrenList = []
for (let index = 0; index < scripts.length; index++) {
var item = new SideBarEntryItem(
'1.0.0',
scripts[index].script,
vscode.TreeItemCollapsibleState.None
)
item.command = {
command: 'BeeHive-PackageAnalysis.openChild'./ / command id
title: scripts[index].script,
arguments: [index], // Parameters received by the command
}
childrenList[index] = item
}
return childrenList
} else {
/ / the root node
return [
new SideBarEntryItem(
'1.0.0'.'Button Group',
vscode.TreeItemCollapsibleState.Collapsed
),
]
}
}
}
module.exports = function (context: vscode.ExtensionContext) {
// Register the sidebar panel
const sidebarBeeHiveCommand = new SideBarBeeHiveCommand()
const sidebarBeeHivePackageAnalysis = new SideBarBeeHivePackageAnalysis()
vscode.window.registerTreeDataProvider(
'BeeHive-Command',
sidebarBeeHiveCommand
)
vscode.window.registerTreeDataProvider(
'BeeHive-PackageAnalysis',
sidebarBeeHivePackageAnalysis
)
// Register the command
vscode.commands.registerCommand('BeeHive-Command.openChild'.(args) = > {
console.log('[beehive-command-openChild] currently selected :', args)
vscode.window.showInformationMessage(args)
})
vscode.commands.registerCommand(
'BeeHive-PackageAnalysis.openChild'.(args) = > {
console.log('[BeeHive - PackageAnalysis openChild] the currently selected is:', args)
vscode.window.showInformationMessage(args)
}
)
}
Copy the code
Then add the file in the entry file extension.ts
import * as vscode from 'vscode'
export function activate(context: vscode.ExtensionContext) {
console.log('your extension "sugar-demo-vscode" is now active! ')
require('./beehive-sidebar')(context) // Demo7 custom sidebar entry and panel
}
export function deactivate() {}
Copy the code
If you need to trigger content when you click on the node in the left sidebar, just post back some content in Arguments and do the corresponding business action
Results show
The source code to read
- beehive-sidebar.ts
- Package. The viewsContainers in json
- Package. The views in json
8. Read folder directory + content copy clipboard
scenario
Previous example: Customizing the sidebar + panel does what we do, but there are some drawbacks, as we need to dynamically generate our panel content based on the file path.
Take the following example as an example: according to the VScode working directory, read the scripts field of package.json file in the directory, screen out the script commands that meet the specification, and dynamically generate our button
First of all need to be clear that vscode a vscode. Workspace. RootPath, because later vscode support multipleRoot mode, so this field have been out of date invalid. We can only through vscode. Workspace. WorkspaceFolders for current workspace all root folder array;
Note that you get the folder array path, that is, in the following case, you get the path content like this
├ ─ ─ A_Folder │ ├ ─ ─ B_Folder │ │ ├ ─ ─ D_Folder │ │ └ ─ ─ │ │ │ ├ ─ ─ C_Folder │ └ ─ ─ └ ─ ─Copy the code
The above will only get the: A_Folder path, not the B, C, and D paths below.
Another point to note: It’s hard to tell whether this folder belongs to A front-end project or Node project. Here, I classify it by whether package.json exists under this folder.
Do you really want all the folders under “A”?
If you really want to, my idea is that you can only use Node’s FS module to retrieve the A folder and recurse all the way down. There is always A way.
OK, let’s get to the general idea
The code shown
Register the sidebar panel first
// extension.ts
import * as vscode from 'vscode'
export function activate(context: vscode.ExtensionContext) {
console.log('Plug-in started, go ahead.')
require('./container/commandSet')(context)
}
export function deactivate() {}
Copy the code
Don’t forget that package.json also needs to be added
{
"contributes": {
"commands": []."viewsWelcome": [{"view": "BeeHive-Command"."contents": "Increase your productivity and free up your hands."}]."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. Command Set"
},
{
"id": "BeeHive-Package"."name": "02. Packet Analysis"}}},}Copy the code
CommandSet = commandSet = commandSet = commandSet = 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. Get all vscode projects
const folderList = getWorkSpaceFolderList()
// 2. Register sidebar panel
const sideBar = new SideBarCommand(folderList)
vscode.window.registerTreeDataProvider('BeeHive-Command', sideBar)
// 3. Register commands
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. Copy to clipboard
vscode.env.clipboard.writeText(`cd ${path} \n npm run ${shell? .key}`)
vscode.window.showInformationMessage(
`ok, fine ! shell copied to clipboard ~`); }})}Copy the code
The next big thing is the SideBarCommand that we implemented, which basically overwrites the getChildren method to dynamically generate the panel content
// SideBarCommand.ts
/ * * *@description Command set sidebar instance */
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'./ / command id
title: title,
arguments: [{ title, ...args }], // Parameters received by the command
}
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 script command does not comply with the rule)
childrenList = [noneNode]
}
} else {
const noneNode = getNode(` [${PREFIX}]: scripts command 'does not exist)
childrenList = [noneNode]
}
} else {
const noneNode = getNode(` [${PREFIX}]: The project does not exist 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
}
}
}
Copy the code
The above example is from practice: vscode-Beehive-extension
The source code to read
- SideBarCommand
- commandSet
9. Customize the plug-in preference configuration and perform different logic according to the configuration
scenario
Each plug-in can add its own configuration of preferences. When vsCode is opened, different logic is executed based on the configuration selected by the preferences
The code shown
Let’s now configure our preference parameters in package.json
{
"contributes": {
"configuration": {
"title": "sugar-demo-vscod"."properties": {
"sugar-demo-vscode.matchConfig": {
"type": "string"."description": "Sugar-demo-vscod configuration, low version by default"."enum": [
"lowMatch"."middleMatch"."highMatch"]."default": "lowMatch"."scope": "window"
}
}
}
}
}
Copy the code
Note that the name sugar-demo-vscode must be consistent!
We have implemented the preference configuration above, and look at the effect
We then get the configuration and execute the different logic
// Get the version Settings configured by the user
const matchConfig = vscode.workspace.getConfiguration().get('vscode-beehive-extension.matchConfig')
if (matchConfig === MATCH_CONFIG_MAPS.LOW) {
console.log('low match')}else if (matchConfig === MATCH_CONFIG_MAPS.MIDDLE) {
console.log('in the match')}else if (matchConfig === MATCH_CONFIG_MAPS.HIGH) {
console.log('high-end')}else {
vscode.window.showErrorMessage(`unknown error`)}Copy the code
If you want to modify the matchConfig content in code, you can go through
// The last parameter, true to write global configuration, false to write workspace configuration only
vscode.workspace.getConfiguration().update('vscode-beehive-extension.matchConfig'.'middleMatch, true);
Copy the code
The source code to show
- beehive-customUserConfig.ts
Package and publish
You don’t need me to teach you that, do you? Search or have this aspect of the article, I am not the porter, interested in their own to search, or wait for my follow-up actual combat article to see?
Be a few words
So far, most of the applicable VScode demo examples are in: learn-vscode-extension, if you want to see the source code, please go to 👉 vscode-beehive-extension
A link to the
- Hiro’s blog
- SugarTurboS
- vscode-gitlens
- Official Documentation API
- Xiao Ming -vscode plug-in development overview
- 【KT】 VScode plug-in development example series (1)
Kua small Ming students article, although I did not seriously look at the content, I am looking at the figure, and then go to see the corresponding source of the figure, but in the early development of VScode plug-in, can be said to help or relatively large ~