Configuring a Visual Studio Code Extension
Tags: techtips, programming, vscode
Published: 2020-07-16 13:45:08

---
title: Configuring a Visual Studio Code Extension
published: true
date: 2020-07-15 11:51:02 UTC
tags: techtips,programming,vscode
canonical_url: https://john.colagioia.net/blog/2020/07/15/vsconfig.html
---

As a quick note, I [released this post](https://john.colagioia.net/blog/2020/07/15/vsconfig.html) on my blog, this morning, so it can get to be (as I tend to be) a bit rambling.  Oh, and the original text is [on GitHub](https://github.com/jcolag/entropy-arbitrage) (licensed CC-BY-SA), so if anything seems muddy, by all means:

 * Leave a comment here,
 * Leave a comment on the blog,
 * File an issue on GitHub, or
 * Add a pull request!

{% github jcolag/entropy-arbitrage no-readme %} 

* * *

![Visual Studio Codium](https://dev-to-uploads.s3.amazonaws.com/i/4p48huhag8tawohywz6r.png "Visual Studio Codium")

Continuing [the discussion](/blog/2020/07/08/vscode.html) on creating an extension for Visual Studio Code, and now that [**VSCode Rat**](https://github.com/jcolag/vscode-rat) is—seemingly against all odds—working _far_ better than it has any right to work, it’s time to add a configuration page. After all, it doesn’t make a lot of sense to ask people to blindly trust the URL that I provided or expect them to edit the code to insert their custom URL.

{% link jcolag/writing-visual-studio-code-extensions-42fi %}

{% github jcolag/vscode-rat no-readme %} 

Like last time, this turns out to be a project where it’s harder to find the information needed than to actually perform the tasks required. After a shocking amount of digging, I _finally_ found the poorly named [Contribution Points](https://code.visualstudio.com/api/references/contribution-points) reference, which gives an overview of…a lot.

## Adding Configuration Options

In the process of creating the extension, you might recall the `contributes` property in the `package.json` file. We used it to add a _command_ to explicitly call our new feature.

That command is now obsolete, since all the **VSCode Rat** code runs autonomously, but the property is still useful, because it’s where our configuration options go. In the case of this extension, the property looks something like the following.

```json
"contributes": {
  "commands": [{
    "command": "vscode-rat.helloWorld",
    "title": "Hello World"
  }],
  "configuration": {
    "title": "VSCode Rat",
    "properties": {
      "vscodeRat.targetUrl": {
        "type": "string",
        "default": "http://localhost:8080",
        "description": "Server waiting for VSCode Rat to rat you out!"
      }
    }
  }
},
```

We only have one option: `vscodeRat.targetUrl`, which takes a string (the URL), and has a default and description. And we can see that instantly, the next time we run, by opening _File_/_Preferences_/_Settings_ in the menu, opening the _Extensions_ item, and scrolling to the bottom.

![A Configuration Option](https://dev-to-uploads.s3.amazonaws.com/i/tgeiuff4i2naz2016akg.png "A configuration option!")

That, then, gives us our option. If we need more, we can add more.

### Not Quite

Now that I think about it, we probably want that URL to actually _be_ a URL, so we need some validation. Visual Studio Code doesn’t give us _great_ validation, but it’s decent. We can set a `pattern` property on each configuration option, which is a regular expression. So, we’ll throw that in.

```json
"vscodeRat.targetUrl": {
  "type": "string",
  "default": "http://localhost:8080",
  "description": "Server waiting for VSCode Rat to rat you out!",
  "pattern": "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"
}
```

Since JSON doesn’t know or care about regular expressions, all the back-slashes in the regular expression need to be escaped…with back-slashes, which is why they’re doubled.

## Using Configuration Options

Now that we have a URL for any server willing to accept our POSTs, we can also use it. Since the configuration options can change at any time, we need to check it on every use, modifying our handler code to something like this.

```javascript
vscode.workspace.onDidOpenTextDocument((document) => {
  const file = document.fileName;
  const post_data = `Opened ${file}`;
  const config = vscode.workspace.getConfiguration('vscodeRat');
  const urlParts = url.parse(config.targetUrl);

  httpPost({
    body: post_data,
    headers: {
      'Content-Type': 'text/plain',
    },
    hostname: urlParts.host,
    path: urlParts.path
  });
});
```

You’ll notice that we now call `vscode.workspace.getConfiguration()` with the prefix of our configuration options specified above, to get an object with the extension’s options. It returns something like this.

```json
{
  targetUrl: "http://localhost:8080"
}
```

In this case, I’m using Node’s built-in `url` library to parse the single URL to provide the host name and path required by the `httpPost()` function I snagged for last week.

And that’s it. I can now configure **VSCode Rat** to send all of its updates to a mailbox on [Henry’s Post Test Server](http://ptsv2.com/), and we all lived happily ever after. Well, almost.

## Oops…

When creating the extension, in order to get things moving as quickly as possible, I prototyped with Node’s built-in `http` library, which shouldn’t make HTTPS calls. That’s fine for the sake of this experiment, but an extension ready for production will need to handle *any* kind of URL, which probably means choosing a different networking library—I’ve heard good things about [axios](https://www.npmjs.com/package/axios), for example—and rewriting the POST calls to work with it.

That, however, is far less important. At this point, we now have an extension that we can point to any server, even if the code itself isn't prepared to carry out that promise.

* * *

**Credits** : The header image is the sample image for [VSCodium](https://vscodium.com/) and made available (like the application and their entire site) under the terms of the MIT License.