Vscode has been popular with developers in recent years due to its lightweight and unusual plug-in market. You can find plenty of powerful plug-ins in the plug-in market to help improve coding efficiency. But (there is always a but-🙄) in real development, there will be some special customization requirements that do not find a particularly suitable plugin, so we can roll up our sleeves and build our own wheel.
Plug-in function
Vscode gives plugins a number of capabilities that allow them to arm vscode in almost every way. The main capabilities of the plugins include:
- Provide new themes (including editor color matching, file ICONS, etc.)
- Syntax support for new programming languages (highlighting, code completion, error checking, and more)
- Provides program debugging capabilities
- Custom commands, shortcut keys, menus
- Custom workspace Webview
What plug-ins are developed?
When I write unit tests, I often run into the following questions:
- You need to switch back and forth between the source file and the corresponding single test file, and vscode does not have webstorm’s quick switch between the source file and the test file. The whole switching experience is not good
- When creating a single test file for a source file, you often need to recursively create the test file if the principle is to separate the source file folder from the test file folder. Such as
src/module/child/a.ts
, need to create layerstests/module/child/a.test.ts
Files, this is particularly troublesome 😫
Based on these pain points, I developed a vscode plug-in for quick switching between source test files and quick creation of single test files. Plugin effects:
Plug-in functions:
- Find the test file corresponding to the source file. If only one possible file is found, switch directly; If more than one is found, a drop-down selection box is displayed for the user to select
- Quickly create a single test file. Support for two modes, single test files and source files together, or all single test files in a specific folder and organized by source file directory structure
- Provides rich configuration capabilities, users can customize single test file suffix specifications
You can click on this link, or search for ** Find Test File ** in vscode marketplace:
Environment to prepare
- Nodejs, recommended stable version
- git
Start by installing the yeoman scaffold tool and the official scaffolding tools provided by vscode:
npm install -g yo generator-code
Copy the code
Next, execute the following command to interactively create the plug-in project:
yo code
Copy the code
The project structure
Now that the plug-in project has been created, the project directory structure is as follows:
. ├ ─ ─ node_modules ├ ─ ─ CHANGELOG. Md ├ ─ ─ the README. Md ├ ─ ─ package. The json ├ ─ ─ the SRC │ ├ ─ ─ the extension. The ts │ └ ─ ─test│ ├─ ├─ ├─ exercises, ├─ exercises, exercises, exercises, exercises, exercises, exercises, exercises ├─.vsCode ├─ ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txtCopy the code
Among them:
.vscode
The folder holds the program to run and debug related commandsvsc-extension-quickstart.md
This document describes how to get started with plug-ins and how to run them. It is the first point of concern after a project is createdsrc
This is where the plug-in source code is stored.src/test
Plugins e2E test code, not to worry about)package.json
In addition to containing regular Node project configuration properties, it also contains plug-in configuration properties, which should also be of great concern
By default, the project has been configured to Run the debug parameters, so press F5 to Run the Extension (which is to Run the Run Extension command in.vscode/launch.json) :
Let’s start with package.json. The code snippet related to plug-in configuration is as follows:
{
"name": "test"."displayName": "test"."engines": {
"vscode": "^ 1.57.0"
},
"categories": [
"Other"]."activationEvents": [
"onCommand:test.helloWorld"]."main": "./out/extension.js"."contributes": {
"commands": [{"command": "test.helloWorld"."title": "Hello World"}}}]Copy the code
name
anddisplayName
Needless to say, the name of the plugin and the display name (i.e. the name in the plugin market)engines
In thevscode
Version refers to the version of vscode that the plug-in is compatible withcategories
Represents the classification of plug-ins, but it andkeywords
Differences can only be made by choiceThe official listSelect themain
Represents the plug-in entryactivationEvents
Said whenActivate the plugincontributes
How saidCustom plug-in function
Take a look at SRC /extension.ts again:
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "test" is now active! ');
// Customize the command
let disposable = vscode.commands.registerCommand("test.helloWorld".() = > {
// Triggers a pop-up
vscode.window.showInformationMessage("Hello World from test!");
});
// Register the command in the execution context
context.subscriptions.push(disposable);
}
export function deactivate() {}
Copy the code
Extension.ts exposes two methods:
active
: Runs when the plug-in is activated, usually registering custom commands in itdeactive
: Runs when the plug-in is disabled
These two parts are the core of plug-in development, so let’s walk through the process:
Roll up your sleeves and get to work
The plug-in configuration
First declare the command for the plug-in in package.json, along with the conditions under which the plug-in is activated:
{
"activationEvents": [
"onCommand:find-test-file.jumpToTest"."onCommand:find-test-file.createTestFile"]."contributes": {
"commands": [{"command": "find-test-file.jumpToTest"."title": "Jump To Source/Test File"."category": "Find Test File"."icon": "$(preferences-open-settings)"."enablement": "resourceExtname =~ /.[jt]sx? /"
},
{
"command": "find-test-file.createTestFile"."title": "Create Test File For Current"."category": "Find Test File"."icon": "$(file-add)"."enablement": "resourceExtname =~ /.[jt]sx? /"}}}]Copy the code
In the Commands configuration TAB, add the jumpToTest and createTestFile commands to add several configurations in addition to the general command and title configurations:
category
: Used to group commands in the command panel
icon
: Icon of the command (Follow-up proceduremenus
For configuration) in the format of$(name)
Vscode bringingA set of ICONSenablement
: indicates when commands are displayed in the command panel. The above configuration indicates that only the currently open file ists
(tsx
),js
(jsx
) can be displayed in the command panel
ActivationEvents keeps the plug-in activated when the corresponding command is executed (see the official documentation for more activation conditions). If you want to save time, you can also set it to *, which is activated after vscode starts.
Of course, it’s a better practice to keep activating plug-ins only when necessary.
It’s not always convenient to select commands from the command palette. Shortcuts are king. You can add shortcut key configurations via the KeyBindings attribute (see the official documentation for more KeyBindings configurations) :
{
"contributes": {
"keybindings": [{"command": "find-test-file.jumpToTest"."key": "ctrl+shift+t"."mac": "cmd+shift+t"."when": "resourceExtname =~ /.[jt]sx? /"
},
{
"command": "find-test-file.createTestFile"."key": "ctrl+alt+t"."mac": "cmd+alt+t"."when": "resourceExtname =~ /.[jt]sx? /"}}}]Copy the code
- The Mac and Windows have different keyboard shortcuts
cmd
The key is the same as Window’sctrl
, you need to configure them separately when
When is the shortcut enabled, andcommand
theenablement
Configuration is similar to
Now that there are shortcuts, can there be shortcuts like the right mouse button? Can!!!! Add a configuration with the properties of menus (see the official documentation for more menus) :
{
"contributes": {
"menus": {
"editor/context": [{"command": "find-test-file.jumpToTest"."group": "1_find-test-file"."when": "resourceExtname =~ /.[jt]sx? /"
},
{
"command": "find-test-file.createTestFile"."group": "1_find-test-file"."when": "resourceExtname =~ /.[jt]sx? /"}]."editor/title": [{"command": "find-test-file.jumpToTest"."group": "navigation"."when": "resourceExtname =~ /.[jt]sx? /"
},
{
"command": "find-test-file.createTestFile"."group": "navigation"."when": "resourceExtname =~ /.[jt]sx? /"}]}}}Copy the code
The icon property defined in the previous command is used in editor/title.
The plug-in also needs to provide the ability for user configuration. For example, different projects name test files with different suffixes, some are A.test.ts, some are A.spect.ts. This capability is provided by the Configuration configuration:
{
"contributes": {
"configuration": {
"title": "Find Test File"."properties": {
"findTestFile.basic.testSuffix": {
"type": "string"."default": "\\.(spec|test)"."markdownDescription": "xxxxxx"
},
"findTestFile.basic.excludeFolder": {
"type": "array"."default": [
"node_modules"]."items": {
"type": "string"
},
"uniqueItems": true."markdownDescription": "xxxxxx"
},
"findTestFile.createIfNotFind.enable": {
"type": "boolean"."default": false."markdownDescription": "xxxxxx"
},
"findTestFile.createIfNotFind.preferStructureMode": {
"type": "string"."default": "separate"."enum": [
"separate"."unite"]."markdownEnumDescriptions": [
"xxxxxx"."xxxxxx"]."markdownDescription": "xxxxxx"
},
"findTestFile.createIfNotFind.preferTestDirectory": {
"type": "object"."default": {
"separate": "__tests__"."unite": "__tests__"
},
"properties": {
"separate": {
"type": "string"
},
"unite": {
"type": "string"}},"required": [
"separate"."unite"]."additionalProperties": false."markdownDescription": "xxxxxx"
}
}
}
}
}
Copy the code
The following information is displayed on the Settings page:
Configuration items can be arrays, strings, booleans, enumerations, objects, see official documentation for details.
The plug-in code
The subsequent code will omit the business logic involved in this plug-in and only focus on the configuration and API use of vscode plug-in. After all, the business code is only for specific scenarios 😁. If you want to see the full code, check out the code repository!
SRC /extension.ts
- Register two commands for the plug-in
- Determine the file vscode is currently opening and the current working directory. Business logic needs to be executed only if a specific file is opened
import vscode from "vscode";
function doPrepare() {
// Gets the currently edited file object, empty if no files are open
const activeEditor = vscode.window.activeTextEditor;
if(! activeEditor) {return;
}
// Get the file name of the edit file
const activeFilePath = activeEditor.document.fileName;
// Business code, don't worry
const result = createValidFileReg().exec(getBasename(activeFilePath));
if(! result) {// A warning message is displayed
vscode.window.showWarningMessage(INVALID_FILE_WARNING_MESSAGE);
return;
}
// get the address of the workspace directory currently open with vscode
constworkspaceFilePath = vscode.workspace.getWorkspaceFolder( activeEditor.document.uri )! .uri.fsPath;// omit the business code
}
export function activate(context: vscode.ExtensionContext) {
Register the jumpToTest command
const jumpToTestCommand = vscode.commands.registerCommand(
"find-test-file.jumpToTest".() = > {
// omit the business code});// Register createTestFile
const createTestFileCommand = vscode.commands.registerCommand(
"find-test-file.createTestFile".() = > {
// omit the business code});// Register the command in the execution context
context.subscriptions.push(jumpToTestCommand, createTestFileCommand);
}
export function deactivate() {}
Copy the code
SRC /config.ts main functions:
- Get plug-in configuration information
// src/config.js
import vscode from "vscode";
constgetCfgByKey = <K1 extends keyof Config, K2 extends keyof Config[K1]>( primary: K1, key: K2) => {// Select findTestFile, findTestFile, findTestFile, findTestFile, findTestFile Such as findTestFile. Basic. TestSuffix const config. = vscode workspace. GetConfiguration (" findTestFile "); TestSuffix const CFG = config.get< config [K1][K2]>(' ${primary}.${key} ')! ; Const defaultCfg = config.inspect< config [K1][K2]>(' ${primary}.${key} ')! .defaultValue! ; return [cfg, defaultCfg]; }; // omit the business codeCopy the code
SRC/jumptofile. ts Main functions:
- If a possible target file is found, switch directly to the target file
- If multiple possible target files are found, a dialog box is displayed for users to select
import vscode, { QuickPickItem } from "vscode";
export const openFile = async (filePath: string) = > {// Open the file at the corresponding address. Note that this operation is asynchronous
const document = await vscode.workspace.openTextDocument(filePath);
// Switch the current window to the file. Note that this operation is also asynchronous
await vscode.window.showTextDocument(document);
};
export const jumpToPossibleFiles = async (
current: string.relativeFiles: string[].isJumpToTestFile: boolean.createTestFileOption: CreateTestFileOption
) => {
// Display a selection box to get the result of the user's selection. Note that this is an asynchronous operation
const select = await vscode.window.showQuickPick(pickItems);
// Empty is returned when the selection is deselected
if(! select) {return;
}
// omit the business code
};
Copy the code
SRC/createTestfile. ts
- If the user is not satisfied with the search result or cannot find the test file, the input box is displayed to help the user quickly create the test file
import vscode, { QuickPickItem } from "vscode";
export const createTestFile = async (
{ basename, ext, parent, root }: CreateTestFileOption,
manualCreate: boolean = true) = > {// Displays the input box
const userInputPath = await vscode.window.showInputBox({
prompt: NEW_TEST_FILE_PROMPT,
value: filePath,
valueSelection: [filePath.length, filePath.length],
// Verify that the input is valid. Null is returned indicating that the verification is successful
validateInput(value) {
return isValidFile(basename, ext, value, true)?null: INVALID_TEST_FILE_WARNING_MESSAGE; }});// Cancel input and return empty result
if(! userInputPath) {return; }};Copy the code
See the official documentation for more vscode API usage.
Release the plugin
It’s just a snap. It’s a snap. Next you need to package the plug-in and publish it.
To package plug-ins, install the VSCE library:
npm i -g vsce
Copy the code
Then execute the package command:
vsce package
Copy the code
After the package is complete, the find-test-file-x.x.x. vi file is generated. At this point, you can directly install the plug-in through the plug-in market to verify the effect:
Once the functionality is verified, it can be released to the plug-in market:
- Vscode’s plug-in marketplace is based on Microsoft’s Azure DevOps, where plug-ins are authenticated, hosted, and managed. So before publishing, you need to sign up for an Azure Devops account, just like NPM:
- After registration is complete, create Personal Access Token:
Copy the created token for future use.
- Next you need to create a new Publisher in the plug-in market to publish the plug-in:
- Log in to the VSCE account and use the previously registered Publisher and token:
vsce login publisher-name
Copy the code
Don’t forget to add publisher, icon, categories to package.json:
{
"publisher": "xxxx"."icon": "xxxx/icon.png"."categories": [
"Other"],}Copy the code
- Once login is complete, you can happily publish:
vsce publish
Copy the code
Once successfully published, the plug-in can be searched in the plug-in market (which usually takes a few minutes), and you can also check the usage of the plug-in in the web management side.
conclusion
So far is the author in the development of plug-ins used in vscode knowledge, I hope this article can help you, but also welcome everyone to use the author developed plug-ins and issue.