DEV Community

Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

Custom polymorphic code snippets in VS Code

Code snippets are available in pretty much all code editors these days. They can be a great times saver allowing you to insert commonly used blocks of code for any programming language quickly and easily.

VS Code is no exception and we’ll see exactly how you can create your own custom code snippets to greatly improve your workflow. Not only that but you’ll also learn what polymorphic code snippets are and how useful they can be compared to standard snippets. It’s worth waiting for I promise!

Some implementations of code snippets in other editors can seem a little cryptic to use especially on first exposure. However, in VS Code they’re relatively simple to get the hang of. I was pleasantly surprised to find even dynamic code snippets are pretty straightforward to set up.

So, let’s dive in!

Creating a basic snippet

The process for creating code snippets in VS Code is the same for all programming languages. All custom snippets are stored in JSON files (one for each programming language).

You can access them in VS Code via:

File > Preferences > User Snippets (Windows)

Code > Preferences > User Snippets (macOS)

This displays a drop down list of available languages you can define snippets for. If you’ve already added custom snippets for some languages they appear first in the list for convenience.

Select PHP from the list and a php.json file opens in a new tab inside the editor window. This is where you’ll add your custom snippets for the PHP language.

Each programming language JSON file has a default example in the comments to demonstrate code snippet usage. The example is the same one for all programming languages so isn’t that useful except as a starting point for your first snippet if want to save some typing.

To create a new snippet add a named JSON object to php.json with the following properties:

  • prefix - Text that triggers the code snippet
  • description - Displayed in the list of available snippets as you type in the trigger prefix
  • body - Code snippet content

Here’s a simple example to output the body of a PHP function:

{
"Basic PHP Function": {
"prefix": "func",
"body": [
"function test() {",
"\techo \"Hello World!\";",
"}"
],
"description": "Outputs a basic PHP function."
}
}

The snippet name "Basic PHP Function" is just for your benefit and doesn't appear outside of the JSON file but the prefix and description fields will be visible so it's a good idea to pick meaningful values.

If you only want the snippet to output a single line of then the body can just be a simple string. But most often you’ll want it to span multiple lines in which case define the body as an array of strings as in the example above.

Also if you want the resulting code to be nicely indented then add tab characters \t to the beginning of each line as required. Note how we also escaped the double quote characters so we could use them inside the code snippet.

So, now we’ve defined our code snippet how do we use it?

Firstly, no editor restart is necessary. We can start using the new snippet straight away. Open up an existing PHP file or create a new one and start typing out the first couple of letter of func anywhere after <?php.

Every code snippet matched will be displayed in a pop-up window. But other matches are also displayed such as built-in matches from the PHP language. You can easily tell which ones are code snippets as these are prefixed by a black box with a white border (bottom border is dotted).

To expand out the code snippet select it from the list and hit the Enter or Tab key.

Did you notice when inserting the snippet that you only see the ones available for the programming language you’re currently editing? This makes searching for code snippets very convenient so you don’t have to wade through lots of irrelevant matches.

This is also the key to implementing polymorphic code snippets as we’ll see later on.

Going further with code snippets

Outputting static blocks of code is certainly very useful and can save you a ton of typing but we can do even more with VS Code snippets by making them interactive.

Tab stops

Building on our previous example of the PHP function snippet we can use tab stops to navigate to predefined locations in the code snippet and add our own values.

To define a tab stop just insert a dollar character followed by a number anywhere inside the body of the code snippet.

If we go back to our PHP function example from earlier then we can add tab stops for parameters and the string value.

{
"Basic PHP Function": {
"prefix": "func",
"body": [
"function test( $$1 ) {",
"\techo \"$2\";",
"}",
"",
"$3"
],
"description": "Outputs a basic PHP function."
}
}

Now when the snippet is expanded out the cursor jumps to the first tabs top $1 so you can add a parameter variable. Hitting the tab key again jumps the cursor inside the string value to tab stop $2.

Tab stop order matters here so if we reversed the numbering of the tab stops then the cursor would jump to the string first and then the function parameter.

Note that $$1 for the parameter is not a typo. We're just prefixing the tab stop with a $ character so it doesn't have to be entered every time. You can leave this out of course if you wish.

We also added a third tab stop to jump to outside of the function for convenience so we can easily carry on adding new PHP statements outside of the function body.

Placeholders

Rather than simply jump the cursor to predefined points we can also add numbered placeholder text which gets inserted into the snippet by default.

A numbered tab stop placeholder is defined as:

${1:item}

You can read this as the first tab stop with the default text item. As you cycle through each tab stop you can optionally update the inserted text before tabbing to the next location or leave it at the default value.

{
"Basic PHP Function": {
"prefix": "func",
"body": [
"function test($${1:name}, $${2:age}, $${3:gender}) {",
"\techo \"Output data: {$${4:name}} {$${5:age}} {$${6:gender}}\";",
"}",
"",
"$0"
],
"description": "Outputs a basic PHP function."
}
}

If you don’t alter any of the default placeholder text then the function will be outputted as:

function test($name, $age, $gender) {
    echo "Output data: {$name} {$age} {$gender}";
}

This is fine if you’re happy with the default placeholder text but if you want to change any of the variables then you have to type in the text twice so that they are matched in both places.

If you have more complicated code snippets with the same variables used in several places inside the snippet then this can soon get tedious. We’ll see how to get around this next.

Variable placeholders

Rather than have numbered tab stops you can also have variable placeholder tab stops. This is great for when you have the same variable defined in multiple locations. Every time you update a variable placeholder it updates in all other locations too.

Let’s modify the example from the previous section to use variable placeholders.

{
"Basic PHP Function": {
"prefix": "func",
"body": [
"function test($${name}, $${age}, $${gender}) {",
"\techo \"Output data: {$${name}} {$${age}} {$${gender}}\";",
"}",
"",
"$0"
],
"description": "Outputs a basic PHP function."
}
}

Now when you trigger the snippet if you update any of the placeholders it automatically updates in the other location too which is exactly what we want!

Placeholder choices

If you’re using numbered placeholders then you can optionally provide users with a choice of values that can be inserted too.

The format for this is:

${1|one,two,three|}

The choices are inserted as a comma separated list surrounded by pipe characters.

An example of using placeholder choices is:

{
"Favorite Color": {
"prefix": "favcol",
"body": [
"echo \"My favorite color is ${1|red,green,orange,blue,indigo|}\";",
"$0"
],
"description": "Outputs your favorite color."
}
}

When you trigger this code snippet a drop-down list of choices is presented. Just select the one you want and then hit tab to go to the next tab stop.

Polymorphic code snippets

Now that we’ve covered how to implement code snippets in VS Code let’s turn our attention to making them work more efficiently.

First though let’s talk about polymorphism. The big idea has to do with reusability. It is commonly found in situations where something occurs in multiple forms but is available via a common interface.

Polymorphism is kind of a big deal in object-oriented programming (OOP) and there are entire books dedicated to the subject. For our purposes though we can take this idea of reusability and apply it when implementing code snippets for different programming languages that are invoked via a common trigger.

Let’s say that you have code snippets defined in several different programming languages that do the same thing. i.e. the syntax is different for each snippet but the purpose of the code snippet is the same.

One such example could be to output a value of a variable for debugging purposes.

We’ll implement this in PHP and JavaScript but you could easily extend this for other languages too such as C++, Python, Java, Objective-C and so on.

PHP

{
"Output PHP value": {
"prefix": "pout",
"body": [
"echo \"<pre>\";",
"print\_r($${value});",
"echo \"</pre>\";",
"$0"
],
"description": "Outputs a PHP value to the screen."
}
}

JavaScript

{
"Output JavaScript value": {
"prefix": "jout",
"body": [
"console.log(${value});",
"$0"
],
"description": "Outputs a PHP value to the screen."
}
}

As we continued to add output code snippets for other programming languages we’d have to remember how we named them for each language.

But the trick is to purposely give them all exactly the same trigger.

PHP

{
"Output PHP value": {
"prefix": "out",
"body": [
"echo \"<pre>\";",
"print\_r($${value});",
"echo \"</pre>\";",
"$0"
],
"description": "Outputs a PHP value to the screen."
}
}

JavaScript

{
"Output JavaScript value": {
"prefix": "out",
"body": [
"console.log(${value});",
"$0"
],
"description": "Outputs a PHP value to the screen."
}
}

So now we have a single trigger that contextually outputs a code snippet depending on the type of file you triggered the snippet from. Neat eh?

Try it out for yourself. Start typing out inside a PHP file. As you can see this triggers the code snippet from php.json and likewise if you do the same from a JavaScript file then the javascript.json out snippet gets used instead!

Here’s another example to output the same HTML tags from multiple languages. Tab stops are defined to allow the HTML tags to be changed if required.

HTML

{
"Output HTML": {
"prefix": "tag",
"body": [
"<${h2}>Heading</${h2}>",
"<${p}>I wandered lonely as a cloud.</${p}>",
"$0"
],
"description": "Outputs HTML."
}
}

PHP

{
"Output HTML Tag": {
"prefix": "tag",
"body": [
"echo \"<${h2}>Heading</${h2}>\";",
"echo \"<${p}>I wandered lonely as a cloud.</${p}>\";",
"$0"
],
"description": "Outputs HTML via PHP."
}
}

JavaScript

{
"Output HTML Tag": {
"prefix": "tag",
"body": [
"var heading = \"<${h2}>Heading</${h2}>\";",
"var body = \"<${p}>I wandered lonely as a cloud.</${p}>\";",
"document.querySelector(\"#${id}\").innerHTML = heading + body;",
"$0"
],
"description": "Outputs HTML via JavaScript."
}
}

JSX

"Output HTML Tag": {
"prefix": "tag",
"body": [
"class ${Component} extends React.Component {",
"\trender() {",
"\t\treturn (",
"\t\t\t<Fragment>",
"\t\t\t\t<${h1}>Heading</${h1}>",
"\t\t\t\t<${p}>I wandered lonely as a cloud.</${p}>"
"\t\t\t</Fragment>",
"\t\t)",
"\t}",
"}",
"$0"
],
"description": "Outputs HTML via JSX."
}
}

As before, just start typing out the trigger text (in this case tag) and you'll see the relevant code snippet for the type of file you're currently editing.

Congratulations, you’ve now graduated to the world of polymorphic code snippets!

This approach to developing code snippets is very efficient and can save you from having to remember lot’s of different snippet triggers. Now you only need to remember just a single trigger for snippets that perform a common task.

What’s more, you can create as many of these polymorphic code snippets as you like!

Plug: LogRocket, a DVR for web apps

https://logrocket.com/signup/

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.


Top comments (0)