Making changes on the parser file to pure functions
This commit is contained in:
@@ -1,327 +1,21 @@
|
||||
---@mod codetyper.parser Parser for /@ @/ prompt tags
|
||||
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
local M = {}
|
||||
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
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
|
||||
---@return CoderPrompt[] List of found prompts
|
||||
function M.find_prompts_in_buffer(bufnr)
|
||||
logger.func_entry("parser", "find_prompts_in_buffer", { bufnr = bufnr })
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local content = table.concat(lines, "\n")
|
||||
|
||||
logger.debug(
|
||||
"parser",
|
||||
"find_prompts_in_buffer: bufnr=" .. bufnr .. ", lines=" .. #lines .. ", content_length=" .. #content
|
||||
)
|
||||
|
||||
local cfg = get_config()
|
||||
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
|
||||
end
|
||||
|
||||
--- Get prompt at cursor position
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return CoderPrompt|nil Prompt at cursor or nil
|
||||
function M.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 = M.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
|
||||
|
||||
--- Get the last closed prompt in buffer
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return CoderPrompt|nil Last prompt or nil
|
||||
function M.get_last_prompt(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "get_last_prompt", { bufnr = bufnr })
|
||||
|
||||
local prompts = M.find_prompts_in_buffer(bufnr)
|
||||
|
||||
if #prompts > 0 then
|
||||
local last = prompts[#prompts]
|
||||
logger.debug("parser", "get_last_prompt: returning prompt at line " .. last.start_line)
|
||||
logger.func_exit("parser", "get_last_prompt", "prompt at line " .. last.start_line)
|
||||
return last
|
||||
end
|
||||
|
||||
logger.debug("parser", "get_last_prompt: no prompts found")
|
||||
logger.func_exit("parser", "get_last_prompt", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Extract the prompt type from content
|
||||
---@param content string Prompt content
|
||||
---@return "refactor" | "add" | "document" | "explain" | "generic" Prompt type
|
||||
function M.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
|
||||
|
||||
--- Clean prompt content (trim whitespace, normalize newlines)
|
||||
---@param content string Raw prompt content
|
||||
---@return string Cleaned content
|
||||
function M.clean_prompt(content)
|
||||
logger.func_entry("parser", "clean_prompt", { content_length = #content })
|
||||
|
||||
-- Trim leading/trailing whitespace
|
||||
content = content:match("^%s*(.-)%s*$")
|
||||
-- Normalize multiple newlines
|
||||
content = content:gsub("\n\n\n+", "\n\n")
|
||||
|
||||
logger.debug("parser", "clean_prompt: cleaned from " .. #content .. " chars")
|
||||
logger.func_exit("parser", "clean_prompt", "length=" .. #content)
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
--- Check if line contains a closing tag
|
||||
---@param line string Line to check
|
||||
---@param close_tag string Closing tag
|
||||
---@return boolean
|
||||
function M.has_closing_tag(line, close_tag)
|
||||
logger.func_entry("parser", "has_closing_tag", { line_preview = line:sub(1, 30), close_tag = close_tag })
|
||||
|
||||
local result = line:find(utils.escape_pattern(close_tag)) ~= nil
|
||||
|
||||
logger.debug("parser", "has_closing_tag: result=" .. tostring(result))
|
||||
logger.func_exit("parser", "has_closing_tag", result)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Check if buffer has any unclosed prompts
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return boolean
|
||||
function M.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
|
||||
|
||||
--- Extract file references from prompt content
|
||||
--- Matches @filename patterns but NOT @/ (closing tag)
|
||||
---@param content string Prompt content
|
||||
---@return string[] List of file references
|
||||
function M.extract_file_references(content)
|
||||
logger.func_entry("parser", "extract_file_references", { content_length = #content })
|
||||
|
||||
local files = {}
|
||||
-- Pattern: @ followed by word char, dot, underscore, or dash as FIRST char
|
||||
-- Then optionally more path characters including /
|
||||
-- This ensures @/ is NOT matched (/ cannot be first char)
|
||||
for file in content:gmatch("@([%w%._%-][%w%._%-/]*)") do
|
||||
if file ~= "" then
|
||||
table.insert(files, file)
|
||||
logger.debug("parser", "extract_file_references: found file reference: " .. file)
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("parser", "extract_file_references: found " .. #files .. " file references")
|
||||
logger.func_exit("parser", "extract_file_references", files)
|
||||
|
||||
return files
|
||||
end
|
||||
|
||||
--- Remove file references from prompt content (for clean prompt text)
|
||||
---@param content string Prompt content
|
||||
---@return string Cleaned content without file references
|
||||
function M.strip_file_references(content)
|
||||
logger.func_entry("parser", "strip_file_references", { content_length = #content })
|
||||
|
||||
-- Remove @filename patterns but preserve @/ closing tag
|
||||
-- Pattern requires first char after @ to be word char, dot, underscore, or dash (NOT /)
|
||||
local result = content:gsub("@([%w%._%-][%w%._%-/]*)", "")
|
||||
|
||||
logger.debug("parser", "strip_file_references: stripped " .. (#content - #result) .. " chars")
|
||||
logger.func_exit("parser", "strip_file_references", "length=" .. #result)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Check if cursor is inside an unclosed prompt tag
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return boolean is_inside Whether cursor is inside an open tag
|
||||
---@return number|nil start_line Line where the open tag starts
|
||||
function M.is_cursor_in_open_tag(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "is_cursor_in_open_tag", { bufnr = bufnr })
|
||||
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local cursor_line = cursor[1]
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, cursor_line, false)
|
||||
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 = 0
|
||||
local close_count = 0
|
||||
local last_open_line = nil
|
||||
|
||||
for line_num, line in ipairs(lines) do
|
||||
-- Count opens on this line
|
||||
for _ in line:gmatch(escaped_open) do
|
||||
open_count = open_count + 1
|
||||
last_open_line = line_num
|
||||
logger.debug("parser", "is_cursor_in_open_tag: found open tag at line " .. line_num)
|
||||
end
|
||||
-- Count closes on this line
|
||||
for _ in line:gmatch(escaped_close) do
|
||||
close_count = close_count + 1
|
||||
logger.debug("parser", "is_cursor_in_open_tag: found close tag at line " .. line_num)
|
||||
end
|
||||
end
|
||||
|
||||
local is_inside = open_count > close_count
|
||||
|
||||
logger.debug(
|
||||
"parser",
|
||||
"is_cursor_in_open_tag: open="
|
||||
.. open_count
|
||||
.. ", close="
|
||||
.. close_count
|
||||
.. ", is_inside="
|
||||
.. tostring(is_inside)
|
||||
.. ", last_open_line="
|
||||
.. tostring(last_open_line)
|
||||
)
|
||||
logger.func_exit("parser", "is_cursor_in_open_tag", { is_inside = is_inside, last_open_line = last_open_line })
|
||||
|
||||
return is_inside, is_inside and last_open_line or nil
|
||||
end
|
||||
|
||||
--- Get the word being typed after @ symbol
|
||||
---@param bufnr? number Buffer number
|
||||
---@return string|nil prefix The text after @ being typed, or nil if not typing a file ref
|
||||
function M.get_file_ref_prefix(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "get_file_ref_prefix", { bufnr = bufnr })
|
||||
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, cursor[1] - 1, cursor[1], false)[1]
|
||||
if not line then
|
||||
logger.debug("parser", "get_file_ref_prefix: no line at cursor")
|
||||
logger.func_exit("parser", "get_file_ref_prefix", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
local col = cursor[2]
|
||||
local before_cursor = line:sub(1, col)
|
||||
|
||||
-- Check if we're typing after @ but not @/
|
||||
-- Match @ followed by optional path characters at end of string
|
||||
local prefix = before_cursor:match("@([%w%._%-/]*)$")
|
||||
|
||||
-- Make sure it's not the closing tag pattern
|
||||
if prefix and before_cursor:sub(-2) == "@/" then
|
||||
logger.debug("parser", "get_file_ref_prefix: closing tag detected, returning nil")
|
||||
logger.func_exit("parser", "get_file_ref_prefix", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
logger.debug("parser", "get_file_ref_prefix: prefix=" .. tostring(prefix))
|
||||
logger.func_exit("parser", "get_file_ref_prefix", prefix)
|
||||
|
||||
return prefix
|
||||
end
|
||||
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")
|
||||
|
||||
|
||||
20
lua/codetyper/parser/clean_prompt.lua
Normal file
20
lua/codetyper/parser/clean_prompt.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Clean prompt content (trim whitespace, normalize newlines)
|
||||
---@param content string Raw prompt content
|
||||
---@return string Cleaned content
|
||||
local function clean_prompt(content)
|
||||
logger.func_entry("parser", "clean_prompt", { content_length = #content })
|
||||
|
||||
-- Trim leading/trailing whitespace
|
||||
content = content:match("^%s*(.-)%s*$")
|
||||
-- Normalize multiple newlines
|
||||
content = content:gsub("\n\n\n+", "\n\n")
|
||||
|
||||
logger.debug("parser", "clean_prompt: cleaned from " .. #content .. " chars")
|
||||
logger.func_exit("parser", "clean_prompt", "length=" .. #content)
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
return clean_prompt
|
||||
34
lua/codetyper/parser/detect_prompt_type.lua
Normal file
34
lua/codetyper/parser/detect_prompt_type.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
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
|
||||
24
lua/codetyper/parser/extract_file_references.lua
Normal file
24
lua/codetyper/parser/extract_file_references.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Extract file references from prompt content
|
||||
--- Matches @filename patterns but NOT @/ (closing tag)
|
||||
---@param content string Prompt content
|
||||
---@return string[] List of file references
|
||||
local function extract_file_references(content)
|
||||
logger.func_entry("parser", "extract_file_references", { content_length = #content })
|
||||
|
||||
local files = {}
|
||||
for file in content:gmatch("@([%w%._%-][%w%._%-/]*)") do
|
||||
if file ~= "" then
|
||||
table.insert(files, file)
|
||||
logger.debug("parser", "extract_file_references: found file reference: " .. file)
|
||||
end
|
||||
end
|
||||
|
||||
logger.debug("parser", "extract_file_references: found " .. #files .. " file references")
|
||||
logger.func_exit("parser", "extract_file_references", files)
|
||||
|
||||
return files
|
||||
end
|
||||
|
||||
return extract_file_references
|
||||
26
lua/codetyper/parser/find_prompts_in_buffer.lua
Normal file
26
lua/codetyper/parser/find_prompts_in_buffer.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
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
|
||||
---@return CoderPrompt[] List of found prompts
|
||||
local function find_prompts_in_buffer(bufnr)
|
||||
logger.func_entry("parser", "find_prompts_in_buffer", { bufnr = bufnr })
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local content = table.concat(lines, "\n")
|
||||
|
||||
logger.debug(
|
||||
"parser",
|
||||
"find_prompts_in_buffer: bufnr=" .. bufnr .. ", lines=" .. #lines .. ", content_length=" .. #content
|
||||
)
|
||||
|
||||
local cfg = get_config()
|
||||
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
|
||||
end
|
||||
|
||||
return find_prompts_in_buffer
|
||||
36
lua/codetyper/parser/get_file_ref_prefix.lua
Normal file
36
lua/codetyper/parser/get_file_ref_prefix.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Get the word being typed after @ symbol
|
||||
---@param bufnr? number Buffer number
|
||||
---@return string|nil prefix The text after @ being typed, or nil if not typing a file ref
|
||||
local function get_file_ref_prefix(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "get_file_ref_prefix", { bufnr = bufnr })
|
||||
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local line = vim.api.nvim_buf_get_lines(bufnr, cursor[1] - 1, cursor[1], false)[1]
|
||||
if not line then
|
||||
logger.debug("parser", "get_file_ref_prefix: no line at cursor")
|
||||
logger.func_exit("parser", "get_file_ref_prefix", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
local col = cursor[2]
|
||||
local before_cursor = line:sub(1, col)
|
||||
|
||||
local prefix = before_cursor:match("@([%w%._%-/]*)$")
|
||||
|
||||
if prefix and before_cursor:sub(-2) == "@/" then
|
||||
logger.debug("parser", "get_file_ref_prefix: closing tag detected, returning nil")
|
||||
logger.func_exit("parser", "get_file_ref_prefix", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
logger.debug("parser", "get_file_ref_prefix: prefix=" .. tostring(prefix))
|
||||
logger.func_exit("parser", "get_file_ref_prefix", prefix)
|
||||
|
||||
return prefix
|
||||
end
|
||||
|
||||
return get_file_ref_prefix
|
||||
26
lua/codetyper/parser/get_last_prompt.lua
Normal file
26
lua/codetyper/parser/get_last_prompt.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
local find_prompts_in_buffer = require("codetyper.parser.find_prompts_in_buffer")
|
||||
|
||||
--- Get the last closed prompt in buffer
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return CoderPrompt|nil Last prompt or nil
|
||||
local function get_last_prompt(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "get_last_prompt", { bufnr = bufnr })
|
||||
|
||||
local prompts = find_prompts_in_buffer(bufnr)
|
||||
|
||||
if #prompts > 0 then
|
||||
local last = prompts[#prompts]
|
||||
logger.debug("parser", "get_last_prompt: returning prompt at line " .. last.start_line)
|
||||
logger.func_exit("parser", "get_last_prompt", "prompt at line " .. last.start_line)
|
||||
return last
|
||||
end
|
||||
|
||||
logger.debug("parser", "get_last_prompt: no prompts found")
|
||||
logger.func_exit("parser", "get_last_prompt", nil)
|
||||
return nil
|
||||
end
|
||||
|
||||
return get_last_prompt
|
||||
56
lua/codetyper/parser/get_prompt_at_cursor.lua
Normal file
56
lua/codetyper/parser/get_prompt_at_cursor.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
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
|
||||
19
lua/codetyper/parser/has_closing_tag.lua
Normal file
19
lua/codetyper/parser/has_closing_tag.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Check if line contains a closing tag
|
||||
---@param line string Line to check
|
||||
---@param close_tag string Closing tag
|
||||
---@return boolean
|
||||
local function has_closing_tag(line, close_tag)
|
||||
logger.func_entry("parser", "has_closing_tag", { line_preview = line:sub(1, 30), close_tag = close_tag })
|
||||
|
||||
local result = line:find(utils.escape_pattern(close_tag)) ~= nil
|
||||
|
||||
logger.debug("parser", "has_closing_tag: result=" .. tostring(result))
|
||||
logger.func_exit("parser", "has_closing_tag", result)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return has_closing_tag
|
||||
34
lua/codetyper/parser/has_unclosed_prompts.lua
Normal file
34
lua/codetyper/parser/has_unclosed_prompts.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
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
|
||||
56
lua/codetyper/parser/is_cursor_in_open_tag.lua
Normal file
56
lua/codetyper/parser/is_cursor_in_open_tag.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local utils = require("codetyper.support.utils")
|
||||
local logger = require("codetyper.support.logger")
|
||||
local get_config = require("codetyper.utils.get_config").get_config
|
||||
|
||||
--- Check if cursor is inside an unclosed prompt tag
|
||||
---@param bufnr? number Buffer number (default: current)
|
||||
---@return boolean is_inside Whether cursor is inside an open tag
|
||||
---@return number|nil start_line Line where the open tag starts
|
||||
local function is_cursor_in_open_tag(bufnr)
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
|
||||
logger.func_entry("parser", "is_cursor_in_open_tag", { bufnr = bufnr })
|
||||
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
local cursor_line = cursor[1]
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, cursor_line, false)
|
||||
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 = 0
|
||||
local close_count = 0
|
||||
local last_open_line = nil
|
||||
|
||||
for line_num, line in ipairs(lines) do
|
||||
for _ in line:gmatch(escaped_open) do
|
||||
open_count = open_count + 1
|
||||
last_open_line = line_num
|
||||
logger.debug("parser", "is_cursor_in_open_tag: found open tag at line " .. line_num)
|
||||
end
|
||||
for _ in line:gmatch(escaped_close) do
|
||||
close_count = close_count + 1
|
||||
logger.debug("parser", "is_cursor_in_open_tag: found close tag at line " .. line_num)
|
||||
end
|
||||
end
|
||||
|
||||
local is_inside = open_count > close_count
|
||||
|
||||
logger.debug(
|
||||
"parser",
|
||||
"is_cursor_in_open_tag: open="
|
||||
.. open_count
|
||||
.. ", close="
|
||||
.. close_count
|
||||
.. ", is_inside="
|
||||
.. tostring(is_inside)
|
||||
.. ", last_open_line="
|
||||
.. tostring(last_open_line)
|
||||
)
|
||||
logger.func_exit("parser", "is_cursor_in_open_tag", { is_inside = is_inside, last_open_line = last_open_line })
|
||||
|
||||
return is_inside, is_inside and last_open_line or nil
|
||||
end
|
||||
|
||||
return is_cursor_in_open_tag
|
||||
17
lua/codetyper/parser/strip_file_references.lua
Normal file
17
lua/codetyper/parser/strip_file_references.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
local logger = require("codetyper.support.logger")
|
||||
|
||||
--- Remove file references from prompt content (for clean prompt text)
|
||||
---@param content string Prompt content
|
||||
---@return string Cleaned content without file references
|
||||
local function strip_file_references(content)
|
||||
logger.func_entry("parser", "strip_file_references", { content_length = #content })
|
||||
|
||||
local result = content:gsub("@([%w%._%-][%w%._%-/]*)", "")
|
||||
|
||||
logger.debug("parser", "strip_file_references: stripped " .. (#content - #result) .. " chars")
|
||||
logger.func_exit("parser", "strip_file_references", "length=" .. #result)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return strip_file_references
|
||||
Reference in New Issue
Block a user