Review and cleanup
This commit is contained in:
parent
050f9bd3b5
commit
2b7717bccf
@ -16,30 +16,116 @@ local current_suggestion = {
|
||||
|
||||
-- Add at the top of the file with other state variables
|
||||
local completion_cache = {
|
||||
last_line = nil,
|
||||
last_col = nil,
|
||||
suggestions = {},
|
||||
timestamp = 0,
|
||||
ttl = 30000 -- Cache TTL in milliseconds (30 seconds)
|
||||
entries = {},
|
||||
max_entries = 1000,
|
||||
ttl = 30 * 60 * 1000, -- 30 minutes TTL
|
||||
last_cleanup = 0
|
||||
}
|
||||
|
||||
-- Add this function
|
||||
local function get_cached_suggestion(line, col)
|
||||
-- Add completion triggers detection
|
||||
local function should_trigger_completion(line_text, col)
|
||||
local config = require("gemini.config")
|
||||
local trigger_chars = config.options.completion.trigger_characters or "."
|
||||
|
||||
-- Don't trigger on empty lines or spaces
|
||||
if line_text:match("^%s*$") then return false end
|
||||
|
||||
-- Check minimum characters
|
||||
local text_before_cursor = line_text:sub(1, col)
|
||||
if #text_before_cursor < current_suggestion.min_chars then return false end
|
||||
|
||||
-- Check if we're in a comment
|
||||
local filetype = vim.bo.filetype
|
||||
local comment_string = vim.bo.commentstring
|
||||
if comment_string then
|
||||
local comment_start = comment_string:match("^(.-)%%s")
|
||||
if comment_start and text_before_cursor:match(vim.pesc(comment_start)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for trigger characters
|
||||
local last_char = text_before_cursor:sub(-1)
|
||||
if trigger_chars:find(last_char, 1, true) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check for meaningful context
|
||||
local meaningful_pattern = "[%w_][%w_%.%:]*$" -- Matches identifiers and dot/colon access
|
||||
local context = text_before_cursor:match(meaningful_pattern)
|
||||
if context and #context >= 2 then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Improved cache key generation
|
||||
local function get_cache_key(context, line_text, col)
|
||||
local prefix = line_text:sub(1, col)
|
||||
local filetype = vim.bo.filetype
|
||||
local key_parts = {
|
||||
filetype,
|
||||
prefix,
|
||||
vim.inspect(context):sub(1, 100) -- Limited context hash
|
||||
}
|
||||
return vim.fn.sha256(table.concat(key_parts, "||"))
|
||||
end
|
||||
|
||||
-- Cache management
|
||||
local function cleanup_cache()
|
||||
local now = vim.loop.now()
|
||||
if completion_cache.last_line == line
|
||||
and completion_cache.last_col == col
|
||||
and (now - completion_cache.timestamp) < completion_cache.ttl then
|
||||
return completion_cache.suggestions
|
||||
if now - completion_cache.last_cleanup < 60000 then return end -- Cleanup max once per minute
|
||||
|
||||
local count = 0
|
||||
local expired = {}
|
||||
|
||||
for key, entry in pairs(completion_cache.entries) do
|
||||
if now - entry.timestamp > completion_cache.ttl then
|
||||
table.insert(expired, key)
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
-- Remove expired entries
|
||||
for _, key in ipairs(expired) do
|
||||
completion_cache.entries[key] = nil
|
||||
end
|
||||
|
||||
-- If still too many entries, remove oldest
|
||||
if count > completion_cache.max_entries then
|
||||
local entries = {}
|
||||
for k, v in pairs(completion_cache.entries) do
|
||||
table.insert(entries, {key = k, timestamp = v.timestamp})
|
||||
end
|
||||
table.sort(entries, function(a, b) return a.timestamp < b.timestamp end)
|
||||
|
||||
for i = 1, count - completion_cache.max_entries do
|
||||
completion_cache.entries[entries[i].key] = nil
|
||||
end
|
||||
end
|
||||
|
||||
completion_cache.last_cleanup = now
|
||||
end
|
||||
|
||||
-- Cache access
|
||||
local function get_cached_completion(context, line_text, col)
|
||||
cleanup_cache()
|
||||
local key = get_cache_key(context, line_text, col)
|
||||
local entry = completion_cache.entries[key]
|
||||
|
||||
if entry and (vim.loop.now() - entry.timestamp) < completion_cache.ttl then
|
||||
return entry.completion
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Add this function
|
||||
local function cache_suggestion(line, col, suggestions)
|
||||
completion_cache.last_line = line
|
||||
completion_cache.last_col = col
|
||||
completion_cache.suggestions = suggestions
|
||||
completion_cache.timestamp = vim.loop.now()
|
||||
local function cache_completion(context, line_text, col, completion)
|
||||
local key = get_cache_key(context, line_text, col)
|
||||
completion_cache.entries[key] = {
|
||||
completion = completion,
|
||||
timestamp = vim.loop.now()
|
||||
}
|
||||
end
|
||||
|
||||
-- Helper function to get visible lines around cursor
|
||||
@ -279,11 +365,29 @@ function M.trigger_completion()
|
||||
local col = cursor[2]
|
||||
local current_line = vim.api.nvim_get_current_line()
|
||||
|
||||
-- Check if we should trigger completion
|
||||
if not should_trigger_completion(current_line, col) then
|
||||
clear_suggestion()
|
||||
return
|
||||
end
|
||||
|
||||
-- Check rate limiting
|
||||
if should_rate_limit() then return end
|
||||
|
||||
-- Get context
|
||||
local visible_lines = vim.api.nvim_buf_get_lines(0, math.max(0, line - 10), line + 10, false)
|
||||
local context, detected_file_type = get_context_around_cursor(visible_lines, 10, current_suggestion.max_context_lines)
|
||||
local context = get_context_around_cursor(visible_lines, 10, current_suggestion.max_context_lines)
|
||||
|
||||
-- Create a very specific prompt for raw completion
|
||||
-- Check cache first
|
||||
local cached_completion = get_cached_completion(context, current_line, col)
|
||||
if cached_completion then
|
||||
vim.schedule(function()
|
||||
show_suggestion(cached_completion, col)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- Create prompt for completion
|
||||
local prompt = string.format([[
|
||||
You are an autocomplete engine. Respond ONLY with the direct completion text.
|
||||
DO NOT include:
|
||||
@ -297,19 +401,23 @@ Language: %s
|
||||
Context:
|
||||
%s
|
||||
Complete this line:
|
||||
%s]], detected_file_type, table.concat(context, "\n"), current_line)
|
||||
%s]], vim.bo.filetype, table.concat(context, "\n"), current_line)
|
||||
|
||||
-- Make API request
|
||||
api.get_response(prompt, nil, function(response, error)
|
||||
if error then
|
||||
vim.notify("Completion error: " .. error, vim.log.levels.ERROR)
|
||||
if error:match("code = 429") then
|
||||
handle_rate_limit()
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if response then
|
||||
-- Show the raw suggestion directly
|
||||
-- Cache the successful completion
|
||||
cache_completion(context, current_line, col, response)
|
||||
|
||||
vim.schedule(function()
|
||||
-- Only show if cursor position hasn't changed
|
||||
local new_cursor = vim.api.nvim_win_get_cursor(0)
|
||||
if new_cursor[1] - 1 == line and new_cursor[2] == col then
|
||||
show_suggestion(response, col)
|
||||
|
@ -22,11 +22,13 @@ M.defaults = {
|
||||
completion = {
|
||||
enabled = true,
|
||||
debounce_ms = 1000,
|
||||
min_chars = 0,
|
||||
min_chars = 2,
|
||||
max_context_lines = 10,
|
||||
style = "ghost", -- or "inline"
|
||||
trigger_characters = ".", -- Add trigger characters
|
||||
style = "ghost",
|
||||
trigger_characters = ".:", -- Trigger on dot and colon
|
||||
exclude_filetypes = { "TelescopePrompt", "neo-tree" },
|
||||
cache_ttl = 30 * 60 * 1000, -- 30 minutes
|
||||
max_cache_entries = 1000,
|
||||
suggestion_highlight = {
|
||||
fg = '#666666',
|
||||
italic = true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user