Configuring Julia formatter and linter with nvim-lspconfig for neovim

Hello,

For Neovim, I have successfully integrated LanguageServer.jl through lspconfig as instructed here. Auto-completion and hover documentation worked.

screenshot

I want to integrate JuliaFormatter.jl and StaticLint.jl which are installed in the project located in ~/.julia/environment/nvim-lspconfig but I can’t figure how to do it.

nvim-lspconfig.lua
-- (1) install lsp, formatter, and linter with Mason
-- --

-- import lsp keymaps
local on_attach = require("config.keymaps_lspsaga").on_attach

-- import local UTF-8 icons
local diagnostic_signs = require("util.icons").diagnostic_signs

local config = function()
    require("neoconf").setup({})
    -- nvim-cmp package
    local capabilities = require('cmp_nvim_lsp').default_capabilities()

    -- lspconfig package
    local lspconfig = require("lspconfig")

    -- set diagnostic icons
    for type, icon in pairs(diagnostic_signs) do
        local hl = "DiagnosticSign" .. type
        vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" })
    end


    -- (2) LSP Setup
    -- -- --

    -- lua
    lspconfig.lua_ls.setup({
        -- attach nvim-cmp
        capabilities = capabilities,

        -- set lsp keymaps
        on_attach = on_attach,

        settings = {
            Lua = {
                -- make the language server recognize "vim" global
                diagnostics = {
                    globals = { "nvim" }, -- was vim
                },
                workspace = {
                    -- make language server aware of runtime files
                    library = {
                        [vim.fn.expand("$VIMRUNTIME/lua")] = true,
                        [vim.fn.stdpath("config") .. "/lua"] = true,
                    },
                },
            },
        },
    })

    -- python
    lspconfig.pyright.setup({
        -- attach nvim-cmp
        capabilities = capabilities,

        -- set lsp keymaps
        on_attach = on_attach,

        -- features
        settings = {
            pyright = {
                disableOrganizeImports = false,
                analysis = {
                    useLibraryCodeForTypes = true,
                    autoSearchPaths = true,
                    diagnosticMode = "workspace",
                    autoImportCompletions = true,
                },
            },
        },
    })

    -- haskell
    lspconfig.hls.setup({
        -- attach nvim-cmp
        capabilities = capabilities,

        -- set lsp keymaps
        on_attach = on_attach,

        -- settings for haskell
        settings = {
            haskell = {
                formattingProvider = "fourmolu", -- using fourmolu
            },
        },
    })

    -- julia
    -- uses project ~/.julia/environments/nvim-lspconfig
    -- requires only: Pkg add LanguageServer
    -- doc: https://github.com/neovim/nvim-lspconfig/blob/b972e7154bc94ab4ecdbb38c8edbccac36f83996/doc/server_configurations.md#julials
    -- auto-completion worked
    lspconfig.julials.setup({})

    -- (3) linter and formatter objects
    -- -- --

    -- lua
    local luacheck = require("efmls-configs.linters.luacheck") -- linter
    local stylua = require("efmls-configs.formatters.stylua") -- formatter

    -- python
    local flake8 = require("efmls-configs.linters.flake8") -- linter
    local black = require("efmls-configs.formatters.black") -- formatter

    -- haskell
    local hlint = { -- linter
        lintCommand = "hlint --stdin",
        lintStdin = true,
        lintFormats = {"%f:%l:%c: %m"},
    }
    local fourmolu = { -- formatter
        formatCommand = "fourmolu --stdin-input-file ${INPUT}",
        formatStdin = true,
    }

    -- (4) efm server
    -- -- --
    lspconfig.efm.setup({
        filetypes = {
            -- lua
            "lua",

            -- python
            "python",

            -- haskell
            "haskell",
        },
        init_options = {
            documentFormatting = true,
            documentRangeFormatting = true,
            hover = true,
            documentSymbol = true,
            codeAction = true,
            completion = true,
        },
        settings = {
            languages = {
                -- lua
                lua = { luacheck, stylua },

                -- python
                python = { flake8, black },

                -- haskell
                haskell = { hlint, fourmolu },
            },
        },
    })
end

return {
    "neovim/nvim-lspconfig",
    config = config,
    lazy = false,
    dependencies = {
        "windwp/nvim-autopairs",
        "williamboman/mason.nvim",
        "creativenull/efmls-configs-nvim",
    },
}
1 Like

You might want to check the wiki.

Thanks. I checked nvim-cmp and nvim-lspconfig section but it does not seem to contain JuliaFormatter.jl or StaticLint.jl

Do I need to use alternative lsp plugins?

No you dont. LanguageServer.jl comes with StaticLint and JuliaFormatter. There is already a format function from nvim-lspconfig. You really have to check out other ppl configs like mine. I binded mine to Space + L + F to format.

I am not sure what part of the documentation or wiki that are missing tbh. But nvim-lspconfig will use whatever formatter has from the Language Server implementation of the language if it does exist. Julia’s LanguageServer.jl uses JuliaFormatter.jl for example. You can see it in action here

I started to inspect and tinker with your configurations here.

For the first step of installation, I installed LanguageServer.jl and PackageCompiler.jl in nvim-lspconfig. Then I faced a weird error:

You have a rogue ' at the end of the line there.

You are right. Sorry for the bad question. I should be more careful.

After successfully compiling packages in @nvim-lspconfig, I couldn’t get Julia’s LSP running through your configurations. Even autocompletion does not work.

LspLog

LspInfo

There is a minimal configuration here which uses nvim-cmp and nvim-lspconfig but I don’t feel you would recommend it.

What would be the minimal configuration you do recommend to test?

tbh i am not sure how yours doesn’t work when some of my friends use my config… and i see that it really ran from the logs. the question is, how much did you tinker that caused that error like if you touched the custom command i made. if not, it might be something else.

and just showing logs without what youre typing doesn’t really give much info.

EDIT: i will try a clean install by wiping out the config cache of my nvim lsp and try installing.

Yep. it just works. Both project specific and global environment runs julia lsp just fine.

I also made sure that this works even on a container instance of julia e.g. distrobox on this line erudite.nvim/lua/lsp.lua at af692926e7cd8936f0acf25b59c0a4dd8dfaa83f - uncomfyhalomacro/erudite.nvim - Codeberg.org

And this is the variable script path being used

This ensures it points to my custom script.

There are possibilities why yours didn’t work.

  • You have conflicting configurations.
  • You tinkered the config but didn’t know what you were doing.
  • You forgot to install some prerequisites before bootstrapping the configuration, aka “running nvim the first time”.

If one or more of these are happening, I am pretty sure you just need to read more documentation and learn about the Neovim editor. Jumping over to someone’s config without Lua/Vimscript knowledge and just copy-pasting is going to end up you being frustrated.

Otherwise, just use VSCode. It’s a decent editor. No more fusses about learning the config language when it’s just JSON.

Thank you for your generous time.

I re-pulled your updated repo without any modifications. I got these two errors once I run nvim tem.jl:

First Error

Second Error

I did not install rust-analyzer, cargo, yarn, or tmux.

Now you are free to either:

  • Continue troubleshooting with me, or
  • Point me to resources related to foundations of neovim and language servers.

I shall flag the thread as solved if you selected the latter.

Thanks again.

There is one thing I noticed about this. Please install the pre-requisites. This is a personal config so much has to be done before doing anything.

One thing you must do are

  • delete any rust-specific plugins at lua/plugins.lua
  • delete the keymaps folder in lua folder.
  • delete whichkey.nvim at lua/plugins.lua.
  • you can leave lua/lsp.lua alone.
  • delete require("keymaps") at init.lua.

but if this is too difficult for you, i can provide a very minimal config with just lazy.nvim and nvim-lspconfig installed with just julia as the language server.

There are a lot of guides. You don’t need me. It’s something you need to make time to get used to or use existing configs from community like AstroNvim or LazyVim.

I have a smaller config just for you and feel free to read over it and copy over what’s necessary.

Smaller config here - uncomfyhalomacro/julia.nvim: An attempt to make a sane configuration for Julia x Neovim - ComfyForge

You are doing an incredible effort. Thank you so much.

For your new minimal configuration:

Build. I used build = "julia --project=@nvim-lspconfig --startup-file=no --history-file=no" and manually configured nvim-lspconfig project as instructed in your erudite repo. The original build line did not work with me.

lualine. I get this error from lualine

lualine

Removing lualine plugin caused error in the LSP, So I just ignored the error.

LSP & Auto-cmp. auto-completion and LSP successfully worked.

LSP & CMP


Lspsaga. I had to install Lspsaga plugin in order to see diagnostics.

Lspsaga

I still need to figure how to show diagnostics in-line rather than calling Lspsaga show_buf_diagnostics.

Resources. Spoon-feeding beyond this stage seems unhealthy. Would you recommend resources relevant to foundations of language-servers, and how neovim interacts with them?

Wiki. I suggest you minimize your configurations, removing keymaps, neo-tree, lualine, colourscheme, and global settings. Adding latex-cmp is reasonable. Then we send Julia’s wiki moderators to update Tools section. The goal is not to run your configuration on my machine, but paving the way for the community to use neovim, so that anyone can learn and configure by herself. I am happy to assist.

Let me know your thoughts before I flag this thread as solved.

Thank you again. You are a wonderful friend.

i think you have to exit neovim after the bootstrap and enter neovim again. that’s what is causing the error i believe

I mean it should be possible. I just added those just to give you a feel of what it’s like adding a theme and a colorscheme. users can just use the built-in Netrw with :Ntree :slight_smile: