Skip to content

Commit

Permalink
feat: partial match for multi-mode maps in duplicates (#57)
Browse files Browse the repository at this point in the history
fix: capture more than two duplicates of a mapping
refactor: store modes as table, convert to string on render
  • Loading branch information
willothy committed Jan 2, 2024
1 parent 31f0a7f commit 954b4d9
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 6 deletions.
4 changes: 2 additions & 2 deletions lua/hawtkeys/ts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ local function find_maps_in_file(filePath)
end
i = i + 1
end
map.mode = table.concat(modes, ", ")
map.mode = modes
end
table.insert(tsKeymaps, map)
end
Expand Down Expand Up @@ -311,7 +311,7 @@ local function find_maps_in_file(filePath)
end
i = i + 1
end
map.mode = table.concat(modes, ", ")
map.mode = modes
end
table.insert(tsKeymaps, map)
end
Expand Down
10 changes: 8 additions & 2 deletions lua/hawtkeys/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,16 @@ M.show_all = function()
local pattern = "%s (%s) - %s"
for i, data in ipairs(all) do
local filename = utils.reduceHome(data.from_file)
local line = pattern:format(data.lhs, data.mode, filename)
local mode
if type(data.mode) == "table" then
mode = table.concat(data.mode, ", ")
else
mode = data.mode
end
local line = pattern:format(data.lhs, mode, filename)

local offset_mode = #data.lhs + 2
local offset_file = offset_mode + #data.mode + 2
local offset_file = offset_mode + #mode + 2

local l2 = data.rhs
if l2 == nil or l2 == "" then
Expand Down
42 changes: 40 additions & 2 deletions lua/hawtkeys/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,55 @@ function M.merge_tables(t1, t2)
return t3
end

---Returns true if a and b contain any of the same values
---@param a string | string[]
---@param b string | string[]
---@return boolean
local function match_modes(a, b)
if type(a) == "string" then
a = { a }
end
if type(b) == "string" then
b = { b }
end
-- note: there will only ever be a few modes in each table. this is fine.
for _, v in ipairs(a) do
for _, v2 in ipairs(b) do
if v == v2 then
return true
end
end
end
return false
end

---@param keymaps HawtkeysKeyMapData[]
---@return { [string]: HawtkeysKeyMapData[] }
function M.find_duplicates(keymaps)
local duplicates = {}
local seen = {}
for _, v in pairs(keymaps) do
for _, v2 in pairs(keymaps) do
if v.lhs == v2.lhs and v.mode == v2.mode and v.rhs ~= v2.rhs then
duplicates[v.lhs] = { v, v2 }
if
v.lhs == v2.lhs
and v.rhs ~= v2.rhs
and match_modes(v.mode or "n", v2.mode or "n")
then
if not seen[v.lhs] then
seen[v.lhs] = {}
end
if duplicates[v.lhs] == nil then
duplicates[v.lhs] = { v, v2 }
seen[v.lhs][v] = true
seen[v.lhs][v2] = true
elseif seen[v.lhs] == nil or seen[v.lhs][v2] == nil then
table.insert(duplicates[v.lhs], v2)
seen[v.lhs][v2] = true
end
end
end
end

return duplicates
end

Expand Down
65 changes: 65 additions & 0 deletions tests/hawtkeys/dupes_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
local hawtkeys = require("hawtkeys")
local util = require("hawtkeys.utils")
local ts = require("hawtkeys.ts")
---@diagnostic disable-next-line: undefined-field
local eq = assert.are.same

describe("HawtkeysDupes", function()
before_each(function()
require("plenary.reload").reload_module("hawtkeys")
ts.reset_scanned_files()
hawtkeys.setup({})
end)

it("should detect duplicates", function()
local keymap = ts.find_maps_in_file(
"tests/hawtkeys/example_configs/duplicates.lua"
)

eq("n", keymap[1].mode)
eq("<leader>t", keymap[1].lhs)

eq("n", keymap[2].mode)
eq("<leader>t", keymap[2].lhs)

eq("x", keymap[3].mode)
eq("<leader>f", keymap[3].lhs)

eq("x", keymap[4].mode)
eq("<leader>f", keymap[4].lhs)

local dupes = util.find_duplicates(keymap)

eq("n", dupes["<leader>t"][1].mode)
eq("n", dupes["<leader>t"][2].mode)

eq("x", dupes["<leader>f"][1].mode)
eq("x", dupes["<leader>f"][2].mode)
end)

it(
"should detect duplicates with partial mode matches for multi-mode maps",
function()
local keymap = ts.find_maps_in_file(
"tests/hawtkeys/example_configs/multi_mode.lua"
)
eq({ "n", "x" }, keymap[1].mode)
eq("<leader>2", keymap[1].lhs)
eq(':echo "hello"<CR>', keymap[1].rhs)

eq({ "x", "v" }, keymap[2].mode)
eq("<leader>2", keymap[2].lhs)
eq(':echo "hello2"<CR>', keymap[2].rhs)

eq("v", keymap[3].mode)
eq("<leader>2", keymap[3].lhs)
eq(':echo "hello3"<CR>', keymap[3].rhs)

local dupes = util.find_duplicates(keymap)

eq({ "n", "x" }, dupes["<leader>2"][1].mode)
eq({ "x", "v" }, dupes["<leader>2"][2].mode)
eq("v", dupes["<leader>2"][3].mode)
end
)
end)
7 changes: 7 additions & 0 deletions tests/hawtkeys/example_configs/duplicates.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vim.keymap.set("n", "<leader>t", ":term", {})

vim.api.nvim_set_keymap("n", "<leader>t", "<cmd>ToggleTerm<CR>", {})

vim.keymap.set("x", "<leader>f", ':echo "test"<CR>', {})

vim.api.nvim_set_keymap("x", "<leader>f", '<cmd>echo "test"<CR>', {})
5 changes: 5 additions & 0 deletions tests/hawtkeys/example_configs/multi_mode.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vim.keymap.set({ "n", "x" }, "<leader>2", ':echo "hello"<CR>')

vim.keymap.set({ "x", "v" }, "<leader>2", ':echo "hello2"<CR>')

vim.keymap.set("v", "<leader>2", ':echo "hello3"<CR>')
13 changes: 13 additions & 0 deletions tests/hawtkeys/ts_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ describe("Treesitter can extract keymaps", function()
eq(':echo "hello"<CR>', keymap[1].rhs)
end)

it("extract multi-mode keymaps", function()
local keymap = ts.find_maps_in_file(
"tests/hawtkeys/example_configs/multi_mode.lua"
)
eq({ "n", "x" }, keymap[1].mode)
eq("<leader>2", keymap[1].lhs)
eq(':echo "hello"<CR>', keymap[1].rhs)

eq({ "x", "v" }, keymap[2].mode)
eq("<leader>2", keymap[2].lhs)
eq(':echo "hello2"<CR>', keymap[2].rhs)
end)

it("Extract short dot index aliasesd keymap", function()
hawtkeys.setup({
customMaps = {
Expand Down

0 comments on commit 954b4d9

Please sign in to comment.