Skip to content

Latest commit

 

History

History
170 lines (135 loc) · 7.42 KB

README.org

File metadata and controls

170 lines (135 loc) · 7.42 KB

Emacs with LSP in Devcontainer

This is a doom emacs configuration of how to use emacs with language server in devcontainer.

status of devcontainer support

Currently I’m the main contributor of lsp-bridge’s devcontainer support. Here I trace the features that I’d like to add, and what I’ve done for Emacs to work with devcontainer.

statusscope
DONEdevcontainer-featureable to install lsp-bridge
DONEdevcontainer-featureable to install any language server that lsp-bridge supports [1]
DONEdevcontainer-featuredaily auto update latest version of lsp-bridge and release
DONElsp-bridgeopen container file using find-file /docker:
DONElsp-bridgeenable auto-completion
DONElsp-bridgesave file by lsp-bridge-remote-save-buffer
DONElsp-bridgeformat buffer using apheleia
DONElsp-bridgejump to definition and jump back
DONEdoom-emacsripgrep search in container
DONEdoom-emacsopen vTerm with bash in container
DONEdevcontainer-featureinstructions of how to setup with Python projects
TBDdevcontainermanage container in Emacs with CLI2ELI
TBDdevcontainerget rid of VSCode [2]
TBDlsp-bridgeauto re-connect to the new container and re-open file if devcontainer has been rebuilt
  • [1] Consider it’s done, while a few language servers are missing at Nixpkgs or require special setting, also language server which runs on Windows is not supported
  • [2] Currently VSCode is needed as port forward is not implemented by devcontainer CLI. POC at devcontainer-cli-port-forwarder

Remote Editing Configuration

TRAMP

  • Use M-x tramp-cleanup-all-connections to remove all cached connection history.
  • Use M-x tramp-cleanup-all-buffers to close all remote buffers.

install additional tools

To install additional tools like ripgrep in a devcontainer, you can use the features/nix.

Add this to your devcontainer.json,

{
  "features": {
    "ghcr.io/devcontainers/features/nix:1": {
       "packages": "ripgrep"
    }
  }
}

use nix to install tools that you want to use in the container.

tramp-remote-path

Ensure that ~/.nix-profile/bin is included in the PATH when executing remote commands.

(after! tramp
  (add-to-list 'tramp-remote-path "~/.nix-profile/bin")
  (add-to-list 'tramp-remote-path 'tramp-own-remote-path))

this will make search tools such as ripgrep.el and projectile-ripgrep works with remote files.

lsp-bridge

(when (package! lsp-bridge
        :recipe (:host github
                 :repo "manateelazycat/lsp-bridge"
                 :branch "master"
                 :files ("*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources")
                 :build (:not compile)))
  ;; doom-emacs has mardown-mode
  ;; (package! markdown-mode)
  (package! yasnippet)
  (package! topsy)
  (package! flymake-bridge
    :recipe (:host github :repo "liuyinz/flymake-bridge" :branch "master")))
(use-package! lsp-bridge
  :config

  ;; for muscle memory to save buffer
  (defun my/save-buffer ()
    (interactive)
    (if lsp-bridge-remote-file-flag
        (call-interactively #'lsp-bridge-remote-save-buffer)
      (call-interactively #'save-buffer)))

  (map! "C-x C-s" #'my/save-buffer))

(use-package! flymake-bridge
  :after lsp-bridge
  :hook (lsp-bridge-mode . flymake-bridge-setup))

(map! :after flymake
      "M-n" #'flymake-goto-next-error
      "M-p" #'flymake-goto-prev-error)

formatter support

Enable format feature in init.el, it will install the apheleia package.

use SPC c f to format the buffer.

(use-package! apheleia
  :after lsp-bridge
  :config
  ;; don't mess up with lsp-mode
  (setq +format-with-lsp nil)
  (setq apheleia-remote-algorithm 'remote))

remote file indicator

Add a sticky header to indicate editing remote file

(use-package! topsy
  :after lsp-bridge
  :config
  ;; display a bar to remind editing remote file
  (setcdr (assoc nil topsy-mode-functions)
          (lambda ()
            (when (lsp-bridge-is-remote-file) "[LBR] REMOTE FILE")))

  ;; do not activate when the current major mode is org-mode
  (add-hook 'lsp-bridge-mode-hook (lambda ()
                                    (unless (derived-mode-p 'org-mode)
                                      (topsy-mode 1)))))

vTerm

Enable vterm feature in init.el

use /bin/bash for vterm when editing container file, use SPC o t to open vTerm buffer

(after! vterm
  (defun my/set-vterm-shell ()
    (when (string-prefix-p "/docker:" (file-remote-p default-directory))
      (when (eq major-mode 'vterm-mode)
        (let ((shell (if (string-prefix-p "/docker:" (file-remote-p default-directory))
                         "/bin/bash"
                       (or (getenv "SHELL") "/bin/bash"))))
          (vterm-send-string (format "exec %s\n" shell))
          (vterm-send-string "clear\n")))))

  (add-hook 'vterm-mode-hook #'my/set-vterm-shell))

how to setup language server for python project (using basedpyright)

It should be clearly stated to avoid any confusing that lsp-bridge itself runs in a python process, and basedpyright-langserver uses another python process.

Normally you created a virtual environment using tools like uv or pdm at the root directory, suppose the name of the virtual environment is “.venv”.

You need to add a section to the pyproject.toml, and basedpyright will inspect the virtual environment correctly, more details.

[tool.basedpyright]
venvPath = "."
venv = ".venv"