feat: add :CoderTransform command for inline tag replacement

New feature: Transform /@ @/ tags directly in any file, not just
.coder.* files. The tags are replaced inline with LLM-generated code.

New commands:
- :CoderTransform - Transform ALL /@ @/ tags in current file
- :CoderTransformCursor - Transform only the tag at cursor position
- :Coder transform - Same as :CoderTransform
- :Coder transform-cursor - Same as :CoderTransformCursor

How it works:
1. Write /@ your prompt @/ anywhere in your code
2. Run :CoderTransform
3. The tag is replaced with generated code matching your file's style

Example:
  /@ create a function to validate email @/

  Becomes:
  function validateEmail(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }
This commit is contained in:
2026-01-11 15:38:41 -05:00
parent 8130a78ed5
commit d11a99ee61
3 changed files with 470 additions and 247 deletions

View File

@@ -20,182 +20,182 @@ local processed_prompts = {}
---@param prompt table Prompt object
---@return string Unique key
local function get_prompt_key(bufnr, prompt)
return string.format("%d:%d:%d:%s", bufnr, prompt.start_line, prompt.end_line, prompt.content:sub(1, 50))
return string.format("%d:%d:%d:%s", bufnr, prompt.start_line, prompt.end_line, prompt.content:sub(1, 50))
end
--- Schedule tree update with debounce
local function schedule_tree_update()
if tree_update_timer then
tree_update_timer:stop()
end
if tree_update_timer then
tree_update_timer:stop()
end
tree_update_timer = vim.defer_fn(function()
local tree = require("codetyper.tree")
tree.update_tree_log()
tree_update_timer = nil
end, TREE_UPDATE_DEBOUNCE_MS)
tree_update_timer = vim.defer_fn(function()
local tree = require("codetyper.tree")
tree.update_tree_log()
tree_update_timer = nil
end, TREE_UPDATE_DEBOUNCE_MS)
end
--- Setup autocommands
function M.setup()
local group = vim.api.nvim_create_augroup(AUGROUP, { clear = true })
local group = vim.api.nvim_create_augroup(AUGROUP, { clear = true })
-- Auto-save coder file when leaving insert mode
vim.api.nvim_create_autocmd("InsertLeave", {
group = group,
pattern = "*.coder.*",
callback = function()
-- Auto-save the coder file
if vim.bo.modified then
vim.cmd("silent! write")
end
-- Check for closed prompts and auto-process
M.check_for_closed_prompt()
end,
desc = "Auto-save and check for closed prompt tags",
})
-- Auto-save coder file when leaving insert mode
vim.api.nvim_create_autocmd("InsertLeave", {
group = group,
pattern = "*.coder.*",
callback = function()
-- Auto-save the coder file
if vim.bo.modified then
vim.cmd("silent! write")
end
-- Check for closed prompts and auto-process
M.check_for_closed_prompt()
end,
desc = "Auto-save and check for closed prompt tags",
})
-- Auto-set filetype for coder files based on extension
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
group = group,
pattern = "*.coder.*",
callback = function()
M.set_coder_filetype()
end,
desc = "Set filetype for coder files",
})
-- Auto-set filetype for coder files based on extension
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
group = group,
pattern = "*.coder.*",
callback = function()
M.set_coder_filetype()
end,
desc = "Set filetype for coder files",
})
-- Auto-open split view when opening a coder file directly (e.g., from nvim-tree)
vim.api.nvim_create_autocmd("BufEnter", {
group = group,
pattern = "*.coder.*",
callback = function()
-- Delay slightly to ensure buffer is fully loaded
vim.defer_fn(function()
M.auto_open_target_file()
end, 50)
end,
desc = "Auto-open target file when coder file is opened",
})
-- Auto-open split view when opening a coder file directly (e.g., from nvim-tree)
vim.api.nvim_create_autocmd("BufEnter", {
group = group,
pattern = "*.coder.*",
callback = function()
-- Delay slightly to ensure buffer is fully loaded
vim.defer_fn(function()
M.auto_open_target_file()
end, 50)
end,
desc = "Auto-open target file when coder file is opened",
})
-- Cleanup on buffer close
vim.api.nvim_create_autocmd("BufWipeout", {
group = group,
pattern = "*.coder.*",
callback = function(ev)
local window = require("codetyper.window")
if window.is_open() then
window.close_split()
end
-- Clear processed prompts for this buffer
local bufnr = ev.buf
for key, _ in pairs(processed_prompts) do
if key:match("^" .. bufnr .. ":") then
processed_prompts[key] = nil
end
end
-- Clear auto-opened tracking
M.clear_auto_opened(bufnr)
end,
desc = "Cleanup on coder buffer close",
})
-- Cleanup on buffer close
vim.api.nvim_create_autocmd("BufWipeout", {
group = group,
pattern = "*.coder.*",
callback = function(ev)
local window = require("codetyper.window")
if window.is_open() then
window.close_split()
end
-- Clear processed prompts for this buffer
local bufnr = ev.buf
for key, _ in pairs(processed_prompts) do
if key:match("^" .. bufnr .. ":") then
processed_prompts[key] = nil
end
end
-- Clear auto-opened tracking
M.clear_auto_opened(bufnr)
end,
desc = "Cleanup on coder buffer close",
})
-- Update tree.log when files are created/written
vim.api.nvim_create_autocmd({ "BufWritePost", "BufNewFile" }, {
group = group,
pattern = "*",
callback = function(ev)
-- Skip coder files and tree.log itself
local filepath = ev.file or vim.fn.expand("%:p")
if filepath:match("%.coder%.") or filepath:match("tree%.log$") then
return
end
-- Schedule tree update with debounce
schedule_tree_update()
end,
desc = "Update tree.log on file creation/save",
})
-- Update tree.log when files are created/written
vim.api.nvim_create_autocmd({ "BufWritePost", "BufNewFile" }, {
group = group,
pattern = "*",
callback = function(ev)
-- Skip coder files and tree.log itself
local filepath = ev.file or vim.fn.expand("%:p")
if filepath:match("%.coder%.") or filepath:match("tree%.log$") then
return
end
-- Schedule tree update with debounce
schedule_tree_update()
end,
desc = "Update tree.log on file creation/save",
})
-- Update tree.log when files are deleted (via netrw or file explorer)
vim.api.nvim_create_autocmd("BufDelete", {
group = group,
pattern = "*",
callback = function(ev)
local filepath = ev.file or ""
-- Skip special buffers and coder files
if filepath == "" or filepath:match("%.coder%.") or filepath:match("tree%.log$") then
return
end
schedule_tree_update()
end,
desc = "Update tree.log on file deletion",
})
-- Update tree.log when files are deleted (via netrw or file explorer)
vim.api.nvim_create_autocmd("BufDelete", {
group = group,
pattern = "*",
callback = function(ev)
local filepath = ev.file or ""
-- Skip special buffers and coder files
if filepath == "" or filepath:match("%.coder%.") or filepath:match("tree%.log$") then
return
end
schedule_tree_update()
end,
desc = "Update tree.log on file deletion",
})
-- Update tree on directory change
vim.api.nvim_create_autocmd("DirChanged", {
group = group,
pattern = "*",
callback = function()
schedule_tree_update()
end,
desc = "Update tree.log on directory change",
})
-- Update tree on directory change
vim.api.nvim_create_autocmd("DirChanged", {
group = group,
pattern = "*",
callback = function()
schedule_tree_update()
end,
desc = "Update tree.log on directory change",
})
end
--- Check if the buffer has a newly closed prompt and auto-process
function M.check_for_closed_prompt()
local codetyper = require("codetyper")
local config = codetyper.get_config()
local parser = require("codetyper.parser")
local codetyper = require("codetyper")
local config = codetyper.get_config()
local parser = require("codetyper.parser")
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = vim.api.nvim_get_current_buf()
-- Get current line
local cursor = vim.api.nvim_win_get_cursor(0)
local line = cursor[1]
local lines = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)
-- Get current line
local cursor = vim.api.nvim_win_get_cursor(0)
local line = cursor[1]
local lines = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)
if #lines == 0 then
return
end
if #lines == 0 then
return
end
local current_line = lines[1]
local current_line = lines[1]
-- Check if line contains closing tag
if parser.has_closing_tag(current_line, config.patterns.close_tag) then
-- Find the complete prompt
local prompt = parser.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)
-- Check if line contains closing tag
if parser.has_closing_tag(current_line, config.patterns.close_tag) then
-- Find the complete prompt
local prompt = parser.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)
-- Check if already processed
if processed_prompts[prompt_key] then
return
end
-- Check if already processed
if processed_prompts[prompt_key] then
return
end
-- Mark as processed
processed_prompts[prompt_key] = true
-- Mark as processed
processed_prompts[prompt_key] = true
-- Auto-process the prompt (no confirmation needed)
utils.notify("Processing prompt...", vim.log.levels.INFO)
vim.schedule(function()
vim.cmd("CoderProcess")
end)
end
end
-- Auto-process the prompt (no confirmation needed)
utils.notify("Processing prompt...", vim.log.levels.INFO)
vim.schedule(function()
vim.cmd("CoderProcess")
end)
end
end
end
--- Reset processed prompts for a buffer (useful for re-processing)
---@param bufnr? number Buffer number (default: current)
function M.reset_processed(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
for key, _ in pairs(processed_prompts) do
if key:match("^" .. bufnr .. ":") then
processed_prompts[key] = nil
end
end
utils.notify("Prompt history cleared - prompts can be re-processed")
bufnr = bufnr or vim.api.nvim_get_current_buf()
for key, _ in pairs(processed_prompts) do
if key:match("^" .. bufnr .. ":") then
processed_prompts[key] = nil
end
end
utils.notify("Prompt history cleared - prompts can be re-processed")
end
--- Track if we already opened the split for this buffer
@@ -204,146 +204,146 @@ local auto_opened_buffers = {}
--- Auto-open target file when a coder file is opened directly
function M.auto_open_target_file()
local window = require("codetyper.window")
local window = require("codetyper.window")
-- Skip if split is already open
if window.is_open() then
return
end
-- Skip if split is already open
if window.is_open() then
return
end
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = vim.api.nvim_get_current_buf()
-- Skip if we already handled this buffer
if auto_opened_buffers[bufnr] then
return
end
-- Skip if we already handled this buffer
if auto_opened_buffers[bufnr] then
return
end
local current_file = vim.fn.expand("%:p")
local current_file = vim.fn.expand("%:p")
-- Skip empty paths
if not current_file or current_file == "" then
return
end
-- Skip empty paths
if not current_file or current_file == "" then
return
end
-- Verify it's a coder file
if not utils.is_coder_file(current_file) then
return
end
-- Verify it's a coder file
if not utils.is_coder_file(current_file) then
return
end
-- Skip if we're in a special buffer (nvim-tree, etc.)
local buftype = vim.bo[bufnr].buftype
if buftype ~= "" then
return
end
-- Skip if we're in a special buffer (nvim-tree, etc.)
local buftype = vim.bo[bufnr].buftype
if buftype ~= "" then
return
end
-- Mark as handled
auto_opened_buffers[bufnr] = true
-- Mark as handled
auto_opened_buffers[bufnr] = true
-- Get the target file path
local target_path = utils.get_target_path(current_file)
-- Get the target file path
local target_path = utils.get_target_path(current_file)
-- Check if target file exists
if not utils.file_exists(target_path) then
utils.notify("Target file not found: " .. vim.fn.fnamemodify(target_path, ":t"), vim.log.levels.WARN)
return
end
-- Check if target file exists
if not utils.file_exists(target_path) then
utils.notify("Target file not found: " .. vim.fn.fnamemodify(target_path, ":t"), vim.log.levels.WARN)
return
end
-- Get config with fallback defaults
local codetyper = require("codetyper")
local config = codetyper.get_config()
-- Get config with fallback defaults
local codetyper = require("codetyper")
local config = codetyper.get_config()
-- Fallback width if config not fully loaded
local width = (config and config.window and config.window.width) or 0.4
if width <= 1 then
width = math.floor(vim.o.columns * width)
end
-- Fallback width if config not fully loaded
local width = (config and config.window and config.window.width) or 0.4
if width <= 1 then
width = math.floor(vim.o.columns * width)
end
-- Store current coder window
local coder_win = vim.api.nvim_get_current_win()
local coder_buf = bufnr
-- Store current coder window
local coder_win = vim.api.nvim_get_current_win()
local coder_buf = bufnr
-- Open target file in a vertical split on the right
local ok, err = pcall(function()
vim.cmd("vsplit " .. vim.fn.fnameescape(target_path))
end)
-- Open target file in a vertical split on the right
local ok, err = pcall(function()
vim.cmd("vsplit " .. vim.fn.fnameescape(target_path))
end)
if not ok then
utils.notify("Failed to open target file: " .. tostring(err), vim.log.levels.ERROR)
auto_opened_buffers[bufnr] = nil -- Allow retry
return
end
if not ok then
utils.notify("Failed to open target file: " .. tostring(err), vim.log.levels.ERROR)
auto_opened_buffers[bufnr] = nil -- Allow retry
return
end
-- Now we're in the target window (right side)
local target_win = vim.api.nvim_get_current_win()
local target_buf = vim.api.nvim_get_current_buf()
-- Now we're in the target window (right side)
local target_win = vim.api.nvim_get_current_win()
local target_buf = vim.api.nvim_get_current_buf()
-- Set the coder window width (left side)
pcall(vim.api.nvim_win_set_width, coder_win, width)
-- Set the coder window width (left side)
pcall(vim.api.nvim_win_set_width, coder_win, width)
-- Update window module state
window._coder_win = coder_win
window._coder_buf = coder_buf
window._target_win = target_win
window._target_buf = target_buf
-- Update window module state
window._coder_win = coder_win
window._coder_buf = coder_buf
window._target_win = target_win
window._target_buf = target_buf
-- Set up window options for coder window
pcall(function()
vim.wo[coder_win].number = true
vim.wo[coder_win].relativenumber = true
vim.wo[coder_win].signcolumn = "yes"
end)
-- Set up window options for coder window
pcall(function()
vim.wo[coder_win].number = true
vim.wo[coder_win].relativenumber = true
vim.wo[coder_win].signcolumn = "yes"
end)
utils.notify("Opened target: " .. vim.fn.fnamemodify(target_path, ":t"))
utils.notify("Opened target: " .. vim.fn.fnamemodify(target_path, ":t"))
end
--- Clear auto-opened tracking for a buffer
---@param bufnr number Buffer number
function M.clear_auto_opened(bufnr)
auto_opened_buffers[bufnr] = nil
auto_opened_buffers[bufnr] = nil
end
--- Set appropriate filetype for coder files
function M.set_coder_filetype()
local filepath = vim.fn.expand("%:p")
local filepath = vim.fn.expand("%:p")
-- Extract the actual extension (e.g., index.coder.ts -> ts)
local ext = filepath:match("%.coder%.(%w+)$")
-- Extract the actual extension (e.g., index.coder.ts -> ts)
local ext = filepath:match("%.coder%.(%w+)$")
if ext then
-- Map extension to filetype
local ft_map = {
ts = "typescript",
tsx = "typescriptreact",
js = "javascript",
jsx = "javascriptreact",
py = "python",
lua = "lua",
go = "go",
rs = "rust",
rb = "ruby",
java = "java",
c = "c",
cpp = "cpp",
cs = "cs",
json = "json",
yaml = "yaml",
yml = "yaml",
md = "markdown",
html = "html",
css = "css",
scss = "scss",
vue = "vue",
svelte = "svelte",
}
if ext then
-- Map extension to filetype
local ft_map = {
ts = "typescript",
tsx = "typescriptreact",
js = "javascript",
jsx = "javascriptreact",
py = "python",
lua = "lua",
go = "go",
rs = "rust",
rb = "ruby",
java = "java",
c = "c",
cpp = "cpp",
cs = "cs",
json = "json",
yaml = "yaml",
yml = "yaml",
md = "markdown",
html = "html",
css = "css",
scss = "scss",
vue = "vue",
svelte = "svelte",
}
local filetype = ft_map[ext] or ext
vim.bo.filetype = filetype
end
local filetype = ft_map[ext] or ext
vim.bo.filetype = filetype
end
end
--- Clear all autocommands
function M.clear()
vim.api.nvim_del_augroup_by_name(AUGROUP)
vim.api.nvim_del_augroup_by_name(AUGROUP)
end
return M

View File

@@ -267,6 +267,210 @@ local function cmd_focus()
end
end
--- Transform inline /@ @/ tags in current file
--- Works on ANY file, not just .coder.* files
local function cmd_transform()
local parser = require("codetyper.parser")
local llm = require("codetyper.llm")
local bufnr = vim.api.nvim_get_current_buf()
local filepath = vim.fn.expand("%:p")
if filepath == "" then
utils.notify("No file in current buffer", vim.log.levels.WARN)
return
end
-- Find all prompts in the current buffer
local prompts = parser.find_prompts_in_buffer(bufnr)
if #prompts == 0 then
utils.notify("No /@ @/ tags found in current file", vim.log.levels.INFO)
return
end
utils.notify("Found " .. #prompts .. " prompt(s) to transform...", vim.log.levels.INFO)
-- Build context for this file
local ext = vim.fn.fnamemodify(filepath, ":e")
local context = llm.build_context(filepath, "code_generation")
-- Process prompts in reverse order (bottom to top) to maintain line numbers
local sorted_prompts = {}
for i = #prompts, 1, -1 do
table.insert(sorted_prompts, prompts[i])
end
-- Track how many are being processed
local pending = #sorted_prompts
local completed = 0
local errors = 0
-- Process each prompt
for _, prompt in ipairs(sorted_prompts) do
local clean_prompt = parser.clean_prompt(prompt.content)
local prompt_type = parser.detect_prompt_type(prompt.content)
-- Build enhanced user prompt
local enhanced_prompt = "TASK: " .. clean_prompt .. "\n\n"
enhanced_prompt = enhanced_prompt .. "REQUIREMENTS:\n"
enhanced_prompt = enhanced_prompt .. "- Generate ONLY " .. (context.language or "code") .. " code\n"
enhanced_prompt = enhanced_prompt .. "- NO markdown code blocks (no ```)\n"
enhanced_prompt = enhanced_prompt .. "- NO explanations or comments about what you did\n"
enhanced_prompt = enhanced_prompt .. "- Match the coding style of the existing file exactly\n"
enhanced_prompt = enhanced_prompt .. "- Output must be ready to insert directly into the file\n"
utils.notify("Processing: " .. clean_prompt:sub(1, 40) .. "...", vim.log.levels.INFO)
-- Generate code for this prompt
llm.generate(enhanced_prompt, context, function(response, err)
if err then
utils.notify("Failed: " .. err, vim.log.levels.ERROR)
errors = errors + 1
elseif response then
-- Replace the prompt tag with generated code
vim.schedule(function()
-- Get current buffer lines
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
-- Calculate the exact range to replace
local start_line = prompt.start_line
local end_line = prompt.end_line
-- Find the full lines containing the tags
local start_line_content = lines[start_line] or ""
local end_line_content = lines[end_line] or ""
-- Check if there's content before the opening tag on the same line
local codetyper = require("codetyper")
local config = codetyper.get_config()
local before_tag = ""
local after_tag = ""
local open_pos = start_line_content:find(utils.escape_pattern(config.patterns.open_tag))
if open_pos and open_pos > 1 then
before_tag = start_line_content:sub(1, open_pos - 1)
end
local close_pos = end_line_content:find(utils.escape_pattern(config.patterns.close_tag))
if close_pos then
local after_close = close_pos + #config.patterns.close_tag
if after_close <= #end_line_content then
after_tag = end_line_content:sub(after_close)
end
end
-- Build the replacement lines
local replacement_lines = vim.split(response, "\n", { plain = true })
-- Add before/after content if any
if before_tag ~= "" and #replacement_lines > 0 then
replacement_lines[1] = before_tag .. replacement_lines[1]
end
if after_tag ~= "" and #replacement_lines > 0 then
replacement_lines[#replacement_lines] = replacement_lines[#replacement_lines] .. after_tag
end
-- Replace the lines in buffer
vim.api.nvim_buf_set_lines(bufnr, start_line - 1, end_line, false, replacement_lines)
completed = completed + 1
if completed + errors >= pending then
utils.notify(
"Transform complete: " .. completed .. " succeeded, " .. errors .. " failed",
errors > 0 and vim.log.levels.WARN or vim.log.levels.INFO
)
end
end)
end
end)
end
end
--- Transform a single prompt at cursor position
local function cmd_transform_at_cursor()
local parser = require("codetyper.parser")
local llm = require("codetyper.llm")
local bufnr = vim.api.nvim_get_current_buf()
local filepath = vim.fn.expand("%:p")
if filepath == "" then
utils.notify("No file in current buffer", vim.log.levels.WARN)
return
end
-- Find prompt at cursor
local prompt = parser.get_prompt_at_cursor(bufnr)
if not prompt then
utils.notify("No /@ @/ tag at cursor position", vim.log.levels.WARN)
return
end
local clean_prompt = parser.clean_prompt(prompt.content)
local context = llm.build_context(filepath, "code_generation")
-- Build enhanced user prompt
local enhanced_prompt = "TASK: " .. clean_prompt .. "\n\n"
enhanced_prompt = enhanced_prompt .. "REQUIREMENTS:\n"
enhanced_prompt = enhanced_prompt .. "- Generate ONLY " .. (context.language or "code") .. " code\n"
enhanced_prompt = enhanced_prompt .. "- NO markdown code blocks (no ```)\n"
enhanced_prompt = enhanced_prompt .. "- NO explanations or comments about what you did\n"
enhanced_prompt = enhanced_prompt .. "- Match the coding style of the existing file exactly\n"
enhanced_prompt = enhanced_prompt .. "- Output must be ready to insert directly into the file\n"
utils.notify("Transforming: " .. clean_prompt:sub(1, 40) .. "...", vim.log.levels.INFO)
llm.generate(enhanced_prompt, context, function(response, err)
if err then
utils.notify("Transform failed: " .. err, vim.log.levels.ERROR)
return
end
if response then
vim.schedule(function()
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
local start_line = prompt.start_line
local end_line = prompt.end_line
local start_line_content = lines[start_line] or ""
local end_line_content = lines[end_line] or ""
local codetyper = require("codetyper")
local config = codetyper.get_config()
local before_tag = ""
local after_tag = ""
local open_pos = start_line_content:find(utils.escape_pattern(config.patterns.open_tag))
if open_pos and open_pos > 1 then
before_tag = start_line_content:sub(1, open_pos - 1)
end
local close_pos = end_line_content:find(utils.escape_pattern(config.patterns.close_tag))
if close_pos then
local after_close = close_pos + #config.patterns.close_tag
if after_close <= #end_line_content then
after_tag = end_line_content:sub(after_close)
end
end
local replacement_lines = vim.split(response, "\n", { plain = true })
if before_tag ~= "" and #replacement_lines > 0 then
replacement_lines[1] = before_tag .. replacement_lines[1]
end
if after_tag ~= "" and #replacement_lines > 0 then
replacement_lines[#replacement_lines] = replacement_lines[#replacement_lines] .. after_tag
end
vim.api.nvim_buf_set_lines(bufnr, start_line - 1, end_line, false, replacement_lines)
utils.notify("Transform complete!", vim.log.levels.INFO)
end)
end
end)
end
--- Main command dispatcher
---@param args table Command arguments
local function coder_cmd(args)
@@ -287,6 +491,8 @@ local function coder_cmd(args)
["ask-toggle"] = cmd_ask_toggle,
["ask-clear"] = cmd_ask_clear,
gitignore = cmd_gitignore,
transform = cmd_transform,
["transform-cursor"] = cmd_transform_at_cursor,
}
local cmd_fn = commands[subcommand]
@@ -306,6 +512,7 @@ function M.setup()
"open", "close", "toggle", "process", "status", "focus",
"tree", "tree-view", "reset", "gitignore",
"ask", "ask-close", "ask-toggle", "ask-clear",
"transform", "transform-cursor",
}
end,
desc = "Codetyper.nvim commands",
@@ -348,6 +555,15 @@ function M.setup()
vim.api.nvim_create_user_command("CoderAskClear", function()
cmd_ask_clear()
end, { desc = "Clear Ask history" })
-- Transform commands (inline /@ @/ tag replacement)
vim.api.nvim_create_user_command("CoderTransform", function()
cmd_transform()
end, { desc = "Transform all /@ @/ tags in current file" })
vim.api.nvim_create_user_command("CoderTransformCursor", function()
cmd_transform_at_cursor()
end, { desc = "Transform /@ @/ tag at cursor" })
end
return M

View File

@@ -4,6 +4,13 @@
local M = {}
/@
create a prompt to generate code based on user description
-- @usage M.create_function
-- @param description string Description of the code to generate
-- @return string Prompt template
@/
--- Prompt template for creating a new function
M.create_function = [[Create a function with the following requirements: