Skip to content

Commit

Permalink
feat!: lazy keymap support (#41)
Browse files Browse the repository at this point in the history
* feat: lazy keymap support

* tests: add lazy tests

* chore: annotation fixes

* refactor!: robust tests and change default config

* chore: lint tests

* refactor: tidy min init

* refactor: tidy min init

---------

Co-authored-by: tris203 <admin@snappeh.com>
  • Loading branch information
tris203 and tris203 committed Dec 23, 2023
1 parent 4b11f0f commit c6705da
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 }"
11 changes: 4 additions & 7 deletions lua/hawtkeys/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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[]

Expand All @@ -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,
Expand All @@ -46,9 +46,6 @@ local _defaultSet = {
optsIndex = 4,
method = "dot_index_expression",
}, --method 2
["whichkey.register"] = {
method = "which_key",
}, -- method 6
}

---@type HawtKeyConfig
Expand Down
62 changes: 54 additions & 8 deletions lua/hawtkeys/ts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,6 +26,9 @@ local tsQuery = require("nvim-treesitter.query")
---@class WhichKeyMapargs
---@field method WhichKeyMethods

---@class LazyKeyMapArgs
---@field method LazyMethods

---@type table<string, boolean>
local scannedFiles = {}

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 = {}
Expand All @@ -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
120 changes: 111 additions & 9 deletions tests/hawtkeys/ts_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -28,15 +72,6 @@ describe("Treesitter can extract keymaps", function()
eq(':echo "hello"<CR>', 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("<leader>3", keymap[1].lhs)
eq(':lua print("hello")<CR>', keymap[1].rhs)
end)

it("Extract short dot index aliasesd keymap", function()
hawtkeys.setup({
customMaps = {
Expand Down Expand Up @@ -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("<leader>3", keymap[1].lhs)
eq(':lua print("hello")<CR>', 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 = {
{
"<leader>1",
":lua print(1)<CR>",
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("<leader>1", lazyKeymaps[1].lhs)
eq(":lua print(1)<CR>", lazyKeymaps[1].rhs)
eq(
"Lazy Init:ellisonleao/nvim-plugin-template",
lazyKeymaps[1].from_file
)
end)
end)
1 change: 1 addition & 0 deletions tests/hawtkeys/ui_spec.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---@diagnostic disable-next-line: undefined-field
local eq = assert.are.same

local MiniTest = require("mini.test")
Expand Down
2 changes: 1 addition & 1 deletion tests/hawtkeys/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
52 changes: 38 additions & 14 deletions tests/minimal_init.lua
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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",
Expand All @@ -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")
Expand All @@ -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

0 comments on commit c6705da

Please sign in to comment.