summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authortheprimeagain <the.primeagen@gmail.com>2026-02-25 15:14:48 -0700
committertheprimeagain <the.primeagen@gmail.com>2026-02-25 15:14:48 -0700
commit9be01a1a50a61635ea7169e01c85fab41638ad66 (patch)
treea4d50311770e1eed49bf330dd0596db19fc7cea3 /lua
parentba72babb9d606f021ef0697a572ced10d5ff0d48 (diff)
downloada4-9be01a1a50a61635ea7169e01c85fab41638ad66.tar.xz
a4-9be01a1a50a61635ea7169e01c85fab41638ad66.zip
the vibe stuff is sort of there. I genuinely dislike what it is, moving
on
Diffstat (limited to 'lua')
-rw-r--r--lua/99/extensions/work/worker.lua9
-rw-r--r--lua/99/init.lua119
-rw-r--r--lua/99/ops/search.lua4
-rw-r--r--lua/99/ops/vibe.lua4
-rw-r--r--lua/99/prompt.lua6
-rw-r--r--lua/99/state.lua5
-rw-r--r--lua/99/test/qfix_navigation_spec.lua70
7 files changed, 191 insertions, 26 deletions
diff --git a/lua/99/extensions/work/worker.lua b/lua/99/extensions/work/worker.lua
index a967b4c..7bc65d9 100644
--- a/lua/99/extensions/work/worker.lua
+++ b/lua/99/extensions/work/worker.lua
@@ -155,13 +155,4 @@ function M.search()
})
end
-function M.last_search_results()
- if M.last_work_search == nil then
- print("no previous search results")
- return
- end
-
- require("99").qfix(M.last_work_search)
-end
-
return M
diff --git a/lua/99/init.lua b/lua/99/init.lua
index 17eeb06..52ba23b 100644
--- a/lua/99/init.lua
+++ b/lua/99/init.lua
@@ -188,6 +188,7 @@ local _99_state
--- locations with notes that will be put into your quick fix list.
--- @field vibe_search fun(opts?: _99.ops.Opts): _99.TraceID | nil
--- Select a previous search, edit it, then pass it to vibe.
+--- @field vibe fun(opts?: _99.ops.Opts): _99.TraceID | nil
--- @field visual fun(opts: _99.ops.Opts): _99.TraceID
--- takes your current selection and sends that along with the prompt provided and replaces
--- your visual selection with the results
@@ -356,10 +357,7 @@ function _99.vibe_search(opts)
local o = process_opts(opts)
local lines = {}
for i, context in ipairs(searches) do
- table.insert(
- lines,
- string.format("%d: %s", i, context:summary())
- )
+ table.insert(lines, string.format("%d: %s", i, context:summary()))
end
Window.capture_select_input("Select Search", {
@@ -454,6 +452,61 @@ end
--- @field col number
--- @field text string
+--- @class _99.QFixOpts
+--- @field operation? "search" | "vibe"
+
+--- @param opts? _99.QFixOpts
+--- @return "search" | "vibe"
+local function qfix_operation(opts)
+ local operation = (opts and opts.operation) or "search"
+ assert(
+ operation == "search" or operation == "vibe",
+ "opts.operation must be either 'search' or 'vibe'"
+ )
+ return operation
+end
+
+--- @param operation "search" | "vibe"
+--- @return _99.Prompt[]
+local function qfix_requests(operation)
+ local out = {} --[[ @as _99.Prompt[] ]]
+ for _, request in ipairs(_99_state.__request_history) do
+ if request.operation == operation then
+ local ok, items = pcall(request.qfix_data, request)
+ if ok and #items > 0 then
+ table.insert(out, request)
+ end
+ end
+ end
+ return out
+end
+
+--- @param operation "search" | "vibe"
+--- @param index number
+--- @return _99.Prompt | nil
+local function qfix_request_at(operation, index)
+ local requests = qfix_requests(operation)
+ if #requests == 0 then
+ return nil
+ end
+
+ local idx = math.max(1, math.min(index, #requests))
+ _99_state.__qfix_history_idx[operation] = idx
+ return requests[idx]
+end
+
+--- @param request _99.Prompt
+local function open_qfix_request(request)
+ local items = request:qfix_data()
+ if #items == 0 then
+ print("there are no quickfix items to show")
+ return
+ end
+
+ vim.fn.setqflist({}, "r", { title = "99 Results", items = items })
+ vim.cmd("copen")
+end
+
function _99.stop_all_requests()
for _, c in pairs(_99_state.__request_by_id) do
if c.state == "requesting" then
@@ -469,16 +522,56 @@ function _99.clear_all_marks()
_99_state.__active_marks = {}
end
---- @param xid number
-function _99.qfix(xid)
- --- @type _99.Prompt
- local entry = _99_state.__request_by_id[xid]
- assert(entry, "qfix_search_results could not find id: " .. xid)
+--- @param opts? _99.QFixOpts
+function _99.qfix_top(opts)
+ local operation = qfix_operation(opts)
+ local requests = qfix_requests(operation)
+ if #requests == 0 then
+ print("there are no quickfix items to show")
+ return
+ end
- local items = entry:qfix_data()
- Logger:set_id(xid):debug("qfix items retrieved", "items", items)
- vim.fn.setqflist({}, "r", { title = "99 Results", items = items })
- vim.cmd("copen")
+ local request = qfix_request_at(operation, #requests)
+ assert(request, "failed to retrieve qfix request")
+ open_qfix_request(request)
+end
+
+--- @param opts? _99.QFixOpts
+function _99.qfix_older(opts)
+ local operation = qfix_operation(opts)
+ local requests = qfix_requests(operation)
+ if #requests == 0 then
+ print("there are no quickfix items to show")
+ return
+ end
+
+ local current = _99_state.__qfix_history_idx[operation]
+ if current == 0 then
+ current = #requests
+ end
+
+ local request = qfix_request_at(operation, current - 1)
+ assert(request, "failed to retrieve older qfix request")
+ open_qfix_request(request)
+end
+
+--- @param opts? _99.QFixOpts
+function _99.qfix_newer(opts)
+ local operation = qfix_operation(opts)
+ local requests = qfix_requests(operation)
+ if #requests == 0 then
+ print("there are no quickfix items to show")
+ return
+ end
+
+ local current = _99_state.__qfix_history_idx[operation]
+ if current == 0 then
+ current = #requests
+ end
+
+ local request = qfix_request_at(operation, current + 1)
+ assert(request, "failed to retrieve newer qfix request")
+ open_qfix_request(request)
end
function _99.clear_previous_requests()
diff --git a/lua/99/ops/search.lua b/lua/99/ops/search.lua
index 0619f47..dc7520f 100644
--- a/lua/99/ops/search.lua
+++ b/lua/99/ops/search.lua
@@ -17,7 +17,9 @@ local function create_search_locations(context, response)
}
if #qf_list > 0 then
- require("99").qfix(context.xid)
+ require("99").qfix_top({
+ operation = "search",
+ })
else
vim.notify("No search results found", vim.log.levels.INFO)
end
diff --git a/lua/99/ops/vibe.lua b/lua/99/ops/vibe.lua
index 9a64b78..3ba15c5 100644
--- a/lua/99/ops/vibe.lua
+++ b/lua/99/ops/vibe.lua
@@ -17,7 +17,9 @@ local function finish_vibe(context, response)
}
if #qf_list > 0 then
- require("99").qfix(context.xid)
+ require("99").qfix_top({
+ operation = "vibe",
+ })
else
vim.notify("No search results found", vim.log.levels.INFO)
end
diff --git a/lua/99/prompt.lua b/lua/99/prompt.lua
index 384dbde..fbb8265 100644
--- a/lua/99/prompt.lua
+++ b/lua/99/prompt.lua
@@ -23,6 +23,7 @@ local filetype_map = {
-- luacheck: ignore
--- @alias _99.Prompt.Data _99.Prompt.Data.Search | _99.Prompt.Data.Tutorial | _99.Prompt.Data.Visual | _99.Prompt.Data.Vibe
--- @alias _99.Prompt.Operation "visual" | "tutorial" | "search" | "vibe"
+--- @alias _99.Prompt.QFixOperation "search" | "vibe"
--- @alias _99.Prompt.EndingState "failed" | "success" | "cancelled"
--- @alias _99.Prompt.State "ready" | "requesting" | _99.Prompt.EndingState
--- @alias _99.Prompt.Cleanup fun(): nil
@@ -35,7 +36,7 @@ local filetype_map = {
--- @class _99.Prompt.Data.Vibe
--- @field type "vibe"
--- @field response string
---- @field xfix_items _99.Search.Result[]
+--- @field qfix_items _99.Search.Result[]
--- @class _99.Prompt.Data.Visual
--- @field type "visual"
@@ -193,6 +194,7 @@ function Prompt.search(_99)
context.data = {
type = "search",
qfix_items = {},
+ response = "",
}
context.logger:debug("99 Request", "method", "search")
@@ -332,7 +334,7 @@ function Prompt:qfix_data()
self.data.type == "search" or self.data.type == "vibe",
"data type is not search or vibe: " .. self.data.type
)
- return self.data.xfix_items
+ return self.data.qfix_items
end
function Prompt:stop()
diff --git a/lua/99/state.lua b/lua/99/state.lua
index ae7fc8c..397e30f 100644
--- a/lua/99/state.lua
+++ b/lua/99/state.lua
@@ -38,6 +38,7 @@ end
--- @field __request_by_id table<number, _99.Prompt>
--- @field __active_marks _99.Mark[]
--- @field __tmp_dir string | nil
+--- @field __qfix_history_idx table<"search" | "vibe", number>
local State = {}
State.__index = State
@@ -55,6 +56,10 @@ local function create()
__view_log_idx = 1,
__request_history = {},
__request_by_id = {},
+ __qfix_history_idx = {
+ search = 0,
+ vibe = 0,
+ },
tmp_dir = nil,
}
end
diff --git a/lua/99/test/qfix_navigation_spec.lua b/lua/99/test/qfix_navigation_spec.lua
new file mode 100644
index 0000000..f079a9e
--- /dev/null
+++ b/lua/99/test/qfix_navigation_spec.lua
@@ -0,0 +1,70 @@
+-- luacheck: globals describe it assert before_each
+local _99 = require("99")
+local test_utils = require("99.test.test_utils")
+local eq = assert.are.same
+
+local content = {
+ "local value = 1",
+ "return value",
+}
+
+local function qfix_first_text()
+ local items = vim.fn.getqflist()
+ local first = items[1]
+ assert(first, "expected a quickfix item")
+ return first.text
+end
+
+describe("qfix navigation", function()
+ local provider
+ local results = {}
+
+ before_each(function()
+ provider = test_utils.test_setup(content, 1, 0)
+ end)
+
+ it("navigates older and newer search quickfix results", function()
+ _99.search({ additional_prompt = "search one" })
+ provider:resolve("success", "/tmp/one.lua:1:1,1,first search")
+ test_utils.next_frame()
+
+ _99.search({ additional_prompt = "search two" })
+ provider:resolve("success", "/tmp/two.lua:1:1,1,second search")
+ test_utils.next_frame()
+
+ _99.search({ additional_prompt = "search three" })
+ provider:resolve("success", "/tmp/three.lua:1:1,1,third search")
+ test_utils.next_frame()
+
+ _99.qfix_older({ operation = "search" })
+ eq("second search", qfix_first_text())
+
+ _99.qfix_older({ operation = "search" })
+ eq("first search", qfix_first_text())
+
+ _99.qfix_newer({ operation = "search" })
+ eq("second search", qfix_first_text())
+
+ _99.qfix_top({ operation = "search" })
+ eq("third search", qfix_first_text())
+ end)
+
+ it("navigates vibe quickfix history through vibe results", function()
+ _99.vibe({ additional_prompt = "vibe one" })
+ provider:resolve("success", "/tmp/a.lua:1:1,1,first vibe")
+ test_utils.next_frame()
+
+ _99.vibe({ additional_prompt = "vibe two" })
+ provider:resolve("success", "/tmp/b.lua:1:1,1,second vibe")
+ test_utils.next_frame()
+
+ _99.qfix_top({ operation = "vibe" })
+ eq("second vibe", qfix_first_text())
+
+ _99.qfix_older({ operation = "vibe" })
+ eq("first vibe", qfix_first_text())
+
+ _99.qfix_newer({ operation = "vibe" })
+ eq("second vibe", qfix_first_text())
+ end)
+end)