# Neovim + LanguageServer.jl

**URL:** <https://discourse.julialang.org/t/neovim-languageserver-jl/37286>\
**Category:** Tooling\
**Tags:** editors\
**Created:** [April 9, 2020, 4:13pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286 "2020-04-09T16:13:25Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![DoktorMike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doktormike/32/2736_2.png) [@DoktorMike](https://discourse.julialang.org/u/DoktorMike)\
**Post date:** [July 2, 2021, 7:50pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/41 "2021-07-02T19:50:46Z")

</div>

Your comment made me think about why it fails for me as I’m setting the server path in the local config. I found the problem which is happening because I insist on printing out bayes formula when I start julia. The PR for fixing `julials` config in nvim-lspconfig is here: [Fixed a small gotcha where the server\_path is set to nonsense if you print stuff in your startup.jl by DoktorMike · Pull Request #1017 · neovim/nvim-lspconfig · GitHub](https://github.com/neovim/nvim-lspconfig/pull/1017)

---

<div class="post-metadata">

**Author:** ![instrnts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/instrnts/32/19224_2.png) [@instrnts](https://discourse.julialang.org/u/instrnts)\
**Post date:** [July 9, 2021, 2:05am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/42 "2021-07-09T02:05:34Z")

</div>

What about [GitHub - hrsh7th/nvim-compe: Auto completion Lua plugin for nvim](https://github.com/hrsh7th/nvim-compe) ?  
Does this do autocomplete for Julia?

I’m trying to figure out if I should go with lspconfig or coc; do you have any comments on the pros and cons?

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [July 9, 2021, 2:22am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/43 "2021-07-09T02:22:45Z")

</div>

My current setup is using nvim-compe + built in lsp for neovim. I like this set up for other languages. For Julia, I have disabled lsp because it hangs for me on some projects and I haven’t had time to debug it. On small files and small projects though, things seem to work well with this set up. It was quite a bit of configuration (nvim-compe + lspsaga + lspconfig + other plugins) though.

I’m guessing coc is more straightforward, but I haven’t used it extensively and not tried it in a long time. So I’m not sure what the advantages or the differences are exactly. If others have thoughts, feel free to chime in.

---

<div class="post-metadata">

**Author:** ![jvaverka](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jvaverka/32/19892_2.png) [@jvaverka](https://discourse.julialang.org/u/jvaverka)\
**Post date:** [July 13, 2021, 3:43pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/44 "2021-07-13T15:43:23Z")

</div>

Hi all,  
Looking for a little help. `:LspInstall julials` results in “[Could not find language server for julials](https://github.com/kabouzeid/nvim-lspinstall/blob/main/lua/lspinstall.lua#L10)”

I have included the following snippet  
`require'lspconfig'.julials.setup{}`  
in my init.lua

Somehow lspinstall isn’t aware of the lspconfig [julials](https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/julials.lua) server config. Anyone come across this before?

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 13, 2021, 4:34pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/45 "2021-07-13T16:34:43Z")

</div>

From the listed servers in [nvim-lspinstall/lua/lspinstall/servers at main · kabouzeid/nvim-lspinstall · GitHub](https://github.com/kabouzeid/nvim-lspinstall/tree/main/lua/lspinstall/servers) `nvim-lspinstall` doesn’t look to have one for `julials`.

(The recommended install method in [https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/julials.lua#L44](https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/julials.lua#L44) works well though.)

---

<div class="post-metadata">

**Author:** ![jvaverka](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jvaverka/32/19892_2.png) [@jvaverka](https://discourse.julialang.org/u/jvaverka)\
**Post date:** [July 13, 2021, 5:52pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/46 "2021-07-13T17:52:22Z")

</div>

Okay, great! I had already stumbled onto this file, but wasn’t sure how to implement.

The line you referenced will install LanguageServer.jl & SymbolServer.jl but that alone will not allow me to do something like `:LspInstall julials`.

I even tried taking the entire config from `nvim-lspconfig/julials.lua` and integrating with my config but there is still no language server attaching to the buffer and no change when trying to `LspInstall`.

How does Neovim know that there is a `julials` option that should then kick off the command to start the LanguageServer.jl?

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 13, 2021, 6:13pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/47 "2021-07-13T18:13:12Z")

</div>

> [@jvaverka](#):
>
> I even tried taking the entire config from `nvim-lspconfig/julials.lua` and integrating with my config but there is still no language server attaching to the buffer and no change when trying to `LspInstall` .

Could be worth doing a `:checkhealth` if you’ve not already to see whether there’s anything obvious that’s causing it. Do any other language servers work in your setup?

I struggled with the default settings for a while before just customising it enough to work for me with (the relevant parts):

```lua
local util = require "lspconfig/util"

local cmd = {
  "julia",
  "--startup-file=no",
  "--history-file=no",
  "/home/mike/.config/nvim/lua/mike/lsp.jl"
}

require"lspconfig".julials.setup {
    cmd = cmd,
    on_new_config = function(new_config, _)
        local server_path = vim.fn.system "julia --startup-file=no -q -e 'print(dirname(dirname(Base.find_package(\"LanguageServer\"))))'"
        local new_cmd = vim.deepcopy(cmd)
        table.insert(new_cmd, 2, "--project=" .. server_path)
        new_config.cmd = new_cmd
    end,
    filetypes = {"julia"},
    root_dir = function(fname)
        return util.find_git_ancestor(fname) or vim.fn.getcwd()
    end
}

```

and `lsp.jl` (since I didn’t like passing it all as an argument):

```julia
using LanguageServer
using LanguageServer.SymbolServer

let env = Base.load_path(),
    dir = pwd(),
    depot_path = get(ENV, "JULIA_DEPOT_PATH", ""),
    project_path = dirname(something(Base.current_project(pwd()), Base.load_path_expand(LOAD_PATH[2])))

    @info env dir project_path depot_path

    server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path)
    server.runlinter = true
    run(server)
end

```

(Hopefully that might help you out a bit.)

---

<div class="post-metadata">

**Author:** ![jvaverka](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jvaverka/32/19892_2.png) [@jvaverka](https://discourse.julialang.org/u/jvaverka)\
**Post date:** [July 13, 2021, 7:14pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/48 "2021-07-13T19:14:03Z")

</div>

Helped me out **A TON**!

 ![Screenshot from 2021-07-13 15-06-21](https://global.discourse-cdn.com/julialang/original/3X/7/1/71bff39c09ccd58e663b877b830cea9184e159c4.png)

Thank you! I had many of the parts, but couldn’t find the glue!

One more question - Not really sure if this is a LanguageServer.jl or a Neovim-LspConfig issue, but could any of this be shared upstream in order to get things working “_out of the box_” for others?

PS - You were right to ask about `:checkhealth` because that was my first thought, but didn’t find anything seriously broken.

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 13, 2021, 7:29pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/49 "2021-07-13T19:29:33Z")

</div>

Glad it’s working now.

> [@jvaverka](#):
>
> One more question - Not really sure if this is a LanguageServer.jl or a Neovim-LspConfig issue, but could any of this be shared upstream in order to get things working “ _out of the box_ ” for others?

Yes, things _should_ be made to just work with the defaults. I hadn’t spent the time to workout whether it was just my config that was causing issues so haven’t reported anything upstream yet.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [July 13, 2021, 10:25pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/50 "2021-07-13T22:25:10Z")

</div>

Thanks for sharing that configuration @mike. I used that to try out LanguageServer for the first time just now. I made some modifications to your setup that I believe are strict improvements (borderline bugfixes?).

`init.vim`:

```nohighlight
lua << EOF
local cmd = {
    "julia",
    "--startup-file=no",
    "--history-file=no",
    "/home/fredrik/.config/nvim/lsp-julia/run.jl"
}
require'lspconfig'.julials.setup{
    cmd = cmd,
    -- Why do I need this? Shouldn't it be enough to override cmd on the line above?
    on_new_config = function(new_config, _)
        new_config.cmd = cmd
    end,
    filetypes = {"julia"},
}
EOF

```

And in `/home/fredrik/.config/nvim/lsp-julia/` I have

```julia
$ tree ~/.config/nvim/lsp-julia/
/home/fredrik/.config/nvim/lsp-julia/
├── Manifest.toml
├── Project.toml
└── run.jl

```

where `~/.config/nvim/lsp-julia/Project.toml` contains the LS deps

```nohighlight
[deps]
LanguageServer = "2b0e0bc5-e4fd-59b4-8912-456d1b03d8d7"
SymbolServer = "cf896787-08d5-524d-9de7-132aaa0cb996"

```

and `~/.config/nvim/lsp-julia/run.jl` is

```julia
# Load LanguageServer from the project next to this file
## Save old load path
old_load_path = copy(LOAD_PATH)
push!(empty!(LOAD_PATH), @ __DIR__ )
## Load packages
using LanguageServer, SymbolServer
## Restore old load path
append!(empty!(LOAD_PATH), old_load_path)

# Figure out the active project
## This works if you are *not* using a Pkg.activate based workflow
## e.g. if you set up LOAD_PATH manually or set JULIA_PROJECT=@. in
## .bashrc or equivalent
project_path = Base.active_project()
## This works if you are using a Pkg.activated based workflow
# project_path = something(Base.current_project(pwd()), Base.active_project())

# Depot path for the server to index
depot_path = get(ENV, "JULIA_DEPOT_PATH", "")

# Start the server
@info "Running julia language server" project_path depot_path
server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path)
server.runlinter = true
run(server)

```

The major improvements compared to your version is that (i) `LanguageServer` is running in a proper environment defined by the `Project.toml` and `Manifest.toml` in `~/.config/nvim/lsp-julia/Project.toml` and (ii) it is independent of the environment (e.g. `JULIA_LOAD_PATH`).

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 14, 2021, 7:16am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/52 "2021-07-14T07:16:48Z")

</div>

Nice, thanks @fredrikekre. That does look like it should improve things.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [July 14, 2021, 7:22am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/53 "2021-07-14T07:22:58Z")

</div>

Most things seems to work for me, but I get

```julia
import JSON ■ Missing reference: JSON

```

for all package importsl. I verified from the logs that the server is running in the correct project where `JSON` is installed. Am I missing something?

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 14, 2021, 8:12am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/54 "2021-07-14T08:12:00Z")

</div>

> [@fredrikekre](#):
>
> for all package importsl. I verified from the logs that the server is running in the correct project where `JSON` is installed. Am I missing something?

Yeah, it’s not getting the right imports for me either with those changes. Not 100% sure what needs adjusted though.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [July 14, 2021, 8:14am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/55 "2021-07-14T08:14:16Z")

</div>

Are you saying it works with your configuration from [Neovim + LanguageServer.jl - #47 by mike](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/47) ?

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 14, 2021, 8:16am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/56 "2021-07-14T08:16:54Z")

</div>

Yup, my current config picks them all up fine.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [July 14, 2021, 5:23pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/57 "2021-07-14T17:23:50Z")

</div>

Okay, strange. I get the same errors with your setup.

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [July 15, 2021, 8:03pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/58 "2021-07-15T20:03:17Z")

</div>

Here’s the diff in my dotfiles that’s working for me:

> <https://github.com/kdheepak/dotfiles/commit/1be17f21e84e1eded41f4f0b3a31e002f23e9925>

I think the `project_path` in the set up by @mike is not matching the one in the built in lsp. The diff I’ve shared above uses the same set up (from @fredrikekre’s repo) and changes the `project_path` to match the one in the built in LSP.

There’s also some changes I made to make the diff portable (i.e. using `vim.fn.expand` to expand the home directory) and an example of how to get detailed LSP log messages (`vim.lsp.set_log_level('trace')`).

I’m sharing here in case others are interested in trying it out. Once we figure out exactly what is going on we can update the nvim-lspconfig to do the right thing.

 ![Screen Shot 2021-07-15 at 2.04.53 PM](https://global.discourse-cdn.com/julialang/original/3X/2/0/204e8ade879d3e6de1fe7798c324e4546301c2f6.png)

Here’s a link to the repo I’m using for this test:

> <https://github.com/kdheepak/julia-lsp-test/blob/main/src/julia_lsp_test.jl>

It’s very simple with just a couple of dependencies:

```julia
   6 │ [deps]
   7 │ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
   8 │ JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
───────┴──────────────────────────────────────────────────────────────────────────

```

---

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike/32/39_2.png) [@mike](https://discourse.julialang.org/u/mike)\
**Post date:** [July 16, 2021, 6:26am UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/59 "2021-07-16T06:26:44Z")

</div>

Thanks @kdheepak, that config works nicely.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [July 16, 2021, 1:14pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/60 "2021-07-16T13:14:37Z")

</div>

I found the problems:

- I was using Julia 1.6.2 which SymbolServer didn’t like ([julia-vscode/SymbolServer.jl#224](https://github.com/julia-vscode/SymbolServer.jl/issues/224)).
- I was passing the path to the `Project.toml` file, which SymbolServer didn’t like since it unconditionally appended `Project.toml` to the path and thus looked for things in `.../Project.toml/Project.toml` ([julia-vscode/SymbolServer.jl#227](https://github.com/julia-vscode/SymbolServer.jl/pull/227)).

* * *

Here is my new configuration: [fredrikekre/.dotfiles](https://github.com/fredrikekre/.dotfiles). Relevant extract:

`init.vim`:

```nohighlight
lua << EOF
local cmd = {
    "julia",
    "--startup-file=no",
    "--history-file=no",
    vim.fn.expand("~/.config/nvim/lsp-julia/run.jl")
}
require'lspconfig'.julials.setup{
    cmd = cmd,
    -- Why do I need this? Shouldn't it be enough to override cmd on the line above?
    on_new_config = function(new_config, _)
        new_config.cmd = cmd
    end,
    filetypes = {"julia"},
}
-- vim.lsp.set_log_level("debug")
EOF

```

`~/.config/nvim/lsp-julia/run.jl`:

```julia
# Load LanguageServer from the project next to this file
## Save old load path
old_load_path = copy(LOAD_PATH)
push!(empty!(LOAD_PATH), @ __DIR__ )
## Load packages
using LanguageServer, SymbolServer
## Restore old load path
append!(empty!(LOAD_PATH), old_load_path)

# Figure out the active project
## This configuration is a good default
project_path = let
    dirname(something(
        ## 1. Finds an explicitly set project (JULIA_PROJECT)
        Base.load_path_expand((
            p = get(ENV, "JULIA_PROJECT", nothing);
            p === nothing ? nothing : isempty(p) ? nothing : p
        )),
        ## 2. Look for a Project.toml file in the current working directory,
        ## or parent directories, with $HOME as an upper boundary
        Base.current_project(),
        ## 3. First entry in the load path
        get(Base.load_path(), 1, nothing),
        ## 4. Fallback to default global environment,
        ## this is more or less unreachable
        Base.load_path_expand("@v#.#"),
    ))
end

# Depot path for the server to index (empty uses default).
depot_path = get(ENV, "JULIA_DEPOT_PATH", "")

# Start the server
@info "Running julia language server" VERSION project_path depot_path
server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path)
server.runlinter = true
run(server)

```

---

<div class="post-metadata">

**Author:** ![jvaverka](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jvaverka/32/19892_2.png) [@jvaverka](https://discourse.julialang.org/u/jvaverka)\
**Post date:** [July 16, 2021, 2:35pm UTC](https://discourse.julialang.org/t/neovim-languageserver-jl/37286/61 "2021-07-16T14:35:12Z")

</div>

This is working perfectly for me! ☝

[Previous page](https://discourse.julialang.org/t/neovim-languageserver-jl/37286.md?page=2)

[Next page](https://discourse.julialang.org/t/neovim-languageserver-jl/37286.md?page=4)
