Code 2x faster with custom VSCode extensions.

NALSengineering
6 min readSep 5, 2023

Credit: Nguyễn Thành Minh

Introduction

It’s rare to find anybody who works in VSCode without using several extensions. After all, they’re here to help us write code faster!

VSCode Extensions

It can help us generate code with a command or snippet.

Commands and Snippets

In case you’re not yet familiar with commands and snippets, I’ll demonstrate it here in this example.

  • Generating data classes from a JSON with a command.
Command example

With just a single command: NALS: Clipboard to Data Model, it generated as many as 26 files of code within a few seconds.

  • Generating an entity class with a snippet.
Snippet Example

By entering 3 letters ett, it generated a class with the same name as the File.

As you can probably guess, extensions can save you a whole lot of time. But even sometimes, you’ll wish there was an extension catered to your specific project. What if you could write one yourself? In this article, I’ll teach you how to create such tools using TypeScript and VSCode API.

Your First Extension

First, install Node.js and Git, then install Yeoman and VS Code Extension Generator using:

npm install -g yo generator-code

To create a new project for your extension, run the following command:

yo code

Then, it’ll ask you about things like the programming language, project name, etc. Here, I’ll choose TypeScript and name it HelloWorld along with the ID helloworld

# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? HelloWorld
### Press <Enter> to choose default for all options below ###
# ? What's the identifier of your extension? helloworld
# ? What's the description of your extension? LEAVE BLANK
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? Yes
# ? Which package manager to use? npm
# ? Do you want to open the new folder with Visual Studio Code? Open with `code`

After creating the project, you can test-run it by hitting F5. This will compile and run the extension in a new Extension Development Host window.

The default project format gives us a Hello World command. We can run the command from the Command Pallete (⇧⌘P) in the new window:

Your first VSCode Extension

You should see the Hello World from HelloWorld! notification showing up. Awesome! But what is actually happening with all that? Don’t worry, I will explain some bits below, mainly regarding two files: extension.js and package.json.

What is Extension.ts?

This is where you register your commands. For instance, if your extension has 10 commands, you’ll need to register them by using the registerCommand function inside theactivate function.

The activate function acts as an entry point — it’s called right after the extension is activated.

Now, let’s rewrite the default HelloWorld command to make our own command.

Normally, all code can go into this file. But, for the sake of clean code, let’s have a separate file for our body function.

First, create the file with the path src/commands/hello_world.ts. Then paste the following code which I’ll explain right below:

import * as vscode from 'vscode'; // 1

export const helloWorld = () => {
console.log('Hello World'); // 2
vscode.window.showInformationMessage('Hello World from NALS!'); // 3
vscode.window.showErrorMessage('your error'); // 4
};
  1. importing VSCode API
  2. We can use console.log to debug our code. We can also place breakpoints like this.
  3. vscode.window.showInformationMessage is a function from VSCode API, it can show information messages to users.
  4. vscode.window.showErrorMessage helps us show error messages to users.

Now, the only thing left in activate function in extension.ts is:

export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand("helloworld.helloWorld", helloWorld)
);
}

Keep in mind, the string “helloworld.helloWorld” can be seen as the ID of the command. It must be declared the exact same way as it is in the package.json file, which I’ll talk about next.

Run the Hello World command again, and we get:

Pro Tip: Sometimes you may not be able to place breakpoints for debugging. When it happens, try running any command to activate this “activate” function.

What is package.json?

package.json

First, let’s pay some attention to the 3 areas I’ve marked red above:

  1. Area 1 is where we enter the name, ID, description, and version of the extension.
  2. Area 2 is where we declare all commands inside the extension. Each command has 2 properties: command and title;command must be identical to the string registered in the registerCommand function in the file extension.ts , while the title will be shown in the Command Pallete. That’s how the command actually links to your code.
  3. Area 3 is where we declare all libraries used in the project. change-caselodash are 2 extremely useful ones for writing VSCode extension.

Full source code: Hello World command

Just like that, we now know how commands work and how to make one. Now, let’s create a command that’s a little more complicated than before.

The AddCopyright Command

In our projects, we always write copyright information like this at the top of our code files.

Copyright

Here, common_paging_controller is the filename.

This takes time, but we can create a command to do the job for us.

First, create the file add_copyright.ts with the path src/commands/add_copyright.ts

import * as vscode from "vscode";
import {
currentPath,
currentFileName,
writeFile,
readFile,
} from "../utils/utils";

export const addCopyRight = async () => {
let currentText = await readFile(currentPath()); // Read current file content
let copyrightContent = `// ${currentFileName()} - Copyright © 2023 — NAL Solutions. All Rights Reserved\n${currentText}`;

// if copyright content is not already added, add it
if (!currentText.startsWith(copyrightContent)) {
await writeFile(currentPath(), copyrightContent);
vscode.window.showInformationMessage("Done!");
} else {
vscode.window.showInformationMessage("copyright already added!");
}
};

The idea is like this: First, the extension reads the active code file and checks if the copyright has already been written. If not, it does the job for us by re-writing the file.

We can check if the code file is being active with:

export const currentFile = () => vscode.window.activeTextEditor!.document.uri;

Once we’ve got currentFile, we can easily obtain its path currentPath and filename currentFileName.

export const currentPath = () => currentFile().path;
export const currentFileName = () => currentPath().substring(currentPath().lastIndexOf('/') + 1, currentPath().lastIndexOf('.'));

All 4 functions currentPath, currentFileName, readFile, and writeFile can be reused, so we place it in the src/utils/utils.ts file.

After coding the addCopyright function, we register it in the activate function of the extension.ts file.

registerCommand

Finally, don’t forget to declare the command in package.json

With that, we’re done!

Add copyright command

Full source code: the Add Copyright command

Conclusion

I hope this example has helped you understand how powerful it can be (and how much time you can save). In the next part, we’ll create a command that is even more powerful. It helps us generate many code files.

--

--

NALSengineering

Knowledge sharing empowers digital transformation and self-development in the daily practices of software development at NAL Solutions.