diff --git a/term/.config/nvim/README.md b/term/.config/nvim/README.md index cb92156..8c939e9 100644 --- a/term/.config/nvim/README.md +++ b/term/.config/nvim/README.md @@ -125,6 +125,8 @@ A feature-rich Neovim setup optimized for Python, JSON, and CSV development. | `K` | Show hover documentation | | `rn` | Rename symbol | | `ca` | Code actions / quick fixes | +| `fx` | Fix diagnostic under cursor | +| `fA` | Fix all source-level diagnostics | | `e` | Show diagnostic error | | `[d / ]d` | Previous/next diagnostic | @@ -132,7 +134,7 @@ A feature-rich Neovim setup optimized for Python, JSON, and CSV development. | Keymap | Action | |--------|--------| -| `f` | Format file | +| `lf` | Format file | ### Git (Gitsigns) @@ -181,7 +183,8 @@ A feature-rich Neovim setup optimized for Python, JSON, and CSV development. ## File Type Specifics ### Python (.py) -- **LSP**: Full autocompletion, type checking, goto definition +- **LSP**: Full autocompletion, type checking, goto definition, Ruff diagnostics and quick fixes +- **Linting**: Ruff LSP (fix with `fx`, or use `fA` for fix-all actions) - **Formatting**: ruff format (fast), black (backup) - **Debugging**: Set breakpoints with `F9`, run with `F5` - **Indentation**: 4 spaces (Python convention) @@ -192,6 +195,18 @@ A feature-rich Neovim setup optimized for Python, JSON, and CSV development. - **Indentation**: 2 spaces - **Folding**: JSON objects/arrays are foldable (`za` to toggle, `zM` to close all) +### Markdown (.md) +- **LSP**: Marksman for Markdown navigation and document features +- **Linting**: markdownlint diagnostics +- **Fixes**: `fx` or `ca` runs `markdownlint --fix` on the saved file +- **Formatting**: Prettier via `lf` +- **Note**: Only markdownlint rules that support automatic fixes can be changed automatically + +### JavaScript/TypeScript/Vue +- **LSP**: TypeScript language features and ESLint diagnostics with quick fixes +- **Linting**: ESLint LSP (fix with `fx`, or use `fA` for fix-all actions) +- **Formatting**: Prettier via `lf` + ### CSV (.csv) - **Treesitter**: Syntax highlighting - **No wrap**: Full row visibility diff --git a/term/.config/nvim/init.lua b/term/.config/nvim/init.lua index d810981..4475138 100644 --- a/term/.config/nvim/init.lua +++ b/term/.config/nvim/init.lua @@ -49,13 +49,78 @@ require("diff-base") -- ============================================================================ -- STEP 4: LSP KEYMAPS -- ============================================================================ +local function fix_markdownlint() + local bufnr = vim.api.nvim_get_current_buf() + local filename = vim.api.nvim_buf_get_name(bufnr) + local markdownlint = vim.fn.exepath("markdownlint") + if markdownlint == "" then + markdownlint = vim.fn.stdpath("data") .. "/mason/bin/markdownlint" + end + + if vim.fn.executable(markdownlint) == 0 then + vim.notify("markdownlint is not installed", vim.log.levels.WARN) + return + end + + if filename == "" then + vim.notify("Save the Markdown buffer before fixing it", vim.log.levels.WARN) + return + end + + vim.cmd.write() + vim.fn.jobstart({ markdownlint, "--fix", filename }, { + buffer = bufnr, + on_exit = function(_, exit_code) + vim.schedule(function() + if exit_code ~= 0 then + vim.notify("markdownlint could not fix this file", vim.log.levels.WARN) + return + end + + vim.cmd.checktime() + vim.notify("markdownlint fixes applied", vim.log.levels.INFO) + vim.defer_fn(function() + require("lint").try_lint() + end, 100) + end) + end, + }) +end + vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" }) vim.keymap.set("n", "gD", vim.lsp.buf.declaration, { desc = "Go to declaration" }) vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { desc = "Go to implementation" }) vim.keymap.set("n", "gr", vim.lsp.buf.references, { desc = "Show references" }) vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Show hover docs" }) vim.keymap.set("n", "rn", vim.lsp.buf.rename, { desc = "Rename symbol" }) -vim.keymap.set("n", "ca", vim.lsp.buf.code_action, { desc = "Code actions" }) +vim.keymap.set("n", "ca", function() + if vim.bo.filetype == "markdown" then + fix_markdownlint() + return + end + vim.lsp.buf.code_action() +end, { desc = "Code actions / Markdown fixes" }) +vim.keymap.set("n", "fx", function() + if vim.bo.filetype == "markdown" then + fix_markdownlint() + return + end + vim.lsp.buf.code_action({ + context = { + diagnostics = vim.diagnostic.get(0, { + lnum = vim.fn.line(".") - 1, + }), + }, + }) +end, { desc = "Fix diagnostic" }) +vim.keymap.set("n", "fA", function() + vim.lsp.buf.code_action({ + apply = true, + context = { + only = { "source.fixAll" }, + }, + }) +end, { desc = "Fix all diagnostics" }) vim.keymap.set("n", "e", vim.diagnostic.open_float, { desc = "Show diagnostic" }) vim.diagnostic.config({ @@ -138,4 +203,3 @@ vim.keymap.set("n", "ch", ":noh", { desc = "clear search highlightin -- toggle word wrap vim.keymap.set("n", "tw", ":set wrap!", { desc = "toggle word wrap" }) - diff --git a/term/.config/nvim/lua/plugins/lsp-config.lua b/term/.config/nvim/lua/plugins/lsp-config.lua index a0ef7b0..be7c750 100644 --- a/term/.config/nvim/lua/plugins/lsp-config.lua +++ b/term/.config/nvim/lua/plugins/lsp-config.lua @@ -44,10 +44,13 @@ return { require("mason-lspconfig").setup({ ensure_installed = { "pyright", -- Python + "ruff", -- Python linting and fixes + "eslint", -- JavaScript/TypeScript linting and fixes "ts_ls", -- TypeScript/JavaScript "vue_ls", -- Vue (Volar) "jsonls", -- JSON "yamlls", -- YAML + "marksman", -- Markdown "html", -- HTML "cssls", -- CSS "bashls", -- Bash @@ -97,6 +100,25 @@ return { }, }) + -- Ruff provides Python lint diagnostics and quick fixes. + vim.lsp.config("ruff", { + filetypes = { "python" }, + }) + + -- ESLint provides lint diagnostics and source-level fixes. + vim.lsp.config("eslint", { + filetypes = { + "javascript", + "javascriptreact", + "typescript", + "typescriptreact", + "vue", + }, + settings = { + workingDirectory = { mode = "auto" }, + }, + }) + -- Type- and JavaScript vim.lsp.config("ts_ls", { filetypes = { @@ -160,6 +182,7 @@ return { -- Other languages vim.lsp.config("jsonls", {}) vim.lsp.config("yamlls", {}) + vim.lsp.config("marksman", {}) vim.lsp.config("html", {}) vim.lsp.config("cssls", {}) vim.lsp.config("bashls", {}) @@ -167,10 +190,13 @@ return { -- Enable servers vim.lsp.enable("lua_ls") vim.lsp.enable("pyright") + vim.lsp.enable("ruff") + vim.lsp.enable("eslint") vim.lsp.enable("ts_ls") vim.lsp.enable("vue_ls") vim.lsp.enable("jsonls") vim.lsp.enable("yamlls") + vim.lsp.enable("marksman") vim.lsp.enable("html") vim.lsp.enable("cssls") vim.lsp.enable("bashls") diff --git a/term/.config/nvim/lua/plugins/nvim-lint.lua b/term/.config/nvim/lua/plugins/nvim-lint.lua index 28d3d2c..9d0b2d9 100644 --- a/term/.config/nvim/lua/plugins/nvim-lint.lua +++ b/term/.config/nvim/lua/plugins/nvim-lint.lua @@ -2,12 +2,6 @@ return { "mfussenegger/nvim-lint", config = function() require("lint").linters_by_ft = { - javascript = { "eslint_d" }, - javascriptreact = { "eslint_d" }, - typescript = { "eslint_d" }, - typescriptreact = { "eslint_d" }, - vue = { "eslint_d" }, - python = { "ruff" }, -- lua = { "selene" }, -- Disabled: lua_ls provides diagnostics sh = { "shellcheck" }, bash = { "shellcheck" }, @@ -17,7 +11,7 @@ return { rust = { "clippy" }, } - vim.api.nvim_create_autocmd({ "BufWritePost" }, { + vim.api.nvim_create_autocmd({ "BufWritePost", "BufEnter", "InsertLeave" }, { callback = function() require("lint").try_lint() end,