Fixing the old configuration

This commit is contained in:
2026-03-18 21:56:45 -04:00
parent f6266c7d94
commit 9f229b26c9
51 changed files with 791 additions and 6549 deletions

View File

@@ -1,7 +1,5 @@
---@mod codetyper.completion Insert mode completion for file references
---
--- Provides completion for @filename inside /@ @/ tags.
local M = {}
local parser = require("codetyper.parser")
@@ -11,182 +9,183 @@ local utils = require("codetyper.support.utils")
---@param prefix string Prefix to filter files
---@return table[] List of completion items
local function get_file_completions(prefix)
local cwd = vim.fn.getcwd()
local current_file = vim.fn.expand("%:p")
local current_dir = vim.fn.fnamemodify(current_file, ":h")
local files = {}
local cwd = vim.fn.getcwd()
local current_file = vim.fn.expand("%:p")
local current_dir = vim.fn.fnamemodify(current_file, ":h")
local files = {}
-- Use vim.fn.glob to find files matching the prefix
local pattern = prefix .. "*"
-- Use vim.fn.glob to find files matching the prefix
local pattern = prefix .. "*"
-- Determine base directory - use current file's directory if outside cwd
local base_dir = cwd
if current_dir ~= "" and not current_dir:find(cwd, 1, true) then
-- File is outside project, use its directory as base
base_dir = current_dir
end
-- Determine base directory - use current file's directory if outside cwd
local base_dir = cwd
if current_dir ~= "" and not current_dir:find(cwd, 1, true) then
-- File is outside project, use its directory as base
base_dir = current_dir
end
-- Search in base directory
local matches = vim.fn.glob(base_dir .. "/" .. pattern, false, true)
-- Search in base directory
local matches = vim.fn.glob(base_dir .. "/" .. pattern, false, true)
-- Search with ** for all subdirectories
local deep_matches = vim.fn.glob(base_dir .. "/**/" .. pattern, false, true)
for _, m in ipairs(deep_matches) do
table.insert(matches, m)
end
-- Search with ** for all subdirectories
local deep_matches = vim.fn.glob(base_dir .. "/**/" .. pattern, false, true)
for _, m in ipairs(deep_matches) do
table.insert(matches, m)
end
-- Also search in cwd if different from base_dir
if base_dir ~= cwd then
local cwd_matches = vim.fn.glob(cwd .. "/" .. pattern, false, true)
for _, m in ipairs(cwd_matches) do
table.insert(matches, m)
end
local cwd_deep = vim.fn.glob(cwd .. "/**/" .. pattern, false, true)
for _, m in ipairs(cwd_deep) do
table.insert(matches, m)
end
end
-- Also search in cwd if different from base_dir
if base_dir ~= cwd then
local cwd_matches = vim.fn.glob(cwd .. "/" .. pattern, false, true)
for _, m in ipairs(cwd_matches) do
table.insert(matches, m)
end
local cwd_deep = vim.fn.glob(cwd .. "/**/" .. pattern, false, true)
for _, m in ipairs(cwd_deep) do
table.insert(matches, m)
end
end
-- Also search specific directories if prefix doesn't have path
if not prefix:find("/") then
local search_dirs = { "src", "lib", "lua", "app", "components", "utils", "tests" }
for _, dir in ipairs(search_dirs) do
local dir_path = base_dir .. "/" .. dir
if vim.fn.isdirectory(dir_path) == 1 then
local dir_matches = vim.fn.glob(dir_path .. "/**/" .. pattern, false, true)
for _, m in ipairs(dir_matches) do
table.insert(matches, m)
end
end
end
end
-- Also search specific directories if prefix doesn't have path
if not prefix:find("/") then
local search_dirs = { "src", "lib", "lua", "app", "components", "utils", "tests" }
for _, dir in ipairs(search_dirs) do
local dir_path = base_dir .. "/" .. dir
if vim.fn.isdirectory(dir_path) == 1 then
local dir_matches = vim.fn.glob(dir_path .. "/**/" .. pattern, false, true)
for _, m in ipairs(dir_matches) do
table.insert(matches, m)
end
end
end
end
-- Convert to relative paths and deduplicate
local seen = {}
for _, match in ipairs(matches) do
-- Convert to relative path based on which base it came from
local rel_path
if match:find(base_dir, 1, true) == 1 then
rel_path = match:sub(#base_dir + 2)
elseif match:find(cwd, 1, true) == 1 then
rel_path = match:sub(#cwd + 2)
else
rel_path = vim.fn.fnamemodify(match, ":t") -- Just filename if can't make relative
end
-- Convert to relative paths and deduplicate
local seen = {}
for _, match in ipairs(matches) do
-- Convert to relative path based on which base it came from
local rel_path
if match:find(base_dir, 1, true) == 1 then
rel_path = match:sub(#base_dir + 2)
elseif match:find(cwd, 1, true) == 1 then
rel_path = match:sub(#cwd + 2)
else
rel_path = vim.fn.fnamemodify(match, ":t") -- Just filename if can't make relative
end
-- Skip directories, coder files, and hidden/generated files
if vim.fn.isdirectory(match) == 0
and not utils.is_coder_file(match)
and not rel_path:match("^%.")
and not rel_path:match("node_modules")
and not rel_path:match("%.git/")
and not rel_path:match("dist/")
and not rel_path:match("build/")
and not seen[rel_path]
then
seen[rel_path] = true
table.insert(files, {
word = rel_path,
abbr = rel_path,
kind = "File",
menu = "[ref]",
})
end
end
-- Skip directories, coder files, and hidden/generated files
if
vim.fn.isdirectory(match) == 0
and not utils.is_coder_file(match)
and not rel_path:match("^%.")
and not rel_path:match("node_modules")
and not rel_path:match("%.git/")
and not rel_path:match("dist/")
and not rel_path:match("build/")
and not seen[rel_path]
then
seen[rel_path] = true
table.insert(files, {
word = rel_path,
abbr = rel_path,
kind = "File",
menu = "[ref]",
})
end
end
-- Sort by length (shorter paths first)
table.sort(files, function(a, b)
return #a.word < #b.word
end)
-- Sort by length (shorter paths first)
table.sort(files, function(a, b)
return #a.word < #b.word
end)
-- Limit results
local result = {}
for i = 1, math.min(#files, 15) do
result[i] = files[i]
end
-- Limit results
local result = {}
for i = 1, math.min(#files, 15) do
result[i] = files[i]
end
return result
return result
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()
if not is_inside then
return false
end
-- Check if we're in an open prompt tag
local is_inside = parser.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()
if prefix == nil then
return false
end
-- Get the prefix being typed
local prefix = parser.get_file_ref_prefix()
if prefix == nil then
return false
end
-- Get completions
local items = get_file_completions(prefix)
-- Get completions
local items = get_file_completions(prefix)
if #items == 0 then
-- Try with empty prefix to show all files
items = get_file_completions("")
end
if #items == 0 then
-- Try with empty prefix to show all files
items = get_file_completions("")
end
if #items > 0 then
-- Calculate start column (position right after @)
local cursor = vim.api.nvim_win_get_cursor(0)
local col = cursor[2] - #prefix + 1 -- 1-indexed for complete()
if #items > 0 then
-- Calculate start column (position right after @)
local cursor = vim.api.nvim_win_get_cursor(0)
local col = cursor[2] - #prefix + 1 -- 1-indexed for complete()
-- Show completion popup
vim.fn.complete(col, items)
return true
end
-- Show completion popup
vim.fn.complete(col, items)
return true
end
return false
return false
end
--- Setup completion for file references (works on ALL files)
function M.setup()
local group = vim.api.nvim_create_augroup("CoderCompletion", { clear = true })
local group = vim.api.nvim_create_augroup("CoderCompletion", { clear = true })
-- Trigger completion on @ in insert mode (works on ALL files)
vim.api.nvim_create_autocmd("InsertCharPre", {
group = group,
pattern = "*",
callback = function()
-- Skip special buffers
if vim.bo.buftype ~= "" then
return
end
-- Trigger completion on @ in insert mode (works on ALL files)
vim.api.nvim_create_autocmd("InsertCharPre", {
group = group,
pattern = "*",
callback = function()
-- Skip special buffers
if vim.bo.buftype ~= "" then
return
end
if vim.v.char == "@" then
-- 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()
if not is_inside then
return
end
if vim.v.char == "@" then
-- 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()
if not is_inside then
return
end
-- Check we're not typing @/ (closing tag)
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
local next_char = line:sub(cursor[2] + 2, cursor[2] + 2)
-- Check we're not typing @/ (closing tag)
local cursor = vim.api.nvim_win_get_cursor(0)
local line = vim.api.nvim_get_current_line()
local next_char = line:sub(cursor[2] + 2, cursor[2] + 2)
if next_char == "/" then
return
end
if next_char == "/" then
return
end
-- Show file completion
M.show_file_completion()
end)
end
end,
desc = "Trigger file completion on @ inside prompt tags",
})
-- Show file completion
M.show_file_completion()
end)
end
end,
desc = "Trigger file completion on @ inside prompt tags",
})
-- Also allow manual trigger with <C-x><C-f> style keybinding in insert mode
vim.keymap.set("i", "<C-x>@", function()
M.show_file_completion()
end, { silent = true, desc = "Coder: Complete file reference" })
-- Also allow manual trigger with <C-x><C-f> style keybinding in insert mode
vim.keymap.set("i", "<C-x>@", function()
M.show_file_completion()
end, { silent = true, desc = "Coder: Complete file reference" })
end
return M

View File

@@ -1,7 +1,7 @@
---@mod codetyper.indexer Project indexer for Codetyper.nvim
---@brief [[
--- Indexes project structure, dependencies, and code symbols.
--- Stores knowledge in .coder/ directory for enriching LLM context.
--- Stores knowledge in .codetyper/ directory for enriching LLM context.
---@brief ]]
local M = {}
@@ -24,7 +24,7 @@ local default_config = {
auto_index = true,
index_on_open = false,
max_file_size = 100000,
excluded_dirs = { "node_modules", "dist", "build", ".git", ".coder", "__pycache__", "vendor", "target" },
excluded_dirs = { "node_modules", "dist", "build", ".git", ".codetyper", "__pycache__", "vendor", "target" },
index_extensions = { "lua", "ts", "tsx", "js", "jsx", "py", "go", "rs", "rb", "java", "c", "cpp", "h", "hpp" },
memory = {
enabled = true,
@@ -94,7 +94,7 @@ local function get_index_path()
if not root then
return nil
end
return root .. "/.coder/" .. INDEX_FILE
return root .. "/.codetyper/" .. INDEX_FILE
end
--- Create empty index structure
@@ -168,8 +168,8 @@ function M.save_index(index)
return false
end
-- Ensure .coder directory exists
local coder_dir = root .. "/.coder"
-- Ensure .codetyper directory exists
local coder_dir = root .. "/.codetyper"
utils.ensure_dir(coder_dir)
local path = get_index_path()

View File

@@ -1,6 +1,6 @@
---@mod codetyper.indexer.memory Memory persistence manager
---@brief [[
--- Stores and retrieves learned patterns and memories in .coder/memories/.
--- Stores and retrieves learned patterns and memories in .codetyper/memories/.
--- Supports session history for learning from interactions.
---@brief ]]
@@ -42,7 +42,7 @@ local function get_memories_dir()
if not root then
return nil
end
return root .. "/.coder/" .. MEMORIES_DIR
return root .. "/.codetyper/" .. MEMORIES_DIR
end
--- Get the sessions directory
@@ -52,7 +52,7 @@ local function get_sessions_dir()
if not root then
return nil
end
return root .. "/.coder/" .. SESSIONS_DIR
return root .. "/.codetyper/" .. SESSIONS_DIR
end
--- Ensure memories directory exists

View File

@@ -44,7 +44,7 @@ local DEFAULT_IGNORES = {
"^node_modules$",
"^__pycache__$",
"^%.git$",
"^%.coder$",
"^%.codetyper$",
"^dist$",
"^build$",
"^target$",