Make yourself an vscode extension

A screenshot of the extension in action on vscode

Overview

Hi, I worked with React Compiler recently, you can find it here. After comparing the render performance, I can see I missed to memoize some cases (lost in the memos). I was thinking it would be nice if any visual tag is attached to the variable which is memoized.

Finding online and could not find any, so why am i not creating one for myself? We will see more about my production in another post, this one will focus only on how can we create and publish an vscode extension to the marketplace.

I'm sure there will be so much such a blog like this for guiding you how to do this, but there will be some struggle that you might occured. This will be the wrapper for the official document

Let's make one together!

Let's start

Initialize the project

Let's start with simple command:

terminal
1npx --package yo --package generator-code -- yo code

This will open a terminal guide to give you options. In this case, we are doing for Typescript, so they suggested to choode the option as following:

terminal
1# ? What type of extension do you want to create? New Extension (TypeScript)
2# ? What's the name of your extension? Complimentor
3### Press <Enter> to choose default for all options below ###
4
5# ? What's the identifier of your extension? complimentor
6# ? What's the description of your extension? LEAVE BLANK
7# ? Initialize a git repository? Y
8# ? Which bundler to use? unbundled
9# ? Which package manager to use? yarn
10
11# ? Do you want to open the new folder with Visual Studio Code? Open with "code"

You can see here they are not bundled and use npm:

  • Not bundling: It's okay, since we only run with Node.js, no browser run so no need to bundle for optimized.
  • using npm: let's use yarn for our case.

Try debugigng for the first time

At the left panel, let's click on Run and Debug (or Cmd/Ctrl + Shift + D). From there select Start Debugging (or F5).

The pop up window will have [Extension Development Host], make sure we interact with correct window.

From here, we Cmd/Ctrl + Shift + P, then type Hello World. You should see the option and the popup message with Hello World from Complimentor!.

Small note

But, you might meet the same issue with me. Type Hello World and see nothing. For deeper research, Option + Cmd/Ctrl + I for opening console, it will throw something like this:

console
1Extension is not compatible with Code 1.96.4. Extension requires: ^1.105.0.

The Code version is imcompatible, go to package.json, update the engine to your equivalent mentioned version, in mine case is 1.96.4:

package.json
1"engines": {
2 "vscode": "^1.96.4" // <--- update here
3},
4"devDependencies": {
5 "@types/vscode": "^1.96.4", // <--- update here too
6}

Now run debug again, you found the Hello World command, and voila!

Take a look inside

Now we have a bunch of new code, what are they, which should I care first?

extension.ts

This is the entry point of your extension.

  • activate: is everything happened when you activate the extension.
  • vscode.commands.registerCommand('', () => {}): this is action when we toggle the extension by command Cmd + Shift + P
  • vscode.window.showInformationMessage(): the popup with message you see at the bottom right of the screen

package.json

This is where you set the config for your extension:

package.json
1"contributes": {
2 "commands": [
3 {
4 "command": "complimentor.helloWorld",
5 "title": "Hello World"
6 }
7 ]
8 },

This will match with the registerCommand inside extension. Remeber to match exactly 2 texts:

package.json
1"activationEvents": [],

This is when the extension activate (in condition you activate the extension inside marketplace). Empty means when you toggle on, but there will be some aother options:

package.json
1"activationEvents": [
2 "onStartupFinished", // the window finished start up
3 "onLanguage:javascript", // language check if js
4 "onLanguage:typescript", // language check if ts
5 "onLanguage:javascriptreact", // language check if jsx
6 "onLanguage:typescriptreact" // language check if tsx
7],

Let's write some code

The idea behind

We will create an extension, that's like a buddy cheers us up everytime we make change to our code. That's easy, so let's list down the feature:

  • When the ide fully loaded, say something like Let's coding!
  • Whenever make change and hit save, say some compliment.
  • And can give compliment when toggle the command.

Adding features

APIs

We need to check the vscode APIs for checking which one should we use, here. But I'll give you the one we'll use:

  • vscode.window.activeTextEditor: Whenever the ide is fulle loaded
  • vscode.workspace.onDidSaveTextDocument: Whenever user save
  • vscode.window.showInformationMessage: Show the pop up with message
  • vscode.commands.registerCommand: Whenever toggle the extension

Adding logics

Inside extension.ts, let's adding an array for the compliments:

extension.ts
1export function activate(context: vscode.ExtensionContext) {
2 const compliments = [
3 "You're doing amazing work!",
4 "That save was smooth as butter!",
5 "Keep it up, code master!",
6 "You're making magic happen!",
7 "Another step toward greatness!",
8 "Code looks cleaner already!",
9 "You're unstoppable today!",
10 "Beautiful save, keep going!",
11 "You're coding like a legend!",
12 "Fantastic progress!",
13 ];
14
15 // ... upcoming code
16}

Then. for the first feature, we listening for the event then pop it out:

extension.ts
1export function activate(context: vscode.ExtensionContext) {
2 const compliments = [
3 // last step
4 ];
5
6 // ... prev code
7
8 if (vscode.window.activeTextEditor) {
9 vscode.window.showInformationMessage("Let's start coding!");
10 }
11
12 // ... upcoming code
13}

Now go for the save event handler:

extension.ts
1export function activate(context: vscode.ExtensionContext) {
2 // ... prev code
3
4 const onDidSave = vscode.workspace.onDidSaveTextDocument(() => {
5 const random = compliments[Math.floor(Math.random() * compliments.length)];
6 vscode.window.showInformationMessage(random);
7 });
8
9 context.subscriptions.push(onDidSave);
10
11 // ... upcoming code
12}

You might try:

extension.ts
1vscode.workspace.onDidSaveTextDocument(() => {
2 const random = compliments[Math.floor(Math.random() * compliments.length)];
3 vscode.window.showInformationMessage(random);
4});
And this still works! But if we add to context.subscriptions, the system will clean up everything for us, instead of hanging event listener even when not needed.

Last one, when the user triggered (this one they give us from the beginning):

extension.ts
1// ... prev code
2
3const disposable = vscode.commands.registerCommand(
4 "complimentor.helloWorld",
5 () => {
6 vscode.window.showInformationMessage("Hello World from Complimentor!");
7 }
8);
9
10context.subscriptions.push(disposable);
11
12// ... upcoming code

So now, if you debug, you hit save, nothing happened. Then when you toggle it, everything works until now. Why?

Adding config

Remember that we have activationEvents": [] at our package.json. As we leave it blank, it will be only triggered when we toggle the extension on. In my case, i want it to be on whenever we start our vscode session, so let's adding this:

package.json
1"activationEvents": [
2 "onStartupFinished", // <--- this one
3],

Make it global

Everything is done! Let's give the world the chance to use it. We have the tutorial here, but let's still go through together!

Launch

Create Azure Devops organization

The given one inside the website makes me misarable for a while, i find someway around but instead im trying this one:

url
1https://aex.dev.azure.com/me?mkt=en-US

Or you can just follow the tutorial!

Get Personal Access Token

Follow this one:

url
1https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token

Create a publisher

Follow this one:

url
1https://code.visualstudio.com/api/working-with-extensions/publishing-extension#create-a-publisher

Prelaunch step

We'll use vsce. It stands for Visual Studio Code Extension. You can install it globally with

terminal
1npm install -g @vscode/vsce

Then we'll check if our extension qualified for the publish. This is some steps you might need to do now:

  • Adjust the README.md file
  • Publish to Github, then update at package.json:
package.json
1"repository": {
2 "type": "git",
3 "url": "https://github.com/YourUserName/complimentor"
4 },
  • Add the publisher to package.json as the one you just created:
package.json
1"publisher": "YourPublisherName",
  • Add the icon to your extension. Just create a new folder at root and add your icon there. Remember only .jpg and .png are supported
package.json
1"icon": "images/icon.png",

Now we go:

terminal
1vsce package

It will check, and generated myExtension.vsix if alls good for publishing.

Launch it

terminal
1vsce publish

Remember to add Personal Access Token for publisher YourPublisherName: here.

Verify the extension

Let's go to the marketplace manager page

url
1https://marketplace.visualstudio.com/manage/publishers/YourPublisherName

then wait a bit for them to verify your extension. Afterward, you will be able to find it at VSCode Marketplace!

Conclusion

It's quite a long post, and I'm glad we can make it here together! I hope you can make yourself one extension, and many more useful one.

By the way, we have this since i created another one for myself, you can find it here. It called MemoMate, the mate for you to highlight the memoized React component in your repo.

Happy coding, pals!

Table of Contents

Overview
Let's start
Initialize the project
Try debugigng for the first time
Small note
Take a look inside
extension.ts
package.json
Let's write some code
The idea behind
Adding features
APIs
Adding logics
Adding config
Make it global
Create Azure Devops organization
Get Personal Access Token
Create a publisher
Prelaunch step
Launch it
Verify the extension
Conclusion