Avoid expr mapping message (#738)

* Avoid display message by register mapping

* Escape to json

* Improve tests

* fmt

* lint

* Fix evacuate condition

* Default silent

* fallback mapping should be silent by default

* Support legacy nvim
This commit is contained in:
hrsh7th
2022-01-15 19:18:04 +09:00
committed by GitHub
parent 098182e2c2
commit 008de7eb8a
2 changed files with 64 additions and 46 deletions

View File

@@ -1,3 +1,4 @@
local cache = require('cmp.utils.cache')
local misc = require('cmp.utils.misc') local misc = require('cmp.utils.misc')
local api = require('cmp.utils.api') local api = require('cmp.utils.api')
@@ -101,15 +102,16 @@ keymap.listen = function(mode, lhs, callback)
end end
local bufnr = existing.buffer and vim.api.nvim_get_current_buf() or -1 local bufnr = existing.buffer and vim.api.nvim_get_current_buf() or -1
local fallback = keymap.evacuate(bufnr, mode, existing)
keymap.set_map(bufnr, mode, lhs, function() keymap.set_map(bufnr, mode, lhs, function()
if mode == 'c' and vim.fn.getcmdtype() == '=' then if mode == 'c' and vim.fn.getcmdtype() == '=' then
return keymap.feed_map(existing) return vim.api.nvim_feedkeys(keymap.t(fallback), 'it', true)
end end
callback( callback(
lhs, lhs,
misc.once(function() misc.once(function()
keymap.feed_map(existing) return vim.api.nvim_feedkeys(keymap.t(fallback), 'it', true)
end) end)
) )
end, { end, {
@@ -119,6 +121,56 @@ keymap.listen = function(mode, lhs, callback)
}) })
end end
---Evacuate existing keymapping.
---@param bufnr number
---@param mode string
---@param existing table
---@return string
keymap.evacuate = setmetatable({
cache = cache.new(),
}, {
__call = function(self, bufnr, mode, existing)
local fallback = self.cache:ensure({ bufnr, mode, existing.lhs }, function()
return string.format('<Plug>(cmp.u.k.evacuate:%s)', misc.id('cmp.utils.keymap.evacuate'))
end)
local callback = not existing.expr and existing.callback
keymap.set_map(bufnr, mode, fallback, function()
local lhs = keymap.t(existing.lhs)
local rhs
if existing.callback then
rhs = existing.callback()
elseif existing.expr then
rhs = vim.api.nvim_eval(keymap.t(existing.rhs))
else
rhs = keymap.t(existing.rhs)
end
if not existing.noremap then
if string.find(rhs, lhs, 1, true) == 1 then
rhs = string.gsub(rhs, '^' .. vim.pesc(lhs), string.format(keymap.t([[<C-r>=v:lua.vim.json.decode(%s)<CR>]]), vim.fn.string(vim.json.encode(lhs))))
end
end
return rhs
end, callback and {
expr = false,
callback = callback,
noremap = existing.noremap,
script = existing.script,
silent = true,
nowait = existing.nowait,
} or {
expr = true,
noremap = existing.noremap,
script = existing.script,
silent = true,
nowait = existing.nowait,
})
return fallback
end,
})
---Get map ---Get map
---@param mode string ---@param mode string
---@param lhs string ---@param lhs string
@@ -165,40 +217,12 @@ keymap.get_map = function(mode, lhs)
callback = nil, callback = nil,
noremap = true, noremap = true,
script = false, script = false,
silent = false, silent = true,
nowait = false, nowait = false,
buffer = false, buffer = false,
} }
end end
---Feed mapping object.
---@param map table
keymap.feed_map = function(map)
local lhs = keymap.t(map.lhs)
local rhs
if map.callback and not map.expr then
return map.callback()
elseif map.callback and map.expr then
rhs = map.callback()
elseif map.expr then
rhs = vim.api.nvim_eval(keymap.t(map.rhs))
else
rhs = keymap.t(map.rhs)
end
if map.noremap then
vim.api.nvim_feedkeys(rhs, 'itn', true)
else
if string.find(rhs, lhs, 1, true) == 1 then
rhs = string.gsub(rhs, '^' .. vim.pesc(lhs), '')
vim.api.nvim_feedkeys(rhs, 'itm', true)
vim.api.nvim_feedkeys(lhs, 'itn', true)
else
vim.api.nvim_feedkeys(rhs, 'itm', true)
end
end
end
---Set keymapping ---Set keymapping
keymap.set_map = setmetatable({ keymap.set_map = setmetatable({
callbacks = {}, callbacks = {},

View File

@@ -1,4 +1,3 @@
local feedkeys = require('cmp.utils.feedkeys')
local spec = require('cmp.utils.spec') local spec = require('cmp.utils.spec')
local keymap = require('cmp.utils.keymap') local keymap = require('cmp.utils.keymap')
@@ -32,7 +31,7 @@ describe('keymap', function()
assert.are.equal(keymap.to_keymap('|'), '<Bar>') assert.are.equal(keymap.to_keymap('|'), '<Bar>')
end) end)
describe('feedmap', function() describe('evacuate', function()
before_each(spec.before) before_each(spec.before)
it('expr & register', function() it('expr & register', function()
@@ -40,9 +39,8 @@ describe('keymap', function()
expr = true, expr = true,
noremap = false, noremap = false,
}) })
feedkeys.call('i', 'nx', function() local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '('))
keymap.feed_map(keymap.get_map('i', '(')) vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
end)
assert.are.same({ '(' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) assert.are.same({ '(' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
end) end)
@@ -55,9 +53,8 @@ describe('keymap', function()
expr = false, expr = false,
noremap = false, noremap = false,
}) })
feedkeys.call('i', 'nx', function() local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '('))
keymap.feed_map(keymap.get_map('i', '(')) vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
end)
assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
end) end)
@@ -69,10 +66,8 @@ describe('keymap', function()
expr = true, expr = true,
noremap = false, noremap = false,
}) })
feedkeys.call('i', 'n', function() local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '<Tab>'))
keymap.feed_map(keymap.get_map('i', '<Tab>')) vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
end)
feedkeys.call('', 'x')
assert.are.same({ 'foobar' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) assert.are.same({ 'foobar' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
end) end)
it('false', function() it('false', function()
@@ -80,9 +75,8 @@ describe('keymap', function()
expr = true, expr = true,
noremap = false, noremap = false,
}) })
feedkeys.call('i', 'nx', function() local fallback = keymap.evacuate(0, 'i', keymap.get_map('i', '<Tab>'))
keymap.feed_map(keymap.get_map('i', '<Tab>')) vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
end)
assert.are.same({ '\taiueo' }, vim.api.nvim_buf_get_lines(0, 0, -1, true)) assert.are.same({ '\taiueo' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
end) end)
end) end)