aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshkan Kiani <ashkan.k.kiani@gmail.com>2019-11-14 17:14:53 -0800
committerGitHub <noreply@github.com>2019-11-14 17:14:53 -0800
commit0ccd248ef958a8d27e752952a880d004078b4ae9 (patch)
tree67f4afbe9bf69322c0481f00aaff171214487c05
parentAdd github actions for docgen (#7) (diff)
downloadnvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar.gz
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar.bz2
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar.lz
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar.xz
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.tar.zst
nvim-lspconfig-0ccd248ef958a8d27e752952a880d004078b4ae9.zip
Add ElmLS (#9)
- Initial add of elmLS support - Removes unnecessary vim.schedule_wrap fn calls in elmls & clangd impls - Add automatic installation for elmls and update docs. - Sort server output in the README. - Add commands for elmls for buffer and globally. - [bugfix] Skeleton could've tried to attach even if root_dir was nil TODO: check for updates and warn the user if there are updates when an elm server is started. Co-authored-by: Seth Messer <seth.messer@gmail.com>
-rw-r--r--README.md84
-rw-r--r--README_preamble.md2
-rw-r--r--lua/nvim_lsp.lua5
-rw-r--r--lua/nvim_lsp/clangd.lua5
-rw-r--r--lua/nvim_lsp/elmls.lua141
-rw-r--r--lua/nvim_lsp/skeleton.lua6
-rw-r--r--lua/nvim_lsp/util.lua10
-rw-r--r--scripts/docgen.lua7
8 files changed, 229 insertions, 31 deletions
diff --git a/README.md b/README.md
index eaf7b202..cf1ad21a 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ them are good references.
Implemented:
- [clangd](https://github.com/neovim/nvim-lsp#clangd)
+- [elmls](https://github.com/neovim/nvim-lsp#elmls)
- [gopls](https://github.com/neovim/nvim-lsp#gopls) (has some errors)
- [pyls](https://github.com/neovim/nvim-lsp#pyls)
- [texlab](https://github.com/neovim/nvim-lsp#texlab)
@@ -151,7 +152,6 @@ nvim_lsp.SERVER.setup({config})
```
# LSP Implementations
-
## clangd
https://clang.llvm.org/extra/clangd/Installation.html
@@ -159,7 +159,7 @@ https://clang.llvm.org/extra/clangd/Installation.html
clangd relies on a [JSON compilation database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) specified
as compile_commands.json or, for simpler projects, a compile_flags.txt.
-```
+```vim
nvim_lsp.clangd.setup({config})
nvim_lsp#setup("clangd", {config})
@@ -172,6 +172,65 @@ nvim_lsp#setup("clangd", {config})
root_dir = root_pattern("compile_commands.json", "compile_flags.txt", ".git")
settings = {}
```
+## elmls
+
+https://github.com/elm-tooling/elm-language-server#installation
+
+You can install elmls automatically to the path at
+ `stdpath("cache")/nvim_lsp/elmls`
+by using the function `nvim_lsp.elmls.install()` or the command `:ElmlsInstall`.
+
+This will only install if it can't find `elm-language-server` and if it hasn't
+been installed before by neovim.
+
+You can see installation info via `:ElmlsInstallInfo` or via
+`nvim_lsp.elmls.get_install_info()`. This will let you know if it is installed.
+
+If you don't want to use neovim to install it, then you can use:
+```sh
+npm install -g elm elm-test elm-format @elm-tooling/elm-language-server
+```
+
+```vim
+nvim_lsp.elmls.setup({config})
+nvim_lsp#setup("elmls", {config})
+
+ Commands:
+ - ElmlsInstall: Install elmls and its dependencies to stdpath("cache")/nvim_lsp/elmls
+ - ElmlsInstallInfo: Print installation info for `elmls`
+
+ Default Values:
+ capabilities = default capabilities, with offsetEncoding utf-8
+ cmd = { "elm-language-server" }
+ filetypes = { "elm" }
+ init_options = {
+ elmAnalyseTrigger = "change",
+ elmFormatPath = "elm-format",
+ elmPath = "elm",
+ elmTestPath = "elm-test"
+ }
+ log_level = 2
+ on_init = function to handle changing offsetEncoding
+ root_dir = root_pattern("elm.json")
+ settings = {}
+```
+## gopls
+
+https://github.com/golang/tools/tree/master/gopls
+
+Google's lsp server for golang.
+
+```vim
+nvim_lsp.gopls.setup({config})
+nvim_lsp#setup("gopls", {config})
+
+ Default Values:
+ cmd = { "gopls" }
+ filetypes = { "go" }
+ log_level = 2
+ root_dir = root_pattern("go.mod", ".git")
+ settings = {}
+```
## pyls
https://github.com/palantir/python-language-server
@@ -214,7 +273,7 @@ settings = {
};
```
-```
+```vim
nvim_lsp.pyls.setup({config})
nvim_lsp#setup("pyls", {config})
@@ -231,7 +290,7 @@ https://texlab.netlify.com/
A completion engine built from scratch for (la)tex.
-```
+```vim
nvim_lsp.texlab.setup({config})
nvim_lsp#setup("texlab", {config})
@@ -253,20 +312,3 @@ nvim_lsp#setup("texlab", {config})
}
}
```
-## gopls
-
-https://github.com/golang/tools/tree/master/gopls
-
-Google's lsp server for golang.
-
-```
-nvim_lsp.gopls.setup({config})
-nvim_lsp#setup("gopls", {config})
-
- Default Values:
- cmd = { "gopls" }
- filetypes = { "go" }
- log_level = 2
- root_dir = root_pattern("go.mod", ".git")
- settings = {}
-```
diff --git a/README_preamble.md b/README_preamble.md
index 365eb5ae..33c7dd55 100644
--- a/README_preamble.md
+++ b/README_preamble.md
@@ -32,6 +32,7 @@ them are good references.
Implemented:
- [clangd](https://github.com/neovim/nvim-lsp#clangd)
+- [elmls](https://github.com/neovim/nvim-lsp#elmls)
- [gopls](https://github.com/neovim/nvim-lsp#gopls) (has some errors)
- [pyls](https://github.com/neovim/nvim-lsp#pyls)
- [texlab](https://github.com/neovim/nvim-lsp#texlab)
@@ -151,4 +152,3 @@ nvim_lsp.SERVER.setup({config})
```
# LSP Implementations
-
diff --git a/lua/nvim_lsp.lua b/lua/nvim_lsp.lua
index a28bc4d5..4a6518f2 100644
--- a/lua/nvim_lsp.lua
+++ b/lua/nvim_lsp.lua
@@ -1,8 +1,9 @@
local skeleton = require 'nvim_lsp/skeleton'
-require 'nvim_lsp/gopls'
-require 'nvim_lsp/texlab'
require 'nvim_lsp/clangd'
+require 'nvim_lsp/elmls'
+require 'nvim_lsp/gopls'
require 'nvim_lsp/pyls'
+require 'nvim_lsp/texlab'
local M = {
util = require 'nvim_lsp/util';
diff --git a/lua/nvim_lsp/clangd.lua b/lua/nvim_lsp/clangd.lua
index b0d4ec25..8abe8ea2 100644
--- a/lua/nvim_lsp/clangd.lua
+++ b/lua/nvim_lsp/clangd.lua
@@ -13,11 +13,11 @@ skeleton.clangd = {
log_level = lsp.protocol.MessageType.Warning;
settings = {};
capabilities = default_capabilities;
- on_init = vim.schedule_wrap(function(client, result)
+ on_init = function(client, result)
if result.offsetEncoding then
client.offset_encoding = result.offsetEncoding
end
- end)
+ end
};
-- commands = {};
-- on_new_config = function(new_config) end;
@@ -37,4 +37,3 @@ as compile_commands.json or, for simpler projects, a compile_flags.txt.
};
}
-- vim:et ts=2 sw=2
-
diff --git a/lua/nvim_lsp/elmls.lua b/lua/nvim_lsp/elmls.lua
new file mode 100644
index 00000000..08a28c45
--- /dev/null
+++ b/lua/nvim_lsp/elmls.lua
@@ -0,0 +1,141 @@
+local skeleton = require 'nvim_lsp/skeleton'
+local util = require 'nvim_lsp/util'
+local lsp = vim.lsp
+local fn = vim.fn
+local api = vim.api
+local need_bins = util.need_bins
+
+local default_capabilities = lsp.protocol.make_client_capabilities()
+default_capabilities.offsetEncoding = {"utf-8", "utf-16"}
+
+local bin_name = "elm-language-server"
+
+local install_dir = util.path.join(fn.stdpath("cache"), "nvim_lsp", "elmls")
+local function get_install_info()
+ local bin_dir = util.path.join(install_dir, "node_modules", ".bin")
+ local bins = { bin_dir = bin_dir; install_dir = install_dir; }
+ bins.elmls = util.path.join(bin_dir, bin_name)
+ bins.elm = util.path.join(bin_dir, "elm")
+ bins.elm_format = util.path.join(bin_dir, "elm-format")
+ bins.elm_test = util.path.join(bin_dir, "elm-test")
+ bins.is_installed = need_bins(bins.elmls, bins.elm, bins.elm_format, bins.elm_test)
+ return bins
+end
+
+local global_commands = {
+ ElmlsInstall = {
+ function()
+ if get_install_info().is_installed then
+ return print("ElmLS is already installed")
+ end
+ skeleton.elmls.install()
+ end;
+ description = 'Install elmls and its dependencies to stdpath("cache")/nvim_lsp/elmls';
+ };
+ ElmlsInstallInfo = {
+ function()
+ local install_info = get_install_info()
+ if not install_info.is_installed then
+ return print("ElmLS is not installed")
+ end
+ print(vim.inspect(install_info))
+ end;
+ description = 'Print installation info for `elmls`';
+ };
+};
+
+util.create_module_commands("elmls", global_commands)
+
+local elm_root_pattern = util.root_pattern("elm.json")
+
+skeleton.elmls = {
+ default_config = {
+ cmd = {bin_name};
+ -- TODO(ashkan) if we comment this out, it will allow elmls to operate on elm.json. It seems like it could do that, but no other editor allows it right now.
+ filetypes = {"elm"};
+ root_dir = function(fname, bufnr)
+ local filetype = api.nvim_buf_get_option(0, 'filetype')
+ if filetype == 'elm' or (filetype == 'json' and fname:match("elm%.json$")) then
+ return elm_root_pattern(fname)
+ end
+ end;
+ log_level = lsp.protocol.MessageType.Warning;
+ settings = {};
+ init_options = {
+ elmPath = "elm",
+ elmFormatPath = "elm-format",
+ elmTestPath = "elm-test",
+ elmAnalyseTrigger = "change",
+ };
+ capabilities = default_capabilities;
+ on_init = function(client, result)
+ if result.offsetEncoding then
+ client.offset_encoding = result.offsetEncoding
+ end
+ end
+ };
+ commands = global_commands;
+ on_new_config = function(new_config)
+ local install_info = get_install_info()
+ if install_info.is_installed then
+ new_config.cmd = {install_info.elmls}
+ util.tbl_deep_extend(new_config.init_options, {
+ elmPath = install_info.elm;
+ elmFormatPath = install_info.elm_format;
+ elmTestPath = install_info.elm_test;
+ })
+ end
+ print(vim.inspect(new_config))
+ end;
+ docs = {
+ description = [[
+https://github.com/elm-tooling/elm-language-server#installation
+
+You can install elmls automatically to the path at
+ `stdpath("cache")/nvim_lsp/elmls`
+by using the function `nvim_lsp.elmls.install()` or the command `:ElmlsInstall`.
+
+This will only install if it can't find `elm-language-server` and if it hasn't
+been installed before by neovim.
+
+You can see installation info via `:ElmlsInstallInfo` or via
+`nvim_lsp.elmls.get_install_info()`. This will let you know if it is installed.
+
+If you don't want to use neovim to install it, then you can use:
+```sh
+npm install -g elm elm-test elm-format @elm-tooling/elm-language-server
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("elm.json")]];
+ on_init = [[function to handle changing offsetEncoding]];
+ capabilities = [[default capabilities, with offsetEncoding utf-8]];
+ };
+ };
+}
+
+function skeleton.elmls.install()
+ if not need_bins(bin_name) then return end
+ if not need_bins("sh", "npm", "mkdir", "cd") then
+ vim.api.nvim_err_writeln('Installation requires "sh", "npm", "mkdir", "cd"')
+ return
+ end
+ local install_info = get_install_info()
+ if install_info.is_installed then
+ return
+ end
+ local cmd = io.popen("sh", "w")
+ local install_script = ([[
+set -eo pipefail
+mkdir -p "{{install_dir}}"
+cd "{{install_dir}}"
+npm install elm elm-test elm-format @elm-tooling/elm-language-server
+]]):gsub("{{(%S+)}}", install_info)
+ print(install_script)
+ cmd:write(install_script)
+ cmd:close()
+end
+
+skeleton.elmls.get_install_info = get_install_info
+-- vim:et ts=2 sw=2
+
diff --git a/lua/nvim_lsp/skeleton.lua b/lua/nvim_lsp/skeleton.lua
index 9fa6f835..0d69fed0 100644
--- a/lua/nvim_lsp/skeleton.lua
+++ b/lua/nvim_lsp/skeleton.lua
@@ -130,9 +130,11 @@ function skeleton.__newindex(t, template_name, template)
function manager.try_add()
local root_dir = get_root_dir(api.nvim_buf_get_name(0), api.nvim_get_current_buf())
- print(api.nvim_get_current_buf(), root_dir)
+ if not root_dir then return end
local id = manager.add(root_dir)
- lsp.buf_attach_client(0, id)
+ if id then
+ lsp.buf_attach_client(0, id)
+ end
end
M.manager = manager
diff --git a/lua/nvim_lsp/util.lua b/lua/nvim_lsp/util.lua
index 190869e6..2b13d227 100644
--- a/lua/nvim_lsp/util.lua
+++ b/lua/nvim_lsp/util.lua
@@ -2,6 +2,7 @@ local validate = vim.validate
local api = vim.api
local lsp = vim.lsp
local uv = vim.loop
+local fn = vim.fn
local M = {}
@@ -89,6 +90,15 @@ function M.create_module_commands(module_name, commands)
end
end
+function M.need_bins(...)
+ for i = 1, select("#", ...) do
+ if 0 == fn.executable((select(i, ...))) then
+ return false
+ end
+ end
+ return true
+end
+
-- Some path utilities
M.path = (function()
local function exists(filename)
diff --git a/scripts/docgen.lua b/scripts/docgen.lua
index 3b02949e..036a5226 100644
--- a/scripts/docgen.lua
+++ b/scripts/docgen.lua
@@ -41,7 +41,10 @@ end
local writer = io.popen("cat README_preamble.md - > README.md", "w")
-for k, v in pairs(skeleton) do
+local skeleton_keys = vim.tbl_keys(skeleton)
+table.sort(skeleton_keys)
+for _, k in ipairs(skeleton_keys) do
+ local v = skeleton[k]
local tconf = v.template_config
local params = {}
@@ -94,7 +97,7 @@ for k, v in pairs(skeleton) do
## {{template_name}}
{{preamble}}
-```
+```vim
nvim_lsp.{{template_name}}.setup({config})
nvim_lsp#setup("{{template_name}}", {config})