null-ls.nvim
null-ls.nvim copied to clipboard
feat: add cspell suggestions to code actions
Add a new cspell code action builtin. When triggering code actions on a line with cspell diagnostic errors (misspelled words) show spelling suggestions in the code actions menu.
This is the followup to #909.
Example:
The line dhis menue
shows the code actions:
Fix dhis -> chis
Fix dhis -> dais
Fix dhis -> phis
Fix dhis -> this
Fix menue -> Benue
Fix menue -> mene
Fix menue -> menu
Fix menue -> menus
Fix menue -> venue
I'm not happy with the design yet. To generate the suggestions the command
cspell sug --num-suggestions=4 dhis menue
is run. Running the process
takes some time and vim blocks while the command is running.
My preferred solution would be: Generate the suggestions while the cspell diagnostic builtin is run and the cspell code action builtin reads the suggestions from some sort of cache. But I have no idea how to communicate between the two builtins, any ideas?
I like this idea. If we could generate diagnostics and suggestions together (and assuming it doesn't significantly add to the time it takes to run the command) we could actually store the suggestion data under the user_data
key (see :h diagnostic-structure
) and retrieve it by adapting the logic you're already using.
Since it looks like we'll have to depend on diagnostics in the first place, I think this would be the simplest way to handle it. This would require adapting the existing cspell
source, and after playing around with it a bit, I wasn't able to get it to generate suggestions and diagnostics in a single command, but if you can figure it out, I think that would be the way to go.
Spelling suggestions are now generated by the diagnostics cspell builtin. The code actions cspell builtin retrieves the suggestions from the user_data
property of the diagnostic.
The next question is if the code action message format is fine Fix dhis -> this
?
And adding documentation.
When this PR is accepted I would close #909 and follow up cspell configuration and custom dictionaries in other PRs.
I have changed the behavior a little bit. You need to be on the misspelled word to show the code action, and only the suggestion for the word under the cursor is displayed.
@yoo I've been using your branch, so far so good. How hard would be to add an option to the suggestion like "Add word
to cspell.json"? I would love to contribute.
Edit: I added the following to your snippet, it does the trick and appends the word to the .json
file.
-- add word to "words" in cspell.json
table.insert(actions, {
title = "Add to cspell.json",
action = function()
local word = vim.api.nvim_buf_get_text(
diagnostic.bufnr,
diagnostic.lnum,
diagnostic.col,
diagnostic.end_lnum,
diagnostic.end_col,
{}
)[1]
local cspell_json = vim.fn.findfile("cspell.json", vim.fn.getcwd() .. ";")
if cspell_json == "" then
vim.notify("\ncspell.json not found", vim.log.levels.WARN)
return
end
local cspell = vim.fn.json_decode(vim.fn.readfile(cspell_json))
if not cspell.words then
cspell.words = {}
end
table.insert(cspell.words, word)
local json = vim.fn.json_encode(cspell)
vim.fn.writefile({ json }, cspell_json)
-- replace word in buffer to trigger cspell to update diagnostics
vim.api.nvim_buf_set_text(
diagnostic.bufnr,
diagnostic.lnum,
diagnostic.col,
diagnostic.end_lnum,
diagnostic.end_col,
{ word }
)
end,
})
The suggestions are now only generated if the cspell code actions builtin is enabled. And added documentation.
@marianozunino I would do this in a follow-up PR.
My thoughts:
Set the path to the config.json
as a config option. This way, the user can decide if they want
a single global config file or lookup the current path.
As for adding words, vscode extension also supports dictionaries
Example:
Are there any updates on this feature?
I went ahead and moved the documentation to the source definition, and otherwise I think this is good to go. Thanks!
Hurray, thanks a lot for this feature!
@yoo I've been using your branch, so far so good. How hard would be to add an option to the suggestion like "Add
word
to cspell.json"? I would love to contribute.Edit: I added the following to your snippet, it does the trick and appends the word to the
.json
file.-- add word to "words" in cspell.json table.insert(actions, { title = "Add to cspell.json", action = function() local word = vim.api.nvim_buf_get_text( diagnostic.bufnr, diagnostic.lnum, diagnostic.col, diagnostic.end_lnum, diagnostic.end_col, {} )[1] local cspell_json = vim.fn.findfile("cspell.json", vim.fn.getcwd() .. ";") if cspell_json == "" then vim.notify("\ncspell.json not found", vim.log.levels.WARN) return end local cspell = vim.fn.json_decode(vim.fn.readfile(cspell_json)) if not cspell.words then cspell.words = {} end table.insert(cspell.words, word) local json = vim.fn.json_encode(cspell) vim.fn.writefile({ json }, cspell_json) -- replace word in buffer to trigger cspell to update diagnostics vim.api.nvim_buf_set_text( diagnostic.bufnr, diagnostic.lnum, diagnostic.col, diagnostic.end_lnum, diagnostic.end_col, { word } ) end, })
@marianozunino @yoo was this feature officially implemented? — thanks for this (love cspell)
@juanpprieto There is an open PR - see #1154.