From 23a4344cefe423ad27c9c6ab48973688d4942154 Mon Sep 17 00:00:00 2001 From: steven-na Date: Wed, 12 Aug 2026 01:07:25 -0700 Subject: Nvim changes --- arch/alpvim/.config/alpvim/init.lua | 684 ++++++++++++++++---------------- arch/alpvim/.config/alpvim/init.lua.old | 523 ++++++++++++++++++++++++ 2 files changed, 870 insertions(+), 337 deletions(-) create mode 100644 arch/alpvim/.config/alpvim/init.lua.old (limited to 'arch/alpvim/.config') diff --git a/arch/alpvim/.config/alpvim/init.lua b/arch/alpvim/.config/alpvim/init.lua index 96a7215..96b073f 100644 --- a/arch/alpvim/.config/alpvim/init.lua +++ b/arch/alpvim/.config/alpvim/init.lua @@ -1,36 +1,24 @@ -- Bootstrap lazy.nvim local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not vim.uv.fs_stat(lazypath) then - vim.fn.system({ - "git", "clone", "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", lazypath, - }) + vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath }) end vim.opt.rtp:prepend(lazypath) --- Leader -vim.g.mapleader = " " +vim.g.mapleader = " " -- Leader vim.g.maplocalleader = " " --- ============================================================ -- Options (adjusted for a raw TTY) --- ============================================================ - local opt = vim.opt - --- Line numbers -opt.number = true +opt.number = true -- Line numbers opt.relativenumber = true --- Indentation -opt.expandtab = true +opt.expandtab = true -- Indentation opt.tabstop = 4 opt.shiftwidth = 4 opt.softtabstop = 4 --- Visual -opt.cursorline = true +opt.cursorline = true -- Visual opt.scrolloff = 20 opt.signcolumn = "yes" opt.list = true @@ -39,8 +27,7 @@ opt.fillchars:append({ fold = "-" }) opt.termguicolors = true opt.colorcolumn = "" --- Behaviour -opt.swapfile = false +opt.swapfile = false -- Behaviour opt.undofile = true opt.updatetime = 250 opt.timeoutlen = 300 @@ -52,351 +39,374 @@ opt.inccommand = "split" opt.hlsearch = true opt.breakindent = true --- Folding (nvim-ufo, see plugin list below) -opt.foldcolumn = "0" +opt.foldcolumn = "0" -- Folding (nvim-ufo, see plugin list below) opt.foldlevel = 99 opt.foldlevelstart = 99 opt.foldenable = true -local map = vim.keymap.set - --- ============================================================ -- Keymaps --- ============================================================ - --- Disable Space in normal/visual (used as leader) -map({ "n", "v" }, "", "", { silent = true }) - --- Save +local map = vim.keymap.set +map({ "n", "v" }, "", "", { silent = true }) -- Disable Space in normal/visual (used as leader) map({ "n", "i" }, "", "w", { desc = "Save" }) - --- Clear search highlight -map("n", "", "nohlsearch") - --- Exit terminal mode +map("n", "", "nohlsearch") -- Clear search highlight map("t", "", "", { desc = "Exit terminal" }) - --- Better up/down on wrapped lines -map({ "n", "v" }, "j", "gj") +map({ "n", "v" }, "j", "gj") -- Better up/down on wrapped lines map({ "n", "v" }, "k", "gk") --- Buffer navigation -map("n", "", "bprevious", { desc = "Prev buffer" }) -map("n", "", "bnext", { desc = "Next buffer" }) +map("n", "", "bprevious", { desc = "Prev buffer" }) -- Buffer navigation +map("n", "", "bnext", { desc = "Next buffer" }) map("n", "bd", "bdelete", { desc = "Delete buffer" }) --- Splits -map("n", "sv", "v", { desc = "Split vertical" }) -map("n", "sh", "s", { desc = "Split horizontal" }) -map("n", "se", "=", { desc = "Equal splits" }) +map("n", "sv", "v", { desc = "Split vertical" }) -- Splits +map("n", "sh", "s", { desc = "Split horizontal" }) +map("n", "se", "=", { desc = "Equal splits" }) map("n", "sx", "close", { desc = "Close split" }) --- Move lines -map("n", "", "m .+1==", { desc = "Move line down" }) -map("n", "", "m .-2==", { desc = "Move line up" }) +map("n", "", "m .+1==", { desc = "Move line down" }) -- Move lines +map("n", "", "m .-2==", { desc = "Move line up" }) map("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) -map("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) +map("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) --- Stay in visual after indent -map("v", "<", "", ">gv") --- ============================================================ --- Completion helper --- ============================================================ - +-- Completion helper: expand blink.cmp menu height + docs while it's open local function expand_menu() - local cfg = require("blink.cmp.config").completion - cfg.menu.max_height = 10 - cfg.documentation.auto_show = true - pcall(function() - require("blink.cmp.completion.windows.menu").update_position() - end) + local cfg = require("blink.cmp.config").completion + cfg.menu.max_height = 10 + cfg.documentation.auto_show = true + pcall(function() + require("blink.cmp.completion.windows.menu").update_position() + end) end - vim.api.nvim_create_autocmd("User", { - pattern = "BlinkCmpMenuClose", - callback = function() - local ok, cfg = pcall(function() return require("blink.cmp.config").completion end) - if not ok then return end - cfg.menu.max_height = 5 - cfg.documentation.auto_show = false - end, + pattern = "BlinkCmpMenuClose", + callback = function() + local ok, cfg = pcall(function() + return require("blink.cmp.config").completion + end) + if not ok then + return + end + cfg.menu.max_height = 5 + cfg.documentation.auto_show = false + end, }) --- ============================================================ --- Fold text helper --- ============================================================ +-- Trim trailing whitespace on save (skip markdown) +vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*", + callback = function() + if vim.bo.filetype == "markdown" then + return + end + local view = vim.fn.winsaveview() + vim.cmd([[keeppatterns %s/\s\+$//e]]) + vim.fn.winrestview(view) + end, +}) +-- Fold text helper for nvim-ufo (ascii "... N lines" suffix instead of unicode) local function ufo_ascii_foldtext(virtText, lnum, endLnum, width, truncate) - local newVirtText = {} - local suffix = (" ... %d lines "):format(endLnum - lnum) - local sufWidth = vim.fn.strdisplaywidth(suffix) - local targetWidth = width - sufWidth - local curWidth = 0 - for _, chunk in ipairs(virtText) do - local chunkText = chunk[1] - local chunkWidth = vim.fn.strdisplaywidth(chunkText) - if targetWidth > curWidth + chunkWidth then - table.insert(newVirtText, chunk) - else - chunkText = truncate(chunkText, targetWidth - curWidth) - local hlGroup = chunk[2] - table.insert(newVirtText, { chunkText, hlGroup }) - chunkWidth = vim.fn.strdisplaywidth(chunkText) - if curWidth + chunkWidth < targetWidth then - suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) - end - break - end - curWidth = curWidth + chunkWidth - end - table.insert(newVirtText, { suffix, "Comment" }) - return newVirtText + local newVirtText = {} + local suffix = (" ... %d lines "):format(endLnum - lnum) + local sufWidth = vim.fn.strdisplaywidth(suffix) + local targetWidth = width - sufWidth + local curWidth = 0 + for _, chunk in ipairs(virtText) do + local chunkText = chunk[1] + local chunkWidth = vim.fn.strdisplaywidth(chunkText) + if targetWidth > curWidth + chunkWidth then + table.insert(newVirtText, chunk) + else + chunkText = truncate(chunkText, targetWidth - curWidth) + table.insert(newVirtText, { chunkText, chunk[2] }) + chunkWidth = vim.fn.strdisplaywidth(chunkText) + if curWidth + chunkWidth < targetWidth then + suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) + end + break + end + curWidth = curWidth + chunkWidth + end + table.insert(newVirtText, { suffix, "Comment" }) + return newVirtText end --- ============================================================ --- Plugins: leap, oil, treesitter, nvim-ufo, clangd, blink.cmp --- ============================================================ - +-- Plugins: leap, oil, treesitter, nvim-ufo, clangd, blink.cmp, mini.base16 require("lazy").setup({ - -- Motion: s + two chars to jump anywhere - { - url = "https://codeberg.org/andyg/leap.nvim", - keys = { - { "s", "(leap)", mode = { "n", "x", "o" }, desc = "Leap" }, - { "S", "(leap-from-window)", mode = { "n", "o" }, desc = "Leap from window" }, - }, - }, - - -- Buffer-based file explorer - { - "stevearc/oil.nvim", - lazy = false, - keys = { - { "e", "Oil", desc = "File explorer" }, - { "-", "Oil", desc = "Open parent dir" }, - }, - opts = { - default_file_explorer = true, - view_options = { show_hidden = true }, - constrain_cursor = false, - }, - }, - - -- Treesitter (syntax highlighting + textobjects) - { - "nvim-treesitter/nvim-treesitter", - branch = "main", - lazy = false, - build = ":TSUpdate", - dependencies = { - { "nvim-treesitter/nvim-treesitter-textobjects", branch = "main" }, - }, - config = function() - require("nvim-treesitter").setup({}) - require("nvim-treesitter").install({ "c" }) - - vim.api.nvim_create_autocmd("FileType", { - callback = function(args) - local lang = vim.treesitter.language.get_lang(vim.bo[args.buf].filetype) - if lang and vim.treesitter.language.add(lang) then - pcall(vim.treesitter.start, args.buf, lang) - vim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" - end - end, - }) - - local ok_to, to = pcall(require, "nvim-treesitter-textobjects") - if not ok_to then return end - to.setup({ - select = { lookahead = true }, - move = { set_jumps = true }, - }) - local sel = require("nvim-treesitter-textobjects.select") - local move = require("nvim-treesitter-textobjects.move") - local swap = require("nvim-treesitter-textobjects.swap") - local tmap = vim.keymap.set - - local objs = { - { "af", "@function.outer", "around function" }, - { "if", "@function.inner", "inside function" }, - { "ac", "@class.outer", "around class" }, - { "ic", "@class.inner", "inside class" }, - { "aa", "@parameter.outer", "around argument" }, - { "ia", "@parameter.inner", "inside argument" }, - { "ab", "@block.outer", "around block" }, - { "ib", "@block.inner", "inside block" }, - { "ai", "@conditional.outer", "around conditional" }, - { "ii", "@conditional.inner", "inside conditional" }, - { "al", "@loop.outer", "around loop" }, - { "il", "@loop.inner", "inside loop" }, - } - for _, o in ipairs(objs) do - local lhs, q, d = o[1], o[2], o[3] - tmap({ "x", "o" }, lhs, function() sel.select_textobject(q, "textobjects") end, { desc = d }) - end - - local nmo = { "n", "x", "o" } - tmap(nmo, "]m", function() move.goto_next_start("@function.outer", "textobjects") end, { desc = "next func start" }) - tmap(nmo, "[m", function() move.goto_previous_start("@function.outer", "textobjects") end, { desc = "prev func start" }) - tmap(nmo, "]M", function() move.goto_next_end("@function.outer", "textobjects") end, { desc = "next func end" }) - tmap(nmo, "[M", function() move.goto_previous_end("@function.outer", "textobjects") end, { desc = "prev func end" }) - tmap(nmo, "]]", function() move.goto_next_start("@class.outer", "textobjects") end, { desc = "next class start" }) - tmap(nmo, "[[", function() move.goto_previous_start("@class.outer", "textobjects") end, { desc = "prev class start" }) - tmap(nmo, "][", function() move.goto_next_end("@class.outer", "textobjects") end, { desc = "next class end" }) - tmap(nmo, "[]", function() move.goto_previous_end("@class.outer", "textobjects") end, { desc = "prev class end" }) - - tmap("n", "a", function() swap.swap_next("@parameter.inner") end, { desc = "Swap arg with next" }) - tmap("n", "A", function() swap.swap_previous("@parameter.inner") end, { desc = "Swap arg with prev" }) - end, - }, -{ - "christoomey/vim-tmux-navigator", - cmd = { - "TmuxNavigateLeft", "TmuxNavigateDown", - "TmuxNavigateUp", "TmuxNavigateRight", - }, - keys = { - { "", "TmuxNavigateLeft", desc = "Pane left", mode = { "n", "t" } }, - { "", "TmuxNavigateDown", desc = "Pane down", mode = { "n", "t" } }, - { "", "TmuxNavigateUp", desc = "Pane up", mode = { "n", "t" } }, - { "", "TmuxNavigateRight", desc = "Pane right", mode = { "n", "t" } }, - }, - init = function() - vim.g.tmux_navigator_no_mappings = 1 - end, -}, - - -- Folding - { - "kevinhwang91/nvim-ufo", - dependencies = { "kevinhwang91/promise-async" }, - event = "BufReadPost", - keys = { - { - "zR", - function() - require("ufo").openAllFolds() - end, - desc = "Open all folds", - }, - { - "zM", - function() - require("ufo").closeAllFolds() - end, - desc = "Close all folds", - }, - }, - opts = { - provider_selector = function() - return { "treesitter", "indent" } - end, - fold_virt_text_handler = ufo_ascii_foldtext, - }, - }, - - -- Completion engine - { - "saghen/blink.cmp", - version = "*", - dependencies = { "L3MON4D3/LuaSnip", "rafamadriz/friendly-snippets" }, - opts = { - keymap = { - preset = "none", - [""] = { "show", "show_documentation", "hide_documentation" }, - [""] = { "hide" }, - [""] = { "accept", "fallback" }, - [""] = { expand_menu, "select_next", "fallback" }, - [""] = { "select_prev", "fallback" }, - [""] = { "scroll_documentation_up", "fallback" }, - [""] = { "scroll_documentation_down", "fallback" }, - [""] = { "select_next", "fallback" }, - [""] = { "select_prev", "fallback" }, - [""] = { "snippet_forward", "fallback" }, - [""] = { "snippet_backward", "fallback" }, - }, - sources = { - default = { "lsp", "path", "snippets", "buffer" }, - }, - snippets = { preset = "luasnip" }, - completion = { - documentation = { auto_show = false, auto_show_delay_ms = 200 }, - ghost_text = { enabled = false }, - menu = { - auto_show = true, - max_height = 5, - draw = { - -- no kind_icon column -- plain text only, no nerd font glyphs - columns = { { "label", "label_description", gap = 1 } }, - }, - }, - }, - }, - }, - { - "L3MON4D3/LuaSnip", - event = "InsertEnter", - dependencies = { "rafamadriz/friendly-snippets" }, - config = function() - require("luasnip.loaders.from_vscode").lazy_load() - end, - }, - - -- LSP - { - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { "saghen/blink.cmp" }, - config = function() - vim.lsp.config("*", { - capabilities = require("blink.cmp").get_lsp_capabilities(), - }) - - vim.lsp.enable({ "clangd" }) - - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(ev) - local m = function(keys, func, desc) - vim.keymap.set("n", keys, func, { buffer = ev.buf, desc = "LSP: " .. desc }) - end - if vim.lsp.inlay_hint then - vim.lsp.inlay_hint.enable(true, { bufnr = ev.buf }) - end - m("gd", vim.lsp.buf.definition, "Goto definition") - m("gD", vim.lsp.buf.declaration, "Goto declaration") - m("gr", vim.lsp.buf.references, "Goto references") - m("gI", vim.lsp.buf.implementation, "Goto implementation") - m("K", vim.lsp.buf.hover, "Hover docs") - m("rn", vim.lsp.buf.rename, "Rename") - m("[d", vim.diagnostic.goto_prev, "Prev diagnostic") - m("]d", vim.diagnostic.goto_next, "Next diagnostic") - m("e", vim.diagnostic.open_float, "Show diagnostic") - end, - }) - - vim.diagnostic.config({ - virtual_text = true, - signs = { - text = { - [vim.diagnostic.severity.ERROR] = "E", - [vim.diagnostic.severity.WARN] = "W", - [vim.diagnostic.severity.INFO] = "I", - [vim.diagnostic.severity.HINT] = "H", - }, - }, - underline = true, - update_in_insert = false, - }) - end, - }, - + { -- Motion: s + two chars to jump anywhere + url = "https://codeberg.org/andyg/leap.nvim", + keys = { + { "s", "(leap)", mode = { "n", "x", "o" }, desc = "Leap" }, + { "S", "(leap-from-window)", mode = { "n", "o" }, desc = "Leap from window" }, + }, + }, + + { -- Buffer-based file explorer + "stevearc/oil.nvim", + lazy = false, + keys = { { "e", "Oil", desc = "File explorer" }, { "-", "Oil", desc = "Open parent dir" } }, + opts = { default_file_explorer = true, view_options = { show_hidden = true }, constrain_cursor = false }, + }, + + { -- Treesitter (syntax highlighting + textobjects) + "nvim-treesitter/nvim-treesitter", + branch = "main", + lazy = false, + build = ":TSUpdate", + dependencies = { { "nvim-treesitter/nvim-treesitter-textobjects", branch = "main" } }, + config = function() + require("nvim-treesitter").setup({}) + require("nvim-treesitter").install({ "c" }) + + vim.api.nvim_create_autocmd("FileType", { + callback = function(args) + local lang = vim.treesitter.language.get_lang(vim.bo[args.buf].filetype) + if lang and vim.treesitter.language.add(lang) then + pcall(vim.treesitter.start, args.buf, lang) + vim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end + end, + }) + + local ok_to, to = pcall(require, "nvim-treesitter-textobjects") + if not ok_to then + return + end + to.setup({ select = { lookahead = true }, move = { set_jumps = true } }) + local sel = require("nvim-treesitter-textobjects.select") + local move = require("nvim-treesitter-textobjects.move") + local swap = require("nvim-treesitter-textobjects.swap") + local tmap = vim.keymap.set + + local objs = { -- text objects: { keymap suffix, query, description } + { "af", "@function.outer", "around function" }, { "if", "@function.inner", "inside function" }, + { "ac", "@class.outer", "around class" }, { "ic", "@class.inner", "inside class" }, + { "aa", "@parameter.outer", "around argument" }, { "ia", "@parameter.inner", "inside argument" }, + { "ab", "@block.outer", "around block" }, { "ib", "@block.inner", "inside block" }, + { "ai", "@conditional.outer", "around conditional" }, { "ii", "@conditional.inner", "inside conditional" }, + { "al", "@loop.outer", "around loop" }, { "il", "@loop.inner", "inside loop" }, + } + for _, o in ipairs(objs) do + local lhs, q, d = o[1], o[2], o[3] + tmap({ "x", "o" }, lhs, function() + sel.select_textobject(q, "textobjects") + end, { desc = d }) + end + + local nmo = { "n", "x", "o" } + local moves = { -- { keymap, move method, query, description } + { "]m", "goto_next_start", "@function.outer", "next func start" }, { "[m", "goto_previous_start", "@function.outer", "prev func start" }, + { "]M", "goto_next_end", "@function.outer", "next func end" }, { "[M", "goto_previous_end", "@function.outer", "prev func end" }, + { "]]", "goto_next_start", "@class.outer", "next class start" }, { "[[", "goto_previous_start", "@class.outer", "prev class start" }, + { "][", "goto_next_end", "@class.outer", "next class end" }, { "[]", "goto_previous_end", "@class.outer", "prev class end" }, + } + for _, mv in ipairs(moves) do + local lhs, method, q, d = mv[1], mv[2], mv[3], mv[4] + tmap(nmo, lhs, function() + move[method](q, "textobjects") + end, { desc = d }) + end + + tmap("n", "a", function() + swap.swap_next("@parameter.inner") + end, { desc = "Swap arg with next" }) + tmap("n", "A", function() + swap.swap_previous("@parameter.inner") + end, { desc = "Swap arg with prev" }) + end, + }, + + { + "christoomey/vim-tmux-navigator", + cmd = { "TmuxNavigateLeft", "TmuxNavigateDown", "TmuxNavigateUp", "TmuxNavigateRight" }, + keys = { + { "", "TmuxNavigateLeft", desc = "Pane left", mode = { "n", "t" } }, + { "", "TmuxNavigateDown", desc = "Pane down", mode = { "n", "t" } }, + { "", "TmuxNavigateUp", desc = "Pane up", mode = { "n", "t" } }, + { "", "TmuxNavigateRight", desc = "Pane right", mode = { "n", "t" } }, + }, + init = function() + vim.g.tmux_navigator_no_mappings = 1 + end, + }, + + { -- Folding + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + event = "BufReadPost", + keys = { + { "zR", function() require("ufo").openAllFolds() end, desc = "Open all folds" }, + { "zM", function() require("ufo").closeAllFolds() end, desc = "Close all folds" }, + }, + opts = { + provider_selector = function() + return { "treesitter", "indent" } + end, + fold_virt_text_handler = ufo_ascii_foldtext, + }, + }, + + { "windwp/nvim-autopairs", event = "InsertEnter", opts = { check_ts = true } }, + + { -- Completion engine + "saghen/blink.cmp", + version = "*", + dependencies = { "L3MON4D3/LuaSnip", "rafamadriz/friendly-snippets" }, + opts = { + keymap = { + preset = "none", + [""] = { "show", "show_documentation", "hide_documentation" }, [""] = { "hide" }, + [""] = { "accept", "fallback" }, [""] = { expand_menu, "select_next", "fallback" }, + [""] = { "select_prev", "fallback" }, [""] = { "scroll_documentation_up", "fallback" }, + [""] = { "scroll_documentation_down", "fallback" }, [""] = { "select_next", "fallback" }, + [""] = { "select_prev", "fallback" }, [""] = { "snippet_forward", "fallback" }, + [""] = { "snippet_backward", "fallback" }, + }, + sources = { default = { "lsp", "path", "snippets", "buffer" } }, + snippets = { preset = "luasnip" }, + completion = { + documentation = { auto_show = false, auto_show_delay_ms = 200 }, + ghost_text = { enabled = false }, + menu = { + auto_show = true, + max_height = 5, + -- no kind_icon column -- plain text only, no nerd font glyphs + draw = { columns = { { "label", "label_description", gap = 1 } } }, + }, + }, + }, + }, + { + "L3MON4D3/LuaSnip", + event = "InsertEnter", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + + { -- Base16 theme, auto-loaded from wallust and live-reloaded on change + "echasnovski/mini.base16", + version = false, + lazy = false, + priority = 1000, + config = function() + local palette_path = vim.fn.expand("~/.cache/wallust/nvim.lua") + local fallback = { + base00 = "#1e1e2e", base01 = "#181825", base02 = "#313244", base03 = "#45475a", + base04 = "#585b70", base05 = "#cdd6f4", base06 = "#f5c2e7", base07 = "#b4befe", + base08 = "#f38ba8", base09 = "#fab387", base0A = "#f9e2af", base0B = "#a6e3a1", + base0C = "#94e2d5", base0D = "#89b4fa", base0E = "#cba6f7", base0F = "#f2cdcd", + } + local function load_palette() + local ok, p = pcall(dofile, palette_path) + return ok and p or fallback + end + + -- groups cleared to guibg=NONE when transparency is toggled on + local transparent_groups = { + "Normal", "NormalNC", "NormalFloat", "SignColumn", "FoldColumn", "EndOfBuffer", + "LineNr", "LineNrAbove", "LineNrBelow", "CursorLineNr", "CursorLine", "StatusLine", + "StatusLineNC", "TabLine", "TabLineFill", "TabLineSel", "VertSplit", "WinSeparator", + "Pmenu", "PmenuSbar", "PmenuThumb", "FloatBorder", "FloatTitle", "CursorLineSign", + "DiagnosticSignError", "DiagnosticSignWarn", "DiagnosticSignInfo", "DiagnosticSignHint", + } + local function apply_transparent() + for _, grp in ipairs(transparent_groups) do + vim.cmd("hi " .. grp .. " guibg=NONE ctermbg=NONE") + end + end + + local function apply(palette) + require("mini.base16").setup({ palette = palette }) + -- pin gutter/sign/diagnostic backgrounds to match Normal (mini.base16 defaults them to base01) + local hls = { + LineNr = { fg = palette.base05, bg = palette.base00 }, + LineNrAbove = { fg = palette.base05, bg = palette.base00 }, + LineNrBelow = { fg = palette.base05, bg = palette.base00 }, + CursorLineNr = { fg = palette.base03, bg = palette.base00, bold = true }, + FoldColumn = { fg = palette.base0C, bg = palette.base00 }, + SignColumn = { bg = palette.base00 }, + CursorLineSign = { bg = palette.base00 }, + DiagnosticSignError = { fg = palette.base08, bg = palette.base00 }, + DiagnosticSignWarn = { fg = palette.base0A, bg = palette.base00 }, + DiagnosticSignInfo = { fg = palette.base0D, bg = palette.base00 }, + DiagnosticSignHint = { fg = palette.base0C, bg = palette.base00 }, + } + for grp, spec in pairs(hls) do + vim.api.nvim_set_hl(0, grp, spec) + end + if vim.g.transparent_bg then + apply_transparent() + end + end + + vim.g.transparent_bg = false + apply(load_palette()) + + local watcher = vim.uv.new_fs_event() -- live-reload palette on wallust regen + if watcher then + watcher:start(palette_path, {}, vim.schedule_wrap(function() + apply(load_palette()) + end)) + end + + vim.keymap.set("n", "tt", function() + vim.g.transparent_bg = not vim.g.transparent_bg + if vim.g.transparent_bg then + apply_transparent() + else + apply(load_palette()) + end + end, { desc = "Toggle transparent background" }) + end, + }, + + { -- LSP + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { "saghen/blink.cmp" }, + config = function() + vim.lsp.config("*", { capabilities = require("blink.cmp").get_lsp_capabilities() }) + vim.lsp.enable({ "clangd" }) + + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(ev) + local m = function(keys, func, desc) + vim.keymap.set("n", keys, func, { buffer = ev.buf, desc = "LSP: " .. desc }) + end + if vim.lsp.inlay_hint then + vim.lsp.inlay_hint.enable(true, { bufnr = ev.buf }) + end + m("gd", vim.lsp.buf.definition, "Goto definition") + m("gD", vim.lsp.buf.declaration, "Goto declaration") + m("gr", vim.lsp.buf.references, "Goto references") + m("gI", vim.lsp.buf.implementation, "Goto implementation") + m("K", vim.lsp.buf.hover, "Hover docs") + m("rn", vim.lsp.buf.rename, "Rename") + m("[d", vim.diagnostic.goto_prev, "Prev diagnostic") + m("]d", vim.diagnostic.goto_next, "Next diagnostic") + m("e", vim.diagnostic.open_float, "Show diagnostic") + end, + }) + + vim.diagnostic.config({ + virtual_text = true, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = "E", [vim.diagnostic.severity.WARN] = "W", + [vim.diagnostic.severity.INFO] = "I", [vim.diagnostic.severity.HINT] = "H", + }, + }, + underline = true, + update_in_insert = false, + }) + end, + }, }, { - install = { colorscheme = { "retrobox" } }, - checker = { enabled = false }, - change_detection = { notify = false }, + checker = { enabled = false }, + change_detection = { notify = false }, }) - -vim.cmd.colorscheme("retrobox") diff --git a/arch/alpvim/.config/alpvim/init.lua.old b/arch/alpvim/.config/alpvim/init.lua.old new file mode 100644 index 0000000..46a4ef3 --- /dev/null +++ b/arch/alpvim/.config/alpvim/init.lua.old @@ -0,0 +1,523 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.uv.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) + +-- Leader +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +-- ============================================================ +-- Options (adjusted for a raw TTY) +-- ============================================================ + +local opt = vim.opt + +-- Line numbers +opt.number = true +opt.relativenumber = true + +-- Indentation +opt.expandtab = true +opt.tabstop = 4 +opt.shiftwidth = 4 +opt.softtabstop = 4 + +-- Visual +opt.cursorline = true +opt.scrolloff = 20 +opt.signcolumn = "yes" +opt.list = true +opt.listchars = { tab = " ", trail = ".", nbsp = "_" } +opt.fillchars:append({ fold = "-" }) +opt.termguicolors = true +opt.colorcolumn = "" + +-- Behaviour +opt.swapfile = false +opt.undofile = true +opt.updatetime = 250 +opt.timeoutlen = 300 +opt.splitbelow = true +opt.splitright = true +opt.ignorecase = true +opt.smartcase = true +opt.inccommand = "split" +opt.hlsearch = true +opt.breakindent = true + +-- Folding (nvim-ufo, see plugin list below) +opt.foldcolumn = "0" +opt.foldlevel = 99 +opt.foldlevelstart = 99 +opt.foldenable = true + +local map = vim.keymap.set + +-- ============================================================ +-- Keymaps +-- ============================================================ + +-- Disable Space in normal/visual (used as leader) +map({ "n", "v" }, "", "", { silent = true }) + +-- Save +map({ "n", "i" }, "", "w", { desc = "Save" }) + +-- Clear search highlight +map("n", "", "nohlsearch") + +-- Exit terminal mode +map("t", "", "", { desc = "Exit terminal" }) + +-- Better up/down on wrapped lines +map({ "n", "v" }, "j", "gj") +map({ "n", "v" }, "k", "gk") + +-- Buffer navigation +map("n", "", "bprevious", { desc = "Prev buffer" }) +map("n", "", "bnext", { desc = "Next buffer" }) +map("n", "bd", "bdelete", { desc = "Delete buffer" }) + +-- Splits +map("n", "sv", "v", { desc = "Split vertical" }) +map("n", "sh", "s", { desc = "Split horizontal" }) +map("n", "se", "=", { desc = "Equal splits" }) +map("n", "sx", "close", { desc = "Close split" }) + +-- Move lines +map("n", "", "m .+1==", { desc = "Move line down" }) +map("n", "", "m .-2==", { desc = "Move line up" }) +map("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) +map("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) + +-- Stay in visual after indent +map("v", "<", "", ">gv") + +-- ============================================================ +-- Completion helper +-- ============================================================ + +local function expand_menu() + local cfg = require("blink.cmp.config").completion + cfg.menu.max_height = 10 + cfg.documentation.auto_show = true + pcall(function() + require("blink.cmp.completion.windows.menu").update_position() + end) +end + +vim.api.nvim_create_autocmd("User", { + pattern = "BlinkCmpMenuClose", + callback = function() + local ok, cfg = pcall(function() + return require("blink.cmp.config").completion + end) + if not ok then + return + end + cfg.menu.max_height = 5 + cfg.documentation.auto_show = false + end, +}) +-- +-- ============================================================ +-- Trim whitespace on save +-- ============================================================ + +vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*", + callback = function() + if vim.bo.filetype == "markdown" then + return + end + local view = vim.fn.winsaveview() + vim.cmd([[keeppatterns %s/\s\+$//e]]) + vim.fn.winrestview(view) + end, +}) + +-- ============================================================ +-- Fold text helper +-- ============================================================ + +local function ufo_ascii_foldtext(virtText, lnum, endLnum, width, truncate) + local newVirtText = {} + local suffix = (" ... %d lines "):format(endLnum - lnum) + local sufWidth = vim.fn.strdisplaywidth(suffix) + local targetWidth = width - sufWidth + local curWidth = 0 + for _, chunk in ipairs(virtText) do + local chunkText = chunk[1] + local chunkWidth = vim.fn.strdisplaywidth(chunkText) + if targetWidth > curWidth + chunkWidth then + table.insert(newVirtText, chunk) + else + chunkText = truncate(chunkText, targetWidth - curWidth) + local hlGroup = chunk[2] + table.insert(newVirtText, { chunkText, hlGroup }) + chunkWidth = vim.fn.strdisplaywidth(chunkText) + if curWidth + chunkWidth < targetWidth then + suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) + end + break + end + curWidth = curWidth + chunkWidth + end + table.insert(newVirtText, { suffix, "Comment" }) + return newVirtText +end + +-- ============================================================ +-- Plugins: leap, oil, treesitter, nvim-ufo, clangd, blink.cmp +-- ============================================================ + +require("lazy").setup({ + + -- Motion: s + two chars to jump anywhere + { + url = "https://codeberg.org/andyg/leap.nvim", + keys = { + { "s", "(leap)", mode = { "n", "x", "o" }, desc = "Leap" }, + { "S", "(leap-from-window)", mode = { "n", "o" }, desc = "Leap from window" }, + }, + }, + + -- Buffer-based file explorer + { + "stevearc/oil.nvim", + lazy = false, + keys = { + { "e", "Oil", desc = "File explorer" }, + { "-", "Oil", desc = "Open parent dir" }, + }, + opts = { + default_file_explorer = true, + view_options = { show_hidden = true }, + constrain_cursor = false, + }, + }, + + -- Treesitter (syntax highlighting + textobjects) + { + "nvim-treesitter/nvim-treesitter", + branch = "main", + lazy = false, + build = ":TSUpdate", + dependencies = { + { "nvim-treesitter/nvim-treesitter-textobjects", branch = "main" }, + }, + config = function() + require("nvim-treesitter").setup({}) + require("nvim-treesitter").install({ "c" }) + + vim.api.nvim_create_autocmd("FileType", { + callback = function(args) + local lang = vim.treesitter.language.get_lang(vim.bo[args.buf].filetype) + if lang and vim.treesitter.language.add(lang) then + pcall(vim.treesitter.start, args.buf, lang) + vim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end + end, + }) + + local ok_to, to = pcall(require, "nvim-treesitter-textobjects") + if not ok_to then + return + end + to.setup({ + select = { lookahead = true }, + move = { set_jumps = true }, + }) + local sel = require("nvim-treesitter-textobjects.select") + local move = require("nvim-treesitter-textobjects.move") + local swap = require("nvim-treesitter-textobjects.swap") + local tmap = vim.keymap.set + + local objs = { + { "af", "@function.outer", "around function" }, + { "if", "@function.inner", "inside function" }, + { "ac", "@class.outer", "around class" }, + { "ic", "@class.inner", "inside class" }, + { "aa", "@parameter.outer", "around argument" }, + { "ia", "@parameter.inner", "inside argument" }, + { "ab", "@block.outer", "around block" }, + { "ib", "@block.inner", "inside block" }, + { "ai", "@conditional.outer", "around conditional" }, + { "ii", "@conditional.inner", "inside conditional" }, + { "al", "@loop.outer", "around loop" }, + { "il", "@loop.inner", "inside loop" }, + } + for _, o in ipairs(objs) do + local lhs, q, d = o[1], o[2], o[3] + tmap({ "x", "o" }, lhs, function() + sel.select_textobject(q, "textobjects") + end, { desc = d }) + end + + local nmo = { "n", "x", "o" } + tmap(nmo, "]m", function() + move.goto_next_start("@function.outer", "textobjects") + end, { desc = "next func start" }) + tmap(nmo, "[m", function() + move.goto_previous_start("@function.outer", "textobjects") + end, { desc = "prev func start" }) + tmap(nmo, "]M", function() + move.goto_next_end("@function.outer", "textobjects") + end, { desc = "next func end" }) + tmap(nmo, "[M", function() + move.goto_previous_end("@function.outer", "textobjects") + end, { desc = "prev func end" }) + tmap(nmo, "]]", function() + move.goto_next_start("@class.outer", "textobjects") + end, { desc = "next class start" }) + tmap(nmo, "[[", function() + move.goto_previous_start("@class.outer", "textobjects") + end, { desc = "prev class start" }) + tmap(nmo, "][", function() + move.goto_next_end("@class.outer", "textobjects") + end, { desc = "next class end" }) + tmap(nmo, "[]", function() + move.goto_previous_end("@class.outer", "textobjects") + end, { desc = "prev class end" }) + + tmap("n", "a", function() + swap.swap_next("@parameter.inner") + end, { desc = "Swap arg with next" }) + tmap("n", "A", function() + swap.swap_previous("@parameter.inner") + end, { desc = "Swap arg with prev" }) + end, + }, + { + "christoomey/vim-tmux-navigator", + cmd = { + "TmuxNavigateLeft", + "TmuxNavigateDown", + "TmuxNavigateUp", + "TmuxNavigateRight", + }, + keys = { + { "", "TmuxNavigateLeft", desc = "Pane left", mode = { "n", "t" } }, + { "", "TmuxNavigateDown", desc = "Pane down", mode = { "n", "t" } }, + { "", "TmuxNavigateUp", desc = "Pane up", mode = { "n", "t" } }, + { "", "TmuxNavigateRight", desc = "Pane right", mode = { "n", "t" } }, + }, + init = function() + vim.g.tmux_navigator_no_mappings = 1 + end, + }, + + -- Folding + { + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + event = "BufReadPost", + keys = { + { + "zR", + function() + require("ufo").openAllFolds() + end, + desc = "Open all folds", + }, + { + "zM", + function() + require("ufo").closeAllFolds() + end, + desc = "Close all folds", + }, + }, + opts = { + provider_selector = function() + return { "treesitter", "indent" } + end, + fold_virt_text_handler = ufo_ascii_foldtext, + }, + }, + { + "windwp/nvim-autopairs", + event = "InsertEnter", + opts = { check_ts = true }, + }, + + -- Completion engine + { + "saghen/blink.cmp", + version = "*", + dependencies = { "L3MON4D3/LuaSnip", "rafamadriz/friendly-snippets" }, + opts = { + keymap = { + preset = "none", + [""] = { "show", "show_documentation", "hide_documentation" }, + [""] = { "hide" }, + [""] = { "accept", "fallback" }, + [""] = { expand_menu, "select_next", "fallback" }, + [""] = { "select_prev", "fallback" }, + [""] = { "scroll_documentation_up", "fallback" }, + [""] = { "scroll_documentation_down", "fallback" }, + [""] = { "select_next", "fallback" }, + [""] = { "select_prev", "fallback" }, + [""] = { "snippet_forward", "fallback" }, + [""] = { "snippet_backward", "fallback" }, + }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + }, + snippets = { preset = "luasnip" }, + completion = { + documentation = { auto_show = false, auto_show_delay_ms = 200 }, + ghost_text = { enabled = false }, + menu = { + auto_show = true, + max_height = 5, + draw = { + -- no kind_icon column -- plain text only, no nerd font glyphs + columns = { { "label", "label_description", gap = 1 } }, + }, + }, + }, + }, + }, + { + "L3MON4D3/LuaSnip", + event = "InsertEnter", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + + -- Base16 theme, auto-loaded from wallust and live-reloaded on change + { + "echasnovski/mini.base16", + version = false, + lazy = false, + priority = 1000, + config = function() + local palette_path = vim.fn.expand("~/.cache/wallust/nvim.lua") + local fallback = { + base00 = "#1e1e2e", base01 = "#181825", base02 = "#313244", base03 = "#45475a", + base04 = "#585b70", base05 = "#cdd6f4", base06 = "#f5c2e7", base07 = "#b4befe", + base08 = "#f38ba8", base09 = "#fab387", base0A = "#f9e2af", base0B = "#a6e3a1", + base0C = "#94e2d5", base0D = "#89b4fa", base0E = "#cba6f7", base0F = "#f2cdcd", + } + local function load_palette() + local ok, p = pcall(dofile, palette_path) + return ok and p or fallback + end + + local transparent_groups = { + "Normal", "NormalNC", "NormalFloat", "SignColumn", "FoldColumn", "EndOfBuffer", + "LineNr", "LineNrAbove", "LineNrBelow", "CursorLineNr", "CursorLine", "StatusLine", + "StatusLineNC", "TabLine", "TabLineFill", "TabLineSel", "VertSplit", "WinSeparator", "Pmenu", "PmenuSbar", + "PmenuThumb", "FloatBorder", "FloatTitle", "CursorLineSign", + "DiagnosticSignError", "DiagnosticSignWarn", "DiagnosticSignInfo", "DiagnosticSignHint", + } + local function apply_transparent() + for _, grp in ipairs(transparent_groups) do + vim.cmd("hi " .. grp .. " guibg=NONE ctermbg=NONE") + end + end + + local function apply(palette) + require("mini.base16").setup({ palette = palette }) + vim.api.nvim_set_hl(0, "LineNr", { fg = palette.base05, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "LineNrAbove", { fg = palette.base05, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "LineNrBelow", { fg = palette.base05, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "CursorLineNr", { fg = palette.base03, bg = palette.base00, bold = true }) + vim.api.nvim_set_hl(0, "FoldColumn", { fg = palette.base0C, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "SignColumn", { bg = palette.base00 }) + vim.api.nvim_set_hl(0, "CursorLineSign", { bg = palette.base00 }) + vim.api.nvim_set_hl(0, "DiagnosticSignError", { fg = palette.base08, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "DiagnosticSignWarn", { fg = palette.base0A, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "DiagnosticSignInfo", { fg = palette.base0D, bg = palette.base00 }) + vim.api.nvim_set_hl(0, "DiagnosticSignHint", { fg = palette.base0C, bg = palette.base00 }) + if vim.g.transparent_bg then + apply_transparent() + end + end + + vim.g.transparent_bg = false + apply(load_palette()) + + local watcher = vim.uv.new_fs_event() + if watcher then + watcher:start(palette_path, {}, vim.schedule_wrap(function() + apply(load_palette()) + end)) + end + + vim.keymap.set("n", "tt", function() + vim.g.transparent_bg = not vim.g.transparent_bg + if vim.g.transparent_bg then + apply_transparent() + else + apply(load_palette()) + end + end, { desc = "Toggle transparent background" }) + end, + }, + + -- LSP + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { "saghen/blink.cmp" }, + config = function() + vim.lsp.config("*", { + capabilities = require("blink.cmp").get_lsp_capabilities(), + }) + + vim.lsp.enable({ "clangd" }) + + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(ev) + local m = function(keys, func, desc) + vim.keymap.set("n", keys, func, { buffer = ev.buf, desc = "LSP: " .. desc }) + end + if vim.lsp.inlay_hint then + vim.lsp.inlay_hint.enable(true, { bufnr = ev.buf }) + end + m("gd", vim.lsp.buf.definition, "Goto definition") + m("gD", vim.lsp.buf.declaration, "Goto declaration") + m("gr", vim.lsp.buf.references, "Goto references") + m("gI", vim.lsp.buf.implementation, "Goto implementation") + m("K", vim.lsp.buf.hover, "Hover docs") + m("rn", vim.lsp.buf.rename, "Rename") + m("[d", vim.diagnostic.goto_prev, "Prev diagnostic") + m("]d", vim.diagnostic.goto_next, "Next diagnostic") + m("e", vim.diagnostic.open_float, "Show diagnostic") + end, + }) + + vim.diagnostic.config({ + virtual_text = true, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = "E", + [vim.diagnostic.severity.WARN] = "W", + [vim.diagnostic.severity.INFO] = "I", + [vim.diagnostic.severity.HINT] = "H", + }, + }, + underline = true, + update_in_insert = false, + }) + end, + }, +}, { + checker = { enabled = false }, + change_detection = { notify = false }, +}) -- cgit v1.2.3