local make_builtin = require("null-ls.helpers").make_builtin local methods = require("null-ls.methods") local h = require("cspell.helpers") local make_add_to_json = require("cspell.code_actions.make_add_to_json") local make_add_to_dictionary_action = require("cspell.code_actions.make_add_to_dictionary_action") local CODE_ACTION = methods.internal.CODE_ACTION --- Filter diagnostics generated by the cspell built-in ---@param bufnr number ---@param lnum number ---@param cursor_col number ---@return table local cspell_diagnostics = function(bufnr, lnum, cursor_col) local diagnostics = {} for _, diagnostic in ipairs(vim.diagnostic.get(bufnr, { lnum = lnum })) do if diagnostic.source == "cspell" and cursor_col >= diagnostic.col and cursor_col < diagnostic.end_col then table.insert(diagnostics, diagnostic) end end return diagnostics end return make_builtin({ name = "cspell", meta = { url = "https://github.com/streetsidesoftware/cspell", description = "Injects actions to fix typos found by `cspell`.", notes = { "This source depends on the `cspell` built-in diagnostics source, so make sure to register it, too.", }, usage = [[ local cspell = require('cspell') local sources = { cspell.diagnostics, cspell.code_actions } ]], }, method = CODE_ACTION, filetypes = {}, generator = { ---@param params GeneratorParams ---@return table fn = function(params) params.cwd = params.cwd or vim.loop.cwd() params.cwd = "~/.config/cspell/" ---@type table local actions = {} local cspell = h.async_get_config_info(params) local diagnostics = cspell_diagnostics(params.bufnr, params.row - 1, params.col) if vim.tbl_isempty(diagnostics) then return actions end for _, diagnostic in ipairs(diagnostics) do -- replace word with a suggestion for _, suggestion in ipairs(diagnostic.user_data.suggestions) do table.insert(actions, { title = string.format("Use %s", suggestion), action = function() h.set_word(diagnostic, suggestion) ---@type CSpellSourceConfig local code_action_config = params:get_config() local on_success = code_action_config.on_success if on_success then on_success(cspell and cspell.path, params, "use_suggestion") end end, }) end local word = h.get_word(diagnostic) -- add word to "words" in cspell.json table.insert( actions, make_add_to_json({ diagnostic = diagnostic, word = word, params = params, cspell = cspell, }) ) if cspell == nil then break end -- add word to a custom dictionary for _, dictionary in ipairs(cspell.config.dictionaryDefinitions or {}) do if dictionary ~= nil and dictionary.addWords then table.insert( actions, make_add_to_dictionary_action({ diagnostic = diagnostic, word = word, params = params, cspell = cspell, dictionary = dictionary, }) ) end end end return actions end, }, })