From 972e5f9c68cc433c5fc26adf92cd25b293a3776a Mon Sep 17 00:00:00 2001 From: brustybee Date: Mon, 9 Mar 2026 17:02:03 +0530 Subject: One shot upload --- lua/colorscheme_persistence.lua | 50 ++++++++++++++ lua/config/colorschemes.lua | 82 +++++++++++++++++++++++ lua/config/init.lua | 4 ++ lua/config/keys.lua | 35 ++++++++++ lua/config/lsp.lua | 91 +++++++++++++++++++++++++ lua/config/options.lua | 51 +++++++++++++++ lua/nixCatsUtils/lzUtils.lua | 36 ++++++++++ lua/plugins/ai.lua | 29 ++++++++ lua/plugins/completion.lua | 65 ++++++++++++++++++ lua/plugins/debug.lua | 90 +++++++++++++++++++++++++ lua/plugins/formatter.lua | 46 +++++++++++++ lua/plugins/general.lua | 94 ++++++++++++++++++++++++++ lua/plugins/git.lua | 98 +++++++++++++++++++++++++++ lua/plugins/init.lua | 12 ++++ lua/plugins/linter.lua | 40 +++++++++++ lua/plugins/misc.lua | 50 ++++++++++++++ lua/plugins/picker.lua | 142 ++++++++++++++++++++++++++++++++++++++++ lua/plugins/tsitter.lua | 115 ++++++++++++++++++++++++++++++++ 18 files changed, 1130 insertions(+) create mode 100644 lua/colorscheme_persistence.lua create mode 100644 lua/config/colorschemes.lua create mode 100644 lua/config/init.lua create mode 100644 lua/config/keys.lua create mode 100644 lua/config/lsp.lua create mode 100644 lua/config/options.lua create mode 100644 lua/nixCatsUtils/lzUtils.lua create mode 100644 lua/plugins/ai.lua create mode 100644 lua/plugins/completion.lua create mode 100644 lua/plugins/debug.lua create mode 100644 lua/plugins/formatter.lua create mode 100644 lua/plugins/general.lua create mode 100644 lua/plugins/git.lua create mode 100644 lua/plugins/init.lua create mode 100644 lua/plugins/linter.lua create mode 100644 lua/plugins/misc.lua create mode 100644 lua/plugins/picker.lua create mode 100644 lua/plugins/tsitter.lua (limited to 'lua') diff --git a/lua/colorscheme_persistence.lua b/lua/colorscheme_persistence.lua new file mode 100644 index 0000000..e5f6cda --- /dev/null +++ b/lua/colorscheme_persistence.lua @@ -0,0 +1,50 @@ +local M = {} + +-- (~/.local/share/nvim/last_theme.txt) +local theme_cache_path = vim.fn.stdpath("data") .. "/last_theme.txt" + +M.is_programmatic_change = false + +function M.load_theme() + local theme = "" + + local f = io.open(theme_cache_path, "r") + if f then + theme = f:read("*all"):gsub("%s+", "") + f:close() + end + + if theme == "" then + theme = nixCats.extra("colorscheme") + end + + M.is_programmatic_change = true + local status, _ = pcall(vim.cmd.colorscheme, theme) + + -- just to be safe + if not status then + vim.cmd.colorscheme("habamax") + end +end + +vim.api.nvim_create_autocmd("ColorScheme", { + callback = function(args) + -- If the change was programmatic (like at startup), don't overwrite the file + if M.is_programmatic_change then + M.is_programmatic_change = false -- Reset for the next manual change + return + end + + -- Save the new theme name to the file + local theme_name = args.match + local f = io.open(theme_cache_path, "w") + if f then + f:write(theme_name) + f:close() + end + end, +}) + +M.load_theme() + +return M diff --git a/lua/config/colorschemes.lua b/lua/config/colorschemes.lua new file mode 100644 index 0000000..f09ecd3 --- /dev/null +++ b/lua/config/colorschemes.lua @@ -0,0 +1,82 @@ +if nixCats("theme") then + require("vague").setup({ + transparent = true, + bold = false, + }) + + require("gruvbox-material").setup({ + italics = true, + contrast = "medium", + comments = { + italics = true, + }, + background = { + transparent = true, + }, + float = { + force_background = true, + background_color = nil, + }, + }) + + require("kanso").setup({ + compile = true, + transparent = true, + dimInactive = false, + terminalColors = true, + overrides = function(colors) + local theme = colors.theme + return { + Pmenu = { fg = theme.ui.fg, bg = theme.ui.bg_p1 }, + NormalFloat = { bg = theme.ui.bg_p1 }, + FloatTitle = { fg = theme.ui.special, bg = theme.ui.bg_p1 }, + FloatBorder = { fg = theme.ui.shade0, bg = theme.ui.bg_p1 }, + } + end, + background = { + dark = "ink", + light = "pearl", + }, + foreground = "default", + }) + + require("rose-pine").setup({ + styles = { + bold = true, + italic = true, + transparency = true, + }, + }) + + require("kanagawa").setup({ + compile = true, + undercurl = true, + commentStyle = { italic = true }, + functionStyle = {}, + keywordStyle = { italic = true }, + statementStyle = { bold = true }, + typeStyle = {}, + transparent = true, + dimInactive = false, + terminalColors = true, + colors = { + palette = {}, + theme = { + wave = {}, + lotus = {}, + dragon = {}, + all = { ui = { bg_gutter = "none" } }, + }, + }, + overrides = function(colors) + return {} + end, + theme = "dragon", + background = { + dark = "dragon", + light = "lotus", + }, + }) +end + +return {} diff --git a/lua/config/init.lua b/lua/config/init.lua new file mode 100644 index 0000000..2be1996 --- /dev/null +++ b/lua/config/init.lua @@ -0,0 +1,4 @@ +require("config.options") +require("config.colorschemes") +require("config.keys") +require("config.lsp") diff --git a/lua/config/keys.lua b/lua/config/keys.lua new file mode 100644 index 0000000..518b9c1 --- /dev/null +++ b/lua/config/keys.lua @@ -0,0 +1,35 @@ +vim.keymap.set("v", "J", ":m '>+1gv=gv", { silent = true }) +vim.keymap.set("v", "K", ":m '<-2gv=gv", { silent = true }) + +vim.keymap.set("n", "J", "mzJ`z", { silent = true }) +vim.keymap.set("n", "", "zz", { silent = true }) +vim.keymap.set("n", "", "zz", { silent = true }) +vim.keymap.set("n", "n", "nzzzv", { silent = true }) +vim.keymap.set("n", "N", "Nzzzv", { silent = true }) +vim.keymap.set({ "n", "v" }, "y", [["+y]]) +vim.keymap.set({ "n", "v" }, "d", [["_d"]]) + +vim.keymap.set("n", "q:", "") -- disable that annoying cmd history buffer thingy + +vim.keymap.set("n", "", "cnextzz") +vim.keymap.set("n", "", "cprevzz") +vim.keymap.set("n", "k", "lnextzz") +vim.keymap.set("n", "j", "lprevzz") +vim.keymap.set("n", "bn", "bn") +vim.keymap.set("n", "bp", "bp") + +vim.keymap.set("n", "u", [[:%s/\<\>//gI]]) +vim.keymap.set("n", "px", "!chmod +x %") +vim.keymap.set("n", "", "nohlsearch") + +local function hover_cap(opts) + opts = vim.tbl_deep_extend("force", opts or {}, { + max_width = 100, + max_height = 25, + wrap = true, + }) + return vim.lsp.buf.hover(opts) +end + +vim.keymap.set("n", "K", hover_cap, { silent = true }) +-- vim.keymap.set("n", "rn", vim.lsp.buf.rename, { desc = "Rename Symbol" }) diff --git a/lua/config/lsp.lua b/lua/config/lsp.lua new file mode 100644 index 0000000..2e7cf05 --- /dev/null +++ b/lua/config/lsp.lua @@ -0,0 +1,91 @@ +vim.lsp.inlay_hint.enable(true) +vim.lsp.enable({ + "clangd", + "lua_ls", + "nixd", + "nil_ls", + "zls", + "pyrefly", + "marksman", + "harper", + "tinymist", + "gopls", + "tombi", +}) + +vim.lsp.config("nil_ls", { + settings = { + formatting = { + command = { "nixfmt" }, + }, + }, +}) + +vim.lsp.config("lua_ls", { + settings = { + Lua = { + codeLens = { enable = true }, + hint = { + enable = true, + semicolon = "Disable", + }, + workspace = { + checkThirdParty = false, + -- IMPORTANT: Leave library empty here. + -- lazydev will inject the correct Nix store paths dynamically. + library = {}, + }, + runtime = { + version = "LuaJIT", + -- Setting this to false allows lazydev to find files + -- outside your immediate workspace (like Nix store plugins) + pathStrict = false, + }, + }, + }, +}) + +vim.lsp.config("*", { + capabilities = { textDocument = { semanticTokens = { multilineTokenSupport = true } } }, + root_markers = { ".git", ".editorconfig", "flake.nix", "shell.nix" }, +}) + +vim.diagnostic.config({ + severity_sort = true, + severity_sort_priority = { + Error = 100, + Warn = 90, + Hint = 50, + Info = 10, + }, +}) + +local RustLsp = function(mode, keymap, action, bufnr) + vim.keymap.set(mode, keymap, function() + vim.cmd.RustLsp(action) + end, { silent = true, buffer = bufnr }) +end + +vim.g.rustaceanvim = { + tools = {}, + server = { + on_attach = function(client, bufnr) + RustLsp({ "n", "x" }, "gra", "codeAction", bufnr) + RustLsp("n", "ee", "explainError", bufnr) + RustLsp("n", "K", { "hover", "actions" }, bufnr) + RustLsp("n", "L", { "hover", "range" }, bufnr) + end, + default_settings = { + ["rust-analyzer"] = { + checkOnSave = { + enable = false, + command = "clippy", + }, + procMacro = { + enable = true, + }, + }, + }, + }, + dap = {}, +} diff --git a/lua/config/options.lua b/lua/config/options.lua new file mode 100644 index 0000000..c50b859 --- /dev/null +++ b/lua/config/options.lua @@ -0,0 +1,51 @@ +vim.loader.enable() +vim.g.mapleader = " " +vim.g.maplocalleader = " " +vim.o.updatetime = 1500 + +vim.opt.inccommand = "split" + +vim.opt.undofile = false +vim.opt.undodir = vim.fn.expand("~/.local/share/nvim/undo") + +vim.o.termguicolors = true +-- vim.opt.guicursor = "n-v-c-sm:block,ci-ve:ver25,r-cr-o:hor20" +vim.o.showmode = true +vim.o.showcmd = false +vim.o.signcolumn = "yes" +vim.o.cursorline = true +vim.o.cursorlineopt = "number" -- Restricts the highlight ONLY to the number column +vim.o.background = "dark" +vim.o.conceallevel = 2 +vim.o.autoread = true + +vim.o.nu = true +vim.o.relativenumber = true + +vim.o.mouse = "" +vim.o.scrolloff = 21 +vim.g.loaded_netrwPlugin = 1 +vim.g.loaded_netrw = 1 + +vim.o.expandtab = true +vim.o.tabstop = 4 +vim.o.softtabstop = 4 +vim.o.shiftwidth = 4 +vim.o.smartindent = false +vim.o.smarttab = true +vim.o.breakindent = true +vim.o.autoindent = true + +vim.o.wrap = false +vim.o.linebreak = false + +vim.o.hlsearch = true +vim.o.incsearch = true + +vim.o.title = true +vim.o.swapfile = false + +vim.opt.foldlevel = 99 +vim.opt.foldlevelstart = 99 +vim.opt.foldenable = true +vim.o.foldmethod = "expr" diff --git a/lua/nixCatsUtils/lzUtils.lua b/lua/nixCatsUtils/lzUtils.lua new file mode 100644 index 0000000..2e2393d --- /dev/null +++ b/lua/nixCatsUtils/lzUtils.lua @@ -0,0 +1,36 @@ +--[[ + This directory is the luaUtils template. + You can choose what things from it that you would like to use. + And then delete the rest. + Everything in this directory is optional. +--]] + +local M = {} +-- A nixCats specific lze handler that you can use to conditionally enable by category easier. +-- at the start of your config, register with +-- require('lze').register_handlers(require('nixCatsUtils.lzUtils').for_cat) +-- before any calls to require('lze').load using the handler have been made. +-- accepts: +-- for_cat = { "your" "cat" }; +-- for_cat = { cat = { "your" "cat" }, default = bool } +-- for_cat = "your.cat"; +-- for_cat = { cat = "your.cat", default = bool } +-- where default is an alternate value for when nixCats was NOT used to install the config +M.for_cat = { + spec_field = "for_cat", + set_lazy = false, + modify = function(plugin) + if type(plugin.for_cat) == "table" and plugin.for_cat.cat ~= nil then + if vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] ~= nil then + plugin.enabled = nixCats(plugin.for_cat.cat) or false + else + plugin.enabled = plugin.for_cat.default + end + else + plugin.enabled = nixCats(plugin.for_cat) or false + end + return plugin + end, +} + +return M diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua new file mode 100644 index 0000000..0aa51d8 --- /dev/null +++ b/lua/plugins/ai.lua @@ -0,0 +1,29 @@ +return { + { + "opencode-nvim", + for_cat = "ai", + keys = { + -- stylua: ignore start + { 'co', function() require('opencode').toggle() end, desc = 'Toggle opencode' }, + { 'ca', function() require('opencode').ask() end, desc = 'Ask opencode', mode = { 'n', 'v' } }, + { 'cA', function() require('opencode').ask('@buffer ', { submit = true }) end, desc = 'Ask opencode about current file', mode = { 'n', 'v' } }, + { 'cn', function() require('opencode').command('session.new') end, desc = 'New session' }, + { 'ce', function() require('opencode').prompt('Explain @this and its context') end, desc = 'Explain code at cursor', mode = { 'n', 'v' } }, + { 'cr', function() require('opencode').prompt('Review @buffer for correctness and readability') end, desc = 'Review file' }, + { 'cf', function() require('opencode').prompt('Fix @diagnostics') end, desc = 'Fix errors' }, + { 'cp', function() require('opencode').prompt('Optimize @this for performance and readability') end, desc = 'Optimize selection', mode = 'v' }, + { 'cd', function() require('opencode').prompt('Add documentation comments for @this') end, desc = 'Document selection', mode = 'v' }, + { 'ct', function() require('opencode').prompt('Add tests for @this') end, desc = 'Test selection', mode = 'v' }, + { 'cs', function() require('opencode').select() end, desc = 'Select opencode action', mode = { 'n', 'v' } }, + -- stylua: ignore end + }, + before = function() + vim.g.opencode_opts = { + providers = { + enabled = "terminal", + tmux = {}, + }, + } + end, + }, +} diff --git a/lua/plugins/completion.lua b/lua/plugins/completion.lua new file mode 100644 index 0000000..79946e1 --- /dev/null +++ b/lua/plugins/completion.lua @@ -0,0 +1,65 @@ +return { + { + "blink.cmp", + event = { "InsertEnter", "CmdlineEnter" }, + for_cat = "core.completion", + load = function(name) + require("lzextras").loaders.multi({ + name, + -- "blink-ripgrep.nvim", + "friendly-snippets", + }) + end, + after = function(_) + require("blink.cmp").setup({ + keymap = { preset = "default" }, + appearance = { nerd_font_variant = "mono" }, + signature = { enabled = false }, + completion = { + documentation = { + auto_show = false, + }, + menu = { + draw = { + columns = { + { "label", "label_description", gap = 1 }, + { "kind_icon", "kind", gap = 1 }, + }, + treesitter = { "lsp" }, + }, + }, + }, + sources = { + default = { "lsp", "path", "snippets", "buffer", "cmdline", "omni" }, + providers = { + path = { + score_offset = 25, + }, + lsp = { + fallbacks = {}, + score_offset = 20, + }, + snippets = { + score_offset = 20, + }, + buffer = { + score_offset = 5, + }, + -- ripgrep = { + -- module = "blink-ripgrep", + -- name = "Ripgrep", + -- opts = { + -- project_root_marker = { ".git", "flake.nix", "flake.lock" }, + -- backend = { + -- use = "gitgrep-or-ripgrep", + -- customize_icon_highlight = false, + -- }, + -- }, + -- }, + }, + }, + fuzzy = { implementation = "prefer_rust_with_warning" }, + }) + end, + }, +} diff --git a/lua/plugins/debug.lua b/lua/plugins/debug.lua new file mode 100644 index 0000000..659336b --- /dev/null +++ b/lua/plugins/debug.lua @@ -0,0 +1,90 @@ +return { + { + "nvim-dap-go", + for_cat = { cat = "go", default = false }, + on_plugin = { "nvim-dap" }, + after = function(_) + require("dap-go").setup() + end, + }, + { + "nvim-dap", + for_cat = "debug", + on_require = { "dap" }, + keys = { + { "", desc = "Debug: Start/Continue" }, + { "", desc = "Debug: Step Into" }, + { "", desc = "Debug: Step Over" }, + { "", desc = "Debug: Step Out" }, + { "b", desc = "Debug: Toggle Breakpoint" }, + { "B", desc = "Debug: Set Breakpoint" }, + { "", desc = "Debug: See last session result." }, + }, + load = function(name) + require("lzextras").loaders.multi({ + name, + "nvim-dap-ui", + "nvim-dap-virtual-text", + }) + end, + after = function(_) + local dap = require("dap") + local dapui = require("dapui") + + -- Basic debugging keymaps, feel free to change to your liking! + vim.keymap.set("n", "", dap.continue, { desc = "Debug: Start/Continue" }) + vim.keymap.set("n", "", dap.step_into, { desc = "Debug: Step Into" }) + vim.keymap.set("n", "", dap.step_over, { desc = "Debug: Step Over" }) + vim.keymap.set("n", "", dap.step_out, { desc = "Debug: Step Out" }) + vim.keymap.set("n", "b", dap.toggle_breakpoint, { desc = "Debug: Toggle Breakpoint" }) + vim.keymap.set("n", "B", function() + dap.set_breakpoint(vim.fn.input("Breakpoint condition: ")) + end, { desc = "Debug: Set Breakpoint" }) + + -- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception. + vim.keymap.set("n", "", dapui.toggle, { desc = "Debug: See last session result." }) + + dap.listeners.after.event_initialized["dapui_config"] = dapui.open + dap.listeners.before.event_terminated["dapui_config"] = dapui.close + dap.listeners.before.event_exited["dapui_config"] = dapui.close + + -- Dap UI setup + -- For more information, see |:help nvim-dap-ui| + dapui.setup() + + require("nvim-dap-virtual-text").setup({ + -- enabled = true, -- enable this plugin (the default) + -- enabled_commands = true, -- create commands DapVirtualTextEnable, DapVirtualTextDisable, DapVirtualTextToggle, (DapVirtualTextForceRefresh for refreshing when debug adapter did not notify its termination) + -- highlight_changed_variables = true, -- highlight changed values with NvimDapVirtualTextChanged, else always NvimDapVirtualText + -- highlight_new_as_changed = false, -- highlight new variables in the same way as changed variables (if highlight_changed_variables) + -- show_stop_reason = true, -- show stop reason when stopped for exceptions + -- commented = false, -- prefix virtual text with comment string + -- only_first_definition = true, -- only show virtual text at first definition (if there are multiple) + -- all_references = false, -- show virtual text on all all references of the variable (not only definitions) + -- clear_on_continue = false, -- clear virtual text on "continue" (might cause flickering when stepping) + -- --- A callback that determines how a variable is displayed or whether it should be omitted + -- --- variable Variable https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable + -- --- buf number + -- --- stackframe dap.StackFrame https://microsoft.github.io/debug-adapter-protocol/specification#Types_StackFrame + -- --- node userdata tree-sitter node identified as variable definition of reference (see `:h tsnode`) + -- --- options nvim_dap_virtual_text_options Current options for nvim-dap-virtual-text + -- --- string|nil A text how the virtual text should be displayed or nil, if this variable shouldn't be displayed + -- display_callback = function(variable, buf, stackframe, node, options) + -- if options.virt_text_pos == "inline" then + -- return " = " .. variable.value + -- else + -- return variable.name .. " = " .. variable.value + -- end + -- end, + -- -- position of virtual text, see `:h nvim_buf_set_extmark()`, default tries to inline the virtual text. Use 'eol' to set to end of line + -- virt_text_pos = vim.fn.has("nvim-0.10") == 1 and "inline" or "eol", + -- + -- -- experimental features: + -- all_frames = false, -- show virtual text for all stack frames not only current. Only works for debugpy on my machine. + -- virt_lines = false, -- show virtual lines instead of virtual text (will flicker!) + -- virt_text_win_col = nil, -- position the virtual text at a fixed window column (starting from the first text column) , + -- -- e.g. 80 to position at column 80, see `:h nvim_buf_set_extmark()` + }) + end, + }, +} diff --git a/lua/plugins/formatter.lua b/lua/plugins/formatter.lua new file mode 100644 index 0000000..cc600e5 --- /dev/null +++ b/lua/plugins/formatter.lua @@ -0,0 +1,46 @@ +return { + { + "conform.nvim", + event = { "BufReadPre", "BufNewFile" }, + for_cats = "core.general", + after = function() + local conform = require("conform") + + conform.setup({ + format_after_save = { + lsp_format = "fallback", + quiet = true, + }, + + formatters_by_ft = { + lua = { "stylua" }, + go = { "gofmt" }, + rust = { "rustfmt" }, + toml = { "tombi" }, + java = { "google-java-format" }, + cmake = { "cmake_format" }, + typescript = { "prettierd" }, + javascript = { "prettierd" }, + c = { "clang-format" }, + cpp = { "clang-format" }, + python = { "ruff_fix", "ruff_organize_imports", "ruff_format" }, + }, + + formatters = { + ["google-java-format"] = { + prepend_args = { "--aosp" }, + }, + ["clang-format"] = { + prepend_args = { "-style={BasedOnStyle: LLVM, IndentWidth: 4, TabWidth: 4, UseTab: Never}" }, + }, + }, + }) + + vim.keymap.set({ "n", "v" }, "lf", function() + conform.format({ async = true }) + end, { + desc = "Language format", + }) + end, + }, +} diff --git a/lua/plugins/general.lua b/lua/plugins/general.lua new file mode 100644 index 0000000..f115247 --- /dev/null +++ b/lua/plugins/general.lua @@ -0,0 +1,94 @@ +return { + { + "guess-indent.nvim", + for_cat = "core.general", + event = "DeferredUIEnter", + after = function() + require("guess-indent").setup({ + auto_cmd = true, + override_editorconfig = true, + filetype_exclude = { + "netrw", + "tutor", + "oil", + "gitcommit", + }, + buftype_exclude = { + "help", + "nofile", + "terminal", + "prompt", + }, + on_tab_options = { + ["expandtab"] = false, + }, + on_space_options = { + ["expandtab"] = true, + ["tabstop"] = "detected", + ["softtabstop"] = "detected", + ["shiftwidth"] = "detected", + }, + }) + end, + }, + { + "nvim-surround", + for_cat = "core.general", + event = { "BufReadPre", "BufNewFile" }, + after = function() + require("nvim-surround").setup() + end, + }, + { + "oil.nvim", + keys = { { "o", "Oil", desc = "Open oil" } }, + for_cat = "core.general", + after = function() + require("oil").setup({ + default_file_explorer = true, + columns = { "icon", "permissions", "size" }, + keymaps = { + ["-"] = "actions.parent", + [""] = "actions.select", + [""] = "actions.select_vsplit", + [""] = "actions.select_split", + }, + }) + end, + }, + { + "undotree", + for_cat = "core.general", + cmd = { "UndotreeToggle", "UndotreeHide", "UndotreeShow", "UndotreeFocus", "UndotreePersistUndo" }, + keys = { { "U", "UndotreeToggle", mode = { "n" }, desc = "Undo Tree" } }, + before = function(_) + vim.g.undotree_WindowLayout = 1 + vim.g.undotree_SplitWidth = 40 + vim.g.undotree_WindowLayout = 3 + end, + }, + { + "lazydev.nvim", + ft = "lua", + after = function() + require("lazydev").setup({ + library = { + { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + }, + + integrations = { + -- Fixes lspconfig's workspace management for LuaLS + -- Only create a new workspace if the buffer is not part + -- of an existing workspace or one of its libraries + lspconfig = true, + -- add the cmp source for completion of: + -- `require "modname"` + -- `---@module "modname"` + cmp = true, + -- same, but for Coq + coq = false, + }, + }) + end, + }, +} diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua new file mode 100644 index 0000000..0e333f8 --- /dev/null +++ b/lua/plugins/git.lua @@ -0,0 +1,98 @@ +return { + { + "neogit", + for_cat = "core.git", + keys = { { "gg", "Neogit", desc = "Open Neogit Ui" } }, + cmd = { "Neogit" }, + after = function() + require("neogit").setup({ + disable_hint = true, + kind = "split_above", + + commit_editor = { + kind = "tab", + show_staged_diff = true, + staged_diff_split_kind = "auto", + spell_check = true, + }, + }) + end, + }, + { + "gitsigns.nvim", + event = { "DeferredUIEnter" }, + for_cat = "core.git", + after = function(_) + require("gitsigns").setup({ + signs = { + add = { text = "+" }, + change = { text = "~" }, + delete = { text = "_" }, + topdelete = { text = "‾" }, + changedelete = { text = "~" }, + }, + + on_attach = function(bufnr) + local gs = package.loaded.gitsigns + + local function map(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + + -- Navigation + map({ "n", "v" }, "]c", function() + if vim.wo.diff then + return "]c" + end + vim.schedule(function() + gs.next_hunk() + end) + return "" + end, { expr = true, desc = "Jump to next hunk" }) + + map({ "n", "v" }, "[c", function() + if vim.wo.diff then + return "[c" + end + vim.schedule(function() + gs.prev_hunk() + end) + return "" + end, { expr = true, desc = "Jump to previous hunk" }) + + -- Actions + -- visual mode + map("v", "hs", function() + gs.stage_hunk({ vim.fn.line("."), vim.fn.line("v") }) + end, { desc = "stage git hunk" }) + map("v", "hr", function() + gs.reset_hunk({ vim.fn.line("."), vim.fn.line("v") }) + end, { desc = "reset git hunk" }) + -- normal mode + map("n", "gs", gs.stage_hunk, { desc = "git stage hunk" }) + map("n", "gr", gs.reset_hunk, { desc = "git reset hunk" }) + map("n", "gS", gs.stage_buffer, { desc = "git Stage buffer" }) + map("n", "gu", gs.undo_stage_hunk, { desc = "undo stage hunk" }) + map("n", "gR", gs.reset_buffer, { desc = "git Reset buffer" }) + map("n", "gp", gs.preview_hunk, { desc = "preview git hunk" }) + map("n", "gb", function() + gs.blame_line({ full = false }) + end, { desc = "git blame line" }) + -- map('n', 'gd', gs.diffthis, { desc = 'git diff against index' }) + map("n", "gD", function() + gs.diffthis("~") + end, { desc = "git diff against last commit" }) + + -- Toggles + map("n", "gtb", gs.toggle_current_line_blame, { desc = "toggle git blame line" }) + map("n", "gtd", gs.toggle_deleted, { desc = "toggle git show deleted" }) + + -- Text object + map({ "o", "x" }, "ih", ":Gitsigns select_hunk", { desc = "select git hunk" }) + end, + }) + end, + }, +} diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua new file mode 100644 index 0000000..19e47d1 --- /dev/null +++ b/lua/plugins/init.lua @@ -0,0 +1,12 @@ +return { + { import = "plugins.ai" }, + { import = "plugins.general" }, + { import = "plugins.completion" }, + { import = "plugins.git" }, + { import = "plugins.formatter" }, + { import = "plugins.tsitter" }, + { import = "plugins.misc" }, + { import = "plugins.picker" }, + { import = "plugins.debug" }, + { import = "plugins.linter" }, +} diff --git a/lua/plugins/linter.lua b/lua/plugins/linter.lua new file mode 100644 index 0000000..c804d1c --- /dev/null +++ b/lua/plugins/linter.lua @@ -0,0 +1,40 @@ +return { + { + "nvim-lint", + event = { "BufReadPre", "BufNewFile" }, + for_cats = "core.general", + after = function() + local lint = require("lint") + + lint.linters_by_ft = { + python = { "ruff" }, + go = { "golangcilint" }, + rust = { "clippy" }, + c = { "clangtidy" }, + cpp = { "clangtidy" }, + java = { "checkstyle" }, + cmake = { "cmakelint" }, + javascript = { "eslint_d" }, + typescript = { "eslint_d" }, + } + + local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) + + vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost" }, { + group = lint_augroup, + callback = function() + lint.try_lint(nil, { ignore_errors = true }) + end, + }) + + vim.api.nvim_create_autocmd({ "InsertLeave" }, { + group = lint_augroup, + callback = function() + if vim.bo.filetype ~= "rust" then + lint.try_lint(nil, { ignore_errors = true }) + end + end, + }) + end, + }, +} diff --git a/lua/plugins/misc.lua b/lua/plugins/misc.lua new file mode 100644 index 0000000..37185ae --- /dev/null +++ b/lua/plugins/misc.lua @@ -0,0 +1,50 @@ +return { + { + "obsidian.nvim", + for_cats = "misc", + event = { + "BufReadPre " .. vim.fn.expand("~") .. "/Notes/**/*.md", + "BufNewFile " .. vim.fn.expand("~") .. "/Notes/**/*.md", + }, + after = function() + require("obsidian").setup({ + legacy_commands = false, + workspaces = { + { + name = "personal", + path = "~/Notes", + }, + }, + }) + end, + }, + { + "typst-preview.nvim", + ft = "typst", + for_cats = "misc", + after = function() + require("typst-preview").setup({ + debug = false, + open_cmd = nil, + port = nil, + invert_colors = "never", + follow_cursor = true, + dependencies_bin = { + tinymist = "tinymist", + websocat = "websocat", + }, + extra_args = nil, + get_root = function(path_of_main_file) + local root = os.getenv("TYPST_ROOT") + if root then + return root + end + return vim.fn.fnamemodify(path_of_main_file, ":p:h") + end, + get_main_file = function(path_of_buffer) + return path_of_buffer + end, + }) + end, + }, +} diff --git a/lua/plugins/picker.lua b/lua/plugins/picker.lua new file mode 100644 index 0000000..478a689 --- /dev/null +++ b/lua/plugins/picker.lua @@ -0,0 +1,142 @@ +local mini = function(key, action, desc) + return { + key, + "Pick " .. action .. "", + mode = { "n" }, + desc = desc, + } +end + +local telescope_builtin = function(key, action, desc) + return { + key, + "Telescope " .. action .. "", + mode = { "n" }, + desc = desc, + } +end + +return { + { + "mini.pick", + for_cat = "core.picker.mini", + event = "DeferredUIEnter", + keys = { + mini("ff", "files", "finde files"), + mini("fb", "buffers", "Find open buffers"), + mini("fh", "help", "Find help"), + mini("/", "grep_live", "Live grep"), + + -- MiniExtra + mini("fd", "diagnostic", "Diagnostics"), + mini("fgb", "git_branches", "Git branches"), + mini("fc", "git_commits", "Git commits"), + + -- LSP scopes + mini("fr", "lsp scope='references'", "LSP references"), + mini("ds", "lsp scope='document_symbol'", "Document symbols"), + mini("ws", "lsp scope='workspace_symbol'", "Workspace symbols"), + + mini("ld", "lsp scope='definition'", "Goto definition"), + mini("ltd", "lsp scope='type_definition'", "Goto type definition"), + mini("lD", "lsp scope='declaration'", "Goto declaration"), + mini("lr", "lsp scope='references'", "Goto references"), + mini("lI", "lsp scope='implementation'", "Goto implementation"), + }, + load = function(name) + require("lzextras").loaders.multi({ + name, + "mini.extra", + }) + end, + after = function() + require("mini.pick").setup() + end, + }, + { + "telescope.nvim", + event = "DeferredUIEnter", + for_cat = "core.picker.telescope", + keys = { + telescope_builtin("ff", "find_files", "Search files in cwd"), + telescope_builtin("fb", "buffers", "Search files in cwd"), + telescope_builtin("fo", "oldfiles", "Recent files"), + telescope_builtin("fr", "registers", "Registers"), + telescope_builtin("fj", "jumplist", "Jump list"), + telescope_builtin("fm", "marks", "Marks"), + + telescope_builtin("fq", "quickfix", "Quickfix list"), + telescope_builtin("fl", "loclist", "Location list"), + + telescope_builtin("st", "treesitter", "Treesitter symbols"), + + telescope_builtin("sc", "commands", "Commands"), + telescope_builtin("sp", "spell_suggest", "Spell suggestions"), + + telescope_builtin("sg", "live_grep", "Search by grep"), + telescope_builtin("ss", "grep_string", "Search string"), + telescope_builtin("sk", "keymaps", "Search keymaps"), + telescope_builtin("sh", "help_tags", "Search help tags"), + telescope_builtin("/", "current_buffer_fuzzy_find", "Search in current buffer"), + + telescope_builtin("gc", "git_commits", "Git commits"), + telescope_builtin("gB", "git_branches", "Git branches"), + telescope_builtin("gs", "git_status", "Git status"), + telescope_builtin("gS", "git_stash", "Git stash"), + + telescope_builtin("ls", "lsp_document_symbols", "Document symbols"), + telescope_builtin("lS", "lsp_workspace_symbols", "Workspace symbols"), + telescope_builtin("lds", "lsp_dynamic_workspace_symbols", "Workspace symbols"), + telescope_builtin("ld", "diagnostics", "Diagnostics"), + telescope_builtin("lD", "lsp_definitions", "LSP definitions"), + telescope_builtin("li", "lsp_incoming_calls", "LSP incoming calls"), + telescope_builtin("lo", "lsp_outgoing_calls", "LSP outgoing calls"), + telescope_builtin("lt", "lsp_type_definitions", "LSP type definitions"), + telescope_builtin("grr", "lsp_references", "LSP references"), + telescope_builtin("gri", "lsp_implementations", "LSP implementations"), + }, + load = function(name) + require("lzextras").loaders.multi({ + name, + "telescope-fzf-native.nvim", + "telescope-ui-select.nvim", + }) + end, + after = function() + require("telescope").setup({ + defaults = { + mappings = { + i = { + [""] = "to_fuzzy_refine", + }, + }, + }, + pickers = { + buffers = { + mappings = { + i = { + -- [""] = "delete_buffer", + }, + n = { + ["d"] = "delete_buffer", + }, + }, + }, + }, + extensions = { + fzf = { + fuzzy = true, + override_generic_sorter = true, + override_file_sorter = true, + case_mode = "smart_case", + }, + ["ui-select"] = { + require("telescope.themes").get_dropdown({}), + }, + }, + }) + require("telescope").load_extension("fzf") + require("telescope").load_extension("ui-select") + end, + }, +} diff --git a/lua/plugins/tsitter.lua b/lua/plugins/tsitter.lua new file mode 100644 index 0000000..8bdb0ca --- /dev/null +++ b/lua/plugins/tsitter.lua @@ -0,0 +1,115 @@ +return { + { + "nvim-treesitter", + lazy = false, + after = function(plugin) + ---@param buf integer + ---@param language string + local function treesitter_try_attach(buf, language) + -- check if parser exists and load it + if not vim.treesitter.language.add(language) then + return false + end + -- enables syntax highlighting and other treesitter features + vim.treesitter.start(buf, language) + + -- enables treesitter based folds + vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()" + + -- enables treesitter based indentation + vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + + return true + end + + local installable_parsers = require("nvim-treesitter").get_available() + vim.api.nvim_create_autocmd("FileType", { + callback = function(args) + local buf, filetype = args.buf, args.match + local language = vim.treesitter.language.get_lang(filetype) + if not language then + return + end + + if not treesitter_try_attach(buf, language) then + if vim.tbl_contains(installable_parsers, language) then + -- not already installed, so try to install them via nvim-treesitter if possible + require("nvim-treesitter").install(language):await(function() + treesitter_try_attach(buf, language) + end) + end + end + end, + }) + end, + }, + { + "nvim-treesitter-textobjects", + lazy = false, + before = function(plugin) + -- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main?tab=readme-ov-file#using-a-package-manager + -- Disable entire built-in ftplugin mappings to avoid conflicts. + -- See https://github.com/neovim/neovim/tree/master/runtime/ftplugin for built-in ftplugins. + vim.g.no_plugin_maps = true + + -- Or, disable per filetype (add as you like) + -- vim.g.no_python_maps = true + -- vim.g.no_ruby_maps = true + -- vim.g.no_rust_maps = true + -- vim.g.no_go_maps = true + end, + after = function(plugin) + require("nvim-treesitter-textobjects").setup({ + select = { + -- Automatically jump forward to textobj, similar to targets.vim + lookahead = true, + -- You can choose the select mode (default is charwise 'v') + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * method: eg 'v' or 'o' + -- and should return the mode ('v', 'V', or '') or a table + -- mapping query_strings to modes. + selection_modes = { + ["@parameter.outer"] = "v", -- charwise + ["@function.outer"] = "V", -- linewise + -- ['@class.outer'] = '', -- blockwise + }, + -- If you set this to `true` (default is `false`) then any textobject is + -- extended to include preceding or succeeding whitespace. Succeeding + -- whitespace has priority in order to act similarly to eg the built-in + -- `ap`. + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * selection_mode: eg 'v' + -- and should return true of false + include_surrounding_whitespace = false, + }, + }) + + -- keymaps + -- You can use the capture groups defined in `textobjects.scm` + vim.keymap.set({ "x", "o" }, "am", function() + require("nvim-treesitter-textobjects.select").select_textobject("@function.outer", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "im", function() + require("nvim-treesitter-textobjects.select").select_textobject("@function.inner", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "ac", function() + require("nvim-treesitter-textobjects.select").select_textobject("@class.outer", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "ic", function() + require("nvim-treesitter-textobjects.select").select_textobject("@class.inner", "textobjects") + end) + -- You can also use captures from other query groups like `locals.scm` + vim.keymap.set({ "x", "o" }, "as", function() + require("nvim-treesitter-textobjects.select").select_textobject("@local.scope", "locals") + end) + + -- NOTE: for more textobjects options, see the following link. + -- This template is using the new `main` branch of the repo. + -- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main + end, + }, +} -- cgit v1.3.1