diff --git a/modules/neovim/init/spellcheck.nix b/modules/neovim/init/spellcheck.nix index d8957ef..c7b495f 100644 --- a/modules/neovim/init/spellcheck.nix +++ b/modules/neovim/init/spellcheck.nix @@ -1,11 +1,14 @@ { config, + pkgs, lib, ... }: let inherit (lib.modules) mkIf mkRenamedOptionModule; inherit (lib.options) mkOption mkEnableOption literalExpression; - inherit (lib.types) listOf str; + inherit (lib.strings) concatLines; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.types) listOf str attrsOf; inherit (lib.nvim.lua) listToLuaTable; inherit (lib.nvim.dag) entryAfter; @@ -24,10 +27,43 @@ in { description = '' A list of languages that should be used for spellchecking. - To add your own language files, you may place your `spell` - directory in either `~/.config/nvim` or the - [additionalRuntimePaths](#opt-vim.additionalRuntimePaths) - directory provided by **nvf**. + To add your own language files, you may place your `spell` directory in either + {file}`$XDG_CONFIG_HOME/nvf` or in a path that is included in the + [additionalRuntimePaths](#opt-vim.additionalRuntimePaths) list provided by nvf. + ''; + }; + + extraSpellWords = mkOption { + type = attrsOf (listOf str); + default = {}; + example = literalExpression ''{"en.utf-8" = ["nvf" "word_you_want_to_add"];}''; + description = '' + Additional words to be used for spellchecking. The names of each key will be + used as the language code for the spell file. For example + + ```nix + "en.utf-8" = [ ... ]; + ``` + + will result in `en.utf-8.add.spl` being added to Neovim's runtime in the + {file}`spell` directory. + + ::: {.warning} + The attribute keys must be in `"."` format for Neovim to + compile your spellfiles without mangling the resulting file names. Please + make sure that you enter the correct value, as nvf does not do any kind of + internal checking. Please see {command}`:help mkspell` for more details. + + Example: + + ```nix + # "en" is the name, and "utf-8" is the encoding. For most use cases, utf-8 + # will be enough, however, you may change it to any encoding format Neovim + # accepts, e.g., utf-16. + "en.utf-8" = ["nvf" "word_you_want_to_add"]; + => $out/spell/en-utf-8.add.spl + ``` + ::: ''; }; @@ -38,8 +74,10 @@ in { description = '' A list of filetypes for which spellchecking will be disabled. - You may use `echo &filetype` in Neovim to find out the + ::: {.tip} + You may use {command}`:echo &filetype` in Neovim to find out the filetype for a specific buffer. + ::: ''; }; @@ -58,18 +96,53 @@ in { }; config = mkIf cfg.enable { - vim.luaConfigRC.spellcheck = entryAfter ["basic"] '' - vim.opt.spell = true - vim.opt.spelllang = ${listToLuaTable cfg.languages} + vim = { + additionalRuntimePaths = let + spellfilesJoined = pkgs.symlinkJoin { + name = "nvf-spellfiles-joined"; + paths = mapAttrsToList (name: value: pkgs.writeTextDir "spell/${name}.add" (concatLines value)) cfg.extraSpellWords; + postBuild = '' + echo "Spellfiles joined" + ''; + }; - -- Disable spellchecking for certain filetypes - -- as configured by `vim.spellcheck.ignoredFiletypes` - vim.api.nvim_create_autocmd({ "FileType" }, { - pattern = ${listToLuaTable cfg.ignoredFiletypes}, - callback = function() - vim.opt_local.spell = false - end, - }) - ''; + compileJoinedSpellfiles = + pkgs.runCommandLocal "nvf-compile-spellfiles" { + # Use the same version of Neovim as the user's configuration + nativeBuildInputs = [config.vim.package]; + } '' + mkdir -p "$out/spell" + + spellfilesJoined=$(find -L "${spellfilesJoined}/spell" -type f) + for spellfile in $spellfilesJoined; do + # Hacky way to ensure that the mangled extensions are omitted from the + # joined spellfiles. E.g. + local name=$(basename "$spellfile" ".add") + echo "Compiling spellfile: $spellfile" + nvim --headless --clean \ + --cmd "mkspell $out/spell/$name.add.spl $spellfile" -Es -n + done + ''; + in + mkIf (cfg.extraSpellWords != {}) [ + # If .outPath is missing, additionalRuntimePaths receives the *function* + # instead of a path, causing errors. + compileJoinedSpellfiles.outPath + ]; + + luaConfigRC.spellcheck = entryAfter ["basic"] '' + vim.opt.spell = true + vim.opt.spelllang = ${listToLuaTable cfg.languages} + + -- Disable spellchecking for certain filetypes + -- as configured by `vim.spellcheck.ignoredFiletypes` + vim.api.nvim_create_autocmd({ "FileType" }, { + pattern = ${listToLuaTable cfg.ignoredFiletypes}, + callback = function() + vim.opt_local.spell = false + end, + }) + ''; + }; }; }