Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: default keymaps for cmp and snippets make typing difficult #2533

Open
3 tasks done
dyfrgi opened this issue Feb 9, 2024 · 18 comments
Open
3 tasks done

bug: default keymaps for cmp and snippets make typing difficult #2533

dyfrgi opened this issue Feb 9, 2024 · 18 comments
Labels
bug Something isn't working

Comments

@dyfrgi
Copy link

dyfrgi commented Feb 9, 2024

Did you check docs and existing issues?

  • I have read all the LazyVim docs
  • I have searched the existing issues of LazyVim
  • I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

v0.9.4

Operating system/version

Debian 12

Describe the bug

While typing, with the default friendly-snippets configuration from and keymaps, it will pull up snippets. If one of them is at the end of a line, you have to notice this and hit a different key from normal to avoid entering it. This substantially reduces possible input speed due to adding a round-trip through cmp before you can hit enter.

It also looks like lua/lazyvim/plugins/coding.lua is trying to configure C-CR to abort completion, but with this minimal configuration it currently inserts the first match instead.

Steps To Reproduce

Open a new file
Type something that triggers a default snippet at the end of a line (e.g. "m log m" will trigger an m/D/Y date snippet)
Hit enter

Expected Behavior

A newline appears

Repro

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  "folke/LazyVim",
  -- add any other plugins here
  { "LazyVim/LazyVim", import = "lazyvim.plugins" },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here
@dyfrgi dyfrgi added the bug Something isn't working label Feb 9, 2024
@dyfrgi
Copy link
Author

dyfrgi commented Feb 9, 2024

As a side note, the mappings for this aren't on the keymaps docs page, which made it take longer for me to figure out what was going on.

@dpetka2001
Copy link
Contributor

I don't quite understand what the bug is. Can you explain in detail? Hitting Enter while the nvim-cmp auto-completion menu is open will select the entry. If you want a new line while the auto-completion menu is open you have to press <C-Enter>. Otherwise you have to close the auto-completion menu with <C-e> and hit Enter to behave like normal Enter that inserts a new line. That's just the way the nvim-cmp plugin works. If you don't like the default mappings you can change them in your personal configuration to do what you'd like.

The mappings for this aren't on the keymaps docs page, because these are internal mappings to nvim-cmp and internal mappings aren't documented on the website.

@dyfrgi
Copy link
Author

dyfrgi commented Feb 9, 2024

Unfortunately, pressing <C-Enter> also does not work with the minimal repro I posted above. If you want to stay in insert mode, you can hit <C-e>, otherwise <Esc> also works.

A minimal fix for it is to add a user config like the following:

local cmp = require("cmp")
return {
 "hrsh7th/nvim-cmp",
  opts = {
    completion = {
      completeopt = "menu,menuone,noinsert,noselect",
    },
    mapping = cmp.mapping.preset.insert({
      ["<CR>"] = cmp.mapping.confirm({ select = false }),
    }),
  }
}

You need both the completeopt setting and the change to the keymap, as otherwise the default is to select the first item, and the <CR> mapping with select = false is ignored in favor of the global vim setting. This could be made a bit lazier by making the opts into a function, as right now "cmp" is unconditionally loaded.

Personally, I think that the current default is bad. Auto-completion should not insert random stuff that's completely unrelated to what I have written, like snippets regarding the date. It's one thing to automatically insert a partly typed variable name, it's another thing to insert an unrelated snippet. But if LazyVim devs want the current behavior, then maybe this could be added to the recipes page?

In the course of figuring out how to fix this for my own configuration, I also noticed a couple of minor doc bugs. nvim-cmp appears twice on the plugins page; here is the second occurence: https://www.lazyvim.org/plugins/coding#nvim-cmp-1. And the first one has both the options and full spec out of sync with the current LazyVim code, missing at least luasnip from sources, though maybe there's other things too.

@dpetka2001
Copy link
Contributor

This is not a bug. It's a default that was chosen by the maintainer and the users can freely change that behavior in their personal configuration according to their liking. Not everyone has the same preferences. select = false is being ignored by the LSP and that's why you also have to specify opts.completion.completeopt. This is not a behavior that is specified by LazyVim. You can also follow this recipe from nvim-cmp wiki that only selects with Enter if an entry is selected.

Regarding the docs, there is a second instance of nvim-cmp because it is defined in 2 different places. The second one is being defined in the Luasnip spec and that seperation was made, so that users that use other snippets engines could add their corresponding nvim-cmp source.

Since all that you describe is just personal preference, I would advise to close this issue and do whatever you want in your personal configuration. This is not a LazyVim bug after all.

@abeldekat
Copy link
Contributor

Personally, I think that the current default is bad.

@dyfrgi,

Please close this issue. This is not a bug, but a personal preference.

@dyfrgi
Copy link
Author

dyfrgi commented Feb 12, 2024

I think that having good defaults is important to this project. That is really the core thing that LazyVim provides - a set of defaults and a starting point for a neovim configuration. As such, a bad default is a bug, or at the minimum having good defaults is a feature. I also think that a default which makes it so that "just type some stuff in insert mode without hitting any commands" doesn't work out of the box is a bad default. I also think that having confusing documentation, where a plugin is shown as having multiple configurations, one of which is blank and doesn't describe anything close to how it's configured, is a documentation bug.

I also think that having <C-Enter> not cancel out of completion without selecting anything, as I am told it is supposed to do, and which I mentioned in the original report will actually select something, is a clear and obvious bug.

Perhaps those other two issues (<C-Enter> and the documentation) should be separated out and this issue should be kept solely about the default. That would be fine by me, but I won't be filing the other bugs as I currently feel like my contributions aren't welcome here.

It seems like you disagree with some of the above. I'm still not clear on why. Do you think that good defaults aren't important to this project? Or that having a good default is a feature, and not a bug? Or that this is a good default? Or that, regardless of whether it is a good default, it is somehow not our place to question it? If the project maintainers want to close this as "NOTABUG WONTFIX" I won't re-open it.

@abeldekat
Copy link
Contributor

Key <c-cr> might not be recognized by your terminal.

You can test this by opening Neovim and entering insert mode.
Press <c-v> and then: <c-cr>. That should show <c-cr>

With kitty, the key works as expected. When using tmux with kitty, some additional tmux tweaking might be necessary.

In alacritty, the following needs to be added to alacritty.toml:

[[keyboard.bindings]]
# accept ctrl enter
key = "Enter"
mods = "Control"
chars = "\u001b[13;5u"

@wren
Copy link

wren commented Feb 19, 2024

I had very similar troubles when I started using LazyVim.

I ended up figuring some of it out and putting in my own config (see here). This is obviously tailored to my own preferences, and there might be better ways to accomplish the goal, but it's been working for purposed for a few months now.

Please note that it really took way too long to learn how to map a new key for completion, and required a bunch of research into a plugin

But I completely agree that it's a very confusing default (honestly, I think that it's antithetical to Vim's core idea of "modes," but that's probably opening a can of worms that would be unproductive to discuss in this issue). It also took way too long to learn how to fix the behavior, and required deep research into a plugin that I didn't feel like I should've had to learn about.

I agree that this should be fixed as the default in LazyVim if at all possible. But even if not the default, having the option available as an extra could really make it significantly easier to pick up LazyVim for people bothered by this behavior.

@shoop
Copy link

shoop commented Feb 29, 2024

Just wanted to chime in here that I have the same experience as @dyfrgi and @wren . Not sure if it is my terminal not accepting CTRL-Enter, but it's not very discoverable and it sucks that the only way I knew how get my "enter" is to press ESC first. In other words, for me it is also a bad default.

@folke
Copy link
Collaborator

folke commented Mar 7, 2024

I actually kinda agree. It wasn't really an issue before for me, but now with copilot and others, there's pretty much always a completion available.

My muscle memory has already adapted and I use esc or c-enter automatically.

Not sure what a good way to fix this could be.

Need to think about it.

@dyfrgi
Copy link
Author

dyfrgi commented Mar 8, 2024

That's a very good point about copilot. The thing that was biting me was snippets, not symbols. I wonder if it's possible to configure this to work differently based on which source supplied the completion? Or even based on some confidence value supplied by the source.

@shjohnson-pi
Copy link

I'm new to vim, Neovim, and LazyVim, so I was also confused by the default behavior and how to change it.

I managed to get my desired settings with the following saved at ~/.config/nvim/lua/plugins/steven.lua

  • <Enter> is unmapped (only inserts newlines)
  • <Tab> to autocomplete
return {
  -- Disable default Tab Key mappings in LuaSnip
  {
    "L3MON4D3/LuaSnip",
    keys = function()
      return {}
    end,
  },
  {
    "hrsh7th/nvim-cmp",
    ---@param opts cmp.ConfigSchema
    opts = function(_, opts)
      local cmp = require("cmp")
      opts.mapping = cmp.mapping.preset.insert({
        -- Press Tab to autocomplete
        ["<Tab>"] = cmp.mapping.confirm({ select = true }),
      })
    end,
  },
}

@victorkamoto
Copy link

victorkamoto commented Mar 31, 2024

Not sure what a good way to fix this could be.

How about this?
https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#safely-select-entries-with-cr

image

@Dogacel
Copy link

Dogacel commented Apr 3, 2024

I highly recommend remapping <CR> for various reasons,

  1. Not very intuitive
  2. Not all terminals support <CR-Enter> and at that point it becomes very annoying to use autocomplete, especially with copilot suggesting junk everywhere.

I'm using this,
https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#intellij-like-mapping

What grinds me with Tab completion is I don't know how to dismiss the cmp and just insert a regular <Tab> character 🙂 I tried mapping stuff like however it did not work.

I use warp and ironically they are sponsor for a few nvim plugins.

Any suggestion is appreciated.

My plugin:

local cmp = require("cmp")
return {
  "hrsh7th/nvim-cmp",
  opts = {
    completion = {
      completeopt = "menu,menuone,noinsert,noselect",
    },
    mapping = {
      ["<CR>"] = cmp.mapping(function(fallback)
        cmp.confirm({ select = false })
        fallback()
      end),
      ["<S-Tab>"] = cmp.mapping(function(fallback)
        cmp.confirm({ select = false })
        fallback()
      end),
      ["<Tab>"] = cmp.mapping(function(fallback)
        -- This little snippet will confirm with tab, and if no entry is selected, will confirm the first item
        if cmp.visible() then
          local entry = cmp.get_selected_entry()
          if not entry then
            cmp.confirm({ select = false })
            fallback()
            -- cmp.select_next_item({ behavior = cmp.SelectBehavior.Select })
          else
            cmp.confirm({ select = true })
          end
        else
          fallback()
        end
      end, { "i", "s", "c" }),
    },
  },
}

@victorkamoto
Copy link

What grinds me with Tab completion is I don't know how to dismiss the cmp and just insert a regular <Tab> character 🙂 I tried mapping stuff like however it did not work.

<C-e> is already mapped to dismiss/abort a completion

@Dogacel
Copy link

Dogacel commented Apr 4, 2024

What grinds me with Tab completion is I don't know how to dismiss the cmp and just insert a regular <Tab> character 🙂 I tried mapping stuff like however it did not work.

<C-e> is already mapped to dismiss/abort a completion

Thanks I did not know that, however it is still annoying because I have to <C-e>Tab<C-e>Tab... each time 😛 Just having to <C-Tab><C-Tab>.. feels more intuitive.

@victorkamoto
Copy link

victorkamoto commented Apr 4, 2024

The lazyvim config doesn't cater for tab completion. Since you added it yourself, you'll have to make custom mappings to cater for your usecase

@matkarlg
Copy link

matkarlg commented May 19, 2024

An option is to only switch the <CR> and <C-CR> keys.

To choose the autocomplete. Instead of escaping copilot before a newline.
Instead of <Esc><CR>, <C-CR> or <C-e><CR> for a newline in insert mode.

  • <CR> always newline
  • <C-CR> for insert autocomplete
  • <S-CR> for replace autocomplete
{
  "nvim-cmp",
  ---@param opts cmp.ConfigSchema
  opts = function(_, opts)
    local cmp = require("cmp")

    -- <CR> always newline
    opts.mapping["<CR>"] = function(fallback)
      cmp.abort()
      fallback()
    end

    -- Confirm insert completion with <C-CR>
    opts.mapping["<C-CR>"] = cmp.mapping.confirm({ select = true })

    -- Confirm replace completion with <S-CR>, already in
    -- https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/coding.lua
},

To also support terminals with <C-CR> issues, we change the above <CR> mapping to https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#safely-select-entries-with-cr


If it helps anyone to get the <C-CR> <S-CR> mappings to work inside tmux with kitty terminal.

tmux

bind -n S-Enter send-keys Escape "[13;2u"
bind -n C-Enter send-keys Escape "[13;5u"

kitty

map shift+enter send_text all \x1b[13;2u
map ctrl+enter send_text all \x1b[13;5u

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

10 participants