diff --git a/README.md b/README.md index 0f25814..fb1a377 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ can be a `LazyKeys` table with the following key-value pairs: - **[1]**: (`string`) lhs **_(required)_** - **[2]**: (`string|fun()`) rhs **_(optional)_** - **mode**: (`string|string[]`) mode **_(optional, defaults to `"n"`)_** +- **ft**: (`string|string[]`) `filetype` for buffer-local keymaps **_(optional)_** - any other option valid for `vim.keymap.set` Key mappings will load the plugin the first time they get executed. diff --git a/lua/lazy/core/handler/keys.lua b/lua/lazy/core/handler/keys.lua index cdf2243..5db4f0f 100644 --- a/lua/lazy/core/handler/keys.lua +++ b/lua/lazy/core/handler/keys.lua @@ -9,6 +9,7 @@ local Loader = require("lazy.core.loader") ---@field noremap? boolean ---@field remap? boolean ---@field expr? boolean +---@field ft? string|string[] ---@field id string ---@class LazyKeysHandler:LazyHandler @@ -53,7 +54,7 @@ end function M.opts(keys) local opts = {} for k, v in pairs(keys) do - if type(k) ~= "number" and k ~= "mode" and k ~= "id" then + if type(k) ~= "number" and k ~= "mode" and k ~= "id" and k ~= "ft" then opts[k] = v end end @@ -64,33 +65,62 @@ end function M:_add(keys) local lhs = keys[1] local opts = M.opts(keys) - vim.keymap.set(keys.mode, lhs, function() - local plugins = self.active[keys.id] - -- always delete the mapping immediately to prevent recursive mappings - self:_del(keys) - self.active[keys.id] = nil + ---@param buf? number + local function add(buf) + vim.keymap.set(keys.mode, lhs, function() + local plugins = self.active[keys.id] - Util.track({ keys = lhs }) - Loader.load(plugins, { keys = lhs }) - Util.track() + -- always delete the mapping immediately to prevent recursive mappings + self:_del(keys, buf) + self.active[keys.id] = nil - local feed = vim.api.nvim_replace_termcodes("" .. lhs, true, true, true) - -- insert instead of append the lhs - vim.api.nvim_feedkeys(feed, "i", false) - end, { - desc = opts.desc, - nowait = opts.nowait, - -- we do not return anything, but this is still needed to make operator pending mappings work - expr = true, - }) + if plugins then + Util.track({ keys = lhs }) + Loader.load(plugins, { keys = lhs }) + Util.track() + end + + local feed = vim.api.nvim_replace_termcodes("" .. lhs, true, true, true) + -- insert instead of append the lhs + vim.api.nvim_feedkeys(feed, "i", false) + end, { + desc = opts.desc, + nowait = opts.nowait, + -- we do not return anything, but this is still needed to make operator pending mappings work + expr = true, + buffer = buf, + }) + end + + if keys.ft then + vim.api.nvim_create_autocmd("FileType", { + pattern = keys.ft, + callback = function(event) + if self.active[keys.id] then + add(event.buf) + else + -- Only create the mapping if its managed by lazy + -- otherwise the plugin is supposed to manage it + if keys[2] then + self:_del(keys, event.buf) + end + end + end, + }) + else + add() + end end ---@param keys LazyKeys -function M:_del(keys) - pcall(vim.keymap.del, keys.mode, keys[1]) +---@param buf number? +function M:_del(keys, buf) + pcall(vim.keymap.del, keys.mode, keys[1], { buffer = buf }) if keys[2] then - vim.keymap.set(keys.mode, keys[1], keys[2], M.opts(keys)) + local opts = M.opts(keys) + opts.buffer = buf + vim.keymap.set(keys.mode, keys[1], keys[2], opts) end end