diff options
| author | kylo252 <[email protected]> | 2021-07-31 06:06:08 +0200 | 
|---|---|---|
| committer | GitHub <[email protected]> | 2021-07-31 00:06:08 -0400 | 
| commit | 9d89929d9bb47d1f78c2d3945b761da2f24a5643 (patch) | |
| tree | 7f5d281ddb4bbdcecffe01c0234d02be32ede1f7 /lua | |
| parent | 6f4dd8471b24f71ed6712fb6b9acc0ac79b9137a (diff) | |
Enable querying lang-server formatting capabilities (#1078)
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/core/galaxyline.lua | 30 | ||||
| -rw-r--r-- | lua/default-config.lua | 521 | ||||
| -rw-r--r-- | lua/lsp/init.lua | 98 | ||||
| -rw-r--r-- | lua/lsp/keybinds.lua | 67 | ||||
| -rw-r--r-- | lua/lsp/null-ls.lua | 113 | ||||
| -rw-r--r-- | lua/lsp/service.lua | 122 | ||||
| -rw-r--r-- | lua/utils/init.lua | 6 | 
7 files changed, 531 insertions, 426 deletions
| diff --git a/lua/core/galaxyline.lua b/lua/core/galaxyline.lua index cf7d35d0..2aae0242 100644 --- a/lua/core/galaxyline.lua +++ b/lua/core/galaxyline.lua @@ -6,6 +6,8 @@ if not status_ok then    return  end +local utils = require "utils" +  -- NOTE: if someone defines colors but doesn't have them then this will break  local palette_status_ok, colors = pcall(require, lvim.colorscheme .. ".palette")  if not palette_status_ok then @@ -200,36 +202,22 @@ table.insert(gls.right, {    },  }) --- TODO: this function doesn't need to be this complicated  local function get_attached_provider_name(msg)    msg = msg or "LSP Inactive" -  local buf_ft = vim.bo.filetype    local buf_clients = vim.lsp.buf_get_clients()    if next(buf_clients) == nil then      return msg    end - -  local utils = require "utils" -  local config = require("null-ls.config").get() -  local builtins = require "null-ls.builtins" -  -- concat all the builtin formatters and linters from null-ls -  local all_things = builtins.formatting -  for k, v in pairs(builtins.diagnostics) do -    all_things[k] = v -  end - -  -- if we open multiple filetypes in the same session -  -- null-ls will register multiple formatter/linters -  -- but only use the ones that support vim.bo.filetype -  -- so we need to filter them +  local buf_ft = vim.bo.filetype    local buf_client_names = {} +  local null_ls_providers = require("lsp.null-ls").requested_providers    for _, client in pairs(buf_clients) do      if client.name == "null-ls" then -      -- for every registered formatter/linter in the current buffer -      for _, v in pairs(config._names) do -        -- show only the ones that are being used for the current filetype -        if utils.has_value(all_things[v].filetypes, buf_ft) then -          table.insert(buf_client_names, v) +      for _, provider in pairs(null_ls_providers) do +        if vim.tbl_contains(provider.filetypes, buf_ft) then +          if not vim.tbl_contains(buf_client_names, provider.name) then +            table.insert(buf_client_names, provider.name) +          end          end        end      else diff --git a/lua/default-config.lua b/lua/default-config.lua index 25c6dcef..41636757 100644 --- a/lua/default-config.lua +++ b/lua/default-config.lua @@ -47,6 +47,7 @@ lvim = {      popup_border = "single",      default_keybinds = true,      on_attach_callback = nil, +    on_init_callback = nil,    },    plugins = { @@ -54,11 +55,13 @@ lvim = {    },    autocommands = {}, +  debug = false,  }  local schemas = nil -local common_on_attach = require("lsp.service").common_on_attach -local common_capabilities = require("lsp.service").common_capabilities() +local common_on_attach = require("lsp").common_on_attach +local common_capabilities = require("lsp").common_capabilities() +local common_on_init = require("lsp").common_on_init  local status_ok, jsonls_settings = pcall(require, "nlspsettings.jsonls")  if status_ok then    schemas = jsonls_settings.get_default_schemas() @@ -67,9 +70,12 @@ end  -- TODO move all of this into lang specific files, only require when using  lvim.lang = {    asm = { -    formatter = { -      exe = "asmfmt", -      args = {}, +    formatters = { +      { +        -- @usage can be asmfmt +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -78,9 +84,12 @@ lvim.lang = {      },    },    beancount = { -    formatter = { -      exe = "bean_format", -      args = {}, +    formatters = { +      { +        -- @usage can be bean_format +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -88,19 +97,21 @@ lvim.lang = {        setup = {          cmd = { "beancount-langserver" },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    c = { -    formatter = { -      exe = "clang_format", -      args = {}, -      stdin = true, -    }, -    linters = { -      "clangtidy", +    formatters = { +      { +        -- @usage can be clang_format or uncrustify +        exe = "", +        args = {}, +        stdin = true, +      },      }, +    linters = {},      lsp = {        provider = "clangd",        setup = { @@ -113,20 +124,21 @@ lvim.lang = {            "--clang-tidy-checks=-*,llvm-*,clang-analyzer-*",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    cpp = { -    formatter = { -      exe = "clang_format", -      args = {}, -      stdin = true, -    }, -    linters = { -      "cppcheck", -      "clangtidy", +    formatters = { +      { +        -- @usage can be clang_format or uncrustify +        exe = "", +        args = {}, +        stdin = true, +      },      }, +    linters = {},      lsp = {        provider = "clangd",        setup = { @@ -139,14 +151,18 @@ lvim.lang = {            "--clang-tidy-checks=-*,llvm-*,clang-analyzer-*",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    crystal = { -    formatter = { -      exe = "crystal_format", -      args = {}, +    formatters = { +      { +        -- @usage can be crystal_format +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -154,14 +170,18 @@ lvim.lang = {        setup = {          cmd = { "crystalline" },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    cs = { -    formatter = { -      exe = "clang_format", -      args = {}, +    formatters = { +      { +        -- @usage can be clang_format or uncrustify +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -174,14 +194,18 @@ lvim.lang = {            tostring(vim.fn.getpid()),          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    cmake = { -    formatter = { -      exe = "cmake_format", -      args = {}, +    formatters = { +      { +        -- @usage can be cmake_format +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -192,15 +216,16 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    clojure = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "clojure_lsp", @@ -210,14 +235,18 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    css = { -    formatter = { -      exe = "prettier", -      args = {}, +    formatters = { +      { +        -- @usage can be prettier or prettierd +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -229,14 +258,18 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    d = { -    formatter = { -      exe = "dfmt", -      args = {}, +    formatters = { +      { +        -- @usage can be dfmt +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -244,15 +277,19 @@ lvim.lang = {        setup = {          cmd = { "serve-d" },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    dart = { -    formatter = { -      exe = "dart_format", -      args = {}, -      stdin = true, +    formatters = { +      { +        -- @usage can be dart_format +        exe = "", +        args = {}, +        stdin = true, +      },      },      linters = {},      lsp = { @@ -264,14 +301,18 @@ lvim.lang = {            "--lsp",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    docker = { -    formatter = { -      exe = "", -      args = {}, +    formatters = { +      { +        exe = "", +        args = {}, +      }, +      -- @usage can be {"hadolint"}      },      linters = {},      lsp = { @@ -282,15 +323,19 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    elixir = { -    formatter = { -      exe = "mix", -      args = {}, -      stdin = true, +    formatters = { +      { +        -- @usage can be mix +        exe = "", +        args = {}, +        stdin = true, +      },      },      linters = {},      lsp = { @@ -300,15 +345,19 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/elixir/elixir-ls/language_server.sh",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    elm = { -    formatter = { -      exe = "elm_format", -      args = {}, -      stdin = true, +    formatters = { +      { +        -- @usage can be elm_format +        exe = "", +        args = {}, +        stdin = true, +      },      },      linters = {},      lsp = { @@ -318,6 +367,7 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/elm/node_modules/.bin/elm-language-server",          },          on_attach = common_on_attach, +        on_init = common_on_init,          init_options = {            elmAnalyseTrigger = "change",            elmFormatPath = DATA_PATH .. "/lspinstall/elm/node_modules/.bin/elm-format", @@ -328,9 +378,12 @@ lvim.lang = {      },    },    erlang = { -    formatter = { -      exe = "erlfmt", -      args = {}, +    formatters = { +      { +        -- @usage can be erlfmt +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -340,35 +393,40 @@ lvim.lang = {            "erlang_ls",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    emmet = { active = false },    fish = { -    formatter = { -      exe = "fish_indent", -      args = {}, +    formatters = { +      { +        -- @usage can be fish_indent +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = {        provider = "",        setup = {          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    go = { -    formatter = { -      exe = "gofmt", -      args = {}, -      stdin = true, -    }, -    linters = { -      "golangcilint", -      "revive", +    formatters = { +      { +        -- @usage can be gofmt or goimports or gofumpt +        exe = "", +        args = {}, +        stdin = true, +      },      }, +    linters = {},      lsp = {        provider = "gopls",        setup = { @@ -376,15 +434,16 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/go/gopls",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    graphql = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "graphql", @@ -396,20 +455,20 @@ lvim.lang = {            "stream",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    html = { -    formatter = { -      exe = "prettier", -      args = {}, -    }, -    linters = { -      "tidy", -      -- https://docs.errata.ai/vale/scoping#html -      "vale", +    formatters = { +      { +        -- @usage can be prettier or prettierd +        exe = "", +        args = {}, +      },      }, +    linters = {},      lsp = {        provider = "html",        setup = { @@ -419,14 +478,18 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    java = { -    formatter = { -      exe = "prettier", -      args = { "--stdin-filepath", vim.api.nvim_buf_get_name(0) }, +    formatters = { +      { +        -- @usage can be clang_format or uncrustify +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -434,15 +497,19 @@ lvim.lang = {        setup = {          cmd = { DATA_PATH .. "/lspinstall/java/jdtls.sh" },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    json = { -    formatter = { -      exe = "json_tool", -      args = {}, -      stdin = true, +    formatters = { +      { +        -- @usage can be json_tool or prettier or prettierd +        exe = "", +        args = {}, +        stdin = true, +      },      },      linters = {},      lsp = { @@ -454,6 +521,7 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,          settings = {            json = { @@ -477,10 +545,10 @@ lvim.lang = {      },    },    julia = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "julials", @@ -493,15 +561,16 @@ lvim.lang = {            CONFIG_PATH .. "/utils/julia/run.jl",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    kotlin = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "kotlin_language_server", @@ -510,6 +579,7 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/kotlin/server/bin/kotlin-language-server",          },          on_attach = common_on_attach, +        on_init = common_on_init,          root_dir = function(fname)            local util = require "lspconfig/util" @@ -530,11 +600,14 @@ lvim.lang = {      },    },    lua = { -    formatter = { -      exe = "stylua", -      args = {}, +    formatters = { +      { +        -- @usage can be stylua or lua_format +        exe = "stylua", +        args = {}, +      },      }, -    linters = { "luacheck" }, +    linters = {},      lsp = {        provider = "sumneko_lua",        setup = { @@ -543,7 +616,9 @@ lvim.lang = {            "-E",            DATA_PATH .. "/lspinstall/lua/main.lua",          }, +        capabilities = common_capabilities,          on_attach = common_on_attach, +        on_init = common_on_init,          settings = {            Lua = {              runtime = { @@ -572,20 +647,26 @@ lvim.lang = {      },    },    nginx = { -    formatter = { -      exe = "nginx_beautifier", -      args = { -        provider = "", -        setup = {}, +    formatters = { +      { +        -- @usage can be nginx_beautifier +        exe = "", +        args = { +          provider = "", +          setup = {}, +        },        },      },      linters = {},      lsp = {},    },    perl = { -    formatter = { -      exe = "perltidy", -      args = {}, +    formatters = { +      { +        -- @usage can be perltidy +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -594,9 +675,12 @@ lvim.lang = {      },    },    sql = { -    formatter = { -      exe = "sqlformat", -      args = {}, +    formatters = { +      { +        -- @usage can be sqlformat +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -607,9 +691,12 @@ lvim.lang = {      },    },    php = { -    formatter = { -      exe = "phpcbf", -      args = {}, +    formatters = { +      { +        -- @usage can be phpcbf +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -620,6 +707,7 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          filetypes = { "php", "phtml" },          settings = {            intelephense = { @@ -632,28 +720,30 @@ lvim.lang = {      },    },    puppet = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "puppet",        setup = {          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    javascript = { -    -- @usage can be prettier or eslint -    formatter = { -      exe = "prettier", -      args = {}, -    }, -    linters = { -      "eslint", +    -- @usage can be prettier or prettier_d_slim or prettierd +    formatters = { +      { +        exe = "", +        args = {}, +      },      }, +    -- @usage can be {"eslint"} or {"eslint_d"} +    linters = {},      lsp = {        provider = "tsserver",        setup = { @@ -663,19 +753,21 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    javascriptreact = { -    -- @usage can be prettier or eslint -    formatter = { -      exe = "prettier", -      args = {}, -    }, -    linters = { -      "eslint", +    formatters = { +      { +        -- @usage can be prettier or prettier_d_slim or prettierd +        exe = "", +        args = {}, +      },      }, +    -- @usage can be {"eslint"} or {"eslint_d"} +    linters = {},      lsp = {        provider = "tsserver",        setup = { @@ -685,21 +777,20 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    python = { -    -- @usage can be flake8 or yapf -    formatter = { -      exe = "black", -      args = {}, -    }, -    linters = { -      "flake8", -      "pylint", -      "mypy", +    formatters = { +      { +        -- @usage can be black or yapf or isort +        exe = "", +        args = {}, +      },      }, +    linters = {},      lsp = {        provider = "pyright",        setup = { @@ -708,6 +799,7 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      }, @@ -715,9 +807,12 @@ lvim.lang = {    -- R -e 'install.packages("formatR",repos = "http://cran.us.r-project.org")'    -- R -e 'install.packages("readr",repos = "http://cran.us.r-project.org")'    r = { -    formatter = { -      exe = "format_r", -      args = {}, +    formatters = { +      { +        -- @usage can be format_r +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -730,16 +825,20 @@ lvim.lang = {            "languageserver::run()",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    ruby = { -    formatter = { -      exe = "rufo", -      args = {}, +    formatters = { +      { +        -- @usage can be rufo +        exe = "", +        args = {}, +      },      }, -    linters = { "ruby" }, +    linters = {},      lsp = {        provider = "solargraph",        setup = { @@ -748,14 +847,18 @@ lvim.lang = {            "stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    rust = { -    formatter = { -      exe = "rustfmt", -      args = {}, +    formatters = { +      { +        -- @usage can be rustfmt +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -765,32 +868,38 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/rust/rust-analyzer",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    scala = { -    formatter = { -      exe = "scalafmt", -      args = {}, +    formatters = { +      { +        -- @usage can be scalafmt +        exe = "", +        args = {}, +      },      },      linters = { "" },      lsp = {        provider = "metals",        setup = {          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    sh = { -    -- @usage can be 'shfmt' -    formatter = { -      exe = "shfmt", -      args = {}, +    formatters = { +      { +        -- @usage can be shfmt +        exe = "", +        args = {}, +      },      }, -    -- @usage can be 'shellcheck' -    linters = { "shellcheck" }, +    linters = {},      lsp = {        provider = "bashls",        setup = { @@ -799,15 +908,16 @@ lvim.lang = {            "start",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    svelte = { -    formatter = { +    formatters = { {        exe = "",        args = {}, -    }, +    } },      linters = {},      lsp = {        provider = "svelte", @@ -817,14 +927,18 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    swift = { -    formatter = { -      exe = "swiftformat", -      args = {}, +    formatters = { +      { +        -- @usage can be swiftformat +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -835,6 +949,7 @@ lvim.lang = {            "sourcekit-lsp",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      }, @@ -852,9 +967,12 @@ lvim.lang = {      },    },    terraform = { -    formatter = { -      exe = "terraform_fmt", -      args = {}, +    formatters = { +      { +        -- @usage can be terraform_fmt +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -865,35 +983,41 @@ lvim.lang = {            "serve",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    tex = { -    formatter = { -      exe = "latexindent", -      args = {}, -      stdin = false, +    formatters = { +      { +        exe = "", +        args = {}, +        stdin = false, +      }, +      -- @usage can be chktex or vale      }, -    linters = { "chktex" }, +    linters = {},      lsp = {        provider = "texlab",        setup = {          cmd = { DATA_PATH .. "/lspinstall/latex/texlab" },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    typescript = { -    -- @usage can be prettier or eslint -    formatter = { -      exe = "prettier", -      args = {}, -    }, -    linters = { -      "eslint", +    formatters = { +      { +        -- @usage can be prettier or prettierd or prettier_d_slim +        exe = "", +        args = {}, +      }, +      -- @usage can be {"eslint"} or {"eslint_d"}      }, +    linters = {},      lsp = {        provider = "tsserver",        setup = { @@ -903,19 +1027,21 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    typescriptreact = { -    -- @usage can be prettier or eslint -    formatter = { -      exe = "prettier", -      args = {}, -    }, -    linters = { -      "eslint", +    formatters = { +      { +        -- @usage can be prettier or prettierd or prettier_d_slim +        exe = "", +        args = {}, +      },      }, +    -- @usage can be {"eslint"} or {"eslint_d"} +    linters = {},      lsp = {        provider = "tsserver",        setup = { @@ -925,15 +1051,19 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    vim = { -    formatter = { -      exe = "", -      args = {}, +    formatters = { +      { +        exe = "", +        args = {}, +      },      }, +    -- @usage can be {"vint"}      linters = { "" },      lsp = {        provider = "vimls", @@ -943,15 +1073,20 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    vue = { -    formatter = { -      exe = "prettier", -      args = {}, +    formatters = { +      { +        -- @usage can be prettier or prettierd or prettier_d_slim +        exe = "", +        args = {}, +      },      }, +    -- @usage can be {"eslint"} or {"eslint_d"}      linters = {},      lsp = {        provider = "vuels", @@ -960,14 +1095,18 @@ lvim.lang = {            DATA_PATH .. "/lspinstall/vue/node_modules/.bin/vls",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    yaml = { -    formatter = { -      exe = "prettier", -      args = {}, +    formatters = { +      { +        -- @usage can be prettier or prettierd +        exe = "", +        args = {}, +      },      },      linters = {},      lsp = { @@ -978,16 +1117,17 @@ lvim.lang = {            "--stdio",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      },    },    zig = { -    formatter = { +    formatters = { {        exe = "",        args = {},        stdin = false, -    }, +    } },      linters = {},      lsp = {        provider = "zls", @@ -996,6 +1136,7 @@ lvim.lang = {            "zls",          },          on_attach = common_on_attach, +        on_init = common_on_init,          capabilities = common_capabilities,        },      }, diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua index 62c42fd8..67007e81 100644 --- a/lua/lsp/init.lua +++ b/lua/lsp/init.lua @@ -1,55 +1,79 @@ -local utils = require "utils" -local service = require "lsp.service" -local null_ls = require "lsp.null-ls"  local M = {} - +local u = require "utils"  function M.config()    require("lsp.kind").setup()    require("lsp.handlers").setup()    require("lsp.signs").setup() -  require("lsp.keybinds").setup()  end -function M.setup(lang) -  local lang_server = lvim.lang[lang].lsp -  local provider = lang_server.provider -  if utils.check_lsp_client_active(provider) then -    return +local function lsp_highlight_document(client) +  if lvim.lsp.document_highlight == false then +    return -- we don't need further +  end +  -- Set autocommands conditional on server_capabilities +  if client.resolved_capabilities.document_highlight then +    vim.api.nvim_exec( +      [[ +      hi LspReferenceRead cterm=bold ctermbg=red guibg=#464646 +      hi LspReferenceText cterm=bold ctermbg=red guibg=#464646 +      hi LspReferenceWrite cterm=bold ctermbg=red guibg=#464646 +      augroup lsp_document_highlight +        autocmd! * <buffer> +        autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight() +        autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references() +      augroup END +    ]], +      false +    )    end +end -  local overrides = lvim.lsp.override +local function formatter_handler(client) +  local buffer_filetype = vim.bo.filetype +  local ext_provider = lvim.lang[buffer_filetype].formatter.exe -  if utils.is_table(overrides) then -    if utils.has_value(overrides, lang) then -      return -    end +  if ext_provider then +    client.resolved_capabilities.document_formatting = false +    u.lvim_log( +      string.format("Overriding [%s] formatting if exists, Using provider [%s] instead", client.name, ext_provider) +    )    end +end -  if utils.is_string(overrides) then -    if overrides == lang then -      return -    end +function M.common_capabilities() +  local capabilities = vim.lsp.protocol.make_client_capabilities() +  capabilities.textDocument.completion.completionItem.snippetSupport = true +  capabilities.textDocument.completion.completionItem.resolveSupport = { +    properties = { +      "documentation", +      "detail", +      "additionalTextEdits", +    }, +  } +  return capabilities +end + +function M.common_on_init(client, bufnr) +  if lvim.lsp.on_init_callback then +    lvim.lsp.on_init_callback(client, bufnr) +    return    end -  local sources = null_ls.setup(lang) - -  for _, source in pairs(sources) do -    local method = source.method -    local format_method = "NULL_LS_FORMATTING" - -    if utils.is_table(method) then -      if utils.has_value(method, format_method) then -        lang_server.setup.on_attach = service.no_formatter_on_attach -      end -    end - -    if utils.is_string(method) then -      if method == format_method then -        lang_server.setup.on_attach = service.no_formatter_on_attach -      end -    end +  formatter_handler(client) +end + +function M.common_on_attach(client, bufnr) +  if lvim.lsp.on_attach_callback then +    lvim.lsp.on_attach_callback(client, bufnr)    end +  lsp_highlight_document(client) +  require("lsp.keybinds").setup() +  require("lsp.null-ls").setup(vim.bo.filetype) +end -  if provider == "" or provider == nil then +function M.setup(lang) +  local lang_server = lvim.lang[lang].lsp +  local provider = lang_server.provider +  if require("utils").check_lsp_client_active(provider) then      return    end diff --git a/lua/lsp/keybinds.lua b/lua/lsp/keybinds.lua index 820ebce9..cc0d4ec9 100644 --- a/lua/lsp/keybinds.lua +++ b/lua/lsp/keybinds.lua @@ -1,5 +1,70 @@  local M = {} +-- Taken from https://www.reddit.com/r/neovim/comments/gyb077/nvimlsp_peek_defination_javascript_ttserver/ +function M.preview_location(location, context, before_context) +  -- location may be LocationLink or Location (more useful for the former) +  context = context or 15 +  before_context = before_context or 0 +  local uri = location.targetUri or location.uri +  if uri == nil then +    return +  end +  local bufnr = vim.uri_to_bufnr(uri) +  if not vim.api.nvim_buf_is_loaded(bufnr) then +    vim.fn.bufload(bufnr) +  end + +  local range = location.targetRange or location.range +  local contents = vim.api.nvim_buf_get_lines( +    bufnr, +    range.start.line - before_context, +    range["end"].line + 1 + context, +    false +  ) +  local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype") +  return vim.lsp.util.open_floating_preview(contents, filetype, { border = lvim.lsp.popup_border }) +end + +function M.preview_location_callback(_, method, result) +  local context = 15 +  if result == nil or vim.tbl_isempty(result) then +    print("No location found: " .. method) +    return nil +  end +  if vim.tbl_islist(result) then +    M.floating_buf, M.floating_win = M.preview_location(result[1], context) +  else +    M.floating_buf, M.floating_win = M.preview_location(result, context) +  end +end + +function M.PeekDefinition() +  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then +    vim.api.nvim_set_current_win(M.floating_win) +  else +    local params = vim.lsp.util.make_position_params() +    return vim.lsp.buf_request(0, "textDocument/definition", params, M.preview_location_callback) +  end +end + +function M.PeekTypeDefinition() +  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then +    vim.api.nvim_set_current_win(M.floating_win) +  else +    local params = vim.lsp.util.make_position_params() +    return vim.lsp.buf_request(0, "textDocument/typeDefinition", params, M.preview_location_callback) +  end +end + +function M.PeekImplementation() +  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then +    vim.api.nvim_set_current_win(M.floating_win) +  else +    local params = vim.lsp.util.make_position_params() +    return vim.lsp.buf_request(0, "textDocument/implementation", params, M.preview_location_callback) +  end +end +  function M.setup()    if lvim.lsp.default_keybinds then      vim.cmd "nnoremap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>" @@ -13,7 +78,7 @@ function M.setup()        { noremap = true, silent = true }      ) -    vim.cmd "nnoremap <silent> gp <cmd>lua require'lsp.service'.PeekDefinition()<CR>" +    vim.cmd "nnoremap <silent> gp <cmd>lua require'lsp.keybinds'.PeekDefinition()<CR>"      vim.cmd "nnoremap <silent> K :lua vim.lsp.buf.hover()<CR>"      vim.cmd "nnoremap <silent> <C-p> :lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})<CR>"      vim.cmd "nnoremap <silent> <C-n> :lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})<CR>" diff --git a/lua/lsp/null-ls.lua b/lua/lsp/null-ls.lua index 6a31de26..d2222602 100644 --- a/lua/lsp/null-ls.lua +++ b/lua/lsp/null-ls.lua @@ -1,76 +1,79 @@  local M = {} +local u = require "utils" +local null_ls = require "null-ls" -local _, null_ls = pcall(require, "null-ls") -local utils = require "utils" -local sources = {} +local nodejs_local_providers = { "prettier", "prettierd", "prettier_d_slim", "eslint_d", "eslint" } -local local_executables = { "prettier", "prettierd", "prettier_d_slim", "eslint_d", "eslint" } +M.requested_providers = {} -local find_local_exe = function(exe) -  vim.cmd "let root_dir = FindRootDirectory()" -  local root_dir = vim.api.nvim_get_var "root_dir" -  local local_exe = root_dir .. "/node_modules/.bin/" .. exe -  return local_exe +local function is_nodejs_provider(provider) +  for _, local_provider in ipairs(nodejs_local_providers) do +    if local_provider == provider.exe then +      return true +    end +  end +  return false  end --- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/9b8458bd1648e84169a7e8638091ba15c2f20fc0/doc/BUILTINS.md#eslint -local get_normalized_exe = function(exe, type) -  if type == "diagnostics" and exe == "eslint_d" then -    return "eslint" +local function is_provider_found(provider) +  -- special case: fallback to "eslint" +  -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/9b8458bd1648e84169a7e8638091ba15c2f20fc0/doc/BUILTINS.md#eslint +  provider._opts.command = provider._opts.command == "eslint_d" and "eslint" or provider._opts.command + +  local retval = { is_local = false, path = nil } +  if vim.fn.executable(provider._opts.command) == 1 then +    return false, provider._opts.command    end -  return exe +  if is_nodejs_provider(provider) then +    vim.cmd "let root_dir = FindRootDirectory()" +    local root_dir = vim.api.nvim_get_var "root_dir" +    local local_provider_command = root_dir .. "/node_modules/.bin/" .. provider._opts.command +    if vim.fn.executable(local_provider_command) == 1 then +      retval.is_local = true +      retval.path = local_provider_command +    end +  end +  return retval.is_local, retval.path  end -local function setup_ls(exe, type) -  if utils.has_value(local_executables, exe) then -    local normalized_exe = get_normalized_exe(exe, type) -    local smart_executable = null_ls.builtins[type][normalized_exe] -    local local_executable = find_local_exe(exe) -    if vim.fn.executable(local_executable) == 1 then -      smart_executable._opts.command = local_executable -      table.insert(sources, smart_executable) -    else -      if vim.fn.executable(exe) == 1 then -        smart_executable._opts.command = exe -        table.insert(sources, smart_executable) -      end -    end -  else -    if null_ls.builtins[type][exe] and vim.fn.executable(null_ls.builtins[type][exe]._opts.command) then -      table.insert(sources, null_ls.builtins[type][exe]) -    end +local function validate_provider(provider) +  local is_local, provider_path = is_provider_found(provider) +  if not provider_path then +    u.lvim_log(string.format("Unable to find the path for: [%s]", provider)) +    return false    end -  null_ls.register { sources = sources } +  if is_local then +    provider._opts.command = provider_path +  end +  return true  end  -- TODO: for linters and formatters with spaces and '-' replace with '_' -local function setup(filetype, type) -  local executables = nil -  if type == "diagnostics" then -    executables = lvim.lang[filetype].linters +function M.setup(filetype) +  for _, formatter in pairs(lvim.lang[filetype].formatters) do +    local builtin_formatter = null_ls.builtins.formatting[formatter.exe] +    -- FIXME: why doesn't this work? +    -- builtin_formatter._opts.args = formatter.args or builtin_formatter._opts.args +    -- builtin_formatter._opts.to_stdin = formatter.stdin or builtin_formatter._opts.to_stdin +    table.insert(M.requested_providers, builtin_formatter) +    u.lvim_log(string.format("Using format provider: [%s]", formatter.exe))    end -  if type == "formatting" then -    executables = lvim.lang[filetype].formatter.exe + +  for _, linter in pairs(lvim.lang[filetype].linters) do +    local builtin_diagnoser = null_ls.builtins.diagnostics[linter.exe] +    -- FIXME: why doesn't this work? +    -- builtin_diagnoser._opts.args = linter.args or builtin_diagnoser._opts.args +    -- builtin_diagnoser._opts.to_stdin = linter.stdin or builtin_diagnoser._opts.to_stdin +    table.insert(M.requested_providers, builtin_diagnoser) +    u.lvim_log(string.format("Using linter provider: [%s]", linter.exe))    end -  if utils.is_table(executables) then -    for _, exe in pairs(executables) do -      if exe ~= "" then -        setup_ls(exe, type) -      end +  for idx, provider in pairs(M.requested_providers) do +    if not validate_provider(provider) then +      table.remove(M.requested_providers, idx)      end    end -  if utils.is_string(executables) and executables ~= "" then -    setup_ls(executables, type) -  end -end - --- TODO: return the formatter if one was registered, then turn off the builtin formatter -function M.setup(filetype) -  setup(filetype, "formatting") -  setup(filetype, "diagnostics") -  lvim.sources = sources -  return sources +  null_ls.register { sources = M.requested_providers }  end  return M diff --git a/lua/lsp/service.lua b/lua/lsp/service.lua deleted file mode 100644 index 0c49bacd..00000000 --- a/lua/lsp/service.lua +++ /dev/null @@ -1,122 +0,0 @@ -local M = {} - -local function lsp_highlight_document(client) -  if lvim.lsp.document_highlight == false then -    return -- we don't need further -  end -  -- Set autocommands conditional on server_capabilities -  if client.resolved_capabilities.document_highlight then -    vim.api.nvim_exec( -      [[ -      hi LspReferenceRead cterm=bold ctermbg=red guibg=#464646 -      hi LspReferenceText cterm=bold ctermbg=red guibg=#464646 -      hi LspReferenceWrite cterm=bold ctermbg=red guibg=#464646 -      augroup lsp_document_highlight -        autocmd! * <buffer> -        autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight() -        autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references() -      augroup END -    ]], -      false -    ) -  end -end - -function M.lsp_highlight_document(client) -  lsp_highlight_document(client) -end - --- Taken from https://www.reddit.com/r/neovim/comments/gyb077/nvimlsp_peek_defination_javascript_ttserver/ -function M.preview_location(location, context, before_context) -  -- location may be LocationLink or Location (more useful for the former) -  context = context or 15 -  before_context = before_context or 0 -  local uri = location.targetUri or location.uri -  if uri == nil then -    return -  end -  local bufnr = vim.uri_to_bufnr(uri) -  if not vim.api.nvim_buf_is_loaded(bufnr) then -    vim.fn.bufload(bufnr) -  end - -  local range = location.targetRange or location.range -  local contents = vim.api.nvim_buf_get_lines( -    bufnr, -    range.start.line - before_context, -    range["end"].line + 1 + context, -    false -  ) -  local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype") -  return vim.lsp.util.open_floating_preview(contents, filetype, { border = lvim.lsp.popup_border }) -end - -function M.preview_location_callback(_, method, result) -  local context = 15 -  if result == nil or vim.tbl_isempty(result) then -    print("No location found: " .. method) -    return nil -  end -  if vim.tbl_islist(result) then -    M.floating_buf, M.floating_win = M.preview_location(result[1], context) -  else -    M.floating_buf, M.floating_win = M.preview_location(result, context) -  end -end - -function M.PeekDefinition() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/definition", params, M.preview_location_callback) -  end -end - -function M.PeekTypeDefinition() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/typeDefinition", params, M.preview_location_callback) -  end -end - -function M.PeekImplementation() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/implementation", params, M.preview_location_callback) -  end -end - -function M.common_on_attach(client, bufnr) -  if lvim.lsp.on_attach_callback then -    lvim.lsp.on_attach_callback(client, bufnr) -  end -  lsp_highlight_document(client) -end - -function M.no_formatter_on_attach(client, bufnr) -  if lvim.lsp.on_attach_callback then -    lvim.lsp.on_attach_callback(client, bufnr) -  end -  lsp_highlight_document(client) -  client.resolved_capabilities.document_formatting = false -end - -function M.common_capabilities() -  local capabilities = vim.lsp.protocol.make_client_capabilities() -  capabilities.textDocument.completion.completionItem.snippetSupport = true -  capabilities.textDocument.completion.completionItem.resolveSupport = { -    properties = { -      "documentation", -      "detail", -      "additionalTextEdits", -    }, -  } -  return capabilities -end - -return M diff --git a/lua/utils/init.lua b/lua/utils/init.lua index fe1e09aa..a41bfc10 100644 --- a/lua/utils/init.lua +++ b/lua/utils/init.lua @@ -162,6 +162,12 @@ function utils.gsub_args(args)    return args  end +function utils.lvim_log(msg) +  if lvim.debug then +    vim.notify(msg, vim.log.levels.DEBUG) +  end +end +  return utils  -- TODO: find a new home for these autocommands | 
