aboutsummaryrefslogtreecommitdiffstats
path: root/lua/lspconfig
diff options
context:
space:
mode:
Diffstat (limited to 'lua/lspconfig')
-rwxr-xr-xlua/lspconfig/als.lua104
-rw-r--r--lua/lspconfig/angularls.lua72
-rw-r--r--lua/lspconfig/bashls.lua44
-rw-r--r--lua/lspconfig/ccls.lua24
-rw-r--r--lua/lspconfig/clangd.lua60
-rw-r--r--lua/lspconfig/clojure_lsp.lua22
-rwxr-xr-xlua/lspconfig/cmake.lua25
-rw-r--r--lua/lspconfig/codeqlls.lua52
-rw-r--r--lua/lspconfig/configs.lua214
-rw-r--r--lua/lspconfig/cssls.lua56
-rw-r--r--lua/lspconfig/dartls.lua55
-rw-r--r--lua/lspconfig/diagnosticls.lua45
-rw-r--r--lua/lspconfig/dockerls.lua47
-rw-r--r--lua/lspconfig/efm.lua25
-rw-r--r--lua/lspconfig/elixirls.lua110
-rw-r--r--lua/lspconfig/elmls.lua72
-rw-r--r--lua/lspconfig/flow.lua30
-rw-r--r--lua/lspconfig/fortls.lua25
-rw-r--r--lua/lspconfig/gdscript.lua22
-rw-r--r--lua/lspconfig/ghcide.lua24
-rw-r--r--lua/lspconfig/gopls.lua23
-rw-r--r--lua/lspconfig/health.lua26
-rw-r--r--lua/lspconfig/hie.lua38
-rw-r--r--lua/lspconfig/hls.lua24
-rw-r--r--lua/lspconfig/html.lua54
-rw-r--r--lua/lspconfig/intelephense.lua68
-rw-r--r--lua/lspconfig/jdtls.lua138
-rw-r--r--lua/lspconfig/jedi_language_server.lua22
-rw-r--r--lua/lspconfig/jsonls.lua51
-rw-r--r--lua/lspconfig/julials.lua66
-rw-r--r--lua/lspconfig/kotlin_language_server.lua52
-rw-r--r--lua/lspconfig/leanls.lua22
-rw-r--r--lua/lspconfig/metals.lua106
-rw-r--r--lua/lspconfig/nimls.lua45
-rw-r--r--lua/lspconfig/ocamlls.lua45
-rw-r--r--lua/lspconfig/ocamllsp.lua26
-rw-r--r--lua/lspconfig/omnisharp.lua84
-rw-r--r--lua/lspconfig/purescriptls.lua46
-rw-r--r--lua/lspconfig/pyls.lua23
-rw-r--r--lua/lspconfig/pyls_ms.lua153
-rw-r--r--lua/lspconfig/r_language_server.lua30
-rw-r--r--lua/lspconfig/rls.lua31
-rw-r--r--lua/lspconfig/rnix.lua81
-rw-r--r--lua/lspconfig/rome.lua37
-rw-r--r--lua/lspconfig/rust_analyzer.lua27
-rw-r--r--lua/lspconfig/scry.lua24
-rw-r--r--lua/lspconfig/solargraph.lua32
-rw-r--r--lua/lspconfig/sourcekit.lua22
-rw-r--r--lua/lspconfig/sqlls.lua52
-rw-r--r--lua/lspconfig/sumneko_lua.lua133
-rw-r--r--lua/lspconfig/terraformls.lua23
-rw-r--r--lua/lspconfig/texlab.lua85
-rw-r--r--lua/lspconfig/tsserver.lua50
-rw-r--r--lua/lspconfig/util.lua445
-rw-r--r--lua/lspconfig/vimls.lua63
-rw-r--r--lua/lspconfig/vuels.lua125
-rw-r--r--lua/lspconfig/yamlls.lua47
57 files changed, 3547 insertions, 0 deletions
diff --git a/lua/lspconfig/als.lua b/lua/lspconfig/als.lua
new file mode 100755
index 00000000..c5c4a116
--- /dev/null
+++ b/lua/lspconfig/als.lua
@@ -0,0 +1,104 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local server_name = 'als'
+local bin_name = 'ada_language_server'
+
+if vim.fn.has('win32') == 1 then
+ bin_name = 'ada_language_server.exe'
+end
+
+local function make_installer()
+ local install_dir = util.path.join{util.base_install_dir, server_name}
+
+ local url = 'https://dl.bintray.com/reznikmm/ada-language-server/linux-latest.tar.gz'
+ local download_target = util.path.join{install_dir, "als.tar.gz"}
+ local extracted_dir = "linux"
+ local extract_cmd = string.format("tar -xzf '%s' --one-top-level='%s'", download_target, install_dir)
+
+ if vim.fn.has('win32') == 1 then
+ url = 'https://dl.bintray.com/reznikmm/ada-language-server/win32-latest.zip'
+ download_target = util.path.join{install_dir, 'win32-latest.zip'}
+ extracted_dir = 'win32'
+ extract_cmd = string.format("unzip -o '%s' -d '%s'", download_target, install_dir)
+ elseif vim.fn.has('mac') == 1 then
+ url = 'https://dl.bintray.com/reznikmm/ada-language-server/darwin-latest.tar.gz'
+ download_target = util.path.join{install_dir, 'darwin-latest.tar.gz'}
+ extracted_dir = 'darwin'
+ extract_cmd = string.format("tar -xzf '%s' --one-top-level='%s'", download_target, install_dir)
+ end
+
+ local download_cmd = string.format('curl -fLo "%s" --create-dirs "%s"', download_target, url)
+
+ local bin_path = util.path.join{install_dir, extracted_dir, bin_name}
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(server_name, "is already installed")
+ return
+ end
+ if not (util.has_bins("curl")) then
+ error('Need "curl" to install this.')
+ return
+ end
+ vim.fn.mkdir(install_dir, 'p')
+ vim.fn.system(download_cmd)
+ vim.fn.system(extract_cmd)
+ end
+ function X.info()
+ return {
+ is_installed = util.path.exists(bin_path);
+ install_dir = install_dir;
+ cmd = { bin_path };
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = install_info.cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name};
+ filetypes = {"ada"};
+ -- *.gpr and *.adc would be nice to have here
+ root_dir = util.root_pattern("Makefile", ".git");
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/AdaCore/ada_language_server/master/integration/vscode/ada/package.json";
+ description = [[
+https://github.com/AdaCore/ada_language_server
+
+Ada language server. Use `LspInstall als` to install it.
+
+Can be configured by passing a "settings" object to `als.setup{}`:
+
+```lua
+require('lspconfig').als.setup{
+ settings = {
+ ada = {
+ projectFile = "project.gpr";
+ scenarioVariables = { ... };
+ }
+ }
+}
+```
+]];
+ default_config = {
+ root_dir = [[util.root_pattern("Makefile", ".git")]];
+ };
+ };
+};
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/angularls.lua b/lua/lspconfig/angularls.lua
new file mode 100644
index 00000000..f579909f
--- /dev/null
+++ b/lua/lspconfig/angularls.lua
@@ -0,0 +1,72 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = 'angularls'
+local bin_name = server_name
+local install_loc = util.base_install_dir .. '/' .. server_name
+local script_loc = install_loc .. '/node_modules/@angular/language-server/index.js'
+local bin_loc = install_loc .. '/node_modules/.bin/angularls'
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { '@angular/language-server' };
+ binaries = { bin_name };
+ -- angular-language-service doesn't expose a binary, so we create an execution wrapper.
+ post_install_script =
+ 'echo "#! /bin/sh\n' .. 'node ' .. script_loc .. ' \\$*' .. '" > ' .. bin_loc .. '\n' ..
+ 'chmod +x ' .. bin_loc;
+}
+
+-- Angular requires a node_modules directory to probe for @angular/language-service and typescript
+-- in order to use your projects configured versions.
+-- This defaults to the vim cwd, but will get overwritten by the resolved root of the file.
+local function get_probe_dir(root_dir)
+ local project_root = util.find_node_modules_ancestor(root_dir)
+
+ return project_root and (project_root .. '/node_modules') or ''
+end
+
+local default_probe_dir = get_probe_dir(vim.fn.getcwd())
+
+configs[server_name] = {
+ default_config = {
+ cmd = {
+ bin_loc,
+ '--stdio',
+ '--tsProbeLocations', default_probe_dir,
+ '--ngProbeLocations', default_probe_dir
+ };
+ filetypes = {'typescript', 'html', 'typescriptreact', 'typescript.tsx'};
+ -- Check for angular.json or .git first since that is the root of the project.
+ -- Don't check for tsconfig.json or package.json since there are multiple of these
+ -- in an angular monorepo setup.
+ root_dir = util.root_pattern('angular.json', '.git');
+ };
+ on_new_config = function(new_config, new_root_dir)
+ local new_probe_dir = get_probe_dir(new_root_dir)
+
+ -- We need to check our probe directories because they may have changed.
+ new_config.cmd = {
+ bin_loc,
+ '--stdio',
+ '--tsProbeLocations', new_probe_dir,
+ '--ngProbeLocations', new_probe_dir
+ }
+ end;
+ docs = {
+ description = [[
+https://github.com/angular/vscode-ng-language-service
+
+`angular-language-server` can be installed via `:LspInstall angularls`
+
+If you prefer to install this yourself you can through npm `npm install @angular/language-server`.
+Be aware there is no global binary and must be run via `node_modules/@angular/language-server/index.js`
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("angular.json", ".git")]];
+ };
+ }
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
diff --git a/lua/lspconfig/bashls.lua b/lua/lspconfig/bashls.lua
new file mode 100644
index 00000000..59b21079
--- /dev/null
+++ b/lua/lspconfig/bashls.lua
@@ -0,0 +1,44 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "bashls"
+local bin_name = "bash-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "bash-language-server" };
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {"bash-language-server", "start"};
+ filetypes = {"sh"};
+ root_dir = util.path.dirname;
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/mads-hartmann/bash-language-server
+
+Language server for bash, written using tree sitter in typescript.
+]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+};
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/ccls.lua b/lua/lspconfig/ccls.lua
new file mode 100644
index 00000000..d167249d
--- /dev/null
+++ b/lua/lspconfig/ccls.lua
@@ -0,0 +1,24 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.ccls = {
+ default_config = {
+ cmd = {"ccls"};
+ filetypes = {"c", "cpp", "objc", "objcpp"};
+ root_dir = util.root_pattern("compile_commands.json", "compile_flags.txt", ".git");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/MaskRay/vscode-ccls/master/package.json";
+ description = [[
+https://github.com/MaskRay/ccls/wiki
+
+ccls 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.
+For details on how to automatically generate one using CMake look [here](https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html).
+]];
+ default_config = {
+ root_dir = [[root_pattern("compile_commands.json", "compile_flags.txt", ".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/clangd.lua b/lua/lspconfig/clangd.lua
new file mode 100644
index 00000000..d165edbb
--- /dev/null
+++ b/lua/lspconfig/clangd.lua
@@ -0,0 +1,60 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+-- https://clangd.llvm.org/extensions.html#switch-between-sourceheader
+local function switch_source_header(bufnr)
+ bufnr = util.validate_bufnr(bufnr)
+ local params = { uri = vim.uri_from_bufnr(bufnr) }
+ vim.lsp.buf_request(bufnr, 'textDocument/switchSourceHeader', params, function(err, _, result)
+ if err then error(tostring(err)) end
+ if not result then print ("Corresponding file can’t be determined") return end
+ vim.api.nvim_command('edit '..vim.uri_to_fname(result))
+ end)
+end
+
+local root_pattern = util.root_pattern("compile_commands.json", "compile_flags.txt", ".git")
+configs.clangd = {
+ default_config = util.utf8_config {
+ cmd = {"clangd", "--background-index"};
+ filetypes = {"c", "cpp", "objc", "objcpp"};
+ root_dir = function(fname)
+ local filename = util.path.is_absolute(fname) and fname
+ or util.path.join(vim.loop.cwd(), fname)
+ return root_pattern(filename) or util.path.dirname(filename)
+ end;
+ capabilities = {
+ textDocument = {
+ completion = {
+ editsNearCursor = true
+ }
+ }
+ },
+ };
+ commands = {
+ ClangdSwitchSourceHeader = {
+ function()
+ switch_source_header(0)
+ end;
+ description = "Switch between source/header";
+ };
+ };
+ docs = {
+ description = [[
+https://clang.llvm.org/extra/clangd/Installation.html
+
+**NOTE:** Clang >= 9 is recommended! See [this issue for more](https://github.com/neovim/nvim-lsp/issues/23).
+
+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.
+For details on how to automatically generate one using CMake look [here](https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html).
+]];
+ default_config = {
+ root_dir = [[root_pattern("compile_commands.json", "compile_flags.txt", ".git") or dirname]];
+ on_init = [[function to handle changing offsetEncoding]];
+ capabilities = [[default capabilities, with offsetEncoding utf-8]];
+ };
+ };
+}
+
+configs.clangd.switch_source_header = switch_source_header
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/clojure_lsp.lua b/lua/lspconfig/clojure_lsp.lua
new file mode 100644
index 00000000..f1ec6932
--- /dev/null
+++ b/lua/lspconfig/clojure_lsp.lua
@@ -0,0 +1,22 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.clojure_lsp = {
+ default_config = {
+ cmd = {"clojure-lsp"};
+ filetypes = {"clojure", "edn"};
+ root_dir = util.root_pattern("project.clj", "deps.edn", ".git");
+ };
+ docs = {
+ description = [[
+https://github.com/snoe/clojure-lsp
+
+Clojure Language Server
+]];
+ default_config = {
+ root_dir = [[root_pattern("project.clj", "deps.edn", ".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
+
diff --git a/lua/lspconfig/cmake.lua b/lua/lspconfig/cmake.lua
new file mode 100755
index 00000000..9dbcf717
--- /dev/null
+++ b/lua/lspconfig/cmake.lua
@@ -0,0 +1,25 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.cmake = {
+ default_config = {
+ cmd = {"cmake-language-server"};
+ filetypes = {"cmake"};
+ root_dir = util.root_pattern(".git", "compile_commands.json", "build");
+ init_options = {
+ buildDirectory = "build",
+ }
+ };
+ docs = {
+ description = [[
+https://github.com/regen100/cmake-language-server
+
+CMake LSP Implementation
+]];
+ default_config = {
+ root_dir = [[root_pattern(".git", "compile_commands.json", "build")]];
+ };
+ };
+};
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/codeqlls.lua b/lua/lspconfig/codeqlls.lua
new file mode 100644
index 00000000..ffe08df4
--- /dev/null
+++ b/lua/lspconfig/codeqlls.lua
@@ -0,0 +1,52 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "codeqlls"
+
+local root_pattern = util.root_pattern("qlpack.yml")
+
+configs[server_name] = {
+ default_config = {
+ cmd = {"codeql", "execute", "language-server", "--check-errors", "ON_CHANGE", "-q"};
+ filetypes = {'ql'};
+ root_dir = function(fname)
+ return root_pattern("qlpack.yml") or util.path.dirname(fname)
+ end;
+ log_level = vim.lsp.protocol.MessageType.Warning;
+ before_init = function(initialize_params, config)
+ initialize_params['workspaceFolders'] = {{
+ name = 'workspace',
+ uri = initialize_params['rootUri']
+ }}
+ end;
+ settings = {
+ search_path = vim.empty_dict()
+ };
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/github/vscode-codeql/main/extensions/ql-vscode/package.json";
+ description = [[
+Reference:
+https://help.semmle.com/codeql/codeql-cli.html
+
+Binaries:
+https://github.com/github/codeql-cli-binaries
+ ]];
+ default_config = {
+ settings = {
+ search_path = [[list containing all search paths, eg: '~/codeql-home/codeql-repo']];
+ };
+ };
+ };
+ on_new_config = function(config)
+ if type(config.settings.search_path) == 'table' and not vim.tbl_isempty(config.settings.search_path) then
+ local search_path = "--search-path="
+ for _, path in ipairs(config.settings.search_path) do
+ search_path = search_path..vim.fn.expand(path)..":"
+ end
+ config.cmd = {"codeql", "execute", "language-server", "--check-errors", "ON_CHANGE", "-q", search_path}
+ else
+ config.cmd = {"codeql", "execute", "language-server", "--check-errors", "ON_CHANGE", "-q"}
+ end
+ end;
+}
diff --git a/lua/lspconfig/configs.lua b/lua/lspconfig/configs.lua
new file mode 100644
index 00000000..16ef9949
--- /dev/null
+++ b/lua/lspconfig/configs.lua
@@ -0,0 +1,214 @@
+local util = require 'lspconfig/util'
+local api, validate, lsp = vim.api, vim.validate, vim.lsp
+local tbl_extend = vim.tbl_extend
+
+local configs = {}
+
+function configs.__newindex(t, config_name, config_def)
+ validate {
+ name = {config_name, 's'};
+ default_config = {config_def.default_config, 't'};
+ on_new_config = {config_def.on_new_config, 'f', true};
+ on_attach = {config_def.on_attach, 'f', true};
+ commands = {config_def.commands, 't', true};
+ }
+ if config_def.commands then
+ for k, v in pairs(config_def.commands) do
+ validate {
+ ['command.name'] = {k, 's'};
+ ['command.fn'] = {v[1], 'f'};
+ }
+ end
+ else
+ config_def.commands = {}
+ end
+
+ local M = {}
+
+ local default_config = tbl_extend("keep", config_def.default_config, util.default_config)
+
+ -- Force this part.
+ default_config.name = config_name
+
+ -- The config here is the one which will be instantiated for the new server,
+ -- which is why this is a function, so that it can refer to the settings
+ -- object on the server.
+ local function add_callbacks(config)
+ config.callbacks["window/logMessage"] = function(err, method, params, client_id)
+ if params and params.type <= config.log_level then
+ -- TODO(ashkan) remove this after things have settled.
+ assert(lsp.callbacks, "Update to Nvim HEAD. This is an incompatible interface.")
+ assert(lsp.callbacks["window/logMessage"], "Callback for window/logMessage notification is not defined")
+ lsp.callbacks["window/logMessage"](err, method, params, client_id)
+ end
+ end
+
+ config.callbacks["window/showMessage"] = function(err, method, params, client_id)
+ if params and params.type <= config.message_level then
+ -- TODO(ashkan) remove this after things have settled.
+ assert(lsp.callbacks and lsp.callbacks[method], "Update to Nvim HEAD. This is an incompatible interface.")
+ assert(lsp.callbacks["window/showMessage"], "Callback for window/showMessage notification is not defined")
+ lsp.callbacks["window/showMessage"](err, method, params, client_id)
+ end
+ end
+
+ config.callbacks["workspace/configuration"] = function(err, method, params, client_id)
+ if err then error(tostring(err)) end
+ if not params.items then
+ return {}
+ end
+
+ local result = {}
+ for _, item in ipairs(params.items) do
+ if item.section then
+ local value = util.lookup_section(config.settings, item.section) or vim.NIL
+ -- For empty sections with no explicit '' key, return settings as is
+ if value == vim.NIL and item.section == '' then
+ value = config.settings or vim.NIL
+ end
+ table.insert(result, value)
+ end
+ end
+ return result
+ end
+ end
+
+ function M.setup(config)
+ validate {
+ root_dir = {config.root_dir, 'f', default_config.root_dir ~= nil};
+ filetypes = {config.filetype, 't', true};
+ on_new_config = {config.on_new_config, 'f', true};
+ on_attach = {config.on_attach, 'f', true};
+ commands = {config.commands, 't', true};
+ }
+ if config.commands then
+ for k, v in pairs(config.commands) do
+ validate {
+ ['command.name'] = {k, 's'};
+ ['command.fn'] = {v[1], 'f'};
+ }
+ end
+ end
+
+ config = tbl_extend("keep", config, default_config)
+
+ local trigger
+ if config.filetypes then
+ trigger = "FileType "..table.concat(config.filetypes, ',')
+ else
+ trigger = "BufReadPost *"
+ end
+ api.nvim_command(string.format(
+ "autocmd %s lua require'lspconfig'[%q].manager.try_add()"
+ , trigger
+ , config.name
+ ))
+
+ local get_root_dir = config.root_dir
+
+ -- In the case of a reload, close existing things.
+ if M.manager then
+ for _, client in ipairs(M.manager.clients()) do
+ client.stop(true)
+ end
+ M.manager = nil
+ end
+
+ local make_config = function(_root_dir)
+ local new_config = util.tbl_deep_extend("keep", vim.empty_dict(), config)
+ new_config = util.tbl_deep_extend('keep', new_config, default_config)
+ new_config.capabilities = new_config.capabilities or lsp.protocol.make_client_capabilities()
+ new_config.capabilities = util.tbl_deep_extend('keep', new_config.capabilities, {
+ workspace = {
+ configuration = true;
+ }
+ })
+
+ add_callbacks(new_config)
+ if config_def.on_new_config then
+ pcall(config_def.on_new_config, new_config, _root_dir)
+ end
+ if config.on_new_config then
+ pcall(config.on_new_config, new_config, _root_dir)
+ end
+
+ new_config.on_init = util.add_hook_after(new_config.on_init, function(client, _result)
+ function client.workspace_did_change_configuration(settings)
+ if not settings then return end
+ if vim.tbl_isempty(settings) then
+ settings = {[vim.type_idx]=vim.types.dictionary}
+ end
+ return client.notify('workspace/didChangeConfiguration', {
+ settings = settings;
+ })
+ end
+ if not vim.tbl_isempty(new_config.settings) then
+ client.workspace_did_change_configuration(new_config.settings)
+ end
+ end)
+
+ -- Save the old _on_attach so that we can reference it via the BufEnter.
+ new_config._on_attach = new_config.on_attach
+ new_config.on_attach = vim.schedule_wrap(function(client, bufnr)
+ if bufnr == api.nvim_get_current_buf() then
+ M._setup_buffer(client.id)
+ else
+ api.nvim_command(string.format(
+ "autocmd BufEnter <buffer=%d> ++once lua require'lspconfig'[%q]._setup_buffer(%d)"
+ , bufnr
+ , config_name
+ , client.id
+ ))
+ end
+ end)
+
+ new_config.root_dir = _root_dir
+ return new_config
+ end
+
+ local manager = util.server_per_root_dir_manager(function(_root_dir)
+ return make_config(_root_dir)
+ end)
+
+ function manager.try_add()
+ if vim.bo.buftype == 'nofile' then
+ return
+ end
+ local root_dir = get_root_dir(api.nvim_buf_get_name(0), api.nvim_get_current_buf())
+ local id = manager.add(root_dir)
+ if id then
+ lsp.buf_attach_client(0, id)
+ end
+ end
+
+ M.manager = manager
+ M.make_config = make_config
+ end
+
+ function M._setup_buffer(client_id)
+ local client = lsp.get_client_by_id(client_id)
+ if client.config._on_attach then
+ client.config._on_attach(client)
+ end
+ if client.config.commands and not vim.tbl_isempty(client.config.commands) then
+ M.commands = util.tbl_deep_extend("force", M.commands, client.config.commands)
+ end
+ if not M.commands_created and not vim.tbl_isempty(M.commands) then
+ -- Create the module commands
+ util.create_module_commands(config_name, M.commands)
+ M.commands_created = true
+ end
+ end
+
+ M.commands_created = false
+ M.commands = config_def.commands
+ M.name = config_name
+ M.document_config = config_def
+
+ rawset(t, config_name, M)
+
+ return M
+end
+
+return setmetatable({}, configs)
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/cssls.lua b/lua/lspconfig/cssls.lua
new file mode 100644
index 00000000..7b50950a
--- /dev/null
+++ b/lua/lspconfig/cssls.lua
@@ -0,0 +1,56 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "cssls"
+local bin_name = "css-languageserver"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "vscode-css-languageserver-bin" };
+ binaries = {bin_name};
+}
+
+local root_pattern = util.root_pattern("package.json")
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"css", "scss", "less"};
+ root_dir = function(fname)
+ return root_pattern(fname) or vim.loop.os_homedir()
+ end;
+ settings = {
+ css = { validate = true },
+ scss = { validate = true },
+ less = { validate = true }
+ };
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/vscode-langservers/vscode-css-languageserver-bin
+
+`css-languageserver` can be installed via `:LspInstall cssls` or by yourself with `npm`:
+```sh
+npm install -g vscode-css-languageserver-bin
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("package.json")]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/dartls.lua b/lua/lspconfig/dartls.lua
new file mode 100644
index 00000000..1baf05d6
--- /dev/null
+++ b/lua/lspconfig/dartls.lua
@@ -0,0 +1,55 @@
+local util = require 'lspconfig/util'
+local configs = require 'lspconfig/configs'
+
+local server_name = "dartls"
+local bin_name = "dart"
+
+local find_dart_sdk_root_path = function()
+ if vim.fn["executable"]("flutter") == 1 then
+ local flutter_path = vim.fn["resolve"](vim.fn["exepath"]("flutter"))
+ local flutter_bin = vim.fn["fnamemodify"](flutter_path, ":h")
+ return flutter_bin.."/cache/dart-sdk/bin/dart"
+ elseif vim.fn["executable"]("dart") == 1 then
+ return vim.fn["resolve"](vim.fn["exepath"]("dart"))
+ else
+ return ''
+ end
+end
+
+local analysis_server_snapshot_path = function()
+ local dart_sdk_root_path = vim.fn["fnamemodify"](find_dart_sdk_root_path(), ":h")
+ local snapshot = dart_sdk_root_path.."/snapshots/analysis_server.dart.snapshot"
+
+ if vim.fn["has"]("win32") == 1 or vim.fn["has"]("win64") == 1 then
+ snapshot = snapshot:gsub("/", "\\")
+ end
+
+ return snapshot
+end
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, analysis_server_snapshot_path(), "--lsp"};
+ filetypes = {"dart"};
+ root_dir = util.root_pattern("pubspec.yaml");
+ init_options = {
+ onlyAnalyzeProjectsWithOpenFiles = "false",
+ suggestFromUnimportedLibraries = "true",
+ closingLabels = "true",
+ outline = "true",
+ flutterOutline= "false"
+ };
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/Dart-Code/Dart-Code/master/package.json";
+ description = [[
+https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server/tool/lsp_spec
+
+Language server for dart.
+]];
+ default_config = {
+ root_dir = [[root_pattern("pubspec.yaml")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/diagnosticls.lua b/lua/lspconfig/diagnosticls.lua
new file mode 100644
index 00000000..c4f26220
--- /dev/null
+++ b/lua/lspconfig/diagnosticls.lua
@@ -0,0 +1,45 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "diagnosticls"
+local bin_name = "diagnostic-languageserver"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { bin_name };
+ binaries = { bin_name };
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"},
+ filetypes = {},
+ root_dir = util.path.dirname,
+ },
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name], "--stdio"}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/iamcco/diagnostic-languageserver
+
+Diagnostic language server integrate with linters.
+]];
+ default_config = {
+ filetypes = "Empty by default, override to add filetypes",
+ root_dir = "Vim's starting directory";
+ init_options = "Configuration from https://github.com/iamcco/diagnostic-languageserver#config--document";
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
diff --git a/lua/lspconfig/dockerls.lua b/lua/lspconfig/dockerls.lua
new file mode 100644
index 00000000..572e4701
--- /dev/null
+++ b/lua/lspconfig/dockerls.lua
@@ -0,0 +1,47 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "dockerls"
+local bin_name = "docker-langserver"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "dockerfile-language-server-nodejs" };
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"Dockerfile", "dockerfile"};
+ root_dir = util.root_pattern("Dockerfile");
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/rcjsuen/dockerfile-language-server-nodejs
+
+`docker-langserver` can be installed via `:LspInstall dockerls` or by yourself with `npm`:
+```sh
+npm install -g dockerfile-language-server-nodejs
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("Dockerfile")]];
+ };
+ };
+};
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/efm.lua b/lua/lspconfig/efm.lua
new file mode 100644
index 00000000..d4fc88ac
--- /dev/null
+++ b/lua/lspconfig/efm.lua
@@ -0,0 +1,25 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "efm"
+local bin_name = "efm-langserver"
+
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name};
+ root_dir = util.root_pattern(".git");
+ };
+
+ docs = {
+ description = [[
+https://github.com/mattn/efm-langserver
+
+General purpose Language Server that can use specified error message format generated from specified command.
+]];
+ default_config = {
+ root_dir = [[root_pattern(".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/elixirls.lua b/lua/lspconfig/elixirls.lua
new file mode 100644
index 00000000..fcd91a04
--- /dev/null
+++ b/lua/lspconfig/elixirls.lua
@@ -0,0 +1,110 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "elixirls"
+local bin_name = "elixir-ls"
+local cmd = "language_server"
+
+if vim.fn.has('mac') == 1 or vim.fn.has('unix') == 1 then
+ cmd = cmd..".sh"
+elseif vim.fn.has('win32') == 1 or vim.fn.has('win64') == 1 then
+ cmd = cmd..".bat"
+else
+ error("System is not supported, try to install manually.")
+ return
+end
+
+local function make_installer()
+ local P = util.path.join
+ local install_dir = P{util.base_install_dir, server_name}
+ local cmd_path = P{install_dir, bin_name, "release", cmd}
+
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(server_name, "is already installed.")
+ return
+ end
+
+ if not (util.has_bins("elixir") and util.has_bins("erl")) then
+ error("Need elixir and erl to install this")
+ return
+ end
+
+ local script = [=[
+ set -e
+
+ # clone project
+ git clone https://github.com/elixir-lsp/elixir-ls
+ cd elixir-ls
+
+ # fetch dependencies and compile
+ mix deps.get && mix compile
+
+ # install executable
+ mix elixir_ls.release -o release
+ ]=]
+ vim.fn.mkdir(install_info.install_dir, "p")
+ util.sh(script, install_info.install_dir)
+ end
+
+ function X.info()
+ return {
+ is_installed = util.path.exists(cmd_path);
+ install_dir = install_dir;
+ cmd = { cmd_path };
+ }
+ end
+
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = install_info.cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[server_name] = {
+ default_config = {
+ cmd = { cmd };
+ filetypes = {"elixir", "eelixir"};
+ root_dir = function(fname)
+ return util.root_pattern("mix.exs", ".git")(fname) or vim.loop.os_homedir()
+ end;
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/JakeBecker/vscode-elixir-ls/master/package.json";
+ description = [[
+https://github.com/elixir-lsp/elixir-ls
+
+`elixir-ls` can be installed via `:LspInstall elixirls` or by yourself by following the instructions [here](https://github.com/elixir-lsp/elixir-ls#building-and-running).
+
+This language server does not provide a global binary, but must be installed manually. The command `:LspInstaller elixirls` makes an attempt at installing the binary by
+Fetching the elixir-ls repository from GitHub, compiling it and then installing it.
+
+```lua
+require'lspconfig'.elixirls.setup{
+ -- Unix
+ cmd = { "path/to/language_server.sh" };
+ -- Windows
+ cmd = { "path/to/language_server.bat" };
+ ...
+}
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("mix.exs", ".git") or vim.loop.os_homedir()]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/elmls.lua b/lua/lspconfig/elmls.lua
new file mode 100644
index 00000000..c35824c4
--- /dev/null
+++ b/lua/lspconfig/elmls.lua
@@ -0,0 +1,72 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local lsp = vim.lsp
+local api = vim.api
+
+local server_name = "elmls"
+local bin_name = "elm-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "elm", "elm-test", "elm-format", "@elm-tooling/elm-language-server" };
+ binaries = {bin_name, "elm", "elm-format", "elm-test"};
+}
+
+local default_capabilities = lsp.protocol.make_client_capabilities()
+default_capabilities.offsetEncoding = {"utf-8", "utf-16"}
+local elm_root_pattern = util.root_pattern("elm.json")
+
+configs[server_name] = {
+ 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)
+ 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;
+ init_options = {
+ elmPath = "elm",
+ elmFormatPath = "elm-format",
+ elmTestPath = "elm-test",
+ elmAnalyseTrigger = "change",
+ };
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ new_config.init_options = util.tbl_deep_extend('force', new_config.init_options, {
+ elmPath = install_info.binaries["elm"];
+ elmFormatPath = install_info.binaries["elm-format"];
+ elmTestPath = install_info.binaries["elm-test"];
+ })
+ end
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/elm-tooling/elm-language-client-vscode/master/package.json";
+ description = [[
+https://github.com/elm-tooling/elm-language-server#installation
+
+If you don't want to use Nvim 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")]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
+
diff --git a/lua/lspconfig/flow.lua b/lua/lspconfig/flow.lua
new file mode 100644
index 00000000..5e0abab3
--- /dev/null
+++ b/lua/lspconfig/flow.lua
@@ -0,0 +1,30 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.flow = {
+ default_config = {
+ cmd = {"npx", "--no-install", "flow","lsp"};
+ filetypes = {"javascript", "javascriptreact", "javascript.jsx"};
+ root_dir = util.root_pattern(".flowconfig");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/flowtype/flow-for-vscode/master/package.json";
+ description = [[
+https://flow.org/
+https://github.com/facebook/flow
+
+See below for how to setup Flow itself.
+https://flow.org/en/docs/install/
+
+See below for lsp command options.
+
+```sh
+npx flow lsp --help
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".flowconfig")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/fortls.lua b/lua/lspconfig/fortls.lua
new file mode 100644
index 00000000..7a66c703
--- /dev/null
+++ b/lua/lspconfig/fortls.lua
@@ -0,0 +1,25 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.fortls = {
+ default_config = {
+ cmd = {"fortls"};
+ filetypes = {"fortran"};
+ root_dir = util.root_pattern(".fortls");
+ settings = {
+ nthreads = 1,
+ };
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/hansec/vscode-fortran-ls/master/package.json";
+ description = [[
+https://github.com/hansec/fortran-language-server
+
+Fortran Language Server for the Language Server Protocol
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".fortls")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/gdscript.lua b/lua/lspconfig/gdscript.lua
new file mode 100644
index 00000000..ecd3288f
--- /dev/null
+++ b/lua/lspconfig/gdscript.lua
@@ -0,0 +1,22 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.gdscript = {
+ default_config = {
+ cmd = {"nc", "localhost", "6008"};
+ filetypes = {"gd", "gdscript", "gdscript3"};
+ root_dir = util.root_pattern("project.godot", ".git");
+ };
+ docs = {
+ description = [[
+https://github.com/godotengine/godot
+
+Language server for GDScript, used by Godot Engine.
+]];
+ default_config = {
+ root_dir = util.root_pattern("project.godot", ".git");
+ };
+ };
+};
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/ghcide.lua b/lua/lspconfig/ghcide.lua
new file mode 100644
index 00000000..c427d599
--- /dev/null
+++ b/lua/lspconfig/ghcide.lua
@@ -0,0 +1,24 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.ghcide = {
+ default_config = {
+ cmd = { "ghcide", "--lsp" };
+ filetypes = { "haskell", "lhaskell" };
+ root_dir = util.root_pattern("stack.yaml", "hie-bios", "BUILD.bazel", "cabal.config", "package.yaml");
+ };
+
+ docs = {
+ package_json = "https://raw.githubusercontent.com/digital-asset/ghcide/master/extension/package.json";
+ description = [[
+https://github.com/digital-asset/ghcide
+
+A library for building Haskell IDE tooling.
+]];
+ default_config = {
+ root_dir = [[root_pattern("stack.yaml", "hie-bios", "BUILD.bazel", "cabal.config", "package.yaml")]];
+ };
+ };
+};
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/gopls.lua b/lua/lspconfig/gopls.lua
new file mode 100644
index 00000000..08eacc15
--- /dev/null
+++ b/lua/lspconfig/gopls.lua
@@ -0,0 +1,23 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.gopls = {
+ default_config = {
+ cmd = {"gopls"};
+ filetypes = {"go", "gomod"};
+ root_dir = util.root_pattern("go.mod", ".git");
+ };
+ -- on_new_config = function(new_config) end;
+ -- on_attach = function(client, bufnr) end;
+ docs = {
+ description = [[
+https://github.com/golang/tools/tree/master/gopls
+
+Google's lsp server for golang.
+]];
+ default_config = {
+ root_dir = [[root_pattern("go.mod", ".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/health.lua b/lua/lspconfig/health.lua
new file mode 100644
index 00000000..3abab080
--- /dev/null
+++ b/lua/lspconfig/health.lua
@@ -0,0 +1,26 @@
+local M = {}
+function M.check_health()
+ local configs = require 'lspconfig/configs'
+
+ for _, top_level_config in pairs(configs) do
+ -- If users execute `:LspInstall` or `:LspInstallInfo`,
+ -- a config is required but is not added make_config function.
+ if not (top_level_config.make_config == nil) then
+ -- the folder needs to exist
+ local config = top_level_config.make_config(".")
+
+ local status, cmd = pcall(vim.lsp._cmd_parts, config.cmd)
+ if not status then
+ vim.fn['health#report_error'](string.format("%s: config.cmd error, %s", config.name, cmd))
+ else
+ if not (vim.fn.executable(cmd) == 1) then
+ vim.fn['health#report_error'](string.format("%s: The given command %q is not executable.", config.name, cmd))
+ else
+ vim.fn['health#report_info'](string.format("%s: configuration checked.", config.name))
+ end
+ end
+ end
+ end
+end
+
+return M
diff --git a/lua/lspconfig/hie.lua b/lua/lspconfig/hie.lua
new file mode 100644
index 00000000..f57326dc
--- /dev/null
+++ b/lua/lspconfig/hie.lua
@@ -0,0 +1,38 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.hie = {
+ default_config = {
+ cmd = {"hie-wrapper", "--lsp"};
+ filetypes = {"haskell"};
+ root_dir = util.root_pattern("stack.yaml", "package.yaml", ".git");
+ };
+
+ docs = {
+ package_json = "https://raw.githubusercontent.com/alanz/vscode-hie-server/master/package.json";
+ description = [[
+https://github.com/haskell/haskell-ide-engine
+
+the following init_options are supported (see https://github.com/haskell/haskell-ide-engine#configuration):
+```lua
+init_options = {
+ languageServerHaskell = {
+ hlintOn = bool;
+ maxNumberOfProblems = number;
+ diagnosticsDebounceDuration = number;
+ liquidOn = bool (default false);
+ completionSnippetsOn = bool (default true);
+ formatOnImportOn = bool (default true);
+ formattingProvider = string (default "brittany", alternate "floskell");
+ }
+}
+```
+ ]];
+
+ default_config = {
+ root_dir = [[root_pattern("stack.yaml", "package.yaml", ".git")]];
+ };
+ };
+};
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/hls.lua b/lua/lspconfig/hls.lua
new file mode 100644
index 00000000..9c29b82c
--- /dev/null
+++ b/lua/lspconfig/hls.lua
@@ -0,0 +1,24 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.hls = {
+ default_config = {
+ cmd = {"haskell-language-server-wrapper", "--lsp"};
+ filetypes = {"haskell", "lhaskell"};
+ root_dir = util.root_pattern("*.cabal", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml");
+ };
+
+ docs = {
+ description = [[
+https://github.com/haskell/haskell-language-server
+
+Haskell Language Server
+ ]];
+
+ default_config = {
+ root_dir = [[root_pattern("*.cabal", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml")]];
+ };
+ };
+};
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/html.lua b/lua/lspconfig/html.lua
new file mode 100644
index 00000000..a9636222
--- /dev/null
+++ b/lua/lspconfig/html.lua
@@ -0,0 +1,54 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "html"
+local bin_name = "html-languageserver"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "vscode-html-languageserver-bin" };
+ binaries = {bin_name};
+}
+
+local root_pattern = util.root_pattern("package.json")
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"html"};
+ root_dir = function(fname)
+ return root_pattern(fname) or vim.loop.os_homedir()
+ end;
+ settings = {};
+ init_options = {
+ embeddedLanguages = { css= true, javascript= true },
+ configurationSection = { 'html', 'css', 'javascript' },
+ }
+
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/vscode-langservers/vscode-html-languageserver-bin
+
+`html-languageserver` can be installed via `:LspInstall html` or by yourself with `npm`:
+```sh
+npm install -g vscode-html-languageserver-bin
+```
+]];
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/intelephense.lua b/lua/lspconfig/intelephense.lua
new file mode 100644
index 00000000..7e381349
--- /dev/null
+++ b/lua/lspconfig/intelephense.lua
@@ -0,0 +1,68 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "intelephense"
+local bin_name = "intelephense"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "intelephense" };
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"php"};
+ root_dir = function (pattern)
+ local cwd = vim.loop.cwd();
+ local root = util.root_pattern("composer.json", ".git")(pattern);
+
+ -- prefer cwd if root is a descendant
+ return util.path.is_descendant(cwd, root) and cwd or root;
+ end;
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://intelephense.com/
+
+`intelephense` can be installed via `:LspInstall intelephense` or by yourself with `npm`:
+```sh
+npm install -g intelephense
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("composer.json", ".git")]];
+ init_options = [[{
+ storagePath = Optional absolute path to storage dir. Defaults to os.tmpdir().
+ globalStoragePath = Optional absolute path to a global storage dir. Defaults to os.homedir().
+ licenceKey = Optional licence key or absolute path to a text file containing the licence key.
+ clearCache = Optional flag to clear server state. State can also be cleared by deleting {storagePath}/intelephense
+ -- See https://github.com/bmewburn/intelephense-docs#initialisation-options
+ }]];
+ settings = [[{
+ intelephense = {
+ files = {
+ maxSize = 1000000;
+ };
+ };
+ -- See https://github.com/bmewburn/intelephense-docs#configuration-options
+ }]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/jdtls.lua b/lua/lspconfig/jdtls.lua
new file mode 100644
index 00000000..be9ba6e8
--- /dev/null
+++ b/lua/lspconfig/jdtls.lua
@@ -0,0 +1,138 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local callbacks = require 'vim.lsp.callbacks'
+local path = util.path
+
+local server_name = "jdtls"
+
+local function make_installer()
+ local install_dir = path.join { util.base_install_dir, server_name }
+ local tar_name = "jdt-language-server-latest.tar.gz"
+ local script = string.format([[
+ curl -LO http://download.eclipse.org/jdtls/snapshots/%s > %s
+ tar xf %s
+ ]], tar_name, tar_name, tar_name)
+ local launcher_ls = "ls " .. path.join { install_dir, "plugins", "org.eclipse.equinox.launcher_*.jar" }
+
+ local X = {}
+
+ function X.install()
+ if not util.has_bins("curl", "tar") then
+ error('Need the binaries "curl", "tar" to install this.')
+ return
+ end
+
+ vim.fn.mkdir(install_dir, "p")
+ util.sh(script, install_dir)
+ end
+
+ function X.info()
+ return {
+ is_installed = util.path.exists(install_dir, 'features') ~= false;
+ install_dir = install_dir;
+ }
+ end
+
+ function X.get_os_config()
+ if vim.fn.has("osx") == 1 then
+ return "config_mac"
+ elseif vim.fn.has("unix") == 1 then
+ return "config_linux"
+ else
+ return "config_win"
+ end
+ end
+
+ function X.get_launcher()
+ local file = io.popen(launcher_ls)
+ local results = {}
+
+ for line in file:lines() do
+ table.insert(results, line)
+ end
+
+ if #results == 1 then
+ return results[1]
+ end
+
+ error("Could not find launcher for jdtls.")
+ end
+
+ function X.configure(config)
+ local install_info = X.info()
+ local launcher_path = X.get_launcher()
+
+ if install_info.is_installed then
+ config.cmd = vim.list_extend(
+ vim.list_extend(
+ {
+ "java",
+ "-Declipse.application=org.eclipse.jdt.ls.core.id1",
+ "-Dosgi.bundles.defaultStartLevel=4",
+ "-Declipse.product=org.eclipse.jdt.ls.core.product",
+ "-Dlog.level=ALL",
+ "-noverify",
+ "-Xmx1G",
+ },
+ config.init_options.jvm_args),
+ {
+ "-jar", launcher_path,
+ "-configuration", path.join { install_dir, config.init_options.os_config or X.get_os_config() },
+ "-data", config.init_options.workspace,
+ -- TODO: Handle Java versions 8 and under. This may just work...
+ "--add-modules=ALL-SYSTEM",
+ "--add-opens", "java.base/java.util=ALL-UNNAMED",
+ "--add-opens", "java.base/java.lang=ALL-UNNAMED"
+ })
+ end
+ end
+
+ return X
+end
+
+local installer = make_installer()
+
+configs[server_name] = {
+ default_config = {
+ filetypes = { "java" };
+ root_dir = util.root_pattern('.git');
+ init_options = {
+ workspace = path.join { vim.loop.os_homedir(), "workspace" };
+ jvm_args = {};
+ os_config = nil;
+ };
+ callbacks = {
+ -- Due to an invalid protocol implementation in the jdtls we have to
+ -- conform these to be spec compliant.
+ -- https://github.com/eclipse/eclipse.jdt.ls/issues/376
+ ['textDocument/codeAction'] = function(a, b, actions)
+ for _,action in ipairs(actions) do
+ -- TODO: (steelsojka) Handle more than one edit?
+ if action.command == 'java.apply.workspaceEdit' then
+ action.edit = action.arguments[1]
+ end
+ end
+
+ callbacks['textDocument/codeAction'](a, b, actions)
+ end
+ };
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ docs = {
+ description = [[
+https://projects.eclipse.org/projects/eclipse.jdt.ls
+
+Language server can be installed with `:LspInstall jdtls`
+
+Language server for Java.
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".git")]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
diff --git a/lua/lspconfig/jedi_language_server.lua b/lua/lspconfig/jedi_language_server.lua
new file mode 100644
index 00000000..5fd6cbfc
--- /dev/null
+++ b/lua/lspconfig/jedi_language_server.lua
@@ -0,0 +1,22 @@
+local configs = require 'lspconfig/configs'
+
+configs.jedi_language_server = {
+ default_config = {
+ cmd = {"jedi-language-server"};
+ filetypes = {"python"};
+ root_dir = function(fname)
+ return vim.fn.getcwd()
+ end;
+ };
+ docs = {
+ description = [[
+https://github.com/pappasam/jedi-language-server
+
+`jedi-language-server`, a language server for Python, built on top of jedi
+ ]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/jsonls.lua b/lua/lspconfig/jsonls.lua
new file mode 100644
index 00000000..616a0bbe
--- /dev/null
+++ b/lua/lspconfig/jsonls.lua
@@ -0,0 +1,51 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "jsonls"
+local bin_name = "vscode-json-languageserver"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = {bin_name};
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"json"};
+ root_dir = util.root_pattern(".git", vim.fn.getcwd());
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ -- this language server config is in VSCode built-in package.json
+ package_json = "https://raw.githubusercontent.com/microsoft/vscode/master/extensions/json-language-features/package.json";
+ description = [[
+https://github.com/vscode-langservers/vscode-json-languageserver
+
+vscode-json-languageserver, a language server for JSON and JSON schema
+
+`vscode-json-languageserver` can be installed via `:LspInstall jsonls` or by yourself with `npm`:
+```sh
+npm install -g vscode-json-languageserver
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern(".git", vim.fn.getcwd())]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/julials.lua b/lua/lspconfig/julials.lua
new file mode 100644
index 00000000..f74ce7b7
--- /dev/null
+++ b/lua/lspconfig/julials.lua
@@ -0,0 +1,66 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local environment_directory = util.path.join(util.base_install_dir, "julials")
+
+configs.julials = {
+ default_config = {
+ cmd = {
+ "julia", "--project=" .. environment_directory, "--startup-file=no", "--history-file=no", "-e", [[
+ using Pkg;
+ Pkg.instantiate()
+ using LanguageServer; using SymbolServer;
+ depot_path = get(ENV, "JULIA_DEPOT_PATH", "")
+ project_path = dirname(something(Base.current_project(pwd()), Base.load_path_expand(LOAD_PATH[2])))
+ # Make sure that we only load packages from this environment specifically.
+ empty!(LOAD_PATH)
+ push!(LOAD_PATH, "@")
+ @info "Running language server" env=Base.load_path()[1] pwd() project_path depot_path
+ server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path);
+ server.runlinter = true;
+ run(server);
+ ]]
+ };
+ filetypes = {'julia'};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/julia-vscode/julia-vscode/master/package.json";
+ description = [[
+https://github.com/julia-vscode/julia-vscode
+`LanguageServer.jl` can be installed via `:LspInstall julials` or by yourself the `julia` and `Pkg`:
+```sh
+julia --project=]] .. environment_directory .. [[ -e 'using Pkg; Pkg.add("LanguageServer"); Pkg.add("SymbolServer")'
+```
+If you want to install the LanguageServer manually, you will have to ensure that the Julia environment is stored in this location:
+```vim
+:lua print(require'lspconfig'.util.path.join(require'lspconfig'.util.base_install_dir, "julials"))
+```
+ ]];
+ };
+}
+
+configs.julials.install = function()
+
+ local script = [[
+ julia --project=]] .. environment_directory .. [[ -e 'using Pkg; Pkg.add("LanguageServer"); Pkg.add("SymbolServer")'
+ ]]
+
+ util.sh(script, vim.loop.os_homedir())
+end
+
+configs.julials.install_info = function()
+ local script = [[
+ julia --project=]] .. environment_directory .. [[ -e 'using LanguageServer; using SymbolServer'
+ ]]
+
+ local status = pcall(vim.fn.system, script)
+
+ return {
+ is_installed = status and vim.v.shell_error == 0;
+ }
+end
+
+--- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/kotlin_language_server.lua b/lua/lspconfig/kotlin_language_server.lua
new file mode 100644
index 00000000..373c782c
--- /dev/null
+++ b/lua/lspconfig/kotlin_language_server.lua
@@ -0,0 +1,52 @@
+--- default config for gradle-projects of the
+--- kotlin-language-server: https://github.com/fwcd/kotlin-language-server
+---
+--- This server requires vim to be aware of the kotlin-filetype.
+--- You could refer for this capability to:
+--- https://github.com/udalov/kotlin-vim (recommended)
+--- Note that there is no LICENSE specified yet.
+
+local util = require 'lspconfig/util'
+local configs = require 'lspconfig/configs'
+
+configs.kotlin_language_server = {
+ default_config = {
+ filetypes = { "kotlin" };
+ root_dir = util.root_pattern("settings.gradle");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/fwcd/vscode-kotlin/master/package.json";
+ description = [[
+ A kotlin language server which was developed for internal usage and
+ released afterwards. Maintaining is not done by the original author,
+ but by fwcd.
+
+ It is builded via gradle and developed on github.
+ Source and additional description:
+ https://github.com/fwcd/kotlin-language-server
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("settings.gradle")]];
+ capabilities = [[
+ smart code completion,
+ diagnostics,
+ hover,
+ document symbols,
+ definition lookup,
+ method signature help,
+ dependency resolution,
+ additional plugins from: https://github.com/fwcd
+
+ Snipped of License (refer to source for full License):
+
+ The MIT License (MIT)
+
+ Copyright (c) 2016 George Fraser
+ Copyright (c) 2018 fwcd
+
+ ]];
+ };
+ };
+}
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/leanls.lua b/lua/lspconfig/leanls.lua
new file mode 100644
index 00000000..cd6f4644
--- /dev/null
+++ b/lua/lspconfig/leanls.lua
@@ -0,0 +1,22 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.leanls = {
+ default_config = {
+ cmd = {"lean-language-server", "--stdio"};
+ filetypes = {"lean"};
+ root_dir = util.root_pattern(".git");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/leanprover/vscode-lean/master/package.json";
+ description = [[
+https://github.com/leanprover/lean-client-js/tree/master/lean-language-server
+
+Lean language server.
+ ]];
+ default_config = {
+ root_dir = [[util.root_pattern(".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/metals.lua b/lua/lspconfig/metals.lua
new file mode 100644
index 00000000..12e244bb
--- /dev/null
+++ b/lua/lspconfig/metals.lua
@@ -0,0 +1,106 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local server_name = "metals"
+local bin_name = "metals"
+
+local function make_installer()
+ local install_dir = util.path.join{util.base_install_dir, server_name}
+ local metals_bin = util.path.join{install_dir, bin_name}
+ local server_version
+ if (vim.g.metals_server_version) then
+ server_version = vim.g.metals_server_version
+ else
+ server_version = 'latest.release'
+ end
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(server_name, "is already installed")
+ return
+ end
+ if not (util.has_bins("curl")) then
+ error('Need "curl" to install this.')
+ return
+ end
+ if not (util.has_bins("java")) then
+ error('Need "JDK" to install this.')
+ return
+ end
+
+ local coursier_exe = nil
+ if util.has_bins("cs") then
+ coursier_exe = "cs"
+ elseif util.has_bins("coursier") then
+ coursier_exe = "coursier"
+ end
+ if not coursier_exe then
+ coursier_exe = install_dir .. "/coursier"
+ local download_cmd = string.format("curl -fLo %s --create-dirs https://git.io/coursier-cli", coursier_exe)
+ local chmod_cmd = string.format("chmod +x %s", coursier_exe)
+ vim.fn.system(download_cmd)
+ vim.fn.system(chmod_cmd)
+ else
+ os.execute("mkdir -p " .. install_dir)
+ end
+
+ local install_cmd = string.format("%s bootstrap --java-opt -Xss4m --java-opt -Xms100m org.scalameta:metals_2.12:%s -r bintray:scalacenter/releases -r sonatype:snapshots -o %s -f", coursier_exe, server_version, metals_bin)
+ vim.fn.system(install_cmd)
+ end
+ function X.info()
+ return {
+ is_installed = util.path.exists(metals_bin);
+ install_dir = install_dir;
+ cmd = { metals_bin };
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = install_info.cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name};
+ filetypes = {"scala"};
+ root_dir = util.root_pattern("build.sbt", "build.sc", "build.gradle", "pom.xml");
+ message_level = vim.lsp.protocol.MessageType.Log;
+ init_options = {
+ statusBarProvider = "show-message",
+ isHttpEnabled = true,
+ compilerOptions = {
+ snippetAutoIndent = false
+ }
+ };
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/scalameta/metals-vscode/master/package.json";
+ description = [[
+https://scalameta.org/metals/
+
+To target a specific version on Metals, set the following.
+If nothing is set, the latest stable will be used.
+```vim
+let g:metals_server_version = '0.8.4+106-5f2b9350-SNAPSHOT'
+```
+
+Scala language server with rich IDE features.
+`metals` can be installed via `:LspInstall metals`.
+]];
+ default_config = {
+ root_dir = [[util.root_pattern("build.sbt", "build.sc", "build.gradle", "pom.xml")]];
+ };
+ };
+};
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
diff --git a/lua/lspconfig/nimls.lua b/lua/lspconfig/nimls.lua
new file mode 100644
index 00000000..f71c60f9
--- /dev/null
+++ b/lua/lspconfig/nimls.lua
@@ -0,0 +1,45 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.nimls = {
+ default_config = {
+ cmd = {"nimlsp",};
+ filetypes = {'nim'};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/pragmagic/vscode-nim/master/package.json";
+ description = [[
+https://github.com/PMunch/nimlsp
+`nimlsp` can be installed via `:LspInstall nimls` or by yourself the `nimble` package manager:
+```sh
+nimble install nimlsp
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".git") or os_homedir]];
+ };
+ };
+}
+
+configs.nimls.install = function()
+ local script = [[
+ nimble install nimlsp
+ ]]
+
+ util.sh(script, vim.loop.os_homedir())
+end
+
+configs.nimls.install_info = function()
+ local script = [[
+ nimlsp --version
+ ]]
+
+ local status = pcall(vim.fn.system, script)
+
+ return {
+ is_installed = status and vim.v.shell_error == 0;
+ }
+end
diff --git a/lua/lspconfig/ocamlls.lua b/lua/lspconfig/ocamlls.lua
new file mode 100644
index 00000000..05e71992
--- /dev/null
+++ b/lua/lspconfig/ocamlls.lua
@@ -0,0 +1,45 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "ocamlls"
+local bin_name = "ocaml-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "ocaml-language-server" };
+ binaries = { bin_name };
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = { bin_name, "--stdio" };
+ filetypes = { "ocaml", "reason" };
+ root_dir = util.root_pattern(".merlin", "package.json");
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/ocaml-lsp/ocaml-language-server
+
+`ocaml-language-server` can be installed via `:LspInstall ocamlls` or by yourself with `npm`
+```sh
+npm install -g ocaml-langauge-server
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".merlin", "package.json")]];
+ };
+ };
+};
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/ocamllsp.lua b/lua/lspconfig/ocamllsp.lua
new file mode 100644
index 00000000..9efc59b4
--- /dev/null
+++ b/lua/lspconfig/ocamllsp.lua
@@ -0,0 +1,26 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.ocamllsp = {
+ default_config = {
+ cmd = {"ocamllsp",};
+ filetypes = {'ocaml', 'reason'};
+ root_dir = util.root_pattern(".merlin", "package.json", ".git");
+ };
+ docs = {
+ description = [[
+https://github.com/ocaml/ocaml-lsp
+
+`ocaml-lsp` can be installed as described in [installation guide](https://github.com/ocaml/ocaml-lsp#installation).
+
+To install the lsp server in a particular opam switch:
+```sh
+opam pin add ocaml-lsp-server https://github.com/ocaml/ocaml-lsp.git
+opam install ocaml-lsp-server
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".merlin", "package.json")]];
+ };
+ };
+}
diff --git a/lua/lspconfig/omnisharp.lua b/lua/lspconfig/omnisharp.lua
new file mode 100644
index 00000000..a608537d
--- /dev/null
+++ b/lua/lspconfig/omnisharp.lua
@@ -0,0 +1,84 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local server_name = 'omnisharp'
+local bin_name = 'run'
+
+local function make_installer()
+ local install_dir = util.path.join{util.base_install_dir, server_name}
+ local pid = vim.fn.getpid()
+ local url = 'linux-x64'
+
+ if vim.fn.has('win32') == 1 then
+ url = 'win-x64'
+ bin_name = 'Omnisharp.exe'
+ elseif vim.fn.has('mac') == 1 then
+ url = 'osx'
+ end
+ local bin_path = util.path.join{install_dir, bin_name}
+
+ local download_target = util.path.join{install_dir, string.format("omnisharp-%s.zip", url)}
+ local extract_cmd = string.format("unzip '%s' -d '%s'", download_target, install_dir)
+ local download_cmd = string.format('curl -fLo "%s" --create-dirs "https://github.com/OmniSharp/omnisharp-roslyn/releases/latest/download/omnisharp-%s.zip"', download_target, url)
+ local make_executable_cmd = string.format("chmod u+x '%s'", bin_path)
+
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(server_name, "is already installed")
+ return
+ end
+ if not (util.has_bins("curl")) then
+ error('Need "curl" to install this.')
+ return
+ end
+ vim.fn.mkdir(install_dir, 'p')
+ vim.fn.system(download_cmd)
+ vim.fn.system(extract_cmd)
+ vim.fn.system(make_executable_cmd)
+ end
+ function X.info()
+ return {
+ is_installed = util.path.exists(bin_path);
+ install_dir = install_dir;
+ cmd = { bin_path, "--languageserver" , "--hostPID", tostring(pid)};
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = install_info.cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[server_name] = {
+ default_config = {
+ cmd = installer.info().cmd;
+ filetypes = {"cs", "vb"};
+ root_dir = util.root_pattern("*.csproj", "*.sln");
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ init_options = {
+ };
+ };
+ -- on_new_config = function(new_config) end;
+ -- on_attach = function(client, bufnr) end;
+ docs = {
+ description = [[
+https://github.com/omnisharp/omnisharp-roslyn
+OmniSharp server based on Roslyn workspaces
+]];
+ default_config = {
+ root_dir = [[root_pattern(".csproj", ".sln", ".git")]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/purescriptls.lua b/lua/lspconfig/purescriptls.lua
new file mode 100644
index 00000000..14465d5b
--- /dev/null
+++ b/lua/lspconfig/purescriptls.lua
@@ -0,0 +1,46 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "purescriptls"
+local bin_name = "purescript-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "purescript", "purescript-language-server" };
+ binaries = {bin_name, "purs"};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {"purescript-language-server", "--stdio"};
+ filetypes = {"purescript"};
+ root_dir = util.root_pattern("spago.dhall", "bower.json");
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/nwolverson/vscode-ide-purescript/master/package.json";
+ description = [[
+https://github.com/nwolverson/purescript-language-server
+`purescript-language-server` can be installed via `:LspInstall purescriptls` or by yourself with `npm`
+```sh
+npm install -g purescript-language-server
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("spago.dhall, bower.json")]];
+ };
+ };
+};
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/pyls.lua b/lua/lspconfig/pyls.lua
new file mode 100644
index 00000000..fef0749d
--- /dev/null
+++ b/lua/lspconfig/pyls.lua
@@ -0,0 +1,23 @@
+local configs = require 'lspconfig/configs'
+
+configs.pyls = {
+ default_config = {
+ cmd = {"pyls"};
+ filetypes = {"python"};
+ root_dir = function(fname)
+ return vim.fn.getcwd()
+ end;
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/palantir/python-language-server/develop/vscode-client/package.json";
+ description = [[
+https://github.com/palantir/python-language-server
+
+`python-language-server`, a language server for Python.
+ ]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/pyls_ms.lua b/lua/lspconfig/pyls_ms.lua
new file mode 100644
index 00000000..a1a8b687
--- /dev/null
+++ b/lua/lspconfig/pyls_ms.lua
@@ -0,0 +1,153 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local name = "pyls_ms"
+
+local function get_latest_pyls()
+ local f = io.popen("curl -k --silent 'https://pvsc.blob.core.windows.net/python-language-server-stable?restype=container&comp=list&prefix=Python-Language-Server-osx-x64'")
+ local l = f:read("*a")
+ f:close()
+ local version
+ for w in string.gmatch (l, "x64%.(.-).nupkg") do
+ version = w
+ end
+ return version
+end
+
+local function make_installer()
+ local P = util.path.join
+ local install_dir = P{util.base_install_dir, name}
+
+ local bin = P{install_dir, "Microsoft.Python.LanguageServer.dll"}
+ local cmd = {"dotnet", "exec", bin}
+
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(name, "is already installed")
+ return
+ end
+ if not (util.has_bins("curl")) then
+ error('Need "curl" to install this.')
+ return
+ end
+ if not (util.has_bins("dotnet")) then
+ error('Need ".NET Core" to install this.')
+ return
+ end
+
+ local system
+ if vim.fn.has('mac') == 1 then
+ system = 'osx'
+ elseif vim.fn.has('unix') == 1 then
+ system = 'linux'
+ elseif vim.fn.has('win32') == 1 then
+ system = 'win'
+ else
+ error('Unable to identify host operating system')
+ end
+
+ local version = get_latest_pyls()
+ local url = string.format("https://pvsc.azureedge.net/python-language-server-stable/Python-Language-Server-%s-x64.%s.nupkg", string.lower(system), version)
+ local download_cmd = string.format('curl -fLo %s --create-dirs %s', install_info.install_dir .. "/pyls.nupkg", url)
+ local install_cmd = ''
+
+ if vim.fn.has('mac') == 1 or vim.fn.has('unix') == 1 then
+ install_cmd = "unzip " .. install_info.install_dir .. "/pyls.nupkg -d " .. install_info.install_dir
+ elseif vim.fn.has('win32') == 1 then
+ install_cmd = "Expand-Archive -Force " .. install_info.install_dir .. "/pyls.nupkg -d " .. install_info.install_dir
+ end
+
+ vim.fn.system(download_cmd)
+ vim.fn.system(install_cmd)
+ end
+ function X.info()
+ return {
+ is_installed = util.path.exists(bin);
+ install_dir = install_dir;
+ cmd = cmd;
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[name] = {
+
+ default_config = {
+ filetypes = {"python"};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ settings = {
+ python = {
+ analysis = {
+ errors = {};
+ info = {};
+ disabled = {};
+ };
+ };
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ init_options = {
+ interpreter = {
+ properties =
+ {
+ InterpreterPath = "";
+ Version = "";
+ };
+ };
+ displayOptions = {};
+ analysisUpdates = true;
+ asyncStartup = true;
+ };
+ };
+ docs = {
+ description = [[
+https://github.com/Microsoft/python-language-server
+
+`python-language-server`, a language server for Python.
+
+Requires [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script) to run. On Linux or macOS:
+
+```bash
+curl -L https://dot.net/v1/dotnet-install.sh | sh
+```
+
+`python-language-server` can be installed via `:LspInstall pyls_ms` or you can [build](https://github.com/microsoft/python-language-server/blob/master/CONTRIBUTING.md#setup) your own.
+
+If you want to use your own build, set cmd to point to `Microsoft.Python.languageServer.dll`.
+
+```lua
+cmd = { "dotnet", "exec", "path/to/Microsoft.Python.languageServer.dll" };
+```
+
+If the `python` interpreter is not in your PATH environment variable, set the `InterpreterPath` and `Version` properties accordingly.
+
+```lua
+InterpreterPath = "path/to/python",
+Version = "3.8"
+```
+
+This server accepts configuration via the `settings` key.
+
+ ]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+};
+
+configs[name].install = installer.install
+configs[name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/r_language_server.lua b/lua/lspconfig/r_language_server.lua
new file mode 100644
index 00000000..d75da11f
--- /dev/null
+++ b/lua/lspconfig/r_language_server.lua
@@ -0,0 +1,30 @@
+local util = require 'lspconfig/util'
+local configs = require 'lspconfig/configs'
+
+configs.r_language_server = {
+ default_config = {
+ cmd = {"R", "--slave", "-e", "languageserver::run()"};
+ filetypes = {"r", "rmd"};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ log_level = vim.lsp.protocol.MessageType.Warning;
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/REditorSupport/vscode-r-lsp/master/package.json";
+ description = [[
+ [languageserver](https://github.com/REditorSupport/languageserver) is an
+ implementation of the Microsoft's Language Server Protocol for the R
+ language.
+
+ It is released on CRAN and can be easily installed by
+
+ ```R
+ install.packages("languageserver")
+ ```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern(".git") or os_homedir]]
+ };
+ };
+}
diff --git a/lua/lspconfig/rls.lua b/lua/lspconfig/rls.lua
new file mode 100644
index 00000000..a1b15d9f
--- /dev/null
+++ b/lua/lspconfig/rls.lua
@@ -0,0 +1,31 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.rls = {
+ default_config = {
+ cmd = {"rls"};
+ filetypes = {"rust"};
+ root_dir = util.root_pattern("Cargo.toml");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/rust-lang/rls-vscode/master/package.json";
+ description = [[
+https://github.com/rust-lang/rls
+
+rls, a language server for Rust
+
+See https://github.com/rust-lang/rls#setup to setup rls itself.
+See https://github.com/rust-lang/rls#configuration for rls-specific settings.
+
+If you want to use rls for a particular build, eg nightly, set cmd as follows:
+
+```lua
+cmd = {"rustup", "run", "nightly", "rls"}
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("Cargo.toml")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/rnix.lua b/lua/lspconfig/rnix.lua
new file mode 100644
index 00000000..deaeac98
--- /dev/null
+++ b/lua/lspconfig/rnix.lua
@@ -0,0 +1,81 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local name = "rnix"
+
+local function make_installer()
+ local P = util.path.join
+ local install_dir = P{util.base_install_dir, name}
+
+ local bin = P{install_dir, "bin", "rnix-lsp"}
+ local cmd = {bin}
+
+ local X = {}
+ function X.install()
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(name, "is already installed")
+ return
+ end
+ if not (util.has_bins("cargo")) then
+ error('Need "cargo" to install this.')
+ return
+ end
+
+ local install_cmd = "cargo install rnix-lsp --root=" .. install_info.install_dir .. " rnix-lsp"
+
+ vim.fn.system(install_cmd)
+ end
+ function X.info()
+ return {
+ is_installed = util.path.exists(bin);
+ install_dir = install_dir;
+ cmd = cmd;
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[name] = {
+
+ default_config = {
+ cmd = {"rnix-lsp"};
+ filetypes = {"nix"};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ settings = {
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ init_options = {
+ };
+ };
+ docs = {
+ description = [[
+https://github.com/nix-community/rnix-lsp
+
+A language server for Nix providing basic completion and formatting via nixpkgs-fmt.
+
+To install manually, run `cargo install rnix-lsp`. If you are using nix, rnix-lsp is in nixpkgs.
+
+This server accepts configuration via the `settings` key.
+
+ ]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+};
+
+configs[name].install = installer.install
+configs[name].install_info = installer.info
diff --git a/lua/lspconfig/rome.lua b/lua/lspconfig/rome.lua
new file mode 100644
index 00000000..a8d813f2
--- /dev/null
+++ b/lua/lspconfig/rome.lua
@@ -0,0 +1,37 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.rome = {
+ default_config = {
+ cmd = {'rome', 'lsp'},
+ filetypes = {
+ 'javascript',
+ 'javascriptreact',
+ 'json',
+ 'typescript',
+ 'typescript.tsx',
+ 'typescriptreact'
+ },
+ root_dir = function(fname)
+ return util.find_package_json_ancestor(fname) or
+ util.find_node_modules_ancestor(fname) or
+ util.find_git_ancestor(fname) or
+ util.path.dirname(fname)
+ end
+ },
+ docs = {
+ description = [[
+https://romefrontend.dev
+
+Language server for the Rome Frontend Toolchain.
+
+```sh
+npm install [-g] rome
+```
+]],
+ default_config = {
+ root_dir = [[root_pattern('package.json', 'node_modules', '.git') or dirname]]
+ }
+ }
+}
+
diff --git a/lua/lspconfig/rust_analyzer.lua b/lua/lspconfig/rust_analyzer.lua
new file mode 100644
index 00000000..2d545517
--- /dev/null
+++ b/lua/lspconfig/rust_analyzer.lua
@@ -0,0 +1,27 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.rust_analyzer = {
+ default_config = {
+ cmd = {"rust-analyzer"};
+ filetypes = {"rust"};
+ root_dir = util.root_pattern("Cargo.toml", "rust-project.json");
+ settings = {
+ ["rust-analyzer"] = {}
+ }
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/rust-analyzer/rust-analyzer/master/editors/code/package.json";
+ description = [[
+https://github.com/rust-analyzer/rust-analyzer
+
+rust-analyzer (aka rls 2.0), a language server for Rust
+
+See [docs](https://github.com/rust-analyzer/rust-analyzer/tree/master/docs/user#settings) for extra settings.
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("Cargo.toml", "rust-project.json")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/scry.lua b/lua/lspconfig/scry.lua
new file mode 100644
index 00000000..d2b5164e
--- /dev/null
+++ b/lua/lspconfig/scry.lua
@@ -0,0 +1,24 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.scry = {
+ default_config = {
+ cmd = {'scry'},
+ filetypes = {'crystal'},
+ root_dir = function(fname)
+ return util.root_pattern('shard.yml') or
+ util.find_git_ancestor(fname) or
+ util.path.dirname(fname)
+ end
+ },
+ docs = {
+ description = [[
+https://github.com/crystal-lang-tools/scry
+
+Crystal language server.
+]],
+ default_config = {
+ root_dir = [[root_pattern('shard.yml', '.git') or dirname]]
+ }
+ }
+}
diff --git a/lua/lspconfig/solargraph.lua b/lua/lspconfig/solargraph.lua
new file mode 100644
index 00000000..5aa2ec17
--- /dev/null
+++ b/lua/lspconfig/solargraph.lua
@@ -0,0 +1,32 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local bin_name = "solargraph"
+if vim.fn.has('win32') == 1 then
+ bin_name = bin_name..'.bat'
+end
+configs.solargraph = {
+ default_config = {
+ cmd = {bin_name, "stdio"};
+ filetypes = {"ruby"};
+ root_dir = util.root_pattern("Gemfile", ".git");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/castwide/vscode-solargraph/master/package.json";
+ description = [[
+https://solargraph.org/
+
+solargraph, a language server for Ruby
+
+You can install solargraph via gem install.
+
+```sh
+gem install solargraph
+```
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("Gemfile", ".git")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/sourcekit.lua b/lua/lspconfig/sourcekit.lua
new file mode 100644
index 00000000..4b80b085
--- /dev/null
+++ b/lua/lspconfig/sourcekit.lua
@@ -0,0 +1,22 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.sourcekit = {
+ default_config = {
+ cmd = {"xcrun", "sourcekit-lsp"};
+ filetypes = {"swift", "c", "cpp", "objective-c", "objective-cpp"};
+ root_dir = util.root_pattern("Package.swift", ".git")
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/apple/sourcekit-lsp/master/Editors/vscode/package.json";
+ description = [[
+https://github.com/apple/sourcekit-lsp
+
+Language server for Swift and C/C++/Objective-C.
+ ]];
+ default_config = {
+ root_dir = [[root_pattern("Package.swift", ".git")]];
+ };
+ };
+};
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/sqlls.lua b/lua/lspconfig/sqlls.lua
new file mode 100644
index 00000000..aced4e02
--- /dev/null
+++ b/lua/lspconfig/sqlls.lua
@@ -0,0 +1,52 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "sqlls"
+local bin_name = "sql-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "sql-language-server" };
+ binaries = {bin_name};
+}
+
+local root_pattern = util.root_pattern(".sqllsrc.json")
+
+configs[server_name] = {
+ default_config = {
+ filetypes = {"sql", "mysql"};
+ root_dir = function(fname)
+ return root_pattern(fname) or vim.loop.os_homedir()
+ end;
+ settings = {};
+ };
+ on_new_config = function(config)
+ local install_info = installer.info();
+ local P = util.path.join
+ if install_info.is_installed then
+ local bin_ex = P{install_info.bin_dir, bin_name}
+ config.cmd = {bin_ex, "up", "--method", "stdio"}
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/joe-re/sql-language-server
+
+`cmd` value is **not set** by default. An installer is provided via the `:LspInstall` command that uses the *nvm_lsp node_modules* directory to find the sql-language-server executable. The `cmd` value can be overriden in the `setup` table;
+
+```lua
+require'lspconfig'.sqlls.setup{
+ cmd = {"path/to/command", "up", "--method", "stdio"};
+ ...
+}
+```
+
+This LSP can be installed via `:LspInstall sqlls` or with `npm`. If using LspInstall, run `:LspInstallInfo sqlls` to view installation paths. Find further instructions on manual installation of the sql-language-server at [joe-re/sql-language-server](https://github.com/joe-re/sql-language-server).
+<br>
+ ]];
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/sumneko_lua.lua b/lua/lspconfig/sumneko_lua.lua
new file mode 100644
index 00000000..3faca644
--- /dev/null
+++ b/lua/lspconfig/sumneko_lua.lua
@@ -0,0 +1,133 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local name = "sumneko_lua"
+local bin_name = "lua-language-server"
+
+local function make_installer()
+ local P = util.path.join
+ local install_dir = P{util.base_install_dir, name}
+ local git_dir = P{install_dir, bin_name}
+ local os, bin, ninja_zip, build_file
+
+ if vim.fn.has('osx') == 1 then
+ os = 'macOS'
+ bin = P{git_dir, "bin", "macOS", bin_name}
+ ninja_zip = "ninja-mac.zip"
+ build_file = "macos.ninja"
+ elseif vim.fn.has('unix') == 1 then
+ os = 'Linux'
+ bin = P{git_dir, "bin", "Linux", bin_name}
+ ninja_zip = "ninja-linux.zip"
+ build_file = "linux.ninja"
+ end
+ local main_file = P{git_dir, "main.lua"}
+ local cmd = {bin, '-E', main_file}
+
+ local X = {}
+ function X.install()
+ if os == nil then
+ error("This installer supports Linux and macOS only")
+ return
+ end
+ local install_info = X.info()
+ if install_info.is_installed then
+ print(name, "is already installed")
+ return
+ end
+ if not (util.has_bins("ninja") or util.has_bins("curl")) then
+ error('Need either "ninja" or "curl" (to download ninja) to install this.')
+ return
+ end
+ if not util.has_bins("sh", "chmod", "unzip", "clang") then
+ error('Need the binaries "sh", "chmod", "unzip", "clang" to install this')
+ return
+ end
+ local script = [=[
+set -e
+bin_name=]=]..bin_name..'\n'..[=[
+ninja_zip=]=]..ninja_zip..'\n'..[=[
+build_file=]=]..build_file..'\n'..[=[
+
+# Install ninja if not available.
+which ninja >/dev/null || {
+ test -x ninja || {
+ curl -LO https://github.com/ninja-build/ninja/releases/download/v1.9.0/$ninja_zip
+ unzip $ninja_zip
+ chmod +x ninja
+ }
+ export PATH="$PWD:$PATH"
+}
+
+# clone project
+git clone https://github.com/sumneko/$bin_name
+cd $bin_name
+git submodule update --init --recursive
+
+# build
+cd 3rd/luamake
+ninja -f ninja/$build_file
+cd ../..
+./3rd/luamake/luamake rebuild
+ ]=]
+ vim.fn.mkdir(install_info.install_dir, "p")
+ util.sh(script, install_info.install_dir)
+ end
+ function X.info()
+ return {
+ is_installed = util.has_bins(bin);
+ install_dir = install_dir;
+ cmd = cmd;
+ }
+ end
+ function X.configure(config)
+ local install_info = X.info()
+ if install_info.is_installed then
+ config.cmd = cmd
+ end
+ end
+ return X
+end
+
+local installer = make_installer()
+
+configs[name] = {
+ default_config = {
+ filetypes = {'lua'};
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end;
+ log_level = vim.lsp.protocol.MessageType.Warning;
+ };
+ on_new_config = function(config)
+ installer.configure(config)
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/sumneko/vscode-lua/master/package.json";
+ description = [[
+https://github.com/sumneko/lua-language-server
+
+Lua language server. **By default, this doesn't have a `cmd` set.** This is
+because it doesn't provide a global binary. We provide an installer for Linux
+and macOS using `:LspInstall`. If you wish to install it yourself, [here is a
+guide](https://github.com/sumneko/lua-language-server/wiki/Build-and-Run-(Standalone)).
+So you should set `cmd` yourself like this.
+
+```lua
+require'lspconfig'.sumneko_lua.setup{
+ cmd = {"path", "to", "cmd"};
+ ...
+}
+```
+
+If you install via our installer, if you execute `:LspInstallInfo sumneko_lua`, you can know `cmd` value.
+]];
+ default_config = {
+ root_dir = [[root_pattern(".git") or os_homedir]];
+ };
+ };
+}
+
+configs[name].install = installer.install
+configs[name].install_info = installer.info
+-- vim:et ts=2
diff --git a/lua/lspconfig/terraformls.lua b/lua/lspconfig/terraformls.lua
new file mode 100644
index 00000000..7d551e5c
--- /dev/null
+++ b/lua/lspconfig/terraformls.lua
@@ -0,0 +1,23 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+configs.terraformls = {
+ default_config = {
+ cmd = {"terraform-ls"};
+ filetypes = {"terraform"};
+ root_dir = util.root_pattern(".terraform", ".git");
+ };
+ docs = {
+ package_json = "https://raw.githubusercontent.com/hashicorp/vscode-terraform/master/package.json";
+ description = [[
+https://github.com/hashicorp/terraform-ls
+
+Terraform language server
+Download a released binary from https://github.com/hashicorp/terraform-ls/releases.
+]];
+ default_config = {
+ root_dir = [[root_pattern(".terraform", ".git")]];
+ };
+ };
+}
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/texlab.lua b/lua/lspconfig/texlab.lua
new file mode 100644
index 00000000..b6e08927
--- /dev/null
+++ b/lua/lspconfig/texlab.lua
@@ -0,0 +1,85 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+local lsp = vim.lsp
+
+local texlab_build_status = vim.tbl_add_reverse_lookup {
+ Success = 0;
+ Error = 1;
+ Failure = 2;
+ Cancelled = 3;
+}
+
+local function buf_build(bufnr)
+ bufnr = util.validate_bufnr(bufnr)
+ local params = { textDocument = { uri = vim.uri_from_bufnr(bufnr) } }
+ lsp.buf_request(bufnr, 'textDocument/build', params,
+ function(err, _, result, _)
+ if err then error(tostring(err)) end
+ print("Build "..texlab_build_status[result.status])
+ end)
+end
+
+-- bufnr isn't actually required here, but we need a valid buffer in order to
+-- be able to find the client for buf_request.
+-- TODO find a client by looking through buffers for a valid client?
+-- local function build_cancel_all(bufnr)
+-- bufnr = util.validate_bufnr(bufnr)
+-- local params = { token = "texlab-build-*" }
+-- lsp.buf_request(bufnr, 'window/progress/cancel', params, function(err, method, result, client_id)
+-- if err then error(tostring(err)) end
+-- print("Cancel result", vim.inspect(result))
+-- end)
+-- end
+
+configs.texlab = {
+ default_config = {
+ cmd = {"texlab"};
+ filetypes = {"tex", "bib"};
+ root_dir = vim.loop.os_homedir;
+ settings = {
+ latex = {
+ build = {
+ args = {"-pdf", "-interaction=nonstopmode", "-synctex=1"};
+ executable = "latexmk";
+ onSave = false;
+ };
+ forwardSearch = {
+ args = {};
+ executable = nil;
+ onSave = false;
+ };
+ lint = {
+ onChange = false;
+ };
+ };
+ bibtex = {
+ formatting = {
+ lineLength = 120
+ };
+ };
+ };
+ };
+ commands = {
+ TexlabBuild = {
+ function()
+ buf_build(0)
+ end;
+ description = "Build the current buffer";
+ };
+ };
+ docs = {
+ description = [[
+https://texlab.netlify.com/
+
+A completion engine built from scratch for (La)TeX.
+
+See https://texlab.netlify.com/docs/reference/configuration for configuration options.
+]];
+ default_config = {
+ root_dir = "vim's starting directory";
+ };
+ };
+}
+
+configs.texlab.buf_build = buf_build
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/tsserver.lua b/lua/lspconfig/tsserver.lua
new file mode 100644
index 00000000..4afc6077
--- /dev/null
+++ b/lua/lspconfig/tsserver.lua
@@ -0,0 +1,50 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "tsserver"
+local bin_name = "typescript-language-server"
+if vim.fn.has('win32') == 1 then
+ bin_name = bin_name..".cmd"
+end
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "typescript-language-server" };
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx"};
+ root_dir = util.root_pattern("package.json", "tsconfig.json", ".git");
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ description = [[
+https://github.com/theia-ide/typescript-language-server
+
+`typescript-language-server` can be installed via `:LspInstall tsserver` or by yourself with `npm`:
+```sh
+npm install -g typescript-language-server
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("package.json", "tsconfig.json", ".git")]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/util.lua b/lua/lspconfig/util.lua
new file mode 100644
index 00000000..14eee811
--- /dev/null
+++ b/lua/lspconfig/util.lua
@@ -0,0 +1,445 @@
+local vim = vim
+local validate = vim.validate
+local api = vim.api
+local lsp = vim.lsp
+local uv = vim.loop
+local fn = vim.fn
+
+local M = {}
+
+M.default_config = {
+ log_level = lsp.protocol.MessageType.Warning;
+ message_level = lsp.protocol.MessageType.Warning;
+ settings = vim.empty_dict();
+ init_options = vim.empty_dict();
+ callbacks = {};
+}
+
+function M.validate_bufnr(bufnr)
+ validate {
+ bufnr = { bufnr, 'n' }
+ }
+ return bufnr == 0 and api.nvim_get_current_buf() or bufnr
+end
+
+function M.add_hook_before(func, new_fn)
+ if func then
+ return function(...)
+ -- TODO which result?
+ new_fn(...)
+ return func(...)
+ end
+ else
+ return new_fn
+ end
+end
+
+function M.add_hook_after(func, new_fn)
+ if func then
+ return function(...)
+ -- TODO which result?
+ func(...)
+ return new_fn(...)
+ end
+ else
+ return new_fn
+ end
+end
+
+function M.tbl_deep_extend(behavior, ...)
+ if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
+ error('invalid "behavior": '..tostring(behavior))
+ end
+
+ if select('#', ...) < 2 then
+ error('wrong number of arguments (given '..tostring(1 + select('#', ...))..', expected at least 3)')
+ end
+
+ local ret = {}
+ if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then
+ ret = vim.empty_dict()
+ end
+
+ for i = 1, select('#', ...) do
+ local tbl = select(i, ...)
+ vim.validate{["after the second argument"] = {tbl,'t'}}
+ if tbl then
+ for k, v in pairs(tbl) do
+ if type(v) == 'table' and not vim.tbl_islist(v) then
+ ret[k] = M.tbl_deep_extend(behavior, ret[k] or vim.empty_dict(), v)
+ elseif behavior ~= 'force' and ret[k] ~= nil then
+ if behavior == 'error' then
+ error('key found in more than one map: '..k)
+ end -- Else behavior is "keep".
+ else
+ ret[k] = v
+ end
+ end
+ end
+ end
+ return ret
+end
+
+function M.nvim_multiline_command(command)
+ validate { command = { command, 's' } }
+ for line in vim.gsplit(command, "\n", true) do
+ api.nvim_command(line)
+ end
+end
+
+function M.lookup_section(settings, section)
+ for part in vim.gsplit(section, '.', true) do
+ settings = settings[part]
+ if not settings then
+ return
+ end
+ end
+ return settings
+end
+
+function M.create_module_commands(module_name, commands)
+ for command_name, def in pairs(commands) do
+ local parts = {"command!"}
+ -- Insert attributes.
+ for k, v in pairs(def) do
+ if type(k) == 'string' and type(v) == 'boolean' and v then
+ table.insert(parts, "-"..k)
+ elseif type(k) == 'number' and type(v) == 'string' and v:match("^%-") then
+ table.insert(parts, v)
+ end
+ end
+ table.insert(parts, command_name)
+ -- The command definition.
+ table.insert(parts,
+ string.format("lua require'lspconfig'[%q].commands[%q][1](<f-args>)", module_name, command_name))
+ api.nvim_command(table.concat(parts, " "))
+ end
+end
+
+function M.has_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)
+ local stat = uv.fs_stat(filename)
+ return stat and stat.type or false
+ end
+
+ local function is_dir(filename)
+ return exists(filename) == 'directory'
+ end
+
+ local function is_file(filename)
+ return exists(filename) == 'file'
+ end
+
+ local is_windows = uv.os_uname().version:match("Windows")
+ local path_sep = is_windows and "\\" or "/"
+
+ local is_fs_root
+ if is_windows then
+ is_fs_root = function(path)
+ return path:match("^%a:$")
+ end
+ else
+ is_fs_root = function(path)
+ return path == "/"
+ end
+ end
+
+ local function is_absolute(filename)
+ if is_windows then
+ return filename:match("^%a:") or filename:match("^\\\\")
+ else
+ return filename:match("^/")
+ end
+ end
+
+ local dirname
+ do
+ local strip_dir_pat = path_sep.."([^"..path_sep.."]+)$"
+ local strip_sep_pat = path_sep.."$"
+ dirname = function(path)
+ if not path then return end
+ local result = path:gsub(strip_sep_pat, ""):gsub(strip_dir_pat, "")
+ if #result == 0 then
+ return "/"
+ end
+ return result
+ end
+ end
+
+ local function path_join(...)
+ local result =
+ table.concat(
+ vim.tbl_flatten {...}, path_sep):gsub(path_sep.."+", path_sep)
+ return result
+ end
+
+ -- Traverse the path calling cb along the way.
+ local function traverse_parents(path, cb)
+ path = uv.fs_realpath(path)
+ local dir = path
+ -- Just in case our algo is buggy, don't infinite loop.
+ for _ = 1, 100 do
+ dir = dirname(dir)
+ if not dir then return end
+ -- If we can't ascend further, then stop looking.
+ if cb(dir, path) then
+ return dir, path
+ end
+ if is_fs_root(dir) then
+ break
+ end
+ end
+ end
+
+ -- Iterate the path until we find the rootdir.
+ local function iterate_parents(path)
+ path = uv.fs_realpath(path)
+ local function it(s, v)
+ if not v then return end
+ if is_fs_root(v) then return end
+ return dirname(v), path
+ end
+ return it, path, path
+ end
+
+ local function is_descendant(root, path)
+ if (not path) then
+ return false;
+ end
+
+ local function cb(dir, _)
+ return dir == root;
+ end
+
+ local dir, _ = traverse_parents(path, cb);
+
+ return dir == root;
+ end
+
+ return {
+ is_dir = is_dir;
+ is_file = is_file;
+ is_absolute = is_absolute;
+ exists = exists;
+ sep = path_sep;
+ dirname = dirname;
+ join = path_join;
+ traverse_parents = traverse_parents;
+ iterate_parents = iterate_parents;
+ is_descendant = is_descendant;
+ }
+end)()
+
+
+-- Returns a function(root_dir), which, when called with a root_dir it hasn't
+-- seen before, will call make_config(root_dir) and start a new client.
+function M.server_per_root_dir_manager(_make_config)
+ local clients = {}
+ local manager = {}
+
+ function manager.add(root_dir)
+ if not root_dir then return end
+ if not M.path.is_dir(root_dir) then return end
+
+ -- Check if we have a client alredy or start and store it.
+ local client_id = clients[root_dir]
+ if not client_id then
+ local new_config = _make_config(root_dir)
+ new_config.on_exit = M.add_hook_before(new_config.on_exit, function()
+ clients[root_dir] = nil
+ end)
+ client_id = lsp.start_client(new_config)
+ clients[root_dir] = client_id
+ end
+ return client_id
+ end
+
+ function manager.clients()
+ local res = {}
+ for _, id in pairs(clients) do
+ local client = lsp.get_client_by_id(id)
+ if client then
+ table.insert(res, client)
+ end
+ end
+ return res
+ end
+
+ return manager
+end
+
+function M.search_ancestors(startpath, func)
+ validate { func = {func, 'f'} }
+ if func(startpath) then return startpath end
+ for path in M.path.iterate_parents(startpath) do
+ if func(path) then return path end
+ end
+end
+
+function M.root_pattern(...)
+ local patterns = vim.tbl_flatten {...}
+ local function matcher(path)
+ for _, pattern in ipairs(patterns) do
+ if M.path.exists(vim.fn.glob(M.path.join(path, pattern))) then
+ return path
+ end
+ end
+ end
+ return function(startpath)
+ return M.search_ancestors(startpath, matcher)
+ end
+end
+function M.find_git_ancestor(startpath)
+ return M.search_ancestors(startpath, function(path)
+ if M.path.is_dir(M.path.join(path, ".git")) then
+ return path
+ end
+ end)
+end
+function M.find_node_modules_ancestor(startpath)
+ return M.search_ancestors(startpath, function(path)
+ if M.path.is_dir(M.path.join(path, "node_modules")) then
+ return path
+ end
+ end)
+end
+function M.find_package_json_ancestor(startpath)
+ return M.search_ancestors(startpath, function(path)
+ if M.path.is_file(M.path.join(path, "package.json")) then
+ return path
+ end
+ end)
+end
+
+local function validate_string_list(t)
+ for _, v in ipairs(t) do
+ if type(v) ~= 'string' then
+ return false
+ end
+ end
+ return true
+end
+
+local function map_list(t, func)
+ local res = {}
+ for i, v in ipairs(t) do table.insert(res, func(v, i)) end
+ return res
+end
+
+local function zip_lists_to_map(a, b)
+ assert(#a == #b)
+ local res = {}
+ for i = 1, #a do res[a[i]] = b[i] end
+ return res
+end
+
+local base_install_dir = M.path.join(fn.stdpath("cache"), "lspconfig")
+M.base_install_dir = base_install_dir
+function M.npm_installer(config)
+ validate {
+ server_name = {config.server_name, 's'};
+ packages = {config.packages, validate_string_list, 'List of npm package names'};
+ binaries = {config.binaries, validate_string_list, 'List of binary names'};
+ post_install_script = {config.post_install_script, 's', true};
+ }
+
+ local install_dir = M.path.join(base_install_dir, config.server_name)
+ local bin_dir = M.path.join(install_dir, "node_modules", ".bin")
+ local function bin_path(name)
+ return M.path.join(bin_dir, name)
+ end
+
+ local binary_paths = map_list(config.binaries, bin_path)
+
+ local function get_install_info()
+ return {
+ bin_dir = bin_dir;
+ install_dir = install_dir;
+ binaries = zip_lists_to_map(config.binaries, binary_paths);
+ is_installed = M.has_bins(unpack(binary_paths));
+ }
+ end
+
+ local function install()
+ -- TODO(ashkan) need all binaries or just the first?
+ if M.has_bins(unpack(config.binaries)) then
+ return print(config.server_name, "is already installed (not by Nvim)")
+ end
+ if not M.has_bins("sh", "npm", "mkdir") then
+ api.nvim_err_writeln('Installation requires "sh", "npm", "mkdir"')
+ return
+ end
+ if get_install_info().is_installed then
+ return print(config.server_name, "is already installed")
+ end
+ local install_params = {
+ packages = table.concat(config.packages, ' ');
+ install_dir = install_dir;
+ post_install_script = config.post_install_script or '';
+ }
+ local cmd = io.popen("sh", "w")
+ local install_script = ([[
+ set -e
+ mkdir -p "{{install_dir}}"
+ cd "{{install_dir}}"
+ [ ! -f package.json ] && npm init -y
+ npm install {{packages}} --no-package-lock --no-save --production
+ {{post_install_script}}
+ ]]):gsub("{{(%S+)}}", install_params)
+ cmd:write(install_script)
+ cmd:close()
+ if not get_install_info().is_installed then
+ api.nvim_err_writeln('Installation of ' .. config.server_name .. ' failed')
+ end
+ end
+
+ return {
+ install = install;
+ info = get_install_info;
+ }
+end
+
+function M.sh(script, cwd)
+ assert(cwd and M.path.is_dir(cwd), "sh: Invalid directory")
+ -- switching to insert mode makes the buffer scroll as new output is added
+ -- and makes it easy and intuitive to cancel the operation with Ctrl-C
+ api.nvim_command("10new | startinsert")
+ local bufnr = api.nvim_get_current_buf()
+ local function on_exit(job_id, code, event_type)
+ if code == 0 then
+ api.nvim_command("silent bwipeout! "..bufnr)
+ end
+ end
+ fn.termopen({"sh", "-c", script}, {cwd = cwd, on_exit = on_exit})
+end
+
+function M.format_vspackage_url(extension_name)
+ local org, package = unpack(vim.split(extension_name, ".", true))
+ assert(org and package)
+ return string.format("https://marketplace.visualstudio.com/_apis/public/gallery/publishers/%s/vsextensions/%s/latest/vspackage", org, package)
+end
+
+
+function M.utf8_config(config)
+ config.capabilities = config.capabilities or lsp.protocol.make_client_capabilities()
+ config.capabilities.offsetEncoding = {"utf-8", "utf-16"}
+ function config.on_init(client, result)
+ if result.offsetEncoding then
+ client.offset_encoding = result.offsetEncoding
+ end
+ end
+ return config
+end
+
+return M
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/vimls.lua b/lua/lspconfig/vimls.lua
new file mode 100644
index 00000000..15e5fed1
--- /dev/null
+++ b/lua/lspconfig/vimls.lua
@@ -0,0 +1,63 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "vimls"
+local bin_name = "vim-language-server"
+if vim.fn.has('win32') == 1 then
+ bin_name = bin_name..".cmd"
+end
+
+local installer = util.npm_installer {
+ server_name = server_name,
+ packages = {"vim-language-server"},
+ binaries = {bin_name}
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"},
+ filetypes = {"vim"},
+ root_dir = function(fname)
+ return util.find_git_ancestor(fname) or vim.loop.os_homedir()
+ end,
+ init_options = {
+ iskeyword = "@,48-57,_,192-255,-#",
+ vimruntime = "",
+ runtimepath = "",
+ diagnostic = {enable = true},
+ indexes = {
+ runtimepath = true,
+ gap = 100,
+ count = 3,
+ projectRootPatterns = {"runtime", "nvim", ".git", "autoload", "plugin"}
+ },
+ suggest = {fromVimruntime = true, fromRuntimepath = true}
+ },
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == "table" then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end,
+ docs = {
+ description = [[
+https://github.com/iamcco/vim-language-server
+
+If you don't want to use Nvim to install it, then you can use:
+```sh
+npm install -g vim-language-server
+```
+]]
+ }
+ }
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/vuels.lua b/lua/lspconfig/vuels.lua
new file mode 100644
index 00000000..4a8774bd
--- /dev/null
+++ b/lua/lspconfig/vuels.lua
@@ -0,0 +1,125 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "vuels"
+local bin_name = "vls"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = { "vls" };
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name};
+ filetypes = {"vue"};
+ root_dir = util.root_pattern("package.json", "vue.config.js");
+ init_options = {
+ config = {
+ vetur = {
+ useWorkspaceDependencies = false;
+ validation = {
+ template = true;
+ style = true;
+ script = true;
+ };
+ completion = {
+ autoImport = false;
+ useScaffoldSnippets = false;
+ tagCasing = "kebab";
+ };
+ format = {
+ defaultFormatter = {
+ js = "none";
+ ts = "none";
+ };
+ defaultFormatterOptions = {};
+ scriptInitialIndent = false;
+ styleInitialIndent = false;
+ }
+ };
+ css = {};
+ html = {
+ suggest = {};
+ };
+ javascript = {
+ format = {};
+ };
+ typescript = {
+ format = {};
+ };
+ emmet = {};
+ stylusSupremacy = {};
+ };
+ };
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ -- Try to preserve any additional args from upstream changes.
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/vuejs/vetur/master/package.json";
+ description = [[
+https://github.com/vuejs/vetur/tree/master/server
+
+Vue language server(vls)
+`vue-language-server` can be installed via `:LspInstall vuels` or by yourself with `npm`:
+```sh
+npm install -g vls
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern("package.json", "vue.config.js")]];
+ init_options = {
+ config = {
+ vetur = {
+ useWorkspaceDependencies = false;
+ validation = {
+ template = true;
+ style = true;
+ script = true;
+ };
+ completion = {
+ autoImport = false;
+ useScaffoldSnippets = false;
+ tagCasing = "kebab";
+ };
+ format = {
+ defaultFormatter = {
+ js = "none";
+ ts = "none";
+ };
+ defaultFormatterOptions = {};
+ scriptInitialIndent = false;
+ styleInitialIndent = false;
+ }
+ };
+ css = {};
+ html = {
+ suggest = {};
+ };
+ javascript = {
+ format = {};
+ };
+ typescript = {
+ format = {};
+ };
+ emmet = {};
+ stylusSupremacy = {};
+ };
+ };
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2
diff --git a/lua/lspconfig/yamlls.lua b/lua/lspconfig/yamlls.lua
new file mode 100644
index 00000000..787e8df3
--- /dev/null
+++ b/lua/lspconfig/yamlls.lua
@@ -0,0 +1,47 @@
+local configs = require 'lspconfig/configs'
+local util = require 'lspconfig/util'
+
+local server_name = "yamlls"
+local bin_name = "yaml-language-server"
+
+local installer = util.npm_installer {
+ server_name = server_name;
+ packages = {bin_name};
+ binaries = {bin_name};
+}
+
+configs[server_name] = {
+ default_config = {
+ cmd = {bin_name, "--stdio"};
+ filetypes = {"yaml"};
+ root_dir = util.root_pattern(".git", vim.fn.getcwd());
+ };
+ on_new_config = function(new_config)
+ local install_info = installer.info()
+ if install_info.is_installed then
+ if type(new_config.cmd) == 'table' then
+ new_config.cmd[1] = install_info.binaries[bin_name]
+ else
+ new_config.cmd = {install_info.binaries[bin_name]}
+ end
+ end
+ end;
+ docs = {
+ package_json = "https://raw.githubusercontent.com/redhat-developer/vscode-yaml/master/package.json";
+ description = [[
+https://github.com/redhat-developer/yaml-language-server
+
+`yaml-language-server` can be installed via `:LspInstall yamlls` or by yourself with `npm`:
+```sh
+npm install -g yaml-language-server
+```
+]];
+ default_config = {
+ root_dir = [[root_pattern(".git", vim.fn.getcwd())]];
+ };
+ };
+}
+
+configs[server_name].install = installer.install
+configs[server_name].install_info = installer.info
+-- vim:et ts=2 sw=2