vim.g.mapleader = " " local map = vim.keymap.set map("n", "", ":nohl", { desc = "Clear search highlighting", silent = true }) map("v", "<", "", ">gv", { desc = "Indent and keep selection" }) map("n", "J", "mzJ`z", { desc = "Join lines without moving cursor" }) map( "n", "ss", [[:%s/\<\>//gI]], { desc = "Replace word cursor is on globally" } ) map("v", "ss", ":s/\\%V", { desc = "Search and replace in visual selection" }) -- general map("n", "$", "g_") map("v", "$", "g_") map("v", ">", ">gv") map("v", "<", "u", function() vim.cmd.packadd("nvim.undotree") require("undotree").open() end, { desc = "Toggle Builtin Undotree" }) map("n", "", "w", { desc = "Save file" }) map("n", "", "%y+", { desc = "Copy whole file" }) map("t", "", "", { desc = "Escape termainl" }) map("n", "tt", ":term", { desc = "Open new terminal" }) -- window navigation map("n", "", "h", { desc = "Switch to left window" }) map("n", "", "j", { desc = "Switch to down window" }) map("n", "", "k", { desc = "Switch to up window" }) map("n", "", "l", { desc = "Switch to right window" }) -- tabs map("n", "tc", ":tabclose", { desc = "Close current tab" }) map("n", "tn", ":tabnew", { desc = "New tab" }) map("n", "]", ":tabnext", { desc = "Next tab" }) map("n", "[", ":tabprevious", { desc = "Previous tab" }) -- yank path map("n", "yp", function() local path = vim.fn.expand("%") vim.fn.setreg("+", path) vim.notify("Copied relative path: " .. path, vim.log.levels.INFO) end, { desc = "Yank relative file path" }) map("n", "yP", function() local path = vim.fn.expand("%:p") vim.fn.setreg("+", path) vim.notify("Copied absolute path: " .. path, vim.log.levels.INFO) end, { desc = "Yank absolute file path" }) -- buffers map("n", "x", function() local buf = vim.api.nvim_get_current_buf() if vim.bo[buf].modified then vim.ui.select({ "Yes", "No" }, { prompt = "Buffer has unsaved changes. Close without saving?", format_item = function(item) return item end, }, function(choice) if choice == "Yes" then vim.api.nvim_buf_delete(buf, { force = true }) end end) else vim.cmd.bdelete() end end, { desc = "Close current buffer" }) map("n", "bn", "enew", { desc = "Buffer new" }) map("n", "bo", function() local current = vim.api.nvim_get_current_buf() local skipped_ft = { "NvimTree", "oil", "aerial" } for _, buf in ipairs(vim.api.nvim_list_bufs()) do if buf ~= current and vim.api.nvim_buf_is_loaded(buf) then local ft = vim.bo[buf].filetype if not vim.tbl_contains(skipped_ft, ft) then vim.api.nvim_buf_delete(buf, { force = true }) end end end end, { desc = "Close other buffers" })