summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorThePrimeAgain <theprimeagain@theprimeagain.com>2026-01-15 11:22:01 -0700
committerThePrimeAgain <theprimeagain@theprimeagain.com>2026-01-15 11:22:01 -0700
commitfc2ce13fcc6454fa12ee1015f921611cd2edc4fa (patch)
treedc2cc7817d012eff49d8a902f8d083e73e98bf59 /lua
parent4e24d093d50177e299823703759a5e276d198170 (diff)
downloada4-fc2ce13fcc6454fa12ee1015f921611cd2edc4fa.tar.xz
a4-fc2ce13fcc6454fa12ee1015f921611cd2edc4fa.zip
autocomplete appearing to work
Diffstat (limited to 'lua')
-rw-r--r--lua/99/extensions/agents/helpers.lua (renamed from lua/99/agents/helpers.lua)4
-rw-r--r--lua/99/extensions/agents/init.lua (renamed from lua/99/agents/init.lua)19
-rw-r--r--lua/99/extensions/cmp.lua76
-rw-r--r--lua/99/extensions/init.lua38
-rw-r--r--lua/99/init.lua75
-rw-r--r--lua/99/window/init.lua19
6 files changed, 161 insertions, 70 deletions
diff --git a/lua/99/agents/helpers.lua b/lua/99/extensions/agents/helpers.lua
index a5000cb..1f4ed01 100644
--- a/lua/99/agents/helpers.lua
+++ b/lua/99/extensions/agents/helpers.lua
@@ -3,8 +3,8 @@ local M = {}
--- @param dir string
--- @return _99.Agents.Rule[]
function M.ls(dir)
- local cursor_rules_dir = vim.uv.cwd() .. dir
- local files = vim.fn.glob(cursor_rules_dir .. "/*.{mdc,md}", false, true)
+ local cwd = vim.fs.joinpath(vim.uv.cwd(), dir)
+ local files = vim.fn.glob(cwd .. "/*.{mdc,md}", false, true)
local rules = {}
for _, file in ipairs(files) do
diff --git a/lua/99/agents/init.lua b/lua/99/extensions/agents/init.lua
index be43727..f594802 100644
--- a/lua/99/agents/init.lua
+++ b/lua/99/extensions/agents/init.lua
@@ -1,4 +1,4 @@
-local helpers = require("99.agents.helpers")
+local helpers = require("99.extensions.agents.helpers")
local M = {}
--- @class _99.Agents.Rule
@@ -17,7 +17,7 @@ local M = {}
function M.rules(_99)
local cursor = helpers.ls(".cursor/rules")
local custom = {}
- for _, path in ipairs(_99.custom_rules) do
+ for _, path in ipairs(_99.completion.custom_rules or {}) do
local c = helpers.ls(path)
table.insert(custom, c)
end
@@ -27,4 +27,19 @@ function M.rules(_99)
}
end
+--- @param rules _99.Agents.Rules
+--- @return _99.Agents.Rule[]
+function M.rules_to_items(rules)
+ local items = {}
+ for _, rule in ipairs(rules.cursor or {}) do
+ table.insert(items, rule)
+ end
+ for _, custom_rules in ipairs(rules.custom or {}) do
+ for _, rule in ipairs(custom_rules) do
+ table.insert(items, rule)
+ end
+ end
+ return items
+end
+
return M
diff --git a/lua/99/extensions/cmp.lua b/lua/99/extensions/cmp.lua
index e55ae36..30e5d2c 100644
--- a/lua/99/extensions/cmp.lua
+++ b/lua/99/extensions/cmp.lua
@@ -1,14 +1,24 @@
+local Agents = require("99.extensions.agents")
+local SOURCE = "99"
+
+--- @param _99 _99.State
+--- @return _99.Agents.Rule[]
+local function rules(_99)
+ return Agents.rules_to_items(Agents.rules(_99))
+end
+
--- @class CmpSource
--- @field _99 _99.State
---- @field items string[]
+--- @field items _99.Agents.Rule[]
local CmpSource = {}
CmpSource.__index = CmpSource
-local SOURCE = "99"
-
--- @param _99 _99.State
function CmpSource.new(_99)
- return setmetatable({}, CmpSource)
+ return setmetatable({
+ _99 = _99,
+ items = rules(_99),
+ }, CmpSource)
end
function CmpSource:is_available()
@@ -39,41 +49,39 @@ end
-- true: I might return more if user types more
-- false: this result set is complete
function CmpSource:complete(params, callback)
- local cmp = require("cmp")
local before = params.context.cursor_before_line or ""
- local prefix = before:match("(%w+)$") or ""
-
local items = {} --[[ @as CompletionItem[] ]]
- print("complete: context", vim.inspect(params.context))
+ if #before > 1 and before:sub(#before - 1) ~= " @" then
+ callback({
+ items = {},
+ isIncomplete = false,
+ })
+ return
+ end
+
+ for _, item in ipairs(self.items) do
+ table.insert(items, {
+ label = item.name,
+ insertText = item.path,
+ filterText = item.name,
+ kind = 17, -- file
+ -- documentation = "here is the documentation and everything associated with it",
+ -- detail = "detail: right side hint",
+ })
+ end
callback({
items = items,
- isIncomplete = true,
+ isIncomplete = false,
})
end
--- resolve(completion_item, callback) (optional)
--- Some sources return lightweight items first, then fill in heavy fields
--- only when the user selects an item.
---
--- For example:
--- - fetch docs lazily
--- - compute expensive detail text
---
--- If you don’t need it, omit it.
+--- TODO: Look into what this could be
function CmpSource:resolve(completion_item, callback)
- -- You can modify completion_item here.
callback(completion_item)
end
--- execute(completion_item, callback) (optional)
--- Called when the item is confirmed, if the item contains an "command" field
--- or if your source wants to perform side-effects.
---
--- Examples:
--- - insert import statements (usually via additionalTextEdits instead)
--- - open a snippet, run something, etc.
function CmpSource:execute(completion_item, callback)
callback(completion_item)
end
@@ -86,24 +94,32 @@ local function init_for_buffer(_99)
local cmp = require("cmp")
cmp.setup.buffer({
sources = {
- { name = "my_source" },
+ { name = SOURCE },
},
})
end
--- @param _99 _99.State
local function init(_99)
- assert(source == nil, "the source must be nil when calling init on an completer")
+ assert(
+ source == nil,
+ "the source must be nil when calling init on an completer"
+ )
local cmp = require("cmp")
source = CmpSource.new(_99)
cmp.register_source(SOURCE, source)
end
-local function refresh_state(_99) end
+--- @param _99 _99.State
+local function refresh_state(_99)
+ source.items = rules(_99)
+end
-return {
+--- @type _99.Extensions.Source
+local source_wrapper = {
init_for_buffer = init_for_buffer,
init = init,
refresh_state = refresh_state,
}
+return source_wrapper
diff --git a/lua/99/extensions/init.lua b/lua/99/extensions/init.lua
index 94190d6..ceb63a5 100644
--- a/lua/99/extensions/init.lua
+++ b/lua/99/extensions/init.lua
@@ -1,5 +1,37 @@
-local M = {}
+local cmp = require("99.extensions.cmp")
---- @param _99 _99.State
-function M.init_buffer(_99)
+--- @class _99.Extensions.Source
+--- @field init_for_buffer fun(_99: _99.State): nil
+--- @field init fun(_99: _99.State): nil
+--- @field refresh_state fun(_99: _99.State): nil
+
+--- @param completion _99.Completion | nil
+--- @return _99.Extensions.Source | nil
+local function get_source(completion)
+ if not completion or not completion.source then
+ return
+ end
+ local source = completion.source
+ if source == "cmp" then
+ return cmp
+ end
end
+
+return {
+ --- @param _99 _99.State
+ init = function(_99)
+ local source = get_source(_99.completion)
+ if not source then
+ return
+ end
+ source.init(_99)
+ end,
+
+ setup_buffer = function(_99)
+ local source = get_source(_99.completion)
+ if not source then
+ return
+ end
+ source.init_for_buffer(_99)
+ end,
+}
diff --git a/lua/99/init.lua b/lua/99/init.lua
index 3faa6e2..a677d6b 100644
--- a/lua/99/init.lua
+++ b/lua/99/init.lua
@@ -6,6 +6,7 @@ local Window = require("99.window")
local get_id = require("99.id")
local RequestContext = require("99.request-context")
local Range = require("99.geo").Range
+local Extensions = require("99.extensions")
--- @alias _99.Cleanup fun(): nil
@@ -34,6 +35,10 @@ local function create_99_state()
}
end
+--- @class _99.Completion
+--- @field source "cmp" | nil
+--- @field custom_rules string[] | nil
+
--- @class _99.Options
--- @field logger _99.Logger.Options?
--- @field model string?
@@ -41,14 +46,14 @@ end
--- @field provider _99.Provider?
--- @field debug_log_prefix string?
--- @field display_errors? boolean
---- @field custom_rules? string[]
+--- @field completion _99.Completion?
--- unanswered question -- will i need to queue messages one at a time or
--- just send them all... So to prepare ill be sending around this state object
--- @class _99.State
+--- @field completion _99.Completion
--- @field model string
--- @field md_files string[]
---- @field custom_rules string[]
--- @field prompts _99.Prompts
--- @field ai_stdout_rows number
--- @field languages string[]
@@ -146,19 +151,25 @@ end
function _99.fill_in_function_prompt()
local context = get_context("fill-in-function-with-prompt")
+
context.logger:debug("start")
- Window.capture_input(function(success, response)
- context.logger:debug(
- "capture_prompt",
- "success",
- success,
- "response",
- response
- )
- if success then
- ops.fill_in_function(context, response)
- end
- end, {})
+ Window.capture_input({
+ cb = function(success, response)
+ context.logger:debug(
+ "capture_prompt",
+ "success",
+ success,
+ "response",
+ response
+ )
+ if success then
+ ops.fill_in_function(context, response)
+ end
+ end,
+ on_load = function()
+ Extensions.setup_buffer(_99_state)
+ end,
+ })
end
function _99.fill_in_function()
@@ -168,18 +179,23 @@ end
function _99.visual_prompt()
local context = get_context("over-range-with-prompt")
context.logger:debug("start")
- Window.capture_input(function(success, response)
- context.logger:debug(
- "capture_prompt",
- "success",
- success,
- "response",
- response
- )
- if success then
- _99.visual(response)
- end
- end, {})
+ Window.capture_input({
+ cb = function(success, response)
+ context.logger:debug(
+ "capture_prompt",
+ "success",
+ success,
+ "response",
+ response
+ )
+ if success then
+ _99.visual(response)
+ end
+ end,
+ on_load = function()
+ Extensions.setup_buffer(_99_state)
+ end,
+ })
end
--- @param prompt string?
@@ -250,7 +266,11 @@ function _99.setup(opts)
opts = opts or {}
_99_state = _99_State.new()
_99_state.provider_override = opts.provider
- _99_state.custom_rules = opts.custom_rules or {}
+ _99_state.completion = opts.completion
+ or {
+ source = nil,
+ custom_rules = {},
+ }
vim.api.nvim_create_autocmd("VimLeavePre", {
callback = function()
@@ -275,6 +295,7 @@ function _99.setup(opts)
_99_state.display_errors = opts.display_errors or false
Languages.initialize(_99_state)
+ Extensions.init(_99_state)
end
--- @param md string
diff --git a/lua/99/window/init.lua b/lua/99/window/init.lua
index 8f45433..3475d5a 100644
--- a/lua/99/window/init.lua
+++ b/lua/99/window/init.lua
@@ -257,9 +257,12 @@ local function set_defaul_win_options(win, name)
vim.bo[win.buf_id].swapfile = false
end
---- @param cb fun(success: boolean, result: string): nil
---- @param opts {}
-function M.capture_input(cb, opts)
+--- @class _99.window.CaptureInputOpts
+--- @field cb fun(success: boolean, result: string): nil
+--- @field on_load? fun(): nil
+
+--- @param opts _99.window.CaptureInputOpts
+function M.capture_input(opts)
_ = opts
M.clear_active_popups()
@@ -299,7 +302,7 @@ function M.capture_input(cb, opts)
local lines = vim.api.nvim_buf_get_lines(win.buf_id, 0, -1, false)
local result = table.concat(lines, "\n")
M.clear_active_popups()
- cb(true, result)
+ opts.cb(true, result)
end,
})
@@ -322,14 +325,18 @@ function M.capture_input(cb, opts)
return
end
M.clear_active_popups()
- cb(false, "")
+ opts.cb(false, "")
end,
})
vim.keymap.set("n", "q", function()
M.clear_active_popups()
- cb(false, "")
+ opts.cb(false, "")
end, { buffer = win.buf_id, nowait = true })
+
+ if opts.on_load then
+ vim.schedule(opts.on_load)
+ end
end
function M.clear_active_popups()