diff options
| author | theprimeagain <the.primeagen@gmail.com> | 2026-02-28 14:29:28 -0700 |
|---|---|---|
| committer | theprimeagain <the.primeagen@gmail.com> | 2026-02-28 14:29:49 -0700 |
| commit | 78f39f61606597ca778ec01e2058a3e652000d7e (patch) | |
| tree | 332ccb8a69a98d664854a7bbb99b297f6460d2d9 /lua | |
| parent | d485196b0a7956e9efb9f73eccfb126b95d113b3 (diff) | |
| download | a4-78f39f61606597ca778ec01e2058a3e652000d7e.tar.xz a4-78f39f61606597ca778ec01e2058a3e652000d7e.zip | |
selection works nicely now
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/99/init.lua | 39 | ||||
| -rw-r--r-- | lua/99/test/window_spec.lua | 38 | ||||
| -rw-r--r-- | lua/99/window/init.lua | 53 | ||||
| -rw-r--r-- | lua/99/window/select-window.lua | 30 |
4 files changed, 126 insertions, 34 deletions
diff --git a/lua/99/init.lua b/lua/99/init.lua index 035ee16..72e4cc0 100644 --- a/lua/99/init.lua +++ b/lua/99/init.lua @@ -6,6 +6,7 @@ local Tracking = require("99.state.tracking") local Level = require("99.logger.level") local ops = require("99.ops") local Window = require("99.window") +local select_window = require("99.window.select-window") local StatusWindow = require("99.window.status-window") local Prompt = require("99.prompt") local State = require("99.state") @@ -216,39 +217,6 @@ local _99 = { FATAL = Level.FATAL, } ---- @param requests _99.Prompt[] ----@param cb fun(r: _99.Prompt): nil -local function capture_request(requests, cb) - local str_requests = Tracking.to_selectable_list(requests) - - Window.capture_select_input("99 Select Request", { - content = str_requests, - cb = function(success, result) - if not success or result == "" then - return - end - - local idx = tonumber(vim.fn.matchstr(result, "^\\d\\+")) - if idx == nil then - return - end - local r = requests[idx] - if not r then - print( - "request not found... potentially report bug: " .. vim.inspect(idx) - ) - return - end - assert( - r:valid(), - "request is not valid... not sure how we got here. please report bug and this word: " - .. vim.inspect(r.operation) - ) - cb(r) - end, - }) -end - --- @param cb fun(context: _99.Prompt, o: _99.ops.Opts?): nil --- @param name string --- @param context _99.Prompt @@ -318,7 +286,10 @@ end function _99.open() local requests = _99_state.tracking:successful() - capture_request(requests, function(r) + local str_requests = Tracking.to_selectable_list(requests) + select_window(str_requests, function(idx) + local r = requests[idx] + assert(r:valid(), "encountered unexpected issue. malformated data") if r.operation == "visual" then --- TODO: this is its own work item for being able to have a global mark --- section in which i keep track of marks for the lifetime of the diff --git a/lua/99/test/window_spec.lua b/lua/99/test/window_spec.lua new file mode 100644 index 0000000..c91c219 --- /dev/null +++ b/lua/99/test/window_spec.lua @@ -0,0 +1,38 @@ +-- luacheck: globals describe it assert before_each after_each +local Window = require("99.window") +local eq = assert.are.same + +describe("Window", function() + local previous_list_uis + + before_each(function() + previous_list_uis = vim.api.nvim_list_uis + vim.api.nvim_list_uis = function() + return { + { width = 120, height = 40 }, + } + end + end) + + after_each(function() + vim.api.nvim_list_uis = previous_list_uis + Window.clear_active_popups() + end) + + it("shows keymap legend window and applies keyoffset", function() + local win = Window.capture_input("Prompt", { + cb = function() end, + keymap = { + q = "cancel", + ["<CR>"] = "submit", + }, + }) + + eq(2, #Window.active_windows) + eq(2, vim.wo[win.win_id].scrolloff) + + local legend = Window.active_windows[2] + local lines = vim.api.nvim_buf_get_lines(legend.buf_id, 0, -1, false) + eq({ "<CR>=submit", "q=cancel" }, lines) + end) +end) diff --git a/lua/99/window/init.lua b/lua/99/window/init.lua index a3a02bb..4cc44f4 100644 --- a/lua/99/window/init.lua +++ b/lua/99/window/init.lua @@ -3,6 +3,9 @@ local Agents = require("99.extensions.agents") local Point = require("99.geo").Point +local BASE = 100 +local LEGEND = 200 + --- @class _99.window.Module --- @field active_windows _99.window.Window[] local M = { @@ -355,11 +358,56 @@ local function highlight_rules_found(win, rules, group) }) end +--- @alias _99.window.KeyMap table<string, string> --- @class _99.window.CaptureInputOpts --- @field cb fun(success: boolean, result: string): nil --- @field on_load? fun(): nil --- @field content? string[] --- @field rules? _99.Agents.Rules +--- @field keymap? _99.window.KeyMap + +--- @param keymap _99.window.KeyMap +--- @param width number +--- @return string[] +local function keymap_lines(keymap, width) + local keys = vim.tbl_keys(keymap) + table.sort(keys) + + local lines = { "" } + for _, key in ipairs(keys) do + local current = lines[#lines] + local legend = string.format("%s=%s", key, keymap[key]) + if #current + #legend + 1 > width then + table.insert(lines, legend) + else + lines[#lines] = string.format("%s %s", current, legend) + end + end + + return lines +end + +--- @param win _99.window.Window +--- @param keymap _99.window.KeyMap +local function create_window_legend(win, keymap) + local lines = keymap_lines(keymap, win.config.width - 2) + local keyoffset = #lines + local keymap_config = create_window_inside(win, keyoffset - 1) + keymap_config.height = keyoffset + keymap_config.zindex = LEGEND + + local keymap_win = create_floating_window(keymap_config, "", false) + vim.bo[keymap_win.buf_id].buftype = "nofile" + vim.bo[keymap_win.buf_id].bufhidden = "wipe" + vim.bo[keymap_win.buf_id].swapfile = false + vim.bo[keymap_win.buf_id].modifiable = true + vim.bo[keymap_win.buf_id].readonly = false + vim.api.nvim_buf_set_lines(keymap_win.buf_id, 0, -1, false, lines) + vim.bo[keymap_win.buf_id].modifiable = false + vim.bo[keymap_win.buf_id].readonly = true + + vim.wo[win.win_id].scrolloff = keyoffset +end --- @param name string --- @param opts _99.window.CaptureInputOpts @@ -374,6 +422,10 @@ function M.capture_input(name, opts) set_defaul_win_options(win, "99-prompt") vim.api.nvim_set_current_win(win.win_id) + opts.keymap = opts.keymap or {} + opts.keymap.q = "cancel" + create_window_legend(win, opts.keymap) + local group = vim.api.nvim_create_augroup( "99_present_prompt_" .. win.buf_id, { clear = true } @@ -458,6 +510,7 @@ function M.capture_select_input(name, opts) win = M.capture_input(name, { content = opts.content, rules = opts.rules, + keymap = opts.keymap, cb = function(success, result) if not success then opts.cb(false, result) diff --git a/lua/99/window/select-window.lua b/lua/99/window/select-window.lua new file mode 100644 index 0000000..3c90e0b --- /dev/null +++ b/lua/99/window/select-window.lua @@ -0,0 +1,30 @@ +local Window = require("99.window") + +--- @param lines string[] +---@param cb fun(idx: number): nil +local function select_window(lines, cb) + Window.capture_select_input("Select", { + content = lines, + keymap = { + enter = "select", + }, + cb = function(success, result) + if not success or result == "" then + return + end + + local idx = tonumber(vim.fn.matchstr(result, "^\\d\\+")) + if idx == nil then + return + end + local r = lines[idx] + if not r then + return + end + cb(idx) + end, + }) +end + + +return select_window |
