Wansmer / langmapper.nvim

A plugin that makes Neovim more friendly to non-English input methods 🤝
MIT License
128 stars 7 forks source link

nvim-cmp bindings don't work when using Latin layout #8

Closed ghost closed 1 year ago

ghost commented 1 year ago

nvim-cmp bindings like <C-e> (abort completion) and <C-f> (scroll down through documentation) work perfectly fine in Russian layout but not in English. <C-*> bindings set via nvim_set_keymap() work as usual.

Tested in https://github.com/Wansmer/nvim-config with only changes being xkb-switcher for get_current_layout_id and ru for id of Russian layout.

Wansmer commented 1 year ago

In my config (https://github.com/Wansmer/nvim-config) <C-e> and <C-f> remapped in lua/mappings.lua. That's why it no work with cmp bindings.

It is a strange, that it is not remapped while InsertEnter for cmp. I will check it later.

ghost commented 1 year ago

In your config <C-e> is mapped to abort in lua/config/plugins/cmp.lua and works as expected in insert mode. Same for <C-n> and <C-p>, and the behavior described in the issue persists after deleting relevant lines in `lua/mappings.lua'.

Thank you for your work, this plugin really saves me from a lot of pain!

danilshvalov commented 1 year ago

I'm facing a similar problem. in my case, no mapping related to nvim-cmp and ctrl does not work. It turned out to be solved with the following hack:

local keymap = require("cmp.utils.keymap")
keymap.set_map = function(bufnr, mode, lhs, rhs, opts)
  lhs = require("langmapper.utils").translate_keycode(lhs, "default", "ru")
  opts.buffer = bufnr
  vim.keymap.set(mode, lhs, rhs, opts)
end
Wansmer commented 1 year ago

I've looked at the nvim-cmp code, but so far I haven't been able to figure out why this problem occurs.

In addition to the option suggested above, you can disable hack_keymap and add require('langmapper').automapping({ buffer = true }).

I leave the issue open, because I will still figure it out.

eyev0 commented 1 year ago

@danilshvalov thanks for the snippet, I did manage to make cmp mappings work modifying it a little bit, here's my version

local keymap = require("cmp.utils.keymap")
local origin_set_map = keymap.set_map
local utils = require("langmapper.utils")
keymap.set_map = function(bufnr, mode, lhs, rhs, opts)
  origin_set_map(bufnr, mode, lhs, rhs, opts)
  origin_set_map(bufnr, mode, utils.translate_keycode(lhs, "default", "ru"), rhs, opts)
end
danilshvalov commented 1 year ago

As I understand it, the problem is that nvim-cmp uses the vim.api.nvim_buf_get_keymap function, which returns hacked mappings instead of the necessary ones. So far I have come up with the following hack to solve this problem:

local utils = require("langmapper.utils")

local original_nvim_buf_get_keymap = vim.api.nvim_buf_get_keymap
vim.api.nvim_buf_get_keymap = function(bufnr, mode)
  local maps = original_nvim_buf_get_keymap(bufnr, mode)
  local filtered = {}
  for _, map in ipairs(maps) do
    if map.lhs == utils.translate_keycode(map.lhs, "default", "ru") then
      table.insert(filtered, map)
    end
  end
  return filtered
end

local original_nvim_get_keymap = vim.api.nvim_get_keymap
vim.api.nvim_get_keymap = function(mode)
  local maps = original_nvim_get_keymap(mode)
  local filtered = {}
  for _, map in ipairs(maps) do
    if map.lhs == utils.translate_keycode(map.lhs, "default", "ru") then
      table.insert(filtered, map)
    end
  end
  return filtered
end

It also removes unnecessary mappings in which-key and telescope:

Screenshot 2023-04-30 at 23 48 06 Screenshot 2023-04-30 at 23 49 56
danilshvalov commented 1 year ago

nvim-cmp has several problems with the keymap.set_map substitution solution. So, for example, when pressing <C-j> without text, the input can completely freeze. The solution with the substitution of get_keymap lacks these disadvantages.

Wansmer commented 1 year ago

Fixed with #12, thanks @danilshvalov

For use with nvim-cmp:

local langmapper = require("langmapper")
langmapper.setup()
langmapper.hack_get_keymap()