stevearc / dressing.nvim

Neovim plugin to improve the default vim.ui interfaces
MIT License
1.83k stars 32 forks source link

[Enhancement] Add support for spelling suggestions #60

Closed AniAggarwal closed 2 years ago

AniAggarwal commented 2 years ago

I would love if I could use the same pop up selection menu for picking my spelling suggestions via dressing.nivm (z= keymap).

stevearc commented 2 years ago

That is an interesting idea. I think this is something that would have to be done in Neovim core, since z= is a built-in keymap. I didn't see any API for fetching spelling suggestions; do you know of any?

AniAggarwal commented 2 years ago

Not that I know of.. the closest thing I could find is under vim.spell (at this url, you'll after to ctrl+f, wasn't able to copy link with header). This file may interest you, or maybe not. I don't know much C and though searching through Neovim's docs and source code didn't revealed anything to me, I definitely could have missed something.

Maybe you/I could open an issue on core and see if they add an API? Given the size, I realize if they do decided to do so, it will take a while but could be worth the effort.

stevearc commented 2 years ago

That file does indeed look like where the vim.spell.check function is defined. You should open an issue! I think it's a reasonable request to expose spelling suggestions, especially since there's already precedent for putting some spelling API into lua.

AniAggarwal commented 2 years ago

Before I open an issue, I remembered that which-key.nvim is able to do spell suggestions. Based on my limited lua knowledge, it seems that it overrides the z= map and then manually calls the vim spell checking on the word. But you can check it out here and see if that is really the case. If so, I'll make an issue, but if I'm wrong there might be some way to access the API that we missed.

stevearc commented 2 years ago

Ah, looks like there's a vim function spellsuggest() that does it! Try this:

vim.keymap.set("n", "z=", function()
  local word = vim.fn.expand("<cword>")
  local suggestions = vim.fn.spellsuggest(word)
  vim.ui.select(
    suggestions,
    {},
    vim.schedule_wrap(function(selected)
      if selected then
        vim.api.nvim_feedkeys("ciw" .. selected, "n", true)
        vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, true, true), "n", true)
      end
    end)
  )
end)

Note that you'll need to update dressing to get this change: b188b7750c78c0dbe0c61d79d824673a53ff82db

AniAggarwal commented 2 years ago

That worked, thanks!

daibertdiego commented 2 weeks ago

You can use this version to include numbers to facilitate the selection.

vim.keymap.set("n", "z=", function()
    local word = vim.fn.expand("<cword>")
    local suggestions = vim.fn.spellsuggest(word)

    -- Create a new list with formatted suggestions
    local formatted_suggestions = {}
    for i, suggestion in ipairs(suggestions) do
        table.insert(formatted_suggestions, string.format("%d -> %s", i, suggestion))
    end

    vim.ui.select(
        formatted_suggestions,
        {},
        vim.schedule_wrap(function(selected)
            if selected then
                -- Extract the actual suggestion from the selected string
                local index = tonumber(selected:match("^(%d+)")) -- Get the number at the start
                local actual_suggestion = suggestions[index] -- Get the corresponding suggestion
                vim.api.nvim_feedkeys("ciw" .. actual_suggestion, "n", true)
                vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, true, true), "n", true)
            end
        end)
    )
end)