Author: HelloGitHub- Xiaoxia (first published on HelloGitHub official account)

As a developer who relies on code as his “living”, and does bug writing well, editors really matter! Visual Studio Code is no stranger to you. As a great editor, it has several advantages:

  • First of all, it was designed by a very famous engineer: Eric Gamma. Twenty years ago, he was one of the authors of Design Patterns: The Foundations of Reusable Object-oriented Software, a book regarded in the development community as a guiding light for object-oriented software development.

  • Second, for JavaScript writers, VS Code differentiates itself from many different editors, both large and small, such as Sublime, Atom, WebStorm, etc., which are open source and faster than Atom. Lighter than WebStorm.

Introduce a,

Visual Studio Code (Visual Studio Code) is a Microsoft open source editor. Visual Studio Code is available on GitHub at 115K. It is written in TypeScript and has over 300,000 code in total.

Project address: github.com/microsoft/v…

Let’s take a quick look at its product positioning. As you can see, the project authors are positioning it as a lightweight editor, so they want it to be lightweight, responsive, multilingual and so on. VS Code’s editing capabilities come from an open source Web editor also from Microsoft called Monaco, while Electron, a desktop application that uses JavaScript, HTML, and CSS to build cross-platform applications, has been introduced for cross-platform purposes.

Just because there is a clear orientation and direction, there will be a clearer boundary. You may be wondering how he can support multiple languages and still be lightweight. Then we have to take a look at its multi-process architecture.

  • VS Code has a main process entry that is responsible for some global tasks such as window management, interprocess communication, automatic updates, etc.
  • The render process, as its name implies, is responsible for rendering a Web page;
  • Plug-ins host processes. Each plug-in’s code runs in a host process in a separate and isolated Node environment, and plug-ins have no access to the UI.
  • Debug process, used for debugging;
  • Language services, an important special extension, provide an editing experience for many programming languages, as well as automatic replenishment, error checking (diagnostics), jump to definitions and many other language features supported by VS Code.

The core part is its plug-in system, which brings more personalized open source customization to the expansion of the editor. As long as you can find powerful VS Code plug-ins to put together, your editor will be an advanced and efficient tool to work with.

Let’s take a look at some of the capabilities VS Code has to offer.

Ever been itching to make your own VS Code plug-in? Here is an introductory VS Code plug-in.

Two, environmental preparation

First you get Node.js and Git.

Next, “global (-G)” installs Yeoman (modern Web application scaffolding tool) and VS Code Extension Generator, two officially designated tool scaffolds (tools that generate VS Code plug-in projects).

npm install -g yo generator-code
Copy the code

The installation is successful when you see the following message:

Initialize the project structure

Now that we have our dependencies in place, we are ready to use the Yeoman tool to help us quickly create a project structure. For those of you who may not be familiar with this scaffold, simply put, Yeoman is a universal scaffold system that allows you to create any type of application. You can use it to quickly start new projects. So not only JavaScript, Java, Python, C#, etc. can use it to generate projects, as long as the corresponding generator is available. So let’s go ahead and type Yo Code on the command line.

Let’s take a look at the meanings of these choices, which are literally the same, from top to bottom:

  • New plug-ins (Typescript)
  • New plug-in (JavaScript)
  • New theme colors
  • New language support
  • New snippet
  • New key-value bindings
  • New plugin pack
  • New language pack (localization)

As you can see, the tool supports creating multiple types of projects. We’ll start with extensions today, so the difference between the first and second is that if you know how to use TypeScript, choose the first one, which is officially recommended. If you don’t want to do all the typing and validation work, choose the second JavaScript. This time we’ll use JavaScript for a brief introduction, and then you’ll need to fill in a set of initialization information like this:

The comments are as follows:

  • What type of extension do you want to create? (Which type of extension is created?)
  • What’s the name of your extension? (The name of the extension? Should be all lowercase, no Spaces)
  • What’s the identifier of your extension? (Extended logo?)
  • What’s the description of your extension? (What is the extension description?)
  • Initialize a git repository? (Is the Git repository initialized?)
  • Which package manager to use? (Because we installed NPM, so choose NPM, if you have YARN, you can also choose YARN.)
  • Which package manager to use (to download various NPM packages)

4. Create a simple VS Code plugin

The front of the preparation is almost! Then we’ll start driving the Green Train.

Go to the file directory CD test-extension.

Perhaps you think file directory, a look to know, is not a few configuration information or project description, but here configuration information “very important” X3, important to you may be less than a configuration or configuration of the wrong, the function will not come. So let’s spend a little bit of time talking about what’s going on here.

First you can see in package.json the values you set in the previous step. The main meanings of these Settings are as follows. There is a little note here: If your VS Code is old and you can’t update it to the latest, set the following version of engines lower. For example, I changed it to ^1.52.0 to make sure it was compatible with the current VS Code editor:

{
  "name": "test-extension".// Name of the plug-in
  "displayName": "test-extension".// The name displayed in the plugin market
  "description": "vscode extension sample".// Plug-in description
  "version": "0.0.1".// Plugin version
  "engines": { // the lowest version supports vscode
    "vscode": "^ 1.52.0"
  },
  "categories": [ // Category of plug-ins, used to differentiate in the plug-in market
    "Other"]."activationEvents": [ // The list of events activated by plug-ins can have multiple triggering mechanisms, so it is an array
    "onCommand:test-extension.helloWorld"]."main": "./extension.js".// Plugin main entry
  "contributes": { // Contribution point, which is a configuration item used to extend plug-in functions. We will not go into details here
    "commands": [{"command": "test-extension.helloWorld"."title": "Hello World"}},"scripts": {
    "lint": "eslint ."."pretest": "npm run lint"."test": "node ./test/runTest.js"
  },
  "devDependencies": {
    "@types/vscode": "^ 1.55.0"."@types/glob": "^ 7.1.3." "."@types/mocha": "^ 8.0.4"."@types/node": "^ 12.11.7"."eslint": "^ 7.19.0"."glob": "^ 7.1.6." "."mocha": "^ 8.2.1." "."typescript": "^ 4.1.3." "."vscode-test": "^ 1.5.0." "}}Copy the code

The extsnsion. Js file contains two main functions. One is activate, which refers to the processing when the plug-in is activated. Deactivate: deactivate: deactivate: deactivate: deactivate: deactivate: deactivate: deactivate: deactivate

// uses vscode as a module so that you can use many of its functions
const vscode = require('vscode');

/ * * *@param {vscode.ExtensionContext} context* /
function activate(context) {

  console.log('Congratulations, your extension "test-extension" is now active! ');

  let disposable = vscode.commands.registerCommand('test-extension.helloWorld'.function () {
    vscode.window.showInformationMessage('Hello World from test-extension! ');
  });

  context.subscriptions.push(disposable);
}

function deactivate() {}

module.exports = {
  activate,
  deactivate
}
Copy the code

RegisterComman: registerComman: registerComman: registerComman: registerComman: registerComman: registerComman: registerComman: registerComman Yes, it is the command mentioned above in package.json. Let’s take a look at it:

. .// package.json
 "contributes": { // Contribution point, which is a configuration item used to extend plug-in functions. We will not go into details here
    "commands": [{"command": "test-extension.helloWorld"."title": "Hello World"}}],...Copy the code
.// extension.js
function activate(context) {
  console.log('Congratulations, your extension "test-extension" is now active! ');

  let disposable = vscode.commands.registerCommand('test-extension.helloWorld'.function () {
    vscode.window.showInformationMessage('Hello World from test-extension! '); }); context.subscriptions.push(disposable); }...Copy the code

Does that make sense? The command value set in package.json is the registerCommand value set in extension.js. So what do these lines mean? Let’s run it:

He will open a new VS Code editor for you, and the plug-in will only load into this editor. Now we use the call shortcut (MacOS) command+p and type >Hello World (case insensitive) :

If you press Enter, you’ll find a message in the lower right corner that looks like this:

I’m sure you smart people combined with the code must have seen the light, right! I don’t know if you have this question, but where can I see console.log above? Don’t worry, let’s go back to the editor of the plug-in code and look carefully down here. It will appear after we type the command above, because in package.json we set the activation time of the plug-in to onCommand:test-extension.helloWorld:

Test extension = test extension = test extension = test extension = test extension

. .// package.json
"activationEvents": [
    "onCommand:test.helloWorld"],... ."contributes": {
  "commands": [{"command": "test.helloWorld"."title": "Hello World"}}],...Copy the code
// extension.js.function activate(context) {

  console.log('HERE I am!! ');

  let disposable = vscode.commands.registerCommand('test.helloWorld'.function () {
    vscode.window.showInformationMessage('I changed command's name! '); }); context.subscriptions.push(disposable); }...Copy the code

Again according to the above said trigger method again, found that it is still possible! So the name here is just a namespace that you can change to whatever name you want for more complex plug-in architectures. Since it’s a namespace, you can actually do without the prefix.

Implement a plug-in of your own

So much has been introduced in front, have you noticed that in fact this system is not difficult, there are big guys paving the way in front, in fact, we just need to “fill in the blanks” according to the rules, then now we will implement a small function — add a button and his click events.

Modify our package.json as follows, because currently I want the plug-in to have subscribed to button click events when it loads, so here we can change activationEvents to *, so that our plug-in can activate and register events at the beginning:

. ."activationEvents": [
        "*",]."contributes": {
  "commands": [{"command": "test.helloWorld"."title": "Hello World"
    },
    // Register the button click event with a small icon
    {
      "command": "test.button"."title": "Button"."icon": {
        "light": "./media/light/preview.svg"."dark": "./media/dark/preview.svg"}}].// Add the following configuration here
  "menus": {
    "editor/title": [{"command": "test.button"."group": "navigation"}]}},...Copy the code

Then go back to our extension.js and add a simple message alert:

function activate(context) {
  console.log('HERE I am!! ');
  let disposable = vscode.commands.registerCommand('test.helloWorld'.function () {
    vscode.window.showInformationMessage('I changed command's name! ');
  });
  // Add a button click command operation content
  let button = vscode.commands.registerCommand('test.button'.function () {
    vscode.window.showInformationMessage('Button click');
  });
  // Remember to subscribe to this new command as well
  context.subscriptions.push(disposable, button);
}
Copy the code

Take a look at the results:

Is it easy to customize VS Code styles? So let’s analyze what we did up here. First, we modified the package.json configuration to add a menu. What is this menu? The answer is the menu. The menu item definition contains the command that should be invoked when the selection is made and the condition (when) that should be displayed, so you can also add display logic to the menu item display. For example, we specify that the button should be displayed only when the javascript file is opened:

{
  "contributes": {
    "menus": {
      "editor/title": [{"when": "resourceLangId == javascript"."command": "test.button"."group": "navigation"}]}}}Copy the code

The meaning of group is used to define the sorting and grouping of menu items. This menu is not the one we wrote above, but the editor/context menu, so the groups of different menus are actually slightly different, but generally similar. Navigation has the highest display priority:

We could also add one of these:

"menus": {
  "editor/title": [{"command": "test.button"."group": "navigation"."when": "resourceLangId == javascript"}]."editor/context": [{"command": "test.button"."group": "navigation"."when": "resourceLangId == javascript"}}]Copy the code

The effect is the same:

If you’re wondering what else is on the menu, here’s a quick “translation” of the official website (only the common menu is not all) :

Name of the configuration menu item The menu location
commandPalette Global command panel
explorer/context Resource Manager context menu
editor/context Editor right-click context menu
editor/title Editor title bar to display text without pictures
editor/title/context Editor title right-click context menu
debug/callstack/context Debug stack view context menu
debug/toolbar Debug toolbar
scm/title SCM title menu
view/title Look at the title menu
touchBar Touch the bar macOS
timeline/title Timeline view title menu bar
extension/context Extension View context menu

Sixth, make a conclusion

As you can see from the simple example above, VS Code not only allows you to customize the commands you want, but also allows you to customize the editor “within limits”. Why is it restricted? Because according to the official website, the current plugin system has the following limitations:

The plugin does not have the ability to access the DOM of VS Code UI. So you can’t apply custom CSS to VS Code or add HTML elements to VS Code UI extensions. Such limitations are:

  • Ensure that user operations are controllable and consistent
  • Prevents changes in underlying Web technologies from affecting existing plug-ins
  • Ensure that developers can continue to iterate on the original plug-ins as usual without having to break the rules and relearn them

In fact, today’s content is only a small part of the workspace expansion, to learn this huge system, or to continue to study hard! Next time, we’ll look at declarative language features and wonder how auto-prompt and completion works in the editor.


Follow the HelloGitHub public account to receive the first updates.

There are more open source projects and treasure projects waiting to be discovered.