Created
April 22, 2026 01:40
-
-
Save lightstrike/9516434ed525b356e9aa7c5541a74047 to your computer and use it in GitHub Desktop.
Lightstrike nvim bootstrap — single script that installs Neovim + lazy.nvim + full plugin config (LSP, Treesitter, Telescope, Catppuccin, conform, etc.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Lightstrike nvim bootstrap | |
| # Installs Neovim (if needed) and writes the full config to ~/.config/nvim. | |
| # Idempotent — safe to re-run. Backs up any existing config first. | |
| # | |
| # Usage: | |
| # curl -fsSL <gist-raw-url> | bash | |
| # # or | |
| # bash nvim-bootstrap.sh | |
| NVIM_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/nvim" | |
| # --------------------------------------------------------------------------- | |
| # 1. Install Neovim if missing | |
| # --------------------------------------------------------------------------- | |
| if ! command -v nvim &>/dev/null; then | |
| echo ":: Installing Neovim..." | |
| if command -v brew &>/dev/null; then | |
| brew install neovim | |
| else | |
| echo "ERROR: Neovim not found and Homebrew not available. Install Neovim manually." >&2 | |
| exit 1 | |
| fi | |
| fi | |
| echo ":: Neovim $(nvim --version | head -1)" | |
| # --------------------------------------------------------------------------- | |
| # 2. Install external tool dependencies via Homebrew | |
| # --------------------------------------------------------------------------- | |
| BREW_DEPS=(ripgrep fd node prettierd stylua golangci-lint) | |
| if command -v brew &>/dev/null; then | |
| echo ":: Checking Homebrew dependencies..." | |
| for dep in "${BREW_DEPS[@]}"; do | |
| if ! brew list --formula "$dep" &>/dev/null; then | |
| echo " Installing $dep..." | |
| brew install "$dep" | |
| fi | |
| done | |
| fi | |
| # --------------------------------------------------------------------------- | |
| # 3. Back up existing config | |
| # --------------------------------------------------------------------------- | |
| if [ -d "$NVIM_DIR" ]; then | |
| BACKUP="${NVIM_DIR}.bak.$(date +%Y%m%d%H%M%S)" | |
| echo ":: Backing up existing config to $BACKUP" | |
| mv "$NVIM_DIR" "$BACKUP" | |
| fi | |
| mkdir -p "$NVIM_DIR/lua/config" "$NVIM_DIR/lua/plugins" | |
| # --------------------------------------------------------------------------- | |
| # 4. Write config files | |
| # --------------------------------------------------------------------------- | |
| echo ":: Writing config files..." | |
| # -- init.lua --------------------------------------------------------------- | |
| cat > "$NVIM_DIR/init.lua" << 'LUA' | |
| -- Bootstrap lazy.nvim | |
| local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" | |
| if not vim.loop.fs_stat(lazypath) then | |
| vim.fn.system({ | |
| "git", "clone", "--filter=blob:none", | |
| "https://github.com/folke/lazy.nvim.git", | |
| "--branch=stable", lazypath, | |
| }) | |
| end | |
| vim.opt.rtp:prepend(lazypath) | |
| -- Load core settings before plugins | |
| require("config.options") | |
| require("config.keymaps") | |
| -- Load plugins via lazy.nvim | |
| require("lazy").setup("plugins", { | |
| change_detection = { notify = false }, | |
| install = { colorscheme = { "catppuccin" } }, | |
| }) | |
| -- Load autocmds after plugins | |
| require("config.autocmds") | |
| LUA | |
| # -- config/options.lua ----------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/config/options.lua" << 'LUA' | |
| local opt = vim.opt | |
| -- Line numbers | |
| opt.number = true | |
| opt.relativenumber = true | |
| opt.signcolumn = "yes" | |
| -- Tabs / indentation | |
| opt.tabstop = 2 | |
| opt.shiftwidth = 2 | |
| opt.expandtab = true | |
| opt.smartindent = true | |
| -- Search | |
| opt.ignorecase = true | |
| opt.smartcase = true | |
| opt.hlsearch = true | |
| opt.incsearch = true | |
| -- Appearance | |
| opt.termguicolors = true | |
| opt.cursorline = true | |
| opt.scrolloff = 8 | |
| opt.sidescrolloff = 8 | |
| opt.wrap = false | |
| opt.showmode = false | |
| -- Splits | |
| opt.splitbelow = true | |
| opt.splitright = true | |
| -- Performance | |
| opt.updatetime = 250 | |
| opt.timeoutlen = 300 | |
| -- Undo | |
| opt.undofile = true | |
| opt.swapfile = false | |
| -- Clipboard | |
| opt.clipboard = "unnamedplus" | |
| -- Mouse | |
| opt.mouse = "a" | |
| -- Completion | |
| opt.completeopt = "menu,menuone,noselect" | |
| LUA | |
| # -- config/keymaps.lua ----------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/config/keymaps.lua" << 'LUA' | |
| vim.g.mapleader = " " | |
| vim.g.maplocalleader = " " | |
| local map = vim.keymap.set | |
| -- Better window navigation | |
| map("n", "<C-h>", "<C-w>h", { desc = "Go to left window" }) | |
| map("n", "<C-j>", "<C-w>j", { desc = "Go to lower window" }) | |
| map("n", "<C-k>", "<C-w>k", { desc = "Go to upper window" }) | |
| map("n", "<C-l>", "<C-w>l", { desc = "Go to right window" }) | |
| -- Resize windows | |
| map("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "Increase window height" }) | |
| map("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "Decrease window height" }) | |
| map("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "Decrease window width" }) | |
| map("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "Increase window width" }) | |
| -- Move lines | |
| map("v", "J", ":m '>+1<cr>gv=gv", { desc = "Move line down" }) | |
| map("v", "K", ":m '<-2<cr>gv=gv", { desc = "Move line up" }) | |
| -- Better indenting (stay in visual mode) | |
| map("v", "<", "<gv") | |
| map("v", ">", ">gv") | |
| -- Clear search highlight | |
| map("n", "<Esc>", "<cmd>nohlsearch<cr>", { desc = "Clear search highlight" }) | |
| -- Diagnostic navigation | |
| map("n", "[d", vim.diagnostic.goto_prev, { desc = "Previous diagnostic" }) | |
| map("n", "]d", vim.diagnostic.goto_next, { desc = "Next diagnostic" }) | |
| map("n", "<leader>e", vim.diagnostic.open_float, { desc = "Show diagnostic" }) | |
| -- Buffer navigation | |
| map("n", "<S-h>", "<cmd>bprevious<cr>", { desc = "Previous buffer" }) | |
| map("n", "<S-l>", "<cmd>bnext<cr>", { desc = "Next buffer" }) | |
| map("n", "<leader>bd", "<cmd>bdelete<cr>", { desc = "Delete buffer" }) | |
| LUA | |
| # -- config/autocmds.lua ---------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/config/autocmds.lua" << 'LUA' | |
| local autocmd = vim.api.nvim_create_autocmd | |
| -- Highlight on yank | |
| autocmd("TextYankPost", { | |
| callback = function() | |
| vim.highlight.on_yank({ timeout = 200 }) | |
| end, | |
| }) | |
| -- Go: use tabs, 4-wide | |
| autocmd("FileType", { | |
| pattern = "go", | |
| callback = function() | |
| vim.opt_local.tabstop = 4 | |
| vim.opt_local.shiftwidth = 4 | |
| vim.opt_local.expandtab = false | |
| end, | |
| }) | |
| -- Python / Rust: 4-space indent | |
| autocmd("FileType", { | |
| pattern = { "python", "rust" }, | |
| callback = function() | |
| vim.opt_local.tabstop = 4 | |
| vim.opt_local.shiftwidth = 4 | |
| end, | |
| }) | |
| -- Auto-resize splits on terminal resize | |
| autocmd("VimResized", { | |
| callback = function() | |
| vim.cmd("tabdo wincmd =") | |
| end, | |
| }) | |
| LUA | |
| # -- plugins/colorscheme.lua ------------------------------------------------ | |
| cat > "$NVIM_DIR/lua/plugins/colorscheme.lua" << 'LUA' | |
| return { | |
| { | |
| "catppuccin/nvim", | |
| name = "catppuccin", | |
| lazy = false, | |
| priority = 1000, | |
| opts = { | |
| flavour = "mocha", | |
| integrations = { | |
| cmp = true, | |
| gitsigns = true, | |
| mason = true, | |
| treesitter = true, | |
| telescope = { enabled = true }, | |
| native_lsp = { | |
| enabled = true, | |
| inlay_hints = { background = true }, | |
| }, | |
| }, | |
| }, | |
| config = function(_, opts) | |
| require("catppuccin").setup(opts) | |
| vim.cmd.colorscheme("catppuccin") | |
| end, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/completion.lua ------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/completion.lua" << 'LUA' | |
| return { | |
| { | |
| "hrsh7th/nvim-cmp", | |
| event = "InsertEnter", | |
| dependencies = { | |
| "hrsh7th/cmp-nvim-lsp", | |
| "hrsh7th/cmp-buffer", | |
| "hrsh7th/cmp-path", | |
| "L3MON4D3/LuaSnip", | |
| "saadparwaiz1/cmp_luasnip", | |
| "rafamadriz/friendly-snippets", | |
| }, | |
| config = function() | |
| local cmp = require("cmp") | |
| local luasnip = require("luasnip") | |
| require("luasnip.loaders.from_vscode").lazy_load() | |
| cmp.setup({ | |
| snippet = { | |
| expand = function(args) | |
| luasnip.lsp_expand(args.body) | |
| end, | |
| }, | |
| window = { | |
| completion = cmp.config.window.bordered(), | |
| documentation = cmp.config.window.bordered(), | |
| }, | |
| mapping = cmp.mapping.preset.insert({ | |
| ["<C-b>"] = cmp.mapping.scroll_docs(-4), | |
| ["<C-f>"] = cmp.mapping.scroll_docs(4), | |
| ["<C-Space>"] = cmp.mapping.complete(), | |
| ["<C-e>"] = cmp.mapping.abort(), | |
| ["<CR>"] = cmp.mapping.confirm({ select = true }), | |
| ["<Tab>"] = cmp.mapping(function(fallback) | |
| if cmp.visible() then | |
| cmp.select_next_item() | |
| elseif luasnip.expand_or_jumpable() then | |
| luasnip.expand_or_jump() | |
| else | |
| fallback() | |
| end | |
| end, { "i", "s" }), | |
| ["<S-Tab>"] = cmp.mapping(function(fallback) | |
| if cmp.visible() then | |
| cmp.select_prev_item() | |
| elseif luasnip.jumpable(-1) then | |
| luasnip.jump(-1) | |
| else | |
| fallback() | |
| end | |
| end, { "i", "s" }), | |
| }), | |
| sources = cmp.config.sources({ | |
| { name = "nvim_lsp" }, | |
| { name = "luasnip" }, | |
| { name = "path" }, | |
| }, { | |
| { name = "buffer" }, | |
| }), | |
| }) | |
| end, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/editor.lua ----------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/editor.lua" << 'LUA' | |
| return { | |
| -- Auto pairs | |
| { | |
| "windwp/nvim-autopairs", | |
| event = "InsertEnter", | |
| config = function() | |
| require("nvim-autopairs").setup({}) | |
| -- Integrate with cmp | |
| local cmp_autopairs = require("nvim-autopairs.completion.cmp") | |
| require("cmp").event:on("confirm_done", cmp_autopairs.on_confirm_done()) | |
| end, | |
| }, | |
| -- Comment toggling | |
| { | |
| "numToStr/Comment.nvim", | |
| keys = { | |
| { "gcc", mode = "n", desc = "Comment line" }, | |
| { "gc", mode = { "n", "v" }, desc = "Comment" }, | |
| }, | |
| opts = {}, | |
| }, | |
| -- Surround | |
| { | |
| "kylechui/nvim-surround", | |
| version = "*", | |
| event = "VeryLazy", | |
| opts = {}, | |
| }, | |
| -- File explorer | |
| { | |
| "nvim-tree/nvim-tree.lua", | |
| dependencies = { "nvim-tree/nvim-web-devicons" }, | |
| keys = { | |
| { "<leader>t", "<cmd>NvimTreeToggle<cr>", desc = "Toggle file tree" }, | |
| }, | |
| opts = { | |
| filters = { dotfiles = false }, | |
| view = { width = 35 }, | |
| }, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/formatting.lua ------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/formatting.lua" << 'LUA' | |
| return { | |
| { | |
| "stevearc/conform.nvim", | |
| event = { "BufWritePre" }, | |
| cmd = { "ConformInfo" }, | |
| keys = { | |
| { "<leader>cf", function() require("conform").format({ async = true }) end, desc = "Format buffer" }, | |
| }, | |
| opts = { | |
| formatters_by_ft = { | |
| typescript = { "prettierd", "prettier", stop_after_first = true }, | |
| typescriptreact = { "prettierd", "prettier", stop_after_first = true }, | |
| javascript = { "prettierd", "prettier", stop_after_first = true }, | |
| javascriptreact = { "prettierd", "prettier", stop_after_first = true }, | |
| json = { "prettierd", "prettier", stop_after_first = true }, | |
| css = { "prettierd", "prettier", stop_after_first = true }, | |
| html = { "prettierd", "prettier", stop_after_first = true }, | |
| markdown = { "prettierd", "prettier", stop_after_first = true }, | |
| python = { "ruff_format" }, | |
| go = { "goimports", "gofumpt" }, | |
| rust = { "rustfmt" }, | |
| lua = { "stylua" }, | |
| }, | |
| format_on_save = { | |
| timeout_ms = 3000, | |
| lsp_format = "fallback", | |
| }, | |
| }, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/linting.lua ---------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/linting.lua" << 'LUA' | |
| return { | |
| { | |
| "mfussenegger/nvim-lint", | |
| event = { "BufReadPre", "BufNewFile" }, | |
| config = function() | |
| local lint = require("lint") | |
| lint.linters_by_ft = { | |
| -- ruff is handled via LSP, eslint via LSP | |
| -- Add additional linters here if needed | |
| go = { "golangcilint" }, | |
| } | |
| vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, { | |
| callback = function() | |
| lint.try_lint() | |
| end, | |
| }) | |
| end, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/lsp.lua -------------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/lsp.lua" << 'LUA' | |
| return { | |
| -- Mason: auto-install language servers | |
| { | |
| "williamboman/mason.nvim", | |
| cmd = "Mason", | |
| opts = {}, | |
| }, | |
| { | |
| "williamboman/mason-lspconfig.nvim", | |
| dependencies = { "williamboman/mason.nvim" }, | |
| opts = { | |
| ensure_installed = { | |
| "basedpyright", -- Python | |
| "vtsls", -- TypeScript | |
| "gopls", -- Go | |
| "rust_analyzer", -- Rust | |
| "lua_ls", -- Lua (for editing nvim config) | |
| "eslint", -- ESLint | |
| "ruff", -- Python linting/formatting | |
| }, | |
| automatic_installation = true, | |
| }, | |
| }, | |
| -- LSP keymaps + inlay hints via native Neovim 0.11 API | |
| { | |
| "hrsh7th/cmp-nvim-lsp", | |
| lazy = true, | |
| }, | |
| { | |
| "neovim/nvim-lspconfig", | |
| event = { "BufReadPre", "BufNewFile" }, | |
| dependencies = { | |
| "williamboman/mason-lspconfig.nvim", | |
| "hrsh7th/cmp-nvim-lsp", | |
| }, | |
| config = function() | |
| local capabilities = require("cmp_nvim_lsp").default_capabilities() | |
| -- Shared LspAttach autocmd for keymaps + inlay hints | |
| vim.api.nvim_create_autocmd("LspAttach", { | |
| callback = function(ev) | |
| local bufnr = ev.buf | |
| local client = vim.lsp.get_client_by_id(ev.data.client_id) | |
| local map = function(keys, func, desc) | |
| vim.keymap.set("n", keys, func, { buffer = bufnr, desc = "LSP: " .. desc }) | |
| end | |
| map("gd", vim.lsp.buf.definition, "Go to definition") | |
| map("gD", vim.lsp.buf.declaration, "Go to declaration") | |
| map("gr", vim.lsp.buf.references, "References") | |
| map("gi", vim.lsp.buf.implementation, "Go to implementation") | |
| map("gy", vim.lsp.buf.type_definition, "Type definition") | |
| map("K", vim.lsp.buf.hover, "Hover docs") | |
| map("<C-k>", vim.lsp.buf.signature_help, "Signature help") | |
| map("<leader>rn", vim.lsp.buf.rename, "Rename") | |
| map("<leader>ca", vim.lsp.buf.code_action, "Code action") | |
| -- Enable inlay hints | |
| if client and client.supports_method("textDocument/inlayHint") then | |
| vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) | |
| end | |
| end, | |
| }) | |
| -- Configure servers using native vim.lsp.config (Neovim 0.11+) | |
| vim.lsp.config("vtsls", { | |
| capabilities = capabilities, | |
| settings = { | |
| typescript = { | |
| inlayHints = { | |
| parameterNames = { enabled = "all" }, | |
| parameterTypes = { enabled = true }, | |
| variableTypes = { enabled = true }, | |
| propertyDeclarationTypes = { enabled = true }, | |
| functionLikeReturnTypes = { enabled = true }, | |
| }, | |
| }, | |
| javascript = { | |
| inlayHints = { | |
| parameterNames = { enabled = "all" }, | |
| variableTypes = { enabled = true }, | |
| functionLikeReturnTypes = { enabled = true }, | |
| }, | |
| }, | |
| }, | |
| }) | |
| vim.lsp.config("basedpyright", { | |
| capabilities = capabilities, | |
| settings = { | |
| basedpyright = { | |
| analysis = { | |
| typeCheckingMode = "standard", | |
| autoImportCompletions = true, | |
| inlayHints = { | |
| variableTypes = true, | |
| callArgumentNames = true, | |
| functionReturnTypes = true, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }) | |
| vim.lsp.config("ruff", { | |
| capabilities = capabilities, | |
| on_attach = function(client) | |
| -- Disable hover in favor of basedpyright | |
| client.server_capabilities.hoverProvider = false | |
| end, | |
| }) | |
| vim.lsp.config("gopls", { | |
| capabilities = capabilities, | |
| settings = { | |
| gopls = { | |
| analyses = { | |
| unusedparams = true, | |
| shadow = true, | |
| }, | |
| staticcheck = true, | |
| hints = { | |
| assignVariableTypes = true, | |
| compositeLiteralFields = true, | |
| compositeLiteralTypes = true, | |
| constantValues = true, | |
| functionTypeParameters = true, | |
| parameterNames = true, | |
| rangeVariableTypes = true, | |
| }, | |
| }, | |
| }, | |
| }) | |
| vim.lsp.config("eslint", { | |
| capabilities = capabilities, | |
| }) | |
| vim.lsp.config("lua_ls", { | |
| capabilities = capabilities, | |
| settings = { | |
| Lua = { | |
| runtime = { version = "LuaJIT" }, | |
| workspace = { | |
| checkThirdParty = false, | |
| library = { vim.env.VIMRUNTIME }, | |
| }, | |
| telemetry = { enable = false }, | |
| }, | |
| }, | |
| }) | |
| -- Enable all configured servers | |
| vim.lsp.enable({ | |
| "vtsls", "basedpyright", "ruff", "gopls", "eslint", "lua_ls", | |
| }) | |
| -- Diagnostic appearance | |
| vim.diagnostic.config({ | |
| virtual_text = { spacing = 4, prefix = "●" }, | |
| signs = true, | |
| underline = true, | |
| update_in_insert = false, | |
| severity_sort = true, | |
| float = { border = "rounded" }, | |
| }) | |
| end, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/treesitter.lua ------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/treesitter.lua" << 'LUA' | |
| return { | |
| { | |
| "nvim-treesitter/nvim-treesitter", | |
| build = ":TSUpdate", | |
| lazy = false, | |
| config = function() | |
| require("nvim-treesitter").setup() | |
| -- Install grammars | |
| local ensure_installed = { | |
| -- Target languages | |
| "typescript", "tsx", "javascript", "jsdoc", | |
| "python", | |
| "go", "gomod", "gosum", "gowork", | |
| "rust", "toml", | |
| -- General | |
| "lua", "vim", "vimdoc", "query", | |
| "json", "yaml", "html", "css", | |
| "bash", "markdown", "markdown_inline", | |
| "regex", "diff", "gitcommit", "gitignore", | |
| } | |
| -- Use vim.treesitter for highlighting (built-in in 0.11) | |
| vim.api.nvim_create_autocmd("FileType", { | |
| callback = function(ev) | |
| pcall(vim.treesitter.start, ev.buf) | |
| end, | |
| }) | |
| -- Install missing parsers (only on first run) | |
| local install = require("nvim-treesitter.install") | |
| for _, lang in ipairs(ensure_installed) do | |
| local ok = pcall(vim.treesitter.language.add, lang) | |
| if not ok then | |
| install.install(lang) | |
| end | |
| end | |
| end, | |
| }, | |
| { | |
| "nvim-treesitter/nvim-treesitter-textobjects", | |
| dependencies = "nvim-treesitter/nvim-treesitter", | |
| event = { "BufReadPost", "BufNewFile" }, | |
| config = function() | |
| -- textobjects works via queries, not configs in newer versions | |
| local ts_repeat_move = require("nvim-treesitter-textobjects.repeatable_move") or nil | |
| -- Selection keymaps | |
| vim.keymap.set({ "x", "o" }, "af", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@function.outer", "textobjects") | |
| end, { desc = "Select outer function" }) | |
| vim.keymap.set({ "x", "o" }, "if", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@function.inner", "textobjects") | |
| end, { desc = "Select inner function" }) | |
| vim.keymap.set({ "x", "o" }, "ac", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@class.outer", "textobjects") | |
| end, { desc = "Select outer class" }) | |
| vim.keymap.set({ "x", "o" }, "ic", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@class.inner", "textobjects") | |
| end, { desc = "Select inner class" }) | |
| vim.keymap.set({ "x", "o" }, "aa", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@parameter.outer", "textobjects") | |
| end, { desc = "Select outer parameter" }) | |
| vim.keymap.set({ "x", "o" }, "ia", function() | |
| require("nvim-treesitter-textobjects.select").select_textobject("@parameter.inner", "textobjects") | |
| end, { desc = "Select inner parameter" }) | |
| end, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/ui.lua ---------------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/ui.lua" << 'LUA' | |
| return { | |
| -- Telescope (fuzzy finder) | |
| { | |
| "nvim-telescope/telescope.nvim", | |
| branch = "0.1.x", | |
| dependencies = { | |
| "nvim-lua/plenary.nvim", | |
| { "nvim-telescope/telescope-fzf-native.nvim", build = "make" }, | |
| }, | |
| cmd = "Telescope", | |
| keys = { | |
| { "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find files" }, | |
| { "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Live grep" }, | |
| { "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Buffers" }, | |
| { "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help tags" }, | |
| { "<leader>fd", "<cmd>Telescope diagnostics<cr>", desc = "Diagnostics" }, | |
| { "<leader>fs", "<cmd>Telescope lsp_document_symbols<cr>", desc = "Document symbols" }, | |
| { "<leader>fr", "<cmd>Telescope lsp_references<cr>", desc = "References" }, | |
| }, | |
| config = function() | |
| local telescope = require("telescope") | |
| telescope.setup({ | |
| defaults = { | |
| file_ignore_patterns = { "node_modules", ".git/", "target/", "__pycache__" }, | |
| }, | |
| }) | |
| telescope.load_extension("fzf") | |
| end, | |
| }, | |
| -- Trouble (diagnostics panel) | |
| { | |
| "folke/trouble.nvim", | |
| cmd = "Trouble", | |
| keys = { | |
| { "<leader>xx", "<cmd>Trouble diagnostics toggle<cr>", desc = "Diagnostics (Trouble)" }, | |
| { "<leader>xX", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>", desc = "Buffer diagnostics" }, | |
| }, | |
| opts = {}, | |
| }, | |
| -- Gitsigns | |
| { | |
| "lewis6991/gitsigns.nvim", | |
| event = { "BufReadPre", "BufNewFile" }, | |
| opts = { | |
| signs = { | |
| add = { text = "│" }, | |
| change = { text = "│" }, | |
| delete = { text = "━" }, | |
| topdelete = { text = "‾" }, | |
| changedelete = { text = "~" }, | |
| }, | |
| }, | |
| }, | |
| -- Lualine (status bar) | |
| { | |
| "nvim-lualine/lualine.nvim", | |
| dependencies = { "nvim-tree/nvim-web-devicons" }, | |
| event = "VeryLazy", | |
| opts = { | |
| options = { | |
| theme = "catppuccin", | |
| component_separators = { left = "│", right = "│" }, | |
| section_separators = { left = "", right = "" }, | |
| }, | |
| sections = { | |
| lualine_a = { "mode" }, | |
| lualine_b = { "branch", "diff", "diagnostics" }, | |
| lualine_c = { { "filename", path = 1 } }, | |
| lualine_x = { "filetype" }, | |
| lualine_y = { "progress" }, | |
| lualine_z = { "location" }, | |
| }, | |
| }, | |
| }, | |
| -- Indent guides | |
| { | |
| "lukas-reineke/indent-blankline.nvim", | |
| main = "ibl", | |
| event = { "BufReadPost", "BufNewFile" }, | |
| opts = { | |
| indent = { char = "│" }, | |
| scope = { enabled = true }, | |
| }, | |
| }, | |
| -- Which-key (keybinding hints) | |
| { | |
| "folke/which-key.nvim", | |
| event = "VeryLazy", | |
| opts = {}, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/go.lua ---------------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/go.lua" << 'LUA' | |
| return { | |
| { | |
| "ray-x/go.nvim", | |
| dependencies = { | |
| "ray-x/guihua.lua", | |
| "neovim/nvim-lspconfig", | |
| "nvim-treesitter/nvim-treesitter", | |
| }, | |
| event = { "CmdlineEnter" }, | |
| ft = { "go", "gomod" }, | |
| build = ':lua require("go.install").update_all_sync()', | |
| opts = {}, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/python.lua ------------------------------------------------------ | |
| cat > "$NVIM_DIR/lua/plugins/python.lua" << 'LUA' | |
| return { | |
| { | |
| "linux-cultist/venv-selector.nvim", | |
| branch = "regexp", | |
| dependencies = { | |
| "neovim/nvim-lspconfig", | |
| "nvim-telescope/telescope.nvim", | |
| }, | |
| ft = "python", | |
| keys = { | |
| { "<leader>vs", "<cmd>VenvSelect<cr>", desc = "Select Python venv" }, | |
| }, | |
| opts = {}, | |
| }, | |
| } | |
| LUA | |
| # -- plugins/rust.lua -------------------------------------------------------- | |
| cat > "$NVIM_DIR/lua/plugins/rust.lua" << 'LUA' | |
| return { | |
| { | |
| "mrcjkb/rustaceanvim", | |
| version = "^5", | |
| lazy = false, | |
| init = function() | |
| vim.g.rustaceanvim = { | |
| server = { | |
| default_settings = { | |
| ["rust-analyzer"] = { | |
| checkOnSave = { command = "clippy" }, | |
| inlayHints = { | |
| bindingModeHints = { enable = true }, | |
| chainingHints = { enable = true }, | |
| closureReturnTypeHints = { enable = "always" }, | |
| lifetimeElisionHints = { enable = "always" }, | |
| parameterHints = { enable = true }, | |
| typeHints = { enable = true }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| } | |
| end, | |
| }, | |
| { | |
| "saecki/crates.nvim", | |
| event = "BufRead Cargo.toml", | |
| opts = { | |
| completion = { | |
| cmp = { enabled = true }, | |
| }, | |
| }, | |
| }, | |
| } | |
| LUA | |
| # --------------------------------------------------------------------------- | |
| # 5. First launch — install plugins headlessly | |
| # --------------------------------------------------------------------------- | |
| echo ":: Installing plugins (headless)..." | |
| nvim --headless "+Lazy! sync" +qa 2>/dev/null || true | |
| echo "" | |
| echo "Done. Launch nvim — Mason will auto-install LSP servers on first open." | |
| echo "Run :checkhealth to verify everything is working." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment