From 444b5739bdd221c3c3f3c24f0e6d440b4ef81359 Mon Sep 17 00:00:00 2001 From: rootiest Date: Fri, 17 Apr 2026 04:46:48 -0400 Subject: [PATCH] initial commit --- .gemini_session | 1 + init.lua | 21 +++++++ lua/keymaps.lua | 139 ++++++++++++++++++++++++++++++++++++++++++++ lua/lazyload.lua | 87 +++++++++++++++++++++++++++ lua/options.lua | 24 ++++++++ lua/plugins.lua | 135 ++++++++++++++++++++++++++++++++++++++++++ nvim-pack-lock.json | 52 +++++++++++++++++ 7 files changed, 459 insertions(+) create mode 100644 .gemini_session create mode 100644 init.lua create mode 100644 lua/keymaps.lua create mode 100644 lua/lazyload.lua create mode 100644 lua/options.lua create mode 100644 lua/plugins.lua create mode 100644 nvim-pack-lock.json diff --git a/.gemini_session b/.gemini_session new file mode 100644 index 0000000..9612eac --- /dev/null +++ b/.gemini_session @@ -0,0 +1 @@ +19ce389f-03ac-449c-9c0d-ac59f943d577 diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..4599a78 --- /dev/null +++ b/init.lua @@ -0,0 +1,21 @@ +--[[ + ┌────────────────────────────────────────────────────────────────┐ + │ Rootiest Neovim │ + └────────────────────────────────────────────────────────────────┘ +--]] + +-- Set leader keys before loading any plugins +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +-- Initialize global registry +_G.Config = { + plugins = {}, + called = {}, +} + +-- Load core modules +require('lazyload') +require('options') +require('plugins') +require('keymaps') diff --git a/lua/keymaps.lua b/lua/keymaps.lua new file mode 100644 index 0000000..0e73647 --- /dev/null +++ b/lua/keymaps.lua @@ -0,0 +1,139 @@ +--[[ + ┌────────────────────────────────────────────────────────────────┐ + │ Keymaps │ + └────────────────────────────────────────────────────────────────┘ +--]] + +-- System Clipboard Integration +-- This makes 'y' and 'p' (and all other yank/paste operations) +-- use the system clipboard by default. +vim.opt.clipboard = 'unnamedplus' + +---------------------------------------------------------- + +-- Redirect 'delete' and 'change' operations to the 'd' register +-- This keeps your system clipboard (unnamedplus) clean +local delete_keys = { 'd', 'D', 'c', 'C', 'x', 'X' } +for _, key in ipairs(delete_keys) do + vim.keymap.set({ 'n', 'v' }, key, '"d' .. key, { noremap = true, silent = true }) +end + +-- If you ever need to paste what you just deleted: +-- Type "dp (instead of just p) + +---------------------------------------------------------- + +-- Quit and Save All with :Q +-- Replaces safety-checked :xa with a forced write-all-and-quit. +vim.api.nvim_create_user_command('Q', 'xa!', { desc = 'Write all and quit (forced)' }) + +---------------------------------------------------------- + +-- Snacks Keymaps +-- Top Pickers & Explorer +vim.keymap.set("n", "", function() Snacks.picker.smart() end, { desc = "Smart Find Files" }) +vim.keymap.set("n", ",", function() Snacks.picker.buffers() end, { desc = "Buffers" }) +vim.keymap.set("n", "/", function() Snacks.picker.grep() end, { desc = "Grep" }) +vim.keymap.set("n", ":", function() Snacks.picker.command_history() end, { desc = "Command History" }) +vim.keymap.set("n", "n", function() Snacks.picker.notifications() end, { desc = "Notification History" }) +vim.keymap.set("n", "e", function() Snacks.explorer() end, { desc = "File Explorer" }) + +-- Find +vim.keymap.set("n", "fb", function() Snacks.picker.buffers() end, { desc = "Buffers" }) +vim.keymap.set("n", "fc", function() Snacks.picker.files({ cwd = vim.fn.stdpath("config") }) end, { desc = "Find Config File" }) +vim.keymap.set("n", "ff", function() Snacks.picker.files() end, { desc = "Find Files" }) +vim.keymap.set("n", "fg", function() Snacks.picker.git_files() end, { desc = "Find Git Files" }) +vim.keymap.set("n", "fp", function() Snacks.picker.projects() end, { desc = "Projects" }) +vim.keymap.set("n", "fr", function() Snacks.picker.recent() end, { desc = "Recent" }) + +-- Git +vim.keymap.set("n", "gb", function() Snacks.picker.git_branches() end, { desc = "Git Branches" }) +vim.keymap.set("n", "gl", function() Snacks.picker.git_log() end, { desc = "Git Log" }) +vim.keymap.set("n", "gL", function() Snacks.picker.git_log_line() end, { desc = "Git Log Line" }) +vim.keymap.set("n", "gs", function() Snacks.picker.git_status() end, { desc = "Git Status" }) +vim.keymap.set("n", "gS", function() Snacks.picker.git_stash() end, { desc = "Git Stash" }) +vim.keymap.set("n", "gd", function() Snacks.picker.git_diff() end, { desc = "Git Diff (Hunks)" }) +vim.keymap.set("n", "gf", function() Snacks.picker.git_log_file() end, { desc = "Git Log File" }) + +-- GH +vim.keymap.set("n", "gi", function() Snacks.picker.gh_issue() end, { desc = "GitHub Issues (open)" }) +vim.keymap.set("n", "gI", function() Snacks.picker.gh_issue({ state = "all" }) end, { desc = "GitHub Issues (all)" }) +vim.keymap.set("n", "gp", function() Snacks.picker.gh_pr() end, { desc = "GitHub Pull Requests (open)" }) +vim.keymap.set("n", "gP", function() Snacks.picker.gh_pr({ state = "all" }) end, { desc = "GitHub Pull Requests (all)" }) + +-- Grep +vim.keymap.set("n", "sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" }) +vim.keymap.set("n", "sB", function() Snacks.picker.grep_buffers() end, { desc = "Grep Open Buffers" }) +vim.keymap.set("n", "sg", function() Snacks.picker.grep() end, { desc = "Grep" }) +vim.keymap.set({ "n", "x" }, "sw", function() Snacks.picker.grep_word() end, { desc = "Visual selection or word" }) + +-- Search +vim.keymap.set("n", 's"', function() Snacks.picker.registers() end, { desc = "Registers" }) +vim.keymap.set("n", 's/', function() Snacks.picker.search_history() end, { desc = "Search History" }) +vim.keymap.set("n", "sa", function() Snacks.picker.autocmds() end, { desc = "Autocmds" }) +vim.keymap.set("n", "sc", function() Snacks.picker.command_history() end, { desc = "Command History" }) +vim.keymap.set("n", "sC", function() Snacks.picker.commands() end, { desc = "Commands" }) +vim.keymap.set("n", "sd", function() Snacks.picker.diagnostics() end, { desc = "Diagnostics" }) +vim.keymap.set("n", "sD", function() Snacks.picker.diagnostics_buffer() end, { desc = "Buffer Diagnostics" }) +vim.keymap.set("n", "sh", function() Snacks.picker.help() end, { desc = "Help Pages" }) +vim.keymap.set("n", "sH", function() Snacks.picker.highlights() end, { desc = "Highlights" }) +vim.keymap.set("n", "si", function() Snacks.picker.icons() end, { desc = "Icons" }) +vim.keymap.set("n", "sj", function() Snacks.picker.jumps() end, { desc = "Jumps" }) +vim.keymap.set("n", "sk", function() Snacks.picker.keymaps() end, { desc = "Keymaps" }) +vim.keymap.set("n", "sl", function() Snacks.picker.loclist() end, { desc = "Location List" }) +vim.keymap.set("n", "sm", function() Snacks.picker.marks() end, { desc = "Marks" }) +vim.keymap.set("n", "sM", function() Snacks.picker.man() end, { desc = "Man Pages" }) +vim.keymap.set("n", "sp", function() Snacks.picker.lazy() end, { desc = "Search for Plugin Spec" }) +vim.keymap.set("n", "sq", function() Snacks.picker.qflist() end, { desc = "Quickfix List" }) +vim.keymap.set("n", "sR", function() Snacks.picker.resume() end, { desc = "Resume" }) +vim.keymap.set("n", "su", function() Snacks.picker.undo() end, { desc = "Undo History" }) +vim.keymap.set("n", "uC", function() Snacks.picker.colorschemes() end, { desc = "Colorschemes" }) + +-- LSP +vim.keymap.set("n", "gd", function() Snacks.picker.lsp_definitions() end, { desc = "Goto Definition" }) +vim.keymap.set("n", "gD", function() Snacks.picker.lsp_declarations() end, { desc = "Goto Declaration" }) +vim.keymap.set("n", "gr", function() Snacks.picker.lsp_references() end, { nowait = true, desc = "References" }) +vim.keymap.set("n", "gI", function() Snacks.picker.lsp_implementations() end, { desc = "Goto Implementation" }) +vim.keymap.set("n", "gy", function() Snacks.picker.lsp_type_definitions() end, { desc = "Goto T[y]pe Definition" }) +vim.keymap.set("n", "gai", function() Snacks.picker.lsp_incoming_calls() end, { desc = "C[a]lls Incoming" }) +vim.keymap.set("n", "gao", function() Snacks.picker.lsp_outgoing_calls() end, { desc = "C[a]lls Outgoing" }) +vim.keymap.set("n", "ss", function() Snacks.picker.lsp_symbols() end, { desc = "LSP Symbols" }) +vim.keymap.set("n", "sS", function() Snacks.picker.lsp_workspace_symbols() end, { desc = "LSP Workspace Symbols" }) + +-- Other +vim.keymap.set("n", "z", function() Snacks.zen() end, { desc = "Toggle Zen Mode" }) +vim.keymap.set("n", "Z", function() Snacks.zen.zoom() end, { desc = "Toggle Zoom" }) +vim.keymap.set("n", ".", function() Snacks.scratch() end, { desc = "Toggle Scratch Buffer" }) +vim.keymap.set("n", "S", function() Snacks.scratch.select() end, { desc = "Select Scratch Buffer" }) +vim.keymap.set("n", "n", function() Snacks.notifier.show_history() end, { desc = "Notification History" }) +vim.keymap.set("n", "bd", function() Snacks.bufdelete() end, { desc = "Delete Buffer" }) +vim.keymap.set("n", "cR", function() Snacks.rename.rename_file() end, { desc = "Rename File" }) +vim.keymap.set({ "n", "v" }, "gB", function() Snacks.gitbrowse() end, { desc = "Git Browse" }) +vim.keymap.set("n", "gg", function() Snacks.lazygit() end, { desc = "Lazygit" }) +vim.keymap.set("n", "un", function() Snacks.notifier.hide() end, { desc = "Dismiss All Notifications" }) +vim.keymap.set("n", "", function() Snacks.terminal() end, { desc = "Toggle Terminal" }) +vim.keymap.set("n", "", function() Snacks.terminal() end, { desc = "which_key_ignore" }) +vim.keymap.set({ "n", "t" }, "]]", function() Snacks.words.jump(vim.v.count1) end, { desc = "Next Reference" }) +vim.keymap.set({ "n", "t" }, "[[", function() Snacks.words.jump(-vim.v.count1) end, { desc = "Prev Reference" }) +vim.keymap.set("n", "N", function() + Snacks.win({ + file = vim.api.nvim_get_runtime_file("doc/news.txt", false)[1], + width = 0.6, + height = 0.6, + wo = { + spell = false, + wrap = false, + signcolumn = "yes", + statuscolumn = " ", + conceallevel = 3, + }, + }) +end, { desc = "Neovim News" }) + +---------------------------------------------------------- + +-- Persistence Keymaps +vim.keymap.set("n", "qs", function() require("persistence").load() end, { desc = "Restore Session" }) +vim.keymap.set("n", "qS", function() require("persistence").select() end, { desc = "Select Session" }) +vim.keymap.set("n", "ql", function() require("persistence").load({ last = true }) end, { desc = "Restore Last Session" }) +vim.keymap.set("n", "qd", function() require("persistence").stop() end, { desc = "Don't Save Current Session" }) diff --git a/lua/lazyload.lua b/lua/lazyload.lua new file mode 100644 index 0000000..6c99883 --- /dev/null +++ b/lua/lazyload.lua @@ -0,0 +1,87 @@ +-- Lazyload queues for phased plugin loading. +-- +-- on_vim_enter(fn): async fire-and-forget via vim.schedule() (default) +-- on_vim_enter(fn, { sync = true }): synchronous, must complete before next phase +-- on_override(fn): runs after all on_vim_enter callbacks (for .nvim.lua overrides) + +local M = {} + +local vim_enter_queue = {} +local override_queue = {} + +---@param queue { fn: fun(), sync: boolean }[] +local function drain(queue) + for _, entry in ipairs(queue) do + if not entry.sync then + vim.schedule(entry.fn) + end + end + for _, entry in ipairs(queue) do + if entry.sync then + entry.fn() + end + end +end + +local function drain_override() + if not override_queue then + return + end + for _, entry in ipairs(override_queue) do + vim.schedule(function() + local ok, err = pcall(entry.fn) + if not ok then + vim.notify((".nvim.lua override error:\n%s"):format(err), vim.log.levels.ERROR) + end + end) + end + override_queue = nil +end + +vim.api.nvim_create_autocmd("VimEnter", { + once = true, + callback = function() + drain(vim_enter_queue) + vim_enter_queue = nil + drain_override() + end, +}) + +--- Run at VimEnter. Async by default. Pass { sync = true } to run synchronously. +---@param fn fun() +---@param opts? { sync?: boolean } +function M.on_vim_enter(fn, opts) + local sync = opts and opts.sync or false + if vim_enter_queue then + table.insert(vim_enter_queue, { fn = fn, sync = sync }) + elseif sync then + fn() + else + vim.schedule(fn) + end +end + +--- Run after all on_vim_enter callbacks (including async ones) have executed. +--- Intended for project-local overrides from .nvim.lua that need to patch +--- plugin state after setup() has run. Exrc runs at step 7c — before plugin/ +--- files — so it cannot override plugin setup directly; this queue bridges +--- that gap by registering a callback that runs after the VimEnter drain. +---@param fn fun() +function M.on_override(fn) + if override_queue then + table.insert(override_queue, { fn = fn }) + else + vim.schedule(fn) + end +end + +-- Call function only once. +function M.call_once(fn) + local id = tostring(fn) + if fn and not Config.called[id] then + fn() + Config.called[id] = true + end +end + +return M diff --git a/lua/options.lua b/lua/options.lua new file mode 100644 index 0000000..53c2059 --- /dev/null +++ b/lua/options.lua @@ -0,0 +1,24 @@ +--[[ + ┌────────────────────────────────────────────────────────────────┐ + │ Options │ + └────────────────────────────────────────────────────────────────┘ +--]] + +-- Autowrite/Autosave +-- This ensures changes are saved on every buffer change or when leaving insert mode. +vim.api.nvim_create_autocmd({ "InsertLeave", "TextChanged" }, { + group = vim.api.nvim_create_augroup("autosave", { clear = true }), + pattern = { "*" }, + callback = function() + local buftype = vim.api.nvim_get_option_value("buftype", { buf = 0 }) + if buftype == "" and vim.bo.modified then + vim.cmd("silent! update") + end + end, +}) + +-- Performance and UI defaults +vim.opt.updatetime = 200 -- Faster completion and CursorHold events +vim.opt.autowrite = true -- Enable auto write +vim.opt.number = true -- Show line numbers +vim.opt.relativenumber = true -- Relative line numbers diff --git a/lua/plugins.lua b/lua/plugins.lua new file mode 100644 index 0000000..5158059 --- /dev/null +++ b/lua/plugins.lua @@ -0,0 +1,135 @@ +--[[ + ┌────────────────────────────────────────────────────────────────┐ + │ Plugins │ + └────────────────────────────────────────────────────────────────┘ +--]] + +-- Catppuccin.nvim +-- Eagerly load the colorscheme plugin. +vim.pack.add { { src = "https://github.com/catppuccin/nvim", name = "catppuccin" } } + +-- Catppuccin Config +Config.plugins.catppuccin = { + flavour = "mocha", +} +vim.cmd.colorscheme "catppuccin" + +-- Snacks.nvim +-- Eagerly load snacks for dashboard and performance features. +vim.pack.add { { src = "https://github.com/folke/snacks.nvim", name = "snacks" } } + +-- Snacks Config +-- Store opts in the registry first. +Config.plugins.snacks = { + bigfile = { enabled = true }, + dashboard = { + enabled = true, + sections = { + { section = "header" }, + { section = "keys", gap = 1, padding = 1 }, + }, + }, + explorer = { enabled = true }, + indent = { enabled = true }, + input = { enabled = true }, + picker = { enabled = true }, + notifier = { enabled = true }, + quickfile = { enabled = true }, + scope = { enabled = true }, + scroll = { enabled = true }, + statuscolumn = { enabled = true }, + words = { enabled = true }, +} + +-- Setup Snacks with the registered opts. +require("snacks").setup(Config.plugins.snacks) + +-- Persistence.nvim +-- Simple session management. +vim.pack.add { { src = "https://github.com/folke/persistence.nvim", name = "persistence" } } + +-- Persistence Config +Config.plugins.persistence = { + dir = vim.fn.stdpath("state") .. "/sessions/", + need = 1, + branch = true, +} +require("persistence").setup(Config.plugins.persistence) + +-- Lazy-loaded Plugins +local lazyload = require("lazyload") + +lazyload.on_vim_enter(function() + -- Gitsigns.nvim + vim.pack.add { { src = "https://github.com/lewis6991/gitsigns.nvim", name = "gitsigns" } } + require("gitsigns").setup({ + numhl = true, -- Enable line number highlighting + }) + + -- Grug-far.nvim + vim.pack.add { { src = "https://github.com/MagicDuck/grug-far.nvim", name = "grug-far" } } + require("grug-far").setup() + + -- Flash.nvim + vim.pack.add { { src = "https://github.com/folke/flash.nvim", name = "flash" } } + require("flash").setup() + + -- Which-key.nvim + vim.pack.add { { src = "https://github.com/folke/which-key.nvim", name = "which-key" } } + require("which-key").setup() + + -- Mini.ai + vim.pack.add { { src = "https://github.com/echasnovski/mini.ai", name = "mini.ai" } } + + Config.plugins.mini_ai = { + custom_textobjects = { + g = function() + local n_lines = vim.api.nvim_buf_line_count(0) + return { + from = { line = 1, col = 1 }, + to = { line = n_lines, col = math.max(vim.fn.getline(n_lines):len(), 1) }, + } + end, + }, + } + require("mini.ai").setup(Config.plugins.mini_ai) + + -- Icons + vim.pack.add { { src = "https://github.com/nvim-tree/nvim-web-devicons", name = "nvim-web-devicons" } } + + -- Lualine + vim.pack.add { { src = "https://github.com/nvim-lualine/lualine.nvim", name = "lualine" } } + require("lualine").setup({ + options = { + theme = "auto", + globalstatus = true, + }, + sections = { + lualine_b = { "branch", "diff", "diagnostics" }, + } + }) + + -- Noice dependencies + vim.pack.add { { src = "https://github.com/MunifTanjim/nui.nvim", name = "nui" } } + + -- Noice.nvim + vim.pack.add { { src = "https://github.com/folke/noice.nvim", name = "noice" } } + require("noice").setup({ + lsp = { + -- override markdown rendering so that **cmp** and other plugins use **Treesitter** + override = { + ["vim.lsp.util.convert_input_to_markdown_lines"] = true, + ["vim.lsp.util.set_autocmds"] = true, + ["vim.ui.codelens.display_inline"] = true, + }, + }, + -- you can enable a preset for easier configuration + presets = { + bottom_search = true, -- use a classic bottom cmdline for search + command_palette = true, -- position the cmdline and popupmenu together + long_message_to_split = true, -- long messages will be sent to a split + inc_rename = false, -- enables an input dialog for inc-rename.nvim + lsp_doc_border = false, -- add a border to hover docs and signature help + }, + }) +end) diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json new file mode 100644 index 0000000..26b01a1 --- /dev/null +++ b/nvim-pack-lock.json @@ -0,0 +1,52 @@ +{ + "plugins": { + "catppuccin": { + "rev": "426dbebe06b5c69fd846ceb17b42e12f890aedf1", + "src": "https://github.com/catppuccin/nvim" + }, + "flash": { + "rev": "fcea7ff883235d9024dc41e638f164a450c14ca2", + "src": "https://github.com/folke/flash.nvim" + }, + "gitsigns": { + "rev": "8d82c240f190fc33723d48c308ccc1ed8baad69d", + "src": "https://github.com/lewis6991/gitsigns.nvim" + }, + "grug-far": { + "rev": "21604255d0e8f9968322f61f2b6c09e5efe1285a", + "src": "https://github.com/MagicDuck/grug-far.nvim" + }, + "lualine": { + "rev": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c", + "src": "https://github.com/nvim-lualine/lualine.nvim" + }, + "mini.ai": { + "rev": "43eb2074843950a3a25aae56a5f41362ec043bfa", + "src": "https://github.com/echasnovski/mini.ai" + }, + "noice": { + "rev": "7bfd942445fb63089b59f97ca487d605e715f155", + "src": "https://github.com/folke/noice.nvim" + }, + "nui": { + "rev": "de740991c12411b663994b2860f1a4fd0937c130", + "src": "https://github.com/MunifTanjim/nui.nvim" + }, + "nvim-web-devicons": { + "rev": "c72328a5494b4502947a022fe69c0c47e53b6aa6", + "src": "https://github.com/nvim-tree/nvim-web-devicons" + }, + "persistence": { + "rev": "b20b2a7887bd39c1a356980b45e03250f3dce49c", + "src": "https://github.com/folke/persistence.nvim" + }, + "snacks": { + "rev": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e", + "src": "https://github.com/folke/snacks.nvim" + }, + "which-key": { + "rev": "3aab2147e74890957785941f0c1ad87d0a44c15a", + "src": "https://github.com/folke/which-key.nvim" + } + } +}