Refactor: moving injects and start the parser
- moving all the inject functions inside its proper folder - starting the parser refactoring
This commit is contained in:
@@ -7,14 +7,10 @@
|
||||
|
||||
local M = {}
|
||||
|
||||
local inject = require("codetyper.inject.inject")
|
||||
local params = require("codetyper.params.agents.patch")
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Lazy load inject module to avoid circular requires
|
||||
local function get_inject_module()
|
||||
return require("codetyper.inject")
|
||||
end
|
||||
|
||||
--- Lazy load search_replace module
|
||||
local function get_search_replace_module()
|
||||
return require("codetyper.core.diff.search_replace")
|
||||
@@ -630,7 +626,6 @@ function M.apply(patch)
|
||||
end
|
||||
|
||||
-- Use smart injection module for intelligent import handling
|
||||
local inject = get_inject_module()
|
||||
local inject_result = nil
|
||||
|
||||
local has_range = patch.injection_range ~= nil
|
||||
@@ -788,7 +783,7 @@ function M.apply(patch)
|
||||
end
|
||||
|
||||
-- Use smart injection - handles imports automatically
|
||||
inject_result = inject.inject(target_bufnr, code_to_inject, inject_opts)
|
||||
inject_result = inject(target_bufnr, code_to_inject, inject_opts)
|
||||
|
||||
-- Log injection details
|
||||
pcall(function()
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
---@mod codetyper.inject Code injection for Codetyper.nvim
|
||||
|
||||
local M = {}
|
||||
|
||||
local utils = require("codetyper.support.utils")
|
||||
|
||||
--- Inject generated code into target file
|
||||
---@param target_path string Path to target file
|
||||
---@param code string Generated code
|
||||
---@param prompt_type string Type of prompt (refactor, add, document, etc.)
|
||||
function M.inject_code(target_path, code, prompt_type)
|
||||
-- Normalize the target path
|
||||
target_path = vim.fn.fnamemodify(target_path, ":p")
|
||||
|
||||
-- Try to find buffer by path
|
||||
local target_buf = nil
|
||||
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
|
||||
local buf_name = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ":p")
|
||||
if buf_name == target_path then
|
||||
target_buf = buf
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- If still not found, open the file
|
||||
if not target_buf or not vim.api.nvim_buf_is_valid(target_buf) then
|
||||
-- Check if file exists
|
||||
if utils.file_exists(target_path) then
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(target_path))
|
||||
target_buf = vim.api.nvim_get_current_buf()
|
||||
utils.notify("Opened target file: " .. vim.fn.fnamemodify(target_path, ":t"))
|
||||
else
|
||||
utils.notify("Target file not found: " .. target_path, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if not target_buf then
|
||||
utils.notify("Target buffer not found", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
utils.notify("Injecting code into: " .. vim.fn.fnamemodify(target_path, ":t"))
|
||||
|
||||
-- Different injection strategies based on prompt type
|
||||
if prompt_type == "refactor" then
|
||||
M.inject_refactor(target_buf, code)
|
||||
elseif prompt_type == "add" then
|
||||
M.inject_add(target_buf, code)
|
||||
elseif prompt_type == "document" then
|
||||
M.inject_document(target_buf, code)
|
||||
else
|
||||
-- For generic, auto-add instead of prompting
|
||||
M.inject_add(target_buf, code)
|
||||
end
|
||||
|
||||
-- Mark buffer as modified and save
|
||||
vim.bo[target_buf].modified = true
|
||||
|
||||
-- Auto-save the target file
|
||||
vim.schedule(function()
|
||||
if vim.api.nvim_buf_is_valid(target_buf) then
|
||||
local wins = vim.fn.win_findbuf(target_buf)
|
||||
if #wins > 0 then
|
||||
vim.api.nvim_win_call(wins[1], function()
|
||||
vim.cmd("silent! write")
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Inject code with strategy and range (used by patch system)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
---@param opts table|nil { strategy = "replace"|"insert"|"append", range = { start_line, end_line } (1-based) }
|
||||
---@return table { imports_added: number, body_lines: number, imports_merged: boolean }
|
||||
function M.inject(bufnr, code, opts)
|
||||
opts = opts or {}
|
||||
local strategy = opts.strategy or "replace"
|
||||
local range = opts.range
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
local body_lines = #lines
|
||||
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
return { imports_added = 0, body_lines = 0, imports_merged = false }
|
||||
end
|
||||
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
|
||||
if strategy == "replace" and range and range.start_line and range.end_line then
|
||||
local start_0 = math.max(0, range.start_line - 1)
|
||||
local end_0 = math.min(line_count, range.end_line)
|
||||
if end_0 < start_0 then
|
||||
end_0 = start_0
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(bufnr, start_0, end_0, false, lines)
|
||||
elseif strategy == "insert" and range and range.start_line then
|
||||
local at_0 = math.max(0, math.min(range.start_line - 1, line_count))
|
||||
vim.api.nvim_buf_set_lines(bufnr, at_0, at_0, false, lines)
|
||||
else
|
||||
-- append
|
||||
vim.api.nvim_buf_set_lines(bufnr, line_count, line_count, false, lines)
|
||||
end
|
||||
|
||||
return { imports_added = 0, body_lines = body_lines, imports_merged = false }
|
||||
end
|
||||
|
||||
--- Inject code for refactor (replace entire file)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_refactor(bufnr, code)
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Save cursor position
|
||||
local cursor = nil
|
||||
local wins = vim.fn.win_findbuf(bufnr)
|
||||
if #wins > 0 then
|
||||
cursor = vim.api.nvim_win_get_cursor(wins[1])
|
||||
end
|
||||
|
||||
-- Replace buffer content
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
-- Restore cursor position if possible
|
||||
if cursor then
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
cursor[1] = math.min(cursor[1], line_count)
|
||||
pcall(vim.api.nvim_win_set_cursor, wins[1], cursor)
|
||||
end
|
||||
|
||||
utils.notify("Code refactored", vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
--- Inject code for add (append at cursor or end)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_add(bufnr, code)
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Try to find a window displaying this buffer to get cursor position
|
||||
local insert_line
|
||||
local wins = vim.fn.win_findbuf(bufnr)
|
||||
if #wins > 0 then
|
||||
local cursor = vim.api.nvim_win_get_cursor(wins[1])
|
||||
insert_line = cursor[1]
|
||||
else
|
||||
insert_line = vim.api.nvim_buf_line_count(bufnr)
|
||||
end
|
||||
|
||||
-- Insert lines at position
|
||||
vim.api.nvim_buf_set_lines(bufnr, insert_line, insert_line, false, lines)
|
||||
|
||||
utils.notify("Code added at line " .. (insert_line + 1), vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
--- Inject documentation
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated documentation
|
||||
function M.inject_document(bufnr, code)
|
||||
-- Documentation typically goes above the current function/class
|
||||
-- For simplicity, insert at cursor position
|
||||
M.inject_add(bufnr, code)
|
||||
utils.notify("Documentation added", vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
--- Generic injection (prompt user for action)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_generic(bufnr, code)
|
||||
local actions = {
|
||||
"Replace entire file",
|
||||
"Insert at cursor",
|
||||
"Append to end",
|
||||
"Copy to clipboard",
|
||||
"Cancel",
|
||||
}
|
||||
|
||||
vim.ui.select(actions, {
|
||||
prompt = "How to inject the generated code?",
|
||||
}, function(choice)
|
||||
if not choice then
|
||||
return
|
||||
end
|
||||
|
||||
if choice == "Replace entire file" then
|
||||
M.inject_refactor(bufnr, code)
|
||||
elseif choice == "Insert at cursor" then
|
||||
M.inject_add(bufnr, code)
|
||||
elseif choice == "Append to end" then
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
vim.api.nvim_buf_set_lines(bufnr, line_count, line_count, false, lines)
|
||||
utils.notify("Code appended to end", vim.log.levels.INFO)
|
||||
elseif choice == "Copy to clipboard" then
|
||||
vim.fn.setreg("+", code)
|
||||
utils.notify("Code copied to clipboard", vim.log.levels.INFO)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- Preview code in a floating window before injection
|
||||
---@param code string Generated code
|
||||
---@param callback fun(action: string) Callback with selected action
|
||||
function M.preview(code, callback)
|
||||
local codetyper = require("codetyper")
|
||||
local config = codetyper.get_config()
|
||||
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Create buffer for preview
|
||||
local buf = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
||||
|
||||
-- Calculate window size
|
||||
local width = math.min(80, vim.o.columns - 10)
|
||||
local height = math.min(#lines + 2, vim.o.lines - 10)
|
||||
|
||||
-- Create floating window
|
||||
local win = vim.api.nvim_open_win(buf, true, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((vim.o.lines - height) / 2),
|
||||
col = math.floor((vim.o.columns - width) / 2),
|
||||
style = "minimal",
|
||||
border = config.window.border,
|
||||
title = " Generated Code Preview ",
|
||||
title_pos = "center",
|
||||
})
|
||||
|
||||
-- Set buffer options
|
||||
vim.bo[buf].modifiable = false
|
||||
vim.bo[buf].bufhidden = "wipe"
|
||||
|
||||
-- Add keymaps for actions
|
||||
local opts = { buffer = buf, noremap = true, silent = true }
|
||||
|
||||
vim.keymap.set("n", "q", function()
|
||||
vim.api.nvim_win_close(win, true)
|
||||
callback("cancel")
|
||||
end, opts)
|
||||
|
||||
vim.keymap.set("n", "<CR>", function()
|
||||
vim.api.nvim_win_close(win, true)
|
||||
callback("inject")
|
||||
end, opts)
|
||||
|
||||
vim.keymap.set("n", "y", function()
|
||||
vim.fn.setreg("+", code)
|
||||
utils.notify("Copied to clipboard")
|
||||
end, opts)
|
||||
|
||||
-- Show help in command line
|
||||
vim.api.nvim_echo({
|
||||
{ "Press ", "Normal" },
|
||||
{ "<CR>", "Keyword" },
|
||||
{ " to inject, ", "Normal" },
|
||||
{ "y", "Keyword" },
|
||||
{ " to copy, ", "Normal" },
|
||||
{ "q", "Keyword" },
|
||||
{ " to cancel", "Normal" },
|
||||
}, false, {})
|
||||
end
|
||||
|
||||
return M
|
||||
38
lua/codetyper/inject/inject.lua
Normal file
38
lua/codetyper/inject/inject.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
local M = {}
|
||||
--- Inject code with strategy and range (used by patch system)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
---@param opts table|nil { strategy = "replace"|"insert"|"append", range = { start_line, end_line } (1-based) }
|
||||
---@return table { imports_added: number, body_lines: number, imports_merged: boolean }
|
||||
function M.inject(bufnr, code, opts)
|
||||
opts = opts or {}
|
||||
local strategy = opts.strategy or "replace"
|
||||
local range = opts.range
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
local body_lines = #lines
|
||||
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
return { imports_added = 0, body_lines = 0, imports_merged = false }
|
||||
end
|
||||
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
|
||||
if strategy == "replace" and range and range.start_line and range.end_line then
|
||||
local start_0 = math.max(0, range.start_line - 1)
|
||||
local end_0 = math.min(line_count, range.end_line)
|
||||
if end_0 < start_0 then
|
||||
end_0 = start_0
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(bufnr, start_0, end_0, false, lines)
|
||||
elseif strategy == "insert" and range and range.start_line then
|
||||
local at_0 = math.max(0, math.min(range.start_line - 1, line_count))
|
||||
vim.api.nvim_buf_set_lines(bufnr, at_0, at_0, false, lines)
|
||||
else
|
||||
-- append
|
||||
vim.api.nvim_buf_set_lines(bufnr, line_count, line_count, false, lines)
|
||||
end
|
||||
|
||||
return { imports_added = 0, body_lines = body_lines, imports_merged = false }
|
||||
end
|
||||
|
||||
return M
|
||||
75
lua/codetyper/inject/injectCode.lua
Normal file
75
lua/codetyper/inject/injectCode.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
local M = {}
|
||||
|
||||
local utils = require("codetyper.support.utils")
|
||||
|
||||
local inject_refactor = require("codetyper.inject.inject_refactor")
|
||||
local inject_add = require("codetyper.inject.inject_add")
|
||||
local inject_document = require("codetyper.inject.inject_document")
|
||||
|
||||
--- Inject generated code into target file
|
||||
---@param target_path string Path to target file
|
||||
---@param code string Generated code
|
||||
---@param prompt_type string Type of prompt (refactor, add, document, etc.)
|
||||
function M.inject_code(target_path, code, prompt_type)
|
||||
-- Normalize the target path
|
||||
target_path = vim.fn.fnamemodify(target_path, ":p")
|
||||
|
||||
-- Try to find buffer by path
|
||||
local target_buf = nil
|
||||
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
|
||||
local buf_name = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ":p")
|
||||
if buf_name == target_path then
|
||||
target_buf = buf
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- If still not found, open the file
|
||||
if not target_buf or not vim.api.nvim_buf_is_valid(target_buf) then
|
||||
-- Check if file exists
|
||||
if utils.file_exists(target_path) then
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(target_path))
|
||||
target_buf = vim.api.nvim_get_current_buf()
|
||||
utils.notify("Opened target file: " .. vim.fn.fnamemodify(target_path, ":t"))
|
||||
else
|
||||
utils.notify("Target file not found: " .. target_path, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if not target_buf then
|
||||
utils.notify("Target buffer not found", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
utils.notify("Injecting code into: " .. vim.fn.fnamemodify(target_path, ":t"))
|
||||
|
||||
-- Different injection strategies based on prompt type
|
||||
if prompt_type == "refactor" then
|
||||
inject_refactor(target_buf, code)
|
||||
elseif prompt_type == "add" then
|
||||
inject_add(target_buf, code)
|
||||
elseif prompt_type == "document" then
|
||||
inject_document(target_buf, code)
|
||||
else
|
||||
-- For generic, auto-add instead of prompting
|
||||
inject_add(target_buf, code)
|
||||
end
|
||||
|
||||
-- Mark buffer as modified and save
|
||||
vim.bo[target_buf].modified = true
|
||||
|
||||
-- Auto-save the target file
|
||||
vim.schedule(function()
|
||||
if vim.api.nvim_buf_is_valid(target_buf) then
|
||||
local wins = vim.fn.win_findbuf(target_buf)
|
||||
if #wins > 0 then
|
||||
vim.api.nvim_win_call(wins[1], function()
|
||||
vim.cmd("silent! write")
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
25
lua/codetyper/inject/inject_add.lua
Normal file
25
lua/codetyper/inject/inject_add.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
local M = {}
|
||||
|
||||
--- Inject code for add (append at cursor or end)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_add(bufnr, code)
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Try to find a window displaying this buffer to get cursor position
|
||||
local insert_line
|
||||
local wins = vim.fn.win_findbuf(bufnr)
|
||||
if #wins > 0 then
|
||||
local cursor = vim.api.nvim_win_get_cursor(wins[1])
|
||||
insert_line = cursor[1]
|
||||
else
|
||||
insert_line = vim.api.nvim_buf_line_count(bufnr)
|
||||
end
|
||||
|
||||
-- Insert lines at position
|
||||
vim.api.nvim_buf_set_lines(bufnr, insert_line, insert_line, false, lines)
|
||||
|
||||
utils.notify("Code added at line " .. (insert_line + 1), vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
return M
|
||||
14
lua/codetyper/inject/inject_document.lua
Normal file
14
lua/codetyper/inject/inject_document.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
local M = {}
|
||||
local inject_add = require("codetyper.inject.inject_add")
|
||||
|
||||
--- Inject documentation
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated documentation
|
||||
function M.inject_document(bufnr, code)
|
||||
-- Documentation typically goes above the current function/class
|
||||
-- For simplicity, insert at cursor position
|
||||
inject_add(bufnr, code)
|
||||
utils.notify("Documentation added", vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
return M
|
||||
40
lua/codetyper/inject/inject_generic.lua
Normal file
40
lua/codetyper/inject/inject_generic.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
local M = {}
|
||||
local inject_refactor = require("codetyper.inject.inject_refactor")
|
||||
local inject_add = require("codetyper.inject.inject_add")
|
||||
|
||||
--- Generic injection (prompt user for action)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_generic(bufnr, code)
|
||||
local actions = {
|
||||
"Replace entire file",
|
||||
"Insert at cursor",
|
||||
"Append to end",
|
||||
"Copy to clipboard",
|
||||
"Cancel",
|
||||
}
|
||||
|
||||
vim.ui.select(actions, {
|
||||
prompt = "How to inject the generated code?",
|
||||
}, function(choice)
|
||||
if not choice then
|
||||
return
|
||||
end
|
||||
|
||||
if choice == "Replace entire file" then
|
||||
inject_refactor(bufnr, code)
|
||||
elseif choice == "Insert at cursor" then
|
||||
inject_add(bufnr, code)
|
||||
elseif choice == "Append to end" then
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
vim.api.nvim_buf_set_lines(bufnr, line_count, line_count, false, lines)
|
||||
utils.notify("Code appended to end", vim.log.levels.INFO)
|
||||
elseif choice == "Copy to clipboard" then
|
||||
vim.fn.setreg("+", code)
|
||||
utils.notify("Code copied to clipboard", vim.log.levels.INFO)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
29
lua/codetyper/inject/inject_refactor.lua
Normal file
29
lua/codetyper/inject/inject_refactor.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
local M = {}
|
||||
|
||||
--- Inject code for refactor (replace entire file)
|
||||
---@param bufnr number Buffer number
|
||||
---@param code string Generated code
|
||||
function M.inject_refactor(bufnr, code)
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Save cursor position
|
||||
local cursor = nil
|
||||
local wins = vim.fn.win_findbuf(bufnr)
|
||||
if #wins > 0 then
|
||||
cursor = vim.api.nvim_win_get_cursor(wins[1])
|
||||
end
|
||||
|
||||
-- Replace buffer content
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
-- Restore cursor position if possible
|
||||
if cursor then
|
||||
local line_count = vim.api.nvim_buf_line_count(bufnr)
|
||||
cursor[1] = math.min(cursor[1], line_count)
|
||||
pcall(vim.api.nvim_win_set_cursor, wins[1], cursor)
|
||||
end
|
||||
|
||||
utils.notify("Code refactored", vim.log.levels.INFO)
|
||||
end
|
||||
|
||||
return M
|
||||
68
lua/codetyper/inject/preview.lua
Normal file
68
lua/codetyper/inject/preview.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
local M = {}
|
||||
local utils = require("codetyper.support.utils")
|
||||
|
||||
--- Preview code in a floating window before injection
|
||||
---@param code string Generated code
|
||||
---@param callback fun(action: string) Callback with selected action
|
||||
function M.preview(code, callback)
|
||||
local codetyper = require("codetyper")
|
||||
local config = codetyper.get_config()
|
||||
|
||||
local lines = vim.split(code, "\n", { plain = true })
|
||||
|
||||
-- Create buffer for preview
|
||||
local buf = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
||||
|
||||
-- Calculate window size
|
||||
local width = math.min(80, vim.o.columns - 10)
|
||||
local height = math.min(#lines + 2, vim.o.lines - 10)
|
||||
|
||||
-- Create floating window
|
||||
local win = vim.api.nvim_open_win(buf, true, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = height,
|
||||
row = math.floor((vim.o.lines - height) / 2),
|
||||
col = math.floor((vim.o.columns - width) / 2),
|
||||
style = "minimal",
|
||||
border = config.window.border,
|
||||
title = " Generated Code Preview ",
|
||||
title_pos = "center",
|
||||
})
|
||||
|
||||
-- Set buffer options
|
||||
vim.bo[buf].modifiable = false
|
||||
vim.bo[buf].bufhidden = "wipe"
|
||||
|
||||
-- Add keymaps for actions
|
||||
local opts = { buffer = buf, noremap = true, silent = true }
|
||||
|
||||
vim.keymap.set("n", "q", function()
|
||||
vim.api.nvim_win_close(win, true)
|
||||
callback("cancel")
|
||||
end, opts)
|
||||
|
||||
vim.keymap.set("n", "<CR>", function()
|
||||
vim.api.nvim_win_close(win, true)
|
||||
callback("inject")
|
||||
end, opts)
|
||||
|
||||
vim.keymap.set("n", "y", function()
|
||||
vim.fn.setreg("+", code)
|
||||
utils.notify("Copied to clipboard")
|
||||
end, opts)
|
||||
|
||||
-- Show help in command line
|
||||
vim.api.nvim_echo({
|
||||
{ "Press ", "Normal" },
|
||||
{ "<CR>", "Keyword" },
|
||||
{ " to inject, ", "Normal" },
|
||||
{ "y", "Keyword" },
|
||||
{ " to copy, ", "Normal" },
|
||||
{ "q", "Keyword" },
|
||||
{ " to cancel", "Normal" },
|
||||
}, false, {})
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -4,98 +4,8 @@ local M = {}
|
||||
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
-- Get current codetyper configuration at call time
|
||||
local function get_config()
|
||||
local ok, codetyper = pcall(require, "codetyper")
|
||||
if ok and codetyper.get_config then
|
||||
return codetyper.get_config() or {}
|
||||
end
|
||||
-- Fall back to defaults if codetyper isn't available
|
||||
local defaults = require("codetyper.config.defaults")
|
||||
return defaults.get_defaults()
|
||||
end
|
||||
|
||||
--- Find all prompts in buffer content
|
||||
---@param content string Buffer content
|
||||
---@param open_tag string Opening tag
|
||||
---@param close_tag string Closing tag
|
||||
---@return CoderPrompt[] List of found prompts
|
||||
function M.find_prompts(content, open_tag, close_tag)
|
||||
logger.func_entry("parser", "find_prompts", {
|
||||
content_length = #content,
|
||||
open_tag = open_tag,
|
||||
close_tag = close_tag,
|
||||
})
|
||||
|
||||
local prompts = {}
|
||||
local escaped_open = utils.escape_pattern(open_tag)
|
||||
local escaped_close = utils.escape_pattern(close_tag)
|
||||
|
||||
local lines = vim.split(content, "\n", { plain = true })
|
||||
local in_prompt = false
|
||||
local current_prompt = nil
|
||||
local prompt_content = {}
|
||||
|
||||
logger.debug("parser", "find_prompts: parsing " .. #lines .. " lines")
|
||||
|
||||
for line_num, line in ipairs(lines) do
|
||||
if not in_prompt then
|
||||
-- Look for opening tag
|
||||
local start_col = line:find(escaped_open)
|
||||
if start_col then
|
||||
logger.debug("parser", "find_prompts: found opening tag at line " .. line_num .. ", col " .. start_col)
|
||||
in_prompt = true
|
||||
current_prompt = {
|
||||
start_line = line_num,
|
||||
start_col = start_col,
|
||||
content = "",
|
||||
}
|
||||
-- Get content after opening tag on same line
|
||||
local after_tag = line:sub(start_col + #open_tag)
|
||||
local end_col = after_tag:find(escaped_close)
|
||||
if end_col then
|
||||
-- Single line prompt
|
||||
current_prompt.content = after_tag:sub(1, end_col - 1)
|
||||
current_prompt.end_line = line_num
|
||||
current_prompt.end_col = start_col + #open_tag + end_col + #close_tag - 2
|
||||
table.insert(prompts, current_prompt)
|
||||
logger.debug("parser", "find_prompts: single-line prompt completed at line " .. line_num)
|
||||
in_prompt = false
|
||||
current_prompt = nil
|
||||
else
|
||||
table.insert(prompt_content, after_tag)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Look for closing tag
|
||||
local end_col = line:find(escaped_close)
|
||||
if end_col then
|
||||
-- Found closing tag
|
||||
local before_tag = line:sub(1, end_col - 1)
|
||||
table.insert(prompt_content, before_tag)
|
||||
current_prompt.content = table.concat(prompt_content, "\n")
|
||||
current_prompt.end_line = line_num
|
||||
current_prompt.end_col = end_col + #close_tag - 1
|
||||
table.insert(prompts, current_prompt)
|
||||
logger.debug(
|
||||
"parser",
|
||||
"find_prompts: multi-line prompt completed at line " .. line_num .. ", total lines: " .. #prompt_content
|
||||
)
|
||||
in_prompt = false
|
||||
current_prompt = nil
|
||||
prompt_content = {}
|
||||
else
|
||||
table.insert(prompt_content, line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("parser", "find_prompts: found " .. #prompts .. " prompts total")
|
||||
logger.func_exit("parser", "find_prompts", "found " .. #prompts .. " prompts")
|
||||
|
||||
return prompts
|
||||
end
|
||||
local get_config = require("codetyper.utils.get_config").get_config
|
||||
local find_prompts = require("codetyper.parser.find_prompts")
|
||||
|
||||
--- Find prompts in a buffer
|
||||
---@param bufnr number Buffer number
|
||||
@@ -112,7 +22,7 @@ function M.find_prompts_in_buffer(bufnr)
|
||||
)
|
||||
|
||||
local cfg = get_config()
|
||||
local result = M.find_prompts(content, cfg.patterns.open_tag, cfg.patterns.close_tag)
|
||||
local result = find_prompts(content, cfg.patterns.open_tag, cfg.patterns.close_tag)
|
||||
|
||||
logger.func_exit("parser", "find_prompts_in_buffer", "found " .. #result .. " prompts")
|
||||
return result
|
||||
|
||||
85
lua/codetyper/parser/find_prompts.lua
Normal file
85
lua/codetyper/parser/find_prompts.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Find all prompts in buffer content
|
||||
---@param content string Buffer content
|
||||
---@param open_tag string Opening tag
|
||||
---@param close_tag string Closing tag
|
||||
---@return CoderPrompt[] List of found prompts
|
||||
function find_prompts(content, open_tag, close_tag)
|
||||
logger.func_entry("parser", "find_prompts", {
|
||||
content_length = #content,
|
||||
open_tag = open_tag,
|
||||
close_tag = close_tag,
|
||||
})
|
||||
|
||||
local prompts = {}
|
||||
local escaped_open = utils.escape_pattern(open_tag)
|
||||
local escaped_close = utils.escape_pattern(close_tag)
|
||||
|
||||
local lines = vim.split(content, "\n", { plain = true })
|
||||
local in_prompt = false
|
||||
local current_prompt = nil
|
||||
local prompt_content = {}
|
||||
|
||||
logger.debug("parser", "find_prompts: parsing " .. #lines .. " lines")
|
||||
|
||||
for line_num, line in ipairs(lines) do
|
||||
if not in_prompt then
|
||||
-- Look for opening tag
|
||||
local start_col = line:find(escaped_open)
|
||||
if start_col then
|
||||
logger.debug("parser", "find_prompts: found opening tag at line " .. line_num .. ", col " .. start_col)
|
||||
in_prompt = true
|
||||
current_prompt = {
|
||||
start_line = line_num,
|
||||
start_col = start_col,
|
||||
content = "",
|
||||
}
|
||||
-- Get content after opening tag on same line
|
||||
local after_tag = line:sub(start_col + #open_tag)
|
||||
local end_col = after_tag:find(escaped_close)
|
||||
if end_col then
|
||||
-- Single line prompt
|
||||
current_prompt.content = after_tag:sub(1, end_col - 1)
|
||||
current_prompt.end_line = line_num
|
||||
current_prompt.end_col = start_col + #open_tag + end_col + #close_tag - 2
|
||||
table.insert(prompts, current_prompt)
|
||||
logger.debug("parser", "find_prompts: single-line prompt completed at line " .. line_num)
|
||||
in_prompt = false
|
||||
current_prompt = nil
|
||||
else
|
||||
table.insert(prompt_content, after_tag)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Look for closing tag
|
||||
local end_col = line:find(escaped_close)
|
||||
if end_col then
|
||||
-- Found closing tag
|
||||
local before_tag = line:sub(1, end_col - 1)
|
||||
table.insert(prompt_content, before_tag)
|
||||
current_prompt.content = table.concat(prompt_content, "\n")
|
||||
current_prompt.end_line = line_num
|
||||
current_prompt.end_col = end_col + #close_tag - 1
|
||||
table.insert(prompts, current_prompt)
|
||||
logger.debug(
|
||||
"parser",
|
||||
"find_prompts: multi-line prompt completed at line " .. line_num .. ", total lines: " .. #prompt_content
|
||||
)
|
||||
in_prompt = false
|
||||
current_prompt = nil
|
||||
prompt_content = {}
|
||||
else
|
||||
table.insert(prompt_content, line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("parser", "find_prompts: found " .. #prompts .. " prompts total")
|
||||
logger.func_exit("parser", "find_prompts", "found " .. #prompts .. " prompts")
|
||||
|
||||
return prompts
|
||||
end
|
||||
|
||||
return find_prompts
|
||||
14
lua/codetyper/utils/get_config.lua
Normal file
14
lua/codetyper/utils/get_config.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
local M = {}
|
||||
|
||||
-- Get current codetyper configuration at call time
|
||||
function M.get_config()
|
||||
local ok, codetyper = pcall(require, "codetyper")
|
||||
if ok and codetyper.get_config then
|
||||
return codetyper.get_config() or {}
|
||||
end
|
||||
-- Fall back to defaults if codetyper isn't available
|
||||
local defaults = require("codetyper.config.defaults")
|
||||
return defaults.get_defaults()
|
||||
end
|
||||
|
||||
return M
|
||||
1
lua/codetyper/window/init.lua
Normal file
1
lua/codetyper/window/init.lua
Normal file
@@ -0,0 +1 @@
|
||||
// TODO: Migrate the prompt window here to centralized the logic
|
||||
Reference in New Issue
Block a user