diff --git a/lua/gemini/chat.lua b/lua/gemini/chat.lua index 9c887ca..9c8eaf6 100644 --- a/lua/gemini/chat.lua +++ b/lua/gemini/chat.lua @@ -22,6 +22,7 @@ local function setup_chat_highlighting(bufnr) end local function setup_buffer_options(bufnr) + -- Set strict buffer options local options = { buftype = 'nofile', filetype = 'markdown', @@ -30,52 +31,90 @@ local function setup_buffer_options(bufnr) bufhidden = 'wipe', modifiable = false, readonly = true, - undolevels = -1, -- Disable undo - list = false, -- Disable list mode - number = false, -- Disable line numbers + undolevels = -1, + list = false, + number = false, relativenumber = false, - modifiable = false, modified = false, foldmethod = 'manual', foldlevel = 99, + textwidth = 0, + wrapmargin = 0, + expandtab = true, + autoindent = false, + smartindent = false, } for option, value in pairs(options) do vim.api.nvim_buf_set_option(bufnr, option, value) end + + -- Clear buffer name to prevent file operations + vim.api.nvim_buf_set_name(bufnr, '') end local function setup_buffer_autocmds(bufnr) local augroup = vim.api.nvim_create_augroup('GeminiChatBuffer', { clear = true }) - -- Block ALL file operations and buffer modifications + -- Block ALL buffer events that could load files local blocked_events = { 'BufReadCmd', 'FileReadCmd', 'BufWriteCmd', 'FileWriteCmd', 'BufReadPre', 'BufReadPost', 'BufWrite', 'BufWritePre', 'BufWritePost', 'FileReadPre', 'FileReadPost', 'FileWritePre', 'FileWritePost', - 'BufAdd', 'BufCreate', 'BufDelete', 'BufWipeout' + 'BufAdd', 'BufCreate', 'BufDelete', 'BufWipeout', + 'BufNew', 'BufNewFile', 'BufRead', 'BufEnter', 'BufLeave', + 'FileType', 'BufFilePre', 'BufFilePost', + 'FileChangedShell', 'FileChangedShellPost', + 'FileChangedRO', 'FileAppendCmd', 'FileAppendPre', 'FileAppendPost', + 'FilterReadPre', 'FilterReadPost', 'FocusGained', 'FocusLost' } - vim.api.nvim_create_autocmd(blocked_events, { - group = augroup, - buffer = bufnr, - callback = function() - vim.notify('File operations are not allowed in the chat window', vim.log.levels.WARN) - return true - end - }) + for _, event in ipairs(blocked_events) do + vim.api.nvim_create_autocmd(event, { + group = augroup, + buffer = bufnr, + callback = function() + vim.notify('File operations are not allowed in the chat window', vim.log.levels.WARN) + return true -- Prevent the default handler + end + }) + end - -- Prevent dropping files into the buffer + -- Override buffer behavior vim.api.nvim_create_autocmd('BufEnter', { group = augroup, buffer = bufnr, callback = function() + -- Force buffer settings on every enter vim.opt_local.modifiable = false vim.opt_local.readonly = true - -- Disable file-related options vim.opt_local.swapfile = false vim.opt_local.buftype = 'nofile' vim.opt_local.buflisted = false + + -- Disable file loading capabilities + vim.bo[bufnr].buftype = 'nofile' + vim.bo[bufnr].filetype = 'markdown' + + -- Clear file name to prevent file operations + vim.api.nvim_buf_set_name(bufnr, '') + + -- Return true to prevent default BufEnter handling + return true + end + }) + + -- Prevent any attempt to change buffer settings + vim.api.nvim_create_autocmd('OptionSet', { + group = augroup, + buffer = bufnr, + callback = function() + vim.schedule(function() + vim.opt_local.modifiable = false + vim.opt_local.readonly = true + vim.opt_local.buftype = 'nofile' + end) + return true end }) end @@ -83,46 +122,28 @@ end local function setup_buffer_keymaps(bufnr) local opts = { buffer = bufnr, nowait = true, silent = true } - -- Block ALL commands that could manipulate files or buffers - local blocked_cmds = { - 'e', 'edit', 'ene', 'enew', 'fin', 'find', - 'w', 'write', 'wa', 'wall', - 'sp', 'split', 'vs', 'vsplit', - 'new', 'vnew', 'tabnew', - 'read', 'r', 'file', 'f', - 'saveas', 'w', 'wq', 'wqa', - 'q', 'quit', 'qa', 'qall', - 'bn', 'bnext', 'bp', 'bprevious', - 'bd', 'bdelete', 'bw', 'bwipeout', - 'o', 'open', 'browse' - } - - -- Block all command variations - for _, cmd in ipairs(blocked_cmds) do - vim.keymap.set('n', ':' .. cmd, function() - vim.notify('Command not allowed in chat window', vim.log.levels.WARN) - end, opts) - vim.keymap.set('n', ':' .. cmd .. '!', function() - vim.notify('Command not allowed in chat window', vim.log.levels.WARN) - end, opts) - end - - -- Disable command-line completely + -- Disable ALL commands vim.keymap.set('n', ':', function() - vim.notify('Command mode disabled in chat window', vim.log.levels.WARN) + vim.notify('Commands are disabled in chat window', vim.log.levels.WARN) + return '' end, opts) - -- Block common file operation key combinations + -- Block ALL normal mode key combinations that could manipulate files local blocked_keys = { - 'ZZ', 'ZQ', 'gf', 'f', 'gf', - 'v', 's', 'n' + 'ZZ', 'ZQ', 'gf', 'f', 'gf', 'F', + 'v', 's', 'n', '', '', + '^', '6', 'gF', 'gF', + 'o', 'T', 'H', 'J', 'K', 'L' } for _, key in ipairs(blocked_keys) do - vim.keymap.set('n', key, '', opts) + vim.keymap.set({'n', 'v', 'i'}, key, function() + vim.notify('Operation not allowed in chat window', vim.log.levels.WARN) + return '' + end, opts) end - -- Set chat-specific keymaps + -- Only allow specific keymaps for chat functionality local mappings = config.options.mappings vim.keymap.set('n', mappings.close, function() vim.api.nvim_win_close(state.winnr, true) @@ -136,6 +157,12 @@ local function setup_buffer_keymaps(bufnr) vim.keymap.set('n', mappings.new_query, function() require("gemini").prompt_query(state.current_context) end, opts) + + -- Allow basic navigation + local allowed_keys = {'j', 'k', '', '', '', '', 'G', 'gg'} + for _, key in ipairs(allowed_keys) do + vim.keymap.set('n', key, key, opts) + end end function M.create_window()