supermaven-inc / supermaven-nvim

The official Neovim plugin for Supermaven
https://supermaven.com/
MIT License
279 stars 16 forks source link

Incorrect result calling has_suggestion with whitespace between cursor and suggestion #50

Open sQVe opened 4 weeks ago

sQVe commented 4 weeks ago

Hey,

I trigger my suggestions via a cmp key bind, which utilizes the has_suggestion API. This works perfectly when the suggestion is below the cursor, but fails when there is a whitespace between the cursor and suggestion.

This commonly happens for me when defining a new function and insert a new line into the body of the function. Sometimes the indenting ends up wrong, and this is when Supermaven becomes unhappy.

How can I best use the has_suggestion API together with possible whitespace before the suggestion?

All the best

AlejandroSuero commented 3 weeks ago

@sQVe with this section of the README.md, I am not sure if you can use API with supermaven-nvim.util, but there is an utility for checking whitespace.

https://github.com/supermaven-inc/supermaven-nvim/blob/ef3bd1a6b6f722857f2f88d929dd4ac875655611/lua/supermaven-nvim/util.lua#L137-L139

[!NOTE] I am not sure the use case you are referring to exactly. I am visual guy so if you can provide a video with the issue you are experiencing, it will help me a lot to figure a solution or create one if needed.

In my case when I tested out the cmp implementation I only used cmp.sources = { "supermaven" } and disable_inline_completion and disable_keymaps on the plugin settings. With this minimal changes I didn't experience any indentation problems or anything of the sort.

sQVe commented 3 weeks ago

I was able to replicate it consistently and made a recording. The issue is when the snippet has whitespace within it. See video for reference.

https://github.com/supermaven-inc/supermaven-nvim/assets/2284724/41b424d2-6d29-4b39-a81e-ed97e8b982ee

I expand snippets and suggestions with Ctrl + L, which is why ^L is inserted when the expansion fails (the keymap uses the fallback).

My setup is similar to the recommendation here, with some small alterations since I use the builtin snippet support:

M.expand_snippet_or_suggestion = function(fallback)
  local suggestion = require('supermaven-nvim.completion_preview')
  local find_snippet_prefix = require('snippets.utils').find_snippet_prefix

  local word_before_cursor, row, col = cursor.get_word_before()
  local snippet = find_snippet_prefix(word_before_cursor)

  if snippet ~= nil then
    cursor.clear_before_by_length(#word_before_cursor)
    vim.snippet.expand(snippet.body)
  elseif suggestion.has_suggestion() then
    suggestion.on_accept_suggestion()
  else
    fallback()
  end
end

My supermaven setup is really simple with:

M.opts = {
  disable_keymaps = true,
}

Any ideas on how to solve this appreciated! ❤️

AlejandroSuero commented 3 weeks ago

I think this comment is related to the issue:

In the comment bellow that one, I go in more detail about it, but basic explanation is that all the accept behaviour is working the same at the moment, not sure if this is the intended behaviour or not yet, accept_suggestion and accept_word works if no whitespace is present.

Example:

[!NOTE] In the case of indentation if is equal to 2 spaces, it will insert 2 spaces, a tab if is 1 tab, etc..

If it is deep indented like 2 tabs of indentation (4 spaces) it will write the first 2 and then other 2.

Since I don't know if this is the desired behaviour of the plugin or not yet, I haven't created an issue about it yet, but feel free if you want to.

AlejandroSuero commented 3 weeks ago

This is with my setup that it wont use luasnip nor cmp but the issue is the same, only changes in my setup is keymaps.accept_suggestion = "<S-Tab>"

https://github.com/supermaven-inc/supermaven-nvim/assets/71392160/19cfaa9c-f11c-4d70-9019-06e3f203fafe

[!NOTE] As you can see if I insert a new line it puts me at the beginning but have to press <S-Tab> twice to get to the suggestion.

sQVe commented 3 weeks ago
  • Supermaven suggests: ' console.log("Hello world!")' <- it would insert a whitespace until it reaches the next one.

This is only the case when using the default bindings though, right? In cases like mine, where I use Ctrl + L it inputs ^L instead of a whitespace, which breaks the suggestion.


The following method, bound on Ctrl + L, works for me until the whitespace issue is resolved.

M.expand_snippet_or_suggestion = function(fallback)
  local suggestion = require('supermaven-nvim.completion_preview')
  local find_snippet_prefix = require('snippets.utils').find_snippet_prefix

  local word_before_cursor = cursor.get_word_before()
  local snippet = find_snippet_prefix(word_before_cursor)
  local is_whitespace_only_line = string.match(
    vim.api.nvim_get_current_line(),
    '^%s*$'
  ) ~= nil

  if snippet ~= nil then
    cursor.clear_before_by_length(#word_before_cursor)
    vim.snippet.expand(snippet.body)
  elseif suggestion.has_suggestion() then
    suggestion.on_accept_suggestion()
  elseif is_whitespace_only_line then
    vim.api.nvim_feedkeys(
      vim.api.nvim_replace_termcodes('<C-t>', true, false, true),
      'n',
      true
    )
  else
    fallback()
  end
end
AlejandroSuero commented 3 weeks ago

@sQVe in my case I tested it with <C-l> in keymaps.accept_suggestion and the whitespace problem still persists, doesn't insert ^L in my case, just the indent space as mentioned before.

I don't really know if it has something to do with vim.snippets or nvim-snippets I am trying to get it setup the way you have it, and in my case it throws an error when using it (I copied your "utils" function like cursor.<function-name> and find_snippet_prefix):

E5108: Error executing lua: ...hare/nvim/lazy/nvim-snippets/lua/snippets/utils/init.lua:341: attempt to index global 'Snippets' (a nil value)
stack traceback:
        ...hare/nvim/lazy/nvim-snippets/lua/snippets/utils/init.lua:341: in function 'find_snippet_prefix'
        ...rs/aome/.config/nvim/lua/custom/plugins/lsp/nvim-cmp.lua:56: in function 'on_keymap'
        ...rs/aome/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:145: in function 'callback'
        ....local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/keymap.lua:133: in function <....local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/keymap.lua:127>

In my case (my own config), I use luasnip and in cmp.setup({ snippet.expand = function(args) I use luansnip.lsp_expand(args.body) instead of vim.snippet.expand(args.body) and it doesn't trigger to insert ^L.