-- Use native Neovim Lua keymap API local keymap = vim.keymap keymap.set("n", "h", "h", { noremap = true, silent = true, desc = "Window left" }) keymap.set("n", "j", "j", { noremap = true, silent = true, desc = "Window down" }) keymap.set("n", "k", "k", { noremap = true, silent = true, desc = "Window up" }) keymap.set("n", "l", "l", { noremap = true, silent = true, desc = "Window right" }) keymap.set("t", "h", [[h]], { noremap = true, silent = true, desc = "Window left" }) keymap.set("t", "j", [[j]], { noremap = true, silent = true, desc = "Window down" }) keymap.set("t", "k", [[k]], { noremap = true, silent = true, desc = "Window up" }) keymap.set("t", "l", [[l]], { noremap = true, silent = true, desc = "Window right" }) local reload = require("utils.reload") vim.api.nvim_create_user_command("ReloadConfig", reload.reload, {}) vim.keymap.set("n", "r", reload.reload, { noremap = true, silent = true, desc = "Reload config" }) keymap.set("n", "?", function() local ok, wk = pcall(require, "which-key") if not ok then vim.notify("which-key is not available", vim.log.levels.WARN) return end local ok_show = pcall(wk.show, { keys = "", mode = "n" }) if not ok_show then vim.cmd("WhichKey ") end end, { noremap = true, silent = true, desc = "Leader keymaps" }) keymap.set("n", "ff", "lua require('telescope.builtin').find_files()", {noremap = true, silent = true, desc = "Find files"}) keymap.set("n", "fg", "lua require('telescope.builtin').live_grep()", {noremap = true, silent = true, desc = "Find text"}) keymap.set("n", "fb", "lua require('telescope.builtin').buffers()", {noremap = true, silent = true, desc = "Find buffers"}) keymap.set("n", "fh", "lua require('telescope.builtin').help_tags()", {noremap = true, silent = true, desc = "Find help"}) keymap.set("n", "xx", "Trouble diagnostics toggle", { noremap = true, silent = true, desc = "Problems toggle" }) keymap.set("n", "xw", "Trouble diagnostics toggle", { noremap = true, silent = true, desc = "Problems workspace diagnostics" }) keymap.set("n", "xb", "Trouble diagnostics toggle filter.buf=0", { noremap = true, silent = true, desc = "Problems buffer diagnostics" }) keymap.set("n", "xq", "Trouble qflist toggle", { noremap = true, silent = true, desc = "Problems quickfix" }) keymap.set("n", "xl", "Trouble loclist toggle", { noremap = true, silent = true, desc = "Problems location list" }) keymap.set("n", "xr", "Trouble lsp_references toggle", { noremap = true, silent = true, desc = "Problems references" }) keymap.set("n", "xs", "Trouble symbols toggle focus=false", { noremap = true, silent = true, desc = "Problems document symbols" }) keymap.set("n", "xS", "Trouble lsp toggle focus=false win.position=right", { noremap = true, silent = true, desc = "Problems workspace symbols" }) local function with_toggleterm(fn) local ok, toggleterm = pcall(require, "plugins.config.toggleterm") if not ok then pcall(function() require("lazy").load({ plugins = { "toggleterm.nvim" } }) end) ok, toggleterm = pcall(require, "plugins.config.toggleterm") end if not ok then vim.notify("toggleterm is not available", vim.log.levels.WARN) return end fn(toggleterm) end keymap.set("n", "mm", function() with_toggleterm(function(toggleterm) toggleterm.toggle_shell() end) end, { noremap = true, silent = true, desc = "Build terminal" }) keymap.set("t", "mm", [[lua require("plugins.config.toggleterm").toggle_shell()]], { noremap = true, silent = true, desc = "Build terminal" }) keymap.set("n", "mc", function() with_toggleterm(function(toggleterm) toggleterm.rerun_last() end) end, { noremap = true, silent = true, desc = "Build rerun last" }) keymap.set("n", "m1", function() with_toggleterm(function(toggleterm) toggleterm.toggle_build_terminal() end) end, { noremap = true, silent = true, desc = "Build toggle terminal" }) keymap.set("t", "m1", [[lua require("plugins.config.toggleterm").toggle_build_terminal()]], { noremap = true, silent = true, desc = "Build toggle terminal" }) keymap.set("n", "m2", function() with_toggleterm(function(toggleterm) toggleterm.toggle_test_terminal() end) end, { noremap = true, silent = true, desc = "Build test terminal" }) keymap.set("t", "m2", [[lua require("plugins.config.toggleterm").toggle_test_terminal()]], { noremap = true, silent = true, desc = "Build test terminal" }) local function with_neotest(fn) local ok, neotest = pcall(require, "neotest") if not ok then vim.notify("neotest is not available", vim.log.levels.WARN) return end fn(neotest) end local function project_root_for_tests() local current_file = vim.api.nvim_buf_get_name(0) local start_path = current_file ~= "" and vim.fs.dirname(current_file) or vim.loop.cwd() local markers = { "CMakePresets.json", "CMakeLists.txt", ".git" } local found = vim.fs.find(markers, { upward = true, path = start_path })[1] if found then return vim.fs.dirname(found) end return vim.loop.cwd() end keymap.set("n", "tt", function() with_neotest(function(neotest) neotest.run.run() end) end, { noremap = true, silent = true, desc = "Tests run nearest" }) keymap.set("n", "tf", function() with_neotest(function(neotest) neotest.run.run(vim.fn.expand("%")) end) end, { noremap = true, silent = true, desc = "Tests run file" }) keymap.set("n", "ta", function() with_neotest(function(neotest) neotest.run.run(project_root_for_tests()) end) end, { noremap = true, silent = true, desc = "Tests run all" }) keymap.set("n", "tg", function() with_toggleterm(function(toggleterm) toggleterm.run_tests() end) end, { noremap = true, silent = true, desc = "Tests run via ctest" }) keymap.set("n", "td", function() with_neotest(function(neotest) neotest.run.run({ strategy = "dap" }) end) end, { noremap = true, silent = true, desc = "Tests debug nearest" }) keymap.set("n", "to", function() with_neotest(function(neotest) neotest.output.open({ enter = true, auto_close = true }) end) end, { noremap = true, silent = true, desc = "Tests open output" }) keymap.set("n", "tp", function() with_neotest(function(neotest) neotest.output_panel.toggle() end) end, { noremap = true, silent = true, desc = "Tests toggle output panel" }) keymap.set("n", "ts", function() with_neotest(function(neotest) neotest.summary.toggle() end) end, { noremap = true, silent = true, desc = "Tests toggle summary" }) keymap.set("n", "tS", function() with_neotest(function(neotest) neotest.run.stop() end) end, { noremap = true, silent = true, desc = "Tests stop" }) vim.keymap.set("n", "gn", vim.diagnostic.goto_next, { noremap = true, silent = true }) local function with_dap(fn) local ok, dap = pcall(require, "dap") if not ok then vim.notify("nvim-dap is not available", vim.log.levels.WARN) return end fn(dap) end local function with_dapui(fn) local ok, dapui = pcall(require, "dapui") if not ok then vim.notify("nvim-dap-ui is not available", vim.log.levels.WARN) return end fn(dapui) end keymap.set("n", "dc", function() with_dap(function(dap) dap.continue() end) end, { noremap = true, silent = true, desc = "Debug continue" }) keymap.set("n", "dr", function() with_dap(function(dap) dap.restart() end) end, { noremap = true, silent = true, desc = "Debug restart" }) keymap.set("n", "dt", function() with_dap(function(dap) dap.terminate() end) end, { noremap = true, silent = true, desc = "Debug terminate" }) keymap.set("n", "dp", function() with_dap(function(dap) dap.pause() end) end, { noremap = true, silent = true, desc = "Debug pause" }) keymap.set("n", "do", function() with_dap(function(dap) dap.step_over() end) end, { noremap = true, silent = true, desc = "Debug step over" }) keymap.set("n", "di", function() with_dap(function(dap) dap.step_into() end) end, { noremap = true, silent = true, desc = "Debug step into" }) keymap.set("n", "dO", function() with_dap(function(dap) dap.step_out() end) end, { noremap = true, silent = true, desc = "Debug step out" }) keymap.set("n", "du", function() with_dap(function(dap) dap.run_to_cursor() end) end, { noremap = true, silent = true, desc = "Debug run to cursor" }) keymap.set("n", "db", function() with_dap(function(dap) dap.toggle_breakpoint() end) end, { noremap = true, silent = true, desc = "Debug toggle breakpoint" }) keymap.set("n", "dB", function() with_dap(function(dap) dap.set_breakpoint(vim.fn.input("Breakpoint condition: ")) end) end, { noremap = true, silent = true, desc = "Debug conditional breakpoint" }) keymap.set("n", "dl", function() with_dap(function(dap) dap.set_breakpoint(nil, nil, vim.fn.input("Log point message: ")) end) end, { noremap = true, silent = true, desc = "Debug logpoint" }) keymap.set("n", "dx", function() with_dap(function(dap) dap.clear_breakpoints() end) end, { noremap = true, silent = true, desc = "Debug clear breakpoints" }) keymap.set("n", "dd", function() with_dapui(function(dapui) dapui.toggle() end) end, { noremap = true, silent = true, desc = "Debug toggle UI" }) keymap.set("n", "de", function() with_dapui(function(dapui) dapui.eval() end) end, { noremap = true, silent = true, desc = "Debug eval" }) keymap.set("n", "dh", function() with_dap(function() require("dap.ui.widgets").hover() end) end, { noremap = true, silent = true, desc = "Debug hover" }) keymap.set("n", "dq", function() with_dap(function(dap) dap.repl.open() end) end, { noremap = true, silent = true, desc = "Debug open REPL" }) keymap.set("n", "dQ", function() with_dap(function(dap) dap.repl.toggle() end) end, { noremap = true, silent = true, desc = "Debug toggle REPL" }) keymap.set("n", "ds", function() with_dap(function(dap) local session = dap.session() if session then vim.notify("DAP session active", vim.log.levels.INFO) else vim.notify("No active DAP session", vim.log.levels.WARN) end end) end, { noremap = true, silent = true, desc = "Debug session status" }) keymap.set("n", "df", "Telescope dap frames", { noremap = true, silent = true, desc = "Debug frames" }) keymap.set("n", "dC", "Telescope dap commands", { noremap = true, silent = true, desc = "Debug commands" }) keymap.set("n", "dv", "Telescope dap variables", { noremap = true, silent = true, desc = "Debug variables" }) keymap.set("n", "dR", "Telescope dap configurations", { noremap = true, silent = true, desc = "Debug configurations" }) keymap.set("n", "dK", "Telescope dap list_breakpoints", { noremap = true, silent = true, desc = "Debug breakpoints" }) keymap.set("n", "cg", "CMakeGenerate", { noremap = true, silent = true, desc = "CMake generate" }) keymap.set("n", "cb", function() with_toggleterm(function(toggleterm) toggleterm.run_build() end) end, { noremap = true, silent = true, desc = "CMake build (terminal)" }) keymap.set("n", "cB", "CMakeBuild!", { noremap = true, silent = true, desc = "CMake clean build" }) keymap.set("n", "cc", "CMakeClean", { noremap = true, silent = true, desc = "CMake clean" }) keymap.set("n", "ct", "CMakeSelectBuildTarget", { noremap = true, silent = true, desc = "CMake select build target" }) keymap.set("n", "cT", "CMakeSelectBuildType", { noremap = true, silent = true, desc = "CMake select build type" }) keymap.set("n", "cr", "CMakeRun", { noremap = true, silent = true, desc = "CMake run" }) keymap.set("n", "cd", "CMakeDebug", { noremap = true, silent = true, desc = "CMake debug" }) keymap.set("n", "cL", "CMakeSelectLaunchTarget", { noremap = true, silent = true, desc = "CMake select launch target" }) keymap.set("n", "cS", "CMakeSettings", { noremap = true, silent = true, desc = "CMake settings" })