diff --git a/init.lua b/init.lua index bacf2bb..f5f56a7 100644 --- a/init.lua +++ b/init.lua @@ -8,4 +8,29 @@ vim.g.blamer_template = ", • " -- Example: C vim.g.blamer_relative_time = true vim.g.blamer_enabled = true vim.g.blamer_show_in_visual_modes = 0 +vim.opt.shell = "bash" +vim.opt.termguicolors = true + + +-- Create a custom :term command that passes Kitty's custom environment variables +vim.api.nvim_create_user_command("Term", function() + -- 1. Grab Kitty's installation path from your current terminal environment + local kitty_install = os.getenv("KITTY_INSTALLATION_DIR") + + -- 2. Build the manual injection loader path Kitty requires + local kitty_bash_injection = kitty_install and (kitty_install .. "/shell-integration/bash/kitty.bash") or "" + + -- 3. Open a clean terminal, tell Kitty it is safe to interact, and map it + if kitty_install ~= nil and kitty_install ~= "" then + -- Run Bash but explicitly inject the environment loader before anything else handles it + vim.cmd(string.format("terminal env KITTY_SHELL_INTEGRATION=enabled bash --rcfile %s -i", kitty_bash_injection)) + else + -- Fallback safe method if Kitty environment path variables are empty + vim.cmd("terminal bash -il") + end +end, { force = true }) +-- Make sure lowercase ':term' also maps to our special alignment function +vim.cmd([[cabbrev term Term]]) + + require("config.lazy") diff --git a/lazy-lock.json b/lazy-lock.json index e9f986d..f381752 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,11 +1,11 @@ { - "Aquavium.nvim": { "branch": "main", "commit": "d007badfa5920cb50e136d30a3edf4342093d6b5" }, - "alpha-nvim": { "branch": "main", "commit": "6c6a89d5b068b5251c8bdf0dd57bb921bcfeeb09" }, + "Aquavium.nvim": { "branch": "main", "commit": "ff76f104f00fdbbe7885398ea13a3baac0cd96a0" }, + "alpha-nvim": { "branch": "main", "commit": "4ba26e41990c11620c96c0e1cff20eab65efde4a" }, "barbar.nvim": { "branch": "master", "commit": "53b5a2f34b68875898f0531032fbf090e3952ad7" }, "blamer.nvim": { "branch": "master", "commit": "e0d43c11697300eb68f00d69df8b87deb0bf52dc" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, - "bluloco.nvim": { "branch": "main", "commit": "294aa5ac5e639f36ab5db9729ac7583c37d896dc" }, - "codecompanion.nvim": { "branch": "main", "commit": "d4c00c29ffa49a9eda117099916168e32aa12e09" }, + "bluloco.nvim": { "branch": "main", "commit": "912227935d63766fe11e4168840063bd2e9a4274" }, + "codecompanion.nvim": { "branch": "main", "commit": "86118411be00f0451a59c5ef7972c437e979e1b7" }, "conform.nvim": { "branch": "master", "commit": "016802de402556da54c36bd7359b441266b01cdd" }, "contextfiles.nvim": { "branch": "main", "commit": "d5d0525c32777366e5c415fdb682444ce9f753f8" }, "csvview.nvim": { "branch": "main", "commit": "f190de76d2eca0380ddcb2425cd582d740699b55" }, @@ -14,38 +14,38 @@ "everforest-nvim": { "branch": "main", "commit": "a0e9edc57379e8feafc6ba207c26dbb12fc1b6d8" }, "farba.nvim": { "branch": "main", "commit": "a15528695f38a44ba2974b9aae5d6ddf8c694ea2" }, "fidget.nvim": { "branch": "main", "commit": "9e0201673e08e997e7cf52afca5565c70bd117f3" }, - "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "fzf-lua": { "branch": "main", "commit": "05e44d38de0a79c11fba5f7bf8138791b1dbdd1e" }, - "gitsigns.nvim": { "branch": "main", "commit": "5be654f2232c10ddcad19c1607a67b6b4b78fc29" }, + "friendly-snippets": { "branch": "main", "commit": "b4d01b0fdf3c9a549961c2f9ffe8dc09be166219" }, + "fzf-lua": { "branch": "main", "commit": "c67fadd9a24230417267e4f9068227e093c0be2b" }, + "gitsigns.nvim": { "branch": "main", "commit": "fd780920613e541cbdfac41bf711583ed49f9249" }, "gruvbox-material": { "branch": "master", "commit": "11d779b26a9ab2b3db8c22c6ac9fb6e8ed4fea79" }, - "indent-blankline.nvim": { "branch": "master", "commit": "3b1ee1854c1067c34cad2423eb78e280d4069e01" }, + "indent-blankline.nvim": { "branch": "master", "commit": "f1e186e44d3b7f9ae918008e2c28ce37c6023d2d" }, "kanagawa.nvim": { "branch": "master", "commit": "bb85e4bfc8d89b0e62c8fa53ccdd13d12e2f77b3" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, - "lazygit.nvim": { "branch": "main", "commit": "a04ad0dbc725134edbee3a5eea29290976695357" }, + "lazygit.nvim": { "branch": "main", "commit": "9ffc6103926718f7070fb4017694543cd7dc9718" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, "lush.nvim": { "branch": "main", "commit": "9c60ec2279d62487d942ce095e49006af28eed6e" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "40276c4df7e6bdce6801d6c035c6227f9115a855" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "00b5473cca4db5b410ff4bae724e3b6e21f2687f" }, "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, "material.nvim": { "branch": "main", "commit": "92f7366a9315cd386bc4fa4d716fde375dda210f" }, - "mini.icons": { "branch": "main", "commit": "98faae31e9be1cc054ae63485e58ceb185efcad0" }, + "mini.icons": { "branch": "main", "commit": "f916635dc5ae2f479fbb9ab8184bb9444b62e86c" }, "neovim": { "branch": "main", "commit": "ff483051a47e27d84bdef47703538df1ed9f4a47" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "10fc361835c856ba4233ef5ea135b919bf3dce97" }, "nvim-cmp": { "branch": "main", "commit": "2ffe79f1f021def8dd1fcd81deb16f1bb0d989f3" }, "nvim-colorizer.lua": { "branch": "master", "commit": "72a05f62c52241bc7441c820eb53946f92b2e6a4" }, - "nvim-dap": { "branch": "master", "commit": "c9a0738e45f1bd41d792a126941348dce661cf9b" }, + "nvim-dap": { "branch": "master", "commit": "cfa2d58f4537aca6ca83e2de1a0d9f1491121264" }, "nvim-dap-ui": { "branch": "master", "commit": "cc9dd33aade7f20bae414d0cba163bc60d4d4b43" }, "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, - "nvim-lspconfig": { "branch": "master", "commit": "85e732c62ac59ab7c12df71ddd020baa87948390" }, + "nvim-lspconfig": { "branch": "master", "commit": "45a3a444b710511c39abca3b60bb6e23a21e3de5" }, "nvim-nio": { "branch": "master", "commit": "edcc181a875301dd21840189aa2f2f9ad69fc172" }, "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" }, - "nvim-treesitter": { "branch": "main", "commit": "427e9222363d07c32d6db6169e4049c28d58d141" }, - "nvim-web-devicons": { "branch": "master", "commit": "5f032a85be210cd1c6ac98861eb3b187ff3bd5eb" }, - "oil.nvim": { "branch": "master", "commit": "b73018b75affd13fa38e2fc94ef753b465f770d7" }, + "nvim-treesitter": { "branch": "main", "commit": "29212d826054bb2948fa9d3a99eca9bf6a050eb2" }, + "nvim-web-devicons": { "branch": "master", "commit": "ec309a0eaff6ea967e58c275996155ab5c16938d" }, + "oil.nvim": { "branch": "master", "commit": "d3733d933833a0e59b813ecec99341527adf0c28" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, - "render-markdown.nvim": { "branch": "main", "commit": "4663eb3ecd538bd5062628fb6d95bbe6bdca78f6" }, + "render-markdown.nvim": { "branch": "main", "commit": "8e8795368391036643b622875a6da6a51bcd33f4" }, "telescope.nvim": { "branch": "master", "commit": "40aedd8a68c78a656a10a8d62d80c54af59420fb" }, "venv-selector.nvim": { "branch": "main", "commit": "cc4bb3975de8835291f9bb45889e96c6b2795fc4" }, "vesper.nvim": { "branch": "main", "commit": "1717b1ad657c94bec3fc2bdebb0c55452d9fe46d" }, diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index 8818478..49ad155 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -5,6 +5,22 @@ vim.keymap.set({"n", "v"}, "", "18j", {desc = "Fast scroll down"}) vim.keymap.set({"n", "v"}, "", "18k", {desc = "Fast scroll up"}) vim.keymap.set("n", "h", ":noh", {desc = "Remove current highlighting"}) +-- Exit terminal mode easily with Escape +vim.keymap.set('t', '', [[]], { desc = 'Exit terminal mode' }) + +-- In lazygit, keep every key inside the terminal so only Ctrl+C (handled by +-- lazygit itself) can close it -- no nvim key drops you into normal mode. +vim.api.nvim_create_autocmd("TermOpen", { + callback = function() + if vim.fn.expand("%"):match("lazygit") then + -- let pass through to lazygit instead of exiting terminal mode + vim.keymap.set('t', '', '', { buffer = true }) + -- disable the built-in exit-terminal-mode chord + vim.keymap.set('t', [[]], '', { buffer = true }) + end + end, +}) + vim.keymap.set("v", "y", '"+y', {desc='Yank to "+ register for external copy/paste'}) --CODE/LSP @@ -41,9 +57,24 @@ vim.keymap.set("n", "f", ":lua require('conform').format()") local status_ok, dap = pcall(require, "dap") if status_ok then vim.keymap.set("n", "cdb", dap.toggle_breakpoint, { desc = "Debug: Toggle Breakpoint" }) - vim.keymap.set("n", "cdc", dap.continue, { desc = "Debug: Start/Continue" }) + --vim.keymap.set("n", "cdc", dap.continue, { desc = "Debug: Start/Continue" }) + -- new start debug keymap in debugger.lua vim.keymap.set("n", "cdi", dap.step_into, { desc = "Debug: Step Into" }) - vim.keymap.set("n", "cdo", dap.step_over, { desc = "Debug: Step Over" }) - vim.keymap.set("n", "cdO", dap.step_out, { desc = "Debug: Step Out" }) + vim.keymap.set("n", "cdn", dap.step_over, { desc = "Debug: Step Over" }) + vim.keymap.set("n", "cdO", dap.step_out, { desc = "Debug: Step Out" }) vim.keymap.set("n", "cdt", dap.terminate, { desc = "Debug: Terminate" }) + + vim.keymap.set("n", "cdr", dap.restart, { desc = "Debug: Restart" }) + vim.keymap.set("n", "cdp", dap.pause, { desc = "Debug: Pause" }) + vim.keymap.set("n", "cd[", dap.up, { desc = "Debug: Callstack up" }) + vim.keymap.set("n", "cd]", dap.down, { desc = "Debug: Callstack down" }) + vim.keymap.set("n", "cdh", function() + require("dap.ui.widgets").hover() + end, { desc = "DAP: Hover Variable Value" }) + vim.keymap.set("n", "cdu", function() + require("dapui").toggle() + end, { desc = "Debug: Toggle UI" }) + vim.keymap.set("n", "cdw", function() + require("dapui").elements.watches.add(vim.fn.expand("")) + end, { desc = "DAP Add Watch under cursor" }) end diff --git a/lua/config/lazy.lua b/lua/config/lazy.lua index 540fa26..7db2f35 100644 --- a/lua/config/lazy.lua +++ b/lua/config/lazy.lua @@ -45,6 +45,9 @@ require("lazy").setup({ }) vim.cmd("colorscheme " .. colScheme.name); vim.api.nvim_set_hl(0, "alphaheader", {fg = "#3661cf" }) +if (colScheme.name == "rose-pine") then + vim.api.nvim_set_hl(0, "NotifyBackground", { bg = "#232136" }) +end --setup colour indents local highlight = { diff --git a/lua/ignoreConfig/colourConfig.lua.example b/lua/ignoreConfig/colourConfig.lua.example index eaf3163..349ced0 100644 --- a/lua/ignoreConfig/colourConfig.lua.example +++ b/lua/ignoreConfig/colourConfig.lua.example @@ -1,6 +1,37 @@ + +local everforest = { + transparent = 0,--0, 1 or 2, least to most transparent +} + +local kanagawa = { + transparent = true, +} + +local marterial = { + disable = { + background = true, + } +} + +local rosepine = { + styles = { + transparency = true, + } +} + +local gruvbox = { + transparent = 1, +} + local opts = { - name = "everforest", - transparent = 0 + name = "rose-pine", + opts = { + everforest=everforest, + kanagawa=kanagawa, + marterial=material, + rosepine=rosepine, + gruvbox=gruvbox, + } } return opts diff --git a/lua/plugins/colourscheme.lua b/lua/plugins/colourscheme.lua index b77d5cf..558fd68 100644 --- a/lua/plugins/colourscheme.lua +++ b/lua/plugins/colourscheme.lua @@ -10,7 +10,7 @@ local material = { --vim.g.material_style = "palenight" material.setup({ lualine_style = "default", -- Lualine style ( can be 'stealth' or 'default' ) - disable = ignores[1], + disable = ignores.opts.material.disable, custom_highlights = { Comment = { fg = "#b7b0bf" }, LineNr = { fg = "#b7b0bf" }, @@ -54,7 +54,7 @@ local kanagawa = { theme = "lotus", compile = true, commentStyle = { italic = true }, - transparent = ignores.transparent, + transparent = ignores.opts.kanagawa.transparent, colors = { --palette = { -- -- change all usages of these colors @@ -96,7 +96,7 @@ local everforest = { local ignore = require('ignoreConfig.colourConfig'); everforest.setup({ background = "hard", - transparent_background_level = ignore.transparent, + transparent_background_level = ignore.opts.everforest.transparent, italics = true, }); @@ -113,17 +113,18 @@ local rosepine = { lazy = true, config = function() local rosepine = require("rose-pine"); + local ignore = require('ignoreConfig.colourConfig'); rosepine.setup({ variant = "moon", -- Options: "main", "moon", "dawn" dark_variant = "moon", - bold_vert_split = false, - dim_nc_background = false, - disable_background = false, - disable_float_background = false, - disable_italics = false, + styles = { + bold = true, + italic = true, + transparency = ignore.opts.rosepine.styles.transparency, + }, groups = { - background = "base", + --background = "base", panel = "surface", border = "highlight_low", comment = "muted", @@ -299,8 +300,10 @@ local gruvbox = { lazy = false, priority = 1000, config = function() + local ignores = require('ignoreConfig.colourConfig') -- Optionally configure and load the colorscheme -- directly inside the plugin declaration. + vim.g.gruvbox_material_transparent_background = ignores.opts.gruvbox.transparent vim.g.gruvbox_material_enable_italic = true --vim.cmd.colorscheme('gruvbox-material') end diff --git a/lua/plugins/debugger.lua b/lua/plugins/debugger.lua index 5dad865..5bfd5e3 100644 --- a/lua/plugins/debugger.lua +++ b/lua/plugins/debugger.lua @@ -1,3 +1,112 @@ + +local function fzf_pick_executable() + return coroutine.create(function(coro) + local current_cwd = vim.fn.getcwd():gsub("\\", "/") + + require("fzf-lua").files({ + cwd = current_cwd, + cmd = "fd --type x --hidden --no-ignore", + + previewer = false, + header = false, + prompt = "Select Executable ❯ ", + + winopts = { + title = " Select Executable ", + title_pos = "center", + height = 0.40, + width = 0.60, + }, + + actions = { + ["default"] = function(selected) + if selected and selected[1] then + -- 1. Strip icons and formatting spaces to isolate the file string + local entry = require("fzf-lua.path").entry_to_file(selected[1], { cwd = current_cwd }) + + -- 2. Automatically resolve it to an absolute path (handles relative or absolute safely) + local full_path = vim.fn.fnamemodify(entry.path, ":p") + + -- 3. Clean up slashes and hand it to DAP + coroutine.resume(coro, full_path:gsub("\\", "/")) + else + coroutine.resume(coro, vim.fn.empty()) + end + end + } + }) + end) +end + + +local function start_debug_session() + + + local is_windows = vim.fn.has("win32") == 1 + local dap = require("dap") + -- 3. Platform-agnostic Launcher Configuration + if not is_windows then + dap.configurations.cpp = { + { + name = "Launch file", + type = "codelldb", + request = "launch", + program = fzf_pick_executable, + cwd = '${workspaceFolder}', + stopOnEntry = false, + args = {}, + }, + } + else + local vscode = require('dap.ext.vscode') + local launch_json = vim.fn.getcwd() .. "/.vscode/launch.json" + if vim.fn.filereadable(launch_json) == 1 then + dap.configurations.cpp = {} + dap.configurations.c = {} + -- 1. CRUCIAL FIX: Alias the adapters directly so nvim-dap doesn't complain about a missing engine + --if dap.adapters.cppdbg then + -- dap.adapters.cppvsdbg = dap.adapters.cppdbg + --elseif dap.adapters.codelldb then + -- dap.adapters.cppvsdbg = dap.adapters.codelldb + --end + -- 2. Map types inside launch.json to your C++ filetypes + vscode.type_to_filetypes = { + cppvsdbg = { "cpp", "c" }, + cppdbg = { "cpp", "c" }, + codelldb = { "cpp", "c" }, + } + else + -- No launch.json exists. Re-inject your FZF picker template rules + dap.configurations.cpp = { + { + name = "Launch file", + type = "cppdbg", + request = "launch", + program = fzf_pick_executable, + cwd = "${workspaceFolder}", + stopOnEntry = false, + + -- Crucial configurations for Microsoft cpptools: + -- On Windows, this automatically uses MinGW/MSVC underlying debugger engines + MIMode = is_windows and "gdb" or "lldb", + miDebuggerPath = is_windows and "gdb.exe" or nil, -- Uses system path for gdb on Windows + + setupCommands = { + { + text = "-enable-pretty-printing", + description = "enable pretty printing", + ignoreFailures = false, + }, + }, + }, + } + end + end + dap.continue() +end + +vim.keymap.set("n", "cdc", start_debug_session, { desc = "Debug: Start/Continue with Smart Config" }) + return { "mfussenegger/nvim-dap", dependencies = { @@ -15,48 +124,207 @@ return { dapui.setup() require("nvim-dap-virtual-text").setup() + -- The dap-ui "disconnect" control (the plug icon) and dap.disconnect in + -- general send a DAP `disconnect` request. With the codelldb server + -- adapter that path crashes the adapter + -- (STATUS_ACCESS_VIOLATION / 0xC0000005, see dap.log) while the inferior + -- is still attached, and on Windows that takes Neovim down with it. + -- + -- The `terminate` request path (the square Stop button / cdt) + -- tears the inferior down cleanly first, so codelldb's crash on the way + -- out is harmless. Route the disconnect control through terminate too. + -- (_G._dapui is created when dapui.controls is required; force-load it so + -- the override is in place before the controls winbar renders.) + require("dapui.controls") + _G._dapui.disconnect = function() + dap.terminate() + end + -- Automatically manage debugger installations via Mason require("mason-nvim-dap").setup({ - ensure_installed = { "codelldb" }, -- Auto-installs CodeLLDB + ensure_installed = { "codelldb", "cppdbg" }, -- Auto-installs CodeLLDB automatic_installation = true, }) -- Automatically open/close DAP UI panels - dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end - dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end - dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end + -- Defer the open so nvim-dap-ui's async (nio) element buffers are ready. + -- Opening synchronously from inside the DAP event listener races buffer + -- creation and throws "layout.lua: Invalid buffer id: -1". + dap.listeners.after.event_initialized["dapui_config"] = function() + vim.schedule(function() dapui.open() end) + end + dap.listeners.before.event_terminated["dapui_config"] = function() + vim.schedule(function() dapui.close() end) + end + dap.listeners.before.event_exited["dapui_config"] = function() + vim.schedule(function() dapui.close() end) + end -- Step 2 & 3 configurations will go here... - -- Define the adapter connection + -- 1. Detect operating system + local is_windows = vim.fn.has("win32") == 1 + local ext = is_windows and ".exe" or "" + + -- 2. Platform-agnostic CodeLLDB Adapter setup + local mason_registry = require("mason-registry") + local codelldb = mason_registry.get_package("codelldb") + local extension_path = codelldb:get_install_path() .. "/extension/" + + -- CodeLLDB executable is in different subfolders depending on Mason's package version + local codelldb_path = extension_path .. "adapter/codelldb" .. ext + + + local cpptools_pkg = mason_registry.get_package("cpptools") + local cpptools_path = cpptools_pkg:get_install_path() + .. "/extension/debugAdapters/bin/OpenDebugAD7" + .. ext + + dap.adapters.codelldb = { type = 'server', port = "${port}", executable = { - -- Adjust this path if Mason uses a different default location on your OS - command = vim.fn.stdpath("data") .. "/mason/bin/codelldb", + command = codelldb_path, args = {"--port", "${port}"}, + -- Keep the spawned server (and any inferior it launches) off + -- Neovim's console group so terminating a session can't take + -- Neovim down on Windows. Matches the cppvsdbg adapter above. + detached = true, } } - -- Configure C++ configurations - dap.configurations.cpp = { - { - name = "Launch file", - type = "codelldb", - request = "launch", - program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') - end, - cwd = '${workspaceFolder}', - stopOnEntry = false, - args = {}, + dap.adapters.cppdbg = { + id = "cppdbg", + type = "executable", + command = cpptools_path, + -- Must stay detached (the default) so the adapter + gdb + debuggee + -- run in their own process group. With detached=false on Windows + -- they share Neovim's console group, so terminating the session + -- (dap.terminate) sends the Ctrl-C/terminate signal to Neovim too. + options = { + detached = true, }, } - -- Re-use C++ configuration for C language + -- Route MSVC `cppvsdbg` launch configs (as VS/msbuild launch.json + -- generates) to codelldb. We deliberately do NOT use Microsoft's vsdbg: + -- its license permits use only within Visual Studio / VS Code. codelldb + -- is LLVM/LLDB-based (Apache-2.0) and has a native PDB reader, so it can + -- debug MSVC/msbuild binaries without that restriction. + -- + -- codelldb is a TCP `server` adapter, so terminating/disconnecting + -- talks over a socket and can't broadcast a console CTRL event to + -- Neovim the way the gdb-backed cppdbg path does. detached=true keeps + -- the spawned server (and the inferior it launches) off Neovim's + -- console group too -- the original `detached = false` is what still + -- let a disconnect take Neovim down. + dap.adapters.cppvsdbg = { + type = "server", + port = "${port}", + executable = { + command = codelldb_path, + args = { "--port", "${port}" }, + detached = true, + }, + } + + -- 3. Platform-agnostic Launcher Configuration + if not is_windows then + dap.configurations.cpp = { + { + name = "Launch file", + type = "codelldb", + request = "launch", + program = fzf_pick_executable, + cwd = '${workspaceFolder}', + stopOnEntry = false, + args = {}, + }, + } + else + dap.configurations.cpp = { + { + name = "Launch file", + type = "cppdbg", + request = "launch", + program = fzf_pick_executable, + cwd = "${workspaceFolder}", + stopOnEntry = false, + + -- Crucial configurations for Microsoft cpptools: + -- On Windows, this automatically uses MinGW/MSVC underlying debugger engines + MIMode = is_windows and "gdb" or "lldb", + miDebuggerPath = is_windows and "gdb.exe" or nil, -- Uses system path for gdb on Windows + + setupCommands = { + { + text = "-enable-pretty-printing", + description = "enable pretty printing", + ignoreFailures = false, + }, + }, + }, + } + end + dap.configurations.c = dap.configurations.cpp + -- Unity (Mono soft debugger) via Unity's MIT-licensed vscode-unity-debug + -- adapter, extracted from its .vsix into stdpath("data")/unity-debug. + -- Avoids vstuc, whose license (like vsdbg's) is VS Code only. + -- + -- UnityDebug.exe is patched by unity-debug/install.sh (see patch.cs there; + -- original kept as UnityDebug.exe.orig): stock, it only matches editor + -- processes named exactly "Unity"/"Unity Editor", but Unity Hub launches + -- the editor as "unityhub-unity-editor-". The patch makes it a + -- case-insensitive "Unity" prefix match, covering both launch methods and + -- any version. Helper processes (UnityPackageManager, import workers...) + -- match too, so the adapter picks the real editor by the process_id in + -- EditorInstance.json -- which needs the config name to contain "Editor". + local unity_debug_exe = vim.fn.stdpath("data") .. "/unity-debug/extension/bin/UnityDebug.exe" + local unity_debug_install = vim.fn.stdpath("config") .. "/unity-debug/install.sh" + dap.adapters.unity = function(callback) + if vim.fn.filereadable(unity_debug_exe) == 0 then + vim.notify("Installing Unity debug adapter...") + local result = vim.system({ unity_debug_install }, { text = true }):wait() + if result.code ~= 0 then + vim.notify("Unity debug adapter install failed:\n" .. result.stderr, vim.log.levels.ERROR) + return + end + end + callback({ + type = "executable", + command = "mono", + args = { unity_debug_exe }, + -- The adapter strips the leading "/" from `path` (a Windows-ism) + -- before reading it, so run it from / for the now-relative path + -- to resolve. + options = { cwd = "/" }, + }) + end + -- Library/EditorInstance.json only exists while the editor is open; the + -- adapter reads the editor PID from it to derive the debugger port. + -- The Unity project may sit in a repo subfolder, so search upward from + -- the buffer first, then downward from cwd. + local function unity_editor_instance() + local root = vim.fs.root(0, "ProjectSettings") + if root then + return root .. "/Library/EditorInstance.json" + end + local found = vim.fs.find("EditorInstance.json", { path = vim.fn.getcwd(), type = "file", limit = 1 }) + return found[1] + end + + dap.configurations.cs = { + { + name = "Unity Editor", + type = "unity", + request = "launch", -- unity-debug attaches to the running editor despite "launch" + path = unity_editor_instance, + }, + } end } + diff --git a/lua/plugins/nvim-treesitter.lua b/lua/plugins/nvim-treesitter.lua index 89ea397..09d03ff 100644 --- a/lua/plugins/nvim-treesitter.lua +++ b/lua/plugins/nvim-treesitter.lua @@ -20,5 +20,29 @@ return { sync_install = false, highlight = { enable = true }, indent = { enable = true }, + + + -- Enable the textobjects extension + textobjects = { + move = { + enable = true, + set_jumps = true, -- Add jumps to the jumplist (:h jumplist) + + goto_next_start = { + ["]]"] = { query = "@function.outer", desc = "Next function definition start" }, + ["]c"] = { query = "@class.outer", desc = "Next class definition start" }, + }, + goto_previous_start = { + ["[["] = { query = "@function.outer", desc = "Previous function definition start" }, + ["[c"] = { query = "@class.outer", desc = "Previous class definition start" }, + }, + goto_next_end = { + ["]f"] = { query = "@function.outer", desc = "Next function definition end" }, + }, + goto_previous_end = { + ["[f"] = { query = "@function.outer", desc = "Previous function definition end" }, + }, + }, + }, }, } diff --git a/lua/pluginsLate/alpha.lua b/lua/pluginsLate/alpha.lua index f93432d..f23a1e7 100644 --- a/lua/pluginsLate/alpha.lua +++ b/lua/pluginsLate/alpha.lua @@ -38,9 +38,6 @@ return { dashboard.button("l", " Lazy settings", ":Lazy"), dashboard.button("q", "󰅚 quit nvim", ":qa"), } - local handle = io.popen('fortune') - local fortune = handle:read("*a") - handle:close() dashboard.section.footer.val = { [["we define the boundaries of reality;]], [[they don't define us."]], diff --git a/unity-debug/install.sh b/unity-debug/install.sh new file mode 100755 index 0000000..ff9bcb4 --- /dev/null +++ b/unity-debug/install.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Installs Unity's MIT-licensed vscode-unity-debug adapter for nvim-dap and +# patches it to find editors however they were launched (see patch.cs). +# Re-runnable: always re-extracts and re-patches from the pristine .vsix. +set -euo pipefail + +VERSION=3.0.1 +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DEST="${1:-${XDG_DATA_HOME:-$HOME/.local/share}/nvim/unity-debug}" +BIN="$DEST/extension/bin" + +for cmd in curl unzip mono mcs; do + command -v "$cmd" >/dev/null || { echo "unity-debug install: missing '$cmd'" >&2; exit 1; } +done + +mkdir -p "$DEST" +VSIX="$DEST/unity-debug-$VERSION.vsix" +[ -f "$VSIX" ] || curl -fsSL -o "$VSIX" \ + "https://github.com/Unity-Technologies/vscode-unity-debug/releases/download/Version-$VERSION/unity-debug-$VERSION.vsix" +rm -rf "$DEST/extension" +unzip -qo "$VSIX" -d "$DEST" + +TMP="$(mktemp -d)" +trap 'rm -rf "$TMP"' EXIT +mcs "$HERE/patch.cs" -r:"$BIN/Mono.Cecil.dll" -out:"$TMP/patch.exe" +cp "$BIN/UnityDebug.exe" "$BIN/UnityDebug.exe.orig" +MONO_PATH="$BIN" mono "$TMP/patch.exe" "$BIN/UnityDebug.exe.orig" "$TMP/UnityDebug.exe" +cp "$TMP/UnityDebug.exe" "$BIN/UnityDebug.exe" +echo "unity-debug installed and patched in $DEST" diff --git a/unity-debug/patch.cs b/unity-debug/patch.cs new file mode 100644 index 0000000..e5a85e3 --- /dev/null +++ b/unity-debug/patch.cs @@ -0,0 +1,20 @@ +// Patches vscode-unity-debug's UnityProcessDiscovery.GetUnityEditorProcesses to +// prefix-match process names instead of requiring an exact "Unity"/"Unity Editor". +// The comparison is OrdinalIgnoreCase, so the "Unity" prefix then matches editors +// launched directly ("Unity") and via Unity Hub ("unityhub-unity-editor-"). +// Extra matches (UnityPackageManager etc.) are fine: with a config name containing +// "Editor", the adapter picks the editor by process_id from EditorInstance.json. +using System; using System.Linq; using Mono.Cecil; +class Patch { + static int Main(string[] a) { + var asm = AssemblyDefinition.ReadAssembly(a[0]); + var m = asm.MainModule.Types.SelectMany(t => t.Methods).Single(x => x.Name == "GetUnityEditorProcesses"); + var startsWith = asm.MainModule.ImportReference(typeof(string).GetMethod("StartsWith", new[] { typeof(string), typeof(StringComparison) })); + int c = 0; + foreach (var i in m.Body.Instructions) + if (i.Operand is MethodReference r && r.DeclaringType.FullName == "System.String" && r.Name == "Equals" && r.Parameters.Count == 2) { i.Operand = startsWith; c++; } + if (c != 1) { Console.Error.WriteLine($"expected 1 string.Equals call in {m.Name}, found {c}"); return 1; } + asm.Write(a[1]); + return 0; + } +}