local M = require('module'):new() local map = require('lib/map') function M:initialize(config) self.plugins = nukevim.modules:get('plugins') self.keymap = {} end function M:register() if (self.config.ui.enable) then self.plugins:add('folke/which-key.nvim', { branch = "main" }, { { mode = 'n', key = { '?', '?', '?' }, map = ":lua nukevim.modules:get('keymap'):show()", hidden = true }, { mode = 'i', key = { '?', '?', '?' }, map = " lua nukevim.modules:get('keymap'):show()", hidden = true }, { mode = 'v', key = { '?', '?', '?' }, map = " lua nukevim.modules:get('keymap'):show()", hidden = true }, }) end if (self.config.keys ~= nil) then for idx, key in ipairs(self.config.keys) do self:add(key) end end end function M:show() mode = vim.fn.mode() buffer = vim.fn.expand('%') -- n, i, v/V show_buffer_keys = false for i=1,#self.keymap do if (self.keymap[i].buffer ~= nil and self.keymap[i].buffer == buffer) then show_buffer_keys = true break end end if (show_buffer_keys and false) then -- buf = vim.api.nvim_create_buf(false, true) -- win = vim.api.nvim_open_win(buf, false, { -- relative = "editor", -- height = 6, -- focusable = false, -- anchor = "SW", -- style = "minimal", -- row = vim.o.lines, -- col = 0, -- width = vim.o.columns -- }) -- vim.api.nvim_buf_set_option(buf, "filetype", "WhichKey") -- vim.api.nvim_buf_set_option(buf, "buftype", "nofile") -- vim.api.nvim_win_set_option(win, "winhighlight", "NormalFloat:WhichKeyFloat") -- vim.api.nvim_win_set_option(win, "foldmethod", "manual") -- -- vim.api.nvim_win_set_option(win, "winblend", true) -- vim.cmd([[autocmd! WinClosed lua nukevim.modules:get('keymap'):closed()]]) -- vim.api.nvim_buf_set_lines(buf, 0, -1, false, { -- "hello, world!", -- "this is a window" -- }) else require('which-key').show('', { mode = mode }) end end function M:registerBufferLocal() filetype = vim.bo.filetype local_binds = {} for i=1,#self.keymap do if (self.keymap[i].filetype ~= nil and self.keymap[i].filetype == filetype) then table.insert(local_binds, self.keymap[i]) end end self:registerWithWhichKey(local_binds, { buffer = 0 }) end function M:map(mode, key, map, options) M:add({ mode = mode, key = key, map = map, options = options or { noremap = true } }) end function M:add(keymap) -- todo: validate keymap.mode = keymap.mode or nil keymap.key = keymap.key or nil if (type(keymap.key) == "string") then parts = {} for part in string.gmatch(keymap.key, '.') do table.insert(parts, part) end keymap.key = parts end keymap.map = keymap.map or nil keymap.options = keymap.options or { noremap = true } keymap.label = keymap.label or nil keymap.virtual = keymap.virtual or false keymap.hidden = keymap.hidden or false keymap.group = keymap.group or false keymap.with = keymap.with or {} keymap.without = keymap.without or {} table.insert(self.keymap, keymap) end function M:commit() if (self.plugins:has('folke/which-key.nvim') and self.config.ui.enable) then self:commitWithWhichKey() else self:commitWithNative() end end function M:commitWithWhichKey() -- Set up whichkey whichkey = require('which-key') whichkey.setup({ ignore_missing = true, plugins = { marks = true, registers = true, spelling = { enabled = true, suggestions = 20 }, presets = { operators = self.config.ui.show_builtin, motions = self.config.ui.show_builtin, text_objects = self.config.ui.show_builtin, windows = self.config.ui.show_builtin, nav = self.config.ui.show_builtin, z = self.config.ui.show_builtin, g = self.config.ui.show_builtin, } } }) -- Build tree of key binds self:registerWithWhichKey(self.keymap) end function M:registerWithWhichKey(keys, opts) opts = opts or {} tree = {} node = nil for idx, keymap in ipairs(keys) do if (keymap.hidden) then if (keymap.label ~= nil) then keymap.options.desc = keymap.label end map(keymap.mode, table.concat(keymap.key, ""), keymap.map, keymap.options) -- TODO: Hack-y hack. elseif (keymap.filetype ~= nil and opts.buffer == nil) then -- this only applies to a specific filetype, register() will register -- it buffer-local when it's opened else if (tree[keymap.mode] == nil) then tree[keymap.mode] = {} end node = tree[keymap.mode] for i = 1, #keymap.key - 1 do if (node[keymap.key[i]] == nil) then node[keymap.key[i]] = {} end node = node[keymap.key[i]] end last = keymap.key[#keymap.key] have_all_with = true for idx,plugin in ipairs(keymap.with) do have_all_with = have_all_with and self.plugins:has(plugin) end have_any_without = false for idx,plugin in ipairs(keymap.without) do have_any_without = have_any_without or self.plugins:has(plugin) end if (have_all_with and not have_any_without) then if (keymap.group) then node[last] = node[last] or {} node[last]['name'] = keymap.label elseif (keymap.virtual) then node[last] = { keymap.label } else node[last] = { keymap.map, keymap.label or nil } if (keymap.options.noremap) then node[last].noremap = true end if (keymap.options.silent) then node[last].silent = true end if (keymap.options.nowait) then node[last].nowait = true end end end end end for mode, node in pairs(tree) do local_opts = {} for k, v in pairs(opts) do local_opts[k] = v end local_opts['mode'] = mode whichkey.register(node, local_opts) end end function M:commitWithNative() for idx, keymap in ipairs(self.keymap) do if (keymap.label ~= nil) then keymap.options.desc = keymap.label end if (keymap.virtual ~= true) then have_all_with = true for plugin in ipairs(keymap.with) do have_all_with = have_all_with and self.plugins:has(plugin) end have_any_without = false for plugin in ipairs(keymap.without) do have_any_without = have_any_without or self.plugins:has(plugin) end if (have_all_with and not have_any_without) then map(keymap.mode, table.concat(keymap.key, ''), keymap.map, keymap.options) end end end end return M