From 68b763084bcc696577c6138d8f6b935a478f8d22 Mon Sep 17 00:00:00 2001 From: Corey B <14075562+coreyb-git@users.noreply.github.com> Date: Tue, 10 Mar 2026 03:34:56 +1000 Subject: [PATCH 1/4] Feat: Run only in normal editable buffers (buftype == ). This is configurable in opts. --- lua/spellwarn/diagnostics.lua | 27 +++++++++++++++++++-------- lua/spellwarn/init.lua | 9 +++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lua/spellwarn/diagnostics.lua b/lua/spellwarn/diagnostics.lua index 0a9f0dd..77cc162 100644 --- a/lua/spellwarn/diagnostics.lua +++ b/lua/spellwarn/diagnostics.lua @@ -54,22 +54,33 @@ function M.update_diagnostics(opts, bufnr) vim.diagnostic.set(namespace, bufnr, diags, opts.diagnostic_opts) end +local function can_update(opts, bufnr) + local winid = vim.api.nvim_get_current_win() + if winid then + if not vim.wo[winid].spell then + vim.diagnostic.reset(namespace, bufnr) -- ensure old are cleared if spell is toggled to off. + return + end + end + + local buftype = vim.api.nvim_get_option_value("buftype", { buf = bufnr }) + if opts.bt_config[buftype] then + return opts.bt_config[buftype] + end + + return opts.bt_default +end + function M.setup(opts) function M.enable() vim.api.nvim_create_augroup("Spellwarn", {}) vim.api.nvim_create_autocmd(opts.event, { group = "Spellwarn", callback = function() - local winid = vim.api.nvim_get_current_win() local bufnr = vim.fn.bufnr("%") - if winid then - if not vim.wo[winid].spell then - vim.diagnostic.reset(namespace, bufnr) -- ensure old are cleared if spell is toggled to off. - return - end + if can_update(opts, bufnr) then + M.update_diagnostics(opts, bufnr) end - - M.update_diagnostics(opts, bufnr) end, desc = "Update Spellwarn diagnostics", }) diff --git a/lua/spellwarn/init.lua b/lua/spellwarn/init.lua index aa51d0d..01fc52e 100644 --- a/lua/spellwarn/init.lua +++ b/lua/spellwarn/init.lua @@ -8,7 +8,14 @@ local defaults = { "TextChangedI", "TextChangedP", }, + enable = true, -- enable diagnostics on startup + + bt_config = { -- buffer types to run on + [""] = true, + }, + bt_default = false, -- default for types not in bt_config. + ft_config = { -- spellcheck method: "cursor", "iter", or boolean alpha = false, help = false, @@ -17,7 +24,9 @@ local defaults = { mason = false, }, ft_default = true, -- default option for unspecified filetypes + max_file_size = nil, -- maximum file size to check in lines (nil for no limit) + severity = { -- severity for each spelling error type (false to disable diagnostics for that type) spellbad = "WARN", spellcap = "HINT", From a9d186665daa973fff7252b07bb59dc7220218ea Mon Sep 17 00:00:00 2001 From: Corey B <14075562+coreyb-git@users.noreply.github.com> Date: Tue, 10 Mar 2026 03:53:29 +1000 Subject: [PATCH 2/4] Updated README.md --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a92da13..b818ac6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ This is a plugin to display spelling errors as diagnostics. Some language server A simpler solution, therefore, is to use Neovim's existing spellchecking and diagnostics features. This is done by iterating through the flagged words in a buffer and passing them to `vim.diagnostic.set()`. Neovim is fast enough that this is ~instantaneous for most files. See below for installation and configuration instructions. ## Installation + I recommend using [Lazy.nvim](https://github.com/folke/lazy.nvim): + ```lua { "ravibrock/spellwarn.nvim", @@ -23,7 +25,9 @@ I recommend using [Lazy.nvim](https://github.com/folke/lazy.nvim): Note that this uses Neovim's built-in spellchecking. This requires putting `vim.opt.spell = true` and `vim.opt.spelllang = [YOUR LANGUAGE HERE]` somewhere in your Neovim config if you haven't already. You may also want to add the word "spellwarn" to your Neovim dictionary. This can be done by putting the cursor onto "spellwarn" and hitting `zg`. ## Configuration + Pass any of the following options to `require("spellwarn").setup()`: + ```lua { event = { -- event(s) to refresh diagnostics on @@ -33,40 +37,53 @@ Pass any of the following options to `require("spellwarn").setup()`: "TextChangedI", "TextChangedP", }, + enable = true, -- enable diagnostics on startup + + bt_config = { -- buffer types to run on + [""] = true, + }, + bt_default = false, -- default for types not in bt_config. + ft_config = { -- spellcheck method: "cursor", "iter", or boolean - alpha = false, - help = false, - lazy = false, + alpha = false, + help = false, + lazy = false, lspinfo = false, - mason = false, + mason = false, }, ft_default = true, -- default option for unspecified filetypes + max_file_size = nil, -- maximum file size to check in lines (nil for no limit) + severity = { -- severity for each spelling error type (false to disable diagnostics for that type) - spellbad = "WARN", - spellcap = "HINT", + spellbad = "WARN", + spellcap = "HINT", spelllocal = "HINT", - spellrare = "INFO", + spellrare = "INFO", }, - suggest = false, -- show spelling suggestions in diagnostic message (works best with window-style message) - num_suggest = 3, -- number of spelling suggestions shown in diagnostic message + suggest = false, -- show spelling suggestions in diagnostic message + num_suggest = 3, -- number of suggestions shown in diagnostic message prefix = "possible misspelling(s): ", -- prefix for each diagnostic message diagnostic_opts = { severity_sort = true }, -- options for diagnostic display } ``` + Most options are overwritten (e.g. passing `ft_config = { python = false }` will mean that `alpha`, `mason`, etc. are set to true) but `severity` and `diagnostic_opts` are merged, so that (for example) passing `{ spellbad = "HINT" }` won't cause `spellcap` to be nil. You can pass any of `cursor`, `iter`, `treesitter`, `false`, or `true` as options to `ft_config`. The default method is `cursor`, which iterates through the buffer with `]s`. There is also `iter`, which uses Treesitter (if available) and the Lua API. Finally, `false` disables Spellwarn for that filetype and `true` uses the default (`cursor`). The `suggest` option adds spelling suggestions to the diagnostic message, it does not allow auto-complete. `num_suggest` specifies the number of suggestions to show in the diagnostic message. **If you have `suggest` set to `true`, you need to also have `num_suggest >= 1` or else you will have an error.** *Note: `iter` doesn't show `spellcap` errors, but works well other than that. I recommend it.* ## Usage + The plugin should be good to go after installation with the provided snippet. It has sensible defaults. Run `:Spellwarn enable`, `:Spellwarn disable`, or `:Spellwarn toggle` to enable/disable/toggle during runtime (though this will *not* override `max_file_size`, `ft_config`, or `ft_default`). You can also add keybindings for any of these (one possible usecase would be disabling by default with the `enable` key of the configuration table and then only enabling when needed). To disable diagnostics on a specific line, add `spellwarn:disable-next-line` to the line immediately above or `spellwarn:disable-line` to a comment at the end of the line. To disable diagnostics in a file, add a comment with `spellwarn:disable` to the *first or second* line of the file. ## Lua API + The Lua API matches the arguments for the `Spellwarn` command: - `require("spellwarn").disable()` to disable - `require("spellwarn").enable()` to enable - `require("spellwarn").toggle()` to toggle ## Contributing + PRs and issues welcome! Please consult `CONTRIBUTING.md` for style guidelines. From 30a826a7ad528b47f8f251ca7530e38650dce763 Mon Sep 17 00:00:00 2001 From: Corey B <14075562+coreyb-git@users.noreply.github.com> Date: Tue, 10 Mar 2026 04:04:06 +1000 Subject: [PATCH 3/4] Feat: Added preprocess function to opts to custom process the diagnostics table before calling vim.diagnostic.set() --- README.md | 2 ++ lua/spellwarn/diagnostics.lua | 4 ++++ lua/spellwarn/init.lua | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/README.md b/README.md index b818ac6..891a041 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ Pass any of the following options to `require("spellwarn").setup()`: enable = true, -- enable diagnostics on startup + func_preprocess = function() end, -- function to do any custom processing of the diagnostics table before passing it to vim.diagnostic.set + bt_config = { -- buffer types to run on [""] = true, }, diff --git a/lua/spellwarn/diagnostics.lua b/lua/spellwarn/diagnostics.lua index 77cc162..46c9e55 100644 --- a/lua/spellwarn/diagnostics.lua +++ b/lua/spellwarn/diagnostics.lua @@ -50,6 +50,10 @@ function M.update_diagnostics(opts, bufnr) end end end + + -- Pre-process, if a function is set in opts to do anything. + opts.func_preprocess(diags) + -- TODO: Add suffix diagnostics with type of spelling error the way that LSP diagnostics do vim.diagnostic.set(namespace, bufnr, diags, opts.diagnostic_opts) end diff --git a/lua/spellwarn/init.lua b/lua/spellwarn/init.lua index 01fc52e..20b0c3a 100644 --- a/lua/spellwarn/init.lua +++ b/lua/spellwarn/init.lua @@ -11,6 +11,10 @@ local defaults = { enable = true, -- enable diagnostics on startup + func_preprocess = function(diag_tbl) + return diag_tbl + end, -- function to do any custom processing of the diagnostics table before passing it to vim.diagnostic.set + bt_config = { -- buffer types to run on [""] = true, }, From 73d4012e7afc35876e2673512de782e6721823b8 Mon Sep 17 00:00:00 2001 From: Corey B <14075562+coreyb-git@users.noreply.github.com> Date: Tue, 10 Mar 2026 04:16:34 +1000 Subject: [PATCH 4/4] Fix: Forgot to actually re-assign the table from the function call result. --- lua/spellwarn/diagnostics.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/spellwarn/diagnostics.lua b/lua/spellwarn/diagnostics.lua index 46c9e55..f3fe6ba 100644 --- a/lua/spellwarn/diagnostics.lua +++ b/lua/spellwarn/diagnostics.lua @@ -52,7 +52,7 @@ function M.update_diagnostics(opts, bufnr) end -- Pre-process, if a function is set in opts to do anything. - opts.func_preprocess(diags) + diags = opts.func_preprocess(diags) -- TODO: Add suffix diagnostics with type of spelling error the way that LSP diagnostics do vim.diagnostic.set(namespace, bufnr, diags, opts.diagnostic_opts)