Nix + HLS + VS Code / Emacs

Is there any easy(ish) way to setup HLS with VS Code or Emacs with Nix (for Haskell libs)?

I use Mac and NixOS.

My cursory Googling didn’t look promising, but maybe I missed something obvious : )

2 Likes

you should use .envrc to get the nix shell automatically to start and pull in the right hls version + right ghc version.
then configure your editor to use that shell.

1 Like

Emacs or VS Code may use the HLS/GHC from your env PATH, so if you start nix-shell/nix develop before your IDE, that should work out of the box.

As an example, in this project, you may run nix develop --command emacs, and then M-x eglot.

Here is a setting to make emacs runs HLS through nix (so that you can start emacs without having to enter a nix shell first):

(defun start-hls (_mode)
  "Start HLS by trying to wrap in nix develop"
  (cd (projectile-project-root))
  (cond ((file-exists-p "flake.nix")
         (progn
           (message "Running HLS with flake")
           (list "nix" "develop" "--command" "haskell-language-server-wrapper" "--lsp")
           ))
        ;; ((file-exists-p "shell.nix")
        ;;  (progn
        ;;    (message "TODO: handle shell.nix")))
        (t (progn
             (message "Running HLS from host")
             (list "haskell-language-server-wrapper" "--lsp")))
        ))

(require 'eglot)
(add-to-list 'eglot-server-programs
             '(haskell-mode . start-hls))

Also you might want to check HLS before the ide using haskell-language-server-wrapper typecheck.

2 Likes

We have nix/hls in GitHub - input-output-hk/devx: Slightly opinionated shared GitHub Action for Cardano-Haskell projects ; as well as direnv, GitHub actions (including cross compilation) and devcontainer integrations (vscode, gh code spaces, …) on-top of that.

Using this .envrc

# https://github.com/nix-community/nix-direnv A fast, persistent use_nix/use_flake implementation for direnv:
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
  source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
fi
# https://github.com/input-output-hk/devx Slightly opinionated shared GitHub Action for Cardano-Haskell projects 
use flake "github:input-output-hk/devx#ghc8107-iog"

Should work in any direnv/hls capable editor (vscode, emacs, …). Some might need to reload after the initial dev shell initialization due to plug-in interactions. HLS should be found in the direnv provided PATH.

Launching the editor from a direnv enabled shell session should also work.

2 Likes

My template works out of the box with VS Code, both on macOS and NixOS:

If you want a minimal version of this template, try the haskell-flake example template but with .envrc/.vscode copied over from haskell-template: Getting Started | Zero to Flakes

3 Likes

And to setup direnv (highly recommended if you use Nix + VSCode), see

1 Like

Yeah, it is easy. Just install haskell-language-server, vscode and activate the Haskell extension in vscode. For more details you can read the haskell-language-server section in the Nixpkgs manual.

1 Like

Unsure whether optimal, but a few characters (pkgs.haskell-language-server) was all the difference:

with import <nixpkgs>{};

mkShell {
 buildInputs = [ pkgs.haskell-language-server
 	     (pkgs.haskellPackages.ghcWithPackages
	     (hsPkgs: with hsPkgs; [ad normaldistribution lens random-fu]))
	];
   }

then on the command line, in the relevant folder containing your code and default.nix file:

$ nix-shell
nix-shell $ code .
2 Likes