-- The MIT License (MIT) -- -- Copyright © 2026 Scott E. Graves -- -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software -- and associated documentation files (the “Software”), to deal in the Software without restriction, -- including without limitation the rights to use, copy, modify, merge, publish, distribute, -- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in all copies or -- substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- local utils = require("darcula.utils") local utils_os = require("darcula.utils.os") local user_directory = vim.fs.joinpath( utils.iff(utils_os.is_windows, vim.env.NV_DARCULA_DRIVE, vim.env.HOME), ".desktop" ) local user_dictionary = vim.fs.joinpath(user_directory, ".cspell", "user_words.txt") local config_data = { "{", ' "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",', ' "version": "0.2",', ' "dictionaries": ["workspace-words", "user-words"],', ' "dictionaryDefinitions": [{', ' "name": "workspace-words",', ' "path": "./.cspell/words.txt",', ' "addWords": true', " },", " {", ' "name": "user-words",', ' "path": "' .. user_dictionary .. '",', ' "addWords": true', " }", " ]", "}" } local get_workspace_directory = function() return vim.fs.joinpath(NV_Darcula_Git_Root(vim.fn.getcwd())) end local get_workspace_dictionary = function() return vim.fs.joinpath(get_workspace_directory(), ".cspell", "words.txt") end local create_config_file = function(force) force = force and true if force or vim.fn.filereadable(get_workspace_dictionary()) ~= 0 or vim.fn.filereadable(user_dictionary) ~= 0 then local config_file = vim.fs.joinpath(get_workspace_directory(), "cspell.json") if vim.fn.filereadable(config_file) == 0 then vim.fn.writefile(config_data, config_file, "b") end end end local refresh_buffer = function() -- NV_Darcula_Refresh_Buffer() NV_Darcula_LSP_Restart() end local group = utils.augroup_with_autocmd( "cspell_cfg", "User", "RooterChDir", function() create_config_file(false) end ) utils.autocmd( group, "VimEnter", "*", function() create_config_file(false) end ) NV_Darcula_Cspell_Cleanup = function() local get_lines = function(location) if vim.fn.filereadable(location) ~= 0 then return vim.fn.readfile(location, "") end return {} end local cleanup = function(lines) local clean_lines = {} for _, word in pairs(lines) do word = vim.fn.trim(word:lower()) if #word > 0 and not table.contains(clean_lines, word) then table.insert(clean_lines, word) end end return clean_lines end local user_lines = cleanup(get_lines(user_dictionary)) local workspace_lines = cleanup(get_lines(get_workspace_dictionary())) if vim.fn.filereadable(user_dictionary) ~= 0 then table.sort(user_lines) vim.fn.writefile(user_lines, user_dictionary, "b") if vim.fn.filereadable(get_workspace_dictionary()) ~= 0 then local unique_lines = {} for _, word in pairs(workspace_lines) do if not table.contains(user_lines, word) then table.insert(unique_lines, word) end end table.sort(unique_lines) vim.fn.writefile(unique_lines, get_workspace_dictionary(), "b") refresh_buffer() end end vim.notify("Cleaned cspell dictionaries", vim.log.levels.INFO) end local cspell_read_file = function(user) user = user or false local spell_directory = vim.fs.joinpath( utils.iff(user, user_directory, get_workspace_directory()), ".cspell" ) local is_directory = vim.fn.isdirectory(spell_directory) if is_directory == 0 then vim.fn.mkdir(spell_directory, "p") end create_config_file(true) local spell_file = vim.fs.joinpath(spell_directory, "words.txt") local lines = (function() if vim.fn.filereadable(spell_file) ~= 0 then return vim.fn.readfile(spell_file, "") end return {} end)() return lines, spell_file end local cspell_write_word = function(user, lines, spell_file, word) user = user or false word = vim.fn.trim(word) if word ~= nil and #word > 0 and lines ~= nil then for _, value in pairs(lines) do if word:lower() == value:lower() then return end end table.insert(lines, word:lower()) table.sort(lines) vim.fn.writefile(lines, spell_file, "b") vim.notify( "Added '" .. word .. "' to " .. utils.iff(user, "user", "workspace") .. " dictionary", vim.log.levels.INFO ) refresh_buffer() end end NV_Darcula_Cspell_Add_Selected_Word = function(user) user = user or false local lines, spell_file = cspell_read_file(user) NV_Darcula_Grab_Selection( function(word) cspell_write_word(user, lines, spell_file, word) end ) end NV_Darcula_Cspell_Add_Word = function(user) user = user or false local lines, spell_file = cspell_read_file(user) local word = utils.cword() or "" cspell_write_word(user, lines, spell_file, word) end