From 740e27ec856cc688f0ecf0ffe2b55b26ce771407 Mon Sep 17 00:00:00 2001
From: Gustaf Rydholm <gustaf.rydholm@gmail.com>
Date: Wed, 7 Jul 2021 14:27:30 +0200
Subject: Add language support for linting and diagnostics

---
 .config/nvim/ftdetect/zig.lua             |  4 ++
 .config/nvim/ftplugin/c.lua               | 20 +++++++
 .config/nvim/ftplugin/dart.lua            | 11 ++++
 .config/nvim/ftplugin/dockerfile.lua      |  6 ++
 .config/nvim/ftplugin/elixir.lua          | 10 ++++
 .config/nvim/ftplugin/go.lua              | 12 ++++
 .config/nvim/ftplugin/graphql.lua         |  2 +
 .config/nvim/ftplugin/html.lua            | 14 +++++
 .config/nvim/ftplugin/javascript.lua      | 38 +++++++++++++
 .config/nvim/ftplugin/javascriptreact.lua | 38 +++++++++++++
 .config/nvim/ftplugin/json.lua            | 17 ++++++
 .config/nvim/ftplugin/kotlin.lua          | 34 +++++++++++
 .config/nvim/ftplugin/lua.lua             | 44 +++++++++++++++
 .config/nvim/ftplugin/python.lua          | 65 +++++++++++++++++++++
 .config/nvim/ftplugin/rust.lua            | 93 +++++++++++++++++++++++++++++++
 .config/nvim/ftplugin/sh.lua              | 33 +++++++++++
 .config/nvim/ftplugin/tex.lua             |  4 ++
 .config/nvim/ftplugin/vim.lua             |  5 ++
 .config/nvim/ftplugin/yaml.lua            |  6 ++
 .config/nvim/ftplugin/zig.lua             | 14 +++++
 .config/nvim/ftplugin/zsh.lua             | 38 +++++++++++++
 21 files changed, 508 insertions(+)
 create mode 100644 .config/nvim/ftdetect/zig.lua
 create mode 100644 .config/nvim/ftplugin/c.lua
 create mode 100644 .config/nvim/ftplugin/dart.lua
 create mode 100644 .config/nvim/ftplugin/dockerfile.lua
 create mode 100644 .config/nvim/ftplugin/elixir.lua
 create mode 100644 .config/nvim/ftplugin/go.lua
 create mode 100644 .config/nvim/ftplugin/graphql.lua
 create mode 100644 .config/nvim/ftplugin/html.lua
 create mode 100644 .config/nvim/ftplugin/javascript.lua
 create mode 100644 .config/nvim/ftplugin/javascriptreact.lua
 create mode 100644 .config/nvim/ftplugin/json.lua
 create mode 100644 .config/nvim/ftplugin/kotlin.lua
 create mode 100644 .config/nvim/ftplugin/lua.lua
 create mode 100644 .config/nvim/ftplugin/python.lua
 create mode 100644 .config/nvim/ftplugin/rust.lua
 create mode 100644 .config/nvim/ftplugin/sh.lua
 create mode 100644 .config/nvim/ftplugin/tex.lua
 create mode 100644 .config/nvim/ftplugin/vim.lua
 create mode 100644 .config/nvim/ftplugin/yaml.lua
 create mode 100644 .config/nvim/ftplugin/zig.lua
 create mode 100644 .config/nvim/ftplugin/zsh.lua

diff --git a/.config/nvim/ftdetect/zig.lua b/.config/nvim/ftdetect/zig.lua
new file mode 100644
index 0000000..7edf1f6
--- /dev/null
+++ b/.config/nvim/ftdetect/zig.lua
@@ -0,0 +1,4 @@
+vim.cmd [[
+  au BufRead,BufNewFile *.zig set filetype=zig
+  au BufRead,BufNewFile *.zir set filetype=zir
+]]
diff --git a/.config/nvim/ftplugin/c.lua b/.config/nvim/ftplugin/c.lua
new file mode 100644
index 0000000..7443cab
--- /dev/null
+++ b/.config/nvim/ftplugin/c.lua
@@ -0,0 +1,20 @@
+local clangd_flags = { "--background-index" }
+
+if O.lang.clang.cross_file_rename then
+  table.insert(clangd_flags, "--cross-file-rename")
+end
+
+table.insert(clangd_flags, "--header-insertion=" .. O.lang.clang.header_insertion)
+
+require("lspconfig").clangd.setup {
+  cmd = { DATA_PATH .. "/lspinstall/cpp/clangd/bin/clangd", unpack(clangd_flags) },
+  on_attach = require("lsp").common_on_attach,
+  handlers = {
+    ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+      virtual_text = O.lang.clang.diagnostics.virtual_text,
+      signs = O.lang.clang.diagnostics.signs,
+      underline = O.lang.clang.diagnostics.underline,
+      update_in_insert = true,
+    }),
+  },
+}
diff --git a/.config/nvim/ftplugin/dart.lua b/.config/nvim/ftplugin/dart.lua
new file mode 100644
index 0000000..419d040
--- /dev/null
+++ b/.config/nvim/ftplugin/dart.lua
@@ -0,0 +1,11 @@
+require("lspconfig").dartls.setup {
+  cmd = { "dart", O.lang.dart.sdk_path, "--lsp" },
+  on_attach = require("lsp").common_on_attach,
+  init_options = {
+    closingLabels = false,
+    flutterOutline = false,
+    onlyAnalyzeProjectsWithOpenFiles = false,
+    outline = false,
+    suggestFromUnimportedLibraries = true,
+  },
+}
diff --git a/.config/nvim/ftplugin/dockerfile.lua b/.config/nvim/ftplugin/dockerfile.lua
new file mode 100644
index 0000000..37b4317
--- /dev/null
+++ b/.config/nvim/ftplugin/dockerfile.lua
@@ -0,0 +1,6 @@
+-- npm install -g dockerfile-language-server-nodejs
+require("lspconfig").dockerls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/dockerfile/node_modules/.bin/docker-langserver", "--stdio" },
+  on_attach = require("lsp").common_on_attach,
+  root_dir = vim.loop.cwd,
+}
diff --git a/.config/nvim/ftplugin/elixir.lua b/.config/nvim/ftplugin/elixir.lua
new file mode 100644
index 0000000..fbb5b29
--- /dev/null
+++ b/.config/nvim/ftplugin/elixir.lua
@@ -0,0 +1,10 @@
+require("lspconfig").elixirls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/elixir/elixir-ls/language_server.sh" },
+}
+
+-- needed for the LSP to recognize elixir files (alternativly just use elixir-editors/vim-elixir)
+-- vim.cmd([[
+--   au BufRead,BufNewFile *.ex,*.exs set filetype=elixir
+--   au BufRead,BufNewFile *.eex,*.leex,*.sface set filetype=eelixir
+--   au BufRead,BufNewFile mix.lock set filetype=elixir
+-- ]])
diff --git a/.config/nvim/ftplugin/go.lua b/.config/nvim/ftplugin/go.lua
new file mode 100644
index 0000000..56b9cac
--- /dev/null
+++ b/.config/nvim/ftplugin/go.lua
@@ -0,0 +1,12 @@
+require("lspconfig").gopls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/go/gopls" },
+  settings = { gopls = { analyses = { unusedparams = true }, staticcheck = true } },
+  root_dir = require("lspconfig").util.root_pattern(".git", "go.mod"),
+  init_options = { usePlaceholders = true, completeUnimported = true },
+  on_attach = require("lsp").common_on_attach,
+}
+
+vim.opt_local.tabstop = 4
+vim.opt_local.shiftwidth = 4
+vim.opt_local.softtabstop = 4
+vim.opt_local.expandtab = false
diff --git a/.config/nvim/ftplugin/graphql.lua b/.config/nvim/ftplugin/graphql.lua
new file mode 100644
index 0000000..df3dce9
--- /dev/null
+++ b/.config/nvim/ftplugin/graphql.lua
@@ -0,0 +1,2 @@
+-- npm install -g graphql-language-service-cli
+require("lspconfig").graphql.setup { on_attach = require("lsp").common_on_attach }
diff --git a/.config/nvim/ftplugin/html.lua b/.config/nvim/ftplugin/html.lua
new file mode 100644
index 0000000..312301b
--- /dev/null
+++ b/.config/nvim/ftplugin/html.lua
@@ -0,0 +1,14 @@
+-- npm install -g vscode-html-languageserver-bin
+local capabilities = vim.lsp.protocol.make_client_capabilities()
+capabilities.textDocument.completion.completionItem.snippetSupport = true
+
+require("lspconfig").html.setup {
+  cmd = {
+    "node",
+    DATA_PATH .. "/lspinstall/html/vscode-html/html-language-features/server/dist/node/htmlServerMain.js",
+    "--stdio",
+  },
+  on_attach = require("lsp").common_on_attach,
+  capabilities = capabilities,
+}
+vim.cmd "setl ts=2 sw=2"
diff --git a/.config/nvim/ftplugin/javascript.lua b/.config/nvim/ftplugin/javascript.lua
new file mode 100644
index 0000000..ab37036
--- /dev/null
+++ b/.config/nvim/ftplugin/javascript.lua
@@ -0,0 +1,38 @@
+-- npm install -g typescript typescript-language-server
+-- require'snippets'.use_suggested_mappings()
+-- local capabilities = vim.lsp.protocol.make_client_capabilities()
+-- capabilities.textDocument.completion.completionItem.snippetSupport = true;
+-- local on_attach_common = function(client)
+-- print("LSP Initialized")
+-- require'completion'.on_attach(client)
+-- require'illuminate'.on_attach(client)
+-- end
+require("lspconfig").tsserver.setup {
+  cmd = {
+    DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server",
+    "--stdio",
+  },
+  filetypes = {
+    "javascript",
+    "javascriptreact",
+    "javascript.jsx",
+    "typescript",
+    "typescriptreact",
+    "typescript.tsx",
+  },
+  on_attach = require("lsp").tsserver_on_attach,
+  -- This makes sure tsserver is not used for formatting (I prefer prettier)
+  -- on_attach = require'lsp'.common_on_attach,
+  root_dir = require("lspconfig/util").root_pattern("package.json", "tsconfig.json", "jsconfig.json", ".git"),
+  settings = { documentFormatting = false },
+  handlers = {
+    ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+      virtual_text = O.lang.tsserver.diagnostics.virtual_text,
+      signs = O.lang.tsserver.diagnostics.signs,
+      underline = O.lang.tsserver.diagnostics.underline,
+      update_in_insert = true,
+    }),
+  },
+}
+require("lsp.ts-fmt-lint").setup()
+vim.cmd "setl ts=2 sw=2"
diff --git a/.config/nvim/ftplugin/javascriptreact.lua b/.config/nvim/ftplugin/javascriptreact.lua
new file mode 100644
index 0000000..ab37036
--- /dev/null
+++ b/.config/nvim/ftplugin/javascriptreact.lua
@@ -0,0 +1,38 @@
+-- npm install -g typescript typescript-language-server
+-- require'snippets'.use_suggested_mappings()
+-- local capabilities = vim.lsp.protocol.make_client_capabilities()
+-- capabilities.textDocument.completion.completionItem.snippetSupport = true;
+-- local on_attach_common = function(client)
+-- print("LSP Initialized")
+-- require'completion'.on_attach(client)
+-- require'illuminate'.on_attach(client)
+-- end
+require("lspconfig").tsserver.setup {
+  cmd = {
+    DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server",
+    "--stdio",
+  },
+  filetypes = {
+    "javascript",
+    "javascriptreact",
+    "javascript.jsx",
+    "typescript",
+    "typescriptreact",
+    "typescript.tsx",
+  },
+  on_attach = require("lsp").tsserver_on_attach,
+  -- This makes sure tsserver is not used for formatting (I prefer prettier)
+  -- on_attach = require'lsp'.common_on_attach,
+  root_dir = require("lspconfig/util").root_pattern("package.json", "tsconfig.json", "jsconfig.json", ".git"),
+  settings = { documentFormatting = false },
+  handlers = {
+    ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+      virtual_text = O.lang.tsserver.diagnostics.virtual_text,
+      signs = O.lang.tsserver.diagnostics.signs,
+      underline = O.lang.tsserver.diagnostics.underline,
+      update_in_insert = true,
+    }),
+  },
+}
+require("lsp.ts-fmt-lint").setup()
+vim.cmd "setl ts=2 sw=2"
diff --git a/.config/nvim/ftplugin/json.lua b/.config/nvim/ftplugin/json.lua
new file mode 100644
index 0000000..29a3096
--- /dev/null
+++ b/.config/nvim/ftplugin/json.lua
@@ -0,0 +1,17 @@
+-- npm install -g vscode-json-languageserver
+require("lspconfig").jsonls.setup {
+  cmd = {
+    "node",
+    DATA_PATH .. "/lspinstall/json/vscode-json/json-language-features/server/dist/node/jsonServerMain.js",
+    "--stdio",
+  },
+  on_attach = require("lsp").common_on_attach,
+
+  commands = {
+    Format = {
+      function()
+        vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 })
+      end,
+    },
+  },
+}
diff --git a/.config/nvim/ftplugin/kotlin.lua b/.config/nvim/ftplugin/kotlin.lua
new file mode 100644
index 0000000..dbd800b
--- /dev/null
+++ b/.config/nvim/ftplugin/kotlin.lua
@@ -0,0 +1,34 @@
+--- 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 bin_name = DATA_PATH .. "/lspinstall/kotlin/server/bin/kotlin-language-server"
+if vim.fn.has "win32" == 1 then
+  bin_name = bin_name .. ".bat"
+end
+
+local root_files = {
+  "settings.gradle", -- Gradle (multi-project)
+  "settings.gradle.kts", -- Gradle (multi-project)
+  "build.xml", -- Ant
+  "pom.xml", -- Maven
+}
+
+local fallback_root_files = {
+  "build.gradle", -- Gradle
+  "build.gradle.kts", -- Gradle
+}
+
+require("lspconfig").kotlin_language_server.setup {
+  cmd = { bin_name },
+  on_attach = require("lsp").common_on_attach,
+  root_dir = function(fname)
+    return util.root_pattern(unpack(root_files))(fname) or util.root_pattern(unpack(fallback_root_files))(fname)
+  end,
+}
diff --git a/.config/nvim/ftplugin/lua.lua b/.config/nvim/ftplugin/lua.lua
new file mode 100644
index 0000000..3eec445
--- /dev/null
+++ b/.config/nvim/ftplugin/lua.lua
@@ -0,0 +1,44 @@
+-- https://github.com/sumneko/lua-language-server/wiki/Build-and-Run-(Standalone)
+local sumneko_root_path = DATA_PATH .. "/lspinstall/lua"
+local sumneko_binary = sumneko_root_path .. "/sumneko-lua-language-server"
+
+require("lspconfig").sumneko_lua.setup {
+  cmd = { sumneko_binary, "-E", sumneko_root_path .. "/main.lua" },
+  on_attach = require("cfg.lsp").common_on_attach,
+  settings = {
+    Lua = {
+      runtime = {
+        -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
+        version = "LuaJIT",
+        -- Setup your lua path
+        path = vim.split(package.path, ";"),
+      },
+      diagnostics = {
+        -- Get the language server to recognize the `vim` global
+        globals = { "vim" },
+      },
+      workspace = {
+        -- Make the server aware of Neovim runtime files
+        library = {
+          [vim.fn.expand "$VIMRUNTIME/lua"] = true,
+          [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true,
+        },
+        maxPreload = 100000,
+        preloadFileSize = 1000,
+      },
+    },
+  },
+}
+if O.lang.lua.autoformat then
+  require("cfg.utils").define_augroups {
+    _lua_autoformat = {
+      {
+        "BufWritePre",
+        "*.lua",
+        "lua vim.lsp.buf.formatting_sync(nil, 1000)",
+      },
+    },
+  }
+end
+
+vim.cmd "setl ts=2 sw=2"
diff --git a/.config/nvim/ftplugin/python.lua b/.config/nvim/ftplugin/python.lua
new file mode 100644
index 0000000..09eb8d7
--- /dev/null
+++ b/.config/nvim/ftplugin/python.lua
@@ -0,0 +1,65 @@
+local python_arguments = {}
+
+-- TODO replace with path argument
+local flake8 = {
+  LintCommand = "flake8 --ignore=E501 --stdin-display-name ${INPUT} -",
+  lintStdin = true,
+  lintFormats = { "%f:%l:%c: %m" },
+}
+
+local isort = { formatCommand = "isort --quiet -", formatStdin = true }
+
+local yapf = { formatCommand = "yapf --quiet", formatStdin = true }
+local black = { formatCommand = "black --quiet -", formatStdin = true }
+
+if O.lang.python.linter == "flake8" then
+  table.insert(python_arguments, flake8)
+end
+
+if O.lang.python.isort then
+  table.insert(python_arguments, isort)
+end
+
+require("lspconfig").efm.setup {
+  -- init_options = {initializationOptions},
+  cmd = { DATA_PATH .. "/lspinstall/efm/efm-langserver" },
+  init_options = { documentFormatting = true, codeAction = false },
+  filetypes = { "python" },
+  settings = {
+    rootMarkers = { ".git/", "requirements.txt" },
+    languages = {
+      python = python_arguments,
+    },
+  },
+}
+
+-- npm i -g pyright
+require("lspconfig").pyright.setup {
+  cmd = {
+    DATA_PATH .. "/lspinstall/python/node_modules/.bin/pyright-langserver",
+    "--stdio",
+  },
+  on_attach = require("cfg.lsp").common_on_attach,
+  handlers = {
+    ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+      virtual_text = O.lang.python.diagnostics.virtual_text,
+      signs = O.lang.python.diagnostics.signs,
+      underline = O.lang.python.diagnostics.underline,
+      update_in_insert = true,
+    }),
+  },
+  settings = {
+    python = {
+      analysis = {
+        typeCheckingMode = O.lang.python.analysis.type_checking,
+        autoSearchPaths = O.lang.python.analysis.auto_search_paths,
+        useLibraryCodeForTypes = O.lang.python.analysis.use_library_code_types,
+      },
+    },
+  },
+}
+
+if O.plugin.debug.active and O.plugin.dap_install.active then
+  local dap_install = require("dap-install")
+  dap_install.config("python_dbg", {})
+end
diff --git a/.config/nvim/ftplugin/rust.lua b/.config/nvim/ftplugin/rust.lua
new file mode 100644
index 0000000..349e7ce
--- /dev/null
+++ b/.config/nvim/ftplugin/rust.lua
@@ -0,0 +1,93 @@
+if O.lang.rust.rust_tools.active then
+  local opts = {
+    tools = { -- rust-tools options
+      -- automatically set inlay hints (type hints)
+      -- There is an issue due to which the hints are not applied on the first
+      -- opened file. For now, write to the file to trigger a reapplication of
+      -- the hints or just run :RustSetInlayHints.
+      -- default: true
+      autoSetHints = true,
+
+      -- whether to show hover actions inside the hover window
+      -- this overrides the default hover handler
+      -- default: true
+      hover_with_actions = true,
+
+      runnables = {
+        -- whether to use telescope for selection menu or not
+        -- default: true
+        use_telescope = true,
+
+        -- rest of the opts are forwarded to telescope
+      },
+
+      inlay_hints = {
+        -- wheter to show parameter hints with the inlay hints or not
+        -- default: true
+        show_parameter_hints = true,
+
+        -- prefix for parameter hints
+        -- default: "<-"
+        parameter_hints_prefix = "<-",
+
+        -- prefix for all the other hints (type, chaining)
+        -- default: "=>"
+        other_hints_prefix = "=>",
+
+        -- whether to align to the lenght of the longest line in the file
+        max_len_align = false,
+
+        -- padding from the left if max_len_align is true
+        max_len_align_padding = 1,
+
+        -- whether to align to the extreme right or not
+        right_align = false,
+
+        -- padding from the right if right_align is true
+        right_align_padding = 7,
+      },
+
+      hover_actions = {
+        -- the border that is used for the hover window
+        -- see vim.api.nvim_open_win()
+        border = {
+          { "╭", "FloatBorder" },
+          { "─", "FloatBorder" },
+          { "╮", "FloatBorder" },
+          { "│", "FloatBorder" },
+          { "╯", "FloatBorder" },
+          { "─", "FloatBorder" },
+          { "╰", "FloatBorder" },
+          { "│", "FloatBorder" },
+        },
+      },
+    },
+
+    -- all the opts to send to nvim-lspconfig
+    -- these override the defaults set by rust-tools.nvim
+    -- see https://github.com/neovim/nvim-lspconfig/blob/master/CONFIG.md#rust_analyzer
+    server = {
+      cmd = { DATA_PATH .. "/lspinstall/rust/rust-analyzer" },
+      on_attach = require("cfg.lsp").common_on_attach,
+    }, -- rust-analyser options
+  }
+  require("rust-tools").setup(opts)
+else
+  require("lspconfig").rust_analyzer.setup {
+    cmd = { DATA_PATH .. "/lspinstall/rust/rust-analyzer" },
+    on_attach = require("lsp").common_on_attach,
+    filetypes = { "rust" },
+    root_dir = require("lspconfig.util").root_pattern("Cargo.toml", "rust-project.json"),
+  }
+end
+
+-- TODO fix these mappings
+vim.api.nvim_exec(
+  [[
+    autocmd Filetype rust nnoremap <leader>lm <Cmd>RustExpandMacro<CR>
+    autocmd Filetype rust nnoremap <leader>lH <Cmd>RustToggleInlayHints<CR>
+    autocmd Filetype rust nnoremap <leader>le <Cmd>RustRunnables<CR>
+    autocmd Filetype rust nnoremap <leader>lh <Cmd>RustHoverActions<CR>
+    ]],
+  true
+)
diff --git a/.config/nvim/ftplugin/sh.lua b/.config/nvim/ftplugin/sh.lua
new file mode 100644
index 0000000..e5f0a06
--- /dev/null
+++ b/.config/nvim/ftplugin/sh.lua
@@ -0,0 +1,33 @@
+-- npm i -g bash-language-server
+require("lspconfig").bashls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/bash/node_modules/.bin/bash-language-server", "start" },
+  on_attach = require("cfg.lsp").common_on_attach,
+  filetypes = { "sh", "zsh" },
+}
+
+-- sh
+local sh_arguments = {}
+
+local shfmt = { formatCommand = "shfmt -ci -s -bn", formatStdin = true }
+
+local shellcheck = {
+  LintCommand = "shellcheck -f gcc -x",
+  lintFormats = { "%f:%l:%c: %trror: %m", "%f:%l:%c: %tarning: %m", "%f:%l:%c: %tote: %m" },
+}
+
+if O.lang.sh.linter == "shellcheck" then
+  table.insert(sh_arguments, shellcheck)
+end
+
+require("lspconfig").efm.setup {
+  -- init_options = {initializationOptions},
+  cmd = { DATA_PATH .. "/lspinstall/efm/efm-langserver" },
+  init_options = { documentFormatting = true, codeAction = false },
+  filetypes = { "sh" },
+  settings = {
+    rootMarkers = { ".git/" },
+    languages = {
+      sh = sh_arguments,
+    },
+  },
+}
diff --git a/.config/nvim/ftplugin/tex.lua b/.config/nvim/ftplugin/tex.lua
new file mode 100644
index 0000000..b15cb06
--- /dev/null
+++ b/.config/nvim/ftplugin/tex.lua
@@ -0,0 +1,4 @@
+require("lspconfig").texlab.setup {
+  cmd = { DATA_PATH .. "/lspinstall/latex/texlab" },
+  on_attach = require("cfg.lsp").common_on_attach,
+}
diff --git a/.config/nvim/ftplugin/vim.lua b/.config/nvim/ftplugin/vim.lua
new file mode 100644
index 0000000..9dbbe3a
--- /dev/null
+++ b/.config/nvim/ftplugin/vim.lua
@@ -0,0 +1,5 @@
+-- npm install -g vim-language-server
+require("lspconfig").vimls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/vim/node_modules/.bin/vim-language-server", "--stdio" },
+  on_attach = require("cfg.lsp").common_on_attach,
+}
diff --git a/.config/nvim/ftplugin/yaml.lua b/.config/nvim/ftplugin/yaml.lua
new file mode 100644
index 0000000..afb82fe
--- /dev/null
+++ b/.config/nvim/ftplugin/yaml.lua
@@ -0,0 +1,6 @@
+-- npm install -g yaml-language-server
+require("lspconfig").yamlls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/yaml/node_modules/.bin/yaml-language-server", "--stdio" },
+  on_attach = require("cfg.lsp").common_on_attach,
+}
+vim.cmd "setl ts=2 sw=2 ts=2 ai et"
diff --git a/.config/nvim/ftplugin/zig.lua b/.config/nvim/ftplugin/zig.lua
new file mode 100644
index 0000000..72ce8cb
--- /dev/null
+++ b/.config/nvim/ftplugin/zig.lua
@@ -0,0 +1,14 @@
+-- Because lspinstall don't support zig yet,
+-- So we need zls preset in global lib
+-- Further custom install zls in
+-- https://github.com/zigtools/zls/wiki/Downloading-and-Building-ZLS
+require("lspconfig").zls.setup {
+  root_dir = require("lspconfig").util.root_pattern(".git", "build.zig", "zls.json"),
+  on_attach = require("cfg.lsp").common_on_attach,
+}
+require("cfg.utils").define_augroups {
+  _zig_autoformat = {
+    { "BufEnter", "*.zig", ':lua vim.api.nvim_buf_set_option(0, "commentstring", "// %s")' },
+  },
+}
+vim.cmd "setl expandtab tabstop=8 softtabstop=4 shiftwidth=4"
diff --git a/.config/nvim/ftplugin/zsh.lua b/.config/nvim/ftplugin/zsh.lua
new file mode 100644
index 0000000..a00309a
--- /dev/null
+++ b/.config/nvim/ftplugin/zsh.lua
@@ -0,0 +1,38 @@
+-- npm i -g bash-language-server
+require("lspconfig").bashls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/bash/node_modules/.bin/bash-language-server", "start" },
+  on_attach = require("cfg.lsp").common_on_attach,
+  filetypes = { "sh", "zsh" },
+}
+
+-- npm i -g bash-language-server
+require("lspconfig").bashls.setup {
+  cmd = { DATA_PATH .. "/lspinstall/bash/node_modules/.bin/bash-language-server", "start" },
+  on_attach = require("cfg.lsp").common_on_attach,
+  filetypes = { "sh", "zsh" },
+}
+
+-- sh
+local sh_arguments = {}
+
+local shellcheck = {
+  LintCommand = "shellcheck -f gcc -x",
+  lintFormats = { "%f:%l:%c: %trror: %m", "%f:%l:%c: %tarning: %m", "%f:%l:%c: %tote: %m" },
+}
+
+if O.lang.sh.linter == "shellcheck" then
+  table.insert(sh_arguments, shellcheck)
+end
+
+require("lspconfig").efm.setup {
+  -- init_options = {initializationOptions},
+  cmd = { DATA_PATH .. "/lspinstall/efm/efm-langserver" },
+  init_options = { documentFormatting = true, codeAction = false },
+  filetypes = { "zsh" },
+  settings = {
+    rootMarkers = { ".git/" },
+    languages = {
+      sh = sh_arguments,
+    },
+  },
+}
-- 
cgit v1.2.3-70-g09d2