Skip to content
Penelope Yong edited this page Dec 19, 2025 · 29 revisions

LanguageClient-neovim

Vim and Neovim are able to use the Julia LanguageServer via LanguageClient-neovim with completion from nvim-completion-manager.

The following is a basic minimal config (vimrc for Vim; init.vim for Neovim) using vim-plug:

call g:plug#begin()
  Plug 'JuliaEditorSupport/julia-vim'
  Plug 'autozimu/LanguageClient-neovim', {'branch': 'next', 'do': 'bash install.sh'}
  Plug 'roxma/nvim-completion-manager'  " optional
call g:plug#end()

" julia
let g:default_julia_version = '1.0'

" language server
let g:LanguageClient_autoStart = 1
let g:LanguageClient_serverCommands = {
\   'julia': ['julia', '--startup-file=no', '--history-file=no', '-e', '
\       using LanguageServer;
\       using Pkg;
\       import StaticLint;
\       import SymbolServer;
\       env_path = dirname(Pkg.Types.Context().env.project_file);
\       
\       server = LanguageServer.LanguageServerInstance(stdin, stdout, env_path, "");
\       server.runlinter = true;
\       run(server);
\   ']
\ }

nnoremap <silent> K :call LanguageClient_textDocument_hover()<CR>
nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>
nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>

Note:

  1. The LanguageServer, SymbolServer and StaticLint packages must be installed in Julia (1.x), i.e.

    julia> using Pkg
    julia> Pkg.add("LanguageServer")
    julia> Pkg.add("SymbolServer")
    julia> Pkg.add("StaticLint")
  2. If Julia (0.6 or greater) is not present in the PATH environment, either add the julia binary folder to PATH or directly reference the julia binary in g:LanguageClient_serverCommands, e.g. for macOS:

    let g:LanguageClient_serverCommands = {
    \   'julia': ['/Applications/Julia-0.6.app/Contents/Resources/julia/bin/julia', ...
  3. See vim-plug for more details on installing/managing packages in Vim/Neovim

SpaceVim

SpaceVim have a layer to use LanguageServer.jl, the setup is automatic once you installed the Julia layer.

Neovim Built-in LSP

vim.lsp - new API in Neovim 0.11+

If you are using Neovim v0.11+, the easiest way to set up LanguageServer.jl is to:

  1. Install the neovim/nvim-lspconfig plugin, using your plugin manager of choice. The package just needs to exist (i.e., be in Neovim's runtimepath); you don't need to load it with require('lspconfig'). When Neovim launches the LSP it will read the configs stored in the package (which you can also see here).

  2. Set up an environment for LanguageServer.jl by running

    julia --project=~/.julia/environments/nvim-lspconfig -e 'using Pkg; Pkg.add("LanguageServer"); Pkg.add("SymbolServer"); Pkg.add("StaticLint")'

    (Note that you can't choose a different directory for the environment, as this is where the default configuration will look.)

  3. Inside your init.lua file, add vim.lsp.enable('julials'). That's it!

Using Deoplete

Check out this thread on discourse: https://discourse.julialang.org/t/neovim-languageserver-jl/37286/7 OR this blog post. This provides examples of using neovim's built in language server protocol using deoplete with deoplete-lsp.

Using nvim-cmp and nvim-lspconfig (pre-Neovim 0.11)

The neovim/nvim-lspconfig tool is a built-in LSP tool for NeoVim, simply follow its documentation and the Julia LSP works. Note that installing the Julia LSP from Mason does not work out-of-the-box!

A minimal example here.

Another minimal example here:

-- using packer
-- ...

use({ 
  "hrsh7th/nvim-cmp",
  requires = { { "hrsh7th/cmp-nvim-lsp" } },
  config = function()
    cmp.setup({

      completion = {
        completeopt = "menu,menuone,noselect",
      },

      -- You must set mapping.
      mapping = {
        ["<C-p>"] = cmp.mapping.select_prev_item(),
        ["<C-n>"] = cmp.mapping.select_next_item(),
        ["<C-d>"] = cmp.mapping.scroll_docs(-4),
        ["<C-f>"] = cmp.mapping.scroll_docs(4),
        ["<C-Space>"] = cmp.mapping.complete(),
        ["<C-e>"] = cmp.mapping.close(),
      },

      -- You should specify your *installed* sources.
      sources = {
        { name = "nvim_lsp" },
      },
    })

  end,
})

use({
  "neovim/nvim-lspconfig",
  config = function()
    local function create_capabilities()
      local capabilities = vim.lsp.protocol.make_client_capabilities()
      capabilities.textDocument.completion.completionItem.snippetSupport = true
      capabilities.textDocument.completion.completionItem.preselectSupport = true
      capabilities.textDocument.completion.completionItem.tagSupport = { valueSet = { 1 } }
      capabilities.textDocument.completion.completionItem.deprecatedSupport = true
      capabilities.textDocument.completion.completionItem.insertReplaceSupport = true
      capabilities.textDocument.completion.completionItem.labelDetailsSupport = true
      capabilities.textDocument.completion.completionItem.commitCharactersSupport = true
      capabilities.textDocument.completion.completionItem.resolveSupport = {
        properties = { "documentation", "detail", "additionalTextEdits" },
      }
      capabilities.textDocument.completion.completionItem.documentationFormat = { "markdown" }
      capabilities.textDocument.codeAction = {
        dynamicRegistration = true,
        codeActionLiteralSupport = {
          codeActionKind = {
            valueSet = (function()
              local res = vim.tbl_values(vim.lsp.protocol.CodeActionKind)
              table.sort(res)
              return res
            end)(),
          },
        },
      }
      return capabilities
    end
    
    -- disable virtual text (recommended for julia)
    vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
      virtual_text = false,
      underline = false,
      signs = true,
      update_in_insert = false,
    })
    
    local on_attach = function(client, bufnr)
      vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")
    end
    
    local lspconfig = require("lspconfig")
    
    local function lsp_setup(name, config)
      lspconfig[name].setup(config)
    end
    
    lsp_setup("julials", {
      on_attach = on_attach,
      capabilities = create_capabilities(),
    })

  end,
})

-- ...

For a full example, see the following files:

Using completion-nvim (deprecated)

You can also see examples of using neovim, nvim-lsp, completion-nvim and diagnostic-nvim here:

https://github.com/kdheepak/dotfiles/blob/47a38e20ef4bef7a189927646eee3c91f911ffd7/vimrc

Here's the relevant pieces:

  1. Install the plugins
Plug 'nvim-lua/completion-nvim'                                    | " better neovim built in lsp completion
  1. Initialize
autocmd BufEnter * lua require'completion'.on_attach()

lua << EOF
    local nvim_lsp = require'nvim_lsp'
    local on_attach_vim = function()
        require'diagnostic'.on_attach()
    end
    nvim_lsp.julials.setup({on_attach=on_attach_vim})
EOF
  1. Configure
let g:diagnostic_auto_popup_while_jump = 0
let g:diagnostic_enable_virtual_text = 0
let g:diagnostic_enable_underline = 0
let g:completion_timer_cycle = 200 "default value is 80

Clone this wiki locally