Skip to content

Commit 654a68e

Browse files
committed
feat: add register history and C-p/C-n navigation in template editor
1 parent 514fffe commit 654a68e

2 files changed

Lines changed: 77 additions & 3 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,9 @@ After receiving a response from ChatGPT, you can perform several actions to inte
391391
- `{"<C-s>"}`: Save registers (for template editing only)
392392
- `K`: Show special value for placeholder under cursor (for template editing only)
393393
- `Q`: Send current question or conversation to a buffer for chatting.
394+
- For `Template Editor` (register-based QA UI)
395+
- `{"<C-p>"}`: History Cycling; Cycle to previous stored value of the current register
396+
- `{"<C-n>"}`: History Cycling; Cycle to next stored value of the current register
394397
- For `ChatDialog` (The dialog that can get responses)
395398
- `{"<C-a>"}`: Append response to original buffer after selection/current line
396399
- `{"<C-y>"}`: Copy full response to clipboard

lua/simplegpt/tpl.lua

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,29 @@ local utils = require("simplegpt.utils")
66
local conf = require("simplegpt.conf")
77
-- TODO:
88
local M = {}
9+
M.history = {} -- store template & register history
10+
11+
-- Record current template / register values into history
12+
function M.record_history()
13+
-- Build a snapshot of current template/register values
14+
local snapshot = { t = vim.fn.getreg("t") }
15+
for _, k in ipairs(M.get_placeholders()) do
16+
snapshot[k] = vim.fn.getreg(k)
17+
end
18+
19+
-- Append each value to a per-register history list
20+
for reg, val in pairs(snapshot) do
21+
if not M.history[reg] then
22+
M.history[reg] = {}
23+
end
24+
25+
-- avoid storing consecutive duplicate values.
26+
if M.history[reg][#M.history[reg]] ~= val then
27+
table.insert(M.history[reg], val)
28+
end
29+
end
30+
end
31+
932
M.RegQAUI = utils.class("RegQAUI", dialog.BaseDialog) -- register-based QA UI
1033

1134
function M.RegQAUI:ctor(...)
@@ -502,7 +525,14 @@ end
502525
--- register common keys for dialogs
503526
---@param exit_callback
504527
function M.RegQAUI:register_keys(exit_callback)
505-
M.RegQAUI.super.register_keys(self, exit_callback)
528+
-- wrap exit_callback so that history is recorded before exiting
529+
local function _exit_cb(...)
530+
if exit_callback then
531+
exit_callback(...)
532+
end
533+
M.record_history()
534+
end
535+
M.RegQAUI.super.register_keys(self, _exit_cb)
506536
-- Register TPL_DIALOG_KEYMAPS via add_winbar
507537
local keymaps = require("simplegpt.conf").get_tpl_dialog_keymaps()
508538
dialog.add_winbar(self.all_pops[1].winid, keymaps)
@@ -585,8 +615,15 @@ function M.RegQAUI:register_keys(exit_callback)
585615

586616
-- 2) Register 'Q' to exit the NUI and create a buffer chat with the query
587617
local buffer_chat_key = require("simplegpt.conf").options.dialog.keymaps.buffer_chat_keys
588-
for _, pop in ipairs(self.all_pops) do
589-
pop:map("n", buffer_chat_key, function()
618+
local p_d = {t = self.tpl_pop}
619+
for k, ppop in pairs(self.pop_dict) do
620+
p_d[k] = ppop
621+
end
622+
-- start after last entry (newest position)
623+
local _hist_idx = {}
624+
625+
for k, pop in pairs(p_d) do
626+
pop:map("n", buffer_chat_key, function()
590627
-- Exit the current NUI
591628
self:quit() -- this will switch back to the orginal buffer
592629

@@ -599,7 +636,41 @@ function M.RegQAUI:register_keys(exit_callback)
599636

600637
-- Notify the user
601638
vim.notify("Created buffer chat with template query", vim.log.levels.INFO)
639+
640+
-- Record current template and register values for future history/navigation
641+
M.record_history()
602642
end, { noremap = true, desc = "Exit template and create a buffer chat with the query" })
643+
644+
---------------------------------------------------------------------------
645+
-- <Up>/<Down> mappings inside register pop-ups to navigate stored history
646+
---------------------------------------------------------------------------
647+
_hist_idx[k] = (M.history[k] and (#M.history[k] + 1)) or 1
648+
function build_func(k, delta)
649+
local function rotate_history()
650+
local hist = M.history[k]
651+
if not hist or #hist == 0 then
652+
vim.notify("No history for register " .. k, vim.log.levels.WARN)
653+
return
654+
end
655+
local idx = (_hist_idx[k] or 1) + delta
656+
if idx < 1 then
657+
idx = #hist
658+
elseif idx > #hist then
659+
idx = 1
660+
end
661+
_hist_idx[k] = idx
662+
663+
-- update popup buffer and underlying register
664+
vim.api.nvim_buf_set_lines(p_d[k].bufnr, 0, -1, false, vim.split(hist[idx], "\n"))
665+
vim.fn.setreg(k, hist[idx])
666+
end
667+
return rotate_history
668+
end
669+
670+
pop:map("n", "<C-p>", build_func(k, -1),
671+
{ noremap = true, desc = "SimpleGPT: previous history value" })
672+
pop:map("n", "<C-n>", build_func(k, 1),
673+
{ noremap = true, desc = "SimpleGPT: next history value" })
603674
end
604675

605676
-- 3) register “@” in the file-path popup to pick files via fzf-lua

0 commit comments

Comments
 (0)