DEV Community

Filipe Correia for Runtime Revolution

Posted on • Originally published at revs.runtime-revolution.com on

My journey in developing editor extensions

Photo by Ricardo Rocha on Unsplash

When Github’s Atom editor was released a few years ago, I, like many other Web Developers, thought something along the lines of “Neat! An extensible editor built on a stack I know”. A lot of developers started to contribute to it right away and it made the editor pretty great.

I started to use Atom for 2 reasons:

  1. There were new awesome extensions coming out every other week.
  2. I knew the whole stack, which made it pretty awesome to hack and it meant that one day I could create my very own extension.

The big cursor extension

At the time I started using Atom I was programming with 3 indentation based languages: Slim, Sass, and CoffeeScript.

I had no idea I could change the tab sizes so I was using a single space tab. It was a pain to figure out where an indentation block would finish. So I thought it would be really neat if I could transform the editor cursor into a kind of ruler to see where everything finished. I wanted something like this:

To figure out how to do it I just toggled the developer tools on Atom, chose the cursor element and changed its CSS. That was pretty much the proof of concept. I knew it could be done, now all I had to do was actually do it.

I created an extension by picking the option in Atom’s menu to generate one. I had to look a bit at the documentation to figure out how to register a command and how to apply a class to the cursor. The first iteration of the extension was quite simple, it boiled down to:

Simple and it worked.

What happened to it?

When I wrote that extension version 1 of Atom hadn’t come out yet, that meant that the API kept changing, and honestly because I wasn’t needing it anymore I just stopped developing it.

Enter VSCode

Fast forward a couple of years, I started using VSCode instead of Atom. A couple of months ago I was using a neat extension to change some variable names to camel case, snake case, etc…

It was getting repetitive to open up the palette and typing in the command name. I didn’t want to create a keybinding for it. So I thought of the aliases in ZSH shell.

In ZSH there are a lot of plugins that you can add that, among other features, give you shorter versions of shell commands. For example, with the Git plugin git checkout is gco, or with the Rails plugin, rails server is just rs.

So for a command like “Change Case Snake Case”, I could just grab the first letter of each word and have a command called ccsc that would run it.

Writing a VSCode extension

So I decided to look at how to create VSCode extensions. I was already a bit familiar with how the code would look like because of some contributions I did for Scry (a language server for Crystal) which involved looking into Crystal’s VSCode extension.

A VSCode extension is created with a Yeoman generator, (which honestly I had no idea was still a thing). And it looks like this:

The Typescript extension skeleton is pretty neat, it can set you up with a stricter tsconfig(which means that the Typescript files can fail to compile more often, which is good, sometimes) and it can also configure tslint (which is a linter for Typescript).

After the generator is finished you have a hello world extension which adds a command that logs “hello world”. The project makes use of VSCode’s debug tasks to be able to run an instance of VSCode with the extension enabled. This is really easy to set up and lets you add breakpoints as well so it is awesome to explore the API.

Now, to try and build the extension I wanted, I needed to find out how to:

  1. Create a palette box where the user can type.
  2. Filter out the palette box to show the commands according to the short version the user types.
  3. Get all the commands available so that the box has something to search for.
  4. Execute the command.

This took some digging into the docs and example repos that are available. The problem is that the API is very restrictive. This is how I went about tackling the four tasks I had planned.

  1. Create a palette box where the user can type.

You don’t have access to the DOM or the view. Basically, there’s a preset of views you can create (one of them being an actual HTML panel, where you can manipulate the whole HTML). Luckily there’s a view for the palette box, I just had to figure out how that worked.

  1. Filter the palette box

This was a bit of a hack, the API for the QuickPick component doesn’t offer a filter option. It does have an event you can hook whenever the user types, and I just change the list of options each time. It works surprisingly well.

  1. Get all the commands available.

Getting all the commands was a bit weird, you can get a list of the other installed extensions, for each you can access a parsed version of its package.json which has the commands of the extension listed in there.

  1. Execute the command

This was pretty straightforward, just an API call to run a specific command.

In the end, this is what the extension looks like:

Finishing up

This was my experience developing editor extensions. My goal for writing this article was to show that, while it has its challenges, there isn’t much to it. I hope that I’ve inspired you to write your own. At least from my experience, it is very common to have an idea in your head of what could be better in the tools you use, and creating an extension might be the answer.

Links to Stuff

Do you have an idea for an extension? Ever tried creating your own? I’d love to know about your idea or experience, just comment below!

I work at Runtime Revolution from sunny Lisbon developing great products. If you’d like to work with us just reach out.


Top comments (0)