A background.

Three months after I joined the company, I got familiar with the new business, new platform and new technology stack. I found myself in charge of the algorithm A platform, business B background and other management system requirements development process, everyone has been repeating the same work.

  • Copy basic UI component samples;
  • To modify component properties, open a browser and view the document each time.
  • Basic GET,POST request templates;
  • Splicing Filter + Table + EditModal management page;
  • Git add, Git commit, Git pull, git push, etc.
  • The deployment page of C deployment system is displayed.
  • Fill in manual reminder for weekly report every Friday afternoon.

Repetitive work wastes our development time, our thinking time, our ability time.

Therefore, based on VS Code’s plug-in capability, combined with the team’s FE unified UI components and workflow, we developed FE improvement tools with multiple functions. At the same time, learn VS Code plug-in from 0 to 1 development, master more skills.

Two. Function introduction

You can also search for Banma-Helper in the VS Code plugin marketplace to try it out for yourself.

function shortcuts instructions efficiency demo
Tan **** component snippet; Key words even think, automatic complement. bm- In the code, enter bm- and other keywords to automatically insert tan**** component code. + 5%
The tan**** component, hover displays the property document. In the code, hover over the tan**** component to view the properties document. Reduced the number of steps required to view a document in a browser. + 2%
Axios $HTTP request snippet. Key words even think, automatic complement. http In the code, enter keywords such as Ajax or HTTP, and the corresponding request code is automatically inserted. + 5%
Right click

– Open remote warehouse file – Automatically create PR
Right click the mouse Automatically create pr based on the branch where the currently edited file resides
Fill in the weekly report every Friday at 3:00 PM
Shortcut keys automatically execute git workflow cmd + shift + g After the requirements are developed, run the shortcut key and enter the COMMIT information to push the requirements successfully. Open the C deployment system (develop, QA, dev branches work) + 2%
Every day at 3:00 PM, remind to lift anus movement. You can also use shortcut keys, command + Shift + P, to search for movement. Related configuration: Disabled by default. If you need to enable it, refer to:

1. Top left corner code -> Preferences -> Settings -> Search banma-Helper -> Turn on Anus movement configuration (on)

2. Or use the shortcut keys (Command +,) to go to Settings -> Search banma-Helper -> Turn on the Anus movement configuration (on)




Develop VS Code plug-ins from 0 to 1

1. Initialize the project

npm install -g yo generator-code
Copy the code

The scaffolding will generate a project that can be developed immediately. Run the generator and fill in the fields.

When you’re done, go to VS Code, press F5, and you’ll immediately see a plug-in development host window with the plug-in running.

Enter the Hello World command in the command panel (Ctrl+Shift+P).

2. Key interpretation of source files

.├ ─.vscode │ ├─ ├─ ├.json // Configure TypeScript Compilation task ├─.gif // ├─ SRC │ ├─ package.json // ├─ SRC │ ├─ package.json // ├─ SRC │ ├─ package.json // ├─ tsconfig.json // TypeScript ConfigurationCopy the code

The key parts of the plugin — package.json and extensions.ts

2.1 Plug-in Configuration Listpackage.json

Each VS Code plug-in must contain a package.json, which is the plug-in’s configuration manifest. Package. json mixes node. js fields, such as scripts and Dependencies, and contributes some VS Code specific fields, such as Publisher, activationEvents, contributes, etc. Instructions for these VS Code fields can be found in the plug-in manifest reference. We cover some very important fields in this section:

  • activationEvents 和 contributes: Activate the event 和 Publish Content Configuration.
  • engines.vscode: describes the lowest VERSION of the VS Code API that the plug-in depends on.

2.2 Plug-in entry fileextensions.ts

The plug-in entry file exports two functions,

  • activate: is executed when the activation event is triggered.
  • deactivate: Perform cleanup before closing the plug-in.
import * as vscode from 'vscode'; // Once the plug-in is activated, VSCode immediately calls the export function activate(context: Vscode.extensioncontext) {// Console. log will only be executed once on plug-in activation ('Congratulations, your extension "my-first-extension" is now active! '); // Entry commands are already defined in package.json, Now call the registerCommand method // the parameters in registerCommand must be the same as the commands in package.json let Disposable = vscode.commands.registerCommand('extension.sayHello', () = > {/ / every time the commands will be called when the code / / to the user to display a message prompt vscode. Window. ShowInformationMessage (' Hello World! '); }); context.subscriptions.push(disposable); }Copy the code

From there, we can build our own VS Code plug-in based on the scaffold-generated project.

3. Actual combat development function

3.1 AXIos $HTTP request snippet. Key words even think, automatic complement. (Focus on Snippets)

The configuration property used is contributes snippets. Add code snippets for the language.

  • languageThe property must beLanguage identifier;
  • pathMust be usedVS Code snippet formatThe relative path to the code snippet file.
"snippets": [
    {
        "language": "javascript",
        "path": "./snippets/javascript.json"
    }
],
Copy the code
// snippets/javascript.json
{
    "httpPost": {
        "prefix": "httpPost",
        "body": [
            "const params = {}",
            "const url = `${this.PATH_PREFIX.AI}${this.API.TOOL.MSGBOX.FETCH_MSG}`",
            "this.\\$http.post(url, { ...params }).then(result => {",
            "\tconst { code, msg, data } = result",
            "\tif (code === 0) {",
            "\t\tthis.\\$message.success('success')",
            "\t} else {",
            "\t\tthis.\\$message.error(msg)",
            "\t}",
            "}).catch(err => {",
            "\tthis.\\$message.error(err)",
            "})"
        ],
        "description": "Code snippet for \"axios Http Post\""
    }
}
Copy the code

In short, files in the path path are treated as snippets that can be auto-completed by typing in keywords.

In the same way, tan**** component code snippet, keyword link, automatic completion. This method is also used to maintain the component’s snippets fragment files.

3.2 shortcut keys automatically execute git workflow (focus on keybindings, commands, vscode API capabilities)

After the requirements are developed, run the shortcut key and enter the COMMIT information to push the requirements successfully. Open the C deployment system (develop, QA, dev branches work).

Because it involves the operation of shortcut keys and commands. This configuration determines the trigger rules for keybindings that the user inputs.

"keybindings": [
    {
        "command": "banma-helper.git",
        "key": "ctrl+shift+g",
        "mac": "cmd+shift+g"
    },
]
Copy the code

This is coupled with the use of contributes.commands (invoke commands).

"Commands ": [{"command": "banma-helper.git", "title":" git add, commit, push, open C deployment system "},]Copy the code

In the entry extension.ts file, register the command.

import { gitOp } from './lib/gitOp'; export function activate(context: vscode.ExtensionContext) { ... . const git = vscode.commands.registerCommand('banma-helper.git', () => { gitOp(); }); context.subscriptions.push(git); }Copy the code

Git workflow command processing, the main understanding of vscode to provide API capabilities

  • Vscode. InputBoxOptions: Input box UI
  • Vscode. Workspace. WorkspaceFolders: the workspace file
  • Vscode. Window. SetStatusBarMessage: set the progress bar at the bottom
  • Vscode. Window. ShowInformationMessage: message prompt
  • env.openExternal(URI.parse(http://***.***.***.com/fe/task#/deploy/${name})) : Open the external url
// /lib/gitOp.ts import * as vscode from 'vscode'; import * as SimpleGit from 'simple-git/promise'; const { window, workspace, env, Uri: URI } = vscode; export const gitOp = async () => { const options: vscode.InputBoxOptions = { prompt: "Label: ", placeHolder: "Please enter commit information"}; if (workspace.workspaceFolders) { const git: SimpleGit.SimpleGit = SimpleGit(workspace.workspaceFolders[0].uri.path); const value = await window.showInputBox(options); if (! Value) {throw new Error(' please enter commit information '); }; Try {vscode. Window. SetStatusBarMessage (' git workflow to submit, please be patient, 2000); await git.add('.'); const { commit } = await git.commit(value.trim()); const branch = await git.revparse(['--abbrev-ref', 'HEAD']); if (! Commit) {// Throw if (! ['develop', 'qa', 'dev']. Includes (branch)) {throw new Error('commit problem '); } } await git.pull('origin', branch); await git.push('origin', branch); If ([' develop ', 'qa', 'dev]. Includes (branch)) {window. ShowInformationMessage (' push success; about to open Pikachu'); const name = workspace.workspaceFolders[0].uri.path.split('/').reverse()[0]; env.openExternal(URI.parse(`http://***.***.***.com/fe/task#/deploy/${name}`)); } else {window. ShowInformationMessage (' push 'success); } } catch(e) { window.showErrorMessage(e.message); }}};Copy the code

Similarly, shortcut keys generate algorithm A Filter + Table + EditModal files, and also use this principle + file insertion operation.

3.3 Right-click function (focus on understanding Menus, window. ActiveTextEditor)

  • contributes.menus: Sets the command’s menu item for the editor or file manager.
  • The places where the plugin creator can configure the menu are:editor/context(Editor context menu),scm/resource/context(SCM resources), etc..
  • groupThe: property defines the grouping of menus
  • when: The time to display the menu
// package.json "menus": { "editor/context": [ { "command": "banma-helper.reactpro", "group": "1_Starling", "when": "banma-helper:rightClick" }, { "command": "banma-helper.openorigin", "group": "1_Starling" }, { "command": "banma-helper.openpr", "group": "1_Starling" } ] }, "commands": [ { "command": "banma-helper.openpr", "title": "Banma -- create pr"},]Copy the code

Import file registration command:

import OpenOrigin from './lib/openOrigin';

vscode.commands.registerCommand('banma-helper.openpr', () => {
    OpenOrigin.openpr(context);
});
Copy the code

Git logic:

  • window.activeTextEditor: Currently active editor
  • window.activeTextEditor.document.fileName: Path of the file where the cursor is located
  • Get the current branch:const branch = await git.revparse(['--abbrev-ref', 'HEAD']);
import * as vscode from 'vscode'; import * as SimpleGit from 'simple-git/promise'; const { window, Uri: URI, env, workspace } = vscode; export default class ReactRro { public static async openpr(context: vscode.ExtensionContext) { if (window.activeTextEditor && workspace.workspaceFolders) { try { const path = window.activeTextEditor.document.fileName; / / local path const workPath = path. The match (/ banma_ [\ s \ s] * / g) | | []; // Match banma_ path const workPathArray = workPath[0].split('/'); // Path cut const workName = workPathArray[0]; / / project name const gitPath = path. The match (/ banma_ [\ s \ s] * * \ [/ w] / / g) | | [] / / project root const git: SimpleGit.SimpleGit = SimpleGit(gitPath[0]); const branch = await git.revparse(['--abbrev-ref', 'HEAD']); const url = `http://****.****.com/code/repo-detail/bm/${workName}/pr/create?source=refs/heads/${branch}&sourceRepo=bm/${workName}&ta rget=refs/heads/master&targetRepo=bm/${workName}` env.openExternal(URI.parse(url)); } catch (e) {window.showerrorMessage (' open failed '); }} else {window.showErrorMessage('pr failed to create '); }}};Copy the code

Create PR: automatically create a pull request to master based on the current branch.

3.4 every afternoon at 3 o ‘clock, remind one form movement (focus on understanding deactivate, workspace. GetConfiguration window. CreateWebviewPanel)

  • Deactivate: Life cycle – unmount
  • The workspace. GetConfiguration: access to the workspace configuration, support user-defined.
  • Window. CreateWebviewPanel: create and display a new webview panel.

Similarly, registering commands commands,

"Commands ": [{"command": "banma-helper.strong", "title":" tigang movement "}]Copy the code

The starting point of the exercise function design of anus lifting is to turn off the function by default, which will be turned on only by users who have requirements. It will be reminded every afternoon. This involves the user setting up to obtain additional configuration of the plug-in.

In contributes. The configuration of the content of the configuration will be exposed to the user, the user can from the “user Settings” and “the workspace Settings” modify your exposed options.

Contributes. The configuration is the key/value pair JSON format, the user will get the corresponding hints when change the setting and better experience.

You can use the vscode. Workspace. GetConfiguration (‘ myExtension) reads the configuration values.

"configuration": { "title": "banma-helper-strong", "properties": { "banma-helper.strong": { "type": "String", "description" : "one form sports configuration", "enum" : / "on" and "off", "default" : "off", "scope" : "the window"}}},Copy the code

The effect is as follows ↓ :

Next, at 3:00 p.m. every day, it automatically prompts the anus lifting movement and jumps the logic of the anus lifting movement Webview page.

  • Node-schedule is used for scheduled tasks
  • Window. CreateWebviewPanel: create and display a new webview panel, our HTML fragment into the webview. HTML attributes.
// /lib/strong.ts import * as vscode from 'vscode'; const schedule = require('node-schedule'); export default class Strong { private static panel: vscode.WebviewPanel | undefined; Public static schedule() {// 3:30pm const timer = schedule.scheduleJob('50 38 10 * * *',()=>{const matchConfig = vscode.workspace.getConfiguration().get('banma-helper.strong'); If (matchConfig = = = 'on') {vscode. Window. ShowInformationMessage (' 5 s after the anus movement oh, please get ready for your arrival! '); setTimeout(() => { this.send(); }, 5000); }}); return timer; // timer.cancel(); } public static send() { if (this.panel) { this.panel.webview.html = this.generatePage(); this.panel.onDidDispose(() => { this.panel = undefined; }); } else {. This panel = vscode. Window. CreateWebviewPanel (" hyt ", "One form movement", vscode. ViewColumn. One, {enableScripts: true, retainContextWhenHidden: true, }); this.panel.webview.html = this.generatePage(); this.panel.onDidDispose(() => { this.panel = undefined; }); } } public static generatePage(): string { return ` <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta < span style> < span style>. Desc {color: # FFF; font-size: 20px; } button { color: #fff; font-size: 20px; background-color: #252526; border: none; cursor: pointer; } .vi-conatiner { padding-top: 100px; display: flex; align-items: center; justify-content: center; flex-direction: column; } .img-base { width: 300px; height: 500px; } </style> </head> <body style="background-color: #15c27a;" > <div class="vi-conatiner"> <div class="desc"> Regularly lift and relax the anus to promote local blood circulation. </div> <button class=" button "onclick="start()"> 10px"> <img class="img-stop img-base" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ea60bfe91c14a98bd098d19e5616a3a~tplv-k3u1fbpfcp-watermark.image"  alt=""> </div> </div> </body> <script> const img = document.getElementsByClassName('img-stop')[0] function start() { img.src = "https://p1.meituan.net/paotui/kyvcpbt0f1p.gif" } </script> </html>`; }};Copy the code

Finally, add the scheduled task logic to the plug-in startup phase and empty the scheduled task when the plug-in is destroyed.

import Strong from './lib/strong'; const schedule = require('node-schedule'); const jobs = []; export function activate(context: vscode.ExtensionContext) {} const strongTimer = Strong.schedule(); jobs.push(strongTimer); } export function deactivate() {forEach(job => {if (job instanceof schedule.job) {job.cancel(); }}); }Copy the code

Now that the basic functions have been implemented, we can release our plug-in and download it for use in vscode.

4. Release

Use the VSCE tool for publishing.

4.1 installationvsce

npm install -g vsce
Copy the code

Vsce can only distribute plug-ins with Personal Access Tokens, so create at least one Token to distribute plug-ins

4.2 Obtaining a Personal Access Token

First, you need to have an Azure DevOps organization.

Click On New Token to create a New Personal Access Token

Click Create to see the newly created Personal Access Token, copy it, and use it to Create a publisher.

4.3 Terminal Login

Creating a publisher

vsce create-publisher (publisher name)
Copy the code

The login

vsce create-publisher (publisher name)
Copy the code

Incrementally update the plug-in version

Update the plug-in version number with SemVer semantic identifiers: major, Minor, patch increments.

vsce publish patch
Copy the code

It can then be downloaded and used in the vscode plugin marketplace.

4.4 VS Code Version Compatibility

When you make a plug-in, you need to describe the version compatibility of the plug-in to VS Code — modify engines. Vscode in package.json:

{"engines": {"vscode": "^1.50.0"}}Copy the code

4. To summarize

This plug-in is based on the pain points in daily development, as well as according to VS Code plug-in ability, do some functions.

Maybe the implementation is not a best practice, or some of the features are not applicable to the actual situation of your current work project (eg: turn on PR, it is only applicable to the current work project).

But what I want to express is that some scenarios at work require us to take the initiative to think and solve some problems. For example, we can start from VS Code, which we have been using.

Finally, attach the github source address

5. Refer to the article

VS Code Plug-in Development Documentation – Chinese version

Vscode plug-in development

The VSCE login has expired

vsce create-publisher returns 401