From 69c8061b8e4402fd80cb31368029f108e44fd715 Mon Sep 17 00:00:00 2001 From: Carlos Gutierrez Date: Tue, 24 Mar 2026 21:57:02 -0400 Subject: [PATCH] migrating the logs --- lua/codetyper/adapters/nvim/ui/logs_panel.lua | 380 +----------------- .../nvim/ui/logs_panel/add_log_entry.lua | 59 +++ .../adapters/nvim/ui/logs_panel/close.lua | 45 +++ .../adapters/nvim/ui/logs_panel/constants.lua | 8 + .../nvim/ui/logs_panel/ensure_open.lua | 11 + .../adapters/nvim/ui/logs_panel/is_open.lua | 9 + .../adapters/nvim/ui/logs_panel/open.lua | 90 +++++ .../adapters/nvim/ui/logs_panel/setup.lua | 35 ++ .../adapters/nvim/ui/logs_panel/toggle.lua | 14 + .../ui/logs_panel/update_queue_display.lua | 72 ++++ .../nvim/ui/logs_panel/update_title.lua | 21 + lua/codetyper/state/state.lua | 4 + 12 files changed, 374 insertions(+), 374 deletions(-) create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/add_log_entry.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/close.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/constants.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/ensure_open.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/is_open.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/open.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/setup.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/toggle.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/update_queue_display.lua create mode 100644 lua/codetyper/adapters/nvim/ui/logs_panel/update_title.lua diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel.lua b/lua/codetyper/adapters/nvim/ui/logs_panel.lua index 4678b0e..8dcb6b8 100644 --- a/lua/codetyper/adapters/nvim/ui/logs_panel.lua +++ b/lua/codetyper/adapters/nvim/ui/logs_panel.lua @@ -2,379 +2,11 @@ --- local M = {} -local logs = require("codetyper.adapters.nvim.ui.logs") -local queue = require("codetyper.core.events.queue") - ----@class LogsPanelState ----@field buf number|nil Logs buffer ----@field win number|nil Logs window ----@field queue_buf number|nil Queue buffer ----@field queue_win number|nil Queue window ----@field is_open boolean Whether the panel is open ----@field listener_id number|nil Listener ID for logs ----@field queue_listener_id number|nil Listener ID for queue - -local state = { - buf = nil, - win = nil, - queue_buf = nil, - queue_win = nil, - is_open = false, - listener_id = nil, - queue_listener_id = nil, -} - ---- Namespace for highlights -local ns_logs = vim.api.nvim_create_namespace("codetyper_logs_panel") -local ns_queue = vim.api.nvim_create_namespace("codetyper_queue_panel") - ---- Fixed dimensions -local LOGS_WIDTH = 60 -local QUEUE_HEIGHT = 8 - ---- Add a log entry to the buffer ----@param entry table Log entry -local function add_log_entry(entry) - if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then - return - end - - vim.schedule(function() - if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then - return - end - - -- Handle clear event - if entry.level == "clear" then - vim.bo[state.buf].modifiable = true - vim.api.nvim_buf_set_lines(state.buf, 0, -1, false, { - "Generation Logs", - string.rep("─", LOGS_WIDTH - 2), - "", - }) - vim.bo[state.buf].modifiable = false - return - end - - vim.bo[state.buf].modifiable = true - - local formatted = logs.format_entry(entry) - local formatted_lines = vim.split(formatted, "\n", { plain = true }) - local line_count = vim.api.nvim_buf_line_count(state.buf) - - vim.api.nvim_buf_set_lines(state.buf, -1, -1, false, formatted_lines) - - -- Apply highlighting based on level - local hl_map = { - info = "DiagnosticInfo", - debug = "Comment", - request = "DiagnosticWarn", - response = "DiagnosticOk", - tool = "DiagnosticHint", - error = "DiagnosticError", - } - - local hl = hl_map[entry.level] or "Normal" - for i = 0, #formatted_lines - 1 do - vim.api.nvim_buf_add_highlight(state.buf, ns_logs, hl, line_count + i, 0, -1) - end - - vim.bo[state.buf].modifiable = false - - -- Auto-scroll logs - if state.win and vim.api.nvim_win_is_valid(state.win) then - local new_count = vim.api.nvim_buf_line_count(state.buf) - pcall(vim.api.nvim_win_set_cursor, state.win, { new_count, 0 }) - end - end) -end - ---- Update the title with token counts -local function update_title() - if not state.win or not vim.api.nvim_win_is_valid(state.win) then - return - end - - local prompt_tokens, response_tokens = logs.get_token_totals() - local provider, model = logs.get_provider_info() - - if provider and state.buf and vim.api.nvim_buf_is_valid(state.buf) then - vim.bo[state.buf].modifiable = true - local title = string.format("%s | %d/%d tokens", (provider or ""):upper(), prompt_tokens, response_tokens) - vim.api.nvim_buf_set_lines(state.buf, 0, 1, false, { title }) - vim.bo[state.buf].modifiable = false - end -end - ---- Update the queue display -local function update_queue_display() - if not state.queue_buf or not vim.api.nvim_buf_is_valid(state.queue_buf) then - return - end - - vim.schedule(function() - if not state.queue_buf or not vim.api.nvim_buf_is_valid(state.queue_buf) then - return - end - - vim.bo[state.queue_buf].modifiable = true - - local lines = { - "Queue", - string.rep("─", LOGS_WIDTH - 2), - } - - -- Get all events (pending and processing) - local pending = queue.get_pending() - local processing = queue.get_processing() - - -- Add processing events first - for _, event in ipairs(processing) do - local filename = vim.fn.fnamemodify(event.target_path or "", ":t") - local line_num = event.range and event.range.start_line or 0 - local prompt_preview = (event.prompt_content or ""):sub(1, 25):gsub("\n", " ") - if #(event.prompt_content or "") > 25 then - prompt_preview = prompt_preview .. "..." - end - table.insert(lines, string.format("▶ %s:%d %s", filename, line_num, prompt_preview)) - end - - -- Add pending events - for _, event in ipairs(pending) do - local filename = vim.fn.fnamemodify(event.target_path or "", ":t") - local line_num = event.range and event.range.start_line or 0 - local prompt_preview = (event.prompt_content or ""):sub(1, 25):gsub("\n", " ") - if #(event.prompt_content or "") > 25 then - prompt_preview = prompt_preview .. "..." - end - table.insert(lines, string.format("○ %s:%d %s", filename, line_num, prompt_preview)) - end - - if #pending == 0 and #processing == 0 then - table.insert(lines, " (empty)") - end - - vim.api.nvim_buf_set_lines(state.queue_buf, 0, -1, false, lines) - - -- Apply highlights - vim.api.nvim_buf_clear_namespace(state.queue_buf, ns_queue, 0, -1) - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "Title", 0, 0, -1) - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "Comment", 1, 0, -1) - - local line_idx = 2 - for _ = 1, #processing do - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "DiagnosticWarn", line_idx, 0, 1) - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "String", line_idx, 2, -1) - line_idx = line_idx + 1 - end - for _ = 1, #pending do - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "Comment", line_idx, 0, 1) - vim.api.nvim_buf_add_highlight(state.queue_buf, ns_queue, "Normal", line_idx, 2, -1) - line_idx = line_idx + 1 - end - - vim.bo[state.queue_buf].modifiable = false - end) -end - ---- Open the logs panel -function M.open() - if state.is_open then - return - end - - -- Clear previous logs - logs.clear() - - -- Create logs buffer - state.buf = vim.api.nvim_create_buf(false, true) - vim.bo[state.buf].buftype = "nofile" - vim.bo[state.buf].bufhidden = "hide" - vim.bo[state.buf].swapfile = false - - -- Create window on the right - vim.cmd("botright vsplit") - state.win = vim.api.nvim_get_current_win() - vim.api.nvim_win_set_buf(state.win, state.buf) - vim.api.nvim_win_set_width(state.win, LOGS_WIDTH) - - -- Window options for logs - vim.wo[state.win].number = false - vim.wo[state.win].relativenumber = false - vim.wo[state.win].signcolumn = "no" - vim.wo[state.win].wrap = true - vim.wo[state.win].linebreak = true - vim.wo[state.win].winfixwidth = true - vim.wo[state.win].cursorline = false - - -- Set initial content for logs - vim.bo[state.buf].modifiable = true - vim.api.nvim_buf_set_lines(state.buf, 0, -1, false, { - "Generation Logs", - string.rep("─", LOGS_WIDTH - 2), - "", - }) - vim.bo[state.buf].modifiable = false - - -- Create queue buffer - state.queue_buf = vim.api.nvim_create_buf(false, true) - vim.bo[state.queue_buf].buftype = "nofile" - vim.bo[state.queue_buf].bufhidden = "hide" - vim.bo[state.queue_buf].swapfile = false - - -- Create queue window as horizontal split at bottom of logs window - vim.cmd("belowright split") - state.queue_win = vim.api.nvim_get_current_win() - vim.api.nvim_win_set_buf(state.queue_win, state.queue_buf) - vim.api.nvim_win_set_height(state.queue_win, QUEUE_HEIGHT) - - -- Window options for queue - vim.wo[state.queue_win].number = false - vim.wo[state.queue_win].relativenumber = false - vim.wo[state.queue_win].signcolumn = "no" - vim.wo[state.queue_win].wrap = true - vim.wo[state.queue_win].linebreak = true - vim.wo[state.queue_win].winfixheight = true - vim.wo[state.queue_win].cursorline = false - - -- Setup keymaps for logs buffer - local opts = { buffer = state.buf, noremap = true, silent = true } - vim.keymap.set("n", "q", M.close, opts) - vim.keymap.set("n", "", M.close, opts) - - -- Setup keymaps for queue buffer - local queue_opts = { buffer = state.queue_buf, noremap = true, silent = true } - vim.keymap.set("n", "q", M.close, queue_opts) - vim.keymap.set("n", "", M.close, queue_opts) - - -- Register log listener - state.listener_id = logs.add_listener(function(entry) - add_log_entry(entry) - if entry.level == "response" then - vim.schedule(update_title) - end - end) - - -- Register queue listener - state.queue_listener_id = queue.add_listener(function() - update_queue_display() - end) - - -- Initial queue display - update_queue_display() - - state.is_open = true - - -- Return focus to previous window - vim.cmd("wincmd p") - - logs.info("Logs panel opened") -end - ---- Close the logs panel ----@param force? boolean Force close even if not marked as open -function M.close(force) - if not state.is_open and not force then - return - end - - -- Remove log listener - if state.listener_id then - pcall(logs.remove_listener, state.listener_id) - state.listener_id = nil - end - - -- Remove queue listener - if state.queue_listener_id then - pcall(queue.remove_listener, state.queue_listener_id) - state.queue_listener_id = nil - end - - -- Close queue window first - if state.queue_win then - pcall(vim.api.nvim_win_close, state.queue_win, true) - state.queue_win = nil - end - - -- Close logs window - if state.win then - pcall(vim.api.nvim_win_close, state.win, true) - state.win = nil - end - - -- Delete queue buffer - if state.queue_buf then - pcall(vim.api.nvim_buf_delete, state.queue_buf, { force = true }) - state.queue_buf = nil - end - - -- Delete logs buffer - if state.buf then - pcall(vim.api.nvim_buf_delete, state.buf, { force = true }) - state.buf = nil - end - - state.is_open = false -end - ---- Toggle the logs panel -function M.toggle() - if state.is_open then - M.close() - else - M.open() - end -end - ---- Check if panel is open ----@return boolean -function M.is_open() - return state.is_open -end - ---- Ensure panel is open (call before starting generation) -function M.ensure_open() - if not state.is_open then - M.open() - end -end - ---- Setup autocmds for the logs panel -function M.setup() - local group = vim.api.nvim_create_augroup("CodetypeLogsPanel", { clear = true }) - - -- Close logs panel when exiting Neovim - vim.api.nvim_create_autocmd("VimLeavePre", { - group = group, - callback = function() - -- Force close to ensure cleanup even in edge cases - M.close(true) - end, - desc = "Close logs panel before exiting Neovim", - }) - - -- Also clean up when QuitPre fires (handles :qa, :wqa, etc.) - vim.api.nvim_create_autocmd("QuitPre", { - group = group, - callback = function() - -- Check if this is the last window (about to quit Neovim) - local wins = vim.api.nvim_list_wins() - local real_wins = 0 - for _, win in ipairs(wins) do - local buf = vim.api.nvim_win_get_buf(win) - local buftype = vim.bo[buf].buftype - -- Count non-special windows - if buftype == "" or buftype == "help" then - real_wins = real_wins + 1 - end - end - -- If only logs/queue windows remain, close them - if real_wins <= 1 then - M.close(true) - end - end, - desc = "Close logs panel on quit", - }) -end +M.open = require("codetyper.adapters.nvim.ui.logs_panel.open") +M.close = require("codetyper.adapters.nvim.ui.logs_panel.close") +M.toggle = require("codetyper.adapters.nvim.ui.logs_panel.toggle") +M.is_open = require("codetyper.adapters.nvim.ui.logs_panel.is_open") +M.ensure_open = require("codetyper.adapters.nvim.ui.logs_panel.ensure_open") +M.setup = require("codetyper.adapters.nvim.ui.logs_panel.setup") return M diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/add_log_entry.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/add_log_entry.lua new file mode 100644 index 0000000..e88b557 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/add_log_entry.lua @@ -0,0 +1,59 @@ +local state = require("codetyper.state.state") +local logs = require("codetyper.adapters.nvim.ui.logs") +local constants = require("codetyper.adapters.nvim.ui.logs_panel.constants") + +--- Add a log entry to the panel buffer with highlighting +---@param entry table Log entry +local function add_log_entry(entry) + if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then + return + end + + vim.schedule(function() + if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then + return + end + + if entry.level == "clear" then + vim.bo[state.buf].modifiable = true + vim.api.nvim_buf_set_lines(state.buf, 0, -1, false, { + "Generation Logs", + string.rep("─", constants.LOGS_WIDTH - 2), + "", + }) + vim.bo[state.buf].modifiable = false + return + end + + vim.bo[state.buf].modifiable = true + + local formatted = logs.format_entry(entry) + local formatted_lines = vim.split(formatted, "\n", { plain = true }) + local line_count = vim.api.nvim_buf_line_count(state.buf) + + vim.api.nvim_buf_set_lines(state.buf, -1, -1, false, formatted_lines) + + local highlight_map = { + info = "DiagnosticInfo", + debug = "Comment", + request = "DiagnosticWarn", + response = "DiagnosticOk", + tool = "DiagnosticHint", + error = "DiagnosticError", + } + + local highlight_group = highlight_map[entry.level] or "Normal" + for line_offset = 0, #formatted_lines - 1 do + vim.api.nvim_buf_add_highlight(state.buf, constants.ns_logs, highlight_group, line_count + line_offset, 0, -1) + end + + vim.bo[state.buf].modifiable = false + + if state.win and vim.api.nvim_win_is_valid(state.win) then + local new_line_count = vim.api.nvim_buf_line_count(state.buf) + pcall(vim.api.nvim_win_set_cursor, state.win, { new_line_count, 0 }) + end + end) +end + +return add_log_entry diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/close.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/close.lua new file mode 100644 index 0000000..52b36e3 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/close.lua @@ -0,0 +1,45 @@ +local state = require("codetyper.state.state") +local logs = require("codetyper.adapters.nvim.ui.logs") +local queue = require("codetyper.core.events.queue") + +--- Close the logs panel and clean up listeners, windows, buffers +---@param force? boolean Force close even if not marked as open +local function close(force) + if not state.is_open and not force then + return + end + + if state.listener_id then + pcall(logs.remove_listener, state.listener_id) + state.listener_id = nil + end + + if state.queue_listener_id then + pcall(queue.remove_listener, state.queue_listener_id) + state.queue_listener_id = nil + end + + if state.queue_win then + pcall(vim.api.nvim_win_close, state.queue_win, true) + state.queue_win = nil + end + + if state.win then + pcall(vim.api.nvim_win_close, state.win, true) + state.win = nil + end + + if state.queue_buf then + pcall(vim.api.nvim_buf_delete, state.queue_buf, { force = true }) + state.queue_buf = nil + end + + if state.buf then + pcall(vim.api.nvim_buf_delete, state.buf, { force = true }) + state.buf = nil + end + + state.is_open = false +end + +return close diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/constants.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/constants.lua new file mode 100644 index 0000000..04d277c --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/constants.lua @@ -0,0 +1,8 @@ +local constants = { + ns_logs = vim.api.nvim_create_namespace("codetyper_logs_panel"), + ns_queue = vim.api.nvim_create_namespace("codetyper_queue_panel"), + LOGS_WIDTH = 60, + QUEUE_HEIGHT = 8, +} + +return constants diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/ensure_open.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/ensure_open.lua new file mode 100644 index 0000000..b34d0ba --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/ensure_open.lua @@ -0,0 +1,11 @@ +local state = require("codetyper.state.state") +local open = require("codetyper.adapters.nvim.ui.logs_panel.open") + +--- Ensure the logs panel is open (call before starting generation) +local function ensure_open() + if not state.is_open then + open() + end +end + +return ensure_open diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/is_open.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/is_open.lua new file mode 100644 index 0000000..2caecc5 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/is_open.lua @@ -0,0 +1,9 @@ +local state = require("codetyper.state.state") + +--- Check if the logs panel is open +---@return boolean +local function is_open() + return state.is_open +end + +return is_open diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/open.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/open.lua new file mode 100644 index 0000000..c4393f0 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/open.lua @@ -0,0 +1,90 @@ +local state = require("codetyper.state.state") +local logs = require("codetyper.adapters.nvim.ui.logs") +local queue = require("codetyper.core.events.queue") +local constants = require("codetyper.adapters.nvim.ui.logs_panel.constants") +local add_log_entry = require("codetyper.adapters.nvim.ui.logs_panel.add_log_entry") +local update_title = require("codetyper.adapters.nvim.ui.logs_panel.update_title") +local update_queue_display = require("codetyper.adapters.nvim.ui.logs_panel.update_queue_display") +local close = require("codetyper.adapters.nvim.ui.logs_panel.close") + +--- Open the logs panel with logs window and queue window +local function open() + if state.is_open then + return + end + + logs.clear() + + state.buf = vim.api.nvim_create_buf(false, true) + vim.bo[state.buf].buftype = "nofile" + vim.bo[state.buf].bufhidden = "hide" + vim.bo[state.buf].swapfile = false + + vim.cmd("botright vsplit") + state.win = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_buf(state.win, state.buf) + vim.api.nvim_win_set_width(state.win, constants.LOGS_WIDTH) + + vim.wo[state.win].number = false + vim.wo[state.win].relativenumber = false + vim.wo[state.win].signcolumn = "no" + vim.wo[state.win].wrap = true + vim.wo[state.win].linebreak = true + vim.wo[state.win].winfixwidth = true + vim.wo[state.win].cursorline = false + + vim.bo[state.buf].modifiable = true + vim.api.nvim_buf_set_lines(state.buf, 0, -1, false, { + "Generation Logs", + string.rep("─", constants.LOGS_WIDTH - 2), + "", + }) + vim.bo[state.buf].modifiable = false + + state.queue_buf = vim.api.nvim_create_buf(false, true) + vim.bo[state.queue_buf].buftype = "nofile" + vim.bo[state.queue_buf].bufhidden = "hide" + vim.bo[state.queue_buf].swapfile = false + + vim.cmd("belowright split") + state.queue_win = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_buf(state.queue_win, state.queue_buf) + vim.api.nvim_win_set_height(state.queue_win, constants.QUEUE_HEIGHT) + + vim.wo[state.queue_win].number = false + vim.wo[state.queue_win].relativenumber = false + vim.wo[state.queue_win].signcolumn = "no" + vim.wo[state.queue_win].wrap = true + vim.wo[state.queue_win].linebreak = true + vim.wo[state.queue_win].winfixheight = true + vim.wo[state.queue_win].cursorline = false + + local logs_keymap_opts = { buffer = state.buf, noremap = true, silent = true } + vim.keymap.set("n", "q", close, logs_keymap_opts) + vim.keymap.set("n", "", close, logs_keymap_opts) + + local queue_keymap_opts = { buffer = state.queue_buf, noremap = true, silent = true } + vim.keymap.set("n", "q", close, queue_keymap_opts) + vim.keymap.set("n", "", close, queue_keymap_opts) + + state.listener_id = logs.add_listener(function(entry) + add_log_entry(entry) + if entry.level == "response" then + vim.schedule(update_title) + end + end) + + state.queue_listener_id = queue.add_listener(function() + update_queue_display() + end) + + update_queue_display() + + state.is_open = true + + vim.cmd("wincmd p") + + logs.info("Logs panel opened") +end + +return open diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/setup.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/setup.lua new file mode 100644 index 0000000..9e8ec42 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/setup.lua @@ -0,0 +1,35 @@ +local close = require("codetyper.adapters.nvim.ui.logs_panel.close") + +--- Setup autocmds for the logs panel +local function setup() + local group = vim.api.nvim_create_augroup("CodetypeLogsPanel", { clear = true }) + + vim.api.nvim_create_autocmd("VimLeavePre", { + group = group, + callback = function() + close(true) + end, + desc = "Close logs panel before exiting Neovim", + }) + + vim.api.nvim_create_autocmd("QuitPre", { + group = group, + callback = function() + local wins = vim.api.nvim_list_wins() + local real_wins = 0 + for _, win in ipairs(wins) do + local buf = vim.api.nvim_win_get_buf(win) + local buftype = vim.bo[buf].buftype + if buftype == "" or buftype == "help" then + real_wins = real_wins + 1 + end + end + if real_wins <= 1 then + close(true) + end + end, + desc = "Close logs panel on quit", + }) +end + +return setup diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/toggle.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/toggle.lua new file mode 100644 index 0000000..70a4bb4 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/toggle.lua @@ -0,0 +1,14 @@ +local state = require("codetyper.state.state") +local open = require("codetyper.adapters.nvim.ui.logs_panel.open") +local close = require("codetyper.adapters.nvim.ui.logs_panel.close") + +--- Toggle the logs panel open/closed +local function toggle() + if state.is_open then + close() + else + open() + end +end + +return toggle diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/update_queue_display.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/update_queue_display.lua new file mode 100644 index 0000000..0f81d86 --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/update_queue_display.lua @@ -0,0 +1,72 @@ +local state = require("codetyper.state.state") +local queue = require("codetyper.core.events.queue") +local constants = require("codetyper.adapters.nvim.ui.logs_panel.constants") + +--- Update the queue display buffer with pending and processing events +local function update_queue_display() + if not state.queue_buf or not vim.api.nvim_buf_is_valid(state.queue_buf) then + return + end + + vim.schedule(function() + if not state.queue_buf or not vim.api.nvim_buf_is_valid(state.queue_buf) then + return + end + + vim.bo[state.queue_buf].modifiable = true + + local lines = { + "Queue", + string.rep("─", constants.LOGS_WIDTH - 2), + } + + local pending_events = queue.get_pending() + local processing_events = queue.get_processing() + + for _, event in ipairs(processing_events) do + local filename = vim.fn.fnamemodify(event.target_path or "", ":t") + local line_num = event.range and event.range.start_line or 0 + local prompt_preview = (event.prompt_content or ""):sub(1, 25):gsub("\n", " ") + if #(event.prompt_content or "") > 25 then + prompt_preview = prompt_preview .. "..." + end + table.insert(lines, string.format("▶ %s:%d %s", filename, line_num, prompt_preview)) + end + + for _, event in ipairs(pending_events) do + local filename = vim.fn.fnamemodify(event.target_path or "", ":t") + local line_num = event.range and event.range.start_line or 0 + local prompt_preview = (event.prompt_content or ""):sub(1, 25):gsub("\n", " ") + if #(event.prompt_content or "") > 25 then + prompt_preview = prompt_preview .. "..." + end + table.insert(lines, string.format("○ %s:%d %s", filename, line_num, prompt_preview)) + end + + if #pending_events == 0 and #processing_events == 0 then + table.insert(lines, " (empty)") + end + + vim.api.nvim_buf_set_lines(state.queue_buf, 0, -1, false, lines) + + vim.api.nvim_buf_clear_namespace(state.queue_buf, constants.ns_queue, 0, -1) + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "Title", 0, 0, -1) + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "Comment", 1, 0, -1) + + local highlight_line = 2 + for _ = 1, #processing_events do + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "DiagnosticWarn", highlight_line, 0, 1) + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "String", highlight_line, 2, -1) + highlight_line = highlight_line + 1 + end + for _ = 1, #pending_events do + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "Comment", highlight_line, 0, 1) + vim.api.nvim_buf_add_highlight(state.queue_buf, constants.ns_queue, "Normal", highlight_line, 2, -1) + highlight_line = highlight_line + 1 + end + + vim.bo[state.queue_buf].modifiable = false + end) +end + +return update_queue_display diff --git a/lua/codetyper/adapters/nvim/ui/logs_panel/update_title.lua b/lua/codetyper/adapters/nvim/ui/logs_panel/update_title.lua new file mode 100644 index 0000000..222cf4e --- /dev/null +++ b/lua/codetyper/adapters/nvim/ui/logs_panel/update_title.lua @@ -0,0 +1,21 @@ +local state = require("codetyper.state.state") +local logs = require("codetyper.adapters.nvim.ui.logs") + +--- Update the panel title with token counts and provider info +local function update_title() + if not state.win or not vim.api.nvim_win_is_valid(state.win) then + return + end + + local prompt_tokens, response_tokens = logs.get_token_totals() + local provider, _ = logs.get_provider_info() + + if provider and state.buf and vim.api.nvim_buf_is_valid(state.buf) then + vim.bo[state.buf].modifiable = true + local title = string.format("%s | %d/%d tokens", (provider or ""):upper(), prompt_tokens, response_tokens) + vim.api.nvim_buf_set_lines(state.buf, 0, 1, false, { title }) + vim.bo[state.buf].modifiable = false + end +end + +return update_title diff --git a/lua/codetyper/state/state.lua b/lua/codetyper/state/state.lua index 34753df..731df68 100644 --- a/lua/codetyper/state/state.lua +++ b/lua/codetyper/state/state.lua @@ -17,6 +17,10 @@ local state = { total_response_tokens = 0, current_provider = nil, current_model = nil, + queue_buf = nil, + queue_win = nil, + listener_id = nil, + queue_listener_id = nil, } return state