Home

Awesome

Dev Container Features: emacs-lsp-bridge

This repository provides automation to generate devcontainer features for every language server supported by lsp-bridge. It uses nix packages to install the language server and lsp-bridge environment inside the container.

This DevContainer feature automatically updates and releases the latest version of LSP-Bridge daily.

Emacs lsp-bridge showing auto-completion menu when opeing a file in container

Available Features

You can find all available features in the Packages section.

If python3 and pip3 are available in the base image, lsp-bridge will use it to create virtual environment instead of installing another Python interprepter from nix.

Connect lsp-bridge to Container

Here is how you can set up lsp-bridge to connect to the container and open a file in Emacs to start the auto-completion.

Setup devcontainer

Add a .devcontainer/devcontainer.json to your project. Below is an example configuration:

{
	"name": "Ubuntu",
    // Your base image
	"image": "mcr.microsoft.com/devcontainers/base:jammy",
    // Features to add to the dev container. More info: https://containers.dev/features.
	"features": {
		"ghcr.io/nohzafk/devcontainer-feature-emacs-lsp-bridge/gleam:latest": {}
	},
	"forwardPorts": [
        9997,
        9998,
        9999
    ],
    // More info: https://aka.ms/dev-containers-non-root.
	"remoteUser": "vscode"
}

In this configuration, you need to add the features, forwardPorts, and remoteUser fields.

Features

Select the language server you want to use in the features section. For example:

"ghcr.io/nohzafk/devcontainer-feature-emacs-lsp-bridge/typescript_eslint:latest": {}

You can find all available features in the Packages section.

Use the file name of the language server definition file in lsp-bridge as the feature name.

❯ cd lsp-bridge
# ls langserver/
❯ ls multiserver/
 css_emmet.json          jedi_ruff.json                          python-ms_ruff.json
 css_tailwindcss.json    pylsp_ruff.json                         qmlls_javascript.json
 html_emmet.json         pyright-background-analysis_ruff.json   typescript_eslint.json
 html_tailwindcss.json   pyright_ruff.json                       volar_emmet.json

For example, to use the pyright-background-analysis_ruff language server, add this line to the features section in the devcontainer.json:

"ghcr.io/nohzafk/devcontainer-feature-emacs-lsp-bridge/pyright-background-analysis_ruff:latest": {}

Forward Ports

This is needed to communicate with the lsp-bridge server inside the container. Ensure you list the ports 9997 9998 9999 in the forwardPorts section.

Remote User

Identify the default user used by your base image, such as root or vscode.

It is important to get this use right, otherwise lsp-bridge won't be working, if you use vscode to start the devcontainer, mostly it will be vscode.

This user is used to spawn the lsp-bridge server process, and you need to use it when opening a file in Emacs. For more information, see the remoteUser documentation.

Start the devcontainer

Use Dev Containers Extension with VSCode to start the devcontainer

By default devcontainer mount the current project folder under /workspaces/ inside the container, more details.

Without VSCode

If you don't want to use VSCode, you can use the devcontainer CLI command line tool and devcontainer cli port forwarder to start the devcontaienr on Terminal.

the port forwarder is needed because forwardPorts is not implemented by devcontainer CLI, see #issue 22

Use Emacs to open file in devcontainer

use find-file and input the file name prefix /docker:user@, press TAB, and Emacs will list out the container name for use

C-x C-f /docker:user@container:/workspaces/project/file

where
  user           is the user that you want to use inside the container, use the same user as remoteUser in devcontainer.json
  container      is the id or name of the container

check docker-tramp for more details.

Supported language servers (81)

Contributing

Nix Package Definition

The definition of which nix package to use for the language server is specified in _generator/langserver.json. Here is an example:

{
    "langserver": "typescript",
    "packages": "nodePackages.typescript-language-server",
    "langserver_binary": "typescript-language-server"
}

The packages field for some definitions is left empty. Contributions to fill in the missing packages are welcome.

use _generator/run_generator.sh to gnerate the langserver.json

use _generator/test.sh <feature_name> to test the feature