Skip to content

Commit

Permalink
refactor(init): move config into object and add tests (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: tris203 <admin@snappeh.com>
Co-authored-by: Will Hopkins <willothyh@gmail.com>
  • Loading branch information
3 people authored Dec 21, 2023
1 parent 2ecef6f commit f078320
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 72 deletions.
122 changes: 71 additions & 51 deletions lua/hawtkeys/init.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
---@class Hawtkeys
---@field config HawtKeyConfig
---@field package defaultConfig HawtKeyConfig
local M = {}

---@alias SupportedKeyboardLayouts "qwerty" | "dvorak"
---@alias HawtKeySupportedKeyboardLayouts "qwerty" | "dvorak"

---@class HawtKeyConfig
---@field leader string
---@field homerow number
---@field powerFingers number[]
---@field keyboardLayout SupportedKeyboardLayouts
---@field keyboardLayout HawtKeySupportedKeyboardLayouts
---@field keyMapSet { [string] : TSKeyMapArgs | WhichKeyMapargs } | nil
---@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs } | nil
---@field highlights HawtKeyHighlights | nil

---@class HawtKeyHighlights
---@field HawtkeysMatchGreat vim.api.keyset.highlight | nil
Expand All @@ -19,13 +24,11 @@ local M = {}
---@field leader string | nil
---@field homerow number | nil
---@field powerFingers number[] | nil
---@field keyboardLayout SupportedKeyboardLayouts | nil
---@field keyboardLayout HawtKeySupportedKeyboardLayouts | nil
---@field customMaps { [string] : TSKeyMapArgs | WhichKeyMapargs } | nil
---@field highlights HawtKeyHighlights | nil
---

---@type { [string] : TSKeyMapArgs | WhichKeyMapargs }---

local _defaultSet = {
["vim.keymap.set"] = {
modeIndex = 1,
Expand All @@ -46,58 +49,67 @@ local _defaultSet = {
}, -- method 6
}

---@param config HawtKeyPartialConfig
function M.setup(config)
config = config or {}
M.leader = config.leader or " "
M.homerow = config.homerow or 2
M.powerFingers = config.powerFingers or { 2, 3, 6, 7 }
M.keyboardLayout = config.keyboardLayout or "qwerty"
M.keyMapSet = vim.tbl_extend("force", _defaultSet, config.customMaps or {})
local defaultConfig = {
leader = " ",
homerow = 2,
powerFingers = { 2, 3, 6, 7 },
keyboardLayout = "qwerty",
keyMapSet = _defaultSet,
highlights = {
HawtkeysMatchGreat = { link = "DiagnosticOk", underline = true },
HawtkeysMatchGood = { link = "DiagnosticOk" },
HawtkeysMatchOk = { link = "DiagnosticWarn" },
HawtkeysMatchBad = { link = "DiagnosticError" },
},
}

local function apply_highlights()
for name, props in pairs(M.config.highlights) do
local styleConfig
if props.link then
styleConfig = vim.api.nvim_get_hl(0, {
name = props.link,
link = false,
})
else
styleConfig = {}
end

local default_match_great
if not config.highlights or not config.highlights.HawtkeysMatchGreat then
default_match_great =
vim.api.nvim_get_hl(0, { name = "DiagnosticOk", link = false })
default_match_great.underline = true
for k, v in pairs(props) do
if k ~= "link" then
styleConfig[k] = v
end
end
vim.api.nvim_set_hl(0, name, styleConfig)
end
M.highlights = vim.tbl_extend("keep", config.highlights or {}, {
HawtkeysMatchGreat = default_match_great,
HawtkeysMatchGood = {
link = "DiagnosticOk",
},
HawtkeysMatchOk = {
link = "DiagnosticWarn",
},
HawtkeysMatchBad = {
link = "DiagnosticError",
},
})
end

for name, hl in pairs(M.highlights) do
vim.api.nvim_set_hl(0, name, hl)
---@param config HawtKeyPartialConfig
function M.setup(config)
M.config = M.config or {}
for k, default in pairs(defaultConfig) do
local v = config[k]
if k == "highlights" then
-- shallow merge to preserve highlight values
M.config[k] =
vim.tbl_extend("force", defaultConfig.highlights, v or {})
elseif k == "keyMapSet" then
M.config[k] = vim.tbl_deep_extend(
"force",
defaultConfig.keyMapSet,
config.customMaps or {}
)
elseif type(default) == "table" then
M.config[k] = vim.tbl_deep_extend("force", default, v or {})
else
M.config[k] = v or default
end
end

vim.api.nvim_create_autocmd("ColorScheme", {
callback = function()
if default_match_great then
for k, v in
pairs(
vim.api.nvim_get_hl(
0,
{ name = "DiagnosticOk", link = false }
)
)
do
default_match_great[k] = v
end
default_match_great.underline = true
end
apply_highlights()

for name, hl in pairs(M.highlights) do
vim.api.nvim_set_hl(0, name, hl)
end
end,
vim.api.nvim_create_autocmd("ColorScheme", {
callback = apply_highlights,
})

vim.api.nvim_create_user_command(
Expand All @@ -117,4 +129,12 @@ function M.setup(config)
)
end

setmetatable(M, {
__index = function(_, k)
if k == "defaultConfig" then
return vim.deepcopy(defaultConfig)
end
end,
})

return M
26 changes: 13 additions & 13 deletions lua/hawtkeys/score.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local config = require("hawtkeys")
local hawtkeys = require("hawtkeys")
local keyboardLayouts = require("hawtkeys.keyboards")
local tsSearch = require("hawtkeys.ts")
local utils = require("hawtkeys.utils")
Expand Down Expand Up @@ -51,24 +51,24 @@ local function key_score(key1, key2, str, layout)
local sameFingerPenalty = (key1Data.finger == key2Data.finger) and 1
or 0
local homerowBonus = (
key1Data.row == config.homerow
and key2Data.row == config.homerow
key1Data.row == hawtkeys.config.homerow
and key2Data.row == hawtkeys.config.homerow
)
and 1
or 0
local powerFinger1Bonus = (
key1Data.finger == config.powerFingers[1]
or key1Data.finger == config.powerFingers[2]
or key1Data.finger == config.powerFingers[3]
or key1Data.finger == config.powerFingers[4]
key1Data.finger == hawtkeys.config.powerFingers[1]
or key1Data.finger == hawtkeys.config.powerFingers[2]
or key1Data.finger == hawtkeys.config.powerFingers[3]
or key1Data.finger == hawtkeys.config.powerFingers[4]
)
and 1
or 0
local powerFinger2Bonus = (
key2Data.finger == config.powerFingers[1]
or key2Data.finger == config.powerFingers[2]
or key2Data.finger == config.powerFingers[3]
or key2Data.finger == config.powerFingers[4]
key2Data.finger == hawtkeys.config.powerFingers[1]
or key2Data.finger == hawtkeys.config.powerFingers[2]
or key2Data.finger == hawtkeys.config.powerFingers[3]
or key2Data.finger == hawtkeys.config.powerFingers[4]
)
and 1
or 0
Expand All @@ -91,7 +91,7 @@ end
---@param str string
---@return table
local function generate_combos(str)
str = str:gsub(config.leader, "")
str = str:gsub(hawtkeys.config.leader, "")
local pairs = {}
local len = #str
for i = 1, len - 1 do
Expand All @@ -112,7 +112,7 @@ local function find_matches(str)

for _, combo in ipairs(combinations) do
local a, b = combo:sub(1, 1), combo:sub(2, 2)
local score = key_score(a, b, str, config.keyboardLayout)
local score = key_score(a, b, str, hawtkeys.config.keyboardLayout)
scores[combo] = score
end

Expand Down
18 changes: 10 additions & 8 deletions lua/hawtkeys/ts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local M = {}
local Path = require("plenary.path")
local scan = require("plenary.scandir")
local utils = require("hawtkeys.utils")
local config = require("hawtkeys")
local hawtkeys = require("hawtkeys")
local ts = require("nvim-treesitter.compat")
local tsQuery = require("nvim-treesitter.query")

Expand Down Expand Up @@ -135,7 +135,7 @@ local function find_maps_in_file(filePath)
-- need to use TS to resolve it back to a native keymap
local dotIndexExpressionQuery = ts.parse_query(
"lua",
build_dot_index_expression_query(config.keyMapSet)
build_dot_index_expression_query(hawtkeys.config.keyMapSet)
)
for match in
tsQuery.iter_prepared_matches(
Expand All @@ -152,7 +152,7 @@ local function find_maps_in_file(filePath)
node.node:parent():child(0),
fileContent
)
local mapDef = config.keyMapSet[parent]
local mapDef = hawtkeys.config.keyMapSet[parent]
---@type string
local mode = return_field_data(
node.node,
Expand Down Expand Up @@ -219,8 +219,10 @@ local function find_maps_in_file(filePath)
end
end

local functionCallQuery =
ts.parse_query("lua", build_function_call_query(config.keyMapSet))
local functionCallQuery = ts.parse_query(
"lua",
build_function_call_query(hawtkeys.config.keyMapSet)
)

for match in
tsQuery.iter_prepared_matches(
Expand All @@ -237,7 +239,7 @@ local function find_maps_in_file(filePath)
node.node:parent():child(0),
fileContent
)
local mapDef = config.keyMapSet[parent]
local mapDef = hawtkeys.config.keyMapSet[parent]
---@type string
local mode = return_field_data(
node.node,
Expand Down Expand Up @@ -306,7 +308,7 @@ local function find_maps_in_file(filePath)
end

local whichKeyQuery =
ts.parse_query("lua", build_which_key_query(config.keyMapSet))
ts.parse_query("lua", build_which_key_query(hawtkeys.config.keyMapSet))

for match in
tsQuery.iter_prepared_matches(whichKeyQuery, tree, fileContent, 0, -1)
Expand Down Expand Up @@ -359,7 +361,7 @@ local function get_keymaps_from_vim()
table.insert(vimKeymaps, {
mode = vimKeymap.mode,
-- TODO: leader subsitiution as vim keymaps contain raw leader
lhs = vimKeymap.lhs:gsub(config.leader, "<leader>"),
lhs = vimKeymap.lhs:gsub(hawtkeys.config.leader, "<leader>"),
rhs = vimKeymap.rhs,
from_file = "Vim Defaults",
})
Expand Down
84 changes: 84 additions & 0 deletions tests/hawtkeys/init_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
local hawtkeys = require("hawtkeys")
---@diagnostic disable-next-line: undefined-field
local eq = assert.are.same
---@diagnostic disable-next-line: undefined-field
local falsy = assert.falsy
local userCommands = {
["Hawtkeys"] = "lua require('hawtkeys.ui').show()",
["HawtkeysAll"] = "lua require('hawtkeys.ui').show_all()",
["HawtkeysDupes"] = "lua require('hawtkeys.ui').show_dupes()",
}

describe("set up function", function()
before_each(function()
require("plenary.reload").reload_module("hawtkeys")
for _, command in ipairs(userCommands) do
vim.api.nvim_command("silent! delcommand " .. command)
end
end)
it("should set up the default config", function()
hawtkeys.setup({})
---@diagnostic disable-next-line: invisible
eq(hawtkeys.defaultConfig, hawtkeys.config)
end)

it("should be able to override the default config", function()
hawtkeys.setup({ leader = "," })
eq(",", hawtkeys.config.leader)
end)

it("can set custom highlights", function()
hawtkeys.setup({
highlights = {
HawtkeysMatchGreat = {
link = "DiagnosticSomethingElse",
},
},
})
eq(
"DiagnosticSomethingElse",
hawtkeys.config.highlights.HawtkeysMatchGreat.link
)
eq(
---@diagnostic disable-next-line: invisible
hawtkeys.defaultConfig.highlights.HawtkeysMatchGood,
hawtkeys.config.highlights.HawtkeysMatchGood
)
end)

it("can pass in custom mapping definitions", function()
hawtkeys.setup({
customMaps = {
["custom.map"] = {
method = "dot_index_expression",
lhsIndex = 1,
rhsIndex = 2,
modeIndex = "n",
optsIndex = 3,
},
},
})
eq(
"dot_index_expression",
hawtkeys.config.keyMapSet["custom.map"].method
)
eq(1, hawtkeys.config.keyMapSet["custom.map"].lhsIndex)
eq(2, hawtkeys.config.keyMapSet["custom.map"].rhsIndex)
eq("n", hawtkeys.config.keyMapSet["custom.map"].modeIndex)
eq(3, hawtkeys.config.keyMapSet["custom.map"].optsIndex)
end)

it("User commands should be available after setup", function()
local commandspresetup = vim.api.nvim_get_commands({})
hawtkeys.setup({})
local commandsPostSetup = vim.api.nvim_get_commands({})
-- Check that the commands are not present before setup
for command, _ in ipairs(userCommands) do
falsy(commandspresetup[command])
end
-- Check that the commands are present after setup
for command, action in ipairs(userCommands) do
eq(action, commandsPostSetup[command].definition)
end
end)
end)

0 comments on commit f078320

Please sign in to comment.