From 44440794623ab1db6f97fdba4bea77c2ac9c6c2b Mon Sep 17 00:00:00 2001 From: light7734 Date: Wed, 30 Apr 2025 12:58:30 +0330 Subject: [PATCH] update --- nvim/lazy-lock.json | 4 +- nvim/lsp/cssls.lua | 112 +++++++++++++++++ nvim/lsp/eslint.lua | 256 +++++++++++++++++++++++++++++++++++++++ nvim/lsp/svelte.lua | 93 ++++++++++++++ nvim/lsp/tailwindcss.lua | 192 +++++++++++++++++++++++++++++ nvim/lsp/ts_ls.lua | 149 +++++++++++++++++++++++ nvim/lua/_keymaps.lua | 7 ++ nvim/lua/_lsp.lua | 83 ++++++++++++- nvim/lua/_nvim_tree.lua | 10 +- zshrc.sh | 8 ++ 10 files changed, 906 insertions(+), 8 deletions(-) create mode 100644 nvim/lsp/cssls.lua create mode 100644 nvim/lsp/eslint.lua create mode 100644 nvim/lsp/svelte.lua create mode 100644 nvim/lsp/tailwindcss.lua create mode 100644 nvim/lsp/ts_ls.lua diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json index ac74023..fabfc2b 100644 --- a/nvim/lazy-lock.json +++ b/nvim/lazy-lock.json @@ -7,7 +7,7 @@ "cmp-nvim-lua": { "branch": "main", "commit": "f12408bdb54c39c23e67cab726264c10db33ada8" }, "cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" }, "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, - "gitsigns.nvim": { "branch": "main", "commit": "ee7e50dfbdf49e3acfa416fd3ad3abbdb658582c" }, + "gitsigns.nvim": { "branch": "main", "commit": "140ac646db125904e456e42ab8b538d28f9607d7" }, "gruvbox.nvim": { "branch": "main", "commit": "a933d8666dad9363dc6908ae72cfc832299c2f59" }, "indent-blankline.nvim": { "branch": "master", "commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba" }, "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, @@ -16,7 +16,7 @@ "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, "nvim-tree.lua": { "branch": "master", "commit": "be5b788f2dc1522c73fb7afad9092331c8aebe80" }, "nvim-treesitter": { "branch": "master", "commit": "684eeac91ed8e297685a97ef70031d19ac1de25a" }, - "nvim-web-devicons": { "branch": "master", "commit": "68f70df44652d310d2adedf181b174c33a693665" }, + "nvim-web-devicons": { "branch": "master", "commit": "50b5b06bff13a9b4eab946de7c7033649a6618a1" }, "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, "telescope-args.nvim": { "branch": "main", "commit": "995072920fae8e1bf31daed015114bd54617079a" }, "telescope.nvim": { "branch": "master", "commit": "a4ed82509cecc56df1c7138920a1aeaf246c0ac5" } diff --git a/nvim/lsp/cssls.lua b/nvim/lsp/cssls.lua new file mode 100644 index 0000000..6b7bf9f --- /dev/null +++ b/nvim/lsp/cssls.lua @@ -0,0 +1,112 @@ +local function lsp_highlight_document(client) + if client.server_capabilities.document_highlight then + vim.api.nvim_create_augroup("lsp_document_highlight", { clear = true }) + + vim.api.nvim_create_autocmd("CursorHold", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.document_highlight() + end, + }) + + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.clear_references() + end, + }) + end +end + +local function lsp_keymaps(bufnr) + local opts = { noremap = true, silent = true } + + vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "lua vim.lsp.buf.hover()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", "lua vim.lsp.buf.signature_help()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "lua vim.lsp.buf.references()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", 'lua vim.diagnostic.goto_prev({border="rounded"})', opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", 'lua vim.diagnostic.goto_next({border="rounded"})', opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "lr", "lua vim.lsp.buf.rename()", opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "q", "lua vim.diagnostic.setloclist()", opts) + + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "td", + "lua require 'telescope.builtin'.diagnostics()", + opts + ) + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "tr", + "lua require 'telescope.builtin'.lsp_references()", + opts + ) +end + +local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status_ok then + print("Failed to require cmp_nvim_lsp") + return +end + +local client_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = cmp_nvim_lsp.default_capabilities(client_capabilities) +capabilities.offsetEncoding = { "utf-8", "utf-16" } + +---@brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- `css-languageserver` can be installed via `npm`: +--- +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- Neovim does not currently include built-in snippets. `vscode-css-language-server` only provides completions when snippet support is enabled. To enable completion, install a snippet plugin and add the following override to your language client capabilities during setup. +--- +--- ```lua +--- --Enable (broadcasting) snippet capability for completion +--- local capabilities = vim.lsp.protocol.make_client_capabilities() +--- capabilities.textDocument.completion.completionItem.snippetSupport = true +--- +--- vim.lsp.config('cssls', { +--- capabilities = capabilities, +--- }) +--- ``` +return { + cmd = { 'vscode-css-language-server', '--stdio' }, + filetypes = { 'css', 'scss', 'less' }, + init_options = { provideFormatter = true }, -- needed to enable formatting capabilities + root_markers = { 'package.json', '.git' }, + settings = { + css = { validate = true }, + scss = { validate = true }, + less = { validate = true }, + }, + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + lsp_highlight_document(client) + + if client.supports_method("textDocument/formatting") then + vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + vim.lsp.buf.format() + end, + }) + end + end, +} diff --git a/nvim/lsp/eslint.lua b/nvim/lsp/eslint.lua new file mode 100644 index 0000000..864a9eb --- /dev/null +++ b/nvim/lsp/eslint.lua @@ -0,0 +1,256 @@ +local function lsp_highlight_document(client) + if client.server_capabilities.document_highlight then + vim.api.nvim_create_augroup("lsp_document_highlight", { clear = true }) + + vim.api.nvim_create_autocmd("CursorHold", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.document_highlight() + end, + }) + + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.clear_references() + end, + }) + end +end + +local function lsp_keymaps(bufnr) + local opts = { noremap = true, silent = true } + + vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "lua vim.lsp.buf.hover()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", "lua vim.lsp.buf.signature_help()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "lua vim.lsp.buf.references()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", 'lua vim.diagnostic.goto_prev({border="rounded"})', opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", 'lua vim.diagnostic.goto_next({border="rounded"})', opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "lr", "lua vim.lsp.buf.rename()", opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "q", "lua vim.diagnostic.setloclist()", opts) + + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "td", + "lua require 'telescope.builtin'.diagnostics()", + opts + ) + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "tr", + "lua require 'telescope.builtin'.lsp_references()", + opts + ) +end + +local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status_ok then + print("Failed to require cmp_nvim_lsp") + return +end + +local client_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = cmp_nvim_lsp.default_capabilities(client_capabilities) +capabilities.offsetEncoding = { "utf-8", "utf-16" } + +--- @brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- `vscode-eslint-language-server` is a linting engine for JavaScript / Typescript. +--- It can be installed via `npm`: +--- +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- `vscode-eslint-language-server` provides an `EslintFixAll` command that can be used to format a document on save: +--- ```lua +--- vim.lsp.config('eslint', { +--- --- ... +--- on_attach = function(client, bufnr) +--- vim.api.nvim_create_autocmd("BufWritePre", { +--- buffer = bufnr, +--- command = "EslintFixAll", +--- }) +--- end, +--- }) +--- ``` +--- +--- See [vscode-eslint](https://github.com/microsoft/vscode-eslint/blob/55871979d7af184bf09af491b6ea35ebd56822cf/server/src/eslintServer.ts#L216-L229) for configuration options. +--- +--- Messages handled in lspconfig: `eslint/openDoc`, `eslint/confirmESLintExecution`, `eslint/probeFailed`, `eslint/noLibrary` +--- +--- Additional messages you can handle: `eslint/noConfig` + +local lsp = vim.lsp + +return { + cmd = { 'vscode-eslint-language-server', '--stdio' }, + filetypes = { + 'javascript', + 'javascriptreact', + 'javascript.jsx', + 'typescript', + 'typescriptreact', + 'typescript.tsx', + 'vue', + 'svelte', + 'astro', + }, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + lsp_highlight_document(client) + + vim.api.nvim_buf_create_user_command(0, 'LspEslintFixAll', function() + local bufnr = vim.api.nvim_get_current_buf() + + client:exec_cmd({ + title = 'Fix all Eslint errors for current buffer', + command = 'eslint.applyAllFixes', + arguments = { + { + uri = vim.uri_from_bufnr(bufnr), + version = lsp.util.buf_versions[bufnr], + }, + }, + }, { bufnr = bufnr }) + end, {}) + + vim.api.nvim_create_autocmd("BufWritePre", { + buffer = bufnr, + command = "LspEslintFixAll", + }) + end, + -- https://eslint.org/docs/user-guide/configuring/configuration-files#configuration-file-formats + root_dir = function(bufnr, on_dir) + local root_file_patterns = { + '.eslintrc', + '.eslintrc.js', + '.eslintrc.cjs', + '.eslintrc.yaml', + '.eslintrc.yml', + '.eslintrc.json', + 'eslint.config.js', + 'eslint.config.mjs', + 'eslint.config.cjs', + 'eslint.config.ts', + 'eslint.config.mts', + 'eslint.config.cts', + '.git', + 'package.json', + 'package-lock.json', + '.prettierrc', + } + + local fname = vim.api.nvim_buf_get_name(bufnr) + local root_dir = vim.fs.dirname(vim.fs.find(root_file_patterns, { path = fname, upward = true })[1]) + on_dir(root_dir) + end, + -- Refer to https://github.com/Microsoft/vscode-eslint#settings-options for documentation. + settings = { + validate = 'on', + packageManager = nil, + useESLintClass = false, + experimental = { + useFlatConfig = false, + }, + codeActionOnSave = { + enable = false, + mode = 'all', + }, + format = true, + quiet = false, + onIgnoredFiles = 'off', + rulesCustomizations = {}, + run = 'onType', + problems = { + shortenToSingleLine = false, + }, + -- nodePath configures the directory in which the eslint server should start its node_modules resolution. + -- This path is relative to the workspace folder (root dir) of the server instance. + nodePath = '', + -- use the workspace folder location or the file location (if no workspace folder is open) as the working directory + workingDirectory = { mode = 'location' }, + codeAction = { + disableRuleComment = { + enable = true, + location = 'separateLine', + }, + showDocumentation = { + enable = true, + }, + }, + }, + before_init = function(_, config) + -- The "workspaceFolder" is a VSCode concept. It limits how far the + -- server will traverse the file system when locating the ESLint config + -- file (e.g., .eslintrc). + local root_dir = config.root_dir + + if root_dir then + config.settings = config.settings or {} + config.settings.workspaceFolder = { + uri = root_dir, + name = vim.fn.fnamemodify(root_dir, ':t'), + } + + -- Support flat config + local flat_config_files = { + 'eslint.config.js', + 'eslint.config.mjs', + 'eslint.config.cjs', + 'eslint.config.ts', + 'eslint.config.mts', + 'eslint.config.cts', + } + + for _, file in ipairs(flat_config_files) do + if vim.fn.filereadable(root_dir .. '/' .. file) == 1 then + config.settings.experimental = config.settings.experimental or {} + config.settings.experimental.useFlatConfig = true + break + end + end + + -- Support Yarn2 (PnP) projects + local pnp_cjs = root_dir .. '/.pnp.cjs' + local pnp_js = root_dir .. '/.pnp.js' + if vim.uv.fs_stat(pnp_cjs) or vim.uv.fs_stat(pnp_js) then + local cmd = config.cmd + config.cmd = vim.list_extend({ 'yarn', 'exec' }, cmd) + end + end + end, + handlers = { + ['eslint/openDoc'] = function(_, result) + if result then + vim.ui.open(result.url) + end + return {} + end, + ['eslint/confirmESLintExecution'] = function(_, result) + if not result then + return + end + return 4 -- approved + end, + ['eslint/probeFailed'] = function() + vim.notify('[lspconfig] ESLint probe failed.', vim.log.levels.WARN) + return {} + end, + ['eslint/noLibrary'] = function() + vim.notify('[lspconfig] Unable to find ESLint library.', vim.log.levels.WARN) + return {} + end, + }, +} diff --git a/nvim/lsp/svelte.lua b/nvim/lsp/svelte.lua new file mode 100644 index 0000000..70916ca --- /dev/null +++ b/nvim/lsp/svelte.lua @@ -0,0 +1,93 @@ +local function lsp_highlight_document(client) + if client.server_capabilities.document_highlight then + vim.api.nvim_create_augroup("lsp_document_highlight", { clear = true }) + + vim.api.nvim_create_autocmd("CursorHold", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.document_highlight() + end, + }) + + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.clear_references() + end, + }) + end +end + +local function lsp_keymaps(bufnr) + local opts = { noremap = true, silent = true } + + vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "lua vim.lsp.buf.hover()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", "lua vim.lsp.buf.signature_help()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "lua vim.lsp.buf.references()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", 'lua vim.diagnostic.goto_prev({border="rounded"})', opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", 'lua vim.diagnostic.goto_next({border="rounded"})', opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "lr", "lua vim.lsp.buf.rename()", opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "q", "lua vim.diagnostic.setloclist()", opts) + + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "td", + "lua require 'telescope.builtin'.diagnostics()", + opts + ) + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "tr", + "lua require 'telescope.builtin'.lsp_references()", + opts + ) +end + +local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status_ok then + print("Failed to require cmp_nvim_lsp") + return +end + +local client_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = cmp_nvim_lsp.default_capabilities(client_capabilities) +capabilities.offsetEncoding = { "utf-8", "utf-16" } + + +---@brief +--- +--- https://github.com/sveltejs/language-tools/tree/master/packages/language-server +--- +--- Note: assuming that [ts_ls](#ts_ls) is setup, full JavaScript/TypeScript support (find references, rename, etc of symbols in Svelte files when working in JS/TS files) requires per-project installation and configuration of [typescript-svelte-plugin](https://github.com/sveltejs/language-tools/tree/master/packages/typescript-plugin#usage). +--- +--- `svelte-language-server` can be installed via `npm`: +--- ```sh +--- npm install -g svelte-language-server +--- ``` + +return { + cmd = { 'svelteserver', '--stdio' }, + filetypes = { 'svelte' }, + root_markers = { 'package.json', '.git' }, + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + lsp_highlight_document(client) + + vim.api.nvim_buf_create_user_command(bufnr, 'LspMigrateToSvelte5', function() + client:exec_cmd({ + command = 'migrate_to_svelte_5', + arguments = { vim.uri_from_bufnr(bufnr) }, + }) + end, { desc = 'Migrate Component to Svelte 5 Syntax' }) + end, +} diff --git a/nvim/lsp/tailwindcss.lua b/nvim/lsp/tailwindcss.lua new file mode 100644 index 0000000..08723f8 --- /dev/null +++ b/nvim/lsp/tailwindcss.lua @@ -0,0 +1,192 @@ +local function lsp_highlight_document(client) + if client.server_capabilities.document_highlight then + vim.api.nvim_create_augroup("lsp_document_highlight", { clear = true }) + + vim.api.nvim_create_autocmd("CursorHold", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.document_highlight() + end, + }) + + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.clear_references() + end, + }) + end +end + +local function lsp_keymaps(bufnr) + local opts = { noremap = true, silent = true } + + vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "lua vim.lsp.buf.hover()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", "lua vim.lsp.buf.signature_help()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "lua vim.lsp.buf.references()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", 'lua vim.diagnostic.goto_prev({border="rounded"})', opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", 'lua vim.diagnostic.goto_next({border="rounded"})', opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "lr", "lua vim.lsp.buf.rename()", opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "q", "lua vim.diagnostic.setloclist()", opts) + + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "td", + "lua require 'telescope.builtin'.diagnostics()", + opts + ) + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "tr", + "lua require 'telescope.builtin'.lsp_references()", + opts + ) +end + +local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status_ok then + print("Failed to require cmp_nvim_lsp") + return +end + +local client_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = cmp_nvim_lsp.default_capabilities(client_capabilities) +capabilities.offsetEncoding = { "utf-8", "utf-16" } + +---@brief +--- https://github.com/tailwindlabs/tailwindcss-intellisense +--- +--- Tailwind CSS Language Server can be installed via npm: +--- +--- npm install -g @tailwindcss/language-server + +return { + cmd = { 'tailwindcss-language-server', '--stdio' }, + -- filetypes copied and adjusted from tailwindcss-intellisense + filetypes = { + -- html + 'aspnetcorerazor', + 'astro', + 'astro-markdown', + 'blade', + 'clojure', + 'django-html', + 'htmldjango', + 'edge', + 'eelixir', -- vim ft + 'elixir', + 'ejs', + 'erb', + 'eruby', -- vim ft + 'gohtml', + 'gohtmltmpl', + 'haml', + 'handlebars', + 'hbs', + 'html', + 'htmlangular', + 'html-eex', + 'heex', + 'jade', + 'leaf', + 'liquid', + 'markdown', + 'mdx', + 'mustache', + 'njk', + 'nunjucks', + 'php', + 'razor', + 'slim', + 'twig', + -- css + 'css', + 'less', + 'postcss', + 'sass', + 'scss', + 'stylus', + 'sugarss', + -- js + 'javascript', + 'javascriptreact', + 'reason', + 'rescript', + 'typescript', + 'typescriptreact', + -- mixed + 'vue', + 'svelte', + 'templ', + }, + settings = { + tailwindCSS = { + validate = true, + lint = { + cssConflict = 'warning', + invalidApply = 'error', + invalidScreen = 'error', + invalidVariant = 'error', + invalidConfigPath = 'error', + invalidTailwindDirective = 'error', + recommendedVariantOrder = 'warning', + }, + classAttributes = { + 'class', + 'className', + 'class:list', + 'classList', + 'ngClass', + }, + includeLanguages = { + eelixir = 'html-eex', + eruby = 'erb', + templ = 'html', + htmlangular = 'html', + }, + }, + }, + before_init = function(_, config) + if not config.settings then + config.settings = {} + end + if not config.settings.editor then + config.settings.editor = {} + end + if not config.settings.editor.tabSize then + config.settings.editor.tabSize = vim.lsp.util.get_effective_tabstop() + end + end, + workspace_required = true, + root_dir = function(bufnr, on_dir) + local root_files = { + 'tailwind.config.js', + 'tailwind.config.cjs', + 'tailwind.config.mjs', + 'tailwind.config.ts', + 'postcss.config.js', + 'postcss.config.cjs', + 'postcss.config.mjs', + 'postcss.config.ts', + 'package.json', + } + local fname = vim.api.nvim_buf_get_name(bufnr) + on_dir(vim.fs.dirname(vim.fs.find(root_files, { path = fname, upward = true })[1])) + end, + + capabilities = capabilities, + + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + lsp_highlight_document(client) + end, +} diff --git a/nvim/lsp/ts_ls.lua b/nvim/lsp/ts_ls.lua new file mode 100644 index 0000000..f29eaef --- /dev/null +++ b/nvim/lsp/ts_ls.lua @@ -0,0 +1,149 @@ +local function lsp_highlight_document(client) + if client.server_capabilities.document_highlight then + vim.api.nvim_create_augroup("lsp_document_highlight", { clear = true }) + + vim.api.nvim_create_autocmd("CursorHold", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.document_highlight() + end, + }) + + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = 0, + callback = function() + vim.lsp.buf.clear_references() + end, + }) + end +end + +local function lsp_keymaps(bufnr) + local opts = { noremap = true, silent = true } + + vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "K", "lua vim.lsp.buf.hover()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", "lua vim.lsp.buf.signature_help()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "lua vim.lsp.buf.references()", opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "[d", 'lua vim.diagnostic.goto_prev({border="rounded"})', opts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "]d", 'lua vim.diagnostic.goto_next({border="rounded"})', opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "lr", "lua vim.lsp.buf.rename()", opts) + + vim.api.nvim_buf_set_keymap(bufnr, "n", "q", "lua vim.diagnostic.setloclist()", opts) + + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "td", + "lua require 'telescope.builtin'.diagnostics()", + opts + ) + vim.api.nvim_buf_set_keymap( + bufnr, + "n", + "tr", + "lua require 'telescope.builtin'.lsp_references()", + opts + ) +end + +local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status_ok then + print("Failed to require cmp_nvim_lsp") + return +end + +local client_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = cmp_nvim_lsp.default_capabilities(client_capabilities) +capabilities.offsetEncoding = { "utf-8", "utf-16" } +---@brief +--- +--- https://github.com/typescript-language-server/typescript-language-server +--- +--- `ts_ls`, aka `typescript-language-server`, is a Language Server Protocol implementation for TypeScript wrapping `tsserver`. Note that `ts_ls` is not `tsserver`. +--- +--- `typescript-language-server` depends on `typescript`. Both packages can be installed via `npm`: +--- ```sh +--- npm install -g typescript typescript-language-server +--- ``` +--- +--- To configure typescript language server, add a +--- [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or +--- [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) to the root of your +--- project. +--- +--- Here's an example that disables type checking in JavaScript files. +--- +--- ```json +--- { +--- "compilerOptions": { +--- "module": "commonjs", +--- "target": "es6", +--- "checkJs": false +--- }, +--- "exclude": [ +--- "node_modules" +--- ] +--- } +--- ``` +--- +--- ### Vue support +--- +--- As of 2.0.0, Volar no longer supports TypeScript itself. Instead, a plugin +--- adds Vue support to this language server. +--- +--- *IMPORTANT*: It is crucial to ensure that `@vue/typescript-plugin` and `volar `are of identical versions. +--- +--- ```lua +--- vim.lsp.config('ts_ls', { +--- init_options = { +--- plugins = { +--- { +--- name = "@vue/typescript-plugin", +--- location = "/usr/local/lib/node_modules/@vue/typescript-plugin", +--- languages = {"javascript", "typescript", "vue"}, +--- }, +--- }, +--- }, +--- filetypes = { +--- "javascript", +--- "typescript", +--- "vue", +--- }, +--- }) +--- +--- -- You must make sure volar is setup +--- -- e.g. require'lspconfig'.volar.setup{} +--- -- See volar's section for more information +--- ``` +--- +--- `location` MUST be defined. If the plugin is installed in `node_modules`, +--- `location` can have any value. +--- +--- `languages` must include `vue` even if it is listed in `filetypes`. +--- +--- `filetypes` is extended here to include Vue SFC. + +return { + init_options = { hostInfo = 'neovim' }, + cmd = { 'typescript-language-server', '--stdio' }, + filetypes = { + 'javascript', + 'javascriptreact', + 'javascript.jsx', + 'typescript', + 'typescriptreact', + 'typescript.tsx', + }, + root_markers = { 'tsconfig.json', 'jsconfig.json', 'package.json', '.git' }, + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + lsp_highlight_document(client) + end, +} diff --git a/nvim/lua/_keymaps.lua b/nvim/lua/_keymaps.lua index 6b2eefa..a4bf15f 100644 --- a/nvim/lua/_keymaps.lua +++ b/nvim/lua/_keymaps.lua @@ -34,6 +34,13 @@ vim.api.nvim_create_user_command("ToggleZen", toggle_zen, {}) keymap("n", "", "ToggleZen", opts) keymap("n", "h", "nohl", opts) +local function format_with_prettier() + vim.fn.system('pnpm exec prettier --write ' .. vim.fn.expand('%:p')) + vim.cmd('edit') -- Reload the buffer after formatting +end +vim.api.nvim_create_user_command("FormatWithPrettier", format_with_prettier, {}) +keymap("n", "pr", "writeFormatWithPrettier", opts) + -- Modes -- normal_mode = "n", -- insert_mode = "i", diff --git a/nvim/lua/_lsp.lua b/nvim/lua/_lsp.lua index 4e3991c..2068298 100644 --- a/nvim/lua/_lsp.lua +++ b/nvim/lua/_lsp.lua @@ -1,3 +1,78 @@ +local function supported_by_prettier(filetype) + local filetypes = { + 'javascript', + 'javascriptreact', + 'javascript.jsx', + 'typescript', + 'typescriptreact', + 'typescript.tsx', + 'vue', + 'svelte', + 'astro', + -- html + 'aspnetcorerazor', + 'astro', + 'astro-markdown', + 'blade', + 'clojure', + 'django-html', + 'htmldjango', + 'edge', + 'eelixir', -- vim ft + 'elixir', + 'ejs', + 'erb', + 'eruby', -- vim ft + 'gohtml', + 'gohtmltmpl', + 'haml', + 'handlebars', + 'hbs', + 'html', + 'htmlangular', + 'html-eex', + 'heex', + 'jade', + 'leaf', + 'liquid', + 'markdown', + 'mdx', + 'mustache', + 'njk', + 'nunjucks', + 'php', + 'razor', + 'slim', + 'twig', + -- css + 'css', + 'less', + 'postcss', + 'sass', + 'scss', + 'stylus', + 'sugarss', + -- js + 'javascript', + 'javascriptreact', + 'reason', + 'rescript', + 'typescript', + 'typescriptreact', + -- mixed + 'vue', + 'svelte', + 'templ', + } + + for _, v in ipairs(filetypes) do + if v == filetype then + return true + end + end + return false +end + vim.lsp.enable({ 'clangd', 'lua_ls' @@ -32,5 +107,11 @@ vim.lsp.buf.hover({ border = "rounded" }) vim.lsp.buf.signature_help({ border = "rounded" }) vim.lsp.enable({ 'clangd', - 'luals' + 'luals', + + 'svelte', + 'tailwindcss', + "ts_ls", + "cssls", + "eslint", }) diff --git a/nvim/lua/_nvim_tree.lua b/nvim/lua/_nvim_tree.lua index bf5300c..a1ab8b4 100644 --- a/nvim/lua/_nvim_tree.lua +++ b/nvim/lua/_nvim_tree.lua @@ -20,11 +20,11 @@ end nvim_tree.setup({ on_attach = my_on_attach, - actions = { - open_file = { - quit_on_open = true, + actions = { + open_file = { + quit_on_open = true, + }, }, - }, update_focused_file = { enable = true, @@ -69,7 +69,7 @@ nvim_tree.setup({ }, }, view = { - width = 84, + width = 36, side = "right", }, }) diff --git a/zshrc.sh b/zshrc.sh index 9ae7e58..0eaf14e 100644 --- a/zshrc.sh +++ b/zshrc.sh @@ -46,3 +46,11 @@ ca () { cd ${1:-.} ; clear ; la } cn () { cd ${1:-.} ; clear ; neofetch } cgs() { cd ${1:-.} ; clear ; git status } picomadd() { sed -i '/# OPACITY_RULE/i ,"100:name *= '\'$1\''"' ~/.config/picom/picom.conf } + +# pnpm +export PNPM_HOME="/home/light/.local/share/pnpm" +case ":$PATH:" in + *":$PNPM_HOME:"*) ;; + *) export PATH="$PNPM_HOME:$PATH" ;; +esac +# pnpm end