diff --git a/Makefile b/Makefile index 54bc132..c6f6754 100644 --- a/Makefile +++ b/Makefile @@ -8,4 +8,4 @@ test: --headless \ --noplugin \ -u ${TESTS_INIT} \ - -c "PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${TESTS_INIT}' }" + -c "PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${TESTS_INIT}', sequential = true }" diff --git a/lua/hawtkeys/init.lua b/lua/hawtkeys/init.lua index 310c0d3..eea4311 100644 --- a/lua/hawtkeys/init.lua +++ b/lua/hawtkeys/init.lua @@ -10,8 +10,8 @@ local M = {} ---@field homerow number ---@field powerFingers number[] ---@field keyboardLayout HawtKeySupportedKeyboardLayouts ----@field keyMapSet { [string] : TSKeyMapArgs | WhichKeyMapargs } ----@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs } | nil +---@field keyMapSet { [string] : TSKeyMapArgs | WhichKeyMapargs | LazyKeyMapArgs } +---@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs | LazyKeyMapArgs } | nil ---@field highlights HawtKeyHighlights ---@field lhsBlacklist string[] @@ -26,11 +26,11 @@ local M = {} ---@field homerow number | nil ---@field powerFingers number[] | nil ---@field keyboardLayout HawtKeySupportedKeyboardLayouts | nil ----@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs } | nil +---@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs | LazyKeyMapArgs } | nil ---@field highlights HawtKeyHighlights | nil ---@field lhsBlacklist string[] | nil ----@type { [string] : TSKeyMapArgs | WhichKeyMapargs }--- +---@type { [string] : TSKeyMapArgs | WhichKeyMapargs | LazyKeyMapArgs } local _defaultSet = { ["vim.keymap.set"] = { modeIndex = 1, @@ -46,9 +46,6 @@ local _defaultSet = { optsIndex = 4, method = "dot_index_expression", }, --method 2 - ["whichkey.register"] = { - method = "which_key", - }, -- method 6 } ---@type HawtKeyConfig diff --git a/lua/hawtkeys/ts.lua b/lua/hawtkeys/ts.lua index 0075311..0213b09 100644 --- a/lua/hawtkeys/ts.lua +++ b/lua/hawtkeys/ts.lua @@ -9,9 +9,11 @@ local tsQuery = require("nvim-treesitter.query") ---@alias VimModes 'n' | 'x' | 'v' | 'i' ---@alias WhichKeyMethods 'which_key' ---- ----@alias TreeSitterMethods 'dot_index_expression' | 'function_call' | 'expression_list' ---- + +---@alias LazyMethods 'lazy' + +---@alias TreeSitterMethods 'dot_index_expression' | 'function_call' + ---@alias SetMethods WhichKeyMethods | TreeSitterMethods ---@class TSKeyMapArgs @@ -24,6 +26,9 @@ local tsQuery = require("nvim-treesitter.query") ---@class WhichKeyMapargs ---@field method WhichKeyMethods +---@class LazyKeyMapArgs +---@field method LazyMethods + ---@type table local scannedFiles = {} @@ -130,7 +135,7 @@ local function find_maps_in_file(filePath) local fileContent = Path:new(filePath):read() local parser = vim.treesitter.get_string_parser(fileContent, "lua", {}) -- Get the Lua parser local tree = parser:parse()[1]:root() - local tsKemaps = {} + local tsKeymaps = {} -- TODO: This currently doesnt always work, as the options for helper functions are different, -- need to use TS to resolve it back to a native keymap local dotIndexExpressionQuery = ts.parse_query( @@ -213,7 +218,7 @@ local function find_maps_in_file(filePath) end map.mode = table.concat(modes, ", ") end - table.insert(tsKemaps, map) + table.insert(tsKeymaps, map) end end end @@ -301,7 +306,7 @@ local function find_maps_in_file(filePath) end map.mode = table.concat(modes, ", ") end - table.insert(tsKemaps, map) + table.insert(tsKeymaps, map) end end end @@ -342,13 +347,43 @@ local function find_maps_in_file(filePath) rhs = mapping.cmd, from_file = filePath, } - table.insert(tsKemaps, map) + table.insert(tsKeymaps, map) end end end end - return tsKemaps + return tsKeymaps +end + +---@return table +local function get_keymaps_from_lazy() + local lazyKeyMaps = {} + for _, args in pairs(hawtkeys.config.keyMapSet) do + if args.method == "lazy" then + local ok, lazy = pcall(function() + return require("lazy").plugins() + end) + if not ok then + vim.print("Lazy Loading requires Lazy") + break + end + for _, v in ipairs(lazy) do + if v and v._ and v._.handlers and v._.handlers.keys then + for _, key in pairs(v._.handlers.keys) do + local map = { + lhs = key.lhs, + rhs = key.rhs, + mode = key.mode, + from_file = "Lazy Init:" .. tostring(v[1]), + } + table.insert(lazyKeyMaps, map) + end + end + end + end + end + return lazyKeyMaps end ---@return table @@ -420,6 +455,16 @@ function M.get_all_keymaps() end end + if + hawtkeys.config.keyMapSet.lazy + and hawtkeys.config.keyMapSet.lazy.method == "lazy" + then + local lazyKeyMaps = get_keymaps_from_lazy() + for _, keymap in ipairs(lazyKeyMaps) do + table.insert(keymaps, keymap) + end + end + local vimKeymaps = get_keymaps_from_vim() returnKeymaps = utils.merge_tables(keymaps, vimKeymaps) scannedFiles = {} @@ -432,5 +477,6 @@ end M.find_maps_in_file = find_maps_in_file M.get_keymaps_from_vim = get_keymaps_from_vim +M.get_keymaps_from_lazy = get_keymaps_from_lazy return M diff --git a/tests/hawtkeys/ts_spec.lua b/tests/hawtkeys/ts_spec.lua index 985ade7..66ef80a 100644 --- a/tests/hawtkeys/ts_spec.lua +++ b/tests/hawtkeys/ts_spec.lua @@ -5,9 +5,53 @@ local eq = assert.are.same ---@diagnostic disable-next-line: undefined-field local falsy = assert.falsy +describe("Uninstalled plugins", function() + before_each(function() + require("plenary.reload").reload_module("hawtkeys") + ts.reset_scanned_files() + hawtkeys.setup({ + customMaps = { + ["lazy"] = { + method = "lazy", + }, + ["whichkey.register"] = { + method = "which_key", + }, + }, + }) + vim.cmd("messages clear") + end) + it("which key doesnt cause error", function() + local ok, _ = pcall(function() + return require("which-key") + end) + local keymapWhichKey = ts.find_maps_in_file( + "tests/hawtkeys/example_configs/which-key.register_keymap.lua" + ) + local messages = vim.api.nvim_exec2("messages", { output = true }) + eq(false, ok) + eq(0, #keymapWhichKey) + eq({ + ["output"] = "Which Key Mappings require which-key to be installed", + }, messages) + end) + + it("Lazy doesnt cause error", function() + local ok, _ = pcall(function() + return require("lazy") + end) + local keymapLazy = ts.get_keymaps_from_lazy() + local messages = vim.api.nvim_exec2("messages", { output = true }) + eq(false, ok) + eq(0, #keymapLazy) + eq({ ["output"] = "Lazy Loading requires Lazy" }, messages) + end) +end) + describe("Treesitter can extract keymaps", function() before_each(function() require("plenary.reload").reload_module("hawtkeys") + ts.reset_scanned_files() hawtkeys.setup({}) end) it("extract vim.api.nvim_set_keymap()", function() @@ -28,15 +72,6 @@ describe("Treesitter can extract keymaps", function() eq(':echo "hello"', keymap[1].rhs) end) - it("extract whichkey.register() keymap", function() - local keymap = ts.find_maps_in_file( - "tests/hawtkeys/example_configs/which-key.register_keymap.lua" - ) - eq("n", keymap[1].mode) - eq("3", keymap[1].lhs) - eq(':lua print("hello")', keymap[1].rhs) - end) - it("Extract short dot index aliasesd keymap", function() hawtkeys.setup({ customMaps = { @@ -95,3 +130,70 @@ describe("Treesitter can extract keymaps", function() eq(beforeCount, finalCount) end) end) + +describe("Which Key Managed Maps", function() + before_each(function() + require("plenary.reload").reload_module("hawtkeys") + require("tests.minimal_init").loadWhichKey() + ts.reset_scanned_files() + hawtkeys.setup({ + customMaps = { + ["whichkey.register"] = { + method = "which_key", + }, + }, + }) + end) + + it("extract whichkey.register() keymap", function() + local keymap = ts.find_maps_in_file( + "tests/hawtkeys/example_configs/which-key.register_keymap.lua" + ) + eq("n", keymap[1].mode) + eq("3", keymap[1].lhs) + eq(':lua print("hello")', keymap[1].rhs) + end) +end) + +describe("Lazy Managed Plugins", function() + before_each(function() + require("plenary.reload").reload_module("hawtkeys") + ts.reset_scanned_files() + hawtkeys.setup({ + customMaps = { + ["lazy"] = { + method = "lazy", + }, + }, + }) + require("tests.minimal_init").loadLazy() + vim.g.lazy_did_setup = false + vim.go.loadplugins = true + for modname in pairs(package.loaded) do + if modname:find("lazy") == 1 then + package.loaded[modname] = nil + end + end + local lazy = require("lazy") + lazy.setup({ + "ellisonleao/nvim-plugin-template", + keys = { + { + "1", + ":lua print(1)", + desc = "Test Lazy Print 1", + }, + }, + }) + end) + it("extract keys set in a Lazy init", function() + local lazyKeymaps = ts.get_keymaps_from_lazy() + eq("n", lazyKeymaps[1].mode) + eq("1", lazyKeymaps[1].lhs) + eq(":lua print(1)", lazyKeymaps[1].rhs) + eq( + "Lazy Init:ellisonleao/nvim-plugin-template", + lazyKeymaps[1].from_file + ) + end) +end) diff --git a/tests/hawtkeys/ui_spec.lua b/tests/hawtkeys/ui_spec.lua index 43a27c2..42a45f3 100644 --- a/tests/hawtkeys/ui_spec.lua +++ b/tests/hawtkeys/ui_spec.lua @@ -1,3 +1,4 @@ +---@diagnostic disable-next-line: undefined-field local eq = assert.are.same local MiniTest = require("mini.test") diff --git a/tests/hawtkeys/utils_spec.lua b/tests/hawtkeys/utils_spec.lua index 1558cba..f36f8ae 100644 --- a/tests/hawtkeys/utils_spec.lua +++ b/tests/hawtkeys/utils_spec.lua @@ -21,7 +21,7 @@ describe("utils functionality", function() local keymaps = { { lhs = "a", rhs = "1" }, { lhs = "a", rhs = "2" }, - { lhs = "b", rhs = "3"}, + { lhs = "b", rhs = "3" }, { lhs = "b", rhs = "4" }, } local duplicates = utils.find_duplicates(keymaps) diff --git a/tests/minimal_init.lua b/tests/minimal_init.lua index 5f7fab2..599ea61 100644 --- a/tests/minimal_init.lua +++ b/tests/minimal_init.lua @@ -1,6 +1,39 @@ +local M = {} + +function M.loadLazy() + local lazy_dir = os.getenv("LAZY_DIR") or "/tmp/lazy.nvim" + if vim.fn.isdirectory(lazy_dir) == 0 then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazy_dir, + }) + end + vim.opt.rtp:append(lazy_dir) + print("Installed Lazy to " .. lazy_dir) +end + +function M.loadWhichKey() + local whichkey_dir = os.getenv("WHICHKEY_DIR") or "/tmp/which-key.nvim" + if vim.fn.isdirectory(whichkey_dir) == 0 then + vim.fn.system({ + "git", + "clone", + "https://github.com/folke/which-key.nvim", + whichkey_dir, + }) + end + vim.opt.rtp:append(whichkey_dir) + vim.cmd("runtime plugin/which-key.vim") + print("Installed WhichKey to " .. whichkey_dir) + require("which-key").setup({}) +end + local plenary_dir = os.getenv("PLENARY_DIR") or "/tmp/plenary.nvim" local treesitter_dir = os.getenv("TREESITTER_DIR") or "/tmp/nvim-treesitter" -local whichkey_dir = os.getenv("WHICHKEY_DIR") or "/tmp/which-key.nvim" local mini_dir = os.getenv("MINI_DIR") or "/tmp/mini-test" if vim.fn.isdirectory(plenary_dir) == 0 then vim.fn.system({ @@ -18,14 +51,6 @@ if vim.fn.isdirectory(treesitter_dir) == 0 then treesitter_dir, }) end -if vim.fn.isdirectory(whichkey_dir) == 0 then - vim.fn.system({ - "git", - "clone", - "https://github.com/folke/which-key.nvim", - whichkey_dir, - }) -end if vim.fn.isdirectory(mini_dir) == 0 then vim.fn.system({ "git", @@ -37,8 +62,9 @@ end vim.opt.rtp:append(".") vim.opt.rtp:append(plenary_dir) vim.opt.rtp:append(treesitter_dir) -vim.opt.rtp:append(whichkey_dir) vim.opt.rtp:append(mini_dir) +require("plenary.busted") +require("mini.test").setup() vim.cmd("runtime plugin/plenary.vim") vim.cmd("runtime plugin/treesitter.vim") @@ -48,7 +74,5 @@ require("nvim-treesitter.configs").setup({ enable = true, }, }) -vim.cmd("runtime plugin/which-key.vim") -require("which-key").setup({}) -require("plenary.busted") -require("mini.test").setup() + +return M