From fa37ffe285188f6fb81e6124183452964edf912e Mon Sep 17 00:00:00 2001 From: Jonas Widen Date: Mon, 17 Mar 2025 07:13:07 +0100 Subject: [PATCH] debug completion --- lua/gemini/completion.lua | 101 +++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/lua/gemini/completion.lua b/lua/gemini/completion.lua index c96b5ec..fce4b5c 100644 --- a/lua/gemini/completion.lua +++ b/lua/gemini/completion.lua @@ -50,37 +50,52 @@ end local function show_suggestion(suggestion, start_col) clear_suggestion() - -- Only use first line of suggestion - suggestion = suggestion:match("^[^\n]*") - if suggestion == "" then return end + -- Split suggestion into lines + local suggestion_lines = vim.split(suggestion, "\n") + if #suggestion_lines == 0 then return end + -- Get current line info local line = vim.api.nvim_win_get_cursor(0)[1] - 1 local line_text = vim.api.nvim_buf_get_lines(0, line, line + 1, true)[1] -- Get text before cursor on current line local prefix = string.sub(line_text, 1, start_col) - -- Only show suggestion if it continues the current text - if not suggestion:find("^" .. vim.pesc(prefix), 1, true) then - suggestion = prefix .. suggestion + -- Process first line of suggestion + local first_line = suggestion_lines[1] + if not first_line:find("^" .. vim.pesc(prefix), 1, true) then + first_line = prefix .. first_line end + first_line = first_line:sub(#prefix + 1) - -- Remove the prefix from the suggestion to avoid duplication - suggestion = suggestion:sub(#prefix + 1) - - if suggestion == "" then return end + if first_line == "" and #suggestion_lines == 1 then return end current_suggestion.text = suggestion current_suggestion.start_col = start_col - -- Make the text virtual (doesn't affect actual buffer content) - vim.api.nvim_buf_set_extmark(0, current_suggestion.namespace_id, line, start_col, { - virt_text = {{suggestion, 'GeminiSuggestion'}}, - virt_text_pos = 'inline', - virt_text_hide = true, - }) + -- Show first line as virtual text + if first_line ~= "" then + vim.api.nvim_buf_set_extmark(0, current_suggestion.namespace_id, line, start_col, { + virt_text = {{first_line, 'GeminiSuggestion'}}, + virt_text_pos = 'inline', + virt_text_hide = true, + }) + end - debug_print("Showing suggestion: %s", suggestion) + -- Show remaining lines as virtual lines + if #suggestion_lines > 1 then + local virt_lines = {} + for i = 2, #suggestion_lines do + table.insert(virt_lines, {{suggestion_lines[i], 'GeminiSuggestion'}}) + end + + vim.api.nvim_buf_set_extmark(0, current_suggestion.namespace_id, line, start_col, { + virt_lines = virt_lines, + virt_lines_above = false, + }) + end + + debug_print("Showing suggestion (%d lines)", #suggestion_lines) end function M.accept_suggestion() @@ -96,17 +111,35 @@ function M.accept_suggestion() return false end + -- Split suggestion into lines + local suggestion_lines = vim.split(current_suggestion.text, "\n") + if #suggestion_lines == 0 then return false end + + -- Insert first line at cursor position vim.api.nvim_buf_set_text( 0, line, col, line, col, - {current_suggestion.text} + {suggestion_lines[1]} ) + -- Insert remaining lines below + if #suggestion_lines > 1 then + vim.api.nvim_buf_set_lines( + 0, + line + 1, + line + 1, + false, + vim.list_slice(suggestion_lines, 2) + ) + end + -- Move cursor to end of inserted text - vim.api.nvim_win_set_cursor(0, {line + 1, col + #current_suggestion.text}) + local final_line = line + #suggestion_lines - 1 + local final_col = #suggestion_lines[#suggestion_lines] + vim.api.nvim_win_set_cursor(0, {final_line + 1, final_col}) clear_suggestion() return true @@ -164,27 +197,31 @@ function M.trigger_completion() debug_print("Getting completion for: %s", prefix) - -- Construct context from buffer + -- Construct context with line numbers and cursor position local context = {} + local cursor_line = line + local cursor_col = col -- Add up to 10 previous lines for context local start_line = math.max(1, line - 10) for i = start_line, line - 1 do if lines[i] and #lines[i] > 0 then - table.insert(context, lines[i]) + table.insert(context, string.format("L%d: %s", i, lines[i])) end end - -- Add current line + -- Add current line with cursor position marker (^) if current_line and #current_line > 0 then - table.insert(context, current_line) + local cursor_marker = string.rep(" ", cursor_col) .. "^" + table.insert(context, string.format("L%d (current): %s", cursor_line, current_line)) + table.insert(context, cursor_marker) end -- Add up to 10 lines after current line local end_line = math.min(#lines, line + 10) for i = line + 1, end_line do if lines[i] and #lines[i] > 0 then - table.insert(context, lines[i]) + table.insert(context, string.format("L%d: %s", i, lines[i])) end end @@ -195,11 +232,19 @@ function M.trigger_completion() return end + -- Get file type for better context + local file_type = vim.bo.filetype + -- Construct prompt for Gemini - local prompt = string.format( - "Complete this code. Consider the context (10 lines before and after). Return ONLY the completion that would naturally follow at the cursor position, no explanation:\n%s", - full_context - ) + local prompt = string.format([[ +I'm editing a %s file. Here's the context around line %d where my cursor (^) is: + +%s + +Complete the code at the cursor position. Consider the syntax and style of the surrounding code. +Return ONLY the completion that would naturally follow, no explanation. +The completion can be multiple lines if appropriate for the context. +]], file_type, cursor_line, full_context) -- Validate prompt before sending if #prompt == 0 then