diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 000000000..2ab439274 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,22 @@ +{ + "permissions": { + "allow": [ + "Bash(poetry env info:*)", + "Bash(poetry env list:*)", + "Bash(uvx --help:*)", + "WebFetch(domain:github.com)", + "Bash(nvim:*)", + "Bash(git add:*)", + "Bash(git push)", + "Read(//Users/andrewpatterson/.local/share/nvim/lazy/nvim-treesitter/**)", + "Bash(ls -la queries/python/)", + "Bash(grep -l \"conceal\" queries/python/*.scm)", + "Read(//opt/homebrew/Cellar/neovim/**)", + "Read(//opt/homebrew/Cellar/neovim/0.12.2/bin/**)", + "Bash(brew info *)", + "WebFetch(domain:api.github.com)" + ], + "deny": [], + "ask": [] + } +} diff --git a/ftplugin/markdown.lua b/ftplugin/markdown.lua new file mode 100644 index 000000000..c829417b9 --- /dev/null +++ b/ftplugin/markdown.lua @@ -0,0 +1,2 @@ +-- Activate quarto for markdown files to enable code cell execution +require("quarto").activate() diff --git a/ftplugin/python.lua b/ftplugin/python.lua new file mode 100644 index 000000000..e69de29bb diff --git a/ftplugin/stim.lua b/ftplugin/stim.lua new file mode 100644 index 000000000..54660c36f --- /dev/null +++ b/ftplugin/stim.lua @@ -0,0 +1,8 @@ +-- Comment configuration for .stim files +vim.bo.commentstring = "# %s" + +-- Enable treesitter syntax highlighting. +-- vim.treesitter.start() bypasses nvim-treesitter's highlight module (which +-- only activates parsers it knew about at startup) and directly starts the +-- built-in highlighter for this buffer. +pcall(vim.treesitter.start) diff --git a/init.lua b/init.lua index e861b68ca..5f89c7eda 100644 --- a/init.lua +++ b/init.lua @@ -32,6 +32,11 @@ dofile(vim.g.base46_cache .. "statusline") require "options" require "autocmds" +-- Re-enable Python provider after NvChad options (NvChad disables it, but we need it for Molten) +vim.g.loaded_python3_provider = nil +vim.g.python3_host_prog = vim.fn.exepath('python3') or vim.fn.exepath('python') + vim.schedule(function() require "mappings" end) +require 'myinit' diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 000000000..667139dd1 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,55 @@ +{ + "CopilotChat.nvim": { "branch": "main", "commit": "f0c2a23ab79dc295f5e0eef0d8b587a39020c852" }, + "FixCursorHold.nvim": { "branch": "master", "commit": "1900f89dc17c603eec29960f57c00bd9ae696495" }, + "LuaSnip": { "branch": "master", "commit": "0abc8f390b278c3b4aabc4c004ac8a088b65cf24" }, + "NvChad": { "branch": "v2.5", "commit": "d042cc975247c2aa55fcb228e5d146dc1dc6c648" }, + "avante.nvim": { "branch": "main", "commit": "90a0e77c63251c367935caeaa0070670522c960b" }, + "base46": { "branch": "v3.0", "commit": "884b990dcdbe07520a0892da6ba3e8d202b46337" }, + "better-escape.nvim": { "branch": "master", "commit": "3f4bc0b326606264ff75967f59091b5ddada0554" }, + "cmp-async-path": { "branch": "main", "commit": "98185a91d49ff5dd249aebf2f7456e18063fa2a0" }, + "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-nvim-lua": { "branch": "main", "commit": "e3a22cb071eb9d6508a156306b102c45cd2d573d" }, + "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, + "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, + "copilot.vim": { "branch": "release", "commit": "a12fd5672110c8aa7e3c8419e28c96943ca179be" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, + "hererocks": { "branch": "master", "commit": "3db37265c3839cbd4d27fc73f92fa7b58bc3a76f" }, + "image.nvim": { "branch": "master", "commit": "88351f1f7d9dbae286e671ce3690a49660dd8a5c" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "jupytext.nvim": { "branch": "main", "commit": "c8baf3ad344c59b3abd461ecc17fc16ec44d0f7b" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, + "mcphub.nvim": { "branch": "main", "commit": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f" }, + "menu": { "branch": "main", "commit": "7a0a4a2896b715c066cfbe320bdc048091874cc6" }, + "minty": { "branch": "main", "commit": "aafc9e8e0afe6bf57580858a2849578d8d8db9e0" }, + "molten-nvim": { "branch": "main", "commit": "a286aa914d9a154bc359131aab788b5a077a5a99" }, + "neogen": { "branch": "main", "commit": "23e7e9f883d01289ebd90e98025acc860ea26366" }, + "neotest": { "branch": "master", "commit": "ad991822b7076b1d940b33a9d6d0d30416d5df81" }, + "neotest-python": { "branch": "master", "commit": "e6df4f1892f6137f58135917db24d1655937d831" }, + "none-ls.nvim": { "branch": "main", "commit": "01f8e62ea11603e59ad9ff7afcfa94fd183f76d6" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" }, + "nvim-cmp": { "branch": "main", "commit": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca" }, + "nvim-dap": { "branch": "master", "commit": "9e848e09a697ee95302a3ef2dd43fd6eb709e570" }, + "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, + "nvim-dap-ui": { "branch": "master", "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" }, + "nvim-lint": { "branch": "master", "commit": "01c9842c089069ab497430159312b2c8868a4590" }, + "nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" }, + "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, + "nvim-tree.lua": { "branch": "master", "commit": "8e8be709c9a93e1ebefde7964884a8b564bfd3e0" }, + "nvim-treesitter": { "branch": "master", "commit": "cf12346a3414fa1b06af75c79faebe7f76df080a" }, + "nvim-web-devicons": { "branch": "master", "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" }, + "otter.nvim": { "branch": "main", "commit": "d781eda3bc18dbc8677f9a24abdc705fb74e4428" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "quarto-nvim": { "branch": "main", "commit": "17f1e5d664bc615478230dc0240666329efacf9b" }, + "snippet-converter.nvim": { "branch": "main", "commit": "d7e783618f02541641980ebd823e439bdef64a4f" }, + "stim-treesitter-parser": { "branch": "main", "commit": "3c84d6ab09bc364ed712329cd4f9fb113e489aad" }, + "telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" }, + "ui": { "branch": "v3.0", "commit": "3e67e9d5325fd47fdbc90ca00a147db2f3525754" }, + "vim-markdown": { "branch": "master", "commit": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397" }, + "vimtex": { "branch": "master", "commit": "63745fa542346e0f09a496d440645ef6ff75b62c" }, + "volt": { "branch": "main", "commit": "620de1321f275ec9d80028c68d1b88b409c0c8b1" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/lua/chadrc.lua b/lua/chadrc.lua index 9eca87cde..b34d66cf0 100644 --- a/lua/chadrc.lua +++ b/lua/chadrc.lua @@ -1,24 +1,13 @@ --- This file needs to have same structure as nvconfig.lua --- https://github.com/NvChad/ui/blob/v3.0/lua/nvconfig.lua --- Please read that file to know all available options :( - ---@type ChadrcConfig local M = {} -M.base46 = { - theme = "onedark", +-- Path to overriding theme and highlights files +local highlights = require "highlights" - -- hl_override = { - -- Comment = { italic = true }, - -- ["@comment"] = { italic = true }, - -- }, +M.base46 = { + theme = "catppuccin", + transparency = true, + hl_override = highlights.override, + hl_add = highlights.add } - --- M.nvdash = { load_on_startup = true } --- M.ui = { --- tabufline = { --- lazyload = false --- } --- } - return M diff --git a/lua/configs/cmp.lua b/lua/configs/cmp.lua new file mode 100644 index 000000000..2b36d383a --- /dev/null +++ b/lua/configs/cmp.lua @@ -0,0 +1,52 @@ +local has_words_before = function() + unpack = unpack or table.unpack + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil +end +local cmp = require "cmp" +local options = { + + mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + -- [""] = cmp.mapping.confirm { + -- behavior = cmp.ConfirmBehavior.Insert, + -- select = true, + -- }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.confirm { + behavior = cmp.ConfirmBehavior.Insert, + select = true, + } + elseif require("luasnip").expand_or_jumpable() then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-expand-or-jump", true, true, true), "") + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-jump-prev", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + }, +} + +return options diff --git a/lua/configs/dapui.lua b/lua/configs/dapui.lua new file mode 100644 index 000000000..2b501e99a --- /dev/null +++ b/lua/configs/dapui.lua @@ -0,0 +1,38 @@ +local dap = require "dap" +local dapui = require "dapui" + +-- First, set up dap-ui +dapui.setup { + -- Optional: configure layouts + layouts = { + { + elements = { + -- Elements can be strings or table with id and size keys. + {id = "scopes", size = 1.0}, + }, + size = 40, -- 40 columns + position = "left", + }, + { + elements = { + -- { id = "scopes", size = 0.3 }, + {id = "repl", size = 1.0}, + }, + size = 0.25, -- 25% of total lines + position = "bottom", + }, + }, +} + +-- Automatically open UI when debugging starts +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 + +-- Add some keymaps for debug terminal diff --git a/lua/configs/lint.lua b/lua/configs/lint.lua new file mode 100644 index 000000000..b185862d6 --- /dev/null +++ b/lua/configs/lint.lua @@ -0,0 +1,93 @@ +local M = {} + +M.setup = function() + local lint = require "lint" + + -- local root = vim.fn.getcwd() + -- local pyproject_path = root .. "/pyproject.toml" + -- + -- if vim.fn.filereadable(pyproject_path) == 1 then + -- lint.linters.mypy.args = vim.list_extend( + -- lint.linters.mypy.args or {}, + -- { "--config-file", pyproject_path } + -- ) + -- else + -- lint.linters.mypy.args = vim.list_extend( + -- lint.linters.mypy.args or {}, + -- { "--config-file", "pyproject.toml" } + -- ) + -- end + + lint.linters.mypy = vim.tbl_deep_extend("force", lint.linters.mypy, { + cmd = "python", + args = vim.list_extend({ "-m", "mypy" }, lint.linters.mypy.args) + }) + + lint.linters.pylint = vim.tbl_deep_extend("force", lint.linters.pylint, { + cmd = "python", + args = vim.list_extend({ "-m", "pylint" }, lint.linters.pylint.args) + }) + + + lint.linters_by_ft = { + python = { "ruff", "mypy", "pylint" }, + cpp = { "cpplint", "cppcheck" }, + } + + local signs = { + Error = " ", + Warn = " ", + Hint = " ", + Info = " ", + } + + vim.diagnostic.config({ + virtual_text = false, + signs = true, + underline = true, + update_in_insert = false, + float = { + source = true, + border = "rounded", + header = "", + prefix = "", + format = function(diagnostic) + return string.format("%s: %s", diagnostic.source or "LSP", diagnostic.message) + end, + }, + signs = { + text = signs, + linehl = {}, + numhl = {}, + }, + severity_sort = true, + }) + + local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) + + vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, { + group = lint_augroup, + callback = function() + lint.try_lint() + end, + }) + + -- Highlight configurations + vim.api.nvim_command "highlight DiagnosticUnderlineError gui=underline guisp=#FF0000" + vim.api.nvim_command "highlight DiagnosticUnderlineWarn gui=underline guisp=#FF9900" + vim.api.nvim_command "highlight DiagnosticUnderlineInfo gui=underline guisp=#0000FF" + vim.api.nvim_command "highlight DiagnosticUnderlineHint gui=underline guisp=#00FF00" + + vim.api.nvim_create_autocmd("CursorHold", { + group = lint_augroup, + callback = function() + vim.diagnostic.open_float(nil, { + focusable = false, + scope = "line", + border = "single", + }) + end, + }) +end + +return M diff --git a/lua/configs/lspconfig.lua b/lua/configs/lspconfig.lua index 20a0cce02..aee860199 100644 --- a/lua/configs/lspconfig.lua +++ b/lua/configs/lspconfig.lua @@ -1,6 +1,250 @@ require("nvchad.configs.lspconfig").defaults() -local servers = { "html", "cssls" } -vim.lsp.enable(servers) - -- read :h vim.lsp.config for changing options of lsp servers +local nv_on_attach = require("nvchad.configs.lspconfig").on_attach +local on_init = require("nvchad.configs.lspconfig").on_init +local capabilities = require("nvchad.configs.lspconfig").capabilities + +-- Diagnostic signs - using new API instead of deprecated sign_define +-- local signs = { +-- Error = " ", +-- Warn = " ", +-- Hint = " ", +-- Info = " ", +-- } + -- Diagnostics configuration + +-- Enhanced diagnostic configuration with signs +-- vim.diagnostic.config({ +-- virtual_text = false, -- Keep virtual text enabled +-- signs = true, -- Keep signs for errors +-- underline = true, -- Enable underlining +-- update_in_insert = true, +-- virtual_text = { +-- prefix = "●", +-- source = "if_many", +-- spacing = 4, +-- severity = { +-- min = vim.diagnostic.severity.HINT, +-- }, + -- format = function(diagnostic) + -- if diagnostic.source == "harper_ls" then + -- return string.format("[grammar] %s", diagnostic.message) + -- end + -- return diagnostic.message + -- end, +-- }, +-- float = { +-- source = true, +-- border = "rounded", +-- header = "", +-- prefix = "", +-- format = function(diagnostic) +-- return string.format("%s: %s", diagnostic.source or "LSP", diagnostic.message) +-- end, +-- }, +-- signs = { +-- text = signs, +-- linehl = {}, +-- numhl = {}, +-- }, +-- underline = true, +-- update_in_insert = false, +-- severity_sort = true, +-- }) + +-- Signs are now configured via vim.diagnostic.config above + +-- Show all diagnostics on cursor hold +-- vim.api.nvim_create_autocmd("CursorHold", { +-- callback = function() +-- local opts = { +-- focusable = false, +-- close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" }, +-- border = "rounded", +-- source = "always", +-- prefix = " ", +-- scope = "cursor", +-- } +-- vim.diagnostic.open_float(nil, opts) +-- end, +-- }) +-- +-- wrap NVChad's on_attach to remove that default ra binding +local on_attach = function(client, bufnr) + nv_on_attach(client, bufnr) + -- vim.keymap.del("n", "ra", { buffer = bufnr }) + + -- Add missing LSP keybindings + vim.keymap.set("n", "gr", vim.lsp.buf.references, { buffer = bufnr, desc = "LSP Go to references" }) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { buffer = bufnr, desc = "LSP Go to implementation" }) + + -- Enable inlay hints if supported + if client.supports_method("textDocument/inlayHint") then + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end + + -- Enable semantic tokens if supported + if client.supports_method("textDocument/semanticTokens") then + vim.highlight.priorities.semantic_tokens = 95 + end +end + +local marksman_caps = vim.deepcopy(capabilities) +marksman_caps.workspace = vim.tbl_extend("force", marksman_caps.workspace, { + workspaceFolders = false, +}) + + +-- Define all servers and only specify the bits that differ from the default +local servers = { + -- simple defaults + cssls = {}, + eslint = {}, + -- harper_ls = {}, + html = {}, + jsonls = {}, + + -- -- Lua + -- lua_ls = { + -- settings = { + -- Lua = { + -- diagnostics = { enable = false }, + -- workspace = { + -- library = { + -- vim.fn.expand "$VIMRUNTIME/lua", + -- vim.fn.expand "$VIMRUNTIME/lua/vim/lsp", + -- vim.fn.stdpath "data" .. "/lazy/ui/nvchad_types", + -- vim.fn.stdpath "data" .. "/lazy/lazy.nvim/lua/lazy", + -- }, + -- maxPreload = 100000, + -- preloadFileSize = 10000, + -- }, + -- }, + -- }, + -- }, + -- + -- -- Go (Simplified) + -- gopls = { + -- on_attach = function(client, bufnr) + -- client.server_capabilities.documentFormattingProvider = false + -- client.server_capabilities.documentRangeFormattingProvider = false + -- on_attach(client, bufnr) + -- end, + -- settings = { + -- gopls = { + -- analyses = { + -- unusedparams = true, + -- }, + -- staticcheck = true, + -- gofumpt = true, -- A common and recommended setting + -- }, + -- }, + -- }, + -- + -- -- Ruby LSP (with Rails & RSpec add-ons) + -- ruby_lsp = { + -- on_attach = function(client, bufnr) + -- client.server_capabilities.documentFormattingProvider = false + -- client.server_capabilities.documentRangeFormattingProvider = false + -- require "configs.functions.ruby_deps"(client, bufnr) + -- on_attach(client, bufnr) + -- end, + -- init_options = { + -- formatter = "standard", + -- linters = { "standard" }, + -- addonSettings = { + -- ["Ruby LSP Rails"] = { + -- enablePendingMigrationsPrompt = false, + -- }, + -- ["Ruby LSP RSpec"] = { + -- rspecCommand = "rspec -f d", + -- }, + -- }, + -- }, + -- cmd = { "mise", "exec", "--", "ruby-lsp" }, + -- settings = { + -- ruby = { + -- diagnostics = true, + -- formatting = true, + -- lint = true, + -- completion = true, + -- ignored_diagnostics = { "Layout/TrailingEmptyLines" }, + -- }, + -- }, + -- }, + -- + -- -- TypeScript / JavaScript (Corrected Name) + -- ts_ls = { + -- on_attach = function(client, bufnr) + -- client.server_capabilities.documentFormattingProvider = false + -- client.server_capabilities.documentRangeFormattingProvider = false + -- on_attach(client, bufnr) + -- end, + -- }, + -- + -- -- Biome (alternative JS/TS linter & formatter) + -- biome = { + -- on_attach = function(client, bufnr) + -- client.server_capabilities.documentFormattingProvider = false + -- client.server_capabilities.documentRangeFormattingProvider = false + -- on_attach(client, bufnr) + -- end, + -- }, + -- + -- -- Hypr configuration language + -- hyprls = { + -- -- lspconfig defaults are sufficient here + -- }, + + -- Rust (handled by rustaceanvim) + + -- Markdown + marksman = { + capabilities = marksman_caps, + filetypes = { "markdown" }, + single_file_support = true, + }, + + -- ruff = { + -- cmd = {"ruff", "server"}, + -- filetypes = {"python"}, + -- root_markers = {".git", "pyproject.toml"}, + -- settings = {}, + -- }, + + pyright = { + on_attach = function(client, bufnr) + client.server_capabilities.publishDiagnosticsProvider = false + on_attach(client, bufnr) + end, + settings = { + python = { + analysis = { + typeCheckingMode = "basic", -- options: off, basic, strict + autoSearchPaths = true, + useLibraryCodeForTypes = true, + }, + } + } + }, + -- Disabled to avoid conflicts with marksman and improve performance + -- markdown_oxide = { + -- on_attach = function(client, bufnr) + -- client.server_capabilities.documentFormattingProvider = false + -- client.server_capabilities.documentRangeFormattingProvider = false + -- on_attach(client, bufnr) + -- end, + -- }, +} + +for name, opts in pairs(servers) do + local server_opts = vim.tbl_deep_extend("force", { + on_attach = on_attach, + on_init = on_init, + capabilities = capabilities, + }, opts) + + vim.lsp.config(name, server_opts) +end +vim.lsp.enable(vim.tbl_keys(servers)) diff --git a/lua/configs/mason.lua b/lua/configs/mason.lua new file mode 100644 index 000000000..ad65cf2b0 --- /dev/null +++ b/lua/configs/mason.lua @@ -0,0 +1,22 @@ +-- lua/configs/mason.lua +require("mason").setup({ + ui = { + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗" + } + } +}) + +require("mason-lspconfig").setup({ + ensure_installed = { + "pyright", + "ruff", + "html", + "cssls", + "jsonls", + "marksman", + }, + automatic_installation = true, +}) diff --git a/lua/configs/neotest.lua b/lua/configs/neotest.lua new file mode 100644 index 000000000..ef875c900 --- /dev/null +++ b/lua/configs/neotest.lua @@ -0,0 +1,16 @@ +local neotest = require "neotest" + +neotest.setup { + adapters = { + require "neotest-python" { + python = vim.fn.exepath "python", + root = vim.fn.getcwd(), + dap = { justMyCode = false }, + args = { "--verbose", "-xvs" }, + runner = "pytest", + discovery = { enabled = true }, + }, + }, +} + +return neotest diff --git a/lua/configs/none-ls.lua b/lua/configs/none-ls.lua new file mode 100644 index 000000000..e7b010828 --- /dev/null +++ b/lua/configs/none-ls.lua @@ -0,0 +1,37 @@ +local none_ls = require("none-ls") + +return { + sources = { + -- Mypy with pyproject.toml support + none_ls.builtins.diagnostics.mypy.with({ + extra_args = function(params) + local root = params.root + if root then + local pyproject_path = root .. "/pyproject.toml" + if vim.fn.filereadable(pyproject_path) == 1 then + return {"--config-file", pyproject_path} + end + end + return {} + end, + }), + + -- Ruff for linting and formatting + -- none_ls.builtins.diagnostics.ruff, + -- none_ls.builtins.formatting.ruff, + + -- Pylint if you want it + -- none_ls.builtins.diagnostics.pylint.with({ + -- extra_args = function(params) + -- local root = params.root + -- if root then + -- local pyproject_path = root .. "/pyproject.toml" + -- if vim.fn.filereadable(pyproject_path) == 1 then + -- return {"--rcfile", pyproject_path} + -- end + -- end + -- return {} + -- end, + -- }), + }, +} diff --git a/lua/configs/notebook.lua b/lua/configs/notebook.lua new file mode 100644 index 000000000..f4fe5136c --- /dev/null +++ b/lua/configs/notebook.lua @@ -0,0 +1,60 @@ +-- Notebook utilities +local M = {} + +-- Create a new notebook from a template +function M.new_notebook(filename) + -- Default filename if not provided + if not filename or filename == "" then + filename = vim.fn.input("Notebook name: ", "", "file") + if filename == "" then + print("Cancelled") + return + end + end + + -- Add .md extension if not present + if not filename:match("%.md$") then + filename = filename .. ".md" + end + + -- Create the file with a basic template + local template = [[--- +title: "]] .. filename:gsub("%.md$", "") .. [[" +jupyter: + kernelspec: + display_name: Python 3 + language: python + name: python3 +--- + +# ]] .. filename:gsub("%.md$", "") .. [[ + + +## Setup + +```{python} +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +``` + +## Analysis + +```{python} + +``` +]] + + -- Write the template to the file + vim.fn.writefile(vim.split(template, "\n"), filename) + + -- Open the file + vim.cmd("edit " .. filename) + + -- Initialize Molten for this buffer + vim.cmd("MoltenInit python3") + + print("Created notebook: " .. filename) +end + +return M diff --git a/lua/configs/overrides.lua b/lua/configs/overrides.lua new file mode 100644 index 000000000..0c6f62e81 --- /dev/null +++ b/lua/configs/overrides.lua @@ -0,0 +1,56 @@ +local M = {} + +M.treesitter = { + ensure_installed = { + "vim", + "lua", + "html", + "css", + "javascript", + "typescript", + "tsx", + "c", + "markdown", + "markdown_inline", + }, + indent = { + enable = true, + }, +} + +M.mason = { + ensure_installed = { + -- lua stuff + "lua-language-server", + "stylua", + + -- web dev stuff + "css-lsp", + "html-lsp", + "typescript-language-server", + "deno", + "prettier", + + -- c/cpp stuff + "clangd", + "clang-format", + }, +} + +-- git support in nvimtree +M.nvimtree = { + git = { + enable = true, + }, + + renderer = { + highlight_git = true, + icons = { + show = { + git = true, + }, + }, + }, +} + +return M diff --git a/lua/configs/python.lua b/lua/configs/python.lua new file mode 100644 index 000000000..6fbbd6d25 --- /dev/null +++ b/lua/configs/python.lua @@ -0,0 +1,31 @@ +local M = {} + +M.setup = function() + local lspconfig = require("lspconfig") + + -- Pyright setup + lspconfig.pyright.setup{} + + -- Null-ls setup for Black, Ruff, MyPy + local null_ls = require("null-ls") + null_ls.setup({ + sources = { + null_ls.builtins.formatting.black, -- Black + null_ls.builtins.diagnostics.ruff, -- Ruff + null_ls.builtins.diagnostics.mypy, -- MyPy + }, + }) +end + + -- Format on save using Black + vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*.py", + callback = function() + vim.lsp.buf.format({async = false}) + end, + }) + +local dap = require('dap') + +-- Set key mappings for debugging +return M diff --git a/lua/highlights.lua b/lua/highlights.lua new file mode 100644 index 000000000..ebf2dfb24 --- /dev/null +++ b/lua/highlights.lua @@ -0,0 +1,19 @@ +-- To find any highlight groups: " Telescope highlights" +-- Each highlight group can take a table with variables fg, bg, bold, italic, etc +-- base30 variable names can also be used as colors + +local M = {} + +---@type Base46HLGroupsList +M.override = { + Comment = { + italic = true, + }, +} + +---@type HLTable +M.add = { + NvimTreeOpenedFolderName = { fg = "green", bold = true }, +} + +return M diff --git a/lua/lua_snippets/all.lua b/lua/lua_snippets/all.lua new file mode 100644 index 000000000..0767c7bee --- /dev/null +++ b/lua/lua_snippets/all.lua @@ -0,0 +1,13 @@ +local ls = require "luasnip" +local s = ls.snippet +local sn = ls.snippet_node +local isn = ls.indent_snippet_node +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local r = ls.restore_node +local events = require("luasnip.util.events") +local ai = require("luasnip.nodes.absolute_indexer") + diff --git a/lua/lua_snippets/converted/markdown.json b/lua/lua_snippets/converted/markdown.json new file mode 100644 index 000000000..4b9ac67ee --- /dev/null +++ b/lua/lua_snippets/converted/markdown.json @@ -0,0 +1,316 @@ +{ + "[": { + "prefix": "[", + "body": "[${1:text}](https://${2:address})" + }, + "[\"": { + "prefix": "[\"", + "body": "[${1:text}](https://${2:address} \"${3:title}\")" + }, + "[:": { + "prefix": "[:", + "body": [ + "[${1:id}]: https://${2:url}", + "" + ] + }, + "[:\"": { + "prefix": "[:\"", + "body": [ + "[${1:id}]: https://${2:url} \"${3:title}\"", + "" + ] + }, + "![": { + "prefix": "![", + "body": "![${1:alttext}](${2:/images/image.jpg})" + }, + "![\"": { + "prefix": "![\"", + "body": "![${1:alttext}](${2:/images/image.jpg} \"${3:title}\")" + }, + "![:": { + "prefix": "![:", + "body": [ + "![${1:id}]: ${2:url}", + "" + ] + }, + "![:\"": { + "prefix": "![:\"", + "body": [ + "![${1:id}]: ${2:url} \"${3:title}\"", + "" + ] + }, + "<": { + "prefix": "<", + "body": "" + }, + "**": { + "prefix": "**", + "body": "**${1:bold}**" + }, + "__": { + "prefix": "__", + "body": "__${1:bold}__" + }, + "-": { + "prefix": "-", + "body": "- $0" + }, + "blockquote": { + "prefix": "blockquote", + "body": [ + "{% blockquote %\\}", + "${0:quote}", + "{% endblockquote %\\}", + "" + ] + }, + "blockquote-author": { + "prefix": "blockquote-author", + "body": [ + "{% blockquote ${1:author}, ${2:title} %\\}", + "${0:quote}", + "{% endblockquote %\\}", + "" + ] + }, + "blockquote-link": { + "prefix": "blockquote-link", + "body": [ + "{% blockquote ${1:author} ${2:URL} ${3:link_text} %\\}", + "${0:quote}", + "{% endblockquote %\\}", + "" + ] + }, + "```": { + "prefix": "```", + "body": [ + "```$1", + "${0:$TM_SELECTED_TEXT}", + "```", + "" + ] + }, + "```l": { + "prefix": "```l", + "body": [ + "```${1:language}", + "${2:code}", + "```", + "" + ] + }, + "codeblock-short": { + "prefix": "codeblock-short", + "body": [ + "{% codeblock %\\}", + "${0:code_snippet}", + "{% endcodeblock %\\}", + "" + ] + }, + "codeblock-full": { + "prefix": "codeblock-full", + "body": [ + "{% codeblock ${1:title} lang:${2:language} ${3:URL} ${4:link_text} %\\}", + "${0:code_snippet}", + "{% endcodeblock %\\}", + "" + ] + }, + "gist-full": { + "prefix": "gist-full", + "body": [ + "{% gist ${1:gist_id} ${0:filename} %\\}", + "" + ] + }, + "gist-short": { + "prefix": "gist-short", + "body": [ + "{% gist ${0:gist_id} %\\}", + "" + ] + }, + "img": { + "prefix": "img", + "body": [ + "{% img ${1:class} ${2:URL} ${3:width} ${4:height} ${5:title_text} ${0:alt_text} %\\}", + "" + ] + }, + "youtube": { + "prefix": "youtube", + "body": [ + "{% youtube ${0:video_id} %\\}", + "" + ] + }, + "tb": { + "prefix": "tb", + "body": [ + "| ${0:factors} | ${1:a} | ${2:b} \t|", + "| ------------- |------------- | ------- |", + "| ${3:f1} | Y | N |", + "| ${4:f2} | Y | N |", + "", + "" + ] + }, + "pullquote": { + "prefix": "pullquote", + "body": [ + "{% pullquote %\\}", + "${1:text} {\" ${2:quote} \"\\} ${0:text}", + "{% endpullquote %\\}", + "" + ] + }, + "mbf": { + "prefix": "mbf", + "description": "bold face math text", + "body": "\\mathbf{${1:$TM_SELECTED_TEXT}\\}$0" + }, + "cal": { + "prefix": "cal", + "description": "math curly text", + "body": "\\mathcal{${1:$TM_SELECTED_TEXT}\\}$0" + }, + "sc": { + "prefix": "sc", + "description": "small caps text", + "body": "\\textsc{${1:$TM_SELECTED_TEXT}\\}$0" + }, + "rm": { + "prefix": "rm", + "description": "roman font text", + "body": "\\textrm{${1:$TM_SELECTED_TEXT}\\}$0" + }, + "tt": { + "prefix": "tt", + "description": "typewriter (monospace) text", + "body": "\\texttt{${1:$TM_SELECTED_TEXT}\\}$0" + }, + "frac": { + "prefix": "frac", + "description": "\\frac{}{}", + "body": "\\frac{${1:num}\\}{${2:denom}\\} $0" + }, + "sum": { + "prefix": "sum", + "description": "\\sum^{}_{}", + "body": "\\sum^{${1:n}\\}_{${2:i=1}\\} $0" + }, + "ddt": { + "prefix": "ddt", + "description": "time derivative", + "body": [ + "\\frac{d\\}{dt\\} {$1\\} {$0\\}", + "" + ] + }, + "lim": { + "prefix": "lim", + "description": "limit", + "body": [ + "\\lim_{{$1\\}\\} {{$2\\}\\} {$0\\}", + "" + ] + }, + "pdv": { + "prefix": "pdv", + "description": "partial derivation", + "body": [ + "\\frac{\\partial {$1\\}\\}{partial {$2\\}\\} {$0\\}", + "" + ] + }, + "ppdv": { + "prefix": "ppdv", + "description": "second partial derivation", + "body": [ + "\\frac{partial^2 {$1\\}\\}{partial {$2\\} partial {$3\\}\\} {$0\\}", + "" + ] + }, + "dv": { + "prefix": "dv", + "description": "derivative", + "body": [ + "\\frac{d {$1\\}\\}{d {$2\\}\\} {$0\\}", + "" + ] + }, + "sum": { + "prefix": "sum", + "description": "summation", + "body": [ + "\\sum_{{$1\\}\\} {$0\\}", + "" + ] + }, + "dot": { + "prefix": "dot", + "description": "dot", + "body": [ + "\\dot{{$1\\}\\} {$0\\}", + "" + ] + }, + "ddot": { + "prefix": "ddot", + "description": "ddot", + "body": [ + "\\ddot{{$1\\}\\} {$0\\}", + "" + ] + }, + "vec": { + "prefix": "vec", + "description": "vector", + "body": [ + "\\vec{{$1\\}\\} {$0\\}", + "" + ] + }, + "\\x": { + "prefix": "\\x", + "description": "cross product", + "body": [ + "\\times {$0\\}", + "" + ] + }, + ".": { + "prefix": ".", + "description": "dot product", + "body": [ + "\\cdot {$0\\}", + "" + ] + }, + "int": { + "prefix": "int", + "description": "integral", + "body": "\\int_{{$1\\}\\}^{{$2\\}\\} {$3\\} : d{$4\\} {$5\\}" + }, + "tra": { + "prefix": "tra", + "description": "trace", + "body": "\\textrm{Tr\\}\\left[ $1 \\right]${0:$TM_SELECTED_TEXT}" + }, + "ra": { + "prefix": "ra", + "description": "rightarrow", + "body": "\\rightarrow {$0\\}" + }, + "theta": { + "prefix": "`w", + "dectription": "theta", + "body": "\\theta" + } +} diff --git a/lua/lua_snippets/converted/package.json b/lua/lua_snippets/converted/package.json new file mode 100644 index 000000000..37eca66fc --- /dev/null +++ b/lua/lua_snippets/converted/package.json @@ -0,0 +1,20 @@ +{ + "name": "1", + "description": "Generated by snippet-converter.nvim (https://github.com/smjonas/snippet-converter.nvim)", + "contributes": { + "snippets": [ + { + "language": [ + "markdown" + ], + "path": "./markdown.json" + }, + { + "language": [ + "markdown" + ], + "path": "./markdown.json" + } + ] + } +} diff --git a/lua/lua_snippets/plaintex.lua b/lua/lua_snippets/plaintex.lua new file mode 100644 index 000000000..277b7b90e --- /dev/null +++ b/lua/lua_snippets/plaintex.lua @@ -0,0 +1,16 @@ +local ls = require "luasnip" +local s = ls.snippet +local sn = ls.snippet_node +local isn = ls.indent_snippet_node +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local r = ls.restore_node +local events = require("luasnip.util.events") +local ai = require("luasnip.nodes.absolute_indexer") + +return { + s("tex", t("bruh")) +} diff --git a/lua/lua_snippets/plaintex/plaintex-snippets.json b/lua/lua_snippets/plaintex/plaintex-snippets.json new file mode 100644 index 000000000..806197234 --- /dev/null +++ b/lua/lua_snippets/plaintex/plaintex-snippets.json @@ -0,0 +1,7 @@ +{ + "test": { + "prefix": "metest", + "body": ["bruh"], + "description": "test" + } +} diff --git a/lua/lua_snippets/snippets/markdown.snippets b/lua/lua_snippets/snippets/markdown.snippets new file mode 100644 index 000000000..9b27ad480 --- /dev/null +++ b/lua/lua_snippets/snippets/markdown.snippets @@ -0,0 +1,215 @@ +# Markdown + +# Includes octopress (http://octopress.org/) snippets + +# The suffix `c` stands for "Clipboard". + +snippet [ + [${1:text}](https://${2:address}) +snippet [* + [${1:link}](${2:`@*`}) +snippet [c + [${1:link}](${2:`@+`}) +snippet [" + [${1:text}](https://${2:address} "${3:title}") +snippet ["* + [${1:link}](${2:`@*`} "${3:title}") +snippet ["c + [${1:link}](${2:`@+`} "${3:title}") +snippet [: + [${1:id}]: https://${2:url} + +snippet [:* + [${1:id}]: ${2:`@*`} + +snippet [:c + [${1:id}]: ${2:`@+`} + +snippet [:" + [${1:id}]: https://${2:url} "${3:title}" + +snippet [:"* + [${1:id}]: ${2:`@*`} "${3:title}" + +snippet [:"c + [${1:id}]: ${2:`@+`} "${3:title}" + +snippet ![ + ![${1:alttext}](${2:/images/image.jpg}) +snippet ![* + ![${1:alt}](${2:`@*`}) +snippet ![c + ![${1:alt}](${2:`@+`}) +snippet ![" + ![${1:alttext}](${2:/images/image.jpg} "${3:title}") +snippet !["* + ![${1:alt}](${2:`@*`} "${3:title}") +snippet !["c + ![${1:alt}](${2:`@+`} "${3:title}") +snippet ![: + ![${1:id}]: ${2:url} + +snippet ![:* + ![${1:id}]: ${2:`@*`} + +snippet ![:" + ![${1:id}]: ${2:url} "${3:title}" + +snippet ![:"* + ![${1:id}]: ${2:`@*`} "${3:title}" + +snippet ![:"c + ![${1:id}]: ${2:`@+`} "${3:title}" + +snippet < + +snippet <* + <`@*`> +snippet +snippet ** + **${1:bold}** +snippet __ + __${1:bold}__ +snippet === + `repeat('=', strlen(getline(line('.') - 3)))` + + ${0} +snippet - + - ${0} +snippet --- + `repeat('-', strlen(getline(line('.') - 3)))` + + ${0} +snippet blockquote + {% blockquote %} + ${0:quote} + {% endblockquote %} + +snippet blockquote-author + {% blockquote ${1:author}, ${2:title} %} + ${0:quote} + {% endblockquote %} + +snippet blockquote-link + {% blockquote ${1:author} ${2:URL} ${3:link_text} %} + ${0:quote} + {% endblockquote %} + +snippet ``` + \`\`\`${1} + ${0:${VISUAL}} + \`\`\` + +# Language. +snippet ```l + \`\`\`${1:language} + ${2:code} + \`\`\` + +snippet codeblock-short + {% codeblock %} + ${0:code_snippet} + {% endcodeblock %} + +snippet codeblock-full + {% codeblock ${1:title} lang:${2:language} ${3:URL} ${4:link_text} %} + ${0:code_snippet} + {% endcodeblock %} + +snippet gist-full + {% gist ${1:gist_id} ${0:filename} %} + +snippet gist-short + {% gist ${0:gist_id} %} + +snippet img + {% img ${1:class} ${2:URL} ${3:width} ${4:height} ${5:title_text} ${0:alt_text} %} + +snippet youtube + {% youtube ${0:video_id} %} + +snippet tb + | ${0:factors} | ${1:a} | ${2:b} | + | ------------- |------------- | ------- | + | ${3:f1} | Y | N | + | ${4:f2} | Y | N | + +# The quote should appear only once in the text. It is inherently part of it. +# See http://octopress.org/docs/plugins/pullquote/ for more info. + +snippet pullquote + {% pullquote %} + ${1:text} {" ${2:quote} "} ${0:text} + {% endpullquote %} + +# All taken from tex defaults +snippet mbf bold face math text + \\mathbf{${1:${VISUAL:text}}}${0} +snippet cal math curly text + \\mathcal{${1:${VISUAL:text}}}${0} +snippet sc small caps text + \\textsc{${1:${VISUAL:text}}}${0} +snippet rm roman font text + \\textrm{${1:${VISUAL:text}}}${0} +snippet tt typewriter (monospace) text + \\texttt{${1:${VISUAL:text}}}${0} +snippet frac \frac{}{} + \\frac{${1:num}}{${2:denom}} ${0} +snippet sum \sum^{}_{} + \\sum^{${1:n}}_{${2:i=1}} ${0} +snippet lim \lim_{} + \\lim_{${1:n \\to \\infty}} ${0} +# Time derivative +snippet ddt time derivative + \\frac{d}{dt} {$1} {$0} + +# Limit +snippet lim limit + \\lim_{{$1}} {{$2}} {$0} + +# Partial derivative +snippet pdv partial derivation + \\frac{\\partial {$1}}{\partial {$2}} {$0} + +# Second order partial derivative +snippet ppdv second partial derivation + \\frac{\partial^2 {$1}}{\partial {$2} \partial {$3}} {$0} + +# Ordinary derivative +snippet dv derivative + \\frac{d {$1}}{d {$2}} {$0} + +# Summation +snippet summ summation + \\sum_{{$1}} {$0} + +# Shorthand for time derivative +snippet dot dot + \\dot{{$1}} {$0} + +# Shorthand for second order time derivative +snippet ddot ddot + \\ddot{{$1}} {$0} + +# Vector +snippet vec vector + \\vec{{$1}} {$0} + +# Cross product +snippet \x cross product + \\times {$0} + +# Dot product +snippet . dot product + \\cdot {$0} + +# Integral +snippet int integral + \\int_{{$1}}^{{$2}} {$3} \: d{$4} {$5} +# Trace operator +snippet tra trace + \\textrm{Tr}\\left[ ${1} \\right]${0:${VISUAL}} +# Right arrow +snippet ra rightarrow + \\rightarrow {$0} diff --git a/lua/lua_snippets/tex.lua b/lua/lua_snippets/tex.lua new file mode 100644 index 000000000..ac279d726 --- /dev/null +++ b/lua/lua_snippets/tex.lua @@ -0,0 +1,100 @@ +local ls = require "luasnip" +local s = ls.snippet +local sn = ls.snippet_node +local isn = ls.indent_snippet_node +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local r = ls.restore_node +local events = require("luasnip.util.events") +local ai = require("luasnip.nodes.absolute_indexer") + +local tex = {} +tex.in_mathzone = function() + return vim .fn['vimtex#syntax#in_mathzone']() == 1 +end + +return { + s("ket", { + t({"\\ket{"}), + i(1), + t({"}"}), + i(0) + }, + {condition = tex.in_mathzone } + ), + s("lrb", { + t({"\\left( "}), + i(1), + t(" \\right) "), + i(0) + }), + s("lra", { + t({"\\langle "}), + i(1), + t(" \\rangle "), + i(0) + }), + s("lrs", { + t({"\\left\\[ "}), + i(1), + t(" \\right\\] "), + i(0) + }), + s("lrc", { + t({"\\left\\{ "}), + i(1), + t(" \\right\\} "), + i(0) + }), + s("~", { + t("\\tilde{"), + i(1), + t("} "), + i(0) + } + ), + s("^", { + t("\\hat{"), + i(1), + t("} "), + i(0) + } + ), + s("trm", { + t("\\textrm{"), + i(1), + t("} "), + i(0) + } + ), + s("figcirc", { + t({"\\begin{figure}[h]", + "\t\\begin{center}", + "\t\t\\begin{tikzpicture}", + "\t\t\t\\begin{yquant}", + "\t\t\t\tqubit {$\\ket{"}), + i(3), + t("}$} "), + t("q["), + i(5), + t({"];", + "\t\t\t\t"}), + i(6), + t({"", + "\t\t\t\\end{yquant}", + "\t\t\\end{tikzpicture}", + "\t\\end{center}", + "\t\\caption{"}), + i(1), + t("}\\label{fig:"), + i(2), + t({"}", + "\\end{figure}"}), + i(0) + } + ), + +} diff --git a/lua/lua_snippets/text.lua b/lua/lua_snippets/text.lua new file mode 100644 index 000000000..a28f551ee --- /dev/null +++ b/lua/lua_snippets/text.lua @@ -0,0 +1,16 @@ +local ls = require "luasnip" +local s = ls.snippet +local sn = ls.snippet_node +local isn = ls.indent_snippet_node +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local r = ls.restore_node +local events = require("luasnip.util.events") +local ai = require("luasnip.nodes.absolute_indexer") + +return { + s("test", t("bruh")) +} diff --git a/lua/lua_snippets/ultisnips/markdown.snippets b/lua/lua_snippets/ultisnips/markdown.snippets new file mode 100644 index 000000000..5a2fd467a --- /dev/null +++ b/lua/lua_snippets/ultisnips/markdown.snippets @@ -0,0 +1,284 @@ +priority -50 + +global !p +def math(): + return vim.eval('vimtex#syntax#in_mathzone()') == '1' +endglobal + +global !p +# A overkill(dirty) table with automatic alignment feature +def create_table(snip): + # retrieving single line from current string and treat it like tabstops count + placeholders_string = snip.buffer[snip.line].strip() + rows_amount = int(placeholders_string[0]) + columns_amount = int(placeholders_string[1]) + + prefix_str = "from vimsnippets import display_width;" + + # erase current line + snip.buffer[snip.line] = "" + + # create anonymous snippet with expected content and number of tabstops + anon_snippet_title = "| " + anon_snippet_delimiter = "|" + for col in range(1, columns_amount+1): + sync_rows = [x*columns_amount+col for x in range(rows_amount+1)] + sync_str = ",".join(["t[{0}]".format(x) for x in sync_rows]) + max_width_str = "max(list(map(display_width, [" + sync_str + "])))" + cur_width_str = "display_width(t[" + str(col) + "])" + rv_val = "(" + max_width_str + "-" + cur_width_str + ")*' '" + anon_snippet_title += "${" + str(col) + ":head" + str(col)\ + + "}`!p " + prefix_str + "snip.rv=" + rv_val + "` | " + anon_snippet_delimiter += ":`!p " + prefix_str + "snip.rv = "\ + + max_width_str + "*'-'" + "`-|" + + anon_snippet_title += "\n" + + anon_snippet_delimiter += "\n" + anon_snippet_body = "" + for row in range(1, rows_amount+1): + body_row = "| " + for col in range(1, columns_amount+1): + sync_rows = [x*columns_amount+col for x in range(rows_amount+1)] + sync_str = ",".join(["t[{0}]".format(x) for x in sync_rows]) + max_width_str = "max(list(map(display_width, [" + sync_str + "])))" + cur_width_str = "display_width(t[" + str(row*columns_amount+col) + "])" + rv_val = "(" + max_width_str + "-" + cur_width_str + ")*' '" + placeholder = "R{0}C{1}".format(row, col) + body_row += "${" + str(row*columns_amount+col) + ":" + placeholder\ + + "}`!p " + prefix_str + "snip.rv=" + rv_val + "` | " + + body_row += "\n" + anon_snippet_body += body_row + + anon_snippet_table = anon_snippet_title + anon_snippet_delimiter + anon_snippet_body + + # expand anonymous snippet + snip.expand_anon(anon_snippet_table) +endglobal + +########################### +# Sections and Paragraphs # +########################### +snippet sec "Section" b +# ${1:Section Name} # +$0 +endsnippet + +snippet ssec "Sub Section" b +## ${1:Section Name} ## +$0 +endsnippet + +snippet sssec "SubSub Section" b +### ${1:Section Name} ### +$0 +endsnippet + +snippet par "Paragraph" b +#### ${1:Paragraph Name} #### +$0 +endsnippet + +snippet spar "Paragraph" b +##### ${1:Paragraph Name} ##### +$0 +endsnippet + +################### +# Text formatting # +################### + +snippet * "italics" +*${1:${VISUAL}}*$0 +endsnippet + +snippet ** "bold" +**${1:${VISUAL}}**$0 +endsnippet + +snippet *** "bold italics" +***${1:${VISUAL}}***$0 +endsnippet + +snippet /* "Comment" +$0 +endsnippet + +snippet $ "Mathmode" A +\$${1:${VISUAL}}\$$0 +endsnippet + +snippet $$ "Inline Math" +\$\$ +${1:${VISUAL}} +\$\$ +$0 +endsnippet + +################ +# Common stuff # +################ +snippet link "Link to something" +[${1:${VISUAL:Text}}](${3:https://${2:www.url.com}})$0 +endsnippet + +snippet img "Image" +![${1:pic alt}](${2:path}${3/.+/ "/}${3:opt title}${3/.+/"/})$0 +endsnippet + +snippet ilc "Inline Code" i +\`${1:${VISUAL}}\`$0 +endsnippet + +snippet cbl "Codeblock" b +\`\`\`$1 +${2:${VISUAL}} +\`\`\` +$0 +endsnippet + +snippet refl "Reference Link" +[${1:${VISUAL:Text}}][${2:id}]$0 + +[$2]:${4:https://${3:www.url.com}} "${5:$4}" +endsnippet + +snippet fnt "Footnote" +[^${1:${VISUAL:Footnote}}]$0 + +[^$1]:${2:Text} +endsnippet + +snippet detail "Disclosure" + + ${1:${2}}$0 + +endsnippet + +post_jump "create_table(snip)" +snippet "tb([1-9][1-9])" "Fancy table" br +`!p snip.rv = match.group(1)` +endsnippet + +#snippet `a iA +#\\alpha +#endsnippet +#snippet `b iA +#\\beta +#endsnippet +#snippet `c iA +#\\chi +#endsnippet +#snippet `d iA +#\\delta +#endsnippet +#snippet `e iA +#\\epsilon +#endsnippet +#snippet `f iA +#\\phi +#endsnippet +#snippet `g iA +#\\gamma +#endsnippet +#snippet `h iA +#\\eta +#endsnippet +#snippet `k iA +#\\kappa +#endsnippet +#snippet `l iA +#\\lambda +#endsnippet +#snippet `m iA +#\\mu +#endsnippet +#snippet `n iA +#\\nu +#endsnippet +#snippet `o iA +#\\omega +#endsnippet +#snippet `p iA +#\\pi +#endsnippet +#snippet `q iA +#\\theta +#endsnippet +#snippet `r iA +#\\rho +#endsnippet +#snippet `s iA +#\\sigma +#endsnippet +#snippet `t iA +#\\tau +#endsnippet +#snippet `u iA +#\\upsilon +#endsnippet +#snippet `z iA +#\\zeta +#endsnippet +#snippet `D iA +#\\Delta +#endsnippet +#snippet `F iA +#\\Phi +#endsnippet +#snippet `G iA +#\\Gamma +#endsnippet +#snippet `L iA +#\\Lambda +#endsnippet +#snippet `N iA +#\\nabla +#endsnippet +#snippet `O iA +#\\Omega +#endsnippet +#snippet `Q iA +#\\Theta +#endsnippet +#snippet `R iA +#\\varrho +#endsnippet +#snippet `U iA +#\\Upsilon +#endsnippet +#snippet `X iA +#\\Xi +#endsnippet +#snippet `Y iA +#\\Psi +#endsnippet +#snippet `i iA +#\\int_{$1}^{$2} +#endsnippet +#snippet `S iA +#\\sum_{$1}^{$2} +#endsnippet +#snippet `8 iA +#\\infty +#endsnippet +#snippet `= iA +#\\equiv +#endsnippet +#snippet `. iA +#\\cdot +#endsnippet +#snippet `~ iA +#\\tilde{$1} +#endsnippet +#snippet `^ iA +#\\hat{$1} +#endsnippet +#snippet `; iA +#\\dot{$1} +#endsnippet +#snippet \`_ iA +#\\bar{$1} +#endsnippet +# vim:ft=snippets: diff --git a/lua/mappings.lua b/lua/mappings.lua index 783b78f9c..b668a2694 100644 --- a/lua/mappings.lua +++ b/lua/mappings.lua @@ -1,10 +1,108 @@ require "nvchad.mappings" +local map = vim.keymap.set --- add yours here +-- Normal Mode +map("n", ";", ":", {desc = "enter command mode", nowait = true}) +map("n", "j", "j", {desc = "Disable wrapping" }) +map("n", "k", "k", {desc = "Disable wrapping" }) -local map = vim.keymap.set +map("n", "", ':lua require"dap".continue()', {desc= "Debug continue", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".terminate()', {desc= "Debug Terminate", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".restart()', {desc= "Debug Restart", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".step_over()', {desc= "Step Over", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".step_into()', {desc= "Step Into", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".step_out()', {desc= "Step Out", noremap = true, silent = true } ) +map("n", "", ':lua require"dap".toggle_breakpoint()', {desc = "Toggle Breakpoint", noremap = true, silent = true }) +map("n", "dc", ":lua require'dapui'.toggle()", {desc = "Debug: Toggle UI" }) +map("n", "ds", ":lua require'neogen'.generate()", {desc = "Debug: Test Method" }) + +map("n", "tt", ":lua require'neotest'.run.run()", {desc = "Neotest: Run test" }) +map("n", "dtm", ":lua require'neotest'.run.run({strategy = 'dap'})", {desc = "Neotest: Debug test" }) +map("n", "ts", ":lua require'neotest'.summary.toggle()", {desc = "Neotest: Toggle test summary" }) +map("n", "tp", ":lua require'neotest'.output_panel.toggle()", {desc = "Neotest: Toggle output panel" }) + +map("n", "ac", ":CopilotChat ", {desc = "CopilotChat - Prompt" }) +map("n", "ae", ":CopilotChatExplain", {desc = "CopilotChat - Explain code" }) +map("n", "at", ":CopilotChatTests", {desc = "CopilotChat - Generate tests" }) +map("n", "af", ":CopilotChatFix", {desc = "CopilotChat - Fix code" }) +map("n", "ar", ":CopilotChatReview", {desc = "CopilotChat - Review code" }) +map("n", "aw", ":CopilotChatToggle", {desc = "CopilotChat - Toggle Window" }) +map("n", "aq", + function() + local input = vim.fn.input "Quick Chat: " + if input ~= "" then + require("CopilotChat").ask(input, { + selection = require("CopilotChat.select").buffer, + }) + end + end, + {desc = "CopilotChat - Quick chat"}) + +-- Molten/Quarto (Jupyter) - context-aware keybindings +vim.api.nvim_create_autocmd("FileType", { + pattern = { "python", "markdown" }, + callback = function() + local buf = vim.api.nvim_get_current_buf() + + -- Use Ctrl-Enter for running cells (works in both Python and Markdown notebooks) + vim.keymap.set("n", "", function() + -- Use QuartoSend if available (for markdown), otherwise MoltenEvaluateLine + local has_quarto = pcall(require, "quarto") + if has_quarto and vim.bo.filetype == "markdown" then + require("quarto.runner").run_cell() + else + vim.cmd("MoltenEvaluateLine") + end + end, {desc = "Run cell", buffer = buf, silent = true}) + + vim.keymap.set("v", "", function() + local has_quarto = pcall(require, "quarto") + if has_quarto and vim.bo.filetype == "markdown" then + require("quarto.runner").run_range() + else + vim.cmd("MoltenEvaluateVisual") + end + end, {desc = "Run selection", buffer = buf, silent = true}) + + -- Molten-specific keybindings (use localleader to avoid conflicts) + vim.keymap.set("n", "mi", ":MoltenInit", {desc = "Initialize kernel", buffer = buf, silent = true}) + vim.keymap.set("n", "e", ":MoltenEvaluateOperator", {desc = "Evaluate operator", buffer = buf, silent = true}) + vim.keymap.set("n", "rr", ":MoltenReevaluateCell", {desc = "Re-evaluate cell", buffer = buf, silent = true}) + vim.keymap.set("n", "rd", ":MoltenDelete", {desc = "Delete cell", buffer = buf, silent = true}) + vim.keymap.set("n", "oh", ":MoltenHideOutput", {desc = "Hide output", buffer = buf, silent = true}) + vim.keymap.set("n", "os", ":noautocmd MoltenEnterOutput", {desc = "Open output window", buffer = buf, silent = true}) + vim.keymap.set("v", "r", ":MoltenEvaluateVisualgv", {desc = "Execute visual selection", buffer = buf, silent = true}) + + -- Quarto navigation (only in markdown) + if vim.bo.filetype == "markdown" then + vim.keymap.set("n", "]c", function() require("quarto.runner").run_cell() end, {desc = "Run cell and move next", buffer = buf, silent = true}) + vim.keymap.set("n", "[c", function() require("quarto.runner").run_above() end, {desc = "Run cell above", buffer = buf, silent = true}) + end + end, +}) + +-- Visual mode + +-- map("v", ">", ">gv", {desc = "indent" }) +-- map("v", "ac", ":CopilotChat ", {desc = "CopilotChat - Prompt" }) +-- map("v", "ae", ":CopilotChatExplain", {desc = "CopilotChat - Explain code" }) +-- map("v", "at", ":CopilotChatTests", {desc = "CopilotChat - Generate tests" }) +-- map("v", "af", ":CopilotChatFix", {desc = "CopilotChat - Fix code" }) +-- map("v", "ar", ":CopilotChatReview", {desc = "CopilotChat - Review code" }) + + +-- Insert Mode +map("i", ";;", "", {desc = "Enter normal mode", nowait = true } ) -map("n", ";", ":", { desc = "CMD enter command mode" }) -map("i", "jk", "") +map({"i", "n"}, "", + function() + require("nvchad.term").toggle {pos = "sp", id="htoggleterm"} + end, + {desc = "Toggle horizontal term",} +) --- map({ "n", "i", "v" }, "", " w ") +map("i", "", "u[s1z=`]au", {desc = "Autocorrect spelling" }) +map("i", "", + 'copilot#Accept("")', + {desc ="Accept Copilot suggestion", silent = true, expr = true, noremap = false, replace_keycodes = false } +) diff --git a/lua/myinit.lua b/lua/myinit.lua new file mode 100644 index 000000000..c19984bdb --- /dev/null +++ b/lua/myinit.lua @@ -0,0 +1,145 @@ +vim.opt.spelllang = "en_gb" +vim.opt.spell = true + +-- Suppress network connectivity errors from Copilot/GitHub API +-- This filters out DNS resolution failures and connection timeouts +-- while still showing other important errors +local original_notify = vim.notify +vim.notify = function(msg, level, opts) + -- Patterns to ignore (network-related errors) + local ignore_patterns = { + "Could not resolve host", + "curl error exit_code=6", + "curl error exit_code=7", -- Failed to connect + "curl error exit_code=28", -- Timeout + "api%.github%.com", + "api%.githubcopilot%.com", + "cannot resume dead coroutine", -- Consequence of network errors + } + + -- Check if message matches any ignore pattern + for _, pattern in ipairs(ignore_patterns) do + if msg and type(msg) == "string" and msg:match(pattern) then + -- Silently ignore this error + return + end + end + + -- For all other messages, use original notify + original_notify(msg, level, opts) +end + +-- Also suppress error display for network-related callback failures +vim.api.nvim_create_autocmd("FileType", { + pattern = "*", + callback = function() + -- Override error display to filter network errors + local original_errmsg = vim.api.nvim_err_writeln + vim.api.nvim_err_writeln = function(msg) + -- Check if this is a network-related error + if msg and type(msg) == "string" then + local network_error_patterns = { + "Could not resolve host", + "curl error exit_code=[678]", + "curl error exit_code=28", + "api%.github", + "cannot resume dead coroutine", + } + + for _, pattern in ipairs(network_error_patterns) do + if msg:match(pattern) then + return -- Silently ignore + end + end + end + + -- Show all other errors + original_errmsg(msg) + end + end, + once = true, +}) + +-- local parser_config = require('nvim-treesitter.parsers').get_parser_configs() +-- +-- parser_config.stim = { +-- install_info = { +-- url = "/Users/andrewpatterson/stim-tresitter/", -- Local path to this repository +-- files = {"src/parser.c"}, +-- branch = "main", +-- generate_requires_npm = false, +-- requires_generate_from_grammar = true, +-- }, +-- filetype = "stim", +-- } +-- +-- require('nvim-treesitter.configs').setup({ +-- ensure_installed = { +-- -- your other parsers... +-- }, +-- +-- highlight = { +-- enable = true, +-- additional_vim_regex_highlighting = false, +-- }, +-- auto_install = false, -- Prevent conflicts +-- +-- -- Explicitly configure stim +-- parser_install_dir = vim.fn.stdpath("data") .. "/tree-sitter-parsers", +-- }) + + -- Force reload stim filetype +vim.treesitter.language.register("stim", "stim") +vim.filetype.add({ + extension = { + stim = 'stim', + }, + filename = { + ['*.stim'] = 'stim', + }, +}) +-- package.path = package.path .. ';/Users/andrewpatterson/stim-treesitter/?.lua' +-- local ok, result = pcall(function() +-- return loadfile('/Users/andrewpatterson/stim-tresitter/lua/stim-treesitter.lua') +-- end) +-- +-- if ok and result then +-- print("File found and loadable") +-- local module = result() +-- print("Module type:", type(module)) +-- +-- if module then +-- print("Module contents:") +-- for k, v in pairs(module) do +-- print(" " .. k .. ": " .. type(v)) +-- end +-- +-- if module.setup then +-- print("Setup function found, calling it...") +-- module.setup() +-- print("Setup completed successfully") +-- else +-- print("No setup function found in module") +-- end +-- else +-- print("Module is nil") +-- end +-- else +-- print("File not found or not loadable: " .. tostring(result)) +-- end +-- Load and setup the plugin +-- require('stim-treesitter').setup() +-- local stim_treesitter_module = loadfile('/Users/andrewpatterson/stim-tresitter/lua/stim-treesitter.lua')() +-- stim_treesitter_module.setup() +-- +-- -- Optional: Set up keybindings +-- vim.keymap.set('n', 'si', ':StimInfoTS', { desc = 'Stim: Show measurement info' }) + +-- Notebook utilities +vim.api.nvim_create_user_command("NewNotebook", function(opts) + require("configs.notebook").new_notebook(opts.args) +end, { + nargs = "?", + complete = "file", + desc = "Create a new Jupyter notebook (markdown format)", +}) diff --git a/lua/overrides.lua b/lua/overrides.lua new file mode 100644 index 000000000..398ee957b --- /dev/null +++ b/lua/overrides.lua @@ -0,0 +1,55 @@ +local M = {} + +local has_words_before = function() + unpack = unpack or table.unpack + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil +end +local cmp = require("cmp") + +M.cmp = { + + mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + -- [""] = cmp.mapping.confirm { + -- behavior = cmp.ConfirmBehavior.Insert, + -- select = true, + -- }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.confirm { + behavior = cmp.ConfirmBehavior.Insert, + select = true, + } + elseif require("luasnip").expand_or_jumpable() then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-expand-or-jump", true, true, true), "") + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-jump-prev", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }), + }, +} + +return M diff --git a/lua/plugins/myplugins.lua b/lua/plugins/myplugins.lua new file mode 100644 index 000000000..d582daf2f --- /dev/null +++ b/lua/plugins/myplugins.lua @@ -0,0 +1,479 @@ +local overrides = require "configs.overrides" +local has_words_before = function() + unpack = unpack or table.unpack + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil +end +local cmp = require "cmp" + +---@type NvPluginSpec[] +local plugins = { + + -- Override plugin definition options + { + "mfussenegger/nvim-lint", + event = { + "BufReadPre", + "BufNewFile", + }, + config = function() + require("configs.lint").setup() + end, + }, + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + config = function() + require "nvchad.configs.lspconfig" + require "configs.lspconfig" + end, -- Override to setup mason-lspconfig + }, + { + "nvimtools/none-ls.nvim", + -- event = "VeryLazy", + dependencies = { "nvim-lua/plenary.nvim" }, + config = function() + local none_ls = require("none-ls") + none_ls.setup(require("configs.none-ls")) + end, + }, + + -- override plugin configs + { + "williamboman/mason.nvim", + opts = overrides.mason, + }, + + { + "nvim-treesitter/nvim-treesitter", + opts = overrides.treesitter, + }, + + { + "nvim-tree/nvim-tree.lua", + opts = overrides.nvimtree, + }, + { + "hrsh7th/nvim-cmp", + opts = function() + local conf = require "nvchad.configs.cmp" + conf.mapping[""] = cmp.mapping { + i = function(fallback) + if cmp.visible() and cmp.get_active_entry() then + cmp.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false } + else + fallback() + end + end, + s = cmp.mapping.confirm { select = true }, + c = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true }, + } + conf.mapping[""] = cmp.mapping(function(fallback) + if cmp.visible() then + local entry = cmp.get_selected_entry() + if not entry then + cmp.select_next_item { behavior = cmp.SelectBehavior.Select } + else + cmp.confirm() + end + elseif require("luasnip").expand_or_jumpable() then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-expand-or-jump", true, true, true), "") + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { + "i", + "s", + -- "c", + }) + conf.mapping[""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif require("luasnip").jumpable(-1) then + vim.fn.feedkeys(vim.api.nvim_replace_termcodes("luasnip-jump-prev", true, true, true), "") + else + fallback() + end + end, { + "i", + "s", + }) + return conf + end, + }, + { + "L3MON4D3/LuaSnip", + opts = overrides.luasnip, + config = function() + require("luasnip.loaders.from_lua").lazy_load { paths = { vim.fn.stdpath "config" .. "/lua/custom/lua_snippets" } } + require("luasnip.loaders.from_vscode").lazy_load { + paths = { vim.fn.stdpath "config" .. "/lua/custom/lua_snippets/converted" }, + } + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + + -- Install a plugin + { + "max397574/better-escape.nvim", + event = "InsertEnter", + config = function() + require("better_escape").setup() + end, + }, + + { + "lervag/vimtex", + lazy = false, + config = function() + vim.api.nvim_create_autocmd({ "FileType" }, { + group = vim.api.nvim_create_augroup("lazyvim_vimtex_conceal", { clear = true }), + pattern = { "bib", "tex" }, + callback = function() + vim.wo.conceallevel = 2 + end, + }) + vim.g.vimtex_mappings_disable = { ["n"] = { "K" } } + vim.g.vimtex_quickfix_method = vim.fn.executable "pplatex" == 1 and "pplatex" or "latexlog" + vim.g.tex_flavor = "luatex" + vim.g.vimtex_quickfix_mode = 0 + vim.g.vimtex_compiler_latexmk = { out_dir = "build" } + vim.g.vimtex_view_general_viewer = "zathura" + vim.g.vimtex_viewer_zathura = 1 + vim.g.vimtex_compiler_method = "latexmk" + vim.g.vimtex_compiler_latexmk_engines = { + _ = '-lualatex' + } + vim.g.vimtex_compiler_latexmk = { + build_dir = "build", + aux_dir = "build", + out_dir = "build", + options = { + "-verbose", + "-file-line-error", + "-synctex=1", + "-interaction=nonstopmode", + }, + } + end, + }, + + { + "smjonas/snippet-converter.nvim", + config = function() + local template = { + sources = { + ultisnips = { + vim.fn.stdpath "config" .. "/lua/custom/lua_snippets/ultisnips", + }, + snipmate = { + vim.fn.stdpath "config" .. "/lua/custom/lua_snippets/snippets", + }, + }, + output = { + vscode_luasnip = { + vim.fn.stdpath "config" .. "/lua/custom/lua_snippets/converted", + }, + }, + } + + require("snippet_converter").setup { + templates = { template }, + } + end, + }, + { + "preservim/vim-markdown", + config = function() + vim.g.vim_markdown_math = 1 + end, + }, + { + "mfussenegger/nvim-dap", + dependencies = { + "mfussenegger/nvim-dap-python", + config = function() + require("dap-python").setup "~/.virtualenvs/debugpy/bin/python" + require("dap-python").test_runner = "pytest" + end, + }, + config = function() + local dap = require "dap" + dap.adapters.python = { + type = "executable", + command = "python", + args = { "-m", "debugpy.adapter" }, + } + dap.configurations.python = { + { + type = "python", + request = "launch", + name = "Launch file", + program = "${file}", -- This will launch the current file + pythonPath = function() + return "python" + end, + }, + } + require "configs.python" + end, + }, + { + "rcarriga/nvim-dap-ui", + dependencies = { + "mfussenegger/nvim-dap", + "nvim-neotest/nvim-nio", + }, + config = function() + require "configs.dapui" + end, + }, + { + "nvim-neotest/neotest", + dependencies = { + "nvim-neotest/neotest-python", + "nvim-neotest/nvim-nio", + "nvim-lua/plenary.nvim", + "antoinemadec/FixCursorHold.nvim", + "nvim-treesitter/nvim-treesitter", + }, + ft = "python", + config = function() + require "configs.neotest" + end, + -- config = function() + -- require("neotest").setup { + -- adapters = { + -- require "neotest-python" { + -- python = vim.fn.expand "python", + -- root = function() + -- return vim.fn.getcwd() + -- end, + -- dap = { justMyCode = false }, + -- args = { "--log-level", "DEBUG", "--verbose", "-xvs" }, + -- runner = "pytest", + -- discovery = { + -- enabled = true, + -- }, + -- is_test_file = function(filename) + -- return filename:match "^tests?%.?py$" or filename:match "^test_.+%.py$" or filename:match "%.test_.+%.py$" + -- end, + -- pytest_discover_instances = true, + -- }, + -- }, + -- } + -- end, + }, + { + "danymat/neogen", + dependencies = "nvim-treesitter/nvim-treesitter", + config = true, + ft = { "python", "javascript", "typescript", "lua" }, -- Add filetypes you need + opts = { + enabled = true, + languages = { + python = { + template = { + annotation_convention = "reST", -- or "google_docstrings" or "reST" + }, + }, + }, + }, + }, + { + "github/copilot.vim", + lazy = false, + config = function() + vim.g.copilot_no_tab_map = true + vim.g.copilot_assume_mapped = true + vim.api.nvim_set_keymap("i", "", 'copilot#Accept("")', { silent = true, expr = true }) + end, + }, + { + "yetone/avante.nvim", + event = "VeryLazy", + version = false, + build = "make", + dependencies = { + "nvim-lua/plenary.nvim", + "MunifTanjim/nui.nvim", + "nvim-tree/nvim-web-devicons", + "nvim-tree/nvim-tree.lua", + "github/copilot.vim", + }, + opts = { + provider = "copilot", + providers = { + copilot = { + endpoint = "https://api.githubcopilot.com", + model = "gpt-4.1-2025-04-14", + timeout = 30000, + temperature = 0, + extra_request_body = { + max_tokens = 4096, + }, + }, + }, + behaviour = { + support_paste_from_clipboard = true, + }, + windows = { + sidebar_header = { + enabled = true, + }, + }, + mappings = { + files = { + enabled = true, + }, + }, + }, + }, + { + "CopilotC-Nvim/CopilotChat.nvim", + lazy = false, + -- branch = "canary", + dependencies = { + { "nvim-lua/plenary.nvim" }, + }, + build = "make tiktoken", + opts = { + question_header = "## User ", + answer_header = "## Copilot ", + error_header = "## Error ", + { + -- model = 3gpt-4.1', -- AI model to use + temperature = 0.1, -- Lower = focused, higher = creative + window = { + layout = "vertical", -- 'vertical', 'horizontal', 'float' + width = 0.3, -- 50% of screen width + }, + auto_insert_mode = true, -- Enter insert mode when opening + }, + }, + }, + { + "ravitemer/mcphub.nvim", + lazy = false, + dependencies = { + "CopilotC-Nvim/CopilotChat.nvim", + }, + config = function() + require("mcphub").setup({ + extensions = { + copilotchat = { + enabled = true, + convert_tools_to_functions = true, + convert_resources_to_functions = true, + add_mcp_prefix = false, + }, + }, + }) + end, + }, + + { + "nvim-telescope/telescope.nvim", + opts = overrides.telescope, + }, + + -- Jupyter notebook support + { + "benlubas/molten-nvim", + version = "^1.0.0", + build = ":UpdateRemotePlugins", + ft = { "python", "markdown" }, + cmd = { "MoltenInit", "MoltenInfo" }, + init = function() + vim.g.molten_image_provider = "image.nvim" + vim.g.molten_output_win_max_height = 20 + vim.g.molten_auto_open_output = false + vim.g.molten_wrap_output = true + vim.g.molten_virt_text_output = true + vim.g.molten_virt_lines_off_by_1 = true + end, + }, + { + "3rd/image.nvim", + opts = { + backend = "kitty", + integrations = { + markdown = { + enabled = true, + clear_in_insert_mode = false, + download_remote_images = true, + only_render_image_at_cursor = false, + filetypes = { "markdown", "vimwiki" }, + }, + }, + max_width = nil, + max_height = nil, + max_width_window_percentage = nil, + max_height_window_percentage = 50, + window_overlap_clear_enabled = false, + window_overlap_clear_ft_ignore = { "cmp_menu", "cmp_docs", "" }, + editor_only_render_when_focused = false, + tmux_show_only_in_active_window = false, + hijack_file_patterns = { "*.png", "*.jpg", "*.jpeg", "*.gif", "*.webp" }, + }, + }, + { + "quarto-dev/quarto-nvim", + ft = { "quarto", "markdown" }, + dependencies = { + "jmbuhr/otter.nvim", + "nvim-treesitter/nvim-treesitter", + }, + config = function() + require("quarto").setup { + lspFeatures = { + enabled = false, -- Disable to use your existing LSP setup + languages = { "r", "python", "julia", "bash", "lua", "html" }, + }, + codeRunner = { + enabled = true, + default_method = "molten", + }, + } + end, + }, + { + "GCBallesteros/jupytext.nvim", + ft = { "markdown" }, + opts = { + style = "markdown", + output_extension = "md", + force_ft = "markdown", + }, + }, + { + "DuckTigger/stim-treesitter-parser", + event = "VeryLazy", -- ensure it loads at startup so :TSInstall stim works + dependencies = { "nvim-treesitter/nvim-treesitter" }, + config = function() + require("stim-treesitter-config").setup({ + -- defaults shown: + highlight_measurements = true, + keymaps = { show_info = "si" }, + }) + end, + }, + + -- To make a plugin not be loaded + -- { + -- "NvChad/nvim-colorizer.lua", + -- enabled = false + -- }, + + -- All NvChad plugins are lazy-loaded by default + -- For a plugin to be loaded, you will need to set either `ft`, `cmd`, `keys`, `event`, or set `lazy = false` + -- If you want a plugin to load on startup, add `lazy = false` to a plugin spec, for example + -- { + -- "mg979/vim-visual-multi", + -- lazy = false, + -- } +} + +return plugins