diff --git a/desktop environment/.config/.DS_Store b/desktop environment/.config/.DS_Store new file mode 100644 index 000000000..8c8db36af Binary files /dev/null and b/desktop environment/.config/.DS_Store differ diff --git a/desktop environment/.config/wallpapers/gradient-synth-cat.png b/desktop environment/.config/wallpapers/gradient-synth-cat.png new file mode 100644 index 000000000..d332e1cf0 Binary files /dev/null and b/desktop environment/.config/wallpapers/gradient-synth-cat.png differ diff --git a/nvim/.config/lazygit/config.yml b/nvim/.config/lazygit/config.yml index 9b416c55c..f261a3b89 100644 --- a/nvim/.config/lazygit/config.yml +++ b/nvim/.config/lazygit/config.yml @@ -1,26 +1,31 @@ gui: - nerdFontsVersion: "3" - theme: - activeBorderColor: - - '#74c7ec' - - bold - inactiveBorderColor: - - '#a6adc8' - optionsTextColor: - - '#89b4fa' - selectedLineBgColor: - - '#313244' - cherryPickedCommitBgColor: - - '#45475a' - cherryPickedCommitFgColor: - - '#74c7ec' - unstagedChangesColor: - - '#f38ba8' - defaultFgColor: - - '#cdd6f4' - searchingActiveBorderColor: - - '#f9e2af' + nerdFontsVersion: "3" + theme: + activeBorderColor: + - "#f2cdcd" + - bold + inactiveBorderColor: + - "#a6adc8" + searchingActiveBorderColor: + - "#f9e2af" + optionsTextColor: + - "#89b4fa" + selectedLineBgColor: + - "#313244" + inactiveViewSelectedLineBgColor: + - "#6c7086" + cherryPickedCommitFgColor: + - "#f2cdcd" + cherryPickedCommitBgColor: + - "#45475a" + markedBaseCommitFgColor: + - "#89b4fa" + markedBaseCommitBgColor: + - "#f9e2af" + unstagedChangesColor: + - "#f38ba8" + defaultFgColor: + - "#cdd6f4" authorColors: - '*': '#b4befe' - + "*": "#b4befe" diff --git a/nvim/.config/nvim/lazy-lock.json b/nvim/.config/nvim/lazy-lock.json index c7468e5f6..ebcdb2a37 100644 --- a/nvim/.config/nvim/lazy-lock.json +++ b/nvim/.config/nvim/lazy-lock.json @@ -1,45 +1,54 @@ { - "LazyVim": { "branch": "main", "commit": "28db03f958d58dfff3c647ce28fdc1cb88ac158d" }, - "SchemaStore.nvim": { "branch": "main", "commit": "c103ea363c4776ea9079eccaae54b42aa537a80e" }, - "avante.nvim": { "branch": "main", "commit": "bbf6d8f0d9aa072a2ccffc7701936eaa71985f92" }, - "blink-cmp-avante": { "branch": "master", "commit": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5" }, - "blink.cmp": { "branch": "main", "commit": "b19413d214068f316c78978b08264ed1c41830ec" }, + "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, + "SchemaStore.nvim": { "branch": "main", "commit": "e3a2fc3862fa750603b7067789cb4b90578bcd07" }, + "agentic.nvim": { "branch": "main", "commit": "a19fee663aa8be5f46f0af6fc0b46427b0e75cf2" }, + "baleia.nvim": { "branch": "main", "commit": "710537ff5cd669c5a76c5f5b6a9169fd9b913d18" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "catppuccin": { "branch": "main", "commit": "193e123cdbc4dd3e86db883d55349e9587f0ded6" }, - "conform.nvim": { "branch": "master", "commit": "ffe26e8df8115c9665d24231f8a49fadb2d611ce" }, + "catppuccin": { "branch": "main", "commit": "e068ab5f8261f23f6f71ffd8791ae40315b77b9c" }, + "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, + "dial.nvim": { "branch": "master", "commit": "f2634758455cfa52a8acea6f142dcd6271a1bf57" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, - "follow-md-links.nvim": { "branch": "main", "commit": "728d96d268eef9666f0ee77a083e7e2f0b44f607" }, - "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "fzf-lua": { "branch": "main", "commit": "c7ff27deae5b8966b0764bde962d0855e6e2db93" }, - "gitsigns.nvim": { "branch": "main", "commit": "5813e4878748805f1518cee7abb50fd7205a3a48" }, - "grug-far.nvim": { "branch": "main", "commit": "b58b2d65863f4ebad88b10a1ddd519e5380466e0" }, + "follow-md-links.nvim": { "branch": "main", "commit": "99c4e7c78c0211e02c9ff282044b45f7b9dc2d0f" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, + "grug-far.nvim": { "branch": "main", "commit": "c69859c1d5427ab5fc7ed12380ab521b4e336691" }, + "inc-rename.nvim": { "branch": "main", "commit": "0074b551a17338ccdcd299bd86687cc651bcb33d" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, - "lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" }, - "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "c55bd8a8fb191e24176c206a7af1dd51ce7276a5" }, - "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" }, - "mini.ai": { "branch": "main", "commit": "bfb26d9072670c3aaefab0f53024b2f3729c8083" }, - "mini.hipatterns": { "branch": "main", "commit": "add8d8abad602787377ec5d81f6b248605828e0f" }, - "mini.icons": { "branch": "main", "commit": "ff2e4f1d29f659cc2bad0f9256f2f6195c6b2428" }, - "mini.nvim": { "branch": "main", "commit": "c889667a9d73b106bd303a043eb37a91da4a41a2" }, - "mini.pairs": { "branch": "main", "commit": "472ec50092a3314ec285d2db2baa48602d71fe93" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, + "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, + "mini.ai": { "branch": "main", "commit": "d73c36349aa7b0bab5f77ad71701a1d42211a1df" }, + "mini.hipatterns": { "branch": "main", "commit": "607d604e650cdf21d71f863d040c496a1d0cb320" }, + "mini.icons": { "branch": "main", "commit": "e56797f90192d81f1fda02e662fc3e8e3d775027" }, + "mini.nvim": { "branch": "main", "commit": "c594be5b095204e99473825ec2dee872e7409a4d" }, + "mini.pairs": { "branch": "main", "commit": "4a014143fcb4e9df26198ccb3ecff3b9e77a048c" }, + "mini.surround": { "branch": "main", "commit": "580e4cb98c5900d9fe743865fb5a5b2178b4ab18" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-lint": { "branch": "master", "commit": "897f7771c1ca4b11659dfe372d9376acd9fe3097" }, - "nvim-lspconfig": { "branch": "master", "commit": "a2bd1cf7b0446a7414aaf373cea5e4ca804c9c69" }, - "nvim-treesitter": { "branch": "main", "commit": "2979e048b356cfd32dc419d5803dc356b9832adf" }, - "nvim-treesitter-textobjects": { "branch": "main", "commit": "76deedf0f1cec4496ef8d49b6d1f020f6d0c6ec9" }, - "nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" }, + "nvim-dap": { "branch": "master", "commit": "9e848e09a697ee95302a3ef2dd43fd6eb709e570" }, + "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, + "nvim-dap-ui": { "branch": "master", "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" }, + "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, + "nvim-lint": { "branch": "master", "commit": "01c9842c089069ab497430159312b2c8868a4590" }, + "nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" }, + "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, + "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, - "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, - "render-markdown.nvim": { "branch": "main", "commit": "26097a4eb95b391d0308c1b77cce89b28bbc9916" }, - "snacks.nvim": { "branch": "main", "commit": "fe7cfe9800a182274d0f868a74b7263b8c0c020b" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" }, + "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, - "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, "ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" }, - "uv.nvim": { "branch": "main", "commit": "b565e03a573ee2f6493d0516b7854b9142855a6a" }, - "venv-selector.nvim": { "branch": "main", "commit": "58bae72c84b9f7f864c879ec1896e384296f9ffb" }, - "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } + "uv.nvim": { "branch": "main", "commit": "b0bce1b61584fde99c316aa0587a4996c52df206" }, + "venv-selector.nvim": { "branch": "main", "commit": "cc4bb3975de8835291f9bb45889e96c6b2795fc4" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }, + "yanky.nvim": { "branch": "main", "commit": "020c22d0cfa60358569e49d1d7b91630f175aef0" } } diff --git a/nvim/.config/nvim/lazyvim.json b/nvim/.config/nvim/lazyvim.json index b4af5c38b..01feda31d 100644 --- a/nvim/.config/nvim/lazyvim.json +++ b/nvim/.config/nvim/lazyvim.json @@ -1,6 +1,10 @@ { "extras": [ - "lazyvim.plugins.extras.ai.avante", + "lazyvim.plugins.extras.coding.mini-surround", + "lazyvim.plugins.extras.coding.yanky", + "lazyvim.plugins.extras.dap.core", + "lazyvim.plugins.extras.editor.dial", + "lazyvim.plugins.extras.editor.inc-rename", "lazyvim.plugins.extras.formatting.prettier", "lazyvim.plugins.extras.lang.json", "lazyvim.plugins.extras.lang.markdown", diff --git a/nvim/.config/nvim/lua/config/options.lua b/nvim/.config/nvim/lua/config/options.lua index 6634b80c7..7251ea8b6 100644 --- a/nvim/.config/nvim/lua/config/options.lua +++ b/nvim/.config/nvim/lua/config/options.lua @@ -11,9 +11,6 @@ vim.opt.titlestring = [[ [%{fnamemodify(getcwd(), ":t")}] %t]] -- other vim.opt.wrap = true vim.opt.spell = false - --- bufferline colors --- vim.api.nvim_set_hl(0, "BufferlineFill", { bg = "#1e1e2f" }) --- vim.api.nvim_set_hl(0, "BufferLineBackground", { fg = "#6c7086" }) --- vim.api.nvim_set_hl(0, "BufferLineBufferSelected", { fg = "#CAA6F7", bold = true }) --- vim.api.nvim_set_hl(0, "BufferLineBufferVisible", { fg = "#cdd6f4" }) +vim.g.lazyvim_python_lsp = "basedpyright" +vim.diagnostic.enable(false) +vim.g.lazygit_config = false diff --git a/nvim/.config/nvim/lua/plugins/agentic.lua b/nvim/.config/nvim/lua/plugins/agentic.lua new file mode 100644 index 000000000..c18090c01 --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/agentic.lua @@ -0,0 +1,53 @@ +return { + "carlos-algms/agentic.nvim", + + --- @type agentic.PartialUserConfig + opts = { + -- Any ACP-compatible provider works. Built-in: "claude-agent-acp" | "gemini-acp" | "codex-acp" | "opencode-acp" | "cursor-acp" | "copilot-acp" | "auggie-acp" | "mistral-vibe-acp" | "cline-acp" | "goose-acp" | "kiro-acp" | "pi-acp" + provider = "claude-agent-acp", -- setting the name here is all you need to get started + }, + + -- these are just suggested keymaps; customize as desired + keys = { + -- whichkey group + { "a", group = "agentic" }, + + { + "at", + function() require("agentic").toggle() end, + mode = { "n", "v", "i" }, + desc = "Toggle chat", + }, + { + "aa", + function() require("agentic").add_selection_or_file_to_context() end, + mode = { "n", "v" }, + desc = "Add file/selection to context", + }, + { + "an", + function() require("agentic").new_session() end, + mode = { "n", "v", "i" }, + desc = "New session", + }, + { + "ar", + function() require("agentic").restore_session() end, + mode = { "n", "v", "i" }, + desc = "Restore session", + silent = true, + }, + { + "ad", + function() require("agentic").add_current_line_diagnostics() end, + mode = { "n" }, + desc = "Add line diagnostics", + }, + { + "aD", + function() require("agentic").add_buffer_diagnostics() end, + mode = { "n" }, + desc = "Add buffer diagnostics", + }, + }, +} diff --git a/nvim/.config/nvim/lua/plugins/avante.lua b/nvim/.config/nvim/lua/plugins/avante.lua deleted file mode 100644 index 9a7307cab..000000000 --- a/nvim/.config/nvim/lua/plugins/avante.lua +++ /dev/null @@ -1,45 +0,0 @@ -return { - "yetone/avante.nvim", - event = "VeryLazy", - build = false, - version = false, -- Never set this value to "*"! Never! - opts = { - instructions_file = "avante.md", - provider = "litellm", - providers = { - -- Hide all default providers from model selector - claude = { hide_in_model_selector = true }, - openai = { hide_in_model_selector = true }, - azure = { hide_in_model_selector = true }, - gemini = { hide_in_model_selector = true }, - cohere = { hide_in_model_selector = true }, - copilot = { hide_in_model_selector = true }, - bedrock = { hide_in_model_selector = true }, - ollama = { hide_in_model_selector = true }, - vertex_claude = { hide_in_model_selector = true }, - watsonx_code_assistant = { hide_in_model_selector = true }, - -- Custom provider with multiple models - litellm = { - __inherited_from = "openai", - endpoint = "https://engineroomapi.scrippsnet.com", - model = "claude-sonnet-4-5", - api_key_name = "AVANTE_API_KEY", - hide_in_model_selector = false, - model_names = { - "claude-sonnet-4-5", - "claude-opus-4-5", - "gpt-5", - "gemini-3-pro" - }, - }, - }, - }, - dependencies = { - "nvim-lua/plenary.nvim", - "MunifTanjim/nui.nvim", - --- The below dependencies are optional, - "hrsh7th/nvim-cmp", -- autocompletion for avante commands and mentions - "ibhagwan/fzf-lua", -- for file_selector provider fzf - "folke/snacks.nvim", -- for input provider snacks - }, -} diff --git a/nvim/.config/nvim/lua/plugins/dap-python.lua b/nvim/.config/nvim/lua/plugins/dap-python.lua new file mode 100644 index 000000000..3acfec59e --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/dap-python.lua @@ -0,0 +1,384 @@ +return { + { + "mfussenegger/nvim-dap-python", + dependencies = { "mfussenegger/nvim-dap", "folke/which-key.nvim" }, + keys = { + -- Run Single Method or Class + { + "tt", + function() + -- Get the current line number (0-indexed for TS) + local current_row = vim.api.nvim_win_get_cursor(0)[1] - 1 + + -- Pass the row to the target finder + local target, node, node_name, rel_path = _G.get_python_test_target(current_row) + + local label = "File" + if node then + label = (node:type() == "class_definition") and "Class" or "Method" + + -- This moves the cursor and view to the start of the detected node + local start_row = node:range() + vim.api.nvim_win_set_cursor(0, { start_row + 1, 0 }) + vim.api.nvim_command("normal! zt") + end + + _G.run_python_docker_test(target, label .. ": " .. (node_name or rel_path)) + end, + desc = "Run Selected Test (Based on Line)", + }, + -- Run Buffer + { + "tb", + function() + local rel_path = vim.fn.fnamemodify(vim.fn.expand("%:p"), ":.") + local target = "/var/www/isc/infoscout/" .. rel_path + _G.run_python_docker_test(target, "File: " .. rel_path) + end, + desc = "Run Current Buffer Tests", + }, + -- Run Previous + { + "tp", + function() + local last_run = vim.fn.getreg("p") + if last_run == "" then return end + _G.run_python_docker_test(last_run, "Previous Run") + end, + desc = "Run Previous Tests 'p'", + }, + -- Edit Previous + { + "tP", + function() + local buf = vim.api.nvim_create_buf(false, true) + local content = vim.fn.getreg("p") + -- Split register into lines for the buffer + vim.api.nvim_buf_set_lines(buf, 0, -1, false, vim.split(content, "\n")) + + vim.api.nvim_open_win(buf, true, { + relative = "editor", + width = 100, + height = 10, + row = (vim.o.lines - 10) / 2, + col = (vim.o.columns - 100) / 2, + style = "minimal", + border = "rounded", + title = " Edit Test Targets (One Per Line) " + }) + + vim.api.nvim_create_autocmd("BufHidden", { + buffer = buf, + once = true, + callback = function() + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + -- Filter out empty lines and join with newline + local filtered = {} + for _, l in ipairs(lines) do if l ~= "" then table.insert(filtered, l) end end + vim.fn.setreg("p", table.concat(filtered, "\n")) + vim.notify("Register 'p' updated!") + end, + }) + end, + desc = "Edit Previous Tests 'p'", + }, + -- Inspect + { + "ti", + function() + require("dapui").eval(nil, + { context = "repl", enter = true, width = 100, height = 30, position = "center" }) + end, + desc = "Inspect", + }, + -- Add method/class to 'l' register + { + "ta", + function() + local current_row = vim.api.nvim_win_get_cursor(0)[1] - 1 + local target, _, node_name, _ = _G.get_python_test_target(current_row) + local current_reg = vim.fn.getreg("l") + + -- Split the register into a list of lines to check for EXACT matches + local staged_tests = vim.split(current_reg, "\n", { trimempty = true }) + local is_duplicate = false + for _, staged in ipairs(staged_tests) do + if staged == target then + is_duplicate = true + break + end + end + + if is_duplicate then + vim.notify("Already staged in 'l': " .. node_name) + return + end + + local new_content = current_reg == "" and target or (current_reg .. "\n" .. target) + vim.fn.setreg("l", new_content) + + local count = #vim.split(new_content, "\n", { trimempty = true }) + vim.notify("Staged: " .. node_name .. " (Total: " .. count .. ")") + end, + desc = "Add Method/Class to List 'l'", + }, + -- Run tests in 'l' Register + { + "tl", + function() + local staged = vim.fn.getreg("l") + if staged == "" then + vim.notify("Register 'l' is empty!", vim.log.levels.WARN) + return + end + _G.run_python_docker_test(staged, "custom test list 'l'") + end, + desc = "Run List 'l'", + }, + -- Edit 'l' Register + { + "tL", + function() + local buf = vim.api.nvim_create_buf(false, true) + local content = vim.fn.getreg("l") + -- Split by newline to populate the buffer lines + vim.api.nvim_buf_set_lines(buf, 0, -1, false, vim.split(content, "\n", { trimempty = true })) + + vim.api.nvim_open_win(buf, true, { + relative = "editor", + width = 100, + height = 10, + row = (vim.o.lines - 10) / 2, + col = (vim.o.columns - 100) / 2, + style = "minimal", + border = "rounded", + title = " Edit List 'l'" + }) + + vim.api.nvim_create_autocmd("BufHidden", { + buffer = buf, + once = true, + callback = function() + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + local filtered = {} + for _, l in ipairs(lines) do if l ~= "" then table.insert(filtered, l) end end + vim.fn.setreg("l", table.concat(filtered, "\n")) + vim.notify("Register 'l' updated!") + end, + }) + end, + desc = "Edit List 'l'", + }, + -- Smart 90% Float + { + "tf", + function() + local dap = require("dap") + local dapui = require("dapui") + local width = math.floor(vim.o.columns * 0.9) + local height = math.floor(vim.o.lines * 0.9) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + + -- ACTIVE SESSION: Prompt for choice + if dap.session() then + vim.ui.select({ "scopes", "repl", "watches", "stacks" }, { + prompt = "Select Active Debug Element:", + }, function(choice) + if choice then + dapui.float_element(choice, { + width = width, + height = height, + enter = true, + position = "center", + }) + end + end) + return + end + + -- NO SESSION: Manual Buffer Search (Bypasses DAP-UI warning) + local repl_buf = nil + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if vim.bo[buf].filetype == "dap-repl" then + repl_buf = buf + break + end + end + + if repl_buf and vim.api.nvim_buf_is_valid(repl_buf) then + local float_win = vim.api.nvim_open_win(repl_buf, true, { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + border = "rounded", + title = " REPL History (Post-Mortem) ", + title_pos = "center", + }) + + -- KEYMAP FOR FLOATING WIN: Close on Escape or 'q' + vim.keymap.set("n", "", function() + if vim.api.nvim_win_is_valid(float_win) then + vim.api.nvim_win_close(float_win, true) + end + end, { buffer = repl_buf, silent = true, nowait = true }) + + -- Auto-scroll to bottom of logs + vim.cmd("normal! G") + else + vim.notify("No active session or REPL history found.", vim.log.levels.WARN) + end + end, + desc = "Float DAP UI", + }, + -- Add buffer to 'l' register + { + "tA", + function() + local rel_path = vim.fn.fnamemodify(vim.fn.expand("%:p"), ":.") + local target = "/var/www/isc/infoscout/" .. rel_path + local current_reg = vim.fn.getreg("l") + + -- Prevent duplicates + if string.find(current_reg, target, 1, true) then + vim.notify("File already staged in 'l'") + return + end + + -- Add with newline if buffer isn't empty + local new_content = current_reg == "" and target or (current_reg .. "\n" .. target) + vim.fn.setreg("l", new_content) + + local count = #vim.split(new_content, "\n", { trimempty = true }) + vim.notify("Staged File: " .. rel_path .. " (Total: " .. count .. ")") + end, + desc = "Add File List to 'l'", + }, + }, + config = function() + require("which-key").add({ { "t", group = "test" } }) + + -- Bind debugpy, announce readiness, THEN block for the client. + -- listen() returns once the socket is accepting connections, so the + -- printed sentinel is a precise "safe to attach" signal. We must not + -- probe the port to detect this -- debugpy accepts a single client, + -- and a probe would consume it, so we attach exactly once on the + -- sentinel instead. + local debugpy_bootstrap = table.concat({ + "import sys, debugpy", + "debugpy.listen(('0.0.0.0', 5678))", + "print('DEBUGPY_LISTENING', flush=True)", + "debugpy.wait_for_client()", + "import pytest", + "sys.exit(pytest.main(sys.argv[1:]))", + }, "\n") + + _G.run_python_docker_test = function(target_str, notify_msg) + local dap = require("dap") + dap.terminate() + vim.fn.setreg("p", target_str) + + -- Split by newline to get arguments for pytest + local target_list = vim.split(target_str, "\n", { trimempty = true }) + + vim.notify("Running: " .. notify_msg) + + -- keep the pipe open so we can watch for the sentinel. + -- -Xfrozen_modules=off so debugpy doesn't miss breakpoints in + -- frozen stdlib modules (Python 3.12+). + local cmd = { + "docker", "compose", "exec", "-T", "web", + "python3", "-Xfrozen_modules=off", "-c", debugpy_bootstrap, + "--color=yes", "-s", + } + -- Append all targets (passed through to pytest.main via argv) + for _, t in ipairs(target_list) do table.insert(cmd, t) end + + local attached = false + local function attach() + if attached then return end + attached = true + dap.run({ + type = "python", + request = "attach", + name = "Docker: " .. notify_msg, + connect = { host = "127.0.0.1", port = 5678 }, + pathMappings = { { localRoot = vim.fn.getcwd(), remoteRoot = "/var/www/isc/infoscout" } }, + justMyCode = true, + console = "internalConsole", + redirectOutput = true, + }) + end + + vim.system(cmd, { + text = true, + stdout = function(_, data) + if data and not attached and data:find("DEBUGPY_LISTENING", 1, true) then + vim.schedule(attach) + end + end, + }, function(obj) + -- Never saw the sentinel: surface why instead of hanging. + if not attached then + vim.schedule(function() + vim.notify( + "debugpy never reported listening (exit " + .. tostring(obj.code) .. ")\n" .. (obj.stderr or ""), + vim.log.levels.ERROR + ) + end) + end + end) + end + + _G.get_python_test_target = function(row) + -- If row is provided, use it (0-indexed); otherwise, default to cursor + local node = row + and vim.treesitter.get_node({ pos = { row, 0 } }) + or vim.treesitter.get_node() + + local target_node, method_name, class_name = nil, nil, nil + local curr = node + while curr do + local type = curr:type() + if type == "function_definition" then + target_node = target_node or curr + for i = 0, curr:child_count() - 1 do + local child = curr:child(i) + if child:type() == "identifier" then + method_name = vim.treesitter.get_node_text(child, 0) + end + end + elseif type == "class_definition" then + target_node = target_node or curr + for i = 0, curr:child_count() - 1 do + local child = curr:child(i) + if child:type() == "identifier" then + class_name = vim.treesitter.get_node_text(child, 0) + end + end + end + curr = curr:parent() + end + + local rel_path = vim.fn.fnamemodify(vim.fn.expand("%:p"), ":.") + local target = "/var/www/isc/infoscout/" .. rel_path + local display_name = rel_path + + if class_name then target = target .. "::" .. class_name end + if method_name then + target = target .. "::" .. method_name + display_name = method_name + elseif class_name then + display_name = class_name + end + + return target, target_node, display_name, rel_path + end + + require("dap").adapters.python = { type = "server", host = "127.0.0.1", port = 5678 } + end, + }, +} diff --git a/nvim/.config/nvim/lua/plugins/dap-ui.lua b/nvim/.config/nvim/lua/plugins/dap-ui.lua new file mode 100644 index 000000000..7a3926aa4 --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/dap-ui.lua @@ -0,0 +1,198 @@ +return { + { + "rcarriga/nvim-dap-ui", + dependencies = { "nvim-neotest/nvim-nio" }, + keys = { + { + "du", + function() + local dapui = require("dapui") + local is_open = false + + -- Check for any visible DAP-UI windows or REPL + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + if ft:find("dapui") or ft == "dap-repl" then + is_open = true + break + end + end + + if is_open then + dapui.close() + -- Explicitly close the REPL if it's still hanging around + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == "dap-repl" then + vim.api.nvim_win_close(win, true) + end + end + else + dapui.open(1) -- Open only sidebars by default + vim.api.nvim_command("wincmd p") -- Focus fix + end + end, + desc = "Dap UI: Smart Toggle (Includes REPL Cleanup)", + }, + { + "tI", + function() + require("dapui").toggle(2) -- Toggle the bottom Scopes/Watches layout + end, + desc = "Toggle Scopes and Watches", + }, + }, + opts = { + force_focus = false, + layouts = { + { + elements = { + { id = "repl", size = 1 }, + }, + size = 15, -- Height for the output section + position = "bottom", + }, + { + elements = { + { id = "scopes", size = 0.8 }, -- 80% width + { id = "watches", size = 0.2 }, -- 20% width + }, + position = "bottom", + size = 10, -- Height of the bottom tray + }, + }, + -- Floating window settings for ti + floating = { + max_height = nil, + max_width = nil, + border = "rounded", + mappings = { + close = { "q", "" }, + }, + }, + }, + config = function(_, opts) + local dap, dapui = require("dap"), require("dapui") + dapui.setup(opts) + + -- PERSISTENCE & FOCUS FIX (Merged) + dap.listeners.after.event_initialized["dapui_config"] = function() + local main_win = vim.api.nvim_get_current_win() + -- Open ONLY the first layout (side panes) + dapui.open(1) + + vim.schedule(function() + if main_win and vim.api.nvim_win_is_valid(main_win) then + vim.api.nvim_set_current_win(main_win) + end + end) + end + + -- BREAKPOINT TRIGGER: Auto-open Layout 2 (Bottom Tray) + dap.listeners.after.event_stopped["dapui_config"] = function() + dapui.open(2) + end + + -- Prevent LazyVim from auto-closing the UI + dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close(2) + end + dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close(2) + end + + vim.api.nvim_create_autocmd("FileType", { + pattern = "dap-repl", + callback = function(args) + local bufnr = args.buf + + -- Fix path recognition + vim.cmd([[setlocal isfname+=44,32,34]]) + + -- Auto-scroll + if not vim.b[bufnr].dap_scroll_attached then + vim.api.nvim_buf_attach(bufnr, false, { + on_lines = function() + vim.schedule(function() + if not vim.api.nvim_buf_is_valid(bufnr) then return end + local wins = vim.fn.win_findbuf(bufnr) + for _, win in ipairs(wins) do + local last_line = vim.api.nvim_buf_line_count(bufnr) + pcall(vim.api.nvim_win_set_cursor, win, { last_line, 0 }) + end + end) + end, + }) + vim.b[bufnr].dap_scroll_attached = true + end + + -- Docker-to-Local path mapping with Primary Window targeting + vim.keymap.set("n", "", function() + local line = vim.api.nvim_get_current_line() + local curr_win = vim.api.nvim_get_current_win() -- Get current window (potentially floating) + local docker_root = "/var/www/isc/infoscout" + local local_root = vim.fn.expand("~/Documents/development/projects/infoscout") + + -- Regex Pattern 1: File "path", line XX + local path, line_nr = line:match('File "(.-)", line (%d+)') + -- Regex Pattern 2: /path/to/file.py:XX + if not path then + path, line_nr = line:match('([%w%._/-]+%.py):(%d+)') + end + + if path then + local local_path = path:gsub("^" .. docker_root, local_root) + + -- FIND PRIMARY WINDOW: Look for a window that isn't a DAP-UI element + local target_win = nil + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local wbuf = vim.api.nvim_win_get_buf(win) + local wft = vim.bo[wbuf].filetype + if not wft:find("dapui") and wft ~= "dap-repl" then + target_win = win + break + end + end + + -- Execute the jump in the target window + if target_win then + vim.api.nvim_set_current_win(target_win) + vim.cmd("edit " .. local_path) + if line_nr then + pcall(vim.api.nvim_win_set_cursor, target_win, { tonumber(line_nr), 0 }) + end + vim.cmd("normal! zvzz") + + -- If the REPL was in a floating window, close it now + local win_cfg = vim.api.nvim_win_get_config(curr_win) + if win_cfg.relative ~= "" then + vim.api.nvim_win_close(curr_win, true) + end + else + -- Fallback: open in a vertical split if no main window found + vim.cmd("vsplit " .. local_path) + end + else + pcall(vim.cmd, "normal! gf") + end + end, { buffer = bufnr, desc = "Jump to Local File in Main Window" }) + end, + }) + end, + }, + { + "m00qek/baleia.nvim", + config = function() + vim.g.baleia = require("baleia").setup({ line_starts_at = 3 }) -- Adjust for REPL prompt + + -- Automatically colorize the REPL when it opens + vim.api.nvim_create_autocmd("FileType", { + pattern = "dap-repl", + callback = function(ev) + vim.g.baleia.automatically(ev.buf) + end, + }) + end, + } +} diff --git a/nvim/.config/nvim/lua/plugins/lsp.lua b/nvim/.config/nvim/lua/plugins/lsp.lua index 159ce3f4d..edb68adf0 100644 --- a/nvim/.config/nvim/lua/plugins/lsp.lua +++ b/nvim/.config/nvim/lua/plugins/lsp.lua @@ -6,6 +6,9 @@ return { pyright = { mason = false, }, + basedpyright = { + mason = True + }, }, }, }, diff --git a/nvim/.config/nvim/lua/plugins/noice.lua b/nvim/.config/nvim/lua/plugins/noice.lua new file mode 100644 index 000000000..359494314 --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/noice.lua @@ -0,0 +1,15 @@ +return { + "folke/noice.nvim", + opts = { + routes = { + { + filter = { + event = "notify", -- Use "notify" instead of "msg_show" to catch toast popups + warning = true, -- Only target warnings + find = "Adapter reported a frame", -- Partial string match + }, + opts = { skip = true }, + }, + }, + }, +} diff --git a/nvim/.config/nvim/lua/plugins/snacks.lua b/nvim/.config/nvim/lua/plugins/snacks.lua index 3d7356a25..a8d8e2ad7 100644 --- a/nvim/.config/nvim/lua/plugins/snacks.lua +++ b/nvim/.config/nvim/lua/plugins/snacks.lua @@ -10,10 +10,18 @@ return { }, }, terminal = { - shell = "bash" + shell = "bash", }, image = { - } + }, + styles = { + terminal = { + } + }, + lazygit = { + -- Prevent snacks from injecting its own defaults or preset configs + configure = false, + }, }, }, } diff --git a/nvim/.config/nvim/lua/plugins/surround.lua b/nvim/.config/nvim/lua/plugins/surround.lua new file mode 100644 index 000000000..ac279dca1 --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/surround.lua @@ -0,0 +1,27 @@ +return { + { + "nvim-mini/mini.surround", + opts = { + mappings = { + add = ";;", + delete = ";d", + find = ";f", + find_left = ";F", + highlight = ";h", + replace = ";r", + update_n_lines = ";n", + }, + }, + }, + + { + "folke/flash.nvim", + opts = { + modes = { + char = { + keys = { "f", "F", "t", "T" }, + }, + }, + }, + }, +} diff --git a/nvim/.config/nvim/lua/plugins/which-key.lua b/nvim/.config/nvim/lua/plugins/which-key.lua new file mode 100644 index 000000000..69746e095 --- /dev/null +++ b/nvim/.config/nvim/lua/plugins/which-key.lua @@ -0,0 +1,10 @@ +return { + { + "folke/which-key.nvim", + opts = { + spec = { + { "t", group = "test" }, + }, + }, + }, +} diff --git a/terminal/.bashrc b/terminal/.bashrc index 30c9b0c3e..b8bf8a04e 100644 --- a/terminal/.bashrc +++ b/terminal/.bashrc @@ -3,6 +3,8 @@ if [ -f ~/.bash_secret_keys ]; then source ~/.bash_secret_keys fi +eval "$(/opt/homebrew/bin/brew shellenv)" + [[ $- != *i* ]] && return alias ls='ls --color=auto' alias grep='grep --color=auto' @@ -11,13 +13,5 @@ PS1='[\u@\h \W]\$ ' # Configuration export EDITOR='nvim' -## uv -export PATH="/home/rlegacy/.local/bin:$PATH" -export DEVPOD_SKIP_CHOWN="true" - ## Prompt eval "$(starship init bash)" - -# Aliases -alias wclone='git clone -c "core.sshCommand=ssh -i ~/.ssh/work -F /dev/null"' -alias python='uv run python' diff --git a/terminal/.config/kitty/kitty.conf b/terminal/.config/kitty/kitty.conf index 01a932df7..20f9ab49f 100644 --- a/terminal/.config/kitty/kitty.conf +++ b/terminal/.config/kitty/kitty.conf @@ -1,3 +1,5 @@ +shell /opt/homebrew/bin/bash + allow_remote_control yes listen_on unix:/tmp/mykitty # keybinds @@ -10,18 +12,89 @@ map shift+insert paste_from_clipboard map kitty_mod+c copy_to_clipboard map kitty_mod+v paste_from_clipboard -# theme file -include current-theme.conf +# theme + +# The basic colors +foreground #CDD6F4 +background #1e1e2d +selection_foreground #1e1e2d +selection_background #F5E0DC + +# Cursor colors +cursor #F5E0DC +cursor_text_color #1e1e2d + +# URL underline color when hovering with mouse +url_color #F5E0DC + +# Kitty window border colors +active_border_color #B4BEFE +inactive_border_color #6C7086 +bell_border_color #F9E2AF + +# OS Window titlebar colors +wayland_titlebar_color system +macos_titlebar_color system + +# Tab bar colors +active_tab_foreground #11111B +active_tab_background #CBA6F7 +inactive_tab_foreground #CDD6F4 +inactive_tab_background #181825 +tab_bar_background #11111B + +# Colors for marks (marked text in the terminal) +mark1_foreground #1e1e2d +mark1_background #B4BEFE +mark2_foreground #1e1e2d +mark2_background #CBA6F7 +mark3_foreground #1e1e2d +mark3_background #74C7EC + +# The 16 terminal colors + +# black +color0 #45475A +color8 #585B70 + +# red +color1 #F38BA8 +color9 #F38BA8 + +# green +color2 #A6E3A1 +color10 #A6E3A1 + +# yellow +color3 #F9E2AF +color11 #F9E2AF + +# blue +color4 #89B4FA +color12 #89B4FA + +# magenta +color5 #F5C2E7 +color13 #F5C2E7 + +# cyan +color6 #94E2D5 +color14 #94E2D5 + +# white +color7 #BAC2DE +color15 #A6ADC8 # various looks stuff # font_family CaskaydiaCove Nerd Font Mono -font_family JetBrains Mono Nerd Font -bold_font auto -italic_font auto -bold_italic_font auto +# font_family JetBrainsMono Nerd Font +# bold_font auto +# italic_font auto +# bold_italic_font auto window_margin_width 0 15 5 -font_size 14 -background_opacity 0.4 +padding_padding_width 15 +font_size 16 +background_opacity 0.6 # hide that mouse mouse_hide_wait 0.5 @@ -35,3 +108,11 @@ tab_bar_style powerline tab_powerline_style slanted active_tab_font_style normal + + +# BEGIN_KITTY_FONTS +font_family family="JetBrainsMono Nerd Font Mono" +bold_font auto +italic_font auto +bold_italic_font auto +# END_KITTY_FONTS diff --git a/terminal/.config/starship.toml b/terminal/.config/starship.toml index bb1886015..6303d9bfe 100644 --- a/terminal/.config/starship.toml +++ b/terminal/.config/starship.toml @@ -8,7 +8,6 @@ $username\ $directory\ [](bg:yellow fg:sky)\ $git_branch\ -$git_status\ [](bg:mauve fg:yellow)\ $time\ [ ](fg:mauve)\