From ec2ac379462b8446660c92a2a5bf30e44a2c0f9d Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 6 Jul 2023 22:02:57 -0400 Subject: [PATCH] feat: add keymap navigation functionality still isn't quite right because it's not working for leader keymaps --- dev.lua | 21 ++++----------- lua/keyseer/keymaps/init.lua | 37 ++++++++++++++++++++++++-- lua/keyseer/ui/init.lua | 29 ++++++++++++++++++++- lua/keyseer/ui/panes/home.lua | 49 +++++++++++++++-------------------- 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/dev.lua b/dev.lua index 95b7039..7aad361 100644 --- a/dev.lua +++ b/dev.lua @@ -1,17 +1,6 @@ -local qwerty = require("keyseer.keyboard.qwerty") - -local keyboard = qwerty:new() - -print(vim.pretty_print(qwerty.get_lines)) -print(vim.pretty_print(keyboard.get_lines)) -local Display = require("keyseer.display") - -local display = Display:new({ - show_legend = true, - show_title = false, - keyboard = { - layout = "qwerty", - padding = { 0, 1, 0, 1 }, - }, +local KeySeer = require("keyseer").setup({ + debug = true, }) -display:open() + +local UI = require("keyseer.ui") +UI.show("home", "n") diff --git a/lua/keyseer/keymaps/init.lua b/lua/keyseer/keymaps/init.lua index bd5d964..ab40161 100644 --- a/lua/keyseer/keymaps/init.lua +++ b/lua/keyseer/keymaps/init.lua @@ -11,7 +11,7 @@ local if_nil = vim.F.if_nil ---@class Keymaps ---@field root KeyMapTreeNode The root of the keymap treenode ---@field current_node KeyMapTreeNode The current node of the keymap tree ----@field previous_node KeyMapTreeNode The previous node of the keymap tree +---@field stack table The previous node of the keymap tree local Keymaps = {} Keymaps.__index = Keymaps @@ -25,8 +25,8 @@ function Keymaps:new() }, }, self) + this.stack = {} this.current_node = this.root - this.previous_node = nil return this end @@ -149,4 +149,37 @@ function Keymaps:get_current_keycaps(modifiers) return ret end +---Get the key presses for the current node +---@return table +function Keymaps:get_current_keypresses() + local ret = {} + for keypress, node in pairs(self.current_node.children) do + if next(node.children) ~= nil then + table.insert(ret, keypress) + end + end + return ret +end + +---Update the current node +function Keymaps:push(keypress) + if vim.tbl_isempty(self.current_node.children) then + Utils.notify("Received a keypress for no children.", { level = vim.log.levels.ERROR }) + return + end + if self.current_node.children[keypress] ~= nil then + table.insert(self.stack, self.current_node) + self.current_node = self.current_node.children[keypress] + else + Utils.notify( + "Received a keypress that isn't valid: " .. keypress, + { level = vim.log.levels.ERROR } + ) + vim.print(self.current_node.children[keypress]) + end +end + +function Keymaps:pop() + self.current_node = table.remove(self.stack) +end return Keymaps diff --git a/lua/keyseer/ui/init.lua b/lua/keyseer/ui/init.lua index 93c5179..a58b39b 100644 --- a/lua/keyseer/ui/init.lua +++ b/lua/keyseer/ui/init.lua @@ -3,6 +3,8 @@ local Popup = require("keyseer.ui.popup") local Render = require("keyseer.ui.render") local UIConfig = require("keyseer.ui.config") local Utils = require("keyseer.utils") +local Config = require("keyseer").config +local Keymaps = require("keyseer.keymaps") -- This section of code is copied from https://github.com/folke/lazy.nvim/ -- Mad props and respect go to folke @@ -10,13 +12,16 @@ local Utils = require("keyseer.utils") ---@class KeySeerUIState ---@field pane string Which pane to show ---@field prev_pane string The previous pane shown ----@field keyboard Keyboard The associated keyboard object +---@field keyboard Keyboard The keyboard object +---@field keymaps Keymaps The keymaps +---@field current_keymaps table The keymaps that have been added ---@field mode string The mode for displaying keymaps ---@field modifiers table{string,boolean} What modifier buttons are considered pressed local default_state = { pane = "home", prev_pane = "", mode = "n", + current_keymaps = {}, modifiers = { ctrl = false, shift = false, @@ -74,6 +79,27 @@ function M.create() self.state.pane = k self:update() end, v["desc"]) + + if not self.state.keyboard then + local keyboard_opts = Config.keyboard + local keyboard + local keyboard_options = vim.deepcopy(keyboard_opts) + keyboard_options.layout = nil + + if type(keyboard_opts.layout) == "string" then + keyboard = require("keyseer.keyboard." .. keyboard_opts.layout):new(keyboard_options) + else + ---@type Keyboard + local layout = keyboard_opts.layout + keyboard = layout:new(keyboard_options) + end + + self.state.keyboard = keyboard + end + if not self.state.keymaps then + self.state.keymaps = Keymaps:new() + self.state.keymaps:process_keymaps() + end end -- open details for the keycap under the cursor @@ -98,6 +124,7 @@ function M.create() -- only makes sense on the home pane if self.state.pane == "home" then Utils.notify("Going back") + self.state.keymaps:pop() self:update() end end) diff --git a/lua/keyseer/ui/panes/home.lua b/lua/keyseer/ui/panes/home.lua index e19d8e4..dd93131 100644 --- a/lua/keyseer/ui/panes/home.lua +++ b/lua/keyseer/ui/panes/home.lua @@ -23,45 +23,38 @@ local M = { saved_keymaps = {}, } -function M.ensure_state(ui) - if not ui.state.keyboard then - local keyboard_opts = Config.keyboard - local keyboard - local keyboard_options = vim.deepcopy(keyboard_opts) - keyboard_options.layout = nil - - if type(keyboard_opts.layout) == "string" then - keyboard = require("keyseer.keyboard." .. keyboard_opts.layout):new(keyboard_options) - else - ---@type Keyboard - local layout = keyboard_opts.layout - keyboard = layout:new(keyboard_options) - end - - ui.state.keyboard = keyboard - end - if not ui.state.keymaps then - ui.state.keymaps = Keymaps:new() - ui.state.keymaps:process_keymaps() - end -end - --- TODO: Populate main function M.render(ui) - M.ensure_state(ui) local current_keycaps = ui.state.keymaps:get_current_keycaps(ui.state.modifiers) ui.state.keyboard:populate_lines(ui, current_keycaps) + for _, keypress in pairs(ui.state.current_keymaps) do + vim.keymap.del("n", "g" .. keypress, { buffer = ui.buf }) + end + ui.state.current_keymaps = {} + for _, keypress in pairs(ui.state.keymaps:get_current_keypresses()) do + D.log("UI", "adding keymap for %s", keypress) + table.insert(ui.state.current_keymaps, keypress) + vim.keymap.set("n", "g" .. keypress, function() + ui.state.keymaps:push(keypress) + ui:update() + end, { buffer = ui.buf }) + end end ---Update keymaps when entering the pane function M.on_enter(ui) - M.ensure_state(ui) - Utils.notify("Entering home") + for _, keypress in pairs(ui.state.current_keymaps) do + vim.keymap.set("n", "g" .. keypress, function() + ui.state.keymaps:push(keypress) + ui:update() + end, { buffer = ui.buf }) + end end ---Update keymaps when exiting the pane function M.on_exit(ui) - Utils.notify("Exiting home") + for _, keypress in pairs(ui.state.current_keymaps) do + vim.keymap.del("n", "g" .. keypress, { buffer = ui.buf }) + end end return M