Building a language-specific extension tutorial

Sourcegraph extension button

Extensions can be configured to activate and contribute UI elements only upon the presence of a specific language, languages or glob pattern. This improves performance by only using the network and CPU for extensions that are needed.

In this tutorial, you'll build an extension that activates, displays a button, and hover content, but only if a Python file is present.

Prerequisites

This tutorial presumes you have created and published an extension. If not, complete the Hello world tutorial first.

It also presumes you have the Sourcegraph browser extension installed.

Set up

Create the extension you'll use for this tutorial:

mkdir py-button
cd py-button
npm init sourcegraph-extension

Then publish your extension:

src extension publish

Confirm your extension is enabled and working by:

  • Opening the extension detail page.
  • Viewing a file on Sourcegraph.com and confirming the hover for your extension appears.

Controlling extension activation

To activate only for Python files, the contents of the activationEvents field in package.json changes to:

"activationEvents": ["onLanguage:python"]

Publish your extension to apply this change and now, you will see hovers only when viewing a Python file.

Conditional button display

This code defines an action that will be placed in editor/title section. It uses an icon and a small label to leave space for other other extension buttons.

Replace the contents of the contributes object in package.json:

{
  "actions": [
  {
    "id": "pybutton.open",
      "command": "open",
      "commandArguments": [
        "https://www.python.org/"
      ],
      "actionItem": {
        "description": "Go to python.org",
        "iconURL": "data:image/png;base64,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"
      }
    }
  ],
  "menus": {
    "editor/title": [
      {
        "action": "pybutton.open",
        "when": "resource.language == 'python'"
      }
    ]
  }
}

The when field is an expression. If an expression returns a true or a truthy, the properties of the action it references are used to display an element in the chosen menu location, e.g. editor/title.

The code "when": "resource" means the button will be active on code view pages only. "when": "resource.language == 'python'" means the button will only be active on python code view pages, and show an inactive button on other code views.

Publish the extension to see the button when viewing a Python file.

Sourcegraph extension button

The button when clicked will call the built-in open command to load Python's home page. We're almost done, but we have one more change to do.

Controlling language providers

Language providers e.g. the HoverProvider, control if they provide content by accepting an array of language filters when registered.

In the extension code, replace the contents of the array supplied to registerHoverProvider from '*' to { language: 'python' }. It should now look like this:

sourcegraph.languages.registerHoverProvider([{ language: 'python' }], {
  ...
}

Despite our extension activating for only Python files, we need to filter here too.

When an extension's activeConditions become not true (e.g, looking at a Ruby file), it's not immediately deactivated, meaning its hover registration(s) still exist. It's a safeguard so only Python files trigger hover content to be shown.

The activation documentation delves deeper into deactivation and the extension lifecycle.

Summary

You can now conditionally activate, show a button, and hover content for a specific language!

Next Steps