local augroup = vim.api.nvim_create_augroup("UserConfig", {}) vim.api.nvim_create_autocmd("TextYankPost", { desc = "Highlight when yanking (copying) text", group = vim.api.nvim_create_augroup("kickstart-highlight-yank", { clear = true }), callback = function() vim.hl.on_yank() end, }) vim.api.nvim_create_autocmd({ "BufWritePre" }, { pattern = { "*" }, command = [[%s/\s\+$//e]], }) -- Return to last edit position when opening files vim.api.nvim_create_autocmd("BufReadPost", { group = augroup, callback = function() local mark = vim.api.nvim_buf_get_mark(0, '"') local lcount = vim.api.nvim_buf_line_count(0) if mark[1] > 0 and mark[1] <= lcount then pcall(vim.api.nvim_win_set_cursor, 0, mark) end end, }) -- Auto-close terminal when process exits vim.api.nvim_create_autocmd("TermClose", { group = augroup, callback = function() if vim.v.event.status == 0 then vim.api.nvim_buf_delete(0, {}) end end, }) -- Disable line numbers in terminal vim.api.nvim_create_autocmd("TermOpen", { group = augroup, callback = function() vim.opt_local.number = false vim.opt_local.relativenumber = false vim.opt_local.signcolumn = "no" end, }) -- Auto-resize splits when window is resized vim.api.nvim_create_autocmd("VimResized", { group = augroup, callback = function() vim.cmd("tabdo wincmd =") end, }) local og_virt_text local og_virt_line vim.api.nvim_create_autocmd({ "CursorMoved", "DiagnosticChanged" }, { group = vim.api.nvim_create_augroup("diagnostic_only_virtlines", { clear = true }), callback = function() if og_virt_line == nil then og_virt_line = vim.diagnostic.config().virtual_lines end -- ignore if virtual_lines.current_line is disabled if not (og_virt_line and og_virt_line.current_line) then if og_virt_text then vim.diagnostic.config({ virtual_text = og_virt_text }) og_virt_text = nil end return end if og_virt_text == nil then og_virt_text = vim.diagnostic.config().virtual_text end local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1 if vim.tbl_isempty(vim.diagnostic.get(0, { lnum = lnum })) then vim.diagnostic.config({ virtual_text = og_virt_text }) else vim.diagnostic.config({ virtual_text = false }) end end, }) vim.api.nvim_create_autocmd("LspAttach", { group = vim.api.nvim_create_augroup("lsp-attach", { clear = true }), callback = function(event) local map = function(keys, func, desc) vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc }) end local client = vim.lsp.get_client_by_id(event.data.client_id) if client and client:supports_method("textDocument/implementation") then -- defaults: -- https://neovim.io/doc/user/news-0.11.html#_defaults map("gl", vim.diagnostic.open_float, "Open Diagnostic Float") map("K", vim.lsp.buf.hover, "Hover Documentation") map("gs", vim.lsp.buf.signature_help, "Signature Documentation") map("gD", vim.lsp.buf.declaration, "Goto Declaration") map("la", vim.lsp.buf.code_action, "Code Action") map("lr", vim.lsp.buf.rename, "Rename all references") map("lf", vim.lsp.buf.format, "Format") map( "v", "vsplit | lua vim.lsp.buf.definition()", "Goto Definition in Vertical Split" ) map("gd", vim.lsp.buf.definition, "Goto Definition") map("gr", vim.lsp.buf.references, "Goto References") map("gI", vim.lsp.buf.implementation, "Goto Implementation") end if client and client:supports_method("textDocument/completion") then vim.lsp.completion.enable(true, client.id, event.buf, { autotrigger = true, convert = function(item) return { abbr = item.label:gsub("%b()", "") } end, }) vim.keymap.set("i", "", function() vim.lsp.completion.get() end) client.server_capabilities.completionProvider = client.server_capabilities.completionProvider or {} local trigger_chars = {} for i = 32, 126 do table.insert(trigger_chars, string.char(i)) end client.server_capabilities.completionProvider.triggerCharacters = vim.list_extend( client.server_capabilities.completionProvider.triggerCharacters or {}, trigger_chars ) end if client and client:supports_method("textDocument/formatting") then vim.api.nvim_create_autocmd("BufWritePre", { group = vim.api.nvim_create_augroup("my.lsp", { clear = false }), buffer = event.buf, callback = function() vim.lsp.buf.format({ bufnr = event.buf, id = client.id, timeout_ms = 1000 }) end, }) end if client and client:supports_method("textDocument/inlayHint") then vim.lsp.inlay_hint.enable(true, { bufnr = event.buf }) end if client and client:supports_method("textDocument/documentHighlight") then local highlight_augroup = vim.api.nvim_create_augroup("lsp-highlight", { clear = false }) -- When cursor stops moving: Highlights all instances of the symbol under the cursor -- When cursor moves: Clears the highlighting vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { buffer = event.buf, group = highlight_augroup, callback = vim.lsp.buf.document_highlight, }) vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, { buffer = event.buf, group = highlight_augroup, callback = vim.lsp.buf.clear_references, }) -- When LSP detaches: Clears the highlighting vim.api.nvim_create_autocmd("LspDetach", { group = vim.api.nvim_create_augroup("lsp-detach", { clear = true }), callback = function(event2) vim.lsp.buf.clear_references() vim.api.nvim_clear_autocmds({ group = "lsp-highlight", buffer = event2.buf }) end, }) end end, }) vim.api.nvim_create_autocmd("ModeChanged", { group = vim.api.nvim_create_augroup("diagnostic_redraw", {}), callback = function() pcall(vim.diagnostic.show) end, }) -- terminal local terminal_state = { buf = nil, win = nil, is_open = false, } local function FloatingTerminal() -- If terminal is already open, close it (toggle behavior) if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then vim.api.nvim_win_close(terminal_state.win, false) terminal_state.is_open = false return end -- Create buffer if it doesn't exist or is invalid if not terminal_state.buf or not vim.api.nvim_buf_is_valid(terminal_state.buf) then terminal_state.buf = vim.api.nvim_create_buf(false, true) -- Set buffer options for better terminal experience vim.api.nvim_buf_set_option(terminal_state.buf, "bufhidden", "hide") end -- Calculate window dimensions local width = math.floor(vim.o.columns * 0.8) local height = math.floor(vim.o.lines * 0.8) local row = math.floor((vim.o.lines - height) / 2) local col = math.floor((vim.o.columns - width) / 2) -- Create the floating window terminal_state.win = vim.api.nvim_open_win(terminal_state.buf, true, { relative = "editor", width = width, height = height, row = row, col = col, style = "minimal", border = "rounded", }) -- Set transparency for the floating window vim.api.nvim_win_set_option(terminal_state.win, "winblend", 0) -- Set transparent background for the window vim.api.nvim_win_set_option( terminal_state.win, "winhighlight", "Normal:FloatingTermNormal,FloatBorder:FloatingTermBorder" ) -- Define highlight groups for transparency vim.api.nvim_set_hl(0, "FloatingTermNormal", { bg = "none" }) vim.api.nvim_set_hl(0, "FloatingTermBorder", { bg = "none" }) -- Start terminal if not already running local has_terminal = false local lines = vim.api.nvim_buf_get_lines(terminal_state.buf, 0, -1, false) for _, line in ipairs(lines) do if line ~= "" then has_terminal = true break end end if not has_terminal then vim.fn.termopen(os.getenv("SHELL")) end terminal_state.is_open = true vim.cmd("startinsert") -- Set up auto-close on buffer leave vim.api.nvim_create_autocmd("BufLeave", { buffer = terminal_state.buf, callback = function() if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then vim.api.nvim_win_close(terminal_state.win, false) terminal_state.is_open = false end end, once = true, }) end -- Function to explicitly close the terminal local function CloseFloatingTerminal() if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then vim.api.nvim_win_close(terminal_state.win, false) terminal_state.is_open = false end end -- Key mappings vim.keymap.set( "n", "t", FloatingTerminal, { noremap = true, silent = true, desc = "Toggle floating terminal" } ) vim.keymap.set("t", "", function() if terminal_state.is_open then vim.api.nvim_win_close(terminal_state.win, false) terminal_state.is_open = false end end, { noremap = true, silent = true, desc = "Close floating terminal from terminal mode" })