migrating the cmp brain
This commit is contained in:
@@ -305,8 +305,8 @@ end
|
||||
---@param base_path string Base path to resolve relative file paths
|
||||
---@return table[] attached_files List of {path, content} tables
|
||||
local function read_attached_files(prompt_content, base_path)
|
||||
local parser = require("codetyper.parser")
|
||||
local file_refs = parser.extract_file_references(prompt_content)
|
||||
local extract_file_references = require("codetyper.parser.extract_file_references")
|
||||
local file_refs = extract_file_references(prompt_content)
|
||||
local attached = {}
|
||||
local cwd = vim.fn.getcwd()
|
||||
local base_dir = vim.fn.fnamemodify(base_path, ":h")
|
||||
@@ -349,7 +349,10 @@ function M.check_for_closed_prompt()
|
||||
end
|
||||
is_processing = true
|
||||
|
||||
local parser = require("codetyper.parser")
|
||||
local has_closing_tag = require("codetyper.parser.has_closing_tag")
|
||||
local get_last_prompt = require("codetyper.parser.get_last_prompt")
|
||||
local clean_prompt = require("codetyper.parser.clean_prompt")
|
||||
local strip_file_references = require("codetyper.parser.strip_file_references")
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local current_file = vim.fn.expand("%:p")
|
||||
@@ -373,9 +376,9 @@ function M.check_for_closed_prompt()
|
||||
local current_line = lines[1]
|
||||
|
||||
-- Check if line contains closing tag
|
||||
if parser.has_closing_tag(current_line, config.patterns.close_tag) then
|
||||
if has_closing_tag(current_line, config.patterns.close_tag) then
|
||||
-- Find the complete prompt
|
||||
local prompt = parser.get_last_prompt(bufnr)
|
||||
local prompt = get_last_prompt(bufnr)
|
||||
if prompt and prompt.content and prompt.content ~= "" then
|
||||
-- Generate unique key for this prompt
|
||||
local prompt_key = get_prompt_key(bufnr, prompt)
|
||||
@@ -421,7 +424,7 @@ function M.check_for_closed_prompt()
|
||||
local attached_files = read_attached_files(prompt.content, current_file)
|
||||
|
||||
-- Clean prompt content (strip file references)
|
||||
local cleaned = parser.clean_prompt(parser.strip_file_references(prompt.content))
|
||||
local cleaned = clean_prompt(strip_file_references(prompt.content))
|
||||
|
||||
-- Check if we're working from a coder file
|
||||
local is_from_coder_file = utils.is_coder_file(current_file)
|
||||
@@ -556,7 +559,8 @@ end
|
||||
---@param current_file string Current file path
|
||||
---@param skip_processed_check? boolean Skip the processed check (for manual mode)
|
||||
function M.process_single_prompt(bufnr, prompt, current_file, skip_processed_check)
|
||||
local parser = require("codetyper.parser")
|
||||
local clean_prompt = require("codetyper.parser.clean_prompt")
|
||||
local strip_file_references = require("codetyper.parser.strip_file_references")
|
||||
local scheduler = require("codetyper.core.scheduler.scheduler")
|
||||
|
||||
if not prompt.content or prompt.content == "" then
|
||||
@@ -606,7 +610,7 @@ function M.process_single_prompt(bufnr, prompt, current_file, skip_processed_che
|
||||
local attached_files = read_attached_files(prompt.content, current_file)
|
||||
|
||||
-- Clean prompt content (strip file references)
|
||||
local cleaned = parser.clean_prompt(parser.strip_file_references(prompt.content))
|
||||
local cleaned = clean_prompt(strip_file_references(prompt.content))
|
||||
|
||||
-- Resolve scope in target file FIRST (need it to adjust intent)
|
||||
-- Only resolve scope if NOT from coder file (line numbers don't apply)
|
||||
@@ -744,7 +748,7 @@ end
|
||||
|
||||
--- Check and process all closed prompts in the buffer (works on ANY file)
|
||||
function M.check_all_prompts()
|
||||
local parser = require("codetyper.parser")
|
||||
local find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local current_file = vim.fn.expand("%:p")
|
||||
|
||||
@@ -754,7 +758,7 @@ function M.check_all_prompts()
|
||||
end
|
||||
|
||||
-- Find all prompts in buffer
|
||||
local prompts = parser.find_prompts_in_buffer(bufnr)
|
||||
local prompts = find_prompts_in_buffer(bufnr)
|
||||
|
||||
if #prompts == 0 then
|
||||
return
|
||||
@@ -777,11 +781,11 @@ end
|
||||
--- Check for closed prompt with preference check
|
||||
--- If user hasn't chosen auto/manual mode, ask them first
|
||||
function M.check_for_closed_prompt_with_preference()
|
||||
local parser = require("codetyper.parser")
|
||||
local find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
|
||||
-- First check if there are any prompts to process
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local prompts = parser.find_prompts_in_buffer(bufnr)
|
||||
local prompts = find_prompts_in_buffer(bufnr)
|
||||
if #prompts == 0 then
|
||||
return
|
||||
end
|
||||
@@ -796,11 +800,11 @@ end
|
||||
--- Check all prompts with preference check
|
||||
function M.check_all_prompts_with_preference()
|
||||
local preferences = require("codetyper.config.preferences")
|
||||
local parser = require("codetyper.parser")
|
||||
local find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
|
||||
-- First check if there are any prompts to process
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local prompts = parser.find_prompts_in_buffer(bufnr)
|
||||
local prompts = find_prompts_in_buffer(bufnr)
|
||||
if #prompts == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
65
lua/codetyper/adapters/nvim/cmp/get_brain_completions.lua
Normal file
65
lua/codetyper/adapters/nvim/cmp/get_brain_completions.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
--- Get completion items from brain context
|
||||
---@param prefix string Current word prefix
|
||||
---@return table[] items
|
||||
local function get_brain_completions(prefix)
|
||||
local items = {}
|
||||
|
||||
local ok_brain, brain = pcall(require, "codetyper.brain")
|
||||
if not ok_brain then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Check if brain is initialized safely
|
||||
local is_init = false
|
||||
if brain.is_initialized then
|
||||
local ok, result = pcall(brain.is_initialized)
|
||||
is_init = ok and result
|
||||
end
|
||||
|
||||
if not is_init then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Query brain for relevant patterns
|
||||
local ok_query, result = pcall(brain.query, {
|
||||
query = prefix,
|
||||
max_results = 10,
|
||||
types = { "pattern" },
|
||||
})
|
||||
|
||||
if ok_query and result and result.nodes then
|
||||
for _, node in ipairs(result.nodes) do
|
||||
if node.c and node.c.s then
|
||||
local summary = node.c.s
|
||||
for name in summary:gmatch("functions:%s*([^;]+)") do
|
||||
for func in name:gmatch("([%w_]+)") do
|
||||
if func:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = func,
|
||||
kind = 3, -- Function
|
||||
detail = "[brain]",
|
||||
documentation = summary,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
for name in summary:gmatch("classes:%s*([^;]+)") do
|
||||
for class in name:gmatch("([%w_]+)") do
|
||||
if class:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = class,
|
||||
kind = 7, -- Class
|
||||
detail = "[brain]",
|
||||
documentation = summary,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
return get_brain_completions
|
||||
28
lua/codetyper/adapters/nvim/cmp/get_buffer_completions.lua
Normal file
28
lua/codetyper/adapters/nvim/cmp/get_buffer_completions.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
--- Get completion items from current buffer (fallback)
|
||||
---@param prefix string Current word prefix
|
||||
---@param bufnr number Buffer number
|
||||
---@return table[] items
|
||||
local function get_buffer_completions(prefix, bufnr)
|
||||
local items = {}
|
||||
local seen = {}
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local prefix_lower = prefix:lower()
|
||||
|
||||
for _, line in ipairs(lines) do
|
||||
for word in line:gmatch("[%a_][%w_]*") do
|
||||
if #word >= 3 and word:lower():find(prefix_lower, 1, true) and not seen[word] and word ~= prefix then
|
||||
seen[word] = true
|
||||
table.insert(items, {
|
||||
label = word,
|
||||
kind = 1, -- Text
|
||||
detail = "[buffer]",
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
return get_buffer_completions
|
||||
30
lua/codetyper/adapters/nvim/cmp/get_copilot_suggestion.lua
Normal file
30
lua/codetyper/adapters/nvim/cmp/get_copilot_suggestion.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
--- Try to get Copilot suggestion if plugin is installed
|
||||
---@param prefix string
|
||||
---@return string|nil suggestion
|
||||
local function get_copilot_suggestion(prefix)
|
||||
-- Try copilot.lua suggestion API first
|
||||
local ok, copilot_suggestion = pcall(require, "copilot.suggestion")
|
||||
if ok and copilot_suggestion and type(copilot_suggestion.get_suggestion) == "function" then
|
||||
local ok2, suggestion = pcall(copilot_suggestion.get_suggestion)
|
||||
if ok2 and suggestion and suggestion ~= "" then
|
||||
if prefix == "" or suggestion:lower():match(prefix:lower(), 1) then
|
||||
return suggestion
|
||||
else
|
||||
return suggestion
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: try older copilot module if present
|
||||
local ok3, copilot = pcall(require, "copilot")
|
||||
if ok3 and copilot and type(copilot.get_suggestion) == "function" then
|
||||
local ok4, suggestion = pcall(copilot.get_suggestion)
|
||||
if ok4 and suggestion and suggestion ~= "" then
|
||||
return suggestion
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
return get_copilot_suggestion
|
||||
65
lua/codetyper/adapters/nvim/cmp/get_indexer_completions.lua
Normal file
65
lua/codetyper/adapters/nvim/cmp/get_indexer_completions.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
--- Get completion items from indexer symbols
|
||||
---@param prefix string Current word prefix
|
||||
---@return table[] items
|
||||
local function get_indexer_completions(prefix)
|
||||
local items = {}
|
||||
|
||||
local ok_indexer, indexer = pcall(require, "codetyper.indexer")
|
||||
if not ok_indexer then
|
||||
return items
|
||||
end
|
||||
|
||||
local ok_load, index = pcall(indexer.load_index)
|
||||
if not ok_load or not index then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Search symbols
|
||||
if index.symbols then
|
||||
for symbol, files in pairs(index.symbols) do
|
||||
if symbol:lower():find(prefix:lower(), 1, true) then
|
||||
local files_str = type(files) == "table" and table.concat(files, ", ") or tostring(files)
|
||||
table.insert(items, {
|
||||
label = symbol,
|
||||
kind = 6, -- Variable (generic)
|
||||
detail = "[index] " .. files_str:sub(1, 30),
|
||||
documentation = "Symbol found in: " .. files_str,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Search functions in files
|
||||
if index.files then
|
||||
for filepath, file_index in pairs(index.files) do
|
||||
if file_index and file_index.functions then
|
||||
for _, func in ipairs(file_index.functions) do
|
||||
if func.name and func.name:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = func.name,
|
||||
kind = 3, -- Function
|
||||
detail = "[index] " .. vim.fn.fnamemodify(filepath, ":t"),
|
||||
documentation = func.docstring or ("Function at line " .. (func.line or "?")),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
if file_index and file_index.classes then
|
||||
for _, class in ipairs(file_index.classes) do
|
||||
if class.name and class.name:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = class.name,
|
||||
kind = 7, -- Class
|
||||
detail = "[index] " .. vim.fn.fnamemodify(filepath, ":t"),
|
||||
documentation = class.docstring or ("Class at line " .. (class.line or "?")),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
return get_indexer_completions
|
||||
7
lua/codetyper/adapters/nvim/cmp/has_cmp.lua
Normal file
7
lua/codetyper/adapters/nvim/cmp/has_cmp.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
--- Check if cmp is available
|
||||
---@return boolean
|
||||
local function has_cmp()
|
||||
return pcall(require, "cmp")
|
||||
end
|
||||
|
||||
return has_cmp
|
||||
@@ -6,226 +6,13 @@
|
||||
|
||||
local M = {}
|
||||
|
||||
local source = {}
|
||||
local has_cmp = require("codetyper.adapters.nvim.cmp.has_cmp")
|
||||
local get_brain_completions = require("codetyper.adapters.nvim.cmp.get_brain_completions")
|
||||
local get_indexer_completions = require("codetyper.adapters.nvim.cmp.get_indexer_completions")
|
||||
local get_buffer_completions = require("codetyper.adapters.nvim.cmp.get_buffer_completions")
|
||||
local get_copilot_suggestion = require("codetyper.adapters.nvim.cmp.get_copilot_suggestion")
|
||||
|
||||
--- Check if cmp is available
|
||||
---@return boolean
|
||||
local function has_cmp()
|
||||
return pcall(require, "cmp")
|
||||
end
|
||||
|
||||
--- Get completion items from brain context
|
||||
---@param prefix string Current word prefix
|
||||
---@return table[] items
|
||||
local function get_brain_completions(prefix)
|
||||
local items = {}
|
||||
|
||||
local ok_brain, brain = pcall(require, "codetyper.brain")
|
||||
if not ok_brain then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Check if brain is initialized safely
|
||||
local is_init = false
|
||||
if brain.is_initialized then
|
||||
local ok, result = pcall(brain.is_initialized)
|
||||
is_init = ok and result
|
||||
end
|
||||
|
||||
if not is_init then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Query brain for relevant patterns
|
||||
local ok_query, result = pcall(brain.query, {
|
||||
query = prefix,
|
||||
max_results = 10,
|
||||
types = { "pattern" },
|
||||
})
|
||||
|
||||
if ok_query and result and result.nodes then
|
||||
for _, node in ipairs(result.nodes) do
|
||||
if node.c and node.c.s then
|
||||
-- Extract function/class names from summary
|
||||
local summary = node.c.s
|
||||
for name in summary:gmatch("functions:%s*([^;]+)") do
|
||||
for func in name:gmatch("([%w_]+)") do
|
||||
if func:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = func,
|
||||
kind = 3, -- Function
|
||||
detail = "[brain]",
|
||||
documentation = summary,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
for name in summary:gmatch("classes:%s*([^;]+)") do
|
||||
for class in name:gmatch("([%w_]+)") do
|
||||
if class:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = class,
|
||||
kind = 7, -- Class
|
||||
detail = "[brain]",
|
||||
documentation = summary,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
--- Get completion items from indexer symbols
|
||||
---@param prefix string Current word prefix
|
||||
---@return table[] items
|
||||
local function get_indexer_completions(prefix)
|
||||
local items = {}
|
||||
|
||||
local ok_indexer, indexer = pcall(require, "codetyper.indexer")
|
||||
if not ok_indexer then
|
||||
return items
|
||||
end
|
||||
|
||||
local ok_load, index = pcall(indexer.load_index)
|
||||
if not ok_load or not index then
|
||||
return items
|
||||
end
|
||||
|
||||
-- Search symbols
|
||||
if index.symbols then
|
||||
for symbol, files in pairs(index.symbols) do
|
||||
if symbol:lower():find(prefix:lower(), 1, true) then
|
||||
local files_str = type(files) == "table" and table.concat(files, ", ") or tostring(files)
|
||||
table.insert(items, {
|
||||
label = symbol,
|
||||
kind = 6, -- Variable (generic)
|
||||
detail = "[index] " .. files_str:sub(1, 30),
|
||||
documentation = "Symbol found in: " .. files_str,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Search functions in files
|
||||
if index.files then
|
||||
for filepath, file_index in pairs(index.files) do
|
||||
if file_index and file_index.functions then
|
||||
for _, func in ipairs(file_index.functions) do
|
||||
if func.name and func.name:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = func.name,
|
||||
kind = 3, -- Function
|
||||
detail = "[index] " .. vim.fn.fnamemodify(filepath, ":t"),
|
||||
documentation = func.docstring or ("Function at line " .. (func.line or "?")),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
if file_index and file_index.classes then
|
||||
for _, class in ipairs(file_index.classes) do
|
||||
if class.name and class.name:lower():find(prefix:lower(), 1, true) then
|
||||
table.insert(items, {
|
||||
label = class.name,
|
||||
kind = 7, -- Class
|
||||
detail = "[index] " .. vim.fn.fnamemodify(filepath, ":t"),
|
||||
documentation = class.docstring or ("Class at line " .. (class.line or "?")),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
--- Get completion items from current buffer (fallback)
|
||||
---@param prefix string Current word prefix
|
||||
---@param bufnr number Buffer number
|
||||
---@return table[] items
|
||||
local function get_buffer_completions(prefix, bufnr)
|
||||
local items = {}
|
||||
local seen = {}
|
||||
|
||||
-- Get all lines in buffer
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local prefix_lower = prefix:lower()
|
||||
|
||||
for _, line in ipairs(lines) do
|
||||
-- Extract words that could be identifiers
|
||||
for word in line:gmatch("[%a_][%w_]*") do
|
||||
if #word >= 3 and word:lower():find(prefix_lower, 1, true) and not seen[word] and word ~= prefix then
|
||||
seen[word] = true
|
||||
table.insert(items, {
|
||||
label = word,
|
||||
kind = 1, -- Text
|
||||
detail = "[buffer]",
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
--- Try to get Copilot suggestion if plugin is installed
|
||||
---@param prefix string
|
||||
---@return string|nil suggestion
|
||||
local function get_copilot_suggestion(prefix)
|
||||
-- Try copilot.lua suggestion API first
|
||||
local ok, copilot_suggestion = pcall(require, "copilot.suggestion")
|
||||
if ok and copilot_suggestion and type(copilot_suggestion.get_suggestion) == "function" then
|
||||
local ok2, suggestion = pcall(copilot_suggestion.get_suggestion)
|
||||
if ok2 and suggestion and suggestion ~= "" then
|
||||
-- Only return if suggestion seems to start with prefix (best-effort)
|
||||
if prefix == "" or suggestion:lower():match(prefix:lower(), 1) then
|
||||
return suggestion
|
||||
else
|
||||
return suggestion
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: try older copilot module if present
|
||||
local ok3, copilot = pcall(require, "copilot")
|
||||
if ok3 and copilot and type(copilot.get_suggestion) == "function" then
|
||||
local ok4, suggestion = pcall(copilot.get_suggestion)
|
||||
if ok4 and suggestion and suggestion ~= "" then
|
||||
return suggestion
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Create new cmp source instance
|
||||
function source.new()
|
||||
return setmetatable({}, { __index = source })
|
||||
end
|
||||
|
||||
--- Get source name
|
||||
function source:get_keyword_pattern()
|
||||
return [[\k\+]]
|
||||
end
|
||||
|
||||
--- Check if source is available
|
||||
function source:is_available()
|
||||
return true
|
||||
end
|
||||
|
||||
--- Get debug name
|
||||
function source:get_debug_name()
|
||||
return "codetyper"
|
||||
end
|
||||
|
||||
--- Get trigger characters
|
||||
function source:get_trigger_characters()
|
||||
return { ".", ":", "_" }
|
||||
end
|
||||
local source = require("codetyper.utils.cmp_source")
|
||||
|
||||
--- Complete
|
||||
---@param params table
|
||||
@@ -290,9 +77,7 @@ function source:complete(params, callback)
|
||||
suggestion = res
|
||||
end
|
||||
if suggestion and suggestion ~= "" then
|
||||
-- Truncate suggestion to first line for label display
|
||||
local first_line = suggestion:match("([^\n]+)") or suggestion
|
||||
-- Avoid duplicates
|
||||
if not seen[first_line] then
|
||||
seen[first_line] = true
|
||||
table.insert(items, 1, {
|
||||
@@ -335,7 +120,6 @@ function M.is_registered()
|
||||
return false
|
||||
end
|
||||
|
||||
-- Try to get registered sources
|
||||
local config = cmp.get_config()
|
||||
if config and config.sources then
|
||||
for _, src in ipairs(config.sources) do
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
---
|
||||
local M = {}
|
||||
|
||||
local parser = require("codetyper.parser")
|
||||
local is_cursor_in_open_tag = require("codetyper.parser.is_cursor_in_open_tag")
|
||||
local get_file_ref_prefix = require("codetyper.parser.get_file_ref_prefix")
|
||||
local utils = require("codetyper.support.utils")
|
||||
|
||||
--- Get list of files for completion
|
||||
@@ -110,13 +111,13 @@ end
|
||||
--- Show file completion popup
|
||||
function M.show_file_completion()
|
||||
-- Check if we're in an open prompt tag
|
||||
local is_inside = parser.is_cursor_in_open_tag()
|
||||
local is_inside = is_cursor_in_open_tag()
|
||||
if not is_inside then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get the prefix being typed
|
||||
local prefix = parser.get_file_ref_prefix()
|
||||
local prefix = get_file_ref_prefix()
|
||||
if prefix == nil then
|
||||
return false
|
||||
end
|
||||
@@ -160,7 +161,7 @@ function M.setup()
|
||||
-- Schedule completion popup after the @ is inserted
|
||||
vim.schedule(function()
|
||||
-- Check we're in an open tag
|
||||
local is_inside = parser.is_cursor_in_open_tag()
|
||||
local is_inside = is_cursor_in_open_tag()
|
||||
if not is_inside then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---@mod codetyper.parser Parser for /@ @/ prompt tags
|
||||
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.find_prompts = require("codetyper.parser.find_prompts")
|
||||
M.find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
M.get_prompt_at_cursor = require("codetyper.parser.get_prompt_at_cursor")
|
||||
M.get_last_prompt = require("codetyper.parser.get_last_prompt")
|
||||
M.detect_prompt_type = require("codetyper.parser.detect_prompt_type")
|
||||
M.clean_prompt = require("codetyper.parser.clean_prompt")
|
||||
M.has_closing_tag = require("codetyper.parser.has_closing_tag")
|
||||
M.has_unclosed_prompts = require("codetyper.parser.has_unclosed_prompts")
|
||||
M.extract_file_references = require("codetyper.parser.extract_file_references")
|
||||
M.strip_file_references = require("codetyper.parser.strip_file_references")
|
||||
M.is_cursor_in_open_tag = require("codetyper.parser.is_cursor_in_open_tag")
|
||||
M.get_file_ref_prefix = require("codetyper.parser.get_file_ref_prefix")
|
||||
|
||||
logger.info("parser", "Parser module loaded")
|
||||
|
||||
return M
|
||||
@@ -1,34 +0,0 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Extract the prompt type from content
|
||||
---@param content string Prompt content
|
||||
---@return "refactor" | "add" | "document" | "explain" | "generic" Prompt type
|
||||
local function detect_prompt_type(content)
|
||||
logger.func_entry("parser", "detect_prompt_type", { content_preview = content:sub(1, 50) })
|
||||
|
||||
local lower = content:lower()
|
||||
|
||||
if lower:match("refactor") then
|
||||
logger.debug("parser", "detect_prompt_type: detected 'refactor'")
|
||||
logger.func_exit("parser", "detect_prompt_type", "refactor")
|
||||
return "refactor"
|
||||
elseif lower:match("add") or lower:match("create") or lower:match("implement") then
|
||||
logger.debug("parser", "detect_prompt_type: detected 'add'")
|
||||
logger.func_exit("parser", "detect_prompt_type", "add")
|
||||
return "add"
|
||||
elseif lower:match("document") or lower:match("comment") or lower:match("jsdoc") then
|
||||
logger.debug("parser", "detect_prompt_type: detected 'document'")
|
||||
logger.func_exit("parser", "detect_prompt_type", "document")
|
||||
return "document"
|
||||
elseif lower:match("explain") or lower:match("what") or lower:match("how") then
|
||||
logger.debug("parser", "detect_prompt_type: detected 'explain'")
|
||||
logger.func_exit("parser", "detect_prompt_type", "explain")
|
||||
return "explain"
|
||||
end
|
||||
|
||||
logger.debug("parser", "detect_prompt_type: detected 'generic'")
|
||||
logger.func_exit("parser", "detect_prompt_type", "generic")
|
||||
return "generic"
|
||||
end
|
||||
|
||||
return detect_prompt_type
|
||||
@@ -1,56 +0,0 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
local find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
|
||||
--- Get prompt at cursor position
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return CoderPrompt|nil Prompt at cursor or nil
|
||||
local function get_prompt_at_cursor(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local line = cursor[1]
|
||||
local col = cursor[2] + 1 -- Convert to 1-indexed
|
||||
|
||||
logger.func_entry("parser", "get_prompt_at_cursor", {
|
||||
bufnr = bufnr,
|
||||
line = line,
|
||||
col = col,
|
||||
})
|
||||
|
||||
local prompts = find_prompts_in_buffer(bufnr)
|
||||
|
||||
logger.debug("parser", "get_prompt_at_cursor: checking " .. #prompts .. " prompts")
|
||||
|
||||
for i, prompt in ipairs(prompts) do
|
||||
logger.debug(
|
||||
"parser",
|
||||
"get_prompt_at_cursor: checking prompt " .. i .. " (lines " .. prompt.start_line .. "-" .. prompt.end_line .. ")"
|
||||
)
|
||||
if line >= prompt.start_line and line <= prompt.end_line then
|
||||
logger.debug("parser", "get_prompt_at_cursor: cursor line " .. line .. " is within prompt line range")
|
||||
if line == prompt.start_line and col < prompt.start_col then
|
||||
logger.debug(
|
||||
"parser",
|
||||
"get_prompt_at_cursor: cursor col " .. col .. " is before prompt start_col " .. prompt.start_col
|
||||
)
|
||||
goto continue
|
||||
end
|
||||
if line == prompt.end_line and col > prompt.end_col then
|
||||
logger.debug(
|
||||
"parser",
|
||||
"get_prompt_at_cursor: cursor col " .. col .. " is after prompt end_col " .. prompt.end_col
|
||||
)
|
||||
goto continue
|
||||
end
|
||||
logger.debug("parser", "get_prompt_at_cursor: found prompt at cursor")
|
||||
logger.func_exit("parser", "get_prompt_at_cursor", "prompt found")
|
||||
return prompt
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
logger.debug("parser", "get_prompt_at_cursor: no prompt found at cursor")
|
||||
logger.func_exit("parser", "get_prompt_at_cursor", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
return get_prompt_at_cursor
|
||||
@@ -1,34 +0,0 @@
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
local get_config = require("codetyper.utils.get_config").get_config
|
||||
|
||||
--- Check if buffer has any unclosed prompts
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return boolean
|
||||
local function has_unclosed_prompts(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "has_unclosed_prompts", { bufnr = bufnr })
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local content = table.concat(lines, "\n")
|
||||
|
||||
local cfg = get_config()
|
||||
local escaped_open = utils.escape_pattern(cfg.patterns.open_tag)
|
||||
local escaped_close = utils.escape_pattern(cfg.patterns.close_tag)
|
||||
|
||||
local _, open_count = content:gsub(escaped_open, "")
|
||||
local _, close_count = content:gsub(escaped_close, "")
|
||||
|
||||
local has_unclosed = open_count > close_count
|
||||
|
||||
logger.debug(
|
||||
"parser",
|
||||
"has_unclosed_prompts: open=" .. open_count .. ", close=" .. close_count .. ", unclosed=" .. tostring(has_unclosed)
|
||||
)
|
||||
logger.func_exit("parser", "has_unclosed_prompts", has_unclosed)
|
||||
|
||||
return has_unclosed
|
||||
end
|
||||
|
||||
return has_unclosed_prompts
|
||||
28
lua/codetyper/utils/cmp_source.lua
Normal file
28
lua/codetyper/utils/cmp_source.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
local source = {}
|
||||
|
||||
--- Create new cmp source instance
|
||||
function source.new()
|
||||
return setmetatable({}, { __index = source })
|
||||
end
|
||||
|
||||
--- Get source name
|
||||
function source:get_keyword_pattern()
|
||||
return [[\k\+]]
|
||||
end
|
||||
|
||||
--- Check if source is available
|
||||
function source:is_available()
|
||||
return true
|
||||
end
|
||||
|
||||
--- Get debug name
|
||||
function source:get_debug_name()
|
||||
return "codetyper"
|
||||
end
|
||||
|
||||
--- Get trigger characters
|
||||
function source:get_trigger_characters()
|
||||
return { ".", ":", "_" }
|
||||
end
|
||||
|
||||
return source
|
||||
Reference in New Issue
Block a user