PureScript setup with Neovim (LazyVim)

I recently gave neovim a try for PureScript development. I tried using LazyVim (GitHub - LazyVim/LazyVim: Neovim config for the lazy) after seeing a video on it (Zero to IDE with LazyVim - YouTube).

I am happy to report that it was quick and painless. It also seems to have great defaults - I am not a fan of endless config tweaking. This might just be the IDE that tears me away from Spacemacs.

Here’s my config in hopes that it helps others looking for a vim configuration for PureScript development -

  1. Install LazyVim -

    git clone https://github.com/LazyVim/starter ~/.config/nvim

  2. Create a file ~/.config/nvim/lua/plugins/purescript.lua with the following contents -

    EDIT: Tweaked the config a little to get jumping within libraries working. See PureScript & Spago · Issue #1736 · neovim/nvim-lspconfig · GitHub for more information.

    EDIT 2: Added purs-tidy configuration for automatic formatting.

return {
  -- Syntax highlighting
  { "purescript-contrib/purescript-vim" },

  -- LspConfig
  {
    "neovim/nvim-lspconfig",

    ---@class PluginLspOpts
    opts = {

      ---@type lspconfig.options
      servers = {
        -- purescriptls will be automatically installed with mason and loaded with lspconfig
        purescriptls = {
          settings = {
            purescript = {
              formatter = "purs-tidy",
            },
          },
      },
      setup = {
        purescriptls = function(_, opts)
          opts.root_dir = function(path)
            local util = require("lspconfig.util")
            if path:match("/.spago/") then
              return nil
            end
            return util.root_pattern("bower.json", "psc-package.json", "spago.dhall", "flake.nix", "shell.nix")(path)
          end
        end,
      },
    },
  },
}

That’s it!

LazyVim comes with “which-key” which helps with discovering the key bindings You can also search keybindings with SPC s k.

Some useful key shortcuts I use which cover most of my usecases -

Code navigation
SPC e - Project browser sidebar
SPC x x - Jumplist for errors in current document
SPC x X - Jumplist for errors in current project
SPC c a - Code actions (including automatic imports)
g d - Go to definition of identifier under cursor
K - Show help / type definition for identifier under cursor
SPC f t - Launch the inbuilt terminal in the current project dir

IDE navigation
SPC | - Split vertically
SPC \ - Split horizontally
Ctrl + hjkl - Navigate across splits
Ctrl + Arrow keys - Resize splits
SPC f b - Buffer jumplist
[ b - Prev buffer
] b - Next buffer

2 Likes

Some action shots -

Thanks for sharing :heart:

Probably OT but I hope you don’t mind my questions: Why do you want to depart with Spacemacs and where do you see the pro/cons of Neovim over it or VS code?

There are pros and cons with all of them.

  1. VSCode is pretty painless to get started with, but it doesn’t work in the terminal, the keybindings are terrible, it’s hard to configure (if it fails to work you are stuck), and it isn’t vim. You also feel the difference in speed, for example, I use vim macros heavily and they can get very slow and very buggy on vscode. The git integration (git lens) is not free.

  2. Spacemacs continues to work well and its vi mode (evil) is great and snappy. Magit and org-mode are great! But the PureScript layer could use some more love. As an example, it was recently switched to lsp and that doesn’t work as smoothly anymore. The biggest irritant for me was that the sideline messages keep wrapping, messing up the layout. I eventually had to disable many lsp areas. If I disable lsp altogether and switch back to psc-ide it works well, but lsp is where all IDEs are going so it makes sense to move to that.

  3. Neovim / Lazyvim is vim and works just even better than spacemacs out of the box. Lazy git also seems pretty great. However, the PureScript lsp server is not quite as full featured. You can’t rename variables , and you don’t get type signatures or jump to definition from within library code (you can jump from user code to library code, but you can’t then jump to definition again from within the library code). EDIT: jump to definition works now with a slightly tweaked config. I have updated my config above to reflect that fact.

1 Like

Thank you for your detailed answer.

I’m more or less in a similar situation - I use VS code with the VI(M) extension which is ok but there are quite a few little things the bindings get wrong.

Nice, thanks for sharing. Do you know of a way to also make it format on save? I’ve spent 2 evening trying to get it, to no avail.

Adding this stanza to the purescriptls config worked for me. You need to have purs-tidy installed globally -

settings = {
  purescript = {
    formatter = "purs-tidy",
  },
},

I have updated the config example at the top of the thread to include this!

2 Likes

Awesome! Thanks a lot :grinning:

Long time neovim user. I have built my config by hand.

One thing I haven’t figured out is why lspconfig will only take the first error reported by purescript ls, this isn’t the case with any of my other lsps.

I also can’t get goto definitions working, but this maybe be due to using flakes (nix).

Other than that, I’ve found deving purescript in my neovim pretty awesome!

Is it possibly something specific to your config?

I do see multiple errors -

possibly, but I don’t have this issue with any other LSP. I’m using lspconfig. I’ll have to look to see if there is anything specific in my case, but I haven’t had a second to check.