[KT] vscode plug in development example series (2)

Peng Daokuan 2021-02-23 04:07:14
kt vscode plug development example


background

Blog launch : Hiro's blog

Team blog : SugarTurboS

Warehouse source code : learn-vscode-extension , Ask a star

Following last article 【KT】vscode Plug in development example series ( One ) after , Continue to complete some examples , The following examples are relatively complex and applicable , I don't say much nonsense , Open the door !

Example

6. code snippet

scene

Enter a prefix , You'll get one or more hints , And then the carriage return brings out a lot of code .

Code display

Need modification package.json Medium snippets Configuration of

// package.json
{
"contributes": {
"snippets": [
{
"language": "html",
"path": "./src/snippets/html.json"
}
]
}
}
 Copy code 

And then add a html.json To configure

{
"PDK": {
"prefix": ["PDK", "PD", "PK", "DK"],
"body": ["<PDK>", "${1}", "</PDK>"],
"description": " Peng Daokuan's custom snippets"
}
}
 Copy code 

About each field , You can learn about :create-your-own-snippets

Above we set the language to : html, So running the plug-in , And make sure the plug-in is activated , In the prescribed language html in , Input prefix Related keywords , That's all right.

Effect display

Source code display

7. Custom sidebar + panel

background

You need to customize the sidebar on the left , Complete some interactive logic operations

Code implementation

️ We need to pay attention to : Sidebar buttons (Tree View Container) And panel view (Tree View) To configure at the same time , Otherwise it doesn't work

Sidebar display

First , Let's look at the official documents first , Let's see how to add our custom content to the sidebar on the left

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. Package analysis "
}
]
}
}
}
 Copy code 

️ Be careful :views in key Want to be with activitybar Properties in id bring into correspondence with , Such as sugar It's the same in both

Run our plug-in at this time :Run Extension, You can see our custom sidebar on the left

About icons svg Just pay attention to the path , My point is not the icon ~

We've finished the configuration above package.json after , Let's go back to the documentation , You'll see this passage :tree-view#activationEvents

if necessary , You can just add the following code

{
"activationEvents": ["onView:BeeHive-Command"]
}
 Copy code 

How to define panel content

It's showing the sidebar , But we need to show the content , How do the whole ? Through official documents :tree-data-provider You can achieve 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 = `${this.label}-${this.version}`
// this.description = `${this.version}-${Math.ceil(Math.random() * 1000)}`
}
}
/**
* @description  Entrance file
*/
export class SideBarBeeHiveCommand
implements vscode.TreeDataProvider<SideBarEntryItem> {
constructor(private workspaceRoot?: string) {}
getTreeItem(element: SideBarEntryItem): vscode.TreeItem {
return element
}
getChildren(
element?: SideBarEntryItem
): vscode.ProviderResult<SideBarEntryItem[]> {
if (element) {
// Child node 
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], // The parameters that the command receives 
}
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(private workspaceRoot?: string) {}
getTreeItem(element: SideBarEntryItem): vscode.TreeItem {
return element
}
getChildren(
element?: SideBarEntryItem
): vscode.ProviderResult<SideBarEntryItem[]> {
if (element) {
// Child node 
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], // The parameters that the command receives 
}
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 sidebar panel 
const sidebarBeeHiveCommand = new SideBarBeeHiveCommand()
const sidebarBeeHivePackageAnalysis = new SideBarBeeHivePackageAnalysis()
vscode.window.registerTreeDataProvider(
'BeeHive-Command',
sidebarBeeHiveCommand
)
vscode.window.registerTreeDataProvider(
'BeeHive-PackageAnalysis',
sidebarBeeHivePackageAnalysis
)
// Registration order 
vscode.commands.registerCommand('BeeHive-Command.openChild', (args) => {
console.log('[BeeHive-Command.openChild] The current selection is :', args)
vscode.window.showInformationMessage(args)
})
vscode.commands.registerCommand(
'BeeHive-PackageAnalysis.openChild',
(args) => {
console.log('[BeeHive-PackageAnalysis.openChild] The current selection is :', args)
vscode.window.showInformationMessage(args)
}
)
}
 Copy code 

Then in the entry file extension.ts Add the file

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 code 

If you need to click the node in the left sidebar, trigger the content , Only need arguments There's something going back in it , Then do the corresponding business operation

Effect display

image

Source code reading

8. Read folder Directory + Content copy clipboard

scene

Last example : Custom sidebar + panel Although it can achieve our function , But there are still some shortcomings , After all, we need to dynamically generate our panel content based on the file path .

Take the following example : according to vscode working directory , Read from the directory package.json Of documents scripts Field , Filter out script commands that meet the specifications , Dynamically generate our buttons

The first thing to be clear is :vscode There is one vscode.workspace.rootPath, Because later vscode Support multipleRoot Pattern , So this field is obsolete . We can only pass vscode.workspace.workspaceFolders Gets an array of all root folders in the current workspace ;

Be careful : Is the path to the folder array , in other words , This is the case , The result is that the content of the path is like this

├── A_Folder
│ ├── B_Folder
│ │ ├── D_Folder
│ │ └──
│ │
│ ├── C_Folder
│ └──
└──
 Copy code 

All it gets is : A_Folder The path of , You don't get the following B、C、D route .

One more thing to note is : It's hard to tell whether this folder belongs to a front-end project or Node engineering , Here I am based on whether there is package.json To differentiate , That is, if A The following are package.json , I think it's a complete project ( Don't think of it as a folder )

I really want to get it A All the folders below ?

If you really want to , My idea is : Only through Node Of fs Module to get A The file directory under the folder , Then a recursive , Go all the way down , There will always be ways .

OK, Far away , Let's take a look at a general idea

Code display

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 code 

Don't forget it package.json You also need to add

{
"contributes": {
"commands": [],
"viewsWelcome": [
{
"view": "BeeHive-Command",
"contents": " Improve your efficiency , Release 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. Package analysis "
}
]
}
},
}
 Copy code 

And then there's our play , Let's see. require Come in commandSet How to write ~

// 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. obtain vscode All projects 
const folderList = getWorkSpaceFolderList()
// 2. Register sidebar panel 
const sideBar = new SideBarCommand(folderList)
vscode.window.registerTreeDataProvider('BeeHive-Command', sideBar)
// 3. Registration order 
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 code 

The next big thing is , What we've achieved is SideBarCommand 了 , It's mainly rewritten here getChildren Method , Generate panel content dynamically

// 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 }], // The parameters that the command receives 
}
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 The script command doesn't conform to the rules `)
childrenList = [noneNode]
}
} else {
const noneNode = getNode(`[${PREFIX}]: non-existent scripts Script command `)
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 code 

The above example comes from actual combat : vscode-beehive-extension

Source code reading

9. Customize plug-in preferences configuration , Perform different logic according to configuration

scene

Each plug-in can add its own configuration of preferences , When open vscode when , Select the configuration according to the preference , Execute different logic , Let's talk about how to achieve this effect

Code display

We are now package.json Configure our preferences in

{
"contributes": {
"configuration": {
"title": "sugar-demo-vscod",
"properties": {
"sugar-demo-vscode.matchConfig": {
"type": "string",
"description": "sugar-demo-vscod To configure , Default low configuration version ",
"enum": [
"lowMatch",
"middleMatch",
"highMatch"
],
"default": "lowMatch",
"scope": "window"
}
}
}
}
}
 Copy code 

Here we need to pay attention to , name sugar-demo-vscode Should agree !

We have implemented the preferences configuration above , Look at the effect

Let's get the configuration again , And then perform different logic


// Get the user configured version settings 
const matchConfig = vscode.workspace.getConfiguration().get('vscode-beehive-extension.matchConfig')
if (matchConfig === MATCH_CONFIG_MAPS.LOW) {
console.log(' With low ')
} else if (matchConfig === MATCH_CONFIG_MAPS.MIDDLE) {
console.log(' Chinese match ')
} else if (matchConfig === MATCH_CONFIG_MAPS.HIGH) {
console.log(' With high ')
} else {
vscode.window.showErrorMessage(`unknown error`)
}
 Copy code 

If you want to modify it through code matchConfig Content , Can pass

// Last parameter , by true Write to the global configuration , by false Or not, only the workspace configuration is written 
vscode.workspace.getConfiguration().update('vscode-beehive-extension.matchConfig', 'middleMatch, true);
 Copy code 

Source code display

pack 、 Release

I don't need to teach this thing ? Search for articles in this field , I'm not a porter , If you are interested, you can search by yourself , Or wait for my follow-up practical articles to come out and have a look ?

A little chatter

So far, most of them are applicable vscode demo I put all the examples in : learn-vscode-extension in , If you want to see the actual source code , Please move here : vscode-beehive-extension

Related links

Praise Xiaoming's article , Although I didn't take the content very seriously , I always look at pictures , Then look at the source code corresponding to the figure , But in the early development vscode plug-in unit , It can be said that the help is relatively large ~

版权声明
本文为[Peng Daokuan]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/02/20210223024104486y.html

  1. JavaScript advanced: Javascript object-oriented, JavaScript built-in object, JavaScript BOM, JavaScript encapsulation
  2. JavaScript advanced: Javascript object-oriented, JavaScript built-in object, JavaScript BOM, JavaScript encapsulation
  3. Vue determines whether the El form in the elementui is updated or changed. If it changes, it will prompt whether to save it. If it does not change, it will leave directly
  4. Algorithm problem: sum of two numbers -- JavaScript and Java implementation
  5. High performance nginx HTTPS tuning
  6. JQuery advanced
  7. day 30 jQuery
  8. JQuery:JQuery Basic syntax, jQuery selector, jQuery DOM, comprehensive case check box, comprehensive case random picture
  9. TCP/IP 开胃菜 之 HTTP
  10. JQuery:JQuery Basic syntax, jQuery selector, jQuery DOM, comprehensive case check box, comprehensive case random picture
  11. JavaScript data type
  12. [micro front end] the final chapter of micro front end - Qiankun guide and overall exploration of micro front end
  13. Solve Ajax cross domain problem [5 solutions]
  14. HTTP of TCP / IP appetizer
  15. Optimization of pod creation efficiency in serverless scenario
  16. Iqiyi Sports: experience the ultimate expansion and contraction of serverless, and increase the utilization rate of resources by 40%
  17. First knowledge of HTTP / 1.1
  18. First knowledge of HTTP / 1.1
  19. Webpack learning notes series 05 devserver
  20. Webpack learning notes series 04 - resource processing optimization
  21. How to build a high performance front end intelligent reasoning engine
  22. How to become a professional front end engineer in 2021?
  23. How to transform single / micro service application into serverless application
  24. How to transform single / micro service application into serverless application
  25. How to transform single / micro service application into serverless application
  26. How to connect the ground gas to the micro front end?
  27. How to connect the ground gas to the micro front end?
  28. How to connect the ground gas to the micro front end?
  29. Vue server rendering principle analysis and introduction
  30. Realize the correct loading of text message
  31. Building my own project scaffolding with yeoman
  32. JavaScript advanced prototype and prototype chain
  33. React background management front end system (based on open source framework development) start
  34. JS practical skills breakpoint debugging
  35. I'd like to share with you 20 super easy-to-use Chrome extension plug-ins
  36. Get page element location
  37. Use the powerful API of modern browser to record any interface in the browser and realize export, save and management
  38. Delayed code execution in flutter
  39. Reconfiguration experience of KOA middleware system
  40. Add comments to your blog
  41. Svg editor -- new path
  42. Detailed explanation of debounce and throttle of JavaScript function
  43. Anti shake and throttling and corresponding react hooks package
  44. C2m: the first CSDN article moved to MOOC script 5000 words, detailed painstaking development process, there are renderings and source code at the end of the article
  45. Front end, school recruitment, Taobao, guide
  46. [vue2 & G6] get started quickly
  47. Canvas from the beginning to the pig
  48. Take five minutes to standardize the code comments?
  49. Some thoughts on sass
  50. what?! You haven't filled in the award information yet
  51. How to get the interface + tsdoc needed by TS through swagger
  52. Binary tree
  53. Canvas drawing method in Web screenshot
  54. Front end docker image volume optimization (node + nginx / node + multi-stage construction)
  55. Become a big influence of technology? Coding pages quickly build personal blog
  56. Object and array deconstruction, spread operator, rest operator
  57. Analysis of Axios source code
  58. Two ways to delete useless code in project (Practical)
  59. Edit your picture with canvas
  60. Today's chat: 2-4 years to walk out of the resignation dilemma and comfort zone