From a5ae7026bbdd7a6749b00740c816b6166e9472f9 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Wed, 1 Apr 2026 23:01:39 +0200 Subject: [PATCH 1/7] feat: add new nvim package manager --- files/.config/nvim/init.lua | 3 +- files/.config/nvim/lazy-lock.json | 3 +- .../nvim/lua/custom/plugins/bufferline.lua | 163 ----- .../nvim/lua/custom/plugins/colorscheme.lua | 48 -- .../nvim/lua/custom/plugins/comment.lua | 22 - .../nvim/lua/custom/plugins/copilot.lua | 259 -------- .../nvim/lua/custom/plugins/dadbod.lua | 23 - .../.config/nvim/lua/custom/plugins/debug.lua | 108 ---- .../nvim/lua/custom/plugins/filetype.lua | 212 ------- .../.config/nvim/lua/custom/plugins/folke.lua | 1 - .../nvim/lua/custom/plugins/format.lua | 112 ---- files/.config/nvim/lua/custom/plugins/fzf.lua | 316 ---------- .../nvim/lua/custom/plugins/gaming.lua | 4 - files/.config/nvim/lua/custom/plugins/git.lua | 535 ---------------- .../.config/nvim/lua/custom/plugins/init.lua | 74 --- files/.config/nvim/lua/custom/plugins/lsp.lua | 586 ------------------ .../.config/nvim/lua/custom/plugins/mini.lua | 385 ------------ .../nvim/lua/custom/plugins/navigation.lua | 65 -- .../.config/nvim/lua/custom/plugins/noice.lua | 291 --------- .../nvim/lua/custom/plugins/obsidian.lua | 180 ------ .../nvim/lua/custom/plugins/remote.lua | 35 -- .../.config/nvim/lua/custom/plugins/repl.lua | 31 - .../nvim/lua/custom/plugins/terminal.lua | 94 --- .../nvim/lua/custom/plugins/testing.lua | 65 -- .../.config/nvim/lua/custom/plugins/todo.lua | 58 -- .../nvim/lua/custom/plugins/treesitter.lua | 166 ----- files/.config/nvim/lua/custom/plugins/ui.lua | 322 ---------- .../nvim/lua/custom/plugins/whichkey.lua | 44 -- files/.config/nvim/lua/highlight.lua | 206 +----- files/.config/nvim/lua/lazyloader.lua | 92 --- files/.config/nvim/lua/packloader.lua | 236 +++++++ files/.config/nvim/lua/packs/bufferline.lua | 155 +++++ files/.config/nvim/lua/packs/colorscheme.lua | 30 + files/.config/nvim/lua/packs/comment.lua | 19 + .../{custom/plugins => packs}/completion.lua | 93 ++- files/.config/nvim/lua/packs/copilot.lua | 184 ++++++ files/.config/nvim/lua/packs/dadbod.lua | 4 + files/.config/nvim/lua/packs/debug.lua | 83 +++ files/.config/nvim/lua/packs/filetype.lua | 104 ++++ files/.config/nvim/lua/packs/folke.lua | 0 files/.config/nvim/lua/packs/format.lua | 103 +++ files/.config/nvim/lua/packs/fzf.lua | 228 +++++++ files/.config/nvim/lua/packs/gaming.lua | 4 + files/.config/nvim/lua/packs/git.lua | 411 ++++++++++++ files/.config/nvim/lua/packs/init.lua | 33 + .../lua/{custom/plugins => packs}/linting.lua | 27 +- files/.config/nvim/lua/packs/lsp.lua | 390 ++++++++++++ files/.config/nvim/lua/packs/mini.lua | 154 +++++ files/.config/nvim/lua/packs/navigation.lua | 30 + .../lua/{custom/plugins => packs}/neotree.lua | 0 files/.config/nvim/lua/packs/noice.lua | 284 +++++++++ files/.config/nvim/lua/packs/obsidian.lua | 33 + files/.config/nvim/lua/packs/remote.lua | 11 + files/.config/nvim/lua/packs/repl.lua | 14 + files/.config/nvim/lua/packs/terminal.lua | 88 +++ files/.config/nvim/lua/packs/testing.lua | 56 ++ files/.config/nvim/lua/packs/todo.lua | 42 ++ files/.config/nvim/lua/packs/treesitter.lua | 85 +++ files/.config/nvim/lua/packs/ui.lua | 349 +++++++++++ .../lua/{custom/config => packs}/vimtex.lua | 0 files/.config/nvim/lua/packs/whichkey.lua | 41 ++ files/.config/nvim/lua/tools.lua | 187 +++++- files/.config/nvim/nvim-pack-lock.json | 452 ++++++++++++++ 63 files changed, 3860 insertions(+), 4573 deletions(-) delete mode 100644 files/.config/nvim/lua/custom/plugins/bufferline.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/colorscheme.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/comment.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/copilot.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/dadbod.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/debug.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/filetype.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/folke.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/format.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/fzf.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/gaming.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/git.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/init.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/lsp.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/mini.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/navigation.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/noice.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/obsidian.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/remote.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/repl.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/terminal.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/testing.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/todo.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/treesitter.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/ui.lua delete mode 100644 files/.config/nvim/lua/custom/plugins/whichkey.lua delete mode 100644 files/.config/nvim/lua/lazyloader.lua create mode 100644 files/.config/nvim/lua/packloader.lua create mode 100644 files/.config/nvim/lua/packs/bufferline.lua create mode 100644 files/.config/nvim/lua/packs/colorscheme.lua create mode 100644 files/.config/nvim/lua/packs/comment.lua rename files/.config/nvim/lua/{custom/plugins => packs}/completion.lua (80%) create mode 100644 files/.config/nvim/lua/packs/copilot.lua create mode 100644 files/.config/nvim/lua/packs/dadbod.lua create mode 100644 files/.config/nvim/lua/packs/debug.lua create mode 100644 files/.config/nvim/lua/packs/filetype.lua create mode 100644 files/.config/nvim/lua/packs/folke.lua create mode 100644 files/.config/nvim/lua/packs/format.lua create mode 100644 files/.config/nvim/lua/packs/fzf.lua create mode 100644 files/.config/nvim/lua/packs/gaming.lua create mode 100644 files/.config/nvim/lua/packs/git.lua create mode 100644 files/.config/nvim/lua/packs/init.lua rename files/.config/nvim/lua/{custom/plugins => packs}/linting.lua (86%) create mode 100644 files/.config/nvim/lua/packs/lsp.lua create mode 100644 files/.config/nvim/lua/packs/mini.lua create mode 100644 files/.config/nvim/lua/packs/navigation.lua rename files/.config/nvim/lua/{custom/plugins => packs}/neotree.lua (100%) create mode 100644 files/.config/nvim/lua/packs/noice.lua create mode 100644 files/.config/nvim/lua/packs/obsidian.lua create mode 100644 files/.config/nvim/lua/packs/remote.lua create mode 100644 files/.config/nvim/lua/packs/repl.lua create mode 100644 files/.config/nvim/lua/packs/terminal.lua create mode 100644 files/.config/nvim/lua/packs/testing.lua create mode 100644 files/.config/nvim/lua/packs/todo.lua create mode 100644 files/.config/nvim/lua/packs/treesitter.lua create mode 100644 files/.config/nvim/lua/packs/ui.lua rename files/.config/nvim/lua/{custom/config => packs}/vimtex.lua (100%) create mode 100644 files/.config/nvim/lua/packs/whichkey.lua create mode 100644 files/.config/nvim/nvim-pack-lock.json diff --git a/files/.config/nvim/init.lua b/files/.config/nvim/init.lua index 630803c..71f884a 100644 --- a/files/.config/nvim/init.lua +++ b/files/.config/nvim/init.lua @@ -34,8 +34,7 @@ end require('tools') -- has to be loaded before plugins (bootstraps ui, strings, colors) require('keymaps') require('options') -require('highlight') -- needed by plugins for highlight tables -require('lazyloader') +require('packloader') -- Defer non-critical modules for faster startup vim.defer_fn(function() require('external_grep') end, 0) diff --git a/files/.config/nvim/lazy-lock.json b/files/.config/nvim/lazy-lock.json index d6207a9..be76751 100644 --- a/files/.config/nvim/lazy-lock.json +++ b/files/.config/nvim/lazy-lock.json @@ -24,13 +24,12 @@ "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, "glance.nvim": { "branch": "master", "commit": "bf86d8b79dce808e65fdb6e9269d0b4ed6d2eefc" }, "grapple.nvim": { "branch": "main", "commit": "b41ddfc1c39f87f3d1799b99c2f0f1daa524c5f7" }, - "hererocks": { "branch": "master", "commit": "3db37265c3839cbd4d27fc73f92fa7b58bc3a76f" }, "image.nvim": { "branch": "master", "commit": "da2be65c153ba15a14a342b05591652a6df70d58" }, "inc-rename.nvim": { "branch": "main", "commit": "0074b551a17338ccdcd299bd86687cc651bcb33d" }, "incline.nvim": { "branch": "main", "commit": "8b54c59bcb23366645ae10edca6edfb9d3a0853e" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "key-analyzer.nvim": { "branch": "main", "commit": "4e4bef34498e821bcbd5203f44db8b67e4f10e04" }, - "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, "lspkind.nvim": { "branch": "master", "commit": "c7274c48137396526b59d86232eabcdc7fed8a32" }, "markdown-table-mode.nvim": { "branch": "main", "commit": "bb1ea9b76c1b29e15e14806fdfbb2319df5c06f1" }, diff --git a/files/.config/nvim/lua/custom/plugins/bufferline.lua b/files/.config/nvim/lua/custom/plugins/bufferline.lua deleted file mode 100644 index fd6c035..0000000 --- a/files/.config/nvim/lua/custom/plugins/bufferline.lua +++ /dev/null @@ -1,163 +0,0 @@ -return { - - { - 'akinsho/bufferline.nvim', - event = 'UIEnter', - dependencies = { 'echasnovski/mini.icons' }, - config = function() - local bufferline = require('bufferline') - local UI = require('tools').ui - - -- Derive colours from live highlight groups so every theme looks great. - local function hl_hex(name, attr, fallback) - local ok, h = - pcall(vim.api.nvim_get_hl, 0, { name = name, link = false }) - if ok and h and h[attr] then return ('#%06x'):format(h[attr]) end - return fallback - end - - local NUMS = - { '➊', '➋', '➌', '➍', '➎', '➏', '➐', '➑', '➒', '➓' } - - local function setup() - local pal = UI.palette or {} - local bg = hl_hex('StatusLine', 'bg', 'NONE') - local bg_sel = hl_hex('Normal', 'bg', '#1e1e2e') - local fg_sel = hl_hex('Normal', 'fg', '#cdd6f4') - local fg_dim = pal.comment_grey or hl_hex('Comment', 'fg', '#6c7086') - local accent = pal.blue or hl_hex('Function', 'fg', '#82aaff') - - bufferline.setup({ - highlights = { - -- Tabline gutter & inactive tabs share the statusline bg - fill = { bg = bg }, - background = { bg = bg, fg = fg_dim }, - tab = { bg = bg, fg = fg_dim }, - tab_close = { bg = bg, fg = fg_dim }, - close_button = { bg = bg, fg = fg_dim }, - - -- Selected buffer pops out with normal bg - buffer_selected = { - bg = bg_sel, - fg = fg_sel, - bold = true, - italic = false, - }, - close_button_selected = { bg = bg_sel, fg = fg_dim }, - tab_selected = { bg = bg, fg = fg_sel, bold = true }, - - -- Visible (non-focused split) buffer - buffer_visible = { bg = bg, fg = fg_dim }, - - -- Powerline triangle separators - separator = { bg = bg, fg = bg_sel }, - separator_selected = { bg = bg_sel, fg = bg }, - separator_visible = { bg = bg, fg = bg_sel }, - offset_separator = { bg = bg, fg = bg_sel }, - - -- Indicator line under selected tab uses the accent colour - indicator_selected = { fg = accent, bg = bg_sel }, - - -- Numbers - numbers = { bg = bg, fg = fg_dim }, - numbers_selected = { bg = bg_sel, fg = fg_sel }, - - -- Pick - pick = { bg = bg, fg = accent, bold = true, italic = true }, - pick_selected = { - bg = bg_sel, - fg = accent, - bold = true, - italic = true, - }, - }, - - options = { - style_preset = bufferline.style_preset.minimal, - separator_style = { '', '' }, - mode = 'buffers', - custom_areas = { - right = function() - local tabs = vim.api.nvim_list_tabpages() - if #tabs <= 1 then return {} end - local result = {} - local cur = vim.api.nvim_get_current_tabpage() - for i, tab in ipairs(tabs) do - local sym = NUMS[i] or tostring(i) - local hl = tab == cur and 'BufferLineTabSelected' - or 'BufferLineTab' - table.insert(result, { text = ' ' .. sym .. ' ', link = hl }) - end - return result - end, - }, - sort_by = 'insert_after_current', - move_wraps_at_ends = true, - right_mouse_command = 'vert sbuffer %d', - show_close_icon = false, - show_buffer_close_icons = false, - show_tab_indicators = false, - indicator = { style = 'none' }, - - custom_filter = function(buf_number) - local name = vim.api.nvim_buf_get_name(buf_number) - if name:match('^fugitive://') then return false end - if name == '' then return false end - return true - end, - - hover = { enabled = true, delay = 150, reveal = { 'close' } }, - - offsets = { - { - text = ' EXPLORER', - filetype = 'neo-tree', - highlight = 'PanelHeading', - separator = false, - text_align = 'left', - }, - { - text = ' UNDOTREE', - filetype = 'undotree', - highlight = 'PanelHeading', - separator = false, - text_align = 'left', - }, - { - text = '󰆼 DATABASE', - filetype = 'dbui', - highlight = 'PanelHeading', - separator = false, - text_align = 'left', - }, - { - text = ' DIFF VIEW', - filetype = 'DiffviewFiles', - highlight = 'PanelHeading', - separator = false, - text_align = 'left', - }, - }, - }, - }) - end - - setup() - vim.api.nvim_create_autocmd('ColorScheme', { - group = vim.api.nvim_create_augroup('MrlBufferline', { clear = true }), - callback = setup, - }) - - -- Keymaps - local map = function(lhs, rhs, desc) - vim.keymap.set('n', lhs, rhs, { desc = desc }) - end - map('[b', 'BufferLineMoveNext', 'bufferline: move next') - map(']b', 'BufferLineMovePrev', 'bufferline: move prev') - map('gbb', 'BufferLinePick', 'bufferline: pick buffer') - map('gbd', 'BufferLinePickClose', 'bufferline: delete buffer') - map('', 'BufferLineCyclePrev', 'bufferline: prev') - map('', 'BufferLineCycleNext', 'bufferline: next') - end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/colorscheme.lua b/files/.config/nvim/lua/custom/plugins/colorscheme.lua deleted file mode 100644 index e2698a0..0000000 --- a/files/.config/nvim/lua/custom/plugins/colorscheme.lua +++ /dev/null @@ -1,48 +0,0 @@ --- DONE -local is_dev = vim.fn.isdirectory( - '/Users/marcos/Workspaces/personal/theme-builder' -) == 1 - -return { - - { - 'vague2k/vague.nvim', - lazy = false, - enabled = not is_dev, - cond = not is_dev, - priority = 1000, - config = function() - require('vague').setup({ - transparent = false, - style = { - boolean = 'none', - number = 'none', - float = 'none', - error = 'none', - comments = 'italic', - conditionals = 'none', - functions = 'none', - headings = 'bold', - operators = 'none', - strings = 'none', - variables = 'none', - keywords = 'italic', - }, - }) - - vim.cmd('colorscheme vague') - end, - }, - -- BEGIN_NEOVIM_THEME - { - 'marromlam/theme-builder.nvim', - lazy = false, - dev = true, - enabled = is_dev, - cond = is_dev, - priority = 1000, - dir = '/Users/marcos/Workspaces/personal/theme-builder/generated/amberglow/nvim', - config = function() vim.cmd.colorscheme('amberglow') end, - }, - -- END_NEOVIM_THEME -} diff --git a/files/.config/nvim/lua/custom/plugins/comment.lua b/files/.config/nvim/lua/custom/plugins/comment.lua deleted file mode 100644 index bb56912..0000000 --- a/files/.config/nvim/lua/custom/plugins/comment.lua +++ /dev/null @@ -1,22 +0,0 @@ -return { - { - 'numToStr/Comment.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - dependencies = { - 'JoosepAlviste/nvim-ts-context-commentstring', - }, - config = function() - -- import comment plugin safely - local comment = require('Comment') - - local ts_context_commentstring = - require('ts_context_commentstring.integrations.comment_nvim') - - -- enable comment - comment.setup({ - -- for commenting tsx, jsx, svelte, html files - pre_hook = ts_context_commentstring.create_pre_hook(), - }) - end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/copilot.lua b/files/.config/nvim/lua/custom/plugins/copilot.lua deleted file mode 100644 index 247288f..0000000 --- a/files/.config/nvim/lua/custom/plugins/copilot.lua +++ /dev/null @@ -1,259 +0,0 @@ -return { - { - 'zbirenbaum/copilot.lua', - cmd = 'Copilot', - event = 'InsertEnter', - config = function() - require('copilot').setup({ - panel = { - enabled = true, - auto_refresh = false, - keymap = { - jump_prev = '[[', - jump_next = ']]', - accept = '', - refresh = 'gr', - open = '', - }, - layout = { - position = 'bottom', -- | top | left | right - ratio = 0.4, - }, - }, - suggestion = { - enabled = true, - auto_trigger = true, - hide_during_completion = true, - debounce = 75, - keymap = { - accept = '', - accept_word = false, - accept_line = false, - next = '', - prev = '', - dismiss = '', - }, - }, - filetypes = { - yaml = false, - markdown = false, - help = false, - gitcommit = false, - gitrebase = false, - hgcommit = false, - svn = false, - cvs = false, - ['.'] = false, - }, - copilot_node_command = 'node', -- Node.js version must be > 18.x - server_opts_overrides = {}, - }) - -- vim.keymap.set('i', '', require("copilot.suggestion").accept_line(), {decsc='copilot accept'} ) - end, - }, - - { - 'olimorris/codecompanion.nvim', - cmd = { 'CodeCompanion', 'CodeCompanionChat', 'CodeCompanionAgent' }, - dependencies = { - 'nvim-lua/plenary.nvim', - 'nvim-treesitter/nvim-treesitter', - 'nvim-telescope/telescope.nvim', -- Optional - { - 'stevearc/dressing.nvim', -- Optional: Improves the default Neovim UI - opts = {}, - }, - }, - config = function() - require('codecompanion').setup({ - strategies = { - chat = { - adapter = 'copilot', - }, - inline = { - adapter = 'copilot', - }, - agent = { - adapter = 'copilot', - }, - }, - adapters = { - my_openai = function() - return require('codecompanion.adapters').extend( - 'openai_compatible', - { - env = { - url = 'http://127.0.0.1:11434', -- optional: default value is ollama url http://127.0.0.1:11434 - -- api_key = 'OpenAI_API_KEY', -- optional: if your endpoint is authenticated - -- chat_url = '/v1/chat/completions', -- optional: default value, override if different - -- models_endpoint = '/v1/models', -- optional: attaches to the end of the URL to form the endpoint to retrieve models - }, - schema = { - model = { - -- default = 'deepseek-r1:8b', - default = 'deepseek-r1:1.5b', - }, - temperature = { - order = 2, - mapping = 'parameters', - type = 'number', - optional = true, - default = 0.8, - desc = 'What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or top_p but not both.', - validate = function(n) - return n >= 0 and n <= 2, 'Must be between 0 and 2' - end, - }, - max_completion_tokens = { - order = 3, - mapping = 'parameters', - type = 'integer', - optional = true, - default = nil, - desc = 'An upper bound for the number of tokens that can be generated for a completion.', - validate = function(n) - return n > 0, 'Must be greater than 0' - end, - }, - stop = { - order = 4, - mapping = 'parameters', - type = 'string', - optional = true, - default = nil, - desc = 'Sets the stop sequences to use. When this pattern is encountered the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.', - validate = function(s) - return s:len() > 0, 'Cannot be an empty string' - end, - }, - logit_bias = { - order = 5, - mapping = 'parameters', - type = 'map', - optional = true, - default = nil, - desc = 'Modify the likelihood of specified tokens appearing in the completion. Maps tokens (specified by their token ID) to an associated bias value from -100 to 100. Use https://platform.openai.com/tokenizer to find token IDs.', - subtype_key = { - type = 'integer', - }, - subtype = { - type = 'integer', - validate = function(n) - return n >= -100 and n <= 100, - 'Must be between -100 and 100' - end, - }, - }, - }, - } - ) - end, - }, - }) - end, - }, - - { - 'ravitemer/mcphub.nvim', - -- Load only when Avante actually uses it (via require() calls in Avante config) - -- Since Avante is disabled, this won't load on startup - -- If Avante is enabled, mcphub will load lazily when Avante calls require('mcphub') - lazy = true, -- Don't load until explicitly required - dependencies = { - 'nvim-lua/plenary.nvim', - }, - build = 'npm install -g mcp-hub@latest', -- Installs `mcp-hub` node binary globally - config = function() require('mcphub').setup() end, - }, - - { - 'folke/sidekick.nvim', - -- require fzf lua and noice gui for best experience - cmd = { 'Sidekick' }, - dependencies = { - 'nvim-lua/plenary.nvim', - 'folke/noice.nvim', - 'ibhagwan/fzf-lua', - -- Sidekick uses `vim.ui.select` for things like model selection; dressing - -- restores the floating picker UI. - { - 'stevearc/dressing.nvim', - dependencies = { 'ibhagwan/fzf-lua' }, - opts = { - select = { - -- Force fzf-lua for a compact picker (match file picker sizing). - backend = { 'fzf_lua', 'builtin' }, - }, - }, - }, - }, - keys = { - { - '', - mode = 'i', - function() - if not require('sidekick').nes_jump_or_apply() then return '' end - end, - expr = true, - desc = 'Goto/Apply Next Edit Suggestion', - }, - { - 'aa', - function() require('sidekick.cli').toggle() end, - desc = 'Sidekick Toggle CLI', - }, - { - 'as', - function() require('sidekick.cli').select() end, - desc = 'Select CLI', - }, - { - 'at', - function() require('sidekick.cli').send({ msg = '{this}' }) end, - mode = { 'x', 'n' }, - desc = 'Send This', - }, - { - 'av', - function() require('sidekick.cli').send({ msg = '{selection}' }) end, - mode = { 'x' }, - desc = 'Send Visual Selection', - }, - { - 'ap', - function() require('sidekick.cli').prompt() end, - mode = { 'n', 'x' }, - desc = 'Sidekick Select Prompt', - }, - { - '', - function() require('sidekick.cli').focus() end, - mode = { 'n', 'x', 'i', 't' }, - desc = 'Sidekick Switch Focus', - }, - { - 'ac', - function() - require('sidekick.cli').toggle({ name = 'claude', focus = true }) - end, - desc = 'Sidekick Toggle Claude', - }, - }, - opts = { - cli = { - mux = { - enabled = true, - create = 'terminal', -- Folke's pattern: create terminal instead of window - backend = 'tmux', -- Using tmux (Folke commented out zellij) - }, - -- Add custom tools if needed (Folke has a debug tool) - tools = { - -- Example debug tool from Folke's config: - -- debug = { - -- cmd = { "bash", "-c", "env | sort | bat -l env" }, - -- }, - }, - }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/dadbod.lua b/files/.config/nvim/lua/custom/plugins/dadbod.lua deleted file mode 100644 index 8c9c871..0000000 --- a/files/.config/nvim/lua/custom/plugins/dadbod.lua +++ /dev/null @@ -1,23 +0,0 @@ -return { - { - 'kristijanhusak/vim-dadbod-ui', - dependencies = { - { 'tpope/vim-dadbod', lazy = true }, - { - 'kristijanhusak/vim-dadbod-completion', - ft = { 'sql', 'mysql', 'plsql', 'sqlite' }, - lazy = true, - }, - }, - cmd = { - 'DBUI', - 'DBUIToggle', - 'DBUIAddConnection', - 'DBUIFindBuffer', - }, - init = function() - -- Your DBUI configuration - vim.g.db_ui_use_nerd_fonts = 1 - end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/debug.lua b/files/.config/nvim/lua/custom/plugins/debug.lua deleted file mode 100644 index 0dfdcdc..0000000 --- a/files/.config/nvim/lua/custom/plugins/debug.lua +++ /dev/null @@ -1,108 +0,0 @@ -return { - { - 'mfussenegger/nvim-dap', - keys = { - { - '', - function() require('dap').continue() end, - desc = 'Debug: Start/Continue', - }, - { - '', - function() require('dap').step_into() end, - desc = 'Debug: Step Into', - }, - { - '', - function() require('dap').step_over() end, - desc = 'Debug: Step Over', - }, - { - '', - function() require('dap').step_out() end, - desc = 'Debug: Step Out', - }, - { - 'B', - function() require('dap').toggle_breakpoint() end, - desc = 'Debug: Toggle Breakpoint', - }, - { - '', - function() require('dapui').toggle() end, - desc = 'Debug: See last session result.', - }, - }, - dependencies = { - 'rcarriga/nvim-dap-ui', -- Creates a beautiful debugger UI - 'nvim-neotest/nvim-nio', -- Required dependency for nvim-dap-ui - 'williamboman/mason.nvim', -- Installs the debug adapters for you - 'jay-babu/mason-nvim-dap.nvim', - 'leoluz/nvim-dap-go', -- Add your own debuggers here - }, - config = function() - local dap = require('dap') - local dapui = require('dapui') - - require('mason-nvim-dap').setup({ - -- Makes a best effort to setup the various debuggers with - -- reasonable debug configurations - automatic_setup = true, - - -- You can provide additional configuration to the handlers, - -- see mason-nvim-dap README for more information - handlers = {}, - - -- You'll need to check that you have the required things installed - -- online, please don't ask me how to install them :) - ensure_installed = { - -- Update this to ensure that you have the debuggers for the langs you want - 'delve', - 'debugpy', - }, - }) - - -- Dap UI setup - -- For more information, see |:help nvim-dap-ui| - dapui.setup({ - -- Set icons to characters that are more likely to work in every terminal. - -- Feel free to remove or use ones that you like more! :) - -- Don't feel like these are good choices. - icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, - controls = { - icons = { - pause = '', - play = '', - step_into = '󱆭', - step_over = '', - step_out = '󰙣', - step_back = '󱆮', - run_last = '󰙡', - terminate = '', - disconnect = '', - }, - }, - }) - - 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 - - -- Install golang specific config - require('dap-go').setup() - end, - }, - { - 'rest-nvim/rest.nvim', - disable = true, - cond = false, - cmd = { 'Rest' }, - dependencies = { - 'nvim-treesitter/nvim-treesitter', - opts = function(_, opts) - opts.ensure_installed = opts.ensure_installed or {} - table.insert(opts.ensure_installed, 'http') - end, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/filetype.lua b/files/.config/nvim/lua/custom/plugins/filetype.lua deleted file mode 100644 index 39881f2..0000000 --- a/files/.config/nvim/lua/custom/plugins/filetype.lua +++ /dev/null @@ -1,212 +0,0 @@ -return { - - -- markdown support - { - 'plasticboy/vim-markdown', - disable = false, - ft = { 'markdown', 'rst' }, - }, - - { '3rd/image.nvim', ft = { 'markdown', 'neorg', 'org' }, opts = {} }, - - -- syntax highlighting for log files - { - 'mtdl9/vim-log-highlighting', - disable = false, - ft = 'log', - }, - - { - 'raivivek/vim-snakemake', - ft = 'snakemake', - }, - - -- syntax highlighting for kitty conf file - { - 'fladson/vim-kitty', - disable = false, - ft = 'conf', - }, - - -- sets searchable path for filetypes like go so 'gf' works - { - 'tpope/vim-apathy', - disable = false, - ft = { 'go', 'python', 'javascript', 'typescript' }, - }, - - { - 'saecki/crates.nvim', - event = { 'BufRead Cargo.toml' }, - requires = { { 'nvim-lua/plenary.nvim' } }, - config = function() require('crates').setup() end, - }, - - { - 'lbrayner/vim-rzip', - disable = false, - ft = { 'zip', 'docx', 'xlsx', 'pptx' }, - config = function() - vim.cmd([[ - " let g:rzipPlugin_extra_ext = '*.docx' - ]]) - end, - }, - - -- { - -- 'tpope/vim-surround', - -- event = 'InsertEnter', - -- }, - - -- { - -- 'chrisbra/csv.vim', - -- ft = 'csv', - -- }, - - { - 'hat0uma/csvview.nvim', - ft = 'csv', - opts = { - parser = { comments = { '#', '//' } }, - keymaps = { - -- Text objects for selecting fields - textobject_field_inner = { 'if', mode = { 'o', 'x' } }, - textobject_field_outer = { 'af', mode = { 'o', 'x' } }, - -- Excel-like navigation: - -- Use and to move horizontally between fields. - -- Use and to move vertically between rows and place the cursor at the end of the field. - -- Note: In terminals, you may need to enable CSI-u mode to use and . - jump_next_field_end = { '', mode = { 'n', 'v' } }, - jump_prev_field_end = { '', mode = { 'n', 'v' } }, - jump_next_row = { '', mode = { 'n', 'v' } }, - jump_prev_row = { '', mode = { 'n', 'v' } }, - }, - }, - cmd = { 'CsvViewEnable', 'CsvViewDisable', 'CsvViewToggle' }, - }, - - { - 'lifepillar/pgsql.vim', - lazy = true, - disable = true, - cond = false, - }, - { - 'ledger/vim-ledger', - ft = 'ledger', - config = function() - vim.cmd([[ - " For ledger - au BufNewFile,BufRead *.ldg,*.ledger setf ledger | comp ledger - let g:ledger_maxwidth = 120 - let g:ledger_fold_blanks = 1 - function LedgerSort() - :%! ledger -f - print --sort 'date, amount' - :%LedgerAlign - endfunction - command LedgerSort call LedgerSort() - ]]) - end, - }, - - { - 'Kicamon/markdown-table-mode.nvim', - ft = { 'markdown', 'neorg', 'org' }, - config = function() - require('markdown-table-mode').setup({ - filetype = { - '*.md', - }, - options = { - insert = true, -- when typing "|" - insert_leave = true, -- when leaving insert - pad_separator_line = false, -- add space in separator line - alig_style = 'default', -- default, left, center, right - }, - }) - end, - }, - - { - 'marromlam/nvim-docx.nvim', - name = 'nvim-docx', - dir = '~/Workspaces/personal/nvim-docx', - -- disable = true, - -- cond = false, - dev = true, - lazy = false, - keys = { - '', - -- 'X', - ':ReloadXMLFromZip', - desc = 'Reload MS Word', - }, - }, - - ------------------------------------------------------------------------ - --- LaTeX {{{ - ------------------------------------------------------------------------ - - { - -- vimtex - 'lervag/vimtex', - -- cond = false, - -- disable = true, - ft = { 'tex' }, - config = function() require('custom.config.vimtex').config() end, - }, - - { - 'marromlam/tex-kitty', - ft = 'tex', - dir = '/Users/marcos/Projects/personal/pdfcat.nvim/', - dev = true, - -- cond = false, - -- disable = true, - dependencies = { 'lervag/vimtex' }, - config = function() - require('tex-kitty').setup({ - tex_kitty_preview = 1, - }) - end, - }, - - { - 'marromlam/livetex.nvim', - ft = 'tex', - dir = '/Users/marcos/Projects/personal/livetex.nvim', - dev = true, - cond = false, - disable = true, - -- dependencies = { 'lervag/vimtex' }, - config = function() - require('livetex').setup({ - engine = 'auto', -- TS-program magic selects pdflatex/xelatex/lualatex - ramdisk_enabled = true, - ramdisk_volume_name = 'LiveTeXRAM', - ramdisk_size_mb = 1024, - ramdisk_auto_out_dir = true, - -- fmt = 'fastfmt.fmt', -- path to your precompiled preamble - -- fmt = '/Users/marcos/tmp/livetex/fastfmt.fmt', - -- out_dir = '/dev/shm/livetex', -- RAM disk for fast output - -- out_dir = '/Users/marcos/tmp/livetex', -- or any writable path - -- fmt = '/Volumes/LiveTeXRAM/livetex/fastfmt.fmt', - -- out_dir = '/Volumes/LiveTeXRAM/livetex', - live = true, - reload_cmd = false, -- auto reload PDF - -- reload_cmd = 'osascript -e \'tell application "Skim" to revert front document\'', -- auto reload PDF - debounce_ms = 300, - live_interaction = 'batchmode', - show_spinner = true, - -- pdf_target = 'same', -- (default) copy next to .tex - copy_pdf_on_live = true, -- copy PDF on each live compilation (even if pdf_target is "same") - pdf_target = 'symlink', - copy_on_save = true, - synctex = 1, - }) - end, - }, - - -- }}} - ------------------------------------------------------------------------ -} diff --git a/files/.config/nvim/lua/custom/plugins/folke.lua b/files/.config/nvim/lua/custom/plugins/folke.lua deleted file mode 100644 index a564707..0000000 --- a/files/.config/nvim/lua/custom/plugins/folke.lua +++ /dev/null @@ -1 +0,0 @@ -return {} diff --git a/files/.config/nvim/lua/custom/plugins/format.lua b/files/.config/nvim/lua/custom/plugins/format.lua deleted file mode 100644 index 8d8a1a9..0000000 --- a/files/.config/nvim/lua/custom/plugins/format.lua +++ /dev/null @@ -1,112 +0,0 @@ -return { - { - 'stevearc/conform.nvim', - -- lazy = false, - event = { 'BufReadPre', 'BufNewFile' }, - cmd = { 'ConformInfo' }, - keys = { - { - 'lf', - function() - require('conform').format({ async = true, lsp_format = 'fallback' }) - end, - mode = '', - desc = '[F]ormat buffer', - }, - }, - config = function() - local conform = require('conform') - conform.setup({ - notify_on_error = true, - format_on_save = function(bufnr) - -- Disable LSP fallback for languages that don't - -- have a well standardized coding style. You can add additional - -- languages here or re-enable it for the disabled ones. - if vim.g.disable_autoformat or vim.g.formatting_disabled then - return nil - end - if vim.b[bufnr] and vim.b[bufnr].formatting_disabled then - return nil - end - local disable_filetypes = - { c = true, cpp = true, xml = true, cnk = true, map = true } - return { - timeout_ms = 5000, - lsp_format = disable_filetypes[vim.bo[bufnr].filetype] and 'never' - or 'fallback', - } - end, - formatters_by_ft = { - bash = { 'shfmt' }, - javascript = { 'prettier' }, - typescript = { 'prettier' }, - javascriptreact = { 'prettier' }, - typescriptreact = { 'prettier' }, - svelte = { 'prettier' }, - css = { 'prettierd' }, - html = { 'prettier' }, - json = { 'prettier' }, - yaml = { 'prettier' }, - markdown = { 'prettier' }, - graphql = { 'prettier' }, - liquid = { 'prettier' }, - lua = { 'stylua' }, - python = { 'isort', 'black' }, - xml = { 'xmlformat' }, - }, - -- Set default options - default_format_opts = { - lsp_format = 'fallback', - }, - -- Set up format-on-save - -- format_on_save = { timeout_ms = 500 }, - -- Customize formatters - formatters = { - shfmt = { - prepend_args = { '-i', '2' }, - }, - -- Only run prettier if config file exists - prettier = {}, - prettierd = {}, - -- Only run isort if config file exists - isort = {}, - -- Only run stylua if config file exists - stylua = {}, - }, - }) - - vim.api.nvim_create_user_command('Format', function(args) - local range = nil - if args.count ~= -1 then - local end_line = - vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1] - range = { - start = { args.line1, 0 }, - ['end'] = { args.line2, end_line:len() }, - } - end - conform.format({ - async = true, - lsp_format = 'fallback', - range = range, - }) - end, { range = true }) - - vim.api.nvim_create_user_command( - 'FormatDisable', - function(args) vim.g.disable_autoformat = true end, - { - desc = 'Disable autoformat-on-save', - } - ) - - vim.api.nvim_create_user_command( - 'FormatEnable', - function() vim.g.disable_autoformat = false end, - { - desc = 'Re-enable autoformat-on-save', - } - ) - end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/fzf.lua b/files/.config/nvim/lua/custom/plugins/fzf.lua deleted file mode 100644 index 6264352..0000000 --- a/files/.config/nvim/lua/custom/plugins/fzf.lua +++ /dev/null @@ -1,316 +0,0 @@ -local UI = require('tools').ui -local icons = UI.icons or {} -local lsp_hls = (UI.lsp and UI.lsp.highlights) or {} - -local function has_exec(bin) return vim.fn.executable(bin) == 1 end - -local function trim(s) return (s:gsub('^%s+', ''):gsub('%s+$', '')) end - -local function toggle_cli_flag(args, flag) - args.cmd = args.cmd or '' - local escaped = vim.pesc(flag) - local pattern = '(%s*)' .. escaped .. '(%s*)' - if args.cmd:find(escaped) then - args.cmd = args.cmd:gsub(pattern, ' ', 1) - else - args.cmd = trim(args.cmd .. ' ' .. flag) - end -end - -local function restart_files(args) - local ok, fzf = pcall(require, 'fzf-lua') - if ok then fzf.files(args) end -end - -local function open_files_in_cwd(cwd, label) - local dir = type(cwd) == 'string' and cwd or '' - if dir ~= '' and vim.fn.isdirectory(dir) == 1 then - require('fzf-lua').files({ cwd = dir }) - return - end - - local where = label and (' for ' .. label) or '' - vim.notify( - 'Invalid directory' .. where .. ': ' .. tostring(dir), - vim.log.levels.WARN - ) - require('fzf-lua').files() -end - -local function current_buffer_dir() - local name = vim.api.nvim_buf_get_name(0) - if name == '' then return vim.loop.cwd() end - local dir = vim.fn.fnamemodify(name, ':p:h') - if dir == '' then return vim.loop.cwd() end - return dir -end - -return { - { - 'ibhagwan/fzf-lua', - cmd = 'FzfLua', - opts = function() - local ok_lspkind, lspkind = pcall(require, 'lspkind') - local lsp_symbols = ok_lspkind and lspkind.symbols or {} - local has_bat = has_exec('bat') or has_exec('batcat') - local has_delta = has_exec('delta') - return { - winopts = { - split = 'botright new', -- Full-width horizontal split at bottom - -- Alternative: 'topleft new' for full-width at top - preview = { - default = has_bat and 'bat' or 'builtin', - scrollbar = 'float', - }, - }, - -- Native integration for vim.ui.select (replaces custom wrapper). - - ui_select = { - winopts = { - split = 'botright new', - height = 0.35, - preview = { hidden = true }, - }, - fzf_opts = { - ['--info'] = 'default', - }, - }, - fzf_opts = { - ['--info'] = 'default', - }, - files = { - hidden = false, - no_ignore = false, - follow = false, - -- --hidden lets rg/fd see dotfiles; .gitignore still filters untracked ones, - -- so git-tracked hidden files are listed while junk (caches, etc.) stays out. - rg_opts = [[--color=never --files --hidden -g "!.git"]], - fd_opts = [[--color=never --type f --type l --hidden --exclude .git]], - }, - grep = { - rg_opts = '--column --line-number --no-heading --color=always --smart-case --max-columns=4096 --hidden -e', - }, - keymap = { - builtin = { - [''] = 'toggle-preview', - [''] = 'preview-page-down', - [''] = 'preview-page-up', - [''] = { - function(_, args) - toggle_cli_flag(args, '--hidden') - restart_files(args) - end, - }, - [''] = { - function(_, args) - toggle_cli_flag(args, '--no-ignore') - restart_files(args) - end, - }, - }, - fzf = { - ['esc'] = 'abort', - ['ctrl-q'] = 'select-all+accept', - }, - }, - lsp = { - symbols = { - symbol_style = 1, - symbol_icons = lsp_symbols, - symbol_hl = function(s) return lsp_hls[s] end, - }, - }, - git = { - status = { - preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' - or nil, - }, - bcommits = { - preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' - or nil, - }, - commits = { - preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' - or nil, - }, - icons = { - ['M'] = { - icon = (icons.git and icons.git.mod) or 'M', - color = 'yellow', - }, - ['D'] = { - icon = (icons.git and icons.git.remove) or 'D', - color = 'red', - }, - ['A'] = { - icon = (icons.git and icons.git.staged) or 'A', - color = 'green', - }, - ['R'] = { - icon = (icons.git and icons.git.rename) or 'R', - color = 'yellow', - }, - ['C'] = { - icon = (icons.git and icons.git.conflict) or 'C', - color = 'yellow', - }, - ['T'] = { - icon = (icons.git and icons.git.mod) or 'T', - color = 'magenta', - }, - ['?'] = { - icon = (icons.git and icons.git.untracked) or '?', - color = 'magenta', - }, - }, - }, - } - end, - config = function(_, opts) - require('fzf-lua').setup(opts) - - -- Restore full custom statusline for fzf windows - -- fzf-lua has no native config to disable its statusline - vim.api.nvim_create_autocmd({ 'FileType', 'BufWinEnter' }, { - group = vim.api.nvim_create_augroup( - 'FzfLuaStatusline', - { clear = true } - ), - pattern = 'fzf', - callback = function() - -- Use defer_fn to run after fzf-lua sets its statusline - vim.defer_fn(function() - if vim.bo.filetype == 'fzf' then - if - type(_G.Stl) == 'table' and type(_G.Stl.render) == 'function' - then - vim.opt_local.statusline = '%{%v:lua.Stl.render()%}' - end - end - end, 0) - end, - }) - end, - keys = { - { '', 'FzfLua git_files', desc = 'fzf: [f]ind [f]iles' }, - { - 'fa', - 'FzfLua', - desc = 'fzf: [f]ind [a]ll builtins', - }, - { - 'ff', - function() - -- In a git repo: use git ls-files so tracked hidden files appear. - -- Outside a git repo: fall back to regular files picker. - local ok = vim.fn.systemlist( - 'git rev-parse --is-inside-work-tree 2>/dev/null' - )[1] - if ok == 'true' then - require('fzf-lua').git_files({ show_untracked = true }) - else - require('fzf-lua').files() - end - end, - desc = 'fzf: [f]ind [f]iles', - }, - { - 'fb', - 'FzfLua grep_curbuf', - desc = 'fzf: [f]ind in current [b]uffer', - }, - { 'fr', 'FzfLua resume', desc = 'fzf: [f]ind [r]esume' }, - { - 'fva', - 'FzfLua autocmds', - desc = 'fzf: fin [a]utocommands', - }, - { - 'fvh', - 'FzfLua highlights', - desc = 'fzf: find Highlights', - }, - { - 'fvk', - 'FzfLua keymaps', - desc = 'fzf: find Keymaps', - }, - { - 'fle', - 'FzfLua diagnostics_workspace', - desc = 'fzf: Lsp workspace Diagnostics', - }, - { - 'fld', - 'FzfLua lsp_document_symbols', - desc = 'fzf: Lsp document Symbols', - }, - { - 'fls', - 'FzfLua lsp_live_workspace_symbols', - desc = 'fzf: workspace symbols', - }, - { 'f?', 'FzfLua help_tags', desc = 'fzf: find ?help' }, - { - 'fh', - 'FzfLua oldfiles', - desc = 'fzf: Most (f)recently used files', - }, - { - 'fgb', - 'FzfLua git_branches', - desc = 'fzf: [g]it [b]ranches', - }, - { - 'fgs', - 'FzfLua git_status', - desc = 'fzf: [g]it [s]tatus', - }, - { - 'fgc', - 'FzfLua git_commits', - desc = 'fzf: [g]it [c]ommits', - }, - { - 'fgB', - 'FzfLua git_bcommits', - desc = 'fzf: [b]uffer commits', - }, - { - 'fo', - 'FzfLua buffers', - desc = 'fzf: find [o]pen buffers', - }, - { - 'fs', - 'FzfLua live_grep', - desc = 'fzf: [f] with live[g]rep', - }, - { - 'p', - 'FzfLua registers', - desc = 'fzf: [f]ind registers', - }, - { - 'fd', - function() open_files_in_cwd(vim.g.dotfiles, 'dotfiles') end, - desc = 'fzf: [f]ind [d]otfiles', - }, - { - 'fp', - function() open_files_in_cwd(vim.g.projects_directory, 'projects') end, - desc = 'fzf: [f]ind in [p]rojects', - }, - { - 'f.', - function() open_files_in_cwd(current_buffer_dir(), 'current buffer') end, - desc = 'fzf: find in current file dir', - }, - { - 'fc', - function() open_files_in_cwd(vim.g.vim_dir, 'nvim config') end, - desc = 'fzf: [f]ind nvim [c]onfig', - }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/gaming.lua b/files/.config/nvim/lua/custom/plugins/gaming.lua deleted file mode 100644 index 6c4fa7a..0000000 --- a/files/.config/nvim/lua/custom/plugins/gaming.lua +++ /dev/null @@ -1,4 +0,0 @@ -return { - - { 'meznaric/key-analyzer.nvim', opts = {}, cmd = 'KeyAnalyzer' }, -} diff --git a/files/.config/nvim/lua/custom/plugins/git.lua b/files/.config/nvim/lua/custom/plugins/git.lua deleted file mode 100644 index c148725..0000000 --- a/files/.config/nvim/lua/custom/plugins/git.lua +++ /dev/null @@ -1,535 +0,0 @@ -local T = require('tools') -local icons = require('tools').ui.icons.separators - -local gitlinker = T.require_for_later_index('gitlinker') -local function browser_open() - return { action_callback = require('gitlinker.actions').open_in_browser } -end - -return { - ----------------------------------------------------------------------------- - -- git signs {{{ - ----------------------------------------------------------------------------- - { - 'lewis6991/gitsigns.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - opts = { - -- signcolumn = false, -- Disable icons in sign column - signs = { - add = { text = icons.right_block }, - change = { text = icons.right_block }, - delete = { text = icons.right_block }, - topdelete = { text = icons.right_block }, - changedelete = { text = icons.right_block }, - untracked = { text = icons.light_shade_block }, - }, - on_attach = function(bufnr) - local gitsigns = require('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', ']c', function() - if vim.wo.diff then - vim.cmd.normal({ ']c', bang = true }) - else - gitsigns.nav_hunk('next') - end - end, { desc = 'Jump to next git [c]hange' }) - - map('n', '[c', function() - if vim.wo.diff then - vim.cmd.normal({ '[c', bang = true }) - else - gitsigns.nav_hunk('prev') - end - end, { desc = 'Jump to previous git [c]hange' }) - - -- Actions - -- visual mode - map( - 'v', - 'hs', - function() gitsigns.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, - { desc = 'stage git hunk' } - ) - map( - 'v', - 'hr', - function() gitsigns.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, - { desc = 'reset git hunk' } - ) - -- normal mode - map( - 'n', - 'hs', - gitsigns.stage_hunk, - { desc = 'git [s]tage hunk' } - ) - map( - 'n', - 'hr', - gitsigns.reset_hunk, - { desc = 'git [r]eset hunk' } - ) - map( - 'n', - 'hS', - gitsigns.stage_buffer, - { desc = 'git [S]tage buffer' } - ) - map( - 'n', - 'hu', - gitsigns.undo_stage_hunk, - { desc = 'git [u]ndo stage hunk' } - ) - map( - 'n', - 'hR', - gitsigns.reset_buffer, - { desc = 'git [R]eset buffer' } - ) - map( - 'n', - 'hp', - gitsigns.preview_hunk, - { desc = 'git [p]review hunk' } - ) - map( - 'n', - 'hb', - gitsigns.blame_line, - { desc = 'git [b]lame line' } - ) - map( - 'n', - 'hd', - gitsigns.diffthis, - { desc = 'git [d]iff against index' } - ) - map( - 'n', - 'hD', - function() gitsigns.diffthis('@') end, - { desc = 'git [D]iff against last commit' } - ) - -- Toggles - map( - 'n', - 'tb', - gitsigns.toggle_current_line_blame, - { desc = '[T]oggle git show [b]lame line' } - ) - map( - 'n', - 'tD', - gitsigns.toggle_deleted, - { desc = '[T]oggle git show [D]eleted' } - ) - end, - }, - }, - - { - 'ruifm/gitlinker.nvim', - dependencies = { 'nvim-lua/plenary.nvim' }, - keys = { - { - 'gu', - function() gitlinker.get_buf_range_url('n') end, - desc = 'gitlinker: copy line to clipboard', - mode = 'n', - silent = true, - }, - { - 'gu', - function() gitlinker.get_buf_range_url('v') end, - desc = 'gitlinker: copy range to clipboard', - mode = 'v', - silent = true, - }, - { - 'go', - function() gitlinker.get_repo_url(browser_open()) end, - desc = 'gitlinker: open in browser', - silent = true, - }, - { - 'go', - function() gitlinker.get_buf_range_url('n', browser_open()) end, - desc = 'gitlinker: open current line in browser', - silent = true, - }, - { - 'go', - function() gitlinker.get_buf_range_url('v', browser_open()) end, - desc = 'gitlinker: open current selection in browser', - mode = 'v', - silent = true, - }, - }, - opts = { - mappings = nil, - callbacks = { - ['github-work.com'] = function(url_data) -- Resolve the host for work repositories - url_data.host = 'github.com' - return require('gitlinker.hosts').get_github_type_url(url_data) - end, - -- callbacks = { - -- ["github.com"] = function(url_data) - -- local url = require"gitlinker.hosts".get_base_https_url(url_data) .. - -- url_data.repo .. "/blob/" .. url_data.rev .. "/" .. url_data.file - -- if url_data.lstart then - -- url = url .. "#L" .. url_data.lstart - -- if url_data.lend then url = url .. "-L" .. url_data.lend end - -- end - -- return url - -- end - -- } - }, - }, - }, - -- }}} - ----------------------------------------------------------------------------- - ----------------------------------------------------------------------------- - -- git-conflict {{{ - ----------------------------------------------------------------------------- - { - 'akinsho/git-conflict.nvim', - event = 'BufReadPre', - opts = { - default_mappings = true, - default_commands = true, - disable_diagnostics = true, - list_opener = 'copen', - highlights = { - incoming = 'DiffAdd', - current = 'DiffText', - }, - }, - }, - -- }}} - ----------------------------------------------------------------------------- - ----------------------------------------------------------------------------- - -- fugitive {{{ - ----------------------------------------------------------------------------- - { - 'tpope/vim-fugitive', - cmd = { 'Git' }, - event = 'BufReadPre', - init = function() - vim.api.nvim_create_autocmd('DirChanged', { - group = vim.api.nvim_create_augroup('FugitiveWorktreeDetect', { clear = true }), - callback = function() - vim.fn.FugitiveDetect(vim.fn.getcwd()) - end, - }) - end, - keys = { - { - 'gs', - function() - -- FugitiveCommonDir returns the shared .bare dir for all worktrees of the same repo - local cur_common = vim.fn.FugitiveCommonDir(vim.api.nvim_get_current_buf()) - if cur_common == '' then - vim.cmd('tab Git') - return - end - for _, tabnr in ipairs(vim.api.nvim_list_tabpages()) do - for _, winnr in ipairs(vim.api.nvim_tabpage_list_wins(tabnr)) do - local buf = vim.api.nvim_win_get_buf(winnr) - local name = vim.api.nvim_buf_get_name(buf) - if name:match('^fugitive://') then - local tab_common = vim.fn.FugitiveCommonDir(buf) - if tab_common ~= '' and tab_common == cur_common then - vim.api.nvim_set_current_tabpage(tabnr) - return - end - end - end - end - vim.cmd('tab Git') - end, - desc = '[git] Status', - mode = 'n', - }, - { - 'g-', - "lua require 'gitsigns'.blame_line()", - desc = '[git] Blame', - }, - { 'gB', 'Git blame', desc = 'Git Blame' }, - { - 'gb', - 'FzfLua git_branches', - desc = '[git] Checkout branch', - }, - { - 'gc', - 'FzfLua git_commits', - desc = '[git] Checkout commit', - }, - { - 'gC', - 'FzfLua git_bcommits', - desc = '[git] Checkout commit(for current file)', - }, - { - 'gf', - 'Git fall', - desc = '[git] Git fetch all branches', - }, - { - 'gh', - 'diffget //2', - desc = '[git] Get diff from left', - }, - { - 'gH', - '0Gclog', - desc = '[git] Get history for current file', - }, - { - 'gl', - 'diffget //3', - desc = '[git] Get diff from right', - }, - { - 'gj', - "lua require 'gitsigns'.next_hunk()", - desc = '[git] Next Hunk', - }, - { - 'gk', - "lua require 'gitsigns'.prev_hunk()", - desc = '[git] Prev Hunk', - }, - { - 'gP', - 'Git push', - desc = '[git] Git push commited changes', - }, - { - 'gp', - 'Git pull --rebase', - desc = '[git] Git pull and rebase', - }, - { - 'gt', - ':Git push -u origin ', - desc = '[git] set target branch ', - }, - }, - }, - -- }}} - ----------------------------------------------------------------------------- - - -- Other fancy plugins {{{ - -- - - { - 'sindrets/diffview.nvim', - cmd = { 'DiffviewOpen', 'DiffviewClose', 'DiffviewToggleFiles' }, - opts = { - enhanced_diff_hl = true, - signs = { - fold_closed = '', - fold_open = '', - done = '✓', - }, - view = { - merge_tool = { layout = 'diff3_mixed' }, - }, - }, - }, - { - 'isakbm/gitgraph.nvim', - dependencies = { 'sindrets/diffview.nvim' }, - opts = { - symbols = { - merge_commit = 'M', - commit = '*', - }, - format = { - timestamp = '%H:%M:%S %d-%m-%Y', - fields = { 'hash', 'timestamp', 'author', 'branch_name', 'tag' }, - }, - - hooks = { - -- Check diff of a commit - on_select_commit = function(commit) - vim.notify('DiffviewOpen ' .. commit.hash .. '^!') - vim.cmd(':DiffviewOpen ' .. commit.hash .. '^!') - end, - -- Check diff from commit a -> commit b - on_select_range_commit = function(from, to) - vim.notify('DiffviewOpen ' .. from.hash .. '~1..' .. to.hash) - vim.cmd(':DiffviewOpen ' .. from.hash .. '~1..' .. to.hash) - end, - }, - }, - keys = { - { - 'gG', - function() - require('gitgraph').draw({}, { all = true, max_count = 5000 }) - end, - desc = 'GitGraph', - }, - }, - }, - - { - 'ldelossa/gh.nvim', - lazy = false, - cond = false, - disabled = true, - dependencies = { - { - 'ldelossa/litee.nvim', - config = function() require('litee.lib').setup() end, - }, - }, - config = function() require('litee.gh').setup() end, - }, - - -- }}} - - { - -- 'marromlam/git-worktree.nvim', - 'ThePrimeagen/git-worktree.nvim', - -- dev = true, - -- dir = '~/Workspaces/personal/git-worktree.nvim', - - dependencies = { 'nvim-lua/plenary.nvim' }, - cmd = { - 'GitWorktreeCreate', - 'GitWorktreeDelete', - 'GitWorktreeList', - 'GitWorktreeSwitch', - }, - keys = { - { - 'gwl', - function() - require('fzf-lua').fzf_exec(function(cb) - local lines = vim.fn.systemlist('git worktree list --porcelain') - local worktrees = {} - local cur = {} - for _, line in ipairs(lines) do - local path = line:match('^worktree (.+)') - local branch = line:match('^branch refs/heads/(.+)') - if path then cur = { path = path } end - if branch then cur.branch = branch end - if line == '' and cur.path then - table.insert(worktrees, cur) - cur = {} - end - end - if cur.path then table.insert(worktrees, cur) end - for _, wt_entry in ipairs(worktrees) do - cb(string.format('%s\t%s', wt_entry.branch or '(detached)', wt_entry.path)) - end - cb(nil) - end, { - prompt = 'Worktrees> ', - actions = { - ['default'] = function(selected) - local path = selected[1]:match('\t(.+)$') - if path then - require('git-worktree').switch_worktree(path) - end - end, - }, - }) - end, - desc = '[git] List/switch worktree', - }, - { - 'gwd', - function() - require('fzf-lua').fzf_exec(function(cb) - local lines = vim.fn.systemlist('git worktree list --porcelain') - local worktrees = {} - local cur = {} - for _, line in ipairs(lines) do - local path = line:match('^worktree (.+)') - local branch = line:match('^branch refs/heads/(.+)') - if path then cur = { path = path } end - if branch then cur.branch = branch end - if line == '' and cur.path then - table.insert(worktrees, cur) - cur = {} - end - end - if cur.path then table.insert(worktrees, cur) end - -- skip the main worktree (first entry) - for i, wt_entry in ipairs(worktrees) do - if i > 1 then - cb(string.format('%s\t%s', wt_entry.branch or '(detached)', wt_entry.path)) - end - end - cb(nil) - end, { - prompt = 'Delete worktree> ', - fzf_opts = { ['--header'] = 'CTRL-D: force delete branch | ENTER: remove worktree only' }, - actions = { - ['default'] = function(selected) - local path = selected[1]:match('\t(.+)$') - if not path then return end - vim.ui.input( - { prompt = 'Flags ([-f] [-d|-D], or enter to confirm): ' }, - function(flags) - if flags == nil then return end -- cancelled - local cmd = 'gwrm ' .. (flags ~= '' and flags .. ' ' or '') .. vim.fn.shellescape(path) - local out = vim.fn.system(cmd) - if vim.v.shell_error ~= 0 then - vim.notify(out, vim.log.levels.ERROR) - else - vim.notify('Removed worktree: ' .. path) - end - end - ) - end, - }, - }) - end, - desc = '[git] Delete worktree', - }, - { - 'gwc', - function() - vim.ui.input({ prompt = 'New branch name: ' }, function(branch) - if not branch or branch == '' then return end - vim.ui.input( - { prompt = 'Path (default: ' .. branch .. '): ' }, - function(path) - path = (path and path ~= '') and path or branch - vim.ui.input({ prompt = 'Base branch (default: HEAD): ' }, function(base) - base = (base and base ~= '') and base or 'HEAD' - require('git-worktree').create_worktree(path, branch, base) - end) - end - ) - end) - end, - desc = '[git] Create worktree', - }, - }, - config = function() - require('git-worktree').setup() - require('git-worktree').on_tree_change(function(op, metadata) - if op == require('git-worktree').Operations.Switch then - vim.fn.FugitiveDetect(metadata.path) - end - end) - end, - }, -} - --- vim: fdm=marker diff --git a/files/.config/nvim/lua/custom/plugins/init.lua b/files/.config/nvim/lua/custom/plugins/init.lua deleted file mode 100644 index 40b1312..0000000 --- a/files/.config/nvim/lua/custom/plugins/init.lua +++ /dev/null @@ -1,74 +0,0 @@ -return { - { - 'nvim-lua/plenary.nvim', - }, - { - 'jghauser/fold-cycle.nvim', - opts = {}, - keys = { - { - '', - function() require('fold-cycle').open() end, - desc = 'fold-cycle: toggle', - }, - }, - }, - { - - 'andrewferrier/debugprint.nvim', - opts = { keymaps = false }, - dependencies = { - 'echasnovski/mini.hipatterns', - 'ibhagwan/fzf-lua', - }, - version = '*', - keys = { - { - 'dp', - function() return require('debugprint').debugprint({ variable = true }) end, - desc = 'debugprint: cursor', - expr = true, - }, - { - 'do', - function() return require('debugprint').debugprint({ motion = true }) end, - desc = 'debugprint: operator', - expr = true, - }, - { - 'dC', - 'DeleteDebugPrints', - desc = 'debugprint: clear all', - }, - }, - }, - - { - 'marromlam/sailor.vim', - event = 'VimEnter', - run = './install.sh', - }, - - { - 'bogado/file-line', - keys = { - 'gF', - }, - }, - - { - 'will133/vim-dirdiff', - cmd = { 'DirDiff' }, - }, - - { - 'tpope/vim-sleuth', - event = { 'BufReadPre', 'BufNewFile' }, - }, - { 'tpope/vim-surround', event = { 'BufReadPre', 'BufNewFile' } }, - - { - 'tpope/vim-repeat', - keys = { '.' }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/lsp.lua b/files/.config/nvim/lua/custom/plugins/lsp.lua deleted file mode 100644 index 570d02f..0000000 --- a/files/.config/nvim/lua/custom/plugins/lsp.lua +++ /dev/null @@ -1,586 +0,0 @@ -return { -- LSP Configuration & Plugins - { - 'neovim/nvim-lspconfig', - event = { 'BufReadPre' }, - dependencies = { - -- Automatically install LSPs and related tools to stdpath for Neovim - { - 'mason-org/mason.nvim', - opts = { - ui = { - border = 'rounded', - width = 0.8, - height = 0.8, - backdrop = 100, -- 100 = fully transparent (no dimming), 0 = fully opaque - }, - }, - config = function(_, opts) require('mason').setup(opts) end, - }, - { 'mason-org/mason-lspconfig.nvim', opts = {} }, - { 'WhoIsSethDaniel/mason-tool-installer.nvim', opts = {} }, - - -- Useful status updates for LSP. - -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})` - { 'j-hui/fidget.nvim', opts = {} }, - { - 'folke/lazydev.nvim', - ft = 'lua', - opts = { - library = { - { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, - { path = 'wezterm-types', mods = { 'wezterm' } }, - }, - enabled = function(root_dir) - return (vim.g.lazydev_enabled == nil or vim.g.lazydev_enabled) - and not vim.uv.fs_stat(root_dir .. '/.luarc.json') - end, - }, - }, - { - 'stevanmilic/nvim-lspimport', - }, - }, - config = function() - -- Floating UI (hover/signature/diagnostics) border styling - -- Some plugins/LSP helpers call `vim.lsp.util.open_floating_preview` directly, - -- so enforce a default border there too. - do - local orig = vim.lsp.util.open_floating_preview - ---@diagnostic disable-next-line: duplicate-set-field - function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) - opts = opts or {} - opts.border = opts.border or 'rounded' - -- Disable all columns in LSP floating windows - local bufnr, winnr = orig(contents, syntax, opts, ...) - if winnr and vim.api.nvim_win_is_valid(winnr) then - vim.wo[winnr].statuscolumn = '' - vim.wo[winnr].signcolumn = 'no' - vim.wo[winnr].foldcolumn = '0' - vim.wo[winnr].number = false - vim.wo[winnr].relativenumber = false - end - return bufnr, winnr - end - end - - -- Prefer wrapping the existing handlers instead of `vim.lsp.with(...)` - -- (some setups/tools flag `vim.lsp.with` / `vim.lsp.handlers.hover` as deprecated). - local function with_border(handler) - return function(err, result, ctx, config) - config = config or {} - config.border = config.border or 'rounded' - return handler(err, result, ctx, config) - end - end - - vim.lsp.handlers['textDocument/hover'] = - with_border(vim.lsp.handlers['textDocument/hover']) - vim.lsp.handlers['textDocument/signatureHelp'] = - with_border(vim.lsp.handlers['textDocument/signatureHelp']) - - -- Brief aside: **What is LSP?** #234523 - -- - -- LSP is an initialism you've probably heard, but might not understand what it is. - -- - -- LSP stands for Language Server Protocol. It's a protocol that helps editors - -- and language tooling communicate in a standardized fashion. - -- - -- In general, you have a "server" which is some tool built to understand a particular - -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers - -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone - -- processes that communicate with some "client" - in this case, Neovim! - -- - -- LSP provides Neovim with features like: - -- - Go to definition - -- - Find references - -- - Autocompletion - -- - Symbol Search - -- - and more! - -- - -- Thus, Language Servers are external tools that must be installed separately from - -- Neovim. This is where `mason` and related plugins come into play. - -- - -- If you're wondering about lsp vs treesitter, you can check out the wonderfully - -- and elegantly composed help section, `:help lsp-vs-treesitter` - - -- This function gets run when an LSP attaches to a particular buffer. - -- That is to say, every time a new file is opened that is associated with - -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this - -- function will be executed to configure the current buffer - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup( - 'kickstart-lsp-attach', - { clear = true } - ), - callback = function(event) - -- Prevent duplicate keymap setup when multiple LSP servers attach - if vim.b[event.buf].lsp_keymaps_attached then return end - vim.b[event.buf].lsp_keymaps_attached = true - - -- NOTE: Remember that Lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - vim.keymap.set( - 'n', - 'a', - require('lspimport').import, - { noremap = true } - ) - local map = function(keys, func, desc) - vim.keymap.set( - 'n', - keys, - func, - { buffer = event.buf, desc = 'LSP: ' .. desc } - ) - end - - -- Rename the variable under your cursor. - -- Most Language Servers support renaming across files, etc. - map('rn', vim.lsp.buf.rename, '[R]e[n]ame') - - -- Execute a code action, usually your cursor needs to be on top of an error - -- or a suggestion from your LSP for this to activate. - map('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') - - -- Opens a popup that displays documentation about the word under your cursor - -- See `:help K` for why this keymap. - map('gh', vim.lsp.buf.hover, 'Hover Documentation') - - -- WARN: This is not Goto Definition, this is Goto Declaration. - -- For example, in C this would take you to the header. - map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - - -- DISABLED: Document highlight on CursorMove causes severe scrolling lag - -- The CursorMoved autocmds fire on every scroll step, causing expensive LSP operations - -- To re-enable, uncomment the code below and adjust updatetime for better performance - -- - -- local client = vim.lsp.get_client_by_id(event.data.client_id) - -- if - -- client and client.server_capabilities.documentHighlightProvider - -- then - -- local highlight_augroup = vim.api.nvim_create_augroup( - -- 'kickstart-lsp-highlight', - -- { clear = false } - -- ) - -- vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { - -- buffer = event.buf, - -- group = highlight_augroup, - -- callback = vim.lsp.buf.document_highlight, - -- }) - -- - -- vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - -- buffer = event.buf, - -- group = highlight_augroup, - -- callback = vim.lsp.buf.clear_references, - -- }) - -- end - - -- The following autocommand is used to enable inlay hints in your - -- code, if the language server you are using supports them - -- - -- This may be unwanted, since they displace some of your code - local client = vim.lsp.get_client_by_id(event.data.client_id) - if - client - and client.server_capabilities.inlayHintProvider - and vim.lsp.inlay_hint - then - map( - 'th', - function() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) - end, - '[T]oggle Inlay [H]ints' - ) - end - end, - }) - - vim.api.nvim_create_autocmd('LspDetach', { - group = vim.api.nvim_create_augroup( - 'kickstart-lsp-detach', - { clear = true } - ), - callback = function(event) - vim.lsp.buf.clear_references() - -- try to clear the highlights when the LSP detaches - pcall( - function() - vim.api.nvim_clear_autocmds({ - group = 'kickstart-lsp-highlight', - buffer = event.buf, - }) - end - ) - end, - }) - - -- LSP servers and clients are able to communicate to each other what features they support. - -- By default, Neovim doesn't support everything that is in the LSP specification. - -- When you add nvim-cmp, luasnip, etc. Neovim now has *more* capabilities. - -- So, we create new capabilities with nvim cmp, and then broadcast that to the servers. - local original_capabilities = vim.lsp.protocol.make_client_capabilities() - local capabilities = - require('blink.cmp').get_lsp_capabilities(original_capabilities) - - -- Disable file watchers for performance (especially in large projects) - capabilities.workspace = capabilities.workspace or {} - capabilities.workspace.didChangeWatchedFiles = capabilities.workspace.didChangeWatchedFiles - or {} - capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = false - - -- Enable the following language servers - -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. - -- - -- Add any additional override configuration in the following tables. Available keys are: - -- - cmd (table): Override the default command used to start the server - -- - filetypes (table): Override the default list of associated filetypes for the server - -- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features. - -- - settings (table): Override the default settings passed when initializing the server. - -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ - local servers = { - -- clangd = {}, - -- gopls = {}, - basedpyright = { - on_attach = function(client, bufnr) - -- Disable diagnostics from basedpyright - client.server_capabilities.diagnosticProvider = false - end, - settings = { - python = { - analysis = { - typeCheckingMode = 'off', - diagnosticMode = 'openFilesOnly', - autoSearchPaths = true, - useLibraryCodeForTypes = true, - }, - }, - basedpyright = { - disableOrganizeImports = true, - }, - }, - }, - ruff = {}, - -- pylsp = {}, - -- rust_analyzer = {}, - -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs - -- - -- Some languages (like typescript) have entire language plugins that can be useful: - -- https://github.com/pmizio/typescript-tools.nvim - -- - -- But for many setups, the LSP (`tsserver`) will work just fine - -- tsserver = {}, - -- - - lua_ls = { - -- cmd = {...}, - -- filetypes = { ...}, - -- capabilities = {}, - settings = { - Lua = { - diagnostics = { - globals = { 'vim' }, - }, - completion = { - callSnippet = 'Replace', - }, - -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings - -- diagnostics = { disable = { 'missing-fields' } }, - }, - }, - }, - } - - -- Ensure the servers and tools above are installed - -- To check the current status of installed tools and/or manually install - -- other tools, you can run - -- :Mason - -- - -- You can press `g?` for help in this menu. - require('mason').setup() - - -- You can add other tools here that you want Mason to install - -- for you, so that they are available from within Neovim. - local ensure_installed = vim.tbl_keys(servers or {}) - vim.list_extend(ensure_installed, { - -- Lua - 'stylua', - -- Python - 'black', - 'isort', - 'flake8', - 'mypy', - -- Shell - 'shfmt', - -- JS/TS - 'prettier', - 'prettierd', - 'eslint_d', - -- Misc linters - 'hadolint', - 'jsonlint', - 'vale', - 'tflint', - -- Other - 'sonarlint-language-server', - }) - require('mason-tool-installer').setup({ - ensure_installed = ensure_installed, - }) - - require('mason-lspconfig').setup({ - handlers = { - function(server_name) - local server = servers[server_name] or {} - -- This handles overriding only values explicitly passed - -- by the server configuration above. Useful when disabling - -- certain features of an LSP (for example, turning off formatting for tsserver) - server.capabilities = vim.tbl_deep_extend( - 'force', - {}, - capabilities, - server.capabilities or {} - ) - require('lspconfig')[server_name].setup(server) - end, - }, - }) - end, - }, - { - 'simrat39/symbols-outline.nvim', - cmd = 'SymbolsOutline', - keys = { - { 'cs', 'SymbolsOutline', desc = 'Symbols Outline' }, - }, - config = true, - }, - -- Disabled due to deprecated :LspStart command usage - -- { - -- 'zeioth/garbage-day.nvim', - -- dependencies = 'neovim/nvim-lspconfig', - -- event = 'LspAttach', - -- opts = { - -- excluded_lsp_clients = { - -- 'null-ls', - -- 'jdtls', - -- 'marksman', - -- 'lua_ls', - -- 'copilot', - -- }, - -- timout = 3000, -- Timeout in milliseconds for the garbage collection - -- }, - -- }, - { - 'rachartier/tiny-inline-diagnostic.nvim', - event = 'LspAttach', - priority = 1000, - dependencies = { - 'mfussenegger/nvim-lint', - }, - config = function() - -- Don't error if linters aren't installed (common on fresh machines / WSL). - pcall(function() require('lint').try_lint() end) - require('tiny-inline-diagnostic').setup({ - -- "modern", "classic", "minimal", "powerline", "simple" - preset = 'simple', - transparent_bg = false, -- Set the background of the diagnostic to transparent - hi = { - error = 'DiagnosticError', -- Highlight group for error messages - warn = 'DiagnosticWarn', -- Highlight group for warning messages - info = 'DiagnosticInfo', -- Highlight group for informational messages - hint = 'DiagnosticHint', -- Highlight group for hint or suggestion messages - arrow = 'NonText', -- Highlight group for diagnostic arrows - -- Background color for diagnostics - -- Can be a highlight group or a hexadecimal color (#RRGGBB) - background = 'CursorLine', - -- Color blending option for the diagnostic background - -- Use "None" or a hexadecimal color (#RRGGBB) to blend with another color - mixing_color = 'None', - }, - - options = { - show_source = true, - -- Use icons defined in the diagnostic configuration - use_icons_from_diagnostic = false, - - -- Set the arrow icon to the same color as the first diagnostic severity - set_arrow_to_diag_color = false, - - -- Add messages to diagnostics when multiline diagnostics are enabled - -- If set to false, only signs will be displayed - add_messages = true, - - -- Time (in milliseconds) to throttle updates while moving the cursor - -- Increase this value for better performance if your computer is slow - -- or set to 0 for immediate updates and better visual - throttle = 100, -- Increased from 20 to reduce update frequency during scrolling - - -- Minimum message length before wrapping to a new line - softwrap = 30, - - -- Configuration for multiline diagnostics - -- Can either be a boolean or a table with the following options: - -- multilines = { - -- enabled = false, - -- always_show = false, - -- } - -- If it set as true, it will enable the feature with this options: - -- multilines = { - -- enabled = true, - -- always_show = false, - -- } - multilines = { - enabled = false, - always_show = false, - }, - -- Display all diagnostic messages on the cursor line - show_all_diags_on_cursorline = false, - -- Disable diagnostics in Insert and Visual modes - enable_on_insert = false, - enable_on_select = false, - overflow = { - mode = 'wrap', - padding = 0, - }, - -- Configuration for breaking long messages into separate lines - break_line = { - enabled = false, - after = 30, - }, - - -- Custom format function for diagnostic messages - -- Example: - -- format = function(diagnostic) - -- return diagnostic.message .. " [" .. diagnostic.source .. "]" - -- end - format = nil, - virt_texts = { - -- Priority for virtual text display - priority = 2048, - }, - -- Filter diagnostics by severity - severity = { - vim.diagnostic.severity.ERROR, - vim.diagnostic.severity.WARN, - vim.diagnostic.severity.INFO, - vim.diagnostic.severity.HINT, - }, - -- Events to attach diagnostics to buffers - overwrite_events = nil, - }, - disabled_ft = {}, -- List of filetypes to disable the plugin - }) - end, - }, - - { - 'iamkarasik/sonarqube.nvim', - ft = { 'python' }, - dependencies = { - 'mason-org/mason.nvim', - }, - cond = function() - -- Only load if Java is available (required for SonarLint) - return vim.fn.executable('java') == 1 - end, - config = function() - -- Configure with Mason-installed sonarlint-language-server - local extension_path = vim.fn.stdpath('data') - .. '/mason/packages/sonarlint-language-server/extension' - - -- Check if extension exists - if vim.fn.isdirectory(extension_path) == 0 then - vim.notify( - 'SonarLint extension not found. Run :MasonInstall sonarlint-language-server', - vim.log.levels.WARN - ) - return - end - - require('sonarqube').setup({ - lsp = { - cmd = { - vim.fn.exepath('java'), - '-jar', - extension_path .. '/server/sonarlint-ls.jar', - '-stdio', - '-analyzers', - extension_path .. '/analyzers/sonargo.jar', - extension_path .. '/analyzers/sonarhtml.jar', - extension_path .. '/analyzers/sonariac.jar', - extension_path .. '/analyzers/sonarjava.jar', - extension_path .. '/analyzers/sonarjavasymbolicexecution.jar', - extension_path .. '/analyzers/sonarjs.jar', - extension_path .. '/analyzers/sonarphp.jar', - extension_path .. '/analyzers/sonarpython.jar', - extension_path .. '/analyzers/sonartext.jar', - extension_path .. '/analyzers/sonarxml.jar', - }, - }, - python = { - enabled = true, - }, - }) - end, - }, - - { - 'kosayoda/nvim-lightbulb', - event = 'LspAttach', - keys = { - { - 'lb', - ":lua require('nvim-lightbulb').get_status_text()", - desc = 'LSP: Lightbulb status', - }, - }, - opts = { - autocmd = { enabled = true }, - sign = { enabled = false }, - float = { - enabled = true, - win_opts = { border = 'none' }, - }, - }, - }, - { - 'DNLHC/glance.nvim', - event = 'LspAttach', - opts = { - preview_win_opts = { relativenumber = false }, - theme = { enable = true, mode = 'darken' }, - }, - keys = { - { 'gd', 'Glance definitions', desc = 'LSP: Glance definitions' }, - { 'gr', 'Glance references', desc = 'LSP: Glance references' }, - { - 'gy', - 'Glance type_definitions', - desc = 'LSP: Glance type definitions', - }, - { - 'gm', - 'Glance implementations', - desc = 'LSP: Glance implementations', - }, - }, - }, - { - 'smjonas/inc-rename.nvim', - cmd = 'IncRename', - opts = { hl_group = 'Visual', preview_empty_name = true }, - keys = { - { - 'rn', - function() return vim.fmt(':IncRename %s', vim.fn.expand('')) end, - expr = true, - silent = false, - desc = 'lsp: incremental rename', - }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/mini.lua b/files/.config/nvim/lua/custom/plugins/mini.lua deleted file mode 100644 index ba945b5..0000000 --- a/files/.config/nvim/lua/custom/plugins/mini.lua +++ /dev/null @@ -1,385 +0,0 @@ --- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). -return { -- Collection of various small independent plugins/modules - -- Text objects and editing - { - 'echasnovski/mini.ai', - event = { 'BufReadPre', 'BufNewFile' }, - config = function() require('mini.ai').setup({ n_lines = 500 }) end, - }, - { - 'echasnovski/mini.align', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.align').setup({ - -- Module mappings. Use `''` (empty string) to disable one. - mappings = { - start = 'ga', -- Start align mode - start_with_preview = 'gA', -- Start align mode with preview - }, - -- Options which control alignment process - options = { - split_pattern = '', - justify_side = 'left', - merge_delimiter = '', - }, - }) - end, - }, - { - 'echasnovski/mini.pairs', - version = false, - event = { 'InsertEnter' }, - config = function() - require('mini.pairs').setup({ - -- In which modes mappings from this `config` set are enabled - modes = { insert = true, command = false, terminal = false }, - }) - end, - -- Note: mini.pairs doesn't have fast_wrap like nvim-autopairs - -- You can use mini.surround's 'sa' command in visual mode instead - -- Or keep nvim-autopairs enabled just for fast_wrap if needed - }, - { - 'echasnovski/mini.surround', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.surround').setup({ - -- Number of lines within which surrounding is searched - n_lines = 20, - -- Duration (in ms) of highlight when calling `MiniSurround.highlight()` - highlight_duration = 500, - -- Module mappings. Use `''` (empty string) to disable one. - mappings = { - add = 'sa', -- Add surrounding in Normal and Visual modes - delete = 'sd', -- Delete surrounding - find = 'sf', -- Find surrounding (to the right) - find_left = 'sF', -- Find surrounding (to the left) - highlight = 'sh', -- Highlight surrounding - replace = 'sr', -- Replace surrounding - update_n_lines = 'sn', -- Update `n_lines` - }, - }) - end, - }, - { - 'echasnovski/mini.splitjoin', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.splitjoin').setup({ - -- Module mappings. Use `''` (empty string) to disable one. - mappings = { - toggle = 'gS', - split = '', - join = '', - }, - }) - end, - }, - { - 'echasnovski/mini.move', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.move').setup({ - -- Module mappings. Use `''` (empty string) to disable one. - mappings = { - -- Move visual selection in Visual mode - left = '', - right = '', - down = '', - up = '', - -- Move current line in Normal mode - line_left = '', - line_right = '', - line_down = '', - line_up = '', - }, - -- Options which control behavior of module - options = { - reindent_linewise = true, -- Re-indent selected lines during linewise vertical move - }, - }) - end, - }, - -- { - -- 'echasnovski/mini.jump', - -- version = false, - -- event = { 'BufReadPre', 'BufNewFile' }, - -- config = function() - -- require('mini.jump').setup({ - -- -- Delay values (in ms) for different functionalities. Set any to `false` to disable - -- delay = { - -- -- Delay between jump and highlighting all possible jumps - -- highlight = 250, - -- -- Delay between jump and automatic stop if idle (no jump key was pressed) - -- idle_stop = 1000000, - -- }, - -- -- Function to create labels for all available jumps - -- -- For more information, see `:h mini.jump` - -- mappings = { - -- forward = 'f', - -- backward = 'F', - -- forward_till = 't', - -- backward_till = 'T', - -- repeat_jump = ';', - -- }, - -- }) - -- end, - -- }, - - -- Icons - { - 'echasnovski/mini.icons', - version = false, - -- This was a measurable startup cost (~10ms). None of your always-on startup - -- plugins require devicons, so load it after UI is up. - event = 'VeryLazy', - config = function() - -- Setup with optimized config - require('mini.icons').setup({ - -- Customize which file extensions should use icons - -- Optimized: cache string length to avoid repeated calculations - use_file_extension = function(ext, _) - if not ext or ext == '' then return true end - local len = #ext - if len >= 3 then - local suf3 = ext:sub(-3) - if suf3 == 'scm' or suf3 == 'txt' or suf3 == 'yml' then - return false - end - end - if len >= 4 then - local suf4 = ext:sub(-4) - if suf4 == 'json' or suf4 == 'yaml' then return false end - end - return true - end, - }) - - -- Mock nvim-web-devicons API immediately (needed early for other plugins) - require('mini.icons').mock_nvim_web_devicons() - - -- Defer LSP kind tweak (less critical, can happen after startup) - vim.schedule(function() require('mini.icons').tweak_lsp_kind() end) - end, - }, - - -- Git integration - { - 'echasnovski/mini.diff', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.diff').setup({ - -- Options for overriding view - view = { - style = 'sign', - signs = { - add = '┃', - change = '┃', - delete = '┃', - }, - }, - -- Options for overriding diff algorithm - algorithm = 'histogram', - -- Options for overriding highlight groups - highlight = { - additions = 'MiniDiffSignAdd', - deletions = 'MiniDiffSignDelete', - changes = 'MiniDiffSignChange', - text = 'MiniDiffText', - }, - }) - end, - }, - - -- Visual enhancements - { - 'echasnovski/mini.indentscope', - enabled = false, - cond = false, - }, - { - 'echasnovski/mini.trailspace', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.trailspace').setup({ - -- Highlight only in normal buffers (ones with empty 'buftype'). This is - -- useful to not show trailing whitespace where it usually doesn't matter. - only_in_normal_buffers = true, - }) - end, - }, - - -- UI enhancements - { - 'echasnovski/mini.animate', - version = false, - cond = false, - disable = true, - event = 'VeryLazy', - config = function() - require('mini.animate').setup({ - -- Cursor path animation. Displayed only when - -- cursor is moved by j/k or arrow keys. - cursor = { - -- Whether to enable this animation - enable = true, - -- Timing of animation (how to animate) - timing = require('mini.animate').gen_timing.linear({ - duration = 100, - unit = 'total', - }), - }, - -- Vertical scroll animation. Displayed when moving window - -- viewport up/down. - scroll = { - enable = true, - timing = require('mini.animate').gen_timing.linear({ - duration = 150, - unit = 'total', - }), - }, - -- Resize animation. Displayed when resizing splits. - resize = { - enable = true, - timing = require('mini.animate').gen_timing.linear({ - duration = 100, - unit = 'total', - }), - }, - -- Open window animation. Displayed when opening/closing windows. - open = { - enable = true, - timing = require('mini.animate').gen_timing.linear({ - duration = 100, - unit = 'total', - }), - }, - -- Close window animation. Displayed when opening/closing windows. - close = { - enable = true, - timing = require('mini.animate').gen_timing.linear({ - duration = 100, - unit = 'total', - }), - }, - }) - - -- Disable animations for specific buffers and filetypes - local ignore_buffers = { 'terminal', 'nofile', 'neorg://Quick Actions' } - local ignore_filetypes = { - 'qf', - 'dap_watches', - 'dap_scopes', - 'neo-tree', - 'NeogitCommitMessage', - 'NeogitPopup', - 'NeogitStatus', - } - - local function should_disable_animate() - local buf_type = vim.bo.buftype - local filetype = vim.bo.filetype - local buf_name = vim.api.nvim_buf_get_name(0) - - -- Check buffer type - for _, ignore_type in ipairs(ignore_buffers) do - if buf_type == ignore_type or buf_name:match(ignore_type) then - return true - end - end - - -- Check filetype - for _, ignore_ft in ipairs(ignore_filetypes) do - if filetype == ignore_ft then return true end - end - - return false - end - - -- Set up autocommands to disable animations for ignored buffers/filetypes - vim.api.nvim_create_autocmd({ 'BufEnter', 'FileType' }, { - callback = function() - if should_disable_animate() then - vim.b.minianimate_disable = true - else - vim.b.minianimate_disable = false - end - end, - desc = 'Disable mini.animate for specific buffers/filetypes', - }) - end, - }, - { - 'echasnovski/mini.starter', - version = false, - event = 'VimEnter', - config = function() - require('mini.starter').setup({ - -- Whether to open starter buffer on VimEnter. Not opened if command - -- line arguments are present. - autoopen = true, - -- Whether to evaluate action of single active item - evaluate_single = false, - -- Items to be displayed. Should be an array with the following elements: - -- - Item: table with , ,
keys. - -- - Function: should return one of these three categories. - -- - `nil`: empty line (applies `header` + `footer` settings) - -- If `nil` (default), default items will be used. - items = nil, - -- Header to be displayed before items. Converted to single string via - -- `tostring` (use `\n` to display several lines). If function, it is - -- evaluated first. If `nil` (default), polite greeting will be used. - header = nil, - -- Footer to be displayed after items. Converted to single string via - -- `tostring`. If function, it is evaluated first. If `nil` (default), - -- default usage help will be shown. - footer = nil, - -- Characters to update query. Each character will have special buffer - -- mapping overriding your global ones. `:` will be treated specially - -- (see command section in the main readme). - query_updaters = '', - -- Whether to disable showing non-error feedback - silent = false, - }) - end, - }, - - -- Utility modules - { - 'echasnovski/mini.misc', - version = false, - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - require('mini.misc').setup({ - -- Module mappings. Use `''` (empty string) to disable one. - mappings = { - -- Put global mappings here - }, - -- Various options - options = { - -- Whether to use global statusline - use_global_statusline = true, - }, - }) - end, - }, - - { - 'echasnovski/mini.bufremove', - version = '*', - keys = { - { - 'bD', - ' lua MiniBufremove.unshow()', - 'buffer: close buffer', - }, - }, - config = function() require('mini.bufremove').setup() end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/navigation.lua b/files/.config/nvim/lua/custom/plugins/navigation.lua deleted file mode 100644 index 759f51a..0000000 --- a/files/.config/nvim/lua/custom/plugins/navigation.lua +++ /dev/null @@ -1,65 +0,0 @@ -return { - - { - 'stevearc/oil.nvim', - lazy = true, - opts = { - default_file_explorer = true, - delete_to_trash = true, - skip_confirm_for_simple_edits = true, - view_options = { - show_hidden = true, - }, - keymaps = { - [''] = false, -- don't shadow split navigation - [''] = false, - }, - }, - keys = { - { '-', 'Oil', desc = 'oil: open parent directory' }, - }, - }, - - { - 'cbochs/grapple.nvim', - dependencies = { 'echasnovski/mini.icons' }, - opts = { - scope = 'git', - }, - keys = { - { 'm', 'Grapple tag', desc = 'grapple: tag file' }, - { - '', - 'Grapple toggle_tags', - desc = 'grapple: open tags', - }, - { - '1', - 'Grapple select index=1', - desc = 'grapple: select 1', - }, - { - '2', - 'Grapple select index=2', - desc = 'grapple: select 2', - }, - { - '3', - 'Grapple select index=3', - desc = 'grapple: select 3', - }, - { - '4', - 'Grapple select index=4', - desc = 'grapple: select 4', - }, - { - '5', - 'Grapple select index=5', - desc = 'grapple: select 5', - }, - { '[g', 'Grapple cycle_tags prev', desc = 'grapple: prev tag' }, - { ']g', 'Grapple cycle_tags next', desc = 'grapple: next tag' }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/noice.lua b/files/.config/nvim/lua/custom/plugins/noice.lua deleted file mode 100644 index 819c4b2..0000000 --- a/files/.config/nvim/lua/custom/plugins/noice.lua +++ /dev/null @@ -1,291 +0,0 @@ -local fn = vim.fn -local L = vim.log.levels - -return { - 'folke/noice.nvim', - event = 'CmdlineEnter', - cmd = { 'Noice', 'NoiceHistory', 'NoiceLast', 'NoiceDismiss', 'NoiceErrors' }, - dependencies = { 'MunifTanjim/nui.nvim' }, - -- cond = false, - -- disable = true, - opts = { - cmdline = { - format = { - IncRename = { title = ' Rename ' }, - substitute = { - pattern = '^:%%?s/', - icon = ' ', - ft = 'regex', - title = '', - }, - input = { - icon = ' ', - lang = 'text', - view = 'cmdline_popup', - title = '', - }, - }, - }, - popupmenu = { - backend = 'nui', - }, - lsp = { - -- message = { - -- enabled = true, -- Enable Noice to handle LSP messages - -- }, - documentation = { - enabled = false, - opts = { - border = { style = 'rounded' }, - position = { row = 2 }, - }, - }, - signature = { - enabled = false, - opts = { - position = { row = 2 }, - }, - }, - hover = { - enabled = false, - silent = true, - }, - override = { - ['vim.lsp.util.convert_input_to_markdown_lines'] = false, - ['vim.lsp.util.stylize_markdown'] = false, - }, - }, - views = { - vsplit = { size = { width = 'auto' } }, - split = { win_options = { winhighlight = { Normal = 'Normal' } } }, - popup = { - border = { style = 'rounded', padding = { 0, 1 } }, - win_options = { winblend = 0 }, - }, - cmdline_popup = { - position = { row = 5, col = '50%' }, - size = { width = 'auto', height = 'auto' }, - border = { style = 'rounded', padding = { 0, 1 } }, - win_options = { - winblend = 0, - winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, - }, - }, - confirm = { - border = { style = 'rounded', padding = { 0, 1 }, text = { top = '' } }, - win_options = { - winblend = 0, - winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, - }, - }, - popupmenu = { - relative = 'editor', - position = { row = 9, col = '50%' }, - size = { width = 60, height = 10 }, - border = { style = 'rounded', padding = { 0, 1 } }, - win_options = { - winblend = 0, - -- Treat cmdline/popupmenu as "popup-normal" (not float-normal) - winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, - }, - }, - }, - redirect = { view = 'popup', filter = { event = 'msg_show' } }, - routes = { - { - opts = { skip = true }, - filter = { - any = { - { event = 'msg_show', find = 'written' }, - { event = 'msg_show', find = '%d+ lines, %d+ bytes' }, - { event = 'msg_show', kind = 'search_count' }, - { event = 'msg_show', find = '%d+L, %d+B' }, - { event = 'msg_show', find = '^Hunk %d+ of %d' }, - { event = 'msg_show', find = '%d+ change' }, - { event = 'msg_show', find = '%d+ line' }, - { event = 'msg_show', find = '%d+ more line' }, - }, - }, - }, - { - view = 'vsplit', - filter = { event = 'msg_show', min_height = 20 }, - }, - { - view = 'mini', - filter = { - any = { - { event = 'msg_show', min_height = 10 }, - { event = 'msg_show', find = 'Treesitter' }, - }, - }, - opts = { timeout = 10000 }, - }, - { - view = 'mini', - filter = { event = 'notify', find = 'Type%-checking' }, - opts = { replace = true, merge = true, title = 'TSC' }, - stop = true, - }, - { - view = 'mini', - filter = { - any = { - { event = 'msg_show', find = '^E486:' }, - { event = 'notify', max_height = 1 }, - }, - }, -- minimise pattern not found messages - }, - { - view = 'mini', - filter = { - any = { - { warning = true }, - { event = 'msg_show', find = '^Warn' }, - { event = 'msg_show', find = '^W%d+:' }, - { event = 'msg_show', find = '^No hunks$' }, - }, - }, - opts = { - title = 'Warning', - level = L.WARN, - merge = false, - replace = false, - }, - }, - { - view = 'mini', - opts = { - title = 'Error', - level = L.ERROR, - merge = true, - replace = false, - }, - filter = { - any = { - { error = true }, - { event = 'msg_show', find = '^Error' }, - { event = 'msg_show', find = '^E%d+:' }, - }, - }, - }, - { - view = 'mini', - opts = { title = '' }, - filter = { kind = { 'emsg', 'echo', 'echomsg' } }, - }, - }, - commands = { - history = { view = 'vsplit' }, - }, - presets = { - inc_rename = true, - long_message_to_split = true, - lsp_doc_border = true, - }, - }, - config = function(_, opts) - -- Folke's noice enhancements - opts.routes = opts.routes or {} - -- Skip "No information available" notifications - table.insert(opts.routes, { - filter = { - event = 'notify', - find = 'No information available', - }, - opts = { skip = true }, - }) - table.insert(opts.routes, { - filter = { - event = 'notify', - find = 'LSP%[ruff%] Ruff failed to handle a request', - }, - opts = { skip = true }, - }) - table.insert(opts.routes, { - filter = { - event = 'msg_show', - find = 'client%.notify is deprecated', - }, - opts = { skip = true }, - }) - - -- Focus-aware notifications (send to notify_send when not focused) - local focused = true - vim.api.nvim_create_autocmd('FocusGained', { - callback = function() focused = true end, - }) - vim.api.nvim_create_autocmd('FocusLost', { - callback = function() focused = false end, - }) - - table.insert(opts.routes, 1, { - filter = { - ['not'] = { - event = 'lsp', - kind = 'progress', - }, - cond = function() return not focused and false end, - }, - view = 'notify_send', - opts = { stop = false, replace = true }, - }) - - -- Markdown keybindings in markdown files - vim.api.nvim_create_autocmd('FileType', { - pattern = 'markdown', - callback = function(event) - vim.schedule( - function() require('noice.text.markdown').keys(event.buf) end - ) - end, - }) - - require('noice').setup(opts) - - vim.api.nvim_create_user_command( - 'NotifyTest', - function() - vim.notify(('Noice mini toast\n'):rep(6), vim.log.levels.INFO, { - title = 'Noice Mini', - }) - end, - { desc = 'Test Noice mini notifications' } - ) - - -- Noice uses `winhighlight` to map FloatBorder -> NoiceCmdlinePopupBorder. - -- Force these border groups to link to PopupBorder immediately (no scheduling), - -- otherwise they may keep their default DiagnosticSign* colors. - for _, name in ipairs({ - 'NoiceCmdlinePopupBorder', - 'NoiceCmdlinePopupBorderCmdline', - 'NoiceCmdlinePopupBorderSearch', - 'NoiceCmdlinePopupBorderFilter', - 'NoiceCmdlinePopupBorderHelp', - 'NoiceCmdlinePopupBorderSubstitute', - 'NoiceCmdlinePopupBorderIncRename', - 'NoiceCmdlinePopupBorderInput', - 'NoiceCmdlinePopupBorderLua', - 'NoiceConfirmBorder', - }) do - pcall(vim.api.nvim_set_hl, 0, name, { link = 'PopupBorder' }) - end - - vim.keymap.set({ 'n', 'i', 's' }, '', function() - if not require('noice.lsp').scroll(4) then return '' end - end, { silent = true, expr = true }) - - vim.keymap.set({ 'n', 'i', 's' }, '', function() - if not require('noice.lsp').scroll(-4) then return '' end - end, { silent = true, expr = true }) - - vim.keymap.set( - 'c', - '', - function() require('noice').redirect(fn.getcmdline()) end, - { - desc = 'redirect Cmdline', - } - ) - end, -} diff --git a/files/.config/nvim/lua/custom/plugins/obsidian.lua b/files/.config/nvim/lua/custom/plugins/obsidian.lua deleted file mode 100644 index 0bb70e0..0000000 --- a/files/.config/nvim/lua/custom/plugins/obsidian.lua +++ /dev/null @@ -1,180 +0,0 @@ --- local my_vault = vim.fn.expand("~") --- .. "/Library/Mobile Documents/iCloud~md~obsidian/Documents/**.md" -return { - 'epwalsh/obsidian.nvim', - cmd = { - 'ObsidianOpen', - 'ObsidianNew', - 'ObsidianSearch', - 'ObsidianQuickSwitch', - }, - -- lazy = true, - -- event = { - -- "BufReadPre " .. my_vault, - -- "BufNewFile " .. my_vault, - -- }, - keys = { - { 'oo', ':ObsidianOpen' }, - { 'on', ':ObsidianNew' }, - { 'os', ':ObsidianSearch' }, - { 'of', ':ObsidianQuickSwitch' }, - }, - dependencies = { - 'nvim-lua/plenary.nvim', - 'ibhagwan/fzf-lua', - }, - opts = { - ui = { enable = false }, - workspaces = { - { - name = 'personal', - path = vim.g.obsidian, - }, - }, - }, - -- config = function(_, opts) - -- local my_vault = vim.g.obsidian_vault_path - -- - -- require('obsidian').setup({ - -- -- Required, the path to your vault directory. - -- dir = my_vault, - -- - -- -- Optional, if you keep notes in a specific subdirectory of your vault. - -- notes_subdir = 'notes', - -- - -- -- Optional, set the log level for obsidian.nvim. This is an integer corresponding to one of the log - -- -- levels defined by "vim.log.levels.*" or nil, which is equivalent to DEBUG (1). - -- log_level = vim.log.levels.DEBUG, - -- - -- daily_notes = { - -- -- Optional, if you keep daily notes in a separate directory. - -- folder = 'notes/dailies', - -- -- Optional, if you want to change the date format for the ID of daily notes. - -- date_format = '%Y-%m-%d', - -- -- Optional, if you want to change the date format of the default alias of daily notes. - -- alias_format = '%B %-d, %Y', - -- -- Optional, if you want to automatically insert a template from your template directory like 'daily.md' - -- template = nil, - -- }, - -- - -- -- Optional, completion. - -- -- completion = { - -- -- -- If using nvim-cmp, otherwise set to false - -- -- nvim_cmp = true, - -- -- -- Trigger completion at 2 chars - -- -- min_chars = 2, - -- -- -- Where to put new notes created from completion. Valid options are - -- -- -- * "current_dir" - put new notes in same directory as the current buffer. - -- -- -- * "notes_subdir" - put new notes in the default notes subdirectory. - -- -- new_notes_location = 'current_dir', - -- -- - -- -- -- Whether to add the output of the node_id_func to new notes in autocompletion. - -- -- -- E.g. "[[Foo" completes to "[[foo|Foo]]" assuming "foo" is the ID of the note. - -- -- prepend_note_id = true, - -- -- }, - -- - -- -- Optional, key mappings. - -- mappings = { - -- -- Overrides the 'gf' mapping to work on markdown/wiki links within your vault. - -- ['gf'] = { - -- action = function() return require('obsidian').util.gf_passthrough() end, - -- opts = { noremap = false, expr = true, buffer = true }, - -- }, - -- }, - -- - -- -- Optional, if set to true, the specified mappings in the `mappings` - -- -- table will overwrite existing ones. Otherwise a warning is printed - -- -- and the mappings are not applied. - -- -- overwrite_mappings = false, - -- - -- -- Optional, customize how names/IDs for new notes are created. - -- note_id_func = function(title) - -- -- Create note IDs in a Zettelkasten format with a timestamp and a suffix. - -- -- In this case a note with the title 'My new note' will given an ID that looks - -- -- like '1657296016-my-new-note', and therefore the file name '1657296016-my-new-note.md' - -- local suffix = '' - -- if title ~= nil then - -- -- If title is given, transform it into valid file name. - -- suffix = title:gsub(' ', '-'):gsub('[^A-Za-z0-9-]', ''):lower() - -- else - -- -- If title is nil, just add 4 random uppercase letters to the suffix. - -- for _ = 1, 4 do - -- suffix = suffix .. string.char(math.random(65, 90)) - -- end - -- end - -- return tostring(os.time()) .. '-' .. suffix - -- end, - -- - -- -- Optional, set to true if you don't want obsidian.nvim to manage frontmatter. - -- disable_frontmatter = false, - -- - -- -- Optional, alternatively you can customize the frontmatter data. - -- note_frontmatter_func = function(note) - -- -- This is equivalent to the default frontmatter function. - -- local out = { id = note.id, aliases = note.aliases, tags = note.tags } - -- -- `note.metadata` contains any manually added fields in the frontmatter. - -- -- So here we just make sure those fields are kept in the frontmatter. - -- if - -- note.metadata ~= nil - -- and require('obsidian').util.table_length(note.metadata) > 0 - -- then - -- for k, v in pairs(note.metadata) do - -- out[k] = v - -- end - -- end - -- return out - -- end, - -- - -- -- Optional, for templates (see below). - -- templates = { - -- subdir = 'notes/templates', - -- date_format = '%Y-%m-%d', - -- time_format = '%H:%M', - -- -- A map for custom variables, the key should be the variable and the value a function - -- substitutions = {}, - -- }, - -- - -- -- -- Optional, customize the backlinks interface. - -- -- backlinks = { - -- -- -- The default height of the backlinks pane. - -- -- height = 10, - -- -- -- Whether or not to wrap lines. - -- -- wrap = true, - -- -- }, - -- - -- -- Optional, by default when you use `:ObsidianFollowLink` on a link to an external - -- -- URL it will be ignored but you can customize this behavior here. - -- follow_url_func = function(url) - -- -- Open the URL in the default web browser. - -- vim.fn.jobstart({ 'open', url }) -- Mac OS - -- -- vim.fn.jobstart({"xdg-open", url}) -- linux - -- end, - -- - -- -- Optional, set to true if you use the Obsidian Advanced URI plugin. - -- -- https://github.com/Vinzent03/obsidian-advanced-uri - -- use_advanced_uri = true, - -- - -- -- Optional, set to true to force ':ObsidianOpen' to bring the app to the foreground. - -- open_app_foreground = false, - -- - -- -- Optional, by default commands like `:ObsidianSearch` will attempt to use - -- -- telescope.nvim, fzf-lua, and fzf.nvim (in that order), and use the - -- -- first one they find. By setting this option to your preferred - -- -- finder you can attempt it first. Note that if the specified finder - -- -- is not installed, or if it the command does not support it, the - -- -- remaining finders will be attempted in the original order. - -- finder = 'fzf-lua', - -- - -- -- Optional, sort search results by "path", "modified", "accessed", or "created". - -- -- The recommend value is "modified" and `true` for `sort_reversed`, which means, for example `:ObsidianQuickSwitch` - -- -- will show the notes sorted by latest modified time - -- sort_by = 'modified', - -- sort_reversed = true, - -- - -- -- Optional, determines whether to open notes in a horizontal split, a vertical split, - -- -- or replacing the current buffer (default) - -- -- Accepted values are "current", "hsplit" and "vsplit" - -- open_notes_in = 'current', - -- }) - -- end, -} diff --git a/files/.config/nvim/lua/custom/plugins/remote.lua b/files/.config/nvim/lua/custom/plugins/remote.lua deleted file mode 100644 index 3f523ef..0000000 --- a/files/.config/nvim/lua/custom/plugins/remote.lua +++ /dev/null @@ -1,35 +0,0 @@ -return { - { - 'https://codeberg.org/esensar/nvim-dev-container', - lazy = true, - dependencies = 'nvim-treesitter/nvim-treesitter', - -- commit = '462c9c296d65577ee6f0a9f326f5cce9b937eddf', - opts = {}, - -- cmd = 'DevContainer', - }, - -- Tmux integraction {{{ - -- - -- { - -- "otavioschwanck/tmux-awesome-manager.nvim", - -- disable = true, - -- config = function() - -- require("tmux-awesome-manager").setup({ - -- per_project_commands = { -- Configure your per project servers with - -- -- project name = { { cmd, name } } - -- api = { { cmd = "rails server", name = "Rails Server" } }, - -- front = { { cmd = "yarn dev", name = "react server" } }, - -- }, - -- session_name = "Neovim Terminals", - -- use_icon = false, -- use prefix icon - -- icon = " ", -- Prefix icon to use - -- -- project_open_as = 'window', -- Open per_project_commands as. Default: separated_session - -- -- default_size = '30%', -- on panes, the default size - -- -- open_new_as = 'window' -- open new command as. options: pane, window, separated_session. - -- }) - -- end, - -- }, - -- - -- }}} -} - --- vim:foldmethod=marker diff --git a/files/.config/nvim/lua/custom/plugins/repl.lua b/files/.config/nvim/lua/custom/plugins/repl.lua deleted file mode 100644 index 0005d9a..0000000 --- a/files/.config/nvim/lua/custom/plugins/repl.lua +++ /dev/null @@ -1,31 +0,0 @@ -return { - 'marromlam/kitty-repl.nvim', - dev = true, - disable = false, - keys = { - { ';r', ':KittyREPLRun', 'repl: run' }, - { ';s', ':KittyREPLSend', 'repl: run' }, - { ';s', ':KittyREPLSend', 'repl: run' }, - { '', ':KittyREPLSend', 'repl: run' }, - { ';c', ':KittyREPLClear', 'repl: run' }, - { ';k', ':KittyREPLKill', 'repl: run' }, - { ';l', ':KittyREPLRunAgain', 'repl: run' }, - { ';w', ':KittyREPLStart', 'repl: run' }, - { - ';a', - ':lua require("kitty-repl").repl_run_repl()', - 'repl: run comments', - }, - }, - config = function() - require('kitty-repl').setup() - vim.keymap.set('n', ';r', ':KittyREPLRun', {}) - vim.keymap.set('x', ';s', ':KittyREPLSend', {}) - vim.keymap.set('n', ';s', ':KittyREPLSend', {}) - vim.keymap.set('n', '', ':KittyREPLSend', {}) - vim.keymap.set('n', ';c', ':KittyREPLClear', {}) - vim.keymap.set('n', ';k', ':KittyREPLKill', {}) - vim.keymap.set('n', ';l', ':KittyREPLRunAgain', {}) - vim.keymap.set('n', ';w', ':KittyREPLStart', {}) - end, -} diff --git a/files/.config/nvim/lua/custom/plugins/terminal.lua b/files/.config/nvim/lua/custom/plugins/terminal.lua deleted file mode 100644 index 0b1d34a..0000000 --- a/files/.config/nvim/lua/custom/plugins/terminal.lua +++ /dev/null @@ -1,94 +0,0 @@ -local T = require('tools') -local map = vim.keymap.set - -return { - 'akinsho/toggleterm.nvim', - cmd = { 'ToggleTerm', 'ToggleTermOpenAll', 'ToggleTermCloseAll' }, - dev = true, - opts = { - open_mapping = [[]], - shade_filetypes = {}, - direction = 'horizontal', - autochdir = true, - persist_mode = true, - insert_mappings = false, - start_in_insert = true, - highlights = { - FloatBorder = { link = 'FloatBorder' }, - -- Make floating terminals match the main Normal background. - NormalFloat = { link = 'Normal' }, - }, - float_opts = { - -- border = mrl.ui.current.border, - winblend = 3, - }, - size = function(term) - if term.direction == 'horizontal' then - return 15 - elseif term.direction == 'vertical' then - return math.floor(vim.o.columns * 0.4) - end - end, - }, - config = function(_, opts) - require('toggleterm').setup(opts) - - local float_handler = function(term) - if not T.falsy(vim.fn.mapcheck('jk', 't')) then - vim.keymap.del('t', 'jk', { buffer = term.bufnr }) - vim.keymap.del('t', '', { buffer = term.bufnr }) - end - end - - local Terminal = require('toggleterm.terminal').Terminal - - local lazygit = Terminal:new({ - cmd = 'lazygit', - dir = 'git_dir', - hidden = true, - direction = 'float', - on_open = float_handler, - }) - - local lazydocker = Terminal:new({ - cmd = 'lazydocker', - dir = 'git_dir', - hidden = true, - direction = 'float', - on_open = float_handler, - }) - - local btop = Terminal:new({ - cmd = 'btop', - hidden = true, - direction = 'float', - on_open = float_handler, - highlights = { - FloatBorder = { link = 'FloatBorder' }, - NormalFloat = { link = 'Normal' }, - }, - }) - - local gh_dash = Terminal:new({ - cmd = 'gh dash', - hidden = true, - direction = 'float', - on_open = float_handler, - float_opts = { - height = function() return math.floor(vim.o.lines * 0.8) end, - width = function() return math.floor(vim.o.columns * 0.95) end, - }, - }) - - map('n', 'lh', function() gh_dash:toggle() end, { - desc = 'toggleterm: toggle github dashboard', - }) - map('n', 'lg', function() lazygit:toggle() end, { - desc = 'toggleterm: toggle lazygit', - }) - map('n', 'ld', function() lazydocker:toggle() end, { - desc = 'toggleterm: toggle lazydocker', - }) - T.command('Btop', function() btop:toggle() end) - end, -} diff --git a/files/.config/nvim/lua/custom/plugins/testing.lua b/files/.config/nvim/lua/custom/plugins/testing.lua deleted file mode 100644 index a06731e..0000000 --- a/files/.config/nvim/lua/custom/plugins/testing.lua +++ /dev/null @@ -1,65 +0,0 @@ ----@diagnostic disable: missing-fields -local function neotest() return require('neotest') end -local function open() neotest().output.open({ enter = true, short = false }) end -local function run_file() neotest().run.run(vim.fn.expand('%')) end -local function run_file_sync() - neotest().run.run({ vim.fn.expand('%'), concurrent = false }) -end -local function nearest() neotest().run.run() end -local function next_failed() neotest().jump.prev({ status = 'failed' }) end -local function prev_failed() neotest().jump.next({ status = 'failed' }) end -local function toggle_summary() neotest().summary.toggle() end -local function cancel() neotest().run.stop({ interactive = true }) end - -return { - { - 'nvim-neotest/neotest', - keys = { - { 'ts', toggle_summary, desc = 'neotest: toggle summary' }, - { 'to', open, desc = 'neotest: output' }, - { 'tn', nearest, desc = 'neotest: run' }, - { 'tf', run_file, desc = 'neotest: run file' }, - { - 'tF', - run_file_sync, - desc = 'neotest: run file synchronously', - }, - { 'tc', cancel, desc = 'neotest: cancel' }, - { '[n', next_failed, desc = 'jump to next failed test' }, - { ']n', prev_failed, desc = 'jump to previous failed test' }, - }, - config = function() - local namespace = vim.api.nvim_create_namespace('neotest') - vim.diagnostic.config({ - virtual_text = { - format = function(diagnostic) - local value = diagnostic.message - :gsub('\n', ' ') - :gsub('\t', ' ') - :gsub('%s+', ' ') - :gsub('^%s+', '') - return value - end, - }, - }, namespace) - - require('neotest').setup({ - discovery = { enabled = true }, - diagnostic = { enabled = true }, - floating = { border = 'rounded' }, - quickfix = { enabled = false, open = true }, - adapters = { - require('neotest-plenary'), - require('neotest-python'), - }, - }) - end, - dependencies = { - { - 'rcarriga/neotest-plenary', - dependencies = { 'nvim-lua/plenary.nvim' }, - }, - { 'nvim-neotest/neotest-python' }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/todo.lua b/files/.config/nvim/lua/custom/plugins/todo.lua deleted file mode 100644 index df1653e..0000000 --- a/files/.config/nvim/lua/custom/plugins/todo.lua +++ /dev/null @@ -1,58 +0,0 @@ -return { - { - 'folke/todo-comments.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - dependencies = { 'nvim-lua/plenary.nvim' }, - opts = { signs = false }, - config = function(_, opts) - local todo_comments = require('todo-comments') - vim.keymap.set( - 'n', - ']t', - function() todo_comments.jump_next() end, - { desc = 'Next todo comment' } - ) - vim.keymap.set( - 'n', - '[t', - function() todo_comments.jump_prev() end, - { desc = 'Previous todo comment' } - ) - todo_comments.setup(opts) - end, - }, - { - 'folke/trouble.nvim', - dependencies = { 'folke/todo-comments.nvim' }, - cmd = { 'Trouble' }, - opts = {}, - keys = { - { - 'xx', - 'Trouble diagnostics toggle', - desc = 'trouble: workspace diagnostics', - }, - { - 'xd', - 'Trouble diagnostics toggle filter.buf=0', - desc = 'trouble: document diagnostics', - }, - { - 'xq', - 'Trouble qflist toggle', - desc = 'trouble: quickfix list', - }, - { - 'xl', - 'Trouble loclist toggle', - desc = 'trouble: location list', - }, - { - 'xs', - 'Trouble symbols toggle', - desc = 'trouble: document symbols', - }, - { 'xt', 'Trouble todo toggle', desc = 'trouble: todos' }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/treesitter.lua b/files/.config/nvim/lua/custom/plugins/treesitter.lua deleted file mode 100644 index 6d3563b..0000000 --- a/files/.config/nvim/lua/custom/plugins/treesitter.lua +++ /dev/null @@ -1,166 +0,0 @@ --- DONE -return { - { - 'nvim-treesitter/nvim-treesitter', - branch = 'master', - event = { 'BufReadPost', 'BufNewFile' }, - build = ':TSUpdate', - config = function() - ---@diagnostic disable-next-line: missing-fields - require('nvim-treesitter.configs').setup({ - -- NOTE: Keep your broader list, but add Akinsho's core parsers too. - -- stylua: ignore - ensure_installed = { - 'c', 'vim', 'vimdoc', 'query', 'lua', 'luadoc', 'luap', - 'diff', 'regex', 'gitcommit', 'git_config', 'git_rebase', 'markdown', 'markdown_inline', - -- Your stack - 'bash', 'html', 'json', 'javascript', 'typescript', 'tsx', 'yaml', 'css', 'prisma', - 'svelte', 'graphql', 'dockerfile', 'gitignore', - }, - auto_install = true, - highlight = { - enable = true, - disable = { 'tex', 'latex', 'applescript' }, - -- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. - -- If you are experiencing weird indenting issues, add the language to - -- the list of additional_vim_regex_highlighting and disabled languages for indent. - additional_vim_regex_highlighting = { 'org', 'sql' }, - }, - incremental_selection = { - enable = true, - disable = { 'tex', 'latex', 'help' }, - keymaps = { - init_selection = '', - node_incremental = '', - scope_incremental = false, - node_decremental = '', - }, - }, - indent = { - enable = true, - disable = { 'yaml' }, - }, - textobjects = { - lookahead = true, - select = { - enable = true, - include_surrounding_whitespace = true, - keymaps = { - ['af'] = { query = '@function.outer', desc = 'ts: all function' }, - ['if'] = { - query = '@function.inner', - desc = 'ts: inner function', - }, - ['ac'] = { query = '@class.outer', desc = 'ts: all class' }, - ['ic'] = { query = '@class.inner', desc = 'ts: inner class' }, - ['aC'] = { - query = '@conditional.outer', - desc = 'ts: all conditional', - }, - ['iC'] = { - query = '@conditional.inner', - desc = 'ts: inner conditional', - }, - ['aL'] = { - query = '@assignment.lhs', - desc = 'ts: assignment lhs', - }, - ['aR'] = { - query = '@assignment.rhs', - desc = 'ts: assignment rhs', - }, - }, - }, - move = { - enable = true, - set_jumps = true, - goto_next_start = { - [']m'] = '@function.outer', - [']M'] = '@class.outer', - }, - goto_previous_start = { - ['[m'] = '@function.outer', - ['[M'] = '@class.outer', - }, - }, - }, - autopairs = { enable = true }, - playground = { persist_queries = true }, - query_linter = { - enable = true, - use_virtual_text = true, - lint_events = { 'BufWrite', 'CursorHold' }, - }, - }) - end, - }, - - -- IMPORTANT: `nvim-treesitter-textobjects` requires `nvim-treesitter` to be - -- loaded first. If declared as a dependency of treesitter, Lazy will load it - -- *before* treesitter (dependencies load first), causing `require('nvim-treesitter.configs')` - -- to fail. Keep it as a separate plugin that depends on treesitter instead. - { - 'nvim-treesitter/nvim-treesitter-textobjects', - event = { 'BufReadPost', 'BufNewFile' }, - dependencies = { 'nvim-treesitter/nvim-treesitter' }, - }, - - { - 'Wansmer/treesj', - dependencies = { 'nvim-treesitter' }, - opts = { - use_default_keymaps = false, - }, - keys = { - { - 'gS', - 'TSJSplit', - desc = 'split expression to multiple lines', - }, - { 'gJ', 'TSJJoin', desc = 'join expression to single line' }, - }, - }, - { - 'windwp/nvim-ts-autotag', - dependencies = { 'nvim-treesitter' }, - event = { 'BufReadPost', 'BufNewFile' }, - ft = { - 'html', - 'xml', - 'javascript', - 'typescript', - 'javascriptreact', - 'typescriptreact', - 'svelte', - 'vue', - 'markdown', - }, - opts = {}, - }, - - { - 'nvim-treesitter/nvim-treesitter-context', - event = { 'BufReadPost', 'BufNewFile' }, - init = function() - local highlight = require('highlight') - highlight.plugin('treesitter-context', { - { TreesitterContextSeparator = { link = 'Dim' } }, - { TreesitterContext = { inherit = 'Normal' } }, - { TreesitterContextLineNumber = { inherit = 'LineNr' } }, - }) - end, - opts = { - enable = false, - multiline_threshold = 10, - separator = '─', - mode = 'cursor', - }, - keys = { - { - 'sc', - 'TSContext toggle', - desc = 'Toggle [s]cope [c]ontext', - }, - }, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/ui.lua b/files/.config/nvim/lua/custom/plugins/ui.lua deleted file mode 100644 index 00a3768..0000000 --- a/files/.config/nvim/lua/custom/plugins/ui.lua +++ /dev/null @@ -1,322 +0,0 @@ -local UI = require('tools').ui -local icons = UI.icons -return { - { - 'lukas-reineke/indent-blankline.nvim', - event = { 'BufReadPre', 'BufNewFile' }, - main = 'ibl', - opts = { - indent = { char = '┊' }, - exclude = { - filetypes = { 'notify', 'noice', 'noice_popup', 'noice_cmdline' }, - }, - }, - }, - - { - 'SmiteshP/nvim-navic', - event = 'LspAttach', - config = function() - require('nvim-navic').setup({ - highlight = true, - separator = ' › ', - depth_limit = 5, - depth_limit_indicator = '..', - }) - -- Attach navic to LSP clients - vim.api.nvim_create_autocmd('LspAttach', { - callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - if client and client.server_capabilities.documentSymbolProvider then - require('nvim-navic').attach(client, args.buf) - end - end, - }) - end, - }, - - { - 'b0o/incline.nvim', - event = 'VeryLazy', - config = function() - local incline = require('incline') - - local function set_hls() - local pal = UI.palette or {} - local bg = '#121212' - vim.api.nvim_set_hl(0, 'InclineNormal', { - fg = pal.whitesmoke or 'NONE', - bg = bg, - }) - vim.api.nvim_set_hl(0, 'InclineNormalNC', { - fg = pal.light_gray or pal.comment_grey or 'NONE', - bg = bg, - }) - vim.api.nvim_set_hl(0, 'InclineTitle', { - fg = pal.bright_blue or pal.blue or 'NONE', - bg = bg, - bold = true, - }) - vim.api.nvim_set_hl(0, 'InclineModified', { - fg = pal.dark_orange or 'NONE', - bg = bg, - }) - vim.api.nvim_set_hl(0, 'InclineGit', { - fg = pal.teal or pal.green or 'NONE', - bg = bg, - }) - end - - set_hls() - vim.api.nvim_create_autocmd('ColorScheme', { - group = vim.api.nvim_create_augroup('MrlIncline', { clear = true }), - callback = set_hls, - }) - - local devicons_ok, devicons = pcall(require, 'nvim-web-devicons') - - -- Use incline's render function so we can style per-window content. - incline.setup({ - window = { - placement = { horizontal = 'right', vertical = 'top' }, - margin = { vertical = 1, horizontal = 1 }, - padding = 1, - winhighlight = { - Normal = 'InclineNormal', - NormalNC = 'InclineNormalNC', - }, - }, - ignore = { - buftypes = { 'terminal', 'nofile', 'prompt', 'quickfix' }, - filetypes = { - 'neo-tree', - 'NvimTree', - 'undotree', - 'toggleterm', - 'Trouble', - 'noice', - 'notify', - 'qf', - 'diff', - 'alpha', - 'startify', - 'help', - 'gitcommit', - 'NeogitStatus', - 'NeogitCommitMessage', - 'DiffviewFiles', - 'DiffviewFileHistory', - }, - }, - render = function(props) - local buf = props.buf - local ft = vim.bo[buf].ft - local bt = vim.bo[buf].bt - local decor = UI.decorations.get({ - ft = ft, - bt = bt, - setting = 'winbar', - }) - if - (decor and (decor.ft == false or decor.bt == false)) - or (decor and (decor.ft == 'ignore' or decor.bt == 'ignore')) - then - return {} - end - - local name = vim.api.nvim_buf_get_name(buf) - if name == '' then - name = '[No Name]' - else - name = vim.fn.fnamemodify(name, ':t') - end - - local parts = {} - if devicons_ok then - local ext = vim.fn.fnamemodify(name, ':e') - local icon, icon_color = - devicons.get_icon_color(name, ext, { default = true }) - if icon then - table.insert(parts, { icon .. ' ', guifg = icon_color }) - end - else - table.insert( - parts, - { icons.documents.file .. ' ', group = 'InclineTitle' } - ) - end - - table.insert(parts, { name, group = 'InclineTitle' }) - - if vim.bo[buf].modified then - table.insert(parts, { - ' ' .. icons.misc.circle, - group = 'InclineModified', - }) - end - - return parts - end, - }) - end, - }, - - { - 'uga-rosa/ccc.nvim', - cmd = { 'CccPick' }, - opts = function() - local ccc = require('ccc') - local p = ccc.picker - ccc.setup({ - -- win_opts = { border = UI.border }, - highlighter = { - auto_enable = false, - excludes = { - 'dart', - 'lazy', - 'orgagenda', - 'org', - 'NeogitStatus', - 'toggleterm', - }, - }, - }) - end, - }, - - { - 'Wansmer/symbol-usage.nvim', - event = 'LspAttach', - ---@diagnostic disable: undefined-field - config = function() - local symbol_usage = require('symbol-usage') - symbol_usage.setup({ - vt_position = 'end_of_line', - text_format = function(symbol) - local res = {} - local ins = table.insert - - local round_start = { '', 'SymbolUsageLeft' } - local round_end = { '', 'SymbolUsageRight' } - - if symbol.references then - local usage = symbol.references <= 1 and 'usage' or 'usages' - local num = symbol.references == 0 and 'no' or symbol.references - ins(res, round_start) - ins(res, { '󰌹 ', 'SymbolUsageRef' }) - ins(res, { ('%s %s'):format(num, usage), 'SymbolUsageContent' }) - ins(res, round_end) - end - - if symbol.definition then - if #res > 0 then table.insert(res, { ' ', 'NonText' }) end - ins(res, round_start) - ins(res, { '󰳽 ', 'SymbolUsageDef' }) - ins(res, { symbol.definition .. ' defs', 'SymbolUsageContent' }) - ins(res, round_end) - end - - if symbol.implementation then - if #res > 0 then table.insert(res, { ' ', 'NonText' }) end - ins(res, round_start) - ins(res, { '󰡱 ', 'SymbolUsageImpl' }) - ins( - res, - { symbol.implementation .. ' impls', 'SymbolUsageContent' } - ) - ins(res, round_end) - end - - return res - end, - }) - end, - }, - - { - 'mbbill/undotree', - cmd = 'UndotreeToggle', - keys = { - { 'u', 'UndotreeToggle', desc = 'undotree: toggle' }, - }, - config = function() - vim.g.undotree_TreeNodeShape = '◉' -- Alternative: '◉' ◦ - vim.g.undotree_SetFocusWhenToggle = 1 - end, - }, - - -- preview line - { 'nacro90/numb.nvim', event = 'CmdlineEnter', opts = {} }, - - { - 'HiPhish/rainbow-delimiters.nvim', - -- Match Akinsho's load order: define `vim.g.rainbow_delimiters` early, - -- then fill in strategy/query when the plugin loads. - event = { 'BufReadPost', 'BufNewFile' }, - init = function() - -- `vim.g` doesn't support mutating nested fields reliably; always reassign. - local rd = vim.g.rainbow_delimiters or {} - rd.highlight = rd.highlight - or { - 'RainbowDelimiterRed', - 'RainbowDelimiterYellow', - 'RainbowDelimiterBlue', - 'RainbowDelimiterOrange', - 'RainbowDelimiterGreen', - 'RainbowDelimiterViolet', - 'RainbowDelimiterCyan', - } - vim.g.rainbow_delimiters = rd - end, - config = function() - local ok, rainbow_delimiters = pcall(require, 'rainbow-delimiters') - if not ok then return end - - -- Akinsho-style: global strategy + default query name. - local rd = vim.g.rainbow_delimiters or {} - rd.strategy = { - [''] = rainbow_delimiters.strategy['global'], - } - rd.query = { - [''] = 'rainbow-delimiters', - html = 'rainbow-delimiters', -- enable our html tag query override - svelte = 'rainbow-delimiters', - } - vim.g.rainbow_delimiters = rd - - -- Palette-driven colors for the delimiter groups. - local api = vim.api - local group = - api.nvim_create_augroup('MrlRainbowDelimiters', { clear = true }) - - local function set_hls() - local pal = UI.palette or {} - local function as_hex(v, fallback) - if type(v) == 'string' or type(v) == 'number' then return v end - if type(v) == 'table' then return v.base or fallback end - return fallback - end - local colors = { - as_hex(pal.red, '#E06C75'), - as_hex(pal.light_yellow, '#E5C07B'), - as_hex(pal.blue, '#61AFEF'), - as_hex(pal.dark_orange, '#D19A66'), - as_hex(pal.green, '#98C379'), - as_hex(pal.magenta, '#C678DD'), - as_hex(pal.teal, '#56B6C2'), - } - local cur = vim.g.rainbow_delimiters or {} - local names = cur.highlight or {} - for i, name in ipairs(names) do - api.nvim_set_hl(0, name, { fg = colors[i] }) - end - end - - set_hls() - api.nvim_create_autocmd('ColorScheme', { - group = group, - callback = set_hls, - }) - end, - }, -} diff --git a/files/.config/nvim/lua/custom/plugins/whichkey.lua b/files/.config/nvim/lua/custom/plugins/whichkey.lua deleted file mode 100644 index bd59258..0000000 --- a/files/.config/nvim/lua/custom/plugins/whichkey.lua +++ /dev/null @@ -1,44 +0,0 @@ -return { - 'folke/which-key.nvim', - keys = { '', '' }, - cmd = 'WhichKey', - config = function() - local wk = require('which-key') - wk.setup({ - win = { - border = false, - wo = { - winhl = 'Normal:StatusLine,NormalFloat:StatusLine,FloatBorder:StatusLine', - }, - }, - layout = { align = 'center' }, - -- preset = 'modern', - }) - - -- Sync all WhichKey highlight bg to StatusLine - local function sync_hls() - local bg = - vim.api.nvim_get_hl(0, { name = 'StatusLine', link = false }).bg - if not bg then return end - bg = ('#%06x'):format(bg) - for _, name in ipairs({ - 'WhichKeyNormal', - 'WhichKey', - 'WhichKeyDesc', - 'WhichKeyGroup', - 'WhichKeySeparator', - 'WhichKeyValue', - 'WhichKeyBorder', - 'WhichKeyTitle', - }) do - local hl = vim.api.nvim_get_hl(0, { name = name, link = false }) - hl.bg = bg - hl.ctermbg = nil - vim.api.nvim_set_hl(0, name, hl) - end - end - - sync_hls() - vim.api.nvim_create_autocmd('ColorScheme', { callback = sync_hls }) - end, -} diff --git a/files/.config/nvim/lua/highlight.lua b/files/.config/nvim/lua/highlight.lua index 21bc41f..293cbfd 100644 --- a/files/.config/nvim/lua/highlight.lua +++ b/files/.config/nvim/lua/highlight.lua @@ -1,204 +1,2 @@ -local api, fmt = vim.api, string.format -local T = require('tools') -local augroup = T.augroup -local tint, blend, darken_hsl = T.tint, T.blend, T.darken_hsl - ----@alias HLAttrs {from: string, attr: "fg" | "bg", alter: integer} - ----@class HLData ----@field fg string ----@field bg string ----@field bold boolean ----@field italic boolean ----@field undercurl boolean ----@field underline boolean ----@field underdotted boolean ----@field underdashed boolean ----@field underdouble boolean ----@field strikethrough boolean ----@field reverse boolean ----@field nocombine boolean ----@field link string ----@field default boolean - ----@class HLArgs ----@field blend integer? ----@field fg (string | HLAttrs)? ----@field bg (string | HLAttrs)? ----@field sp (string | HLAttrs)? ----@field bold boolean? ----@field italic boolean? ----@field undercurl boolean? ----@field underline boolean? ----@field underdotted boolean? ----@field underdashed boolean? ----@field underdouble boolean? ----@field strikethrough boolean? ----@field reverse boolean? ----@field nocombine boolean? ----@field link string? ----@field default boolean? ----@field clear boolean? ----@field inherit string? - -local enable_italics = true -local attrs = { - fg = true, - bg = true, - sp = true, - blend = true, - bold = true, - italic = enable_italics, - standout = true, - underline = true, - undercurl = true, - underdouble = true, - underdotted = true, - underdashed = true, - strikethrough = true, - reverse = true, - nocombine = true, - link = true, - default = true, -} - ----@private ----@param opts {name: string?, link: boolean?}? ----@param ns integer? ----@return HLData -local function get_hl_as_hex(opts, ns) - ns, opts = ns or 0, opts or {} - opts.link = opts.link ~= nil and opts.link or false - local hl = api.nvim_get_hl(ns, opts) - hl.fg = hl.fg and ('#%06x'):format(hl.fg) - hl.bg = hl.bg and ('#%06x'):format(hl.bg) - return hl -end - ----Get the value a highlight group whilst handling errors, fallbacks as well as returning a gui value ----If no attribute is specified return the entire highlight table ----in the right format ----@param group string ----@param attribute string? ----@param fallback string? ----@return string ----@overload fun(group: string): HLData -local function get(group, attribute, fallback) - assert(group, 'cannot get a highlight without specifying a group name') - local data = get_hl_as_hex({ name = group }) - if not attribute then return data end - - assert( - attrs[attribute], - ('the attribute passed in is invalid: %s'):format(attribute) - ) - local color = data[attribute] or fallback - if not color then return 'NONE' end - return color -end - ----@param hl string | HLAttrs ----@param attr string ----@return HLData -local function resolve_from_attribute(hl, attr) - if type(hl) ~= 'table' or not hl.from then return hl end - local colour = get(hl.from, hl.attr or attr) - if hl.alter then colour = tint(colour, hl.alter) end - return colour -end - ---- Sets a neovim highlight with some syntactic sugar. It takes a highlight table and converts ---- any highlights specified as `GroupName = {fg = { from = 'group'}}` into the underlying colour ---- by querying the highlight property of the from group so it can be used when specifying highlights ---- as a shorthand to derive the right colour. ---- For example: ---- ```lua ---- M.set({ MatchParen = {fg = {from = 'ErrorMsg'}}}) ---- ``` ---- This will take the foreground colour from ErrorMsg and set it to the foreground of MatchParen. ---- NOTE: this function must NOT mutate the options table as these are re-used when the colorscheme is updated ---- ----@param name string ----@param opts HLArgs ----@overload fun(ns: integer, name: string, opts: HLArgs) -local function set(ns, name, opts) - if type(ns) == 'string' and type(name) == 'table' then - opts, name, ns = name, ns, 0 - end - - vim.validate('opts', opts, 'table') - vim.validate('name', name, 'string') - vim.validate('ns', ns, 'number') - - local hl = opts.clear and {} or get_hl_as_hex({ name = opts.inherit or name }) - for attribute, hl_data in pairs(opts) do - local new_data = resolve_from_attribute(hl_data, attribute) - if attrs[attribute] then hl[attribute] = new_data end - end - - T.pcall(fmt('setting highlight "%s"', name), api.nvim_set_hl, ns, name, hl) -end - ----Apply a list of highlights ----@param hls {[string]: HLArgs}[] ----@param namespace integer? -local function all(hls, namespace) - vim.iter(hls):each(function(hl) set(namespace or 0, next(hl)) end) -end - ---- Set window local highlights ----@param name string ----@param win_id number ----@param hls HLArgs[] -local function set_winhl(name, win_id, hls) - local namespace = api.nvim_create_namespace(name) - all(hls, namespace) - api.nvim_win_set_hl_ns(win_id, namespace) -end - ---------------------------------------------------------------------------------- --- Plugin highlights ---------------------------------------------------------------------------------- ---- Takes the overrides for each theme and merges the lists, avoiding duplicates and ensuring ---- priority is given to specific themes rather than the fallback ----@param theme { [string]: HLArgs[] } ----@return HLArgs[] -local function add_theme_overrides(theme) - local res, seen = {}, {} - local list = vim.list_extend(theme[vim.g.colors_name] or {}, theme['*'] or {}) - for _, hl in ipairs(list) do - local n = next(hl) - if not seen[n] then res[#res + 1] = hl end - seen[n] = true - end - return res -end ----Apply highlights for a plugin and refresh on colorscheme change ----@param name string plugin name ----@param opts HLArgs[] | { theme: table } -local function plugin(name, opts) - -- Options can be specified by theme name so check if they have been or there is a general - -- definition otherwise use the opts as is - if opts.theme then - opts = add_theme_overrides(opts.theme) - if not next(opts) then return end - end - vim.schedule(function() all(opts) end) - augroup(fmt('%sHighlightOverrides', name:gsub('^%l', string.upper)), { - event = 'ColorScheme', - command = function() - vim.schedule(function() all(opts) end) - end, - }) -end - -return { - get = get, - set = set, - all = all, - tint = tint, - blend = blend, - darken_hsl = darken_hsl, - plugin = plugin, - set_winhl = set_winhl, -} +-- highlight.lua: merged into tools.lua — this shim keeps old callers working +return require('tools').hl diff --git a/files/.config/nvim/lua/lazyloader.lua b/files/.config/nvim/lua/lazyloader.lua deleted file mode 100644 index 9b3c9c1..0000000 --- a/files/.config/nvim/lua/lazyloader.lua +++ /dev/null @@ -1,92 +0,0 @@ --- [[ Install `lazy.nvim` plugin manager ]] --- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info -local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' -if not vim.loop.fs_stat(lazypath) then - local lazyrepo = 'https://github.com/folke/lazy.nvim.git' - vim.fn.system({ - 'git', - 'clone', - '--filter=blob:none', - '--branch=stable', - lazyrepo, - lazypath, - }) -end ---@diagnostic disable-next-line: undefined-field -vim.opt.rtp:prepend(lazypath) - --- Ensure icons are available, use defaults if not -local icons = require('tools').ui.icons - -require('lazy').setup({ - { import = 'custom.plugins' }, -}, { - defaults = { - lazy = true, - cond = not vim.g.started_by_firenvim, - }, - install = { - missing = true, - -- colorscheme = { 'gruvbox' }, - -- colorscheme = { 'horizon' }, - -- colorscheme = { 'rose-pine' }, - }, - browser = 'brave', - diff = { - cmd = 'diffview.nvim', - }, - checker = { - enabled = true, - notify = false, - }, - - dev = { - path = '/Users/marcos/Projects/personal/', - patterns = { 'marromlam' }, - fallback = true, - }, - -- profiling = { - -- loader = true, - -- require = true, - -- }, - performance = { - cache = { - enabled = true, - disable_events = { 'UiEnter' }, - }, - reset_packpath = true, - rtp = { - reset = true, - disabled_plugins = { - 'matchit', - 'matchparen', - 'tarPlugin', - 'tohtml', - 'tutor', - 'man', - 'spellfile', - }, - }, - }, - - ui = { - border = 'rounded', - backdrop = false, -- Disable backdrop dimming - -- If you are using a Nerd Font: set icons to an empty table which will use the - -- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table - icons = { - cmd = icons.cmd, - config = icons.config, - event = icons.calendar, - ft = icons.folder, - init = icons.settings, - keys = icons.key, - plugin = icons.box, - runtime = icons.runtime, - require = icons.moon, - source = icons.source, - start = icons.rocket, - task = icons.task, - lazy = icons.sleep, - }, - }, -}) diff --git a/files/.config/nvim/lua/packloader.lua b/files/.config/nvim/lua/packloader.lua new file mode 100644 index 0000000..2254515 --- /dev/null +++ b/files/.config/nvim/lua/packloader.lua @@ -0,0 +1,236 @@ +-- lua/packloader.lua + +-- Firenvim: skip the full plugin stack +if vim.g.started_by_firenvim then return end + +vim.g.db_ui_use_nerd_fonts = 1 + +-- --------------------------------------------------------------------------- +-- Plugin installation via vim.pack +-- --------------------------------------------------------------------------- +vim.pack.add({ + -- Colorschemes + 'https://github.com/vague2k/vague.nvim', + + -- LSP + 'https://github.com/neovim/nvim-lspconfig', + 'https://github.com/mason-org/mason.nvim', + 'https://github.com/mason-org/mason-lspconfig.nvim', + 'https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim', + 'https://github.com/j-hui/fidget.nvim', + 'https://github.com/folke/lazydev.nvim', + 'https://github.com/stevanmilic/nvim-lspimport', + 'https://github.com/simrat39/symbols-outline.nvim', + 'https://github.com/rachartier/tiny-inline-diagnostic.nvim', + 'https://github.com/iamkarasik/sonarqube.nvim', + 'https://github.com/kosayoda/nvim-lightbulb', + 'https://github.com/DNLHC/glance.nvim', + 'https://github.com/smjonas/inc-rename.nvim', + + -- Completion + 'https://github.com/saghen/blink.cmp', + 'https://github.com/rafamadriz/friendly-snippets', + 'https://github.com/onsails/lspkind.nvim', + 'https://github.com/Kaiser-Yang/blink-cmp-avante', + 'https://github.com/MeanderingProgrammer/render-markdown.nvim', + + -- Treesitter + 'https://github.com/nvim-treesitter/nvim-treesitter', + 'https://github.com/nvim-treesitter/nvim-treesitter-textobjects', + 'https://github.com/nvim-treesitter/nvim-treesitter-context', + 'https://github.com/JoosepAlviste/nvim-ts-context-commentstring', + 'https://github.com/Wansmer/treesj', + 'https://github.com/windwp/nvim-ts-autotag', + + -- Fuzzy finder + 'https://github.com/ibhagwan/fzf-lua', + + -- Git + 'https://github.com/lewis6991/gitsigns.nvim', + 'https://github.com/ruifm/gitlinker.nvim', + 'https://github.com/akinsho/git-conflict.nvim', + 'https://github.com/tpope/vim-fugitive', + 'https://github.com/sindrets/diffview.nvim', + 'https://github.com/isakbm/gitgraph.nvim', + 'https://github.com/ThePrimeagen/git-worktree.nvim', + + -- UI + 'https://github.com/akinsho/bufferline.nvim', + 'https://github.com/lukas-reineke/indent-blankline.nvim', + 'https://github.com/SmiteshP/nvim-navic', + 'https://github.com/b0o/incline.nvim', + 'https://github.com/uga-rosa/ccc.nvim', + 'https://github.com/Wansmer/symbol-usage.nvim', + 'https://github.com/mbbill/undotree', + 'https://github.com/nacro90/numb.nvim', + 'https://github.com/HiPhish/rainbow-delimiters.nvim', + + -- Noice + 'https://github.com/folke/noice.nvim', + 'https://github.com/MunifTanjim/nui.nvim', + + -- Mini + 'https://github.com/echasnovski/mini.ai', + 'https://github.com/echasnovski/mini.align', + 'https://github.com/echasnovski/mini.pairs', + 'https://github.com/echasnovski/mini.surround', + 'https://github.com/echasnovski/mini.splitjoin', + 'https://github.com/echasnovski/mini.move', + 'https://github.com/echasnovski/mini.icons', + 'https://github.com/echasnovski/mini.diff', + 'https://github.com/echasnovski/mini.trailspace', + 'https://github.com/echasnovski/mini.misc', + 'https://github.com/echasnovski/mini.bufremove', + + -- Format / Lint + 'https://github.com/stevearc/conform.nvim', + 'https://github.com/mfussenegger/nvim-lint', + + -- Debug + 'https://github.com/mfussenegger/nvim-dap', + 'https://github.com/rcarriga/nvim-dap-ui', + 'https://github.com/nvim-neotest/nvim-nio', + 'https://github.com/jay-babu/mason-nvim-dap.nvim', + 'https://github.com/leoluz/nvim-dap-go', + + -- Testing + 'https://github.com/nvim-neotest/neotest', + 'https://github.com/rcarriga/neotest-plenary', + 'https://github.com/nvim-neotest/neotest-python', + + -- Navigation + 'https://github.com/stevearc/oil.nvim', + 'https://github.com/cbochs/grapple.nvim', + + -- Terminal + 'https://github.com/akinsho/toggleterm.nvim', + + -- Copilot / AI + 'https://github.com/zbirenbaum/copilot.lua', + 'https://github.com/olimorris/codecompanion.nvim', + 'https://github.com/ravitemer/mcphub.nvim', + 'https://github.com/folke/sidekick.nvim', + + -- Database + 'https://github.com/tpope/vim-dadbod', + 'https://github.com/kristijanhusak/vim-dadbod-ui', + 'https://github.com/kristijanhusak/vim-dadbod-completion', + + -- Todo / Folke + 'https://github.com/folke/todo-comments.nvim', + 'https://github.com/folke/trouble.nvim', + + -- Whichkey + 'https://github.com/folke/which-key.nvim', + + -- Comment + 'https://github.com/numToStr/Comment.nvim', + + -- Obsidian + 'https://github.com/epwalsh/obsidian.nvim', + + -- REPL + 'https://github.com/marromlam/kitty-repl.nvim', + + -- Remote / containers + 'https://codeberg.org/esensar/nvim-dev-container', + + -- Filetype support + 'https://github.com/plasticboy/vim-markdown', + 'https://github.com/3rd/image.nvim', + 'https://github.com/mtdl9/vim-log-highlighting', + 'https://github.com/raivivek/vim-snakemake', + 'https://github.com/fladson/vim-kitty', + 'https://github.com/tpope/vim-apathy', + 'https://github.com/saecki/crates.nvim', + 'https://github.com/lbrayner/vim-rzip', + 'https://github.com/hat0uma/csvview.nvim', + 'https://github.com/ledger/vim-ledger', + 'https://github.com/Kicamon/markdown-table-mode.nvim', + 'https://github.com/lervag/vimtex', + + -- Gaming / misc + 'https://github.com/meznaric/key-analyzer.nvim', + + -- Init / misc plugins + 'https://github.com/nvim-lua/plenary.nvim', + 'https://github.com/jghauser/fold-cycle.nvim', + 'https://github.com/andrewferrier/debugprint.nvim', + 'https://github.com/marromlam/sailor.vim', + 'https://github.com/bogado/file-line', + 'https://github.com/will133/vim-dirdiff', + 'https://github.com/tpope/vim-sleuth', + 'https://github.com/tpope/vim-surround', + 'https://github.com/tpope/vim-repeat', + + -- Bufferline dep + 'https://github.com/nvim-lua/plenary.nvim', +}) + +-- --------------------------------------------------------------------------- +-- Load configuration for each pack (imperative setup) +-- --------------------------------------------------------------------------- + +-- Always-on / UI (load immediately) +require('packs.colorscheme') +require('packs.mini') +require('packs.noice') +require('packs.bufferline') +require('packs.whichkey') + +-- Fuzzy finder (load immediately for keymaps) +require('packs.fzf') + +-- Navigation (keymaps registered immediately) +require('packs.navigation') + +-- Terminal +require('packs.terminal') + +-- REPL +require('packs.repl') + +-- Copilot / AI (deferred setup via autocmd in each file) +require('packs.copilot') + +-- Database +require('packs.dadbod') + +-- Gaming / misc +require('packs.gaming') + +-- Obsidian (keymaps only, lazy setup) +require('packs.obsidian') + +-- Remote +require('packs.remote') + +-- Comment (on BufReadPre) +require('packs.comment') + +-- Todo / Trouble +require('packs.todo') + +-- Filetype plugins +require('packs.filetype') + +-- Treesitter (on BufReadPost) +require('packs.treesitter') + +-- Heavy plugins: load on BufReadPre/BufNewFile +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlPackloaderHeavy', { clear = true }), + callback = function() + require('packs.lsp') + require('packs.git') + require('packs.ui') + require('packs.format') + require('packs.linting') + require('packs.testing') + require('packs.debug') + require('packs.init') + end, +}) + +-- vim: ts=2 sts=2 sw=2 et fdm=marker diff --git a/files/.config/nvim/lua/packs/bufferline.lua b/files/.config/nvim/lua/packs/bufferline.lua new file mode 100644 index 0000000..a79735c --- /dev/null +++ b/files/.config/nvim/lua/packs/bufferline.lua @@ -0,0 +1,155 @@ +-- packs/bufferline.lua + +local bufferline = require('bufferline') +local UI = require('tools').ui + +-- Derive colours from live highlight groups so every theme looks great. +local function hl_hex(name, attr, fallback) + local ok, h = + pcall(vim.api.nvim_get_hl, 0, { name = name, link = false }) + if ok and h and h[attr] then return ('#%06x'):format(h[attr]) end + return fallback +end + +local NUMS = + { '➊', '➋', '➌', '➍', '➎', '➏', '➐', '➑', '➒', '➓' } + +local function setup() + local pal = UI.palette or {} + local bg = hl_hex('StatusLine', 'bg', 'NONE') + local bg_sel = hl_hex('Normal', 'bg', '#1e1e2e') + local fg_sel = hl_hex('Normal', 'fg', '#cdd6f4') + local fg_dim = pal.comment_grey or hl_hex('Comment', 'fg', '#6c7086') + local accent = pal.blue or hl_hex('Function', 'fg', '#82aaff') + + bufferline.setup({ + highlights = { + -- Tabline gutter & inactive tabs share the statusline bg + fill = { bg = bg }, + background = { bg = bg, fg = fg_dim }, + tab = { bg = bg, fg = fg_dim }, + tab_close = { bg = bg, fg = fg_dim }, + close_button = { bg = bg, fg = fg_dim }, + + -- Selected buffer pops out with normal bg + buffer_selected = { + bg = bg_sel, + fg = fg_sel, + bold = true, + italic = false, + }, + close_button_selected = { bg = bg_sel, fg = fg_dim }, + tab_selected = { bg = bg, fg = fg_sel, bold = true }, + + -- Visible (non-focused split) buffer + buffer_visible = { bg = bg, fg = fg_dim }, + + -- Powerline triangle separators + separator = { bg = bg, fg = bg_sel }, + separator_selected = { bg = bg_sel, fg = bg }, + separator_visible = { bg = bg, fg = bg_sel }, + offset_separator = { bg = bg, fg = bg_sel }, + + -- Indicator line under selected tab uses the accent colour + indicator_selected = { fg = accent, bg = bg_sel }, + + -- Numbers + numbers = { bg = bg, fg = fg_dim }, + numbers_selected = { bg = bg_sel, fg = fg_sel }, + + -- Pick + pick = { bg = bg, fg = accent, bold = true, italic = true }, + pick_selected = { + bg = bg_sel, + fg = accent, + bold = true, + italic = true, + }, + }, + + options = { + style_preset = bufferline.style_preset.minimal, + separator_style = { '', '' }, + mode = 'buffers', + custom_areas = { + right = function() + local tabs = vim.api.nvim_list_tabpages() + if #tabs <= 1 then return {} end + local result = {} + local cur = vim.api.nvim_get_current_tabpage() + for i, tab in ipairs(tabs) do + local sym = NUMS[i] or tostring(i) + local hl = tab == cur and 'BufferLineTabSelected' + or 'BufferLineTab' + table.insert(result, { text = ' ' .. sym .. ' ', link = hl }) + end + return result + end, + }, + sort_by = 'insert_after_current', + move_wraps_at_ends = true, + right_mouse_command = 'vert sbuffer %d', + show_close_icon = false, + show_buffer_close_icons = false, + show_tab_indicators = false, + indicator = { style = 'none' }, + + custom_filter = function(buf_number) + local name = vim.api.nvim_buf_get_name(buf_number) + if name:match('^fugitive://') then return false end + if name == '' then return false end + return true + end, + + hover = { enabled = true, delay = 150, reveal = { 'close' } }, + + offsets = { + { + text = ' EXPLORER', + filetype = 'neo-tree', + highlight = 'PanelHeading', + separator = false, + text_align = 'left', + }, + { + text = ' UNDOTREE', + filetype = 'undotree', + highlight = 'PanelHeading', + separator = false, + text_align = 'left', + }, + { + text = '󰆼 DATABASE', + filetype = 'dbui', + highlight = 'PanelHeading', + separator = false, + text_align = 'left', + }, + { + text = ' DIFF VIEW', + filetype = 'DiffviewFiles', + highlight = 'PanelHeading', + separator = false, + text_align = 'left', + }, + }, + }, + }) +end + +setup() +vim.api.nvim_create_autocmd('ColorScheme', { + group = vim.api.nvim_create_augroup('MrlBufferline', { clear = true }), + callback = setup, +}) + +-- Keymaps +local map = function(lhs, rhs, desc) + vim.keymap.set('n', lhs, rhs, { desc = desc }) +end +map('[b', 'BufferLineMoveNext', 'bufferline: move next') +map(']b', 'BufferLineMovePrev', 'bufferline: move prev') +map('gbb', 'BufferLinePick', 'bufferline: pick buffer') +map('gbd', 'BufferLinePickClose', 'bufferline: delete buffer') +map('', 'BufferLineCyclePrev', 'bufferline: prev') +map('', 'BufferLineCycleNext', 'bufferline: next') diff --git a/files/.config/nvim/lua/packs/colorscheme.lua b/files/.config/nvim/lua/packs/colorscheme.lua new file mode 100644 index 0000000..07273f0 --- /dev/null +++ b/files/.config/nvim/lua/packs/colorscheme.lua @@ -0,0 +1,30 @@ +-- packs/colorscheme.lua + +local is_dev = vim.fn.isdirectory( + '/Users/marcos/Workspaces/personal/theme-builder' +) == 1 + +if not is_dev then + require('vague').setup({ + transparent = false, + style = { + boolean = 'none', + number = 'none', + float = 'none', + error = 'none', + comments = 'italic', + conditionals = 'none', + functions = 'none', + headings = 'bold', + operators = 'none', + strings = 'none', + variables = 'none', + keywords = 'italic', + }, + }) + vim.cmd('colorscheme vague') +else + -- BEGIN_NEOVIM_THEME + vim.cmd.colorscheme('amberglow') + -- END_NEOVIM_THEME +end diff --git a/files/.config/nvim/lua/packs/comment.lua b/files/.config/nvim/lua/packs/comment.lua new file mode 100644 index 0000000..38c039c --- /dev/null +++ b/files/.config/nvim/lua/packs/comment.lua @@ -0,0 +1,19 @@ +-- packs/comment.lua + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlComment', { clear = true }), + callback = function() + -- Disable the default CursorHold autocmd; Comment.nvim calls it via pre_hook only + require('ts_context_commentstring').setup({ enable_autocmd = false }) + + local comment = require('Comment') + local ts_context_commentstring = + require('ts_context_commentstring.integrations.comment_nvim') + + -- enable comment with tsx/jsx/svelte/html support + comment.setup({ + pre_hook = ts_context_commentstring.create_pre_hook(), + }) + end, +}) diff --git a/files/.config/nvim/lua/custom/plugins/completion.lua b/files/.config/nvim/lua/packs/completion.lua similarity index 80% rename from files/.config/nvim/lua/custom/plugins/completion.lua rename to files/.config/nvim/lua/packs/completion.lua index 4b42670..9b73e95 100644 --- a/files/.config/nvim/lua/custom/plugins/completion.lua +++ b/files/.config/nvim/lua/packs/completion.lua @@ -1,52 +1,36 @@ -local highlight = require('highlight') -local ui = require('tools').ui +-- packs/completion.lua -return { - { - 'saghen/blink.cmp', - event = 'InsertEnter', - cond = not vim.g.use_cmp, - disable = vim.g.use_cmp, - dependencies = { - 'rafamadriz/friendly-snippets', - 'onsails/lspkind.nvim', -- vs-code like pictograms - 'Kaiser-Yang/blink-cmp-avante', - { - 'MeanderingProgrammer/render-markdown.nvim', - dependencies = { - 'nvim-treesitter/nvim-treesitter', - }, - opts = { - file_types = { 'markdown', 'Avante' }, - completions = { - blink = { enabled = true }, - }, - }, - }, - }, - version = '*', - init = function() - highlight.plugin('blink', { - -- Keep completion popups consistent with float styling - { BlinkCmpMenuBorder = { link = 'FloatBorder' } }, - { BlinkCmpDocBorder = { link = 'FloatBorder' } }, - { BlinkCmpMenu = { link = 'NormalFloat' } }, - { BlinkCmpDoc = { link = 'NormalFloat' } }, - { BlinkCmpDocCursorLine = { link = 'CursorLine' } }, - }) +local highlight = require('highlight') - -- User command to toggle ghost text - vim.api.nvim_create_user_command('BlinkToggleGhostText', function() - local blink = require('blink.cmp') - local enabled = blink.config.completion.ghost_text.enabled - blink.config.completion.ghost_text.enabled = not enabled - vim.notify( - 'Ghost text ' .. (enabled and 'disabled' or 'enabled'), - vim.log.levels.INFO - ) - end, { desc = 'Toggle blink.cmp ghost text' }) - end, - opts = { +if vim.g.use_cmp then return end + +-- Run init-equivalent code immediately (highlight setup + user command) +highlight.plugin('blink', { + -- Keep completion popups consistent with float styling + { BlinkCmpMenuBorder = { link = 'FloatBorder' } }, + { BlinkCmpDocBorder = { link = 'FloatBorder' } }, + { BlinkCmpMenu = { link = 'NormalFloat' } }, + { BlinkCmpDoc = { link = 'NormalFloat' } }, + { BlinkCmpDocCursorLine = { link = 'CursorLine' } }, +}) + +-- User command to toggle ghost text +vim.api.nvim_create_user_command('BlinkToggleGhostText', function() + local blink = require('blink.cmp') + local enabled = blink.config.completion.ghost_text.enabled + blink.config.completion.ghost_text.enabled = not enabled + vim.notify( + 'Ghost text ' .. (enabled and 'disabled' or 'enabled'), + vim.log.levels.INFO + ) +end, { desc = 'Toggle blink.cmp ghost text' }) + +-- Setup blink.cmp on InsertEnter +vim.api.nvim_create_autocmd('InsertEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlCompletion', { clear = true }), + callback = function() + require('blink.cmp').setup({ -- Custom keymap keymap = { preset = 'none', @@ -256,7 +240,14 @@ return { auto_brackets = { enabled = true }, }, }, - }, - opts_extend = { 'sources.default' }, - }, -} + }) + + -- Also setup render-markdown for markdown/Avante filetypes + require('render-markdown').setup({ + file_types = { 'markdown', 'Avante' }, + completions = { + blink = { enabled = true }, + }, + }) + end, +}) diff --git a/files/.config/nvim/lua/packs/copilot.lua b/files/.config/nvim/lua/packs/copilot.lua new file mode 100644 index 0000000..7df82b1 --- /dev/null +++ b/files/.config/nvim/lua/packs/copilot.lua @@ -0,0 +1,184 @@ +-- packs/copilot.lua + +-- copilot.lua: setup on InsertEnter +vim.api.nvim_create_autocmd('InsertEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlCopilot', { clear = true }), + callback = function() + require('copilot').setup({ + panel = { + enabled = true, + auto_refresh = false, + keymap = { + jump_prev = '[[', + jump_next = ']]', + accept = '', + refresh = 'gr', + open = '', + }, + layout = { + position = 'bottom', -- | top | left | right + ratio = 0.4, + }, + }, + suggestion = { + enabled = true, + auto_trigger = true, + hide_during_completion = true, + debounce = 75, + keymap = { + accept = '', + accept_word = false, + accept_line = false, + next = '', + prev = '', + dismiss = '', + }, + }, + filetypes = { + yaml = false, + markdown = false, + help = false, + gitcommit = false, + gitrebase = false, + hgcommit = false, + svn = false, + cvs = false, + ['.'] = false, + }, + copilot_node_command = 'node', -- Node.js version must be > 18.x + server_opts_overrides = {}, + }) + end, +}) + +-- codecompanion: setup on command invocation (cmd-loaded) +require('codecompanion').setup({ + strategies = { + chat = { + adapter = 'copilot', + }, + inline = { + adapter = 'copilot', + }, + agent = { + adapter = 'copilot', + }, + }, + adapters = { + my_openai = function() + return require('codecompanion.adapters').extend( + 'openai_compatible', + { + env = { + url = 'http://127.0.0.1:11434', -- optional: default value is ollama url http://127.0.0.1:11434 + -- api_key = 'OpenAI_API_KEY', -- optional: if your endpoint is authenticated + -- chat_url = '/v1/chat/completions', -- optional: default value, override if different + -- models_endpoint = '/v1/models', -- optional: attaches to the end of the URL to form the endpoint to retrieve models + }, + schema = { + model = { + -- default = 'deepseek-r1:8b', + default = 'deepseek-r1:1.5b', + }, + temperature = { + order = 2, + mapping = 'parameters', + type = 'number', + optional = true, + default = 0.8, + desc = 'What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or top_p but not both.', + validate = function(n) + return n >= 0 and n <= 2, 'Must be between 0 and 2' + end, + }, + max_completion_tokens = { + order = 3, + mapping = 'parameters', + type = 'integer', + optional = true, + default = nil, + desc = 'An upper bound for the number of tokens that can be generated for a completion.', + validate = function(n) + return n > 0, 'Must be greater than 0' + end, + }, + stop = { + order = 4, + mapping = 'parameters', + type = 'string', + optional = true, + default = nil, + desc = 'Sets the stop sequences to use. When this pattern is encountered the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.', + validate = function(s) + return s:len() > 0, 'Cannot be an empty string' + end, + }, + logit_bias = { + order = 5, + mapping = 'parameters', + type = 'map', + optional = true, + default = nil, + desc = 'Modify the likelihood of specified tokens appearing in the completion. Maps tokens (specified by their token ID) to an associated bias value from -100 to 100. Use https://platform.openai.com/tokenizer to find token IDs.', + subtype_key = { + type = 'integer', + }, + subtype = { + type = 'integer', + validate = function(n) + return n >= -100 and n <= 100, + 'Must be between -100 and 100' + end, + }, + }, + }, + } + ) + end, + }, +}) + +-- mcphub: lazy, only loaded when explicitly required +-- (setup happens on demand) + +-- sidekick.nvim keymaps +vim.keymap.set('i', '', function() + if not require('sidekick').nes_jump_or_apply() then return '' end +end, { expr = true, desc = 'Goto/Apply Next Edit Suggestion' }) + +vim.keymap.set('n', 'aa', function() require('sidekick.cli').toggle() end, { + desc = 'Sidekick Toggle CLI', +}) +vim.keymap.set('n', 'as', function() require('sidekick.cli').select() end, { + desc = 'Select CLI', +}) +vim.keymap.set({ 'x', 'n' }, 'at', function() + require('sidekick.cli').send({ msg = '{this}' }) +end, { desc = 'Send This' }) +vim.keymap.set('x', 'av', function() + require('sidekick.cli').send({ msg = '{selection}' }) +end, { desc = 'Send Visual Selection' }) +vim.keymap.set({ 'n', 'x' }, 'ap', function() + require('sidekick.cli').prompt() +end, { desc = 'Sidekick Select Prompt' }) +vim.keymap.set({ 'n', 'x', 'i', 't' }, '', function() + require('sidekick.cli').focus() +end, { desc = 'Sidekick Switch Focus' }) +vim.keymap.set('n', 'ac', function() + require('sidekick.cli').toggle({ name = 'claude', focus = true }) +end, { desc = 'Sidekick Toggle Claude' }) + +-- Defer sidekick setup slightly to keep startup fast +vim.defer_fn(function() + require('sidekick').setup({ + cli = { + mux = { + enabled = true, + create = 'terminal', -- Folke's pattern: create terminal instead of window + backend = 'tmux', -- Using tmux (Folke commented out zellij) + }, + tools = {}, + }, + }) +end, 100) diff --git a/files/.config/nvim/lua/packs/dadbod.lua b/files/.config/nvim/lua/packs/dadbod.lua new file mode 100644 index 0000000..e92b882 --- /dev/null +++ b/files/.config/nvim/lua/packs/dadbod.lua @@ -0,0 +1,4 @@ +-- packs/dadbod.lua + +-- Your DBUI configuration (init equivalent - runs immediately) +vim.g.db_ui_use_nerd_fonts = 1 diff --git a/files/.config/nvim/lua/packs/debug.lua b/files/.config/nvim/lua/packs/debug.lua new file mode 100644 index 0000000..b32a848 --- /dev/null +++ b/files/.config/nvim/lua/packs/debug.lua @@ -0,0 +1,83 @@ +-- packs/debug.lua + +-- Keymaps (registered immediately so they work as soon as the pack loads) +vim.keymap.set('n', '', function() require('dap').continue() end, { + desc = 'Debug: Start/Continue', +}) +vim.keymap.set('n', '', function() require('dap').step_into() end, { + desc = 'Debug: Step Into', +}) +vim.keymap.set('n', '', function() require('dap').step_over() end, { + desc = 'Debug: Step Over', +}) +vim.keymap.set('n', '', function() require('dap').step_out() end, { + desc = 'Debug: Step Out', +}) +vim.keymap.set('n', 'B', function() require('dap').toggle_breakpoint() end, { + desc = 'Debug: Toggle Breakpoint', +}) +vim.keymap.set('n', '', function() require('dapui').toggle() end, { + desc = 'Debug: See last session result.', +}) + +-- Full setup deferred until BufReadPre (heavy plugins) +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlDebug', { clear = true }), + callback = function() + local dap = require('dap') + local dapui = require('dapui') + + require('mason-nvim-dap').setup({ + -- Makes a best effort to setup the various debuggers with + -- reasonable debug configurations + automatic_setup = true, + + -- You can provide additional configuration to the handlers, + -- see mason-nvim-dap README for more information + handlers = {}, + + -- You'll need to check that you have the required things installed + -- online, please don't ask me how to install them :) + ensure_installed = { + -- Update this to ensure that you have the debuggers for the langs you want + 'delve', + 'debugpy', + }, + }) + + -- Dap UI setup + -- For more information, see |:help nvim-dap-ui| + dapui.setup({ + -- Set icons to characters that are more likely to work in every terminal. + -- Feel free to remove or use ones that you like more! :) + -- Don't feel like these are good choices. + icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, + controls = { + icons = { + pause = '', + play = '', + step_into = '󱆭', + step_over = '', + step_out = '󰙣', + step_back = '󱆮', + run_last = '󰙡', + terminate = '', + disconnect = '', + }, + }, + }) + + 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 + + -- Install golang specific config + require('dap-go').setup() + end, +}) + +-- rest-nvim is disabled (cond = false) +-- if false then +-- require('rest-nvim').setup() +-- end diff --git a/files/.config/nvim/lua/packs/filetype.lua b/files/.config/nvim/lua/packs/filetype.lua new file mode 100644 index 0000000..b9fdb9f --- /dev/null +++ b/files/.config/nvim/lua/packs/filetype.lua @@ -0,0 +1,104 @@ +-- packs/filetype.lua + +-- markdown support (plasticboy/vim-markdown) - ft triggered by vim automatically + +-- image.nvim for markdown/neorg/org +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'markdown', 'neorg', 'org' }, + once = true, + group = vim.api.nvim_create_augroup('MrlImage', { clear = true }), + callback = function() + require('image').setup({}) + end, +}) + +-- crates.nvim for Cargo.toml +vim.api.nvim_create_autocmd('BufRead', { + pattern = 'Cargo.toml', + once = true, + group = vim.api.nvim_create_augroup('MrlCrates', { clear = true }), + callback = function() + require('crates').setup() + end, +}) + +-- csvview.nvim for csv files +vim.api.nvim_create_autocmd('FileType', { + pattern = 'csv', + once = true, + group = vim.api.nvim_create_augroup('MrlCsvView', { clear = true }), + callback = function() + require('csvview').setup({ + parser = { comments = { '#', '//' } }, + keymaps = { + -- Text objects for selecting fields + textobject_field_inner = { 'if', mode = { 'o', 'x' } }, + textobject_field_outer = { 'af', mode = { 'o', 'x' } }, + -- Excel-like navigation: + jump_next_field_end = { '', mode = { 'n', 'v' } }, + jump_prev_field_end = { '', mode = { 'n', 'v' } }, + jump_next_row = { '', mode = { 'n', 'v' } }, + jump_prev_row = { '', mode = { 'n', 'v' } }, + }, + }) + end, +}) + +-- ledger.vim for ledger filetypes +vim.api.nvim_create_autocmd('FileType', { + pattern = 'ledger', + once = true, + group = vim.api.nvim_create_augroup('MrlLedger', { clear = true }), + callback = function() + vim.cmd([[ + au BufNewFile,BufRead *.ldg,*.ledger setf ledger | comp ledger + let g:ledger_maxwidth = 120 + let g:ledger_fold_blanks = 1 + function LedgerSort() + :%! ledger -f - print --sort 'date, amount' + :%LedgerAlign + endfunction + command LedgerSort call LedgerSort() + ]]) + end, +}) + +-- markdown-table-mode for markdown/neorg/org +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'markdown', 'neorg', 'org' }, + once = true, + group = vim.api.nvim_create_augroup('MrlMarkdownTable', { clear = true }), + callback = function() + require('markdown-table-mode').setup({ + filetype = { + '*.md', + }, + options = { + insert = true, -- when typing "|" + insert_leave = true, -- when leaving insert + pad_separator_line = false, -- add space in separator line + alig_style = 'default', -- default, left, center, right + }, + }) + end, +}) + +-- nvim-docx (dev plugin, lazy=false in original - load immediately) +-- vim.keymap.set('n', '', ':ReloadXMLFromZip', { desc = 'Reload MS Word' }) + +-- vimtex for tex files +vim.api.nvim_create_autocmd('FileType', { + pattern = 'tex', + once = true, + group = vim.api.nvim_create_augroup('MrlVimtex', { clear = true }), + callback = function() + require('packs.vimtex').config() + -- tex-kitty setup + require('tex-kitty').setup({ + tex_kitty_preview = 1, + }) + end, +}) + +-- pgsql.vim is disabled (cond = false) +-- livetex.nvim is disabled (cond = false) diff --git a/files/.config/nvim/lua/packs/folke.lua b/files/.config/nvim/lua/packs/folke.lua new file mode 100644 index 0000000..e69de29 diff --git a/files/.config/nvim/lua/packs/format.lua b/files/.config/nvim/lua/packs/format.lua new file mode 100644 index 0000000..5586740 --- /dev/null +++ b/files/.config/nvim/lua/packs/format.lua @@ -0,0 +1,103 @@ +-- packs/format.lua + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlFormat', { clear = true }), + callback = function() + local conform = require('conform') + conform.setup({ + notify_on_error = true, + format_on_save = function(bufnr) + -- Disable LSP fallback for languages that don't + -- have a well standardized coding style. You can add additional + -- languages here or re-enable it for the disabled ones. + if vim.g.disable_autoformat or vim.g.formatting_disabled then + return nil + end + if vim.b[bufnr] and vim.b[bufnr].formatting_disabled then + return nil + end + local disable_filetypes = + { c = true, cpp = true, xml = true, cnk = true, map = true } + return { + timeout_ms = 5000, + lsp_format = disable_filetypes[vim.bo[bufnr].filetype] and 'never' + or 'fallback', + } + end, + formatters_by_ft = { + bash = { 'shfmt' }, + javascript = { 'prettier' }, + typescript = { 'prettier' }, + javascriptreact = { 'prettier' }, + typescriptreact = { 'prettier' }, + svelte = { 'prettier' }, + css = { 'prettierd' }, + html = { 'prettier' }, + json = { 'prettier' }, + yaml = { 'prettier' }, + markdown = { 'prettier' }, + graphql = { 'prettier' }, + liquid = { 'prettier' }, + lua = { 'stylua' }, + python = { 'isort', 'black' }, + xml = { 'xmlformat' }, + }, + -- Set default options + default_format_opts = { + lsp_format = 'fallback', + }, + -- Customize formatters + formatters = { + shfmt = { + prepend_args = { '-i', '2' }, + }, + -- Only run prettier if config file exists + prettier = {}, + prettierd = {}, + -- Only run isort if config file exists + isort = {}, + -- Only run stylua if config file exists + stylua = {}, + }, + }) + + vim.api.nvim_create_user_command('Format', function(args) + local range = nil + if args.count ~= -1 then + local end_line = + vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1] + range = { + start = { args.line1, 0 }, + ['end'] = { args.line2, end_line:len() }, + } + end + conform.format({ + async = true, + lsp_format = 'fallback', + range = range, + }) + end, { range = true }) + + vim.api.nvim_create_user_command( + 'FormatDisable', + function(_args) vim.g.disable_autoformat = true end, + { + desc = 'Disable autoformat-on-save', + } + ) + + vim.api.nvim_create_user_command( + 'FormatEnable', + function() vim.g.disable_autoformat = false end, + { + desc = 'Re-enable autoformat-on-save', + } + ) + end, +}) + +-- Keymap registered immediately +vim.keymap.set('', 'lf', function() + require('conform').format({ async = true, lsp_format = 'fallback' }) +end, { desc = '[F]ormat buffer' }) diff --git a/files/.config/nvim/lua/packs/fzf.lua b/files/.config/nvim/lua/packs/fzf.lua new file mode 100644 index 0000000..9368f16 --- /dev/null +++ b/files/.config/nvim/lua/packs/fzf.lua @@ -0,0 +1,228 @@ +-- packs/fzf.lua + +local UI = require('tools').ui +local icons = UI.icons or {} +local lsp_hls = (UI.lsp and UI.lsp.highlights) or {} + +local function has_exec(bin) return vim.fn.executable(bin) == 1 end + +local function trim(s) return (s:gsub('^%s+', ''):gsub('%s+$', '')) end + +local function toggle_cli_flag(args, flag) + args.cmd = args.cmd or '' + local escaped = vim.pesc(flag) + local pattern = '(%s*)' .. escaped .. '(%s*)' + if args.cmd:find(escaped) then + args.cmd = args.cmd:gsub(pattern, ' ', 1) + else + args.cmd = trim(args.cmd .. ' ' .. flag) + end +end + +local function restart_files(args) + local ok, fzf = pcall(require, 'fzf-lua') + if ok then fzf.files(args) end +end + +local function open_files_in_cwd(cwd, label) + local dir = type(cwd) == 'string' and cwd or '' + if dir ~= '' and vim.fn.isdirectory(dir) == 1 then + require('fzf-lua').files({ cwd = dir }) + return + end + + local where = label and (' for ' .. label) or '' + vim.notify( + 'Invalid directory' .. where .. ': ' .. tostring(dir), + vim.log.levels.WARN + ) + require('fzf-lua').files() +end + +local function current_buffer_dir() + local name = vim.api.nvim_buf_get_name(0) + if name == '' then return vim.loop.cwd() end + local dir = vim.fn.fnamemodify(name, ':p:h') + if dir == '' then return vim.loop.cwd() end + return dir +end + +-- Setup fzf-lua +local ok_lspkind, lspkind = pcall(require, 'lspkind') +local lsp_symbols = ok_lspkind and lspkind.symbols or {} +local has_bat = has_exec('bat') or has_exec('batcat') +local has_delta = has_exec('delta') + +require('fzf-lua').setup({ + winopts = { + split = 'botright new', -- Full-width horizontal split at bottom + -- Alternative: 'topleft new' for full-width at top + preview = { + default = has_bat and 'bat' or 'builtin', + scrollbar = 'float', + }, + }, + -- Native integration for vim.ui.select (replaces custom wrapper). + ui_select = { + winopts = { + split = 'botright new', + height = 0.35, + preview = { hidden = true }, + }, + fzf_opts = { + ['--info'] = 'default', + }, + }, + fzf_opts = { + ['--info'] = 'default', + }, + files = { + hidden = false, + no_ignore = false, + follow = false, + -- --hidden lets rg/fd see dotfiles; .gitignore still filters untracked ones, + -- so git-tracked hidden files are listed while junk (caches, etc.) stays out. + rg_opts = [[--color=never --files --hidden -g "!.git"]], + fd_opts = [[--color=never --type f --type l --hidden --exclude .git]], + }, + grep = { + rg_opts = '--column --line-number --no-heading --color=always --smart-case --max-columns=4096 --hidden -e', + }, + keymap = { + builtin = { + [''] = 'toggle-preview', + [''] = 'preview-page-down', + [''] = 'preview-page-up', + [''] = { + function(_, args) + toggle_cli_flag(args, '--hidden') + restart_files(args) + end, + }, + [''] = { + function(_, args) + toggle_cli_flag(args, '--no-ignore') + restart_files(args) + end, + }, + }, + fzf = { + ['esc'] = 'abort', + ['ctrl-q'] = 'select-all+accept', + }, + }, + lsp = { + symbols = { + symbol_style = 1, + symbol_icons = lsp_symbols, + symbol_hl = function(s) return lsp_hls[s] end, + }, + }, + git = { + status = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' + or nil, + }, + bcommits = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' + or nil, + }, + commits = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' + or nil, + }, + icons = { + ['M'] = { + icon = (icons.git and icons.git.mod) or 'M', + color = 'yellow', + }, + ['D'] = { + icon = (icons.git and icons.git.remove) or 'D', + color = 'red', + }, + ['A'] = { + icon = (icons.git and icons.git.staged) or 'A', + color = 'green', + }, + ['R'] = { + icon = (icons.git and icons.git.rename) or 'R', + color = 'yellow', + }, + ['C'] = { + icon = (icons.git and icons.git.conflict) or 'C', + color = 'yellow', + }, + ['T'] = { + icon = (icons.git and icons.git.mod) or 'T', + color = 'magenta', + }, + ['?'] = { + icon = (icons.git and icons.git.untracked) or '?', + color = 'magenta', + }, + }, + }, +}) + +-- Restore full custom statusline for fzf windows +vim.api.nvim_create_autocmd({ 'FileType', 'BufWinEnter' }, { + group = vim.api.nvim_create_augroup('FzfLuaStatusline', { clear = true }), + pattern = 'fzf', + callback = function() + -- Use defer_fn to run after fzf-lua sets its statusline + vim.defer_fn(function() + if vim.bo.filetype == 'fzf' then + if + type(_G.Stl) == 'table' and type(_G.Stl.render) == 'function' + then + vim.opt_local.statusline = '%{%v:lua.Stl.render()%}' + end + end + end, 0) + end, +}) + +-- Keymaps +vim.keymap.set('n', '', 'FzfLua git_files', { desc = 'fzf: [f]ind [f]iles' }) +vim.keymap.set('n', 'fa', 'FzfLua', { desc = 'fzf: [f]ind [a]ll builtins' }) +vim.keymap.set('n', 'ff', function() + -- In a git repo: use git ls-files so tracked hidden files appear. + -- Outside a git repo: fall back to regular files picker. + local ok = vim.fn.systemlist( + 'git rev-parse --is-inside-work-tree 2>/dev/null' + )[1] + if ok == 'true' then + require('fzf-lua').git_files({ show_untracked = true }) + else + require('fzf-lua').files() + end +end, { desc = 'fzf: [f]ind [f]iles' }) +vim.keymap.set('n', 'fb', 'FzfLua grep_curbuf', { desc = 'fzf: [f]ind in current [b]uffer' }) +vim.keymap.set('n', 'fr', 'FzfLua resume', { desc = 'fzf: [f]ind [r]esume' }) +vim.keymap.set('n', 'fva', 'FzfLua autocmds', { desc = 'fzf: fin [a]utocommands' }) +vim.keymap.set('n', 'fvh', 'FzfLua highlights', { desc = 'fzf: find Highlights' }) +vim.keymap.set('n', 'fvk', 'FzfLua keymaps', { desc = 'fzf: find Keymaps' }) +vim.keymap.set('n', 'fle', 'FzfLua diagnostics_workspace', { desc = 'fzf: Lsp workspace Diagnostics' }) +vim.keymap.set('n', 'fld', 'FzfLua lsp_document_symbols', { desc = 'fzf: Lsp document Symbols' }) +vim.keymap.set('n', 'fls', 'FzfLua lsp_live_workspace_symbols', { desc = 'fzf: workspace symbols' }) +vim.keymap.set('n', 'f?', 'FzfLua help_tags', { desc = 'fzf: find ?help' }) +vim.keymap.set('n', 'fh', 'FzfLua oldfiles', { desc = 'fzf: Most (f)recently used files' }) +vim.keymap.set('n', 'fgb', 'FzfLua git_branches', { desc = 'fzf: [g]it [b]ranches' }) +vim.keymap.set('n', 'fgs', 'FzfLua git_status', { desc = 'fzf: [g]it [s]tatus' }) +vim.keymap.set('n', 'fgc', 'FzfLua git_commits', { desc = 'fzf: [g]it [c]ommits' }) +vim.keymap.set('n', 'fgB', 'FzfLua git_bcommits', { desc = 'fzf: [b]uffer commits' }) +vim.keymap.set('n', 'fo', 'FzfLua buffers', { desc = 'fzf: find [o]pen buffers' }) +vim.keymap.set('n', 'fs', 'FzfLua live_grep', { desc = 'fzf: [f] with live[g]rep' }) +vim.keymap.set('n', 'p', 'FzfLua registers', { desc = 'fzf: [f]ind registers' }) +vim.keymap.set('n', 'fd', function() + open_files_in_cwd(vim.g.dotfiles, 'dotfiles') +end, { desc = 'fzf: [f]ind [d]otfiles' }) +vim.keymap.set('n', 'fp', function() + open_files_in_cwd(vim.g.projects_directory, 'projects') +end, { desc = 'fzf: [f]ind in [p]rojects' }) +vim.keymap.set('n', 'f.', function() + open_files_in_cwd(current_buffer_dir(), 'current buffer') +end, { desc = 'fzf: find in current file dir' }) +vim.keymap.set('n', 'fc', function() + open_files_in_cwd(vim.g.vim_dir, 'nvim config') +end, { desc = 'fzf: [f]ind nvim [c]onfig' }) diff --git a/files/.config/nvim/lua/packs/gaming.lua b/files/.config/nvim/lua/packs/gaming.lua new file mode 100644 index 0000000..5d1efbd --- /dev/null +++ b/files/.config/nvim/lua/packs/gaming.lua @@ -0,0 +1,4 @@ +-- packs/gaming.lua + +-- key-analyzer.nvim: loaded on :KeyAnalyzer command, no setup needed +-- (vim.pack handles loading; setup() is called automatically or not needed) diff --git a/files/.config/nvim/lua/packs/git.lua b/files/.config/nvim/lua/packs/git.lua new file mode 100644 index 0000000..bc3ff76 --- /dev/null +++ b/files/.config/nvim/lua/packs/git.lua @@ -0,0 +1,411 @@ +-- packs/git.lua + +local T = require('tools') +local icons = require('tools').ui.icons.separators + +local gitlinker = T.require_for_later_index('gitlinker') +local function browser_open() + return { action_callback = require('gitlinker.actions').open_in_browser } +end + +-- --------------------------------------------------------------------------- +-- gitsigns {{{ +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlGitsigns', { clear = true }), + callback = function() + require('gitsigns').setup({ + -- signcolumn = false, -- Disable icons in sign column + signs = { + add = { text = icons.right_block }, + change = { text = icons.right_block }, + delete = { text = icons.right_block }, + topdelete = { text = icons.right_block }, + changedelete = { text = icons.right_block }, + untracked = { text = icons.light_shade_block }, + }, + on_attach = function(bufnr) + local gitsigns = require('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', ']c', function() + if vim.wo.diff then + vim.cmd.normal({ ']c', bang = true }) + else + gitsigns.nav_hunk('next') + end + end, { desc = 'Jump to next git [c]hange' }) + + map('n', '[c', function() + if vim.wo.diff then + vim.cmd.normal({ '[c', bang = true }) + else + gitsigns.nav_hunk('prev') + end + end, { desc = 'Jump to previous git [c]hange' }) + + -- Actions + -- visual mode + map( + 'v', + 'hs', + function() gitsigns.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, + { desc = 'stage git hunk' } + ) + map( + 'v', + 'hr', + function() gitsigns.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, + { desc = 'reset git hunk' } + ) + -- normal mode + map( + 'n', + 'hs', + gitsigns.stage_hunk, + { desc = 'git [s]tage hunk' } + ) + map( + 'n', + 'hr', + gitsigns.reset_hunk, + { desc = 'git [r]eset hunk' } + ) + map( + 'n', + 'hS', + gitsigns.stage_buffer, + { desc = 'git [S]tage buffer' } + ) + map( + 'n', + 'hu', + gitsigns.undo_stage_hunk, + { desc = 'git [u]ndo stage hunk' } + ) + map( + 'n', + 'hR', + gitsigns.reset_buffer, + { desc = 'git [R]eset buffer' } + ) + map( + 'n', + 'hp', + gitsigns.preview_hunk, + { desc = 'git [p]review hunk' } + ) + map( + 'n', + 'hb', + gitsigns.blame_line, + { desc = 'git [b]lame line' } + ) + map( + 'n', + 'hd', + gitsigns.diffthis, + { desc = 'git [d]iff against index' } + ) + map( + 'n', + 'hD', + function() gitsigns.diffthis('@') end, + { desc = 'git [D]iff against last commit' } + ) + -- Toggles + map( + 'n', + 'tb', + gitsigns.toggle_current_line_blame, + { desc = '[T]oggle git show [b]lame line' } + ) + map( + 'n', + 'tD', + gitsigns.toggle_deleted, + { desc = '[T]oggle git show [D]eleted' } + ) + end, + }) + end, +}) +-- }}} + +-- --------------------------------------------------------------------------- +-- gitlinker keymaps {{{ +-- --------------------------------------------------------------------------- +vim.keymap.set('n', 'gu', function() + gitlinker.get_buf_range_url('n') +end, { desc = 'gitlinker: copy line to clipboard', silent = true }) + +vim.keymap.set('v', 'gu', function() + gitlinker.get_buf_range_url('v') +end, { desc = 'gitlinker: copy range to clipboard', silent = true }) + +vim.keymap.set('n', 'go', function() + gitlinker.get_repo_url(browser_open()) +end, { desc = 'gitlinker: open in browser', silent = true }) + +vim.keymap.set('v', 'go', function() + gitlinker.get_buf_range_url('v', browser_open()) +end, { desc = 'gitlinker: open current selection in browser', silent = true }) + +-- gitlinker setup (opts only, mappings disabled) +vim.defer_fn(function() + require('gitlinker').setup({ + mappings = nil, + callbacks = { + ['github-work.com'] = function(url_data) -- Resolve the host for work repositories + url_data.host = 'github.com' + return require('gitlinker.hosts').get_github_type_url(url_data) + end, + }, + }) +end, 100) +-- }}} + +-- --------------------------------------------------------------------------- +-- git-conflict {{{ +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd('BufReadPre', { + once = true, + group = vim.api.nvim_create_augroup('MrlGitConflict', { clear = true }), + callback = function() + require('git-conflict').setup({ + default_mappings = true, + default_commands = true, + disable_diagnostics = true, + list_opener = 'copen', + highlights = { + incoming = 'DiffAdd', + current = 'DiffText', + }, + }) + end, +}) +-- }}} + +-- --------------------------------------------------------------------------- +-- fugitive {{{ +-- --------------------------------------------------------------------------- + +-- init equivalent: detect fugitive worktrees on DirChanged +vim.api.nvim_create_autocmd('DirChanged', { + group = vim.api.nvim_create_augroup('FugitiveWorktreeDetect', { clear = true }), + callback = function() + vim.fn.FugitiveDetect(vim.fn.getcwd()) + end, +}) + +-- Fugitive keymaps +vim.keymap.set('n', 'gs', function() + -- FugitiveCommonDir returns the shared .bare dir for all worktrees of the same repo + local cur_common = vim.fn.FugitiveCommonDir(vim.api.nvim_get_current_buf()) + if cur_common == '' then + vim.cmd('tab Git') + return + end + for _, tabnr in ipairs(vim.api.nvim_list_tabpages()) do + for _, winnr in ipairs(vim.api.nvim_tabpage_list_wins(tabnr)) do + local buf = vim.api.nvim_win_get_buf(winnr) + local name = vim.api.nvim_buf_get_name(buf) + if name:match('^fugitive://') then + local tab_common = vim.fn.FugitiveCommonDir(buf) + if tab_common ~= '' and tab_common == cur_common then + vim.api.nvim_set_current_tabpage(tabnr) + return + end + end + end + end + vim.cmd('tab Git') +end, { desc = '[git] Status' }) + +vim.keymap.set('n', 'g-', "lua require 'gitsigns'.blame_line()", { desc = '[git] Blame' }) +vim.keymap.set('n', 'gB', 'Git blame', { desc = 'Git Blame' }) +vim.keymap.set('n', 'gb', 'FzfLua git_branches', { desc = '[git] Checkout branch' }) +vim.keymap.set('n', 'gc', 'FzfLua git_commits', { desc = '[git] Checkout commit' }) +vim.keymap.set('n', 'gC', 'FzfLua git_bcommits', { desc = '[git] Checkout commit(for current file)' }) +vim.keymap.set('n', 'gf', 'Git fall', { desc = '[git] Git fetch all branches' }) +vim.keymap.set('n', 'gh', 'diffget //2', { desc = '[git] Get diff from left' }) +vim.keymap.set('n', 'gH', '0Gclog', { desc = '[git] Get history for current file' }) +vim.keymap.set('n', 'gl', 'diffget //3', { desc = '[git] Get diff from right' }) +vim.keymap.set('n', 'gj', "lua require 'gitsigns'.next_hunk()", { desc = '[git] Next Hunk' }) +vim.keymap.set('n', 'gk', "lua require 'gitsigns'.prev_hunk()", { desc = '[git] Prev Hunk' }) +vim.keymap.set('n', 'gP', 'Git push', { desc = '[git] Git push commited changes' }) +vim.keymap.set('n', 'gp', 'Git pull --rebase', { desc = '[git] Git pull and rebase' }) +vim.keymap.set('n', 'gt', ':Git push -u origin ', { desc = '[git] set target branch ' }) +-- }}} + +-- --------------------------------------------------------------------------- +-- diffview {{{ +-- --------------------------------------------------------------------------- +vim.defer_fn(function() + require('diffview').setup({ + enhanced_diff_hl = true, + signs = { + fold_closed = '', + fold_open = '', + done = '✓', + }, + view = { + merge_tool = { layout = 'diff3_mixed' }, + }, + }) +end, 100) +-- }}} + +-- --------------------------------------------------------------------------- +-- gitgraph {{{ +-- --------------------------------------------------------------------------- +vim.keymap.set('n', 'gG', function() + require('gitgraph').draw({}, { all = true, max_count = 5000 }) +end, { desc = 'GitGraph' }) + +vim.defer_fn(function() + require('gitgraph').setup({ + symbols = { + merge_commit = 'M', + commit = '*', + }, + format = { + timestamp = '%H:%M:%S %d-%m-%Y', + fields = { 'hash', 'timestamp', 'author', 'branch_name', 'tag' }, + }, + hooks = { + -- Check diff of a commit + on_select_commit = function(commit) + vim.notify('DiffviewOpen ' .. commit.hash .. '^!') + vim.cmd(':DiffviewOpen ' .. commit.hash .. '^!') + end, + -- Check diff from commit a -> commit b + on_select_range_commit = function(from, to) + vim.notify('DiffviewOpen ' .. from.hash .. '~1..' .. to.hash) + vim.cmd(':DiffviewOpen ' .. from.hash .. '~1..' .. to.hash) + end, + }, + }) +end, 100) +-- }}} + +-- gh.nvim is disabled (cond = false) + +-- --------------------------------------------------------------------------- +-- git-worktree {{{ +-- --------------------------------------------------------------------------- +vim.keymap.set('n', 'gwl', function() + require('fzf-lua').fzf_exec(function(cb) + local lines = vim.fn.systemlist('git worktree list --porcelain') + local worktrees = {} + local cur = {} + for _, line in ipairs(lines) do + local path = line:match('^worktree (.+)') + local branch = line:match('^branch refs/heads/(.+)') + if path then cur = { path = path } end + if branch then cur.branch = branch end + if line == '' and cur.path then + table.insert(worktrees, cur) + cur = {} + end + end + if cur.path then table.insert(worktrees, cur) end + for _, wt_entry in ipairs(worktrees) do + cb(string.format('%s\t%s', wt_entry.branch or '(detached)', wt_entry.path)) + end + cb(nil) + end, { + prompt = 'Worktrees> ', + actions = { + ['default'] = function(selected) + local path = selected[1]:match('\t(.+)$') + if path then + require('git-worktree').switch_worktree(path) + end + end, + }, + }) +end, { desc = '[git] List/switch worktree' }) + +vim.keymap.set('n', 'gwd', function() + require('fzf-lua').fzf_exec(function(cb) + local lines = vim.fn.systemlist('git worktree list --porcelain') + local worktrees = {} + local cur = {} + for _, line in ipairs(lines) do + local path = line:match('^worktree (.+)') + local branch = line:match('^branch refs/heads/(.+)') + if path then cur = { path = path } end + if branch then cur.branch = branch end + if line == '' and cur.path then + table.insert(worktrees, cur) + cur = {} + end + end + if cur.path then table.insert(worktrees, cur) end + -- skip the main worktree (first entry) + for i, wt_entry in ipairs(worktrees) do + if i > 1 then + cb(string.format('%s\t%s', wt_entry.branch or '(detached)', wt_entry.path)) + end + end + cb(nil) + end, { + prompt = 'Delete worktree> ', + fzf_opts = { ['--header'] = 'CTRL-D: force delete branch | ENTER: remove worktree only' }, + actions = { + ['default'] = function(selected) + local path = selected[1]:match('\t(.+)$') + if not path then return end + vim.ui.input( + { prompt = 'Flags ([-f] [-d|-D], or enter to confirm): ' }, + function(flags) + if flags == nil then return end -- cancelled + local cmd = 'gwrm ' .. (flags ~= '' and flags .. ' ' or '') .. vim.fn.shellescape(path) + local out = vim.fn.system(cmd) + if vim.v.shell_error ~= 0 then + vim.notify(out, vim.log.levels.ERROR) + else + vim.notify('Removed worktree: ' .. path) + end + end + ) + end, + }, + }) +end, { desc = '[git] Delete worktree' }) + +vim.keymap.set('n', 'gwc', function() + vim.ui.input({ prompt = 'New branch name: ' }, function(branch) + if not branch or branch == '' then return end + vim.ui.input( + { prompt = 'Path (default: ' .. branch .. '): ' }, + function(path) + path = (path and path ~= '') and path or branch + vim.ui.input({ prompt = 'Base branch (default: HEAD): ' }, function(base) + base = (base and base ~= '') and base or 'HEAD' + require('git-worktree').create_worktree(path, branch, base) + end) + end + ) + end) +end, { desc = '[git] Create worktree' }) + +vim.defer_fn(function() + require('git-worktree').setup() + require('git-worktree').on_tree_change(function(op, metadata) + if op == require('git-worktree').Operations.Switch then + vim.fn.FugitiveDetect(metadata.path) + end + end) +end, 100) +-- }}} + +-- vim: fdm=marker diff --git a/files/.config/nvim/lua/packs/init.lua b/files/.config/nvim/lua/packs/init.lua new file mode 100644 index 0000000..f02c6e2 --- /dev/null +++ b/files/.config/nvim/lua/packs/init.lua @@ -0,0 +1,33 @@ +-- packs/init.lua + +-- plenary.nvim: no setup needed + +-- fold-cycle +require('fold-cycle').setup({}) +vim.keymap.set('n', '', function() require('fold-cycle').open() end, { + desc = 'fold-cycle: toggle', +}) + +-- debugprint +require('debugprint').setup({ keymaps = {} }) +vim.keymap.set('n', 'dp', function() + return require('debugprint').debugprint({ variable = true }) +end, { desc = 'debugprint: cursor', expr = true }) +vim.keymap.set('n', 'do', function() + return require('debugprint').debugprint({ motion = true }) +end, { desc = 'debugprint: operator', expr = true }) +vim.keymap.set('n', 'dC', 'DeleteDebugPrints', { + desc = 'debugprint: clear all', +}) + +-- sailor.vim: loaded on VimEnter, no explicit setup needed + +-- file-line: activated by the gF key, no setup needed + +-- vim-dirdiff: loaded on :DirDiff command, no setup needed + +-- vim-sleuth: loaded on BufReadPre, no setup needed + +-- vim-surround: loaded on BufReadPre, no setup needed + +-- vim-repeat: loaded on '.', no setup needed diff --git a/files/.config/nvim/lua/custom/plugins/linting.lua b/files/.config/nvim/lua/packs/linting.lua similarity index 86% rename from files/.config/nvim/lua/custom/plugins/linting.lua rename to files/.config/nvim/lua/packs/linting.lua index 899c163..7db4996 100644 --- a/files/.config/nvim/lua/custom/plugins/linting.lua +++ b/files/.config/nvim/lua/packs/linting.lua @@ -1,14 +1,9 @@ -return { - 'mfussenegger/nvim-lint', - event = { 'BufWritePost', 'BufReadPost', 'InsertLeave', 'LspAttach' }, - keys = { - { - 'll', - function() require('lint').try_lint() end, - desc = 'Try linting for current file', - }, - }, - config = function() +-- packs/linting.lua + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlLinting', { clear = true }), + callback = function() local lint = require('lint') local fn = vim.fn @@ -57,11 +52,8 @@ return { lint.linters_by_ft['clojure'] = nil -- example on how to disable lint.linters.flake8 = lint.linters.flake8 or {} - lint.linters.mypy = lint.linters.mypy or {} - lint.linters.eslint_d = lint.linters.eslint_d or {} - lint.linters.luacheck = lint.linters.luacheck or {} local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true }) @@ -74,4 +66,9 @@ return { end, }) end, -} +}) + +-- Keymap registered immediately +vim.keymap.set('n', 'll', function() require('lint').try_lint() end, { + desc = 'Try linting for current file', +}) diff --git a/files/.config/nvim/lua/packs/lsp.lua b/files/.config/nvim/lua/packs/lsp.lua new file mode 100644 index 0000000..9d08874 --- /dev/null +++ b/files/.config/nvim/lua/packs/lsp.lua @@ -0,0 +1,390 @@ +-- packs/lsp.lua + +-- Floating UI (hover/signature/diagnostics) border styling +-- Some plugins/LSP helpers call `vim.lsp.util.open_floating_preview` directly, +-- so enforce a default border there too. +do + local orig = vim.lsp.util.open_floating_preview + ---@diagnostic disable-next-line: duplicate-set-field + function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) + opts = opts or {} + opts.border = opts.border or 'rounded' + -- Disable all columns in LSP floating windows + local bufnr, winnr = orig(contents, syntax, opts, ...) + if winnr and vim.api.nvim_win_is_valid(winnr) then + vim.wo[winnr].statuscolumn = '' + vim.wo[winnr].signcolumn = 'no' + vim.wo[winnr].foldcolumn = '0' + vim.wo[winnr].number = false + vim.wo[winnr].relativenumber = false + end + return bufnr, winnr + end +end + +-- Prefer wrapping the existing handlers instead of `vim.lsp.with(...)` +local function with_border(handler) + return function(err, result, ctx, config) + config = config or {} + config.border = config.border or 'rounded' + return handler(err, result, ctx, config) + end +end + +vim.lsp.handlers['textDocument/hover'] = + with_border(vim.lsp.handlers['textDocument/hover']) +vim.lsp.handlers['textDocument/signatureHelp'] = + with_border(vim.lsp.handlers['textDocument/signatureHelp']) + +-- LspAttach: register keymaps per buffer +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), + callback = function(event) + -- Prevent duplicate keymap setup when multiple LSP servers attach + if vim.b[event.buf].lsp_keymaps_attached then return end + vim.b[event.buf].lsp_keymaps_attached = true + + vim.keymap.set( + 'n', + 'a', + require('lspimport').import, + { noremap = true } + ) + local map = function(keys, func, desc) + vim.keymap.set( + 'n', + keys, + func, + { buffer = event.buf, desc = 'LSP: ' .. desc } + ) + end + + -- Rename the variable under your cursor. + map('rn', vim.lsp.buf.rename, '[R]e[n]ame') + + -- Execute a code action + map('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') + + -- Opens a popup that displays documentation about the word under your cursor + map('gh', vim.lsp.buf.hover, 'Hover Documentation') + + -- WARN: This is not Goto Definition, this is Goto Declaration. + map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + + -- DISABLED: Document highlight on CursorMove causes severe scrolling lag + -- The CursorMoved autocmds fire on every scroll step, causing expensive LSP operations + + -- Enable inlay hints if the language server supports them + local client = vim.lsp.get_client_by_id(event.data.client_id) + if + client + and client.server_capabilities.inlayHintProvider + and vim.lsp.inlay_hint + then + map( + 'th', + function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) + end, + '[T]oggle Inlay [H]ints' + ) + end + end, +}) + +vim.api.nvim_create_autocmd('LspDetach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), + callback = function(event) + vim.lsp.buf.clear_references() + -- try to clear the highlights when the LSP detaches + pcall( + function() + vim.api.nvim_clear_autocmds({ + group = 'kickstart-lsp-highlight', + buffer = event.buf, + }) + end + ) + end, +}) + +-- LSP capabilities (with blink.cmp) +local original_capabilities = vim.lsp.protocol.make_client_capabilities() +local capabilities = + require('blink.cmp').get_lsp_capabilities(original_capabilities) + +-- Disable file watchers for performance (especially in large projects) +capabilities.workspace = capabilities.workspace or {} +capabilities.workspace.didChangeWatchedFiles = capabilities.workspace.didChangeWatchedFiles + or {} +capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = false + +-- Language server configurations +local servers = { + -- clangd = {}, + -- gopls = {}, + basedpyright = { + on_attach = function(client, _bufnr) + -- Disable diagnostics from basedpyright + client.server_capabilities.diagnosticProvider = false + end, + settings = { + python = { + analysis = { + typeCheckingMode = 'off', + diagnosticMode = 'openFilesOnly', + autoSearchPaths = true, + useLibraryCodeForTypes = true, + }, + }, + basedpyright = { + disableOrganizeImports = true, + }, + }, + }, + ruff = {}, + -- pylsp = {}, + -- rust_analyzer = {}, + -- tsserver = {}, + + lua_ls = { + -- cmd = {...}, + -- filetypes = { ...}, + -- capabilities = {}, + settings = { + Lua = { + diagnostics = { + globals = { 'vim' }, + }, + completion = { + callSnippet = 'Replace', + }, + -- diagnostics = { disable = { 'missing-fields' } }, + }, + }, + }, +} + +-- Mason setup +require('mason').setup({ + ui = { + border = 'rounded', + width = 0.8, + height = 0.8, + backdrop = 100, + }, +}) + +-- lazydev for Lua development +require('lazydev').setup({ + library = { + { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, + { path = 'wezterm-types', mods = { 'wezterm' } }, + }, + enabled = function(root_dir) + return (vim.g.lazydev_enabled == nil or vim.g.lazydev_enabled) + and not vim.uv.fs_stat(root_dir .. '/.luarc.json') + end, +}) + +-- fidget for LSP progress +require('fidget').setup({}) + +-- Ensure the servers and tools are installed +local ensure_installed = vim.tbl_keys(servers or {}) +vim.list_extend(ensure_installed, { + -- Lua + 'stylua', + -- Python + 'black', + 'isort', + 'flake8', + 'mypy', + -- Shell + 'shfmt', + -- JS/TS + 'prettier', + 'prettierd', + 'eslint_d', + -- Misc linters + 'hadolint', + 'jsonlint', + 'vale', + 'tflint', + -- Other + 'sonarlint-language-server', +}) +require('mason-tool-installer').setup({ + ensure_installed = ensure_installed, +}) + +require('mason-lspconfig').setup({ + handlers = { + function(server_name) + local server = servers[server_name] or {} + -- This handles overriding only values explicitly passed + -- by the server configuration above. + server.capabilities = vim.tbl_deep_extend( + 'force', + {}, + capabilities, + server.capabilities or {} + ) + require('lspconfig')[server_name].setup(server) + end, + }, +}) + +-- symbols-outline +vim.keymap.set('n', 'cs', 'SymbolsOutline', { desc = 'Symbols Outline' }) +require('symbols-outline').setup() + +-- tiny-inline-diagnostic (on LspAttach) +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlTinyInlineDiag', { clear = true }), + callback = function() + -- Don't error if linters aren't installed (common on fresh machines / WSL). + pcall(function() require('lint').try_lint() end) + require('tiny-inline-diagnostic').setup({ + -- "modern", "classic", "minimal", "powerline", "simple" + preset = 'simple', + transparent_bg = false, + hi = { + error = 'DiagnosticError', + warn = 'DiagnosticWarn', + info = 'DiagnosticInfo', + hint = 'DiagnosticHint', + arrow = 'NonText', + background = 'CursorLine', + mixing_color = 'None', + }, + + options = { + show_source = true, + use_icons_from_diagnostic = false, + set_arrow_to_diag_color = false, + add_messages = true, + throttle = 100, + softwrap = 30, + multilines = { + enabled = false, + always_show = false, + }, + show_all_diags_on_cursorline = false, + enable_on_insert = false, + enable_on_select = false, + overflow = { + mode = 'wrap', + padding = 0, + }, + break_line = { + enabled = false, + after = 30, + }, + format = nil, + virt_texts = { + priority = 2048, + }, + severity = { + vim.diagnostic.severity.ERROR, + vim.diagnostic.severity.WARN, + vim.diagnostic.severity.INFO, + vim.diagnostic.severity.HINT, + }, + overwrite_events = nil, + }, + disabled_ft = {}, + }) + end, +}) + +-- sonarqube.nvim (conditional on java being available) +vim.api.nvim_create_autocmd('FileType', { + pattern = 'python', + once = true, + group = vim.api.nvim_create_augroup('MrlSonarqube', { clear = true }), + callback = function() + if vim.fn.executable('java') ~= 1 then return end + + local extension_path = vim.fn.stdpath('data') + .. '/mason/packages/sonarlint-language-server/extension' + + if vim.fn.isdirectory(extension_path) == 0 then + vim.notify( + 'SonarLint extension not found. Run :MasonInstall sonarlint-language-server', + vim.log.levels.WARN + ) + return + end + + require('sonarqube').setup({ + lsp = { + cmd = { + vim.fn.exepath('java'), + '-jar', + extension_path .. '/server/sonarlint-ls.jar', + '-stdio', + '-analyzers', + extension_path .. '/analyzers/sonargo.jar', + extension_path .. '/analyzers/sonarhtml.jar', + extension_path .. '/analyzers/sonariac.jar', + extension_path .. '/analyzers/sonarjava.jar', + extension_path .. '/analyzers/sonarjavasymbolicexecution.jar', + extension_path .. '/analyzers/sonarjs.jar', + extension_path .. '/analyzers/sonarphp.jar', + extension_path .. '/analyzers/sonarpython.jar', + extension_path .. '/analyzers/sonartext.jar', + extension_path .. '/analyzers/sonarxml.jar', + }, + }, + python = { + enabled = true, + }, + }) + end, +}) + +-- nvim-lightbulb (on LspAttach) +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlLightbulb', { clear = true }), + callback = function() + require('nvim-lightbulb').setup({ + autocmd = { enabled = true }, + sign = { enabled = false }, + float = { + enabled = true, + win_opts = { border = 'none' }, + }, + }) + end, +}) +vim.keymap.set('n', 'lb', function() + require('nvim-lightbulb').get_status_text() +end, { desc = 'LSP: Lightbulb status' }) + +-- glance.nvim (on LspAttach) +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlGlance', { clear = true }), + callback = function() + require('glance').setup({ + preview_win_opts = { relativenumber = false }, + theme = { enable = true, mode = 'darken' }, + }) + end, +}) +vim.keymap.set('n', 'gd', 'Glance definitions', { desc = 'LSP: Glance definitions' }) +vim.keymap.set('n', 'gr', 'Glance references', { desc = 'LSP: Glance references' }) +vim.keymap.set('n', 'gy', 'Glance type_definitions', { desc = 'LSP: Glance type definitions' }) +vim.keymap.set('n', 'gm', 'Glance implementations', { desc = 'LSP: Glance implementations' }) + +-- inc-rename +require('inc_rename').setup({ + hl_group = 'Visual', + preview_empty_name = true, +}) +vim.keymap.set('n', 'rn', function() + return vim.fmt(':IncRename %s', vim.fn.expand('')) +end, { expr = true, silent = false, desc = 'lsp: incremental rename' }) diff --git a/files/.config/nvim/lua/packs/mini.lua b/files/.config/nvim/lua/packs/mini.lua new file mode 100644 index 0000000..bc3b450 --- /dev/null +++ b/files/.config/nvim/lua/packs/mini.lua @@ -0,0 +1,154 @@ +-- packs/mini.lua +-- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). + +-- --------------------------------------------------------------------------- +-- Text objects and editing (on BufReadPre) +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlMiniTextObjects', { clear = true }), + callback = function() + require('mini.ai').setup({ n_lines = 500 }) + + require('mini.align').setup({ + mappings = { + start = 'ga', -- Start align mode + start_with_preview = 'gA', -- Start align mode with preview + }, + options = { + split_pattern = '', + justify_side = 'left', + merge_delimiter = '', + }, + }) + + require('mini.surround').setup({ + n_lines = 20, + highlight_duration = 500, + mappings = { + add = 'sa', -- Add surrounding in Normal and Visual modes + delete = 'sd', -- Delete surrounding + find = 'sf', -- Find surrounding (to the right) + find_left = 'sF', -- Find surrounding (to the left) + highlight = 'sh', -- Highlight surrounding + replace = 'sr', -- Replace surrounding + update_n_lines = 'sn', -- Update `n_lines` + }, + }) + + require('mini.splitjoin').setup({ + mappings = { + toggle = 'gS', + split = '', + join = '', + }, + }) + + require('mini.move').setup({ + mappings = { + -- Move visual selection in Visual mode + left = '', + right = '', + down = '', + up = '', + -- Move current line in Normal mode + line_left = '', + line_right = '', + line_down = '', + line_up = '', + }, + options = { + reindent_linewise = true, + }, + }) + + require('mini.diff').setup({ + view = { + style = 'sign', + signs = { + add = '┃', + change = '┃', + delete = '┃', + }, + }, + algorithm = 'histogram', + highlight = { + additions = 'MiniDiffSignAdd', + deletions = 'MiniDiffSignDelete', + changes = 'MiniDiffSignChange', + text = 'MiniDiffText', + }, + }) + + require('mini.trailspace').setup({ + only_in_normal_buffers = true, + }) + + require('mini.misc').setup({ + mappings = {}, + options = { + use_global_statusline = true, + }, + }) + end, +}) + +-- mini.pairs on InsertEnter +vim.api.nvim_create_autocmd('InsertEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlMiniPairs', { clear = true }), + callback = function() + require('mini.pairs').setup({ + modes = { insert = true, command = false, terminal = false }, + }) + end, +}) + +-- --------------------------------------------------------------------------- +-- Icons (deferred - VeryLazy equivalent) +-- --------------------------------------------------------------------------- +vim.defer_fn(function() + require('mini.icons').setup({ + use_file_extension = function(ext, _) + if not ext or ext == '' then return true end + local len = #ext + if len >= 3 then + local suf3 = ext:sub(-3) + if suf3 == 'scm' or suf3 == 'txt' or suf3 == 'yml' then + return false + end + end + if len >= 4 then + local suf4 = ext:sub(-4) + if suf4 == 'json' or suf4 == 'yaml' then return false end + end + return true + end, + }) + + -- Mock nvim-web-devicons API immediately (needed early for other plugins) + require('mini.icons').mock_nvim_web_devicons() + + -- Defer LSP kind tweak (less critical, can happen after startup) + vim.schedule(function() require('mini.icons').tweak_lsp_kind() end) +end, 100) + +-- --------------------------------------------------------------------------- +-- mini.animate is disabled (cond = false) +-- --------------------------------------------------------------------------- +-- if false then +-- require('mini.animate').setup({...}) +-- end + +-- --------------------------------------------------------------------------- +-- mini.indentscope is disabled (cond = false) +-- --------------------------------------------------------------------------- + + +-- --------------------------------------------------------------------------- +-- mini.bufremove keymaps +-- --------------------------------------------------------------------------- +require('mini.bufremove').setup() +vim.keymap.set('n', 'bD', 'lua MiniBufremove.unshow()', { + desc = 'buffer: close buffer', +}) diff --git a/files/.config/nvim/lua/packs/navigation.lua b/files/.config/nvim/lua/packs/navigation.lua new file mode 100644 index 0000000..cbfb625 --- /dev/null +++ b/files/.config/nvim/lua/packs/navigation.lua @@ -0,0 +1,30 @@ +-- packs/navigation.lua + +-- oil.nvim +require('oil').setup({ + default_file_explorer = true, + delete_to_trash = true, + skip_confirm_for_simple_edits = true, + view_options = { + show_hidden = true, + }, + keymaps = { + [''] = false, -- don't shadow split navigation + [''] = false, + }, +}) +vim.keymap.set('n', '-', 'Oil', { desc = 'oil: open parent directory' }) + +-- grapple.nvim +require('grapple').setup({ + scope = 'git', +}) +vim.keymap.set('n', 'm', 'Grapple tag', { desc = 'grapple: tag file' }) +vim.keymap.set('n', '', 'Grapple toggle_tags', { desc = 'grapple: open tags' }) +vim.keymap.set('n', '1', 'Grapple select index=1', { desc = 'grapple: select 1' }) +vim.keymap.set('n', '2', 'Grapple select index=2', { desc = 'grapple: select 2' }) +vim.keymap.set('n', '3', 'Grapple select index=3', { desc = 'grapple: select 3' }) +vim.keymap.set('n', '4', 'Grapple select index=4', { desc = 'grapple: select 4' }) +vim.keymap.set('n', '5', 'Grapple select index=5', { desc = 'grapple: select 5' }) +vim.keymap.set('n', '[g', 'Grapple cycle_tags prev', { desc = 'grapple: prev tag' }) +vim.keymap.set('n', ']g', 'Grapple cycle_tags next', { desc = 'grapple: next tag' }) diff --git a/files/.config/nvim/lua/custom/plugins/neotree.lua b/files/.config/nvim/lua/packs/neotree.lua similarity index 100% rename from files/.config/nvim/lua/custom/plugins/neotree.lua rename to files/.config/nvim/lua/packs/neotree.lua diff --git a/files/.config/nvim/lua/packs/noice.lua b/files/.config/nvim/lua/packs/noice.lua new file mode 100644 index 0000000..2bf64c2 --- /dev/null +++ b/files/.config/nvim/lua/packs/noice.lua @@ -0,0 +1,284 @@ +-- packs/noice.lua + +local fn = vim.fn +local L = vim.log.levels + +local opts = { + cmdline = { + format = { + IncRename = { title = ' Rename ' }, + substitute = { + pattern = '^:%%?s/', + icon = ' ', + ft = 'regex', + title = '', + }, + input = { + icon = ' ', + lang = 'text', + view = 'cmdline_popup', + title = '', + }, + }, + }, + popupmenu = { + backend = 'nui', + }, + lsp = { + -- message = { + -- enabled = true, -- Enable Noice to handle LSP messages + -- }, + documentation = { + enabled = false, + opts = { + border = { style = 'rounded' }, + position = { row = 2 }, + }, + }, + signature = { + enabled = false, + opts = { + position = { row = 2 }, + }, + }, + hover = { + enabled = false, + silent = true, + }, + override = { + ['vim.lsp.util.convert_input_to_markdown_lines'] = false, + ['vim.lsp.util.stylize_markdown'] = false, + }, + }, + views = { + vsplit = { size = { width = 'auto' } }, + split = { win_options = { winhighlight = { Normal = 'Normal' } } }, + popup = { + border = { style = 'rounded', padding = { 0, 1 } }, + win_options = { winblend = 0 }, + }, + cmdline_popup = { + position = { row = 5, col = '50%' }, + size = { width = 'auto', height = 'auto' }, + border = { style = 'rounded', padding = { 0, 1 } }, + win_options = { + winblend = 0, + winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, + }, + }, + confirm = { + border = { style = 'rounded', padding = { 0, 1 }, text = { top = '' } }, + win_options = { + winblend = 0, + winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, + }, + }, + popupmenu = { + relative = 'editor', + position = { row = 9, col = '50%' }, + size = { width = 60, height = 10 }, + border = { style = 'rounded', padding = { 0, 1 } }, + win_options = { + winblend = 0, + -- Treat cmdline/popupmenu as "popup-normal" (not float-normal) + winhighlight = { Normal = 'NormalPopup', FloatBorder = 'PopupBorder' }, + }, + }, + }, + redirect = { view = 'popup', filter = { event = 'msg_show' } }, + routes = { + { + opts = { skip = true }, + filter = { + any = { + { event = 'msg_show', find = 'written' }, + { event = 'msg_show', find = '%d+ lines, %d+ bytes' }, + { event = 'msg_show', kind = 'search_count' }, + { event = 'msg_show', find = '%d+L, %d+B' }, + { event = 'msg_show', find = '^Hunk %d+ of %d' }, + { event = 'msg_show', find = '%d+ change' }, + { event = 'msg_show', find = '%d+ line' }, + { event = 'msg_show', find = '%d+ more line' }, + }, + }, + }, + { + view = 'vsplit', + filter = { event = 'msg_show', min_height = 20 }, + }, + { + view = 'mini', + filter = { + any = { + { event = 'msg_show', min_height = 10 }, + { event = 'msg_show', find = 'Treesitter' }, + }, + }, + opts = { timeout = 10000 }, + }, + { + view = 'mini', + filter = { event = 'notify', find = 'Type%-checking' }, + opts = { replace = true, merge = true, title = 'TSC' }, + stop = true, + }, + { + view = 'mini', + filter = { + any = { + { event = 'msg_show', find = '^E486:' }, + { event = 'notify', max_height = 1 }, + }, + }, -- minimise pattern not found messages + }, + { + view = 'mini', + filter = { + any = { + { warning = true }, + { event = 'msg_show', find = '^Warn' }, + { event = 'msg_show', find = '^W%d+:' }, + { event = 'msg_show', find = '^No hunks$' }, + }, + }, + opts = { + title = 'Warning', + level = L.WARN, + merge = false, + replace = false, + }, + }, + { + view = 'mini', + opts = { + title = 'Error', + level = L.ERROR, + merge = true, + replace = false, + }, + filter = { + any = { + { error = true }, + { event = 'msg_show', find = '^Error' }, + { event = 'msg_show', find = '^E%d+:' }, + }, + }, + }, + { + view = 'mini', + opts = { title = '' }, + filter = { kind = { 'emsg', 'echo', 'echomsg' } }, + }, + }, + commands = { + history = { view = 'vsplit' }, + }, + presets = { + inc_rename = true, + long_message_to_split = true, + lsp_doc_border = true, + }, +} + +-- Folke's noice enhancements +opts.routes = opts.routes or {} +-- Skip "No information available" notifications +table.insert(opts.routes, { + filter = { + event = 'notify', + find = 'No information available', + }, + opts = { skip = true }, +}) +table.insert(opts.routes, { + filter = { + event = 'notify', + find = 'LSP%[ruff%] Ruff failed to handle a request', + }, + opts = { skip = true }, +}) +table.insert(opts.routes, { + filter = { + event = 'msg_show', + find = 'client%.notify is deprecated', + }, + opts = { skip = true }, +}) + +-- Focus-aware notifications (send to notify_send when not focused) +local focused = true +vim.api.nvim_create_autocmd('FocusGained', { + callback = function() focused = true end, +}) +vim.api.nvim_create_autocmd('FocusLost', { + callback = function() focused = false end, +}) + +table.insert(opts.routes, 1, { + filter = { + ['not'] = { + event = 'lsp', + kind = 'progress', + }, + cond = function() return not focused and false end, + }, + view = 'notify_send', + opts = { stop = false, replace = true }, +}) + +-- Markdown keybindings in markdown files +vim.api.nvim_create_autocmd('FileType', { + pattern = 'markdown', + callback = function(event) + vim.schedule( + function() require('noice.text.markdown').keys(event.buf) end + ) + end, +}) + +require('noice').setup(opts) + +vim.api.nvim_create_user_command( + 'NotifyTest', + function() + vim.notify(('Noice mini toast\n'):rep(6), vim.log.levels.INFO, { + title = 'Noice Mini', + }) + end, + { desc = 'Test Noice mini notifications' } +) + +-- Noice uses `winhighlight` to map FloatBorder -> NoiceCmdlinePopupBorder. +-- Force these border groups to link to PopupBorder immediately (no scheduling), +-- otherwise they may keep their default DiagnosticSign* colors. +for _, name in ipairs({ + 'NoiceCmdlinePopupBorder', + 'NoiceCmdlinePopupBorderCmdline', + 'NoiceCmdlinePopupBorderSearch', + 'NoiceCmdlinePopupBorderFilter', + 'NoiceCmdlinePopupBorderHelp', + 'NoiceCmdlinePopupBorderSubstitute', + 'NoiceCmdlinePopupBorderIncRename', + 'NoiceCmdlinePopupBorderInput', + 'NoiceCmdlinePopupBorderLua', + 'NoiceConfirmBorder', +}) do + pcall(vim.api.nvim_set_hl, 0, name, { link = 'PopupBorder' }) +end + +vim.keymap.set({ 'n', 'i', 's' }, '', function() + if not require('noice.lsp').scroll(4) then return '' end +end, { silent = true, expr = true }) + +vim.keymap.set({ 'n', 'i', 's' }, '', function() + if not require('noice.lsp').scroll(-4) then return '' end +end, { silent = true, expr = true }) + +vim.keymap.set( + 'c', + '', + function() require('noice').redirect(fn.getcmdline()) end, + { + desc = 'redirect Cmdline', + } +) diff --git a/files/.config/nvim/lua/packs/obsidian.lua b/files/.config/nvim/lua/packs/obsidian.lua new file mode 100644 index 0000000..e5cdf22 --- /dev/null +++ b/files/.config/nvim/lua/packs/obsidian.lua @@ -0,0 +1,33 @@ +-- packs/obsidian.lua + +-- Keymaps registered immediately (plugin loaded on demand via commands) +vim.keymap.set('n', 'oo', ':ObsidianOpen', { desc = 'obsidian: open' }) +vim.keymap.set('n', 'on', ':ObsidianNew', { desc = 'obsidian: new' }) +vim.keymap.set('n', 'os', ':ObsidianSearch', { desc = 'obsidian: search' }) +vim.keymap.set('n', 'of', ':ObsidianQuickSwitch', { desc = 'obsidian: quick switch' }) + +-- Defer setup until actually used via command +vim.api.nvim_create_user_command('ObsidianSetup', function() + require('obsidian').setup({ + ui = { enable = false }, + workspaces = { + { + name = 'personal', + path = vim.g.obsidian, + }, + }, + }) +end, { desc = 'Setup obsidian.nvim' }) + +-- Auto-setup on first obsidian command invocation +vim.defer_fn(function() + require('obsidian').setup({ + ui = { enable = false }, + workspaces = { + { + name = 'personal', + path = vim.g.obsidian, + }, + }, + }) +end, 100) diff --git a/files/.config/nvim/lua/packs/remote.lua b/files/.config/nvim/lua/packs/remote.lua new file mode 100644 index 0000000..921a756 --- /dev/null +++ b/files/.config/nvim/lua/packs/remote.lua @@ -0,0 +1,11 @@ +-- packs/remote.lua + +-- nvim-dev-container: lazy, setup with empty opts when needed +vim.defer_fn(function() + local ok, devcontainer = pcall(require, 'devcontainer') + if ok then + devcontainer.setup({}) + end +end, 100) + +-- vim:foldmethod=marker diff --git a/files/.config/nvim/lua/packs/repl.lua b/files/.config/nvim/lua/packs/repl.lua new file mode 100644 index 0000000..e7b425d --- /dev/null +++ b/files/.config/nvim/lua/packs/repl.lua @@ -0,0 +1,14 @@ +-- packs/repl.lua + +require('kitty-repl').setup() +vim.keymap.set('n', ';r', ':KittyREPLRun', { desc = 'repl: run' }) +vim.keymap.set('x', ';s', ':KittyREPLSend', { desc = 'repl: send' }) +vim.keymap.set('n', ';s', ':KittyREPLSend', { desc = 'repl: send' }) +vim.keymap.set('n', '', ':KittyREPLSend', { desc = 'repl: send' }) +vim.keymap.set('n', ';c', ':KittyREPLClear', { desc = 'repl: clear' }) +vim.keymap.set('n', ';k', ':KittyREPLKill', { desc = 'repl: kill' }) +vim.keymap.set('n', ';l', ':KittyREPLRunAgain', { desc = 'repl: run again' }) +vim.keymap.set('n', ';w', ':KittyREPLStart', { desc = 'repl: start' }) +vim.keymap.set('n', ';a', function() + require('kitty-repl').repl_run_repl() +end, { desc = 'repl: run comments' }) diff --git a/files/.config/nvim/lua/packs/terminal.lua b/files/.config/nvim/lua/packs/terminal.lua new file mode 100644 index 0000000..a97ce11 --- /dev/null +++ b/files/.config/nvim/lua/packs/terminal.lua @@ -0,0 +1,88 @@ +-- packs/terminal.lua + +local T = require('tools') +local map = vim.keymap.set + +require('toggleterm').setup({ + open_mapping = [[]], + shade_filetypes = {}, + direction = 'horizontal', + autochdir = true, + persist_mode = true, + insert_mappings = false, + start_in_insert = true, + highlights = { + FloatBorder = { link = 'FloatBorder' }, + -- Make floating terminals match the main Normal background. + NormalFloat = { link = 'Normal' }, + }, + float_opts = { + -- border = mrl.ui.current.border, + winblend = 3, + }, + size = function(term) + if term.direction == 'horizontal' then + return 15 + elseif term.direction == 'vertical' then + return math.floor(vim.o.columns * 0.4) + end + end, +}) + +local float_handler = function(term) + if not T.falsy(vim.fn.mapcheck('jk', 't')) then + vim.keymap.del('t', 'jk', { buffer = term.bufnr }) + vim.keymap.del('t', '', { buffer = term.bufnr }) + end +end + +local Terminal = require('toggleterm.terminal').Terminal + +local lazygit = Terminal:new({ + cmd = 'lazygit', + dir = 'git_dir', + hidden = true, + direction = 'float', + on_open = float_handler, +}) + +local lazydocker = Terminal:new({ + cmd = 'lazydocker', + dir = 'git_dir', + hidden = true, + direction = 'float', + on_open = float_handler, +}) + +local btop = Terminal:new({ + cmd = 'btop', + hidden = true, + direction = 'float', + on_open = float_handler, + highlights = { + FloatBorder = { link = 'FloatBorder' }, + NormalFloat = { link = 'Normal' }, + }, +}) + +local gh_dash = Terminal:new({ + cmd = 'gh dash', + hidden = true, + direction = 'float', + on_open = float_handler, + float_opts = { + height = function() return math.floor(vim.o.lines * 0.8) end, + width = function() return math.floor(vim.o.columns * 0.95) end, + }, +}) + +map('n', 'lh', function() gh_dash:toggle() end, { + desc = 'toggleterm: toggle github dashboard', +}) +map('n', 'lg', function() lazygit:toggle() end, { + desc = 'toggleterm: toggle lazygit', +}) +map('n', 'ld', function() lazydocker:toggle() end, { + desc = 'toggleterm: toggle lazydocker', +}) +T.command('Btop', function() btop:toggle() end) diff --git a/files/.config/nvim/lua/packs/testing.lua b/files/.config/nvim/lua/packs/testing.lua new file mode 100644 index 0000000..fe82aa0 --- /dev/null +++ b/files/.config/nvim/lua/packs/testing.lua @@ -0,0 +1,56 @@ +-- packs/testing.lua + +---@diagnostic disable: missing-fields +local function neotest() return require('neotest') end +local function open() neotest().output.open({ enter = true, short = false }) end +local function run_file() neotest().run.run(vim.fn.expand('%')) end +local function run_file_sync() + neotest().run.run({ vim.fn.expand('%'), concurrent = false }) +end +local function nearest() neotest().run.run() end +local function next_failed() neotest().jump.prev({ status = 'failed' }) end +local function prev_failed() neotest().jump.next({ status = 'failed' }) end +local function toggle_summary() neotest().summary.toggle() end +local function cancel() neotest().run.stop({ interactive = true }) end + +-- Keymaps registered immediately +vim.keymap.set('n', 'ts', toggle_summary, { desc = 'neotest: toggle summary' }) +vim.keymap.set('n', 'to', open, { desc = 'neotest: output' }) +vim.keymap.set('n', 'tn', nearest, { desc = 'neotest: run' }) +vim.keymap.set('n', 'tf', run_file, { desc = 'neotest: run file' }) +vim.keymap.set('n', 'tF', run_file_sync, { desc = 'neotest: run file synchronously' }) +vim.keymap.set('n', 'tc', cancel, { desc = 'neotest: cancel' }) +vim.keymap.set('n', '[n', next_failed, { desc = 'jump to next failed test' }) +vim.keymap.set('n', ']n', prev_failed, { desc = 'jump to previous failed test' }) + +-- Neotest setup on BufReadPre (heavy plugin) +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlNeotest', { clear = true }), + callback = function() + local namespace = vim.api.nvim_create_namespace('neotest') + vim.diagnostic.config({ + virtual_text = { + format = function(diagnostic) + local value = diagnostic.message + :gsub('\n', ' ') + :gsub('\t', ' ') + :gsub('%s+', ' ') + :gsub('^%s+', '') + return value + end, + }, + }, namespace) + + require('neotest').setup({ + discovery = { enabled = true }, + diagnostic = { enabled = true }, + floating = { border = 'rounded' }, + quickfix = { enabled = false, open = true }, + adapters = { + require('neotest-plenary'), + require('neotest-python'), + }, + }) + end, +}) diff --git a/files/.config/nvim/lua/packs/todo.lua b/files/.config/nvim/lua/packs/todo.lua new file mode 100644 index 0000000..04c0d71 --- /dev/null +++ b/files/.config/nvim/lua/packs/todo.lua @@ -0,0 +1,42 @@ +-- packs/todo.lua + +-- todo-comments (on BufReadPre) +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlTodo', { clear = true }), + callback = function() + local todo_comments = require('todo-comments') + vim.keymap.set('n', ']t', function() todo_comments.jump_next() end, { + desc = 'Next todo comment', + }) + vim.keymap.set('n', '[t', function() todo_comments.jump_prev() end, { + desc = 'Previous todo comment', + }) + todo_comments.setup({ signs = false }) + end, +}) + +-- trouble keymaps (registered immediately) +vim.keymap.set('n', 'xx', 'Trouble diagnostics toggle', { + desc = 'trouble: workspace diagnostics', +}) +vim.keymap.set('n', 'xd', 'Trouble diagnostics toggle filter.buf=0', { + desc = 'trouble: document diagnostics', +}) +vim.keymap.set('n', 'xq', 'Trouble qflist toggle', { + desc = 'trouble: quickfix list', +}) +vim.keymap.set('n', 'xl', 'Trouble loclist toggle', { + desc = 'trouble: location list', +}) +vim.keymap.set('n', 'xs', 'Trouble symbols toggle', { + desc = 'trouble: document symbols', +}) +vim.keymap.set('n', 'xt', 'Trouble todo toggle', { + desc = 'trouble: todos', +}) + +-- trouble setup (on command invocation; setup with empty opts) +vim.defer_fn(function() + require('trouble').setup({}) +end, 100) diff --git a/files/.config/nvim/lua/packs/treesitter.lua b/files/.config/nvim/lua/packs/treesitter.lua new file mode 100644 index 0000000..837daeb --- /dev/null +++ b/files/.config/nvim/lua/packs/treesitter.lua @@ -0,0 +1,85 @@ +-- packs/treesitter.lua + +-- treesitter-context highlight init (runs immediately, before plugin loads) +do + local highlight = require('highlight') + highlight.plugin('treesitter-context', { + { TreesitterContextSeparator = { link = 'Dim' } }, + { TreesitterContext = { inherit = 'Normal' } }, + { TreesitterContextLineNumber = { inherit = 'LineNr' } }, + }) +end + +-- treesj keymap (registered immediately) +vim.keymap.set('n', 'gS', 'TSJSplit', { desc = 'split expression to multiple lines' }) +vim.keymap.set('n', 'gJ', 'TSJJoin', { desc = 'join expression to single line' }) + +-- treesitter-context keymap +vim.keymap.set('n', 'sc', 'TSContext toggle', { + desc = 'Toggle [s]cope [c]ontext', +}) + +-- Main treesitter setup (on BufReadPost) +vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlTreesitter', { clear = true }), + callback = function() + -- nvim-treesitter v1 API: configs module is gone + require('nvim-treesitter').setup({ + -- stylua: ignore + ensure_installed = { + 'c', 'vim', 'vimdoc', 'query', 'lua', 'luadoc', 'luap', + 'diff', 'regex', 'gitcommit', 'git_config', 'git_rebase', 'markdown', 'markdown_inline', + 'bash', 'html', 'json', 'javascript', 'typescript', 'tsx', 'yaml', 'css', 'prisma', + 'svelte', 'graphql', 'dockerfile', 'gitignore', 'python', 'go', 'rust', + }, + }) + + -- textobjects (nvim-treesitter-textobjects still works with v1) + require('nvim-treesitter-textobjects').setup({ + select = { + enable = true, + lookahead = true, + include_surrounding_whitespace = true, + keymaps = { + ['af'] = { query = '@function.outer', desc = 'ts: all function' }, + ['if'] = { query = '@function.inner', desc = 'ts: inner function' }, + ['ac'] = { query = '@class.outer', desc = 'ts: all class' }, + ['ic'] = { query = '@class.inner', desc = 'ts: inner class' }, + ['aC'] = { query = '@conditional.outer', desc = 'ts: all conditional' }, + ['iC'] = { query = '@conditional.inner', desc = 'ts: inner conditional' }, + ['aL'] = { query = '@assignment.lhs', desc = 'ts: assignment lhs' }, + ['aR'] = { query = '@assignment.rhs', desc = 'ts: assignment rhs' }, + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + [']m'] = '@function.outer', + [']M'] = '@class.outer', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[M'] = '@class.outer', + }, + }, + }) + + -- treesj setup + require('treesj').setup({ + use_default_keymaps = false, + }) + + -- nvim-ts-autotag setup + require('nvim-ts-autotag').setup({}) + + -- treesitter-context setup + require('treesitter-context').setup({ + enable = false, + multiline_threshold = 10, + separator = '─', + mode = 'cursor', + }) + end, +}) diff --git a/files/.config/nvim/lua/packs/ui.lua b/files/.config/nvim/lua/packs/ui.lua new file mode 100644 index 0000000..ef0d4af --- /dev/null +++ b/files/.config/nvim/lua/packs/ui.lua @@ -0,0 +1,349 @@ +-- packs/ui.lua + +local UI = require('tools').ui +local icons = UI.icons + +-- --------------------------------------------------------------------------- +-- indent-blankline (on BufReadPre) +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlIndentBlankline', { clear = true }), + callback = function() + require('ibl').setup({ + indent = { char = '┊' }, + exclude = { + filetypes = { 'notify', 'noice', 'noice_popup', 'noice_cmdline' }, + }, + }) + end, +}) + +-- --------------------------------------------------------------------------- +-- nvim-navic (on LspAttach) +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlNavic', { clear = true }), + callback = function(args) + require('nvim-navic').setup({ + highlight = true, + separator = ' › ', + depth_limit = 5, + depth_limit_indicator = '..', + }) + -- Attach navic to the first LSP client that triggers this + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client and client.server_capabilities.documentSymbolProvider then + require('nvim-navic').attach(client, args.buf) + end + -- Also register the general autocmd for future LSP attaches + vim.api.nvim_create_autocmd('LspAttach', { + callback = function(inner_args) + local c = vim.lsp.get_client_by_id(inner_args.data.client_id) + if c and c.server_capabilities.documentSymbolProvider then + require('nvim-navic').attach(c, inner_args.buf) + end + end, + }) + end, +}) + +-- --------------------------------------------------------------------------- +-- incline.nvim (deferred - VeryLazy equivalent) +-- --------------------------------------------------------------------------- +vim.defer_fn(function() + local incline = require('incline') + + local function set_hls() + local pal = UI.palette or {} + local bg = '#121212' + vim.api.nvim_set_hl(0, 'InclineNormal', { + fg = pal.whitesmoke or 'NONE', + bg = bg, + }) + vim.api.nvim_set_hl(0, 'InclineNormalNC', { + fg = pal.light_gray or pal.comment_grey or 'NONE', + bg = bg, + }) + vim.api.nvim_set_hl(0, 'InclineTitle', { + fg = pal.bright_blue or pal.blue or 'NONE', + bg = bg, + bold = true, + }) + vim.api.nvim_set_hl(0, 'InclineModified', { + fg = pal.dark_orange or 'NONE', + bg = bg, + }) + vim.api.nvim_set_hl(0, 'InclineGit', { + fg = pal.teal or pal.green or 'NONE', + bg = bg, + }) + end + + set_hls() + vim.api.nvim_create_autocmd('ColorScheme', { + group = vim.api.nvim_create_augroup('MrlIncline', { clear = true }), + callback = set_hls, + }) + + local devicons_ok, devicons = pcall(require, 'nvim-web-devicons') + + -- Use incline's render function so we can style per-window content. + incline.setup({ + window = { + placement = { horizontal = 'right', vertical = 'top' }, + margin = { vertical = 1, horizontal = 1 }, + padding = 1, + winhighlight = { + Normal = 'InclineNormal', + NormalNC = 'InclineNormalNC', + }, + }, + ignore = { + buftypes = { 'terminal', 'nofile', 'prompt', 'quickfix' }, + filetypes = { + 'neo-tree', + 'NvimTree', + 'undotree', + 'toggleterm', + 'Trouble', + 'noice', + 'notify', + 'qf', + 'diff', + 'alpha', + 'startify', + 'help', + 'gitcommit', + 'NeogitStatus', + 'NeogitCommitMessage', + 'DiffviewFiles', + 'DiffviewFileHistory', + }, + }, + render = function(props) + local buf = props.buf + local ft = vim.bo[buf].ft + local bt = vim.bo[buf].bt + local decor = UI.decorations.get({ + ft = ft, + bt = bt, + setting = 'winbar', + }) + if + (decor and (decor.ft == false or decor.bt == false)) + or (decor and (decor.ft == 'ignore' or decor.bt == 'ignore')) + then + return {} + end + + local name = vim.api.nvim_buf_get_name(buf) + if name == '' then + name = '[No Name]' + else + name = vim.fn.fnamemodify(name, ':t') + end + + local parts = {} + if devicons_ok then + local ext = vim.fn.fnamemodify(name, ':e') + local icon, icon_color = + devicons.get_icon_color(name, ext, { default = true }) + if icon then + table.insert(parts, { icon .. ' ', guifg = icon_color }) + end + else + table.insert( + parts, + { icons.documents.file .. ' ', group = 'InclineTitle' } + ) + end + + table.insert(parts, { name, group = 'InclineTitle' }) + + if vim.bo[buf].modified then + table.insert(parts, { + ' ' .. icons.misc.circle, + group = 'InclineModified', + }) + end + + return parts + end, + }) +end, 100) + +-- --------------------------------------------------------------------------- +-- ccc.nvim (cmd-loaded, setup immediately) +-- --------------------------------------------------------------------------- +do + local ok, ccc = pcall(require, 'ccc') + if ok then + ccc.setup({ + -- win_opts = { border = UI.border }, + highlighter = { + auto_enable = false, + excludes = { + 'dart', + 'lazy', + 'orgagenda', + 'org', + 'NeogitStatus', + 'toggleterm', + }, + }, + }) + end +end + +-- --------------------------------------------------------------------------- +-- symbol-usage.nvim (on LspAttach) +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlSymbolUsage', { clear = true }), + callback = function() + ---@diagnostic disable: undefined-field + local symbol_usage = require('symbol-usage') + symbol_usage.setup({ + vt_position = 'end_of_line', + text_format = function(symbol) + local res = {} + local ins = table.insert + + local round_start = { '', 'SymbolUsageLeft' } + local round_end = { '', 'SymbolUsageRight' } + + if symbol.references then + local usage = symbol.references <= 1 and 'usage' or 'usages' + local num = symbol.references == 0 and 'no' or symbol.references + ins(res, round_start) + ins(res, { '󰌹 ', 'SymbolUsageRef' }) + ins(res, { ('%s %s'):format(num, usage), 'SymbolUsageContent' }) + ins(res, round_end) + end + + if symbol.definition then + if #res > 0 then table.insert(res, { ' ', 'NonText' }) end + ins(res, round_start) + ins(res, { '󰳽 ', 'SymbolUsageDef' }) + ins(res, { symbol.definition .. ' defs', 'SymbolUsageContent' }) + ins(res, round_end) + end + + if symbol.implementation then + if #res > 0 then table.insert(res, { ' ', 'NonText' }) end + ins(res, round_start) + ins(res, { '󰡱 ', 'SymbolUsageImpl' }) + ins( + res, + { symbol.implementation .. ' impls', 'SymbolUsageContent' } + ) + ins(res, round_end) + end + + return res + end, + }) + end, +}) + +-- --------------------------------------------------------------------------- +-- undotree +-- --------------------------------------------------------------------------- +vim.keymap.set('n', 'u', 'UndotreeToggle', { desc = 'undotree: toggle' }) +vim.api.nvim_create_autocmd('VimEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlUndotree', { clear = true }), + callback = function() + vim.g.undotree_TreeNodeShape = '◉' -- Alternative: '◉' ◦ + vim.g.undotree_SetFocusWhenToggle = 1 + end, +}) + +-- --------------------------------------------------------------------------- +-- numb.nvim (on CmdlineEnter) +-- --------------------------------------------------------------------------- +vim.api.nvim_create_autocmd('CmdlineEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlNumb', { clear = true }), + callback = function() + require('numb').setup({}) + end, +}) + +-- --------------------------------------------------------------------------- +-- rainbow-delimiters (on BufReadPost) +-- --------------------------------------------------------------------------- + +-- init equivalent: set up rainbow_delimiters global early +do + local rd = vim.g.rainbow_delimiters or {} + rd.highlight = rd.highlight + or { + 'RainbowDelimiterRed', + 'RainbowDelimiterYellow', + 'RainbowDelimiterBlue', + 'RainbowDelimiterOrange', + 'RainbowDelimiterGreen', + 'RainbowDelimiterViolet', + 'RainbowDelimiterCyan', + } + vim.g.rainbow_delimiters = rd +end + +vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlRainbowDelimiters', { clear = true }), + callback = function() + local ok, rainbow_delimiters = pcall(require, 'rainbow-delimiters') + if not ok then return end + + -- Akinsho-style: global strategy + default query name. + local rd = vim.g.rainbow_delimiters or {} + rd.strategy = { + [''] = rainbow_delimiters.strategy['global'], + } + rd.query = { + [''] = 'rainbow-delimiters', + html = 'rainbow-delimiters', -- enable our html tag query override + svelte = 'rainbow-delimiters', + } + vim.g.rainbow_delimiters = rd + + -- Palette-driven colors for the delimiter groups. + local api = vim.api + local group = + api.nvim_create_augroup('MrlRainbowDelimitersColors', { clear = true }) + + local function set_hls() + local pal = UI.palette or {} + local function as_hex(v, fallback) + if type(v) == 'string' or type(v) == 'number' then return v end + if type(v) == 'table' then return v.base or fallback end + return fallback + end + local colors = { + as_hex(pal.red, '#E06C75'), + as_hex(pal.light_yellow, '#E5C07B'), + as_hex(pal.blue, '#61AFEF'), + as_hex(pal.dark_orange, '#D19A66'), + as_hex(pal.green, '#98C379'), + as_hex(pal.magenta, '#C678DD'), + as_hex(pal.teal, '#56B6C2'), + } + local cur = vim.g.rainbow_delimiters or {} + local names = cur.highlight or {} + for i, name in ipairs(names) do + api.nvim_set_hl(0, name, { fg = colors[i] }) + end + end + + set_hls() + api.nvim_create_autocmd('ColorScheme', { + group = group, + callback = set_hls, + }) + end, +}) diff --git a/files/.config/nvim/lua/custom/config/vimtex.lua b/files/.config/nvim/lua/packs/vimtex.lua similarity index 100% rename from files/.config/nvim/lua/custom/config/vimtex.lua rename to files/.config/nvim/lua/packs/vimtex.lua diff --git a/files/.config/nvim/lua/packs/whichkey.lua b/files/.config/nvim/lua/packs/whichkey.lua new file mode 100644 index 0000000..3c49de6 --- /dev/null +++ b/files/.config/nvim/lua/packs/whichkey.lua @@ -0,0 +1,41 @@ +-- packs/whichkey.lua + +vim.defer_fn(function() + local wk = require('which-key') + wk.setup({ + win = { + border = false, + wo = { + winhl = 'Normal:StatusLine,NormalFloat:StatusLine,FloatBorder:StatusLine', + }, + }, + layout = { align = 'center' }, + -- preset = 'modern', + }) + + -- Sync all WhichKey highlight bg to StatusLine + local function sync_hls() + local bg = + vim.api.nvim_get_hl(0, { name = 'StatusLine', link = false }).bg + if not bg then return end + bg = ('#%06x'):format(bg) + for _, name in ipairs({ + 'WhichKeyNormal', + 'WhichKey', + 'WhichKeyDesc', + 'WhichKeyGroup', + 'WhichKeySeparator', + 'WhichKeyValue', + 'WhichKeyBorder', + 'WhichKeyTitle', + }) do + local hl = vim.api.nvim_get_hl(0, { name = name, link = false }) + hl.bg = bg + hl.ctermbg = nil + vim.api.nvim_set_hl(0, name, hl) + end + end + + sync_hls() + vim.api.nvim_create_autocmd('ColorScheme', { callback = sync_hls }) +end, 100) diff --git a/files/.config/nvim/lua/tools.lua b/files/.config/nvim/lua/tools.lua index a57085f..a31d543 100644 --- a/files/.config/nvim/lua/tools.lua +++ b/files/.config/nvim/lua/tools.lua @@ -383,6 +383,184 @@ end -- }}} -------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-- Highlight utilities {{{ +-------------------------------------------------------------------------------- + +---@alias HLAttrs {from: string, attr: "fg" | "bg", alter: integer} + +---@class HLData +---@field fg string +---@field bg string +---@field bold boolean +---@field italic boolean +---@field undercurl boolean +---@field underline boolean +---@field underdotted boolean +---@field underdashed boolean +---@field underdouble boolean +---@field strikethrough boolean +---@field reverse boolean +---@field nocombine boolean +---@field link string +---@field default boolean + +---@class HLArgs +---@field blend integer? +---@field fg (string | HLAttrs)? +---@field bg (string | HLAttrs)? +---@field sp (string | HLAttrs)? +---@field bold boolean? +---@field italic boolean? +---@field undercurl boolean? +---@field underline boolean? +---@field underdotted boolean? +---@field underdashed boolean? +---@field underdouble boolean? +---@field strikethrough boolean? +---@field reverse boolean? +---@field nocombine boolean? +---@field link string? +---@field default boolean? +---@field clear boolean? +---@field inherit string? + +local hl_enable_italics = true +local hl_attrs = { + fg = true, + bg = true, + sp = true, + blend = true, + bold = true, + italic = hl_enable_italics, + standout = true, + underline = true, + undercurl = true, + underdouble = true, + underdotted = true, + underdashed = true, + strikethrough = true, + reverse = true, + nocombine = true, + link = true, + default = true, +} + +---@private +---@param opts {name: string?, link: boolean?}? +---@param ns integer? +---@return HLData +local function hl_get_as_hex(opts, ns) + ns, opts = ns or 0, opts or {} + opts.link = opts.link ~= nil and opts.link or false + local hl = api.nvim_get_hl(ns, opts) + hl.fg = hl.fg and ('#%06x'):format(hl.fg) + hl.bg = hl.bg and ('#%06x'):format(hl.bg) + return hl +end + +---Get the value of a highlight group, handling errors and fallbacks. +---If no attribute is specified return the entire highlight table. +---@param group string +---@param attribute string? +---@param fallback string? +---@return string +---@overload fun(group: string): HLData +local function hl_get(group, attribute, fallback) + assert(group, 'cannot get a highlight without specifying a group name') + local data = hl_get_as_hex({ name = group }) + if not attribute then return data end + assert(hl_attrs[attribute], ('the attribute passed in is invalid: %s'):format(attribute)) + local color = data[attribute] or fallback + if not color then return 'NONE' end + return color +end + +---@param hl string | HLAttrs +---@param attr string +---@return HLData +local function hl_resolve_from_attribute(hl, attr) + if type(hl) ~= 'table' or not hl.from then return hl end + local colour = hl_get(hl.from, hl.attr or attr) + if hl.alter then colour = M.tint(colour, hl.alter) end + return colour +end + +---Set a neovim highlight with syntactic sugar for deriving colors from other groups. +---@param name string +---@param opts HLArgs +---@overload fun(ns: integer, name: string, opts: HLArgs) +local function hl_set(ns, name, opts) + if type(ns) == 'string' and type(name) == 'table' then + opts, name, ns = name, ns, 0 + end + vim.validate('opts', opts, 'table') + vim.validate('name', name, 'string') + vim.validate('ns', ns, 'number') + local hl = opts.clear and {} or hl_get_as_hex({ name = opts.inherit or name }) + for attribute, hl_data in pairs(opts) do + local new_data = hl_resolve_from_attribute(hl_data, attribute) + if hl_attrs[attribute] then hl[attribute] = new_data end + end + M.pcall(fmt('setting highlight "%s"', name), api.nvim_set_hl, ns, name, hl) +end + +---Apply a list of highlights. +---@param hls {[string]: HLArgs}[] +---@param namespace integer? +local function hl_all(hls, namespace) + vim.iter(hls):each(function(hl) hl_set(namespace or 0, next(hl)) end) +end + +---Set window local highlights. +---@param name string +---@param win_id number +---@param hls HLArgs[] +local function hl_set_winhl(name, win_id, hls) + local namespace = api.nvim_create_namespace(name) + hl_all(hls, namespace) + api.nvim_win_set_hl_ns(win_id, namespace) +end + +---@param theme {[string]: HLArgs[]} +---@return HLArgs[] +local function hl_add_theme_overrides(theme) + local res, seen = {}, {} + local list = vim.list_extend(theme[vim.g.colors_name] or {}, theme['*'] or {}) + for _, hl in ipairs(list) do + local n = next(hl) + if not seen[n] then res[#res + 1] = hl end + seen[n] = true + end + return res +end + +---Apply highlights for a plugin and refresh on colorscheme change. +---@param name string plugin name +---@param opts HLArgs[] | { theme: table } +local function hl_plugin(name, opts) + if opts.theme then + opts = hl_add_theme_overrides(opts.theme) + if not next(opts) then return end + end + vim.schedule(function() hl_all(opts) end) + M.augroup(fmt('%sHighlightOverrides', name:gsub('^%l', string.upper)), { + event = 'ColorScheme', + command = function() vim.schedule(function() hl_all(opts) end) end, + }) +end + +M.hl = { + get = hl_get, + set = hl_set, + all = hl_all, + plugin = hl_plugin, + set_winhl = hl_set_winhl, +} + +-- }}} +-------------------------------------------------------------------------------- + -------------------------------------------------------------------------------- -- UI {{{ -------------------------------------------------------------------------------- @@ -693,14 +871,7 @@ M.ui.border = 'rounded' M.ui.current = { border = 'rounded', - float_bg = function() - local ok, HL = pcall(require, 'highlight') - if ok and HL and HL.get then return HL.get('Normal', 'bg') end - local ok2, hl = - pcall(vim.api.nvim_get_hl, 0, { name = 'Normal', link = false }) - if ok2 and hl and hl.bg then return ('#%06x'):format(hl.bg) end - return 'NONE' - end, + float_bg = function() return hl_get('Normal', 'bg') end, } -- }}} diff --git a/files/.config/nvim/nvim-pack-lock.json b/files/.config/nvim/nvim-pack-lock.json new file mode 100644 index 0000000..5d3e1e8 --- /dev/null +++ b/files/.config/nvim/nvim-pack-lock.json @@ -0,0 +1,452 @@ +{ + "plugins": { + "Comment.nvim": { + "rev": "e30b7f2008e52442154b66f7c519bfd2f1e32acb", + "src": "https://github.com/numToStr/Comment.nvim" + }, + "blink-cmp-avante": { + "rev": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5", + "src": "https://github.com/Kaiser-Yang/blink-cmp-avante" + }, + "blink.cmp": { + "rev": "5e088706d92da09949e081cc4d49e2c9ba8cfc8c", + "src": "https://github.com/saghen/blink.cmp" + }, + "bufferline.nvim": { + "rev": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3", + "src": "https://github.com/akinsho/bufferline.nvim" + }, + "ccc.nvim": { + "rev": "9d1a256e006decc574789dfc7d628ca11644d4c2", + "src": "https://github.com/uga-rosa/ccc.nvim" + }, + "codecompanion.nvim": { + "rev": "e0fe366cf3af6c80dcac86cb053ef3fe48aae911", + "src": "https://github.com/olimorris/codecompanion.nvim" + }, + "conform.nvim": { + "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", + "src": "https://github.com/stevearc/conform.nvim" + }, + "copilot.lua": { + "rev": "faa347cef2a9429eec14dada549e000a3b8d0fc9", + "src": "https://github.com/zbirenbaum/copilot.lua" + }, + "crates.nvim": { + "rev": "ac9fa498a9edb96dc3056724ff69d5f40b898453", + "src": "https://github.com/saecki/crates.nvim" + }, + "csvview.nvim": { + "rev": "7022e18a0fbae9aecf99a3ba02b2a541edc2b8a1", + "src": "https://github.com/hat0uma/csvview.nvim" + }, + "debugprint.nvim": { + "rev": "a95f658add600de701763e2956a86278d9d7e2a8", + "src": "https://github.com/andrewferrier/debugprint.nvim" + }, + "diffview.nvim": { + "rev": "4516612fe98ff56ae0415a259ff6361a89419b0a", + "src": "https://github.com/sindrets/diffview.nvim" + }, + "dressing.nvim": { + "rev": "2d7c2db2507fa3c4956142ee607431ddb2828639", + "src": "https://github.com/stevearc/dressing.nvim" + }, + "fidget.nvim": { + "rev": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970", + "src": "https://github.com/j-hui/fidget.nvim" + }, + "file-line": { + "rev": "559088afaf10124ea663ee0f4f73b1de48fb1632", + "src": "https://github.com/bogado/file-line" + }, + "fold-cycle.nvim": { + "rev": "6144567b3307bbcfed0e5b2dd23acb9576575d9e", + "src": "https://github.com/jghauser/fold-cycle.nvim" + }, + "friendly-snippets": { + "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", + "src": "https://github.com/rafamadriz/friendly-snippets" + }, + "fzf-lua": { + "rev": "c9e7b7bfbd01f949164988ee1684035468e1995c", + "src": "https://github.com/ibhagwan/fzf-lua" + }, + "git-conflict.nvim": { + "rev": "a1badcd070d176172940eb55d9d59029dad1c5a6", + "src": "https://github.com/akinsho/git-conflict.nvim" + }, + "git-worktree.nvim": { + "rev": "f247308e68dab9f1133759b05d944569ad054546", + "src": "https://github.com/ThePrimeagen/git-worktree.nvim" + }, + "gitgraph.nvim": { + "rev": "c16daa7d7dd597caf9085644c009cfa80b75db8e", + "src": "https://github.com/isakbm/gitgraph.nvim" + }, + "gitlinker.nvim": { + "rev": "cc59f732f3d043b626c8702cb725c82e54d35c25", + "src": "https://github.com/ruifm/gitlinker.nvim" + }, + "gitsigns.nvim": { + "rev": "caa98e2e5e4c23a1652c23be839d2e1722cecc29", + "src": "https://github.com/lewis6991/gitsigns.nvim" + }, + "glance.nvim": { + "rev": "bf86d8b79dce808e65fdb6e9269d0b4ed6d2eefc", + "src": "https://github.com/DNLHC/glance.nvim" + }, + "grapple.nvim": { + "rev": "b41ddfc1c39f87f3d1799b99c2f0f1daa524c5f7", + "src": "https://github.com/cbochs/grapple.nvim" + }, + "image.nvim": { + "rev": "da2be65c153ba15a14a342b05591652a6df70d58", + "src": "https://github.com/3rd/image.nvim" + }, + "inc-rename.nvim": { + "rev": "0074b551a17338ccdcd299bd86687cc651bcb33d", + "src": "https://github.com/smjonas/inc-rename.nvim" + }, + "incline.nvim": { + "rev": "8b54c59bcb23366645ae10edca6edfb9d3a0853e", + "src": "https://github.com/b0o/incline.nvim" + }, + "indent-blankline.nvim": { + "rev": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03", + "src": "https://github.com/lukas-reineke/indent-blankline.nvim" + }, + "key-analyzer.nvim": { + "rev": "4e4bef34498e821bcbd5203f44db8b67e4f10e04", + "src": "https://github.com/meznaric/key-analyzer.nvim" + }, + "kitty-repl.nvim": { + "rev": "1d52b999b9cf9f2e0ce133fe9445469c796e149c", + "src": "https://github.com/marromlam/kitty-repl.nvim" + }, + "lazydev.nvim": { + "rev": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d", + "src": "https://github.com/folke/lazydev.nvim" + }, + "lspkind.nvim": { + "rev": "c7274c48137396526b59d86232eabcdc7fed8a32", + "src": "https://github.com/onsails/lspkind.nvim" + }, + "markdown-table-mode.nvim": { + "rev": "bb1ea9b76c1b29e15e14806fdfbb2319df5c06f1", + "src": "https://github.com/Kicamon/markdown-table-mode.nvim" + }, + "mason-lspconfig.nvim": { + "rev": "25f609e7fca78af7cede4f9fa3af8a94b1c4950b", + "src": "https://github.com/mason-org/mason-lspconfig.nvim" + }, + "mason-nvim-dap.nvim": { + "rev": "9a10e096703966335bd5c46c8c875d5b0690dade", + "src": "https://github.com/jay-babu/mason-nvim-dap.nvim" + }, + "mason-tool-installer.nvim": { + "rev": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc", + "src": "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim" + }, + "mason.nvim": { + "rev": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65", + "src": "https://github.com/mason-org/mason.nvim" + }, + "mcphub.nvim": { + "rev": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f", + "src": "https://github.com/ravitemer/mcphub.nvim" + }, + "mini.ai": { + "rev": "4b0a6207341d895b6cfe9bcb1e4d3e8607bfe4f4", + "src": "https://github.com/echasnovski/mini.ai" + }, + "mini.align": { + "rev": "4d45e0e4f1fd8baefb6ae52a44659704fe7ebe8b", + "src": "https://github.com/echasnovski/mini.align" + }, + "mini.animate": { + "rev": "8814b56e282cd86635ce9a392ed56b6a85f59731", + "src": "https://github.com/echasnovski/mini.animate" + }, + "mini.bufremove": { + "rev": "ee69f823f84508c556127a5882760d9783692023", + "src": "https://github.com/echasnovski/mini.bufremove" + }, + "mini.diff": { + "rev": "ff3cd5e76e812fa18bde0f8126d6f3bb62008c79", + "src": "https://github.com/echasnovski/mini.diff" + }, + "mini.hipatterns": { + "rev": "2c5dce6dc7443de814d16f7470549811ee86e664", + "src": "https://github.com/echasnovski/mini.hipatterns" + }, + "mini.icons": { + "rev": "5b9076dae1bfbe47ba4a14bc8b967cde0ab5d77e", + "src": "https://github.com/echasnovski/mini.icons" + }, + "mini.misc": { + "rev": "de8947231c29012271722651aa07f6749c41d1ed", + "src": "https://github.com/echasnovski/mini.misc" + }, + "mini.move": { + "rev": "b8ba0b77e91b5f0fe8e014e03f7f59799dec1d96", + "src": "https://github.com/echasnovski/mini.move" + }, + "mini.pairs": { + "rev": "b7fde3719340946feb75017ef9d75edebdeb0566", + "src": "https://github.com/echasnovski/mini.pairs" + }, + "mini.splitjoin": { + "rev": "8112e794cbb022b9d4b7af60b64e9896930f1697", + "src": "https://github.com/echasnovski/mini.splitjoin" + }, + "mini.starter": { + "rev": "cdf909e5bda577e09c61fa6d9a36bb2a88dbc636", + "src": "https://github.com/echasnovski/mini.starter" + }, + "mini.surround": { + "rev": "d205d1741d1fcc1f3117b4e839bf00f74ad72fa2", + "src": "https://github.com/echasnovski/mini.surround" + }, + "mini.trailspace": { + "rev": "27acb69562a4742256ab3e4b0127391fcb49dbb3", + "src": "https://github.com/echasnovski/mini.trailspace" + }, + "neogit": { + "rev": "4681c1fdac1b730592ae195576e87406f7255750", + "src": "https://github.com/NeogitOrg/neogit" + }, + "neotest": { + "rev": "72bc8f1ec62a590fb47368c81f89610e0f353e28", + "src": "https://github.com/nvim-neotest/neotest" + }, + "neotest-plenary": { + "rev": "3523adcf9ffaad1911960c5813b0136c1b63a2ec", + "src": "https://github.com/rcarriga/neotest-plenary" + }, + "neotest-python": { + "rev": "b0d3a861bd85689d8ed73f0590c47963a7eb1bf9", + "src": "https://github.com/nvim-neotest/neotest-python" + }, + "noice.nvim": { + "rev": "7bfd942445fb63089b59f97ca487d605e715f155", + "src": "https://github.com/folke/noice.nvim" + }, + "nui.nvim": { + "rev": "de740991c12411b663994b2860f1a4fd0937c130", + "src": "https://github.com/MunifTanjim/nui.nvim" + }, + "numb.nvim": { + "rev": "12ef3913dea8727d4632c6f2ed47957a993de627", + "src": "https://github.com/nacro90/numb.nvim" + }, + "nvim-dap": { + "rev": "4f5deb110d9ff8994d96c21df95e2271d11214f9", + "src": "https://github.com/mfussenegger/nvim-dap" + }, + "nvim-dap-go": { + "rev": "b4421153ead5d726603b02743ea40cf26a51ed5f", + "src": "https://github.com/leoluz/nvim-dap-go" + }, + "nvim-dap-ui": { + "rev": "f5b6673f374626515401c5bc51b005f784a4f252", + "src": "https://github.com/rcarriga/nvim-dap-ui" + }, + "nvim-dev-container": { + "rev": "87ea57f420b3460d0c45e239057ffc38fa32f886", + "src": "https://codeberg.org/esensar/nvim-dev-container" + }, + "nvim-lightbulb": { + "rev": "c8f21a04f2046b0c99be52ca87800297a7f8322f", + "src": "https://github.com/kosayoda/nvim-lightbulb" + }, + "nvim-lint": { + "rev": "4b03656c09c1561f89b6aa0665c15d292ba9499d", + "src": "https://github.com/mfussenegger/nvim-lint" + }, + "nvim-lspconfig": { + "rev": "8e2084bf5e40c79c1f42210a6ef96a0a4793a763", + "src": "https://github.com/neovim/nvim-lspconfig" + }, + "nvim-lspimport": { + "rev": "9c1c61a5020faeb1863bb66eb4b2a9107e641876", + "src": "https://github.com/stevanmilic/nvim-lspimport" + }, + "nvim-navic": { + "rev": "f5eba192f39b453675d115351808bd51276d9de5", + "src": "https://github.com/SmiteshP/nvim-navic" + }, + "nvim-nio": { + "rev": "21f5324bfac14e22ba26553caf69ec76ae8a7662", + "src": "https://github.com/nvim-neotest/nvim-nio" + }, + "nvim-notify": { + "rev": "8701bece920b38ea289b457f902e2ad184131a5d", + "src": "https://github.com/rcarriga/nvim-notify" + }, + "nvim-surround": { + "rev": "61319d4bd1c5e336e197defa15bd104c51f0fb29", + "src": "https://github.com/kylechui/nvim-surround" + }, + "nvim-treesitter": { + "rev": "7caec274fd19c12b55902a5b795100d21531391f", + "src": "https://github.com/nvim-treesitter/nvim-treesitter" + }, + "nvim-treesitter-context": { + "rev": "adf4b6b0420b7be6c717ef0ac7993183d6c201b1", + "src": "https://github.com/nvim-treesitter/nvim-treesitter-context" + }, + "nvim-treesitter-textobjects": { + "rev": "93d60a475f0b08a8eceb99255863977d3a25f310", + "src": "https://github.com/nvim-treesitter/nvim-treesitter-textobjects" + }, + "nvim-ts-autotag": { + "rev": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595", + "src": "https://github.com/windwp/nvim-ts-autotag" + }, + "nvim-ts-context-commentstring": { + "rev": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f", + "src": "https://github.com/JoosepAlviste/nvim-ts-context-commentstring" + }, + "obsidian.nvim": { + "rev": "14e0427bef6c55da0d63f9a313fd9941be3a2479", + "src": "https://github.com/epwalsh/obsidian.nvim" + }, + "oil.nvim": { + "rev": "0fcc83805ad11cf714a949c98c605ed717e0b83e", + "src": "https://github.com/stevearc/oil.nvim" + }, + "one-small-step-for-vimkind": { + "rev": "1af6ffb9b5229a856e8090fa2f690e0931a5aace", + "src": "https://github.com/jbyuki/one-small-step-for-vimkind" + }, + "plenary.nvim": { + "rev": "b9fd5226c2f76c951fc8ed5923d85e4de065e509", + "src": "https://github.com/nvim-lua/plenary.nvim" + }, + "rainbow-delimiters.nvim": { + "rev": "50080ed0f44dbc18ae13b81278a01b951a06127a", + "src": "https://github.com/HiPhish/rainbow-delimiters.nvim" + }, + "render-markdown.nvim": { + "rev": "c7188a8f9d2953696b6303caccbf39c51fa2c1b1", + "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" + }, + "sailor.vim": { + "rev": "f035b34b655ed7328cbe26b472792894c9b0ccb4", + "src": "https://github.com/marromlam/sailor.vim" + }, + "sidekick.nvim": { + "rev": "17447a05f9385e5f8372b61530f6f9329cb82421", + "src": "https://github.com/folke/sidekick.nvim" + }, + "sonarqube.nvim": { + "rev": "811bf8f46e0aa5ed9c9b5783aaf6f87640df553a", + "src": "https://github.com/iamkarasik/sonarqube.nvim" + }, + "symbol-usage.nvim": { + "rev": "e07c07dfe7504295a369281e95a24e1afa14b243", + "src": "https://github.com/Wansmer/symbol-usage.nvim" + }, + "symbols-outline.nvim": { + "rev": "564ee65dfc9024bdde73a6621820866987cbb256", + "src": "https://github.com/simrat39/symbols-outline.nvim" + }, + "tiny-inline-diagnostic.nvim": { + "rev": "ba133b3e932416e4b9507095731a6d7276878fe8", + "src": "https://github.com/rachartier/tiny-inline-diagnostic.nvim" + }, + "todo-comments.nvim": { + "rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668", + "src": "https://github.com/folke/todo-comments.nvim" + }, + "toggleterm.nvim": { + "rev": "9a88eae817ef395952e08650b3283726786fb5fb", + "src": "https://github.com/akinsho/toggleterm.nvim" + }, + "treesj": { + "rev": "26bc2a8432ba3ea79ed6aa346fba780a3d372570", + "src": "https://github.com/Wansmer/treesj" + }, + "trouble.nvim": { + "rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a", + "src": "https://github.com/folke/trouble.nvim" + }, + "undotree": { + "rev": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d", + "src": "https://github.com/mbbill/undotree" + }, + "vague.nvim": { + "rev": "8c4643f8a5106dbc492918f86ff6b5c81111ce9a", + "src": "https://github.com/vague2k/vague.nvim" + }, + "vim-apathy": { + "rev": "27128a0f55189724c841843ba41cd33cf7186032", + "src": "https://github.com/tpope/vim-apathy" + }, + "vim-dadbod": { + "rev": "6d1d41da4873a445c5605f2005ad2c68c99d8770", + "src": "https://github.com/tpope/vim-dadbod" + }, + "vim-dadbod-completion": { + "rev": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6", + "src": "https://github.com/kristijanhusak/vim-dadbod-completion" + }, + "vim-dadbod-ui": { + "rev": "07e92e22114cc5b1ba4938d99897d85b58e20475", + "src": "https://github.com/kristijanhusak/vim-dadbod-ui" + }, + "vim-dirdiff": { + "rev": "84bc8999fde4b3c2d8b228b560278ab30c7ea4c9", + "src": "https://github.com/will133/vim-dirdiff" + }, + "vim-fugitive": { + "rev": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0", + "src": "https://github.com/tpope/vim-fugitive" + }, + "vim-kitty": { + "rev": "cd72f2d9cfee8d6aba5a180a5ac3ca265b5d3a46", + "src": "https://github.com/fladson/vim-kitty" + }, + "vim-ledger": { + "rev": "4f2d93dd914f625e2d3db47d97bd9f428fedd68f", + "src": "https://github.com/ledger/vim-ledger" + }, + "vim-log-highlighting": { + "rev": "1037e26f3120e6a6a2c0c33b14a84336dee2a78f", + "src": "https://github.com/mtdl9/vim-log-highlighting" + }, + "vim-markdown": { + "rev": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397", + "src": "https://github.com/plasticboy/vim-markdown" + }, + "vim-repeat": { + "rev": "65846025c15494983dafe5e3b46c8f88ab2e9635", + "src": "https://github.com/tpope/vim-repeat" + }, + "vim-rzip": { + "rev": "f65400fed27b27c7cff7ef8d428c4e5ff749bf28", + "src": "https://github.com/lbrayner/vim-rzip" + }, + "vim-sleuth": { + "rev": "be69bff86754b1aa5adcbb527d7fcd1635a84080", + "src": "https://github.com/tpope/vim-sleuth" + }, + "vim-snakemake": { + "rev": "d0015a0f86150c59fb55f65b41529e6ff4469e18", + "src": "https://github.com/raivivek/vim-snakemake" + }, + "vim-surround": { + "rev": "3d188ed2113431cf8dac77be61b842acb64433d9", + "src": "https://github.com/tpope/vim-surround" + }, + "vimtex": { + "rev": "9306903316c3ddd250676b7cf97c84a84c9c8f99", + "src": "https://github.com/lervag/vimtex" + }, + "which-key.nvim": { + "rev": "3aab2147e74890957785941f0c1ad87d0a44c15a", + "src": "https://github.com/folke/which-key.nvim" + } + } +} From 488693face1886b80e97af46f797442d5e6eca04 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Thu, 30 Apr 2026 00:40:34 +0200 Subject: [PATCH 2/7] feat: some updates --- files/.config/gh/config.yml | 2 +- files/.config/nvim/init.lua | 6 +- files/.config/nvim/lua/options.lua | 3 + files/.config/nvim/lua/packloader.lua | 41 ++-- files/.config/nvim/lua/packs/colorscheme.lua | 5 +- files/.config/nvim/lua/packs/comment.lua | 35 +++- files/.config/nvim/lua/packs/copilot.lua | 4 +- files/.config/nvim/lua/packs/dadbod.lua | 3 +- files/.config/nvim/lua/packs/folke.lua | 0 files/.config/nvim/lua/packs/init.lua | 2 +- files/.config/nvim/lua/packs/mini.lua | 47 ++--- files/.config/nvim/lua/packs/neotree.lua | 191 ------------------- files/.config/nvim/lua/packs/obsidian.lua | 14 -- files/.config/nvim/lua/packs/treesitter.lua | 2 +- files/.config/nvim/lua/tools.lua | 34 ++-- files/.config/nvim/nvim-pack-lock.json | 90 ++++----- files/.config/nvim/plugin/autocommands.lua | 39 ++++ files/.config/nvim/plugin/colors.lua | 3 +- files/.config/tmux/statusbar.conf | 29 ++- files/.config/zsh/rc.d/10-plugins.zsh | 5 +- scripts/igfae | 51 ----- 21 files changed, 223 insertions(+), 383 deletions(-) delete mode 100644 files/.config/nvim/lua/packs/folke.lua delete mode 100644 files/.config/nvim/lua/packs/neotree.lua delete mode 100755 scripts/igfae diff --git a/files/.config/gh/config.yml b/files/.config/gh/config.yml index 325ca91..c007a53 100644 --- a/files/.config/gh/config.yml +++ b/files/.config/gh/config.yml @@ -1,5 +1,5 @@ git_protocol: ssh prompt: enabled aliases: - co: pr checkout + co: pr checkout version: "1" diff --git a/files/.config/nvim/init.lua b/files/.config/nvim/init.lua index 71f884a..a347d74 100644 --- a/files/.config/nvim/init.lua +++ b/files/.config/nvim/init.lua @@ -22,10 +22,6 @@ vim.g.obsidian = vim.g.icloud .. '/iCloud~md~obsidian/Documents/Marcos' vim.g.mapleader = ' ' -- Remap leader key vim.g.maplocalleader = '\\' -- Local leader is --- If opening from inside neovim terminal buffer, skip full config -if vim.env.NVIM and vim.env.TERM_PROGRAM == 'nvim' then - return require('lazy').setup({ { 'willothy/flatten.nvim', config = true } }) -end -------------------------------------------------------------------------------- -- Load modules {{{ @@ -42,4 +38,4 @@ vim.defer_fn(function() require('external_grep') end, 0) -- }}} -------------------------------------------------------------------------------- --- vim: ts=2 sts=2 sw=2 et fdm=marker +-- vim: ts=2 sts=2 sw=2 et fdm=marker fol diff --git a/files/.config/nvim/lua/options.lua b/files/.config/nvim/lua/options.lua index 5675a80..3534f07 100644 --- a/files/.config/nvim/lua/options.lua +++ b/files/.config/nvim/lua/options.lua @@ -1,3 +1,6 @@ +-- Suppress deprecation warnings from plugins (e.g. client.notify) +vim.deprecate = function() end + -- Make all keymaps silent by default (Folke's pattern) local keymap_set = vim.keymap.set vim.keymap.set = function(mode, lhs, rhs, opts) diff --git a/files/.config/nvim/lua/packloader.lua b/files/.config/nvim/lua/packloader.lua index 2254515..6e996d8 100644 --- a/files/.config/nvim/lua/packloader.lua +++ b/files/.config/nvim/lua/packloader.lua @@ -1,8 +1,5 @@ -- lua/packloader.lua --- Firenvim: skip the full plugin stack -if vim.g.started_by_firenvim then return end - vim.g.db_ui_use_nerd_fonts = 1 -- --------------------------------------------------------------------------- @@ -77,7 +74,6 @@ vim.pack.add({ 'https://github.com/echasnovski/mini.splitjoin', 'https://github.com/echasnovski/mini.move', 'https://github.com/echasnovski/mini.icons', - 'https://github.com/echasnovski/mini.diff', 'https://github.com/echasnovski/mini.trailspace', 'https://github.com/echasnovski/mini.misc', 'https://github.com/echasnovski/mini.bufremove', @@ -129,8 +125,7 @@ vim.pack.add({ -- Obsidian 'https://github.com/epwalsh/obsidian.nvim', - -- REPL - 'https://github.com/marromlam/kitty-repl.nvim', + -- REPL (loaded conditionally below) -- Remote / containers 'https://codeberg.org/esensar/nvim-dev-container', @@ -156,21 +151,25 @@ vim.pack.add({ 'https://github.com/nvim-lua/plenary.nvim', 'https://github.com/jghauser/fold-cycle.nvim', 'https://github.com/andrewferrier/debugprint.nvim', - 'https://github.com/marromlam/sailor.vim', + -- 'https://github.com/marromlam/sailor.vim', + 'https://github.com/marromlam/tex-kitty', 'https://github.com/bogado/file-line', 'https://github.com/will133/vim-dirdiff', 'https://github.com/tpope/vim-sleuth', - 'https://github.com/tpope/vim-surround', 'https://github.com/tpope/vim-repeat', - - -- Bufferline dep - 'https://github.com/nvim-lua/plenary.nvim', }) -- --------------------------------------------------------------------------- -- Load configuration for each pack (imperative setup) -- --------------------------------------------------------------------------- +-- Theme {{{ +local themes_dev = '/Users/marcos/Workspaces/personal/themes/themes/vim' +if vim.uv.fs_stat(themes_dev) then + vim.opt.runtimepath:prepend(themes_dev) +end +-- }}} + -- Always-on / UI (load immediately) require('packs.colorscheme') require('packs.mini') @@ -188,8 +187,24 @@ require('packs.navigation') require('packs.terminal') -- REPL +local _kitty_dev = '/Users/marcos/Workspaces/personal/kitty-repl.nvim' +if vim.uv.fs_stat(_kitty_dev) then + vim.opt.runtimepath:prepend(_kitty_dev) +else + vim.pack.add({ 'https://github.com/marromlam/kitty-repl.nvim' }) +end require('packs.repl') +local _sailor_dev = '/Users/marcos/Workspaces/personal/sailor.vim' +if vim.uv.fs_stat(_sailor_dev) then + vim.opt.runtimepath:prepend(_sailor_dev) + -- plugin/sailor.lua auto-calls setup() on load; source it explicitly + -- since prepend() doesn't trigger plugin/ sourcing the way pack.add() does + vim.cmd('source ' .. _sailor_dev .. '/plugin/sailor.lua') +else + vim.pack.add({ 'https://github.com/marromlam/sailor.vim' }) +end + -- Copilot / AI (deferred setup via autocmd in each file) require('packs.copilot') @@ -217,13 +232,15 @@ require('packs.filetype') -- Treesitter (on BufReadPost) require('packs.treesitter') +-- Git (load immediately so gs works before any buffer is opened) +require('packs.git') + -- Heavy plugins: load on BufReadPre/BufNewFile vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { once = true, group = vim.api.nvim_create_augroup('MrlPackloaderHeavy', { clear = true }), callback = function() require('packs.lsp') - require('packs.git') require('packs.ui') require('packs.format') require('packs.linting') diff --git a/files/.config/nvim/lua/packs/colorscheme.lua b/files/.config/nvim/lua/packs/colorscheme.lua index 07273f0..a5c256c 100644 --- a/files/.config/nvim/lua/packs/colorscheme.lua +++ b/files/.config/nvim/lua/packs/colorscheme.lua @@ -1,7 +1,8 @@ -- packs/colorscheme.lua +local home_dir = os.getenv('HOME') local is_dev = vim.fn.isdirectory( - '/Users/marcos/Workspaces/personal/theme-builder' + home_dir .. '/Workspaces/personal/themes' ) == 1 if not is_dev then @@ -25,6 +26,6 @@ if not is_dev then vim.cmd('colorscheme vague') else -- BEGIN_NEOVIM_THEME - vim.cmd.colorscheme('amberglow') + vim.cmd.colorscheme('dracula_pro') -- END_NEOVIM_THEME end diff --git a/files/.config/nvim/lua/packs/comment.lua b/files/.config/nvim/lua/packs/comment.lua index 38c039c..4790f68 100644 --- a/files/.config/nvim/lua/packs/comment.lua +++ b/files/.config/nvim/lua/packs/comment.lua @@ -1,19 +1,48 @@ -- packs/comment.lua +-- Patch ts_context_commentstring's update_commentstring to guard against +-- buffers where get_parser() throws (e.g. zip/docx buffers get ft=tar and +-- treesitter registers a parser, but it errors when actually called). +-- Root cause: BufReadCmd (used by vim-rzip) bypasses BufReadPre, so the +-- buffer gets ft=tar, is_treesitter_active() returns true, CursorHold is +-- registered, but get_parser() later throws on the rzip buffer content. +vim.api.nvim_create_autocmd('VimEnter', { + once = true, + group = vim.api.nvim_create_augroup('MrlTsContextPatch', { clear = true }), + callback = function() + local ok, internal = pcall(require, 'ts_context_commentstring.internal') + if not ok then return end + local orig_update = internal.update_commentstring + internal.update_commentstring = function(args) + local guard_ok = pcall(function() + -- Ensure get_parser() actually works before proceeding + vim.treesitter.get_parser(0):trees() + end) + if not guard_ok then return end + orig_update(args) + end + end, +}) + vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { once = true, group = vim.api.nvim_create_augroup('MrlComment', { clear = true }), callback = function() - -- Disable the default CursorHold autocmd; Comment.nvim calls it via pre_hook only require('ts_context_commentstring').setup({ enable_autocmd = false }) local comment = require('Comment') local ts_context_commentstring = require('ts_context_commentstring.integrations.comment_nvim') - -- enable comment with tsx/jsx/svelte/html support + local ts_pre_hook = ts_context_commentstring.create_pre_hook() comment.setup({ - pre_hook = ts_context_commentstring.create_pre_hook(), + pre_hook = function(ctx) + local guard_ok = pcall(function() + vim.treesitter.get_parser(0):trees() + end) + if not guard_ok then return end + return ts_pre_hook(ctx) + end, }) end, }) diff --git a/files/.config/nvim/lua/packs/copilot.lua b/files/.config/nvim/lua/packs/copilot.lua index 7df82b1..12006e0 100644 --- a/files/.config/nvim/lua/packs/copilot.lua +++ b/files/.config/nvim/lua/packs/copilot.lua @@ -1,7 +1,7 @@ -- packs/copilot.lua --- copilot.lua: setup on InsertEnter -vim.api.nvim_create_autocmd('InsertEnter', { +-- copilot.lua: setup on BufReadPre so the LSP client appears in the statusline +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { once = true, group = vim.api.nvim_create_augroup('MrlCopilot', { clear = true }), callback = function() diff --git a/files/.config/nvim/lua/packs/dadbod.lua b/files/.config/nvim/lua/packs/dadbod.lua index e92b882..0ec56dd 100644 --- a/files/.config/nvim/lua/packs/dadbod.lua +++ b/files/.config/nvim/lua/packs/dadbod.lua @@ -1,4 +1,3 @@ -- packs/dadbod.lua --- Your DBUI configuration (init equivalent - runs immediately) -vim.g.db_ui_use_nerd_fonts = 1 +-- vim-dadbod / vim-dadbod-ui: no setup needed, configured via vim.g in packloader.lua diff --git a/files/.config/nvim/lua/packs/folke.lua b/files/.config/nvim/lua/packs/folke.lua deleted file mode 100644 index e69de29..0000000 diff --git a/files/.config/nvim/lua/packs/init.lua b/files/.config/nvim/lua/packs/init.lua index f02c6e2..fe4055f 100644 --- a/files/.config/nvim/lua/packs/init.lua +++ b/files/.config/nvim/lua/packs/init.lua @@ -20,7 +20,7 @@ vim.keymap.set('n', 'dC', 'DeleteDebugPrints', { desc = 'debugprint: clear all', }) --- sailor.vim: loaded on VimEnter, no explicit setup needed +-- sailor.vim: plugin/sailor.lua auto-calls setup() on load (no explicit call needed) -- file-line: activated by the gF key, no setup needed diff --git a/files/.config/nvim/lua/packs/mini.lua b/files/.config/nvim/lua/packs/mini.lua index bc3b450..fc9434a 100644 --- a/files/.config/nvim/lua/packs/mini.lua +++ b/files/.config/nvim/lua/packs/mini.lua @@ -8,17 +8,11 @@ vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { once = true, group = vim.api.nvim_create_augroup('MrlMiniTextObjects', { clear = true }), callback = function() - require('mini.ai').setup({ n_lines = 500 }) - - require('mini.align').setup({ - mappings = { - start = 'ga', -- Start align mode - start_with_preview = 'gA', -- Start align mode with preview - }, - options = { - split_pattern = '', - justify_side = 'left', - merge_delimiter = '', + require('mini.ai').setup({ + n_lines = 500, + custom_textobjects = { + -- Handle namespaced XML/HTML tags like in addition to plain tags + t = { '<(%a[%w:.-]*)%f[^%w:.-][^>]->.-', '^<.->().-()]+>$' }, }, }) @@ -36,6 +30,19 @@ vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { }, }) + require('mini.align').setup({ + mappings = { + start = 'ga', -- Start align mode + start_with_preview = 'gA', -- Start align mode with preview + }, + options = { + split_pattern = '', + justify_side = 'left', + merge_delimiter = '', + }, + }) + + require('mini.splitjoin').setup({ mappings = { toggle = 'gS', @@ -62,24 +69,6 @@ vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { }, }) - require('mini.diff').setup({ - view = { - style = 'sign', - signs = { - add = '┃', - change = '┃', - delete = '┃', - }, - }, - algorithm = 'histogram', - highlight = { - additions = 'MiniDiffSignAdd', - deletions = 'MiniDiffSignDelete', - changes = 'MiniDiffSignChange', - text = 'MiniDiffText', - }, - }) - require('mini.trailspace').setup({ only_in_normal_buffers = true, }) diff --git a/files/.config/nvim/lua/packs/neotree.lua b/files/.config/nvim/lua/packs/neotree.lua deleted file mode 100644 index e3bea76..0000000 --- a/files/.config/nvim/lua/packs/neotree.lua +++ /dev/null @@ -1,191 +0,0 @@ --- Neo-tree is a Neovim plugin to browse the file system --- https://github.com/nvim-neo-tree/neo-tree.nvim -local fn, api = vim.fn, vim.api -local highlight = require('highlight') -local icons = require('tools').ui.icons -local autocmd = api.nvim_create_autocmd - -return { - { - 'nvim-neo-tree/neo-tree.nvim', - branch = 'v3.x', - cmd = { 'Neotree' }, - cond = false, - disable = true, - keys = { - { '', 'Neotree toggle reveal', desc = 'NeoTree' }, - -- { '-', 'Neotree toggle reveal', desc = 'NeoTree' } - }, - -- init = function() - -- autocmd('BufEnter', { - -- desc = 'Load NeoTree if entering a directory', - -- callback = function(args) - -- if fn.isdirectory(api.nvim_buf_get_name(args.buf)) > 0 then - -- require('lazy').load({ plugins = { 'neo-tree.nvim' } }) - -- api.nvim_del_autocmd(args.id) - -- end - -- end, - -- }) - -- - -- - -- init = function() - -- -- FIX: use `autocmd` for lazy-loading neo-tree instead of directly requiring it, - -- -- because `cwd` is not set up properly. - -- vim.api.nvim_create_autocmd("BufEnter", { - -- group = vim.api.nvim_create_augroup("Neotree_start_directory", { clear = true }), - -- desc = "Start Neo-tree with directory", - -- once = true, - -- callback = function() - -- if package.loaded["neo-tree"] then - -- return - -- else - -- local stats = vim.uv.fs_stat(vim.fn.argv(0)) - -- if stats and stats.type == "directory" then - -- require("neo-tree") - -- end - -- end - -- end, - -- }) - -- end, - -- - -- - -- end, - config = function() - local symbols = require('lspkind').symbol_map - local lsp_kinds = require('tools').ui.lsp.highlights - - require('neo-tree').setup({ - window = { - position = 'left', - width = 30, - }, - sources = { 'filesystem', 'git_status', 'document_symbols' }, - source_selector = { - winbar = true, - separator_active = '', - sources = { - { source = 'filesystem' }, - { source = 'git_status' }, - }, - }, - enable_git_status = true, - git_status_async = true, - nesting_rules = { - ['dart'] = { 'freezed.dart', 'g.dart' }, - ['go'] = { - pattern = '(.*)%.go$', - files = { '%1_test.go' }, - }, - ['docker'] = { - pattern = '^dockerfile$', - ignore_case = true, - files = { '.dockerignore', 'docker-compose.*', 'dockerfile*' }, - }, - }, - event_handlers = { - { - event = 'neo_tree_buffer_enter', - handler = function() highlight.set('Cursor', { blend = 100 }) end, - }, - { - event = 'neo_tree_popup_buffer_enter', - handler = function() highlight.set('Cursor', { blend = 0 }) end, - }, - { - event = 'neo_tree_buffer_leave', - handler = function() highlight.set('Cursor', { blend = 0 }) end, - }, - { - event = 'neo_tree_popup_buffer_leave', - handler = function() highlight.set('Cursor', { blend = 100 }) end, - }, - { - event = 'neo_tree_window_after_close', - handler = function() highlight.set('Cursor', { blend = 0 }) end, - }, - { - event = 'neo_tree_popup_input_ready', - handler = function() vim.cmd('stopinsert') end, - }, - }, - filesystem = { - -- hijack_netrw_behavior = 'open_current', - use_libuv_file_watcher = true, - group_empty_dirs = false, - follow_current_file = { - enabled = true, - leave_dirs_open = true, - }, - filtered_items = { - visible = true, - hide_dotfiles = false, - hide_gitignored = true, - never_show = { '.DS_Store' }, - }, - window = { - mappings = { - ['/'] = 'noop', - ['g/'] = 'fuzzy_finder', - }, - }, - }, - default_component_configs = { - icon = { folder_empty = icons.documents.open_folder }, - name = { highlight_opened_files = true }, - document_symbols = { - follow_cursor = true, - kinds = vim.iter(symbols):fold({}, function(acc, k, v) - acc[k] = { icon = v, hl = lsp_kinds[k] } - return acc - end), - }, - modified = { symbol = icons.misc.circle .. ' ' }, - git_status = { - symbols = { - added = icons.git.add, - deleted = icons.git.remove, - modified = icons.git.mod, - renamed = icons.git.rename, - untracked = icons.git.untracked, - ignored = icons.git.ignored, - unstaged = icons.git.unstaged, - staged = icons.git.staged, - conflict = icons.git.conflict, - }, - }, - file_size = { - required_width = 50, - }, - }, - window = { - mappings = { - ['o'] = 'toggle_node', - [''] = 'open_with_window_picker', - [''] = 'split_with_window_picker', - [''] = 'vsplit_with_window_picker', - [''] = 'revert_preview', - ['P'] = { 'toggle_preview', config = { use_float = false } }, - }, - }, - }) - end, - dependencies = { - 'nvim-lua/plenary.nvim', - 'MunifTanjim/nui.nvim', - { - 'ten3roberts/window-picker.nvim', - name = 'window-picker', - config = function() - local picker = require('window-picker') - picker.setup() - picker.pick_window = function() - return picker.select( - { hl = 'WindowPicker', prompt = 'Pick window: ' }, - function(winid) return winid or nil end - ) - end - end, - }, - }, - }, -} diff --git a/files/.config/nvim/lua/packs/obsidian.lua b/files/.config/nvim/lua/packs/obsidian.lua index e5cdf22..94f3d69 100644 --- a/files/.config/nvim/lua/packs/obsidian.lua +++ b/files/.config/nvim/lua/packs/obsidian.lua @@ -6,20 +6,6 @@ vim.keymap.set('n', 'on', ':ObsidianNew', { desc = 'obsidian: new' } vim.keymap.set('n', 'os', ':ObsidianSearch', { desc = 'obsidian: search' }) vim.keymap.set('n', 'of', ':ObsidianQuickSwitch', { desc = 'obsidian: quick switch' }) --- Defer setup until actually used via command -vim.api.nvim_create_user_command('ObsidianSetup', function() - require('obsidian').setup({ - ui = { enable = false }, - workspaces = { - { - name = 'personal', - path = vim.g.obsidian, - }, - }, - }) -end, { desc = 'Setup obsidian.nvim' }) - --- Auto-setup on first obsidian command invocation vim.defer_fn(function() require('obsidian').setup({ ui = { enable = false }, diff --git a/files/.config/nvim/lua/packs/treesitter.lua b/files/.config/nvim/lua/packs/treesitter.lua index 837daeb..215bc0e 100644 --- a/files/.config/nvim/lua/packs/treesitter.lua +++ b/files/.config/nvim/lua/packs/treesitter.lua @@ -31,7 +31,7 @@ vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { 'c', 'vim', 'vimdoc', 'query', 'lua', 'luadoc', 'luap', 'diff', 'regex', 'gitcommit', 'git_config', 'git_rebase', 'markdown', 'markdown_inline', 'bash', 'html', 'json', 'javascript', 'typescript', 'tsx', 'yaml', 'css', 'prisma', - 'svelte', 'graphql', 'dockerfile', 'gitignore', 'python', 'go', 'rust', + 'svelte', 'graphql', 'dockerfile', 'gitignore', 'python', 'go', 'rust', 'xml', }, }) diff --git a/files/.config/nvim/lua/tools.lua b/files/.config/nvim/lua/tools.lua index a31d543..a462836 100644 --- a/files/.config/nvim/lua/tools.lua +++ b/files/.config/nvim/lua/tools.lua @@ -470,7 +470,10 @@ local function hl_get(group, attribute, fallback) assert(group, 'cannot get a highlight without specifying a group name') local data = hl_get_as_hex({ name = group }) if not attribute then return data end - assert(hl_attrs[attribute], ('the attribute passed in is invalid: %s'):format(attribute)) + assert( + hl_attrs[attribute], + ('the attribute passed in is invalid: %s'):format(attribute) + ) local color = data[attribute] or fallback if not color then return 'NONE' end return color @@ -546,7 +549,9 @@ local function hl_plugin(name, opts) vim.schedule(function() hl_all(opts) end) M.augroup(fmt('%sHighlightOverrides', name:gsub('^%l', string.upper)), { event = 'ColorScheme', - command = function() vim.schedule(function() hl_all(opts) end) end, + command = function() + vim.schedule(function() hl_all(opts) end) + end, }) end @@ -556,6 +561,9 @@ M.hl = { all = hl_all, plugin = hl_plugin, set_winhl = hl_set_winhl, + tint = M.tint, + blend = M.blend, + darken_hsl = M.darken_hsl, } -- }}} @@ -588,14 +596,14 @@ M.ui.icons = { hint = '󰌶', -- ⚑ }, git = { - add = '󰐗', - mod = '󰻂', - remove = '󰍶', - ignore = '', - rename = '', + add = '', + mod = '', + remove = '', + ignore = '', + rename = '', untracked = '', - ignored = '󰙦', - unstaged = '󰻂', + ignored = '', + unstaged = '', staged = '', conflict = '', diff = '', @@ -619,6 +627,7 @@ M.ui.icons = { tab = '⇥', bug = '', question = '', + bell = '', clock = '', cmd = '⌘', lock = '', @@ -629,7 +638,7 @@ M.ui.icons = { history = '󰄉', comment = '󰅺', robot = '󰚩', - copilot = '', + copilot = '', lightbulb = '󰌵', search = '󰍉', code = '', @@ -653,7 +662,7 @@ M.ui.icons = { calendar = '', block = '▏', clippy = '', - puzzle = '', + puzzle = '', settings = '⚙', key = '', config = '', @@ -1115,7 +1124,8 @@ local function sl_component(opts) if not opts.priority then opts.priority = 10 end local item_str = sl_chunks_to_string(item) - if vim.api.nvim_strwidth(item_str) == 0 then return end + -- Use byte length: nvim_strwidth returns 0 for Nerd Font private-use glyphs + if #item_str == 0 then return end local click_start = opts.click and sl_get_click_start(opts.click, tostring(opts.id)) diff --git a/files/.config/nvim/nvim-pack-lock.json b/files/.config/nvim/nvim-pack-lock.json index 5d3e1e8..69eb5c9 100644 --- a/files/.config/nvim/nvim-pack-lock.json +++ b/files/.config/nvim/nvim-pack-lock.json @@ -9,7 +9,7 @@ "src": "https://github.com/Kaiser-Yang/blink-cmp-avante" }, "blink.cmp": { - "rev": "5e088706d92da09949e081cc4d49e2c9ba8cfc8c", + "rev": "456d38d1cd3743926f329204c2340f3e7840aad6", "src": "https://github.com/saghen/blink.cmp" }, "bufferline.nvim": { @@ -21,7 +21,7 @@ "src": "https://github.com/uga-rosa/ccc.nvim" }, "codecompanion.nvim": { - "rev": "e0fe366cf3af6c80dcac86cb053ef3fe48aae911", + "rev": "fe792b30974893d8809b06c5e31c5c876c14bbc7", "src": "https://github.com/olimorris/codecompanion.nvim" }, "conform.nvim": { @@ -29,11 +29,11 @@ "src": "https://github.com/stevearc/conform.nvim" }, "copilot.lua": { - "rev": "faa347cef2a9429eec14dada549e000a3b8d0fc9", + "rev": "07aa57148ac28986bab9f55e87ee3d929e2726b1", "src": "https://github.com/zbirenbaum/copilot.lua" }, "crates.nvim": { - "rev": "ac9fa498a9edb96dc3056724ff69d5f40b898453", + "rev": "0f536967abd097d9a4275087483f15d012418740", "src": "https://github.com/saecki/crates.nvim" }, "csvview.nvim": { @@ -41,7 +41,7 @@ "src": "https://github.com/hat0uma/csvview.nvim" }, "debugprint.nvim": { - "rev": "a95f658add600de701763e2956a86278d9d7e2a8", + "rev": "01ff4d03e623243dc9302cdddc14b08bc2fbb7be", "src": "https://github.com/andrewferrier/debugprint.nvim" }, "diffview.nvim": { @@ -53,7 +53,7 @@ "src": "https://github.com/stevearc/dressing.nvim" }, "fidget.nvim": { - "rev": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970", + "rev": "889e2e96edef4e144965571d46f7a77bcc4d0ddf", "src": "https://github.com/j-hui/fidget.nvim" }, "file-line": { @@ -69,7 +69,7 @@ "src": "https://github.com/rafamadriz/friendly-snippets" }, "fzf-lua": { - "rev": "c9e7b7bfbd01f949164988ee1684035468e1995c", + "rev": "4deeecf611c0beba6455e6cf06e2c051a6169dd4", "src": "https://github.com/ibhagwan/fzf-lua" }, "git-conflict.nvim": { @@ -89,7 +89,7 @@ "src": "https://github.com/ruifm/gitlinker.nvim" }, "gitsigns.nvim": { - "rev": "caa98e2e5e4c23a1652c23be839d2e1722cecc29", + "rev": "8d82c240f190fc33723d48c308ccc1ed8baad69d", "src": "https://github.com/lewis6991/gitsigns.nvim" }, "glance.nvim": { @@ -121,7 +121,7 @@ "src": "https://github.com/meznaric/key-analyzer.nvim" }, "kitty-repl.nvim": { - "rev": "1d52b999b9cf9f2e0ce133fe9445469c796e149c", + "rev": "6a280e0cb80c5644c982ffc79e902f7e318a718f", "src": "https://github.com/marromlam/kitty-repl.nvim" }, "lazydev.nvim": { @@ -137,7 +137,7 @@ "src": "https://github.com/Kicamon/markdown-table-mode.nvim" }, "mason-lspconfig.nvim": { - "rev": "25f609e7fca78af7cede4f9fa3af8a94b1c4950b", + "rev": "63a3c6a80538de1003373a619e29aeda27809ad3", "src": "https://github.com/mason-org/mason-lspconfig.nvim" }, "mason-nvim-dap.nvim": { @@ -149,7 +149,7 @@ "src": "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim" }, "mason.nvim": { - "rev": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65", + "rev": "b03fb0f20bc1d43daf558cda981a2be22e73ac42", "src": "https://github.com/mason-org/mason.nvim" }, "mcphub.nvim": { @@ -157,67 +157,67 @@ "src": "https://github.com/ravitemer/mcphub.nvim" }, "mini.ai": { - "rev": "4b0a6207341d895b6cfe9bcb1e4d3e8607bfe4f4", + "rev": "43eb2074843950a3a25aae56a5f41362ec043bfa", "src": "https://github.com/echasnovski/mini.ai" }, "mini.align": { - "rev": "4d45e0e4f1fd8baefb6ae52a44659704fe7ebe8b", + "rev": "6f3c69cd57134ad8fbf1e85dcdc90cb37a8c75c8", "src": "https://github.com/echasnovski/mini.align" }, "mini.animate": { - "rev": "8814b56e282cd86635ce9a392ed56b6a85f59731", + "rev": "0f2117aa519ec238846223d581272a9205fef7c2", "src": "https://github.com/echasnovski/mini.animate" }, "mini.bufremove": { - "rev": "ee69f823f84508c556127a5882760d9783692023", + "rev": "8603490905fdfa31943cf2ede7ef4475e3dbac9a", "src": "https://github.com/echasnovski/mini.bufremove" }, "mini.diff": { - "rev": "ff3cd5e76e812fa18bde0f8126d6f3bb62008c79", + "rev": "ab11575a6c147ecfba894d676d0c93e855021d34", "src": "https://github.com/echasnovski/mini.diff" }, "mini.hipatterns": { - "rev": "2c5dce6dc7443de814d16f7470549811ee86e664", + "rev": "a3ffba45e4119917b254c372df82e79f7d8c4aad", "src": "https://github.com/echasnovski/mini.hipatterns" }, "mini.icons": { - "rev": "5b9076dae1bfbe47ba4a14bc8b967cde0ab5d77e", + "rev": "7fdae2443a0e2910015ca39ad74b50524ee682d3", "src": "https://github.com/echasnovski/mini.icons" }, "mini.misc": { - "rev": "de8947231c29012271722651aa07f6749c41d1ed", + "rev": "4157b1f4cf28525c3c498ce82b1f3480d034a375", "src": "https://github.com/echasnovski/mini.misc" }, "mini.move": { - "rev": "b8ba0b77e91b5f0fe8e014e03f7f59799dec1d96", + "rev": "74d140143b1bb905c3d0aebcfc2f216fd237080e", "src": "https://github.com/echasnovski/mini.move" }, "mini.pairs": { - "rev": "b7fde3719340946feb75017ef9d75edebdeb0566", + "rev": "42387c7fe68fc0b6e95eaf37f1bb76e7bffaa0d9", "src": "https://github.com/echasnovski/mini.pairs" }, "mini.splitjoin": { - "rev": "8112e794cbb022b9d4b7af60b64e9896930f1697", + "rev": "8bd5a3d581b9f3dd3bc91fe495e210b8b0ee981d", "src": "https://github.com/echasnovski/mini.splitjoin" }, "mini.starter": { - "rev": "cdf909e5bda577e09c61fa6d9a36bb2a88dbc636", + "rev": "7bdc9decc8b623f245c1e42a64bc41e61d574c5e", "src": "https://github.com/echasnovski/mini.starter" }, "mini.surround": { - "rev": "d205d1741d1fcc1f3117b4e839bf00f74ad72fa2", + "rev": "2715e04bea3ec9244f15b421dc5b18c0fe326210", "src": "https://github.com/echasnovski/mini.surround" }, "mini.trailspace": { - "rev": "27acb69562a4742256ab3e4b0127391fcb49dbb3", + "rev": "b362246495d18c29b4545a8f1c47f627f8011b7c", "src": "https://github.com/echasnovski/mini.trailspace" }, "neogit": { - "rev": "4681c1fdac1b730592ae195576e87406f7255750", + "rev": "e06745228600a585b88726fc9fba44a373c15a47", "src": "https://github.com/NeogitOrg/neogit" }, "neotest": { - "rev": "72bc8f1ec62a590fb47368c81f89610e0f353e28", + "rev": "fd0b7986dd0ae04e38ec7dc0c78a432e3820839c", "src": "https://github.com/nvim-neotest/neotest" }, "neotest-plenary": { @@ -225,7 +225,7 @@ "src": "https://github.com/rcarriga/neotest-plenary" }, "neotest-python": { - "rev": "b0d3a861bd85689d8ed73f0590c47963a7eb1bf9", + "rev": "e6df4f1892f6137f58135917db24d1655937d831", "src": "https://github.com/nvim-neotest/neotest-python" }, "noice.nvim": { @@ -241,7 +241,7 @@ "src": "https://github.com/nacro90/numb.nvim" }, "nvim-dap": { - "rev": "4f5deb110d9ff8994d96c21df95e2271d11214f9", + "rev": "45a69eba683a2c448dd9ecfc4de89511f0646b5f", "src": "https://github.com/mfussenegger/nvim-dap" }, "nvim-dap-go": { @@ -249,7 +249,7 @@ "src": "https://github.com/leoluz/nvim-dap-go" }, "nvim-dap-ui": { - "rev": "f5b6673f374626515401c5bc51b005f784a4f252", + "rev": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49", "src": "https://github.com/rcarriga/nvim-dap-ui" }, "nvim-dev-container": { @@ -257,15 +257,15 @@ "src": "https://codeberg.org/esensar/nvim-dev-container" }, "nvim-lightbulb": { - "rev": "c8f21a04f2046b0c99be52ca87800297a7f8322f", + "rev": "e974b1a93c917c840545f51b9a66cfd72c520522", "src": "https://github.com/kosayoda/nvim-lightbulb" }, "nvim-lint": { - "rev": "4b03656c09c1561f89b6aa0665c15d292ba9499d", + "rev": "eab58b48eb11d7745c11c505e0f3057165902461", "src": "https://github.com/mfussenegger/nvim-lint" }, "nvim-lspconfig": { - "rev": "8e2084bf5e40c79c1f42210a6ef96a0a4793a763", + "rev": "c588db330592fa477a70d2fee6ba20a57194bdc3", "src": "https://github.com/neovim/nvim-lspconfig" }, "nvim-lspimport": { @@ -285,19 +285,19 @@ "src": "https://github.com/rcarriga/nvim-notify" }, "nvim-surround": { - "rev": "61319d4bd1c5e336e197defa15bd104c51f0fb29", + "rev": "9291040de8cd8a4439eb64c441e8d5d2bf884a5a", "src": "https://github.com/kylechui/nvim-surround" }, "nvim-treesitter": { - "rev": "7caec274fd19c12b55902a5b795100d21531391f", + "rev": "4916d6592ede8c07973490d9322f187e07dfefac", "src": "https://github.com/nvim-treesitter/nvim-treesitter" }, "nvim-treesitter-context": { - "rev": "adf4b6b0420b7be6c717ef0ac7993183d6c201b1", + "rev": "b0c45cefe2c8f7b55fc46f34e563bc428ef99636", "src": "https://github.com/nvim-treesitter/nvim-treesitter-context" }, "nvim-treesitter-textobjects": { - "rev": "93d60a475f0b08a8eceb99255863977d3a25f310", + "rev": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e", "src": "https://github.com/nvim-treesitter/nvim-treesitter-textobjects" }, "nvim-ts-autotag": { @@ -305,7 +305,7 @@ "src": "https://github.com/windwp/nvim-ts-autotag" }, "nvim-ts-context-commentstring": { - "rev": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f", + "rev": "6141a40173c6efa98242dc951ed4b6f892c97027", "src": "https://github.com/JoosepAlviste/nvim-ts-context-commentstring" }, "obsidian.nvim": { @@ -325,11 +325,11 @@ "src": "https://github.com/nvim-lua/plenary.nvim" }, "rainbow-delimiters.nvim": { - "rev": "50080ed0f44dbc18ae13b81278a01b951a06127a", + "rev": "aab6caaffd79b8def22ec4320a5344f7c42f58d2", "src": "https://github.com/HiPhish/rainbow-delimiters.nvim" }, "render-markdown.nvim": { - "rev": "c7188a8f9d2953696b6303caccbf39c51fa2c1b1", + "rev": "54d4b5431e9634ee3d8d30784e017239b5b89d41", "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" }, "sailor.vim": { @@ -345,15 +345,19 @@ "src": "https://github.com/iamkarasik/sonarqube.nvim" }, "symbol-usage.nvim": { - "rev": "e07c07dfe7504295a369281e95a24e1afa14b243", + "rev": "6a449e6b37be61a110606e9a67a7a308774f120f", "src": "https://github.com/Wansmer/symbol-usage.nvim" }, "symbols-outline.nvim": { "rev": "564ee65dfc9024bdde73a6621820866987cbb256", "src": "https://github.com/simrat39/symbols-outline.nvim" }, + "tex-kitty": { + "rev": "ccab91cdb4f69aa9db9751df74dd2163ed2183b4", + "src": "https://github.com/marromlam/tex-kitty" + }, "tiny-inline-diagnostic.nvim": { - "rev": "ba133b3e932416e4b9507095731a6d7276878fe8", + "rev": "57a0eb84b2008c76e77930639890d9874195b1e1", "src": "https://github.com/rachartier/tiny-inline-diagnostic.nvim" }, "todo-comments.nvim": { @@ -377,7 +381,7 @@ "src": "https://github.com/mbbill/undotree" }, "vague.nvim": { - "rev": "8c4643f8a5106dbc492918f86ff6b5c81111ce9a", + "rev": "4f52c75bce7411f64dacbd1bff2a2fce5bdd59e9", "src": "https://github.com/vague2k/vague.nvim" }, "vim-apathy": { diff --git a/files/.config/nvim/plugin/autocommands.lua b/files/.config/nvim/plugin/autocommands.lua index e5af403..aed5e02 100644 --- a/files/.config/nvim/plugin/autocommands.lua +++ b/files/.config/nvim/plugin/autocommands.lua @@ -1,6 +1,45 @@ local augroup = require('tools').augroup local fn, api, v, cmd = vim.fn, vim.api, vim.v, vim.cmd +local startup_archive = require('startup_archive') + +do + local group = + api.nvim_create_augroup('ArchiveStartupRetry', { clear = true }) + + api.nvim_create_autocmd('VimEnter', { + group = group, + once = true, + callback = function() + local arg0 = fn.argv(0) + if arg0 == '' then return end + + local lines = api.nvim_buf_get_lines(0, 0, -1, false) + local ctx = startup_archive.build_ctx({ + argc = fn.argc(), + arg0 = arg0, + zip_exts = vim.g.zipPlugin_ext, + retry_done = vim.g._mrl_archive_startup_retry_done == true, + buftype = vim.bo.buftype, + filetype = vim.bo.filetype, + line_count = api.nvim_buf_line_count(0), + lines = lines, + }) + + if not ctx.is_single_arg or ctx.retry_done or not ctx.is_archive_arg then + return + end + + vim.g._mrl_archive_startup_retry_done = true + local should_retry = startup_archive.should_retry_startup_edit(ctx) + -- Even when the initial buffer looks sane in headless mode, interactive + -- startup can still render it blank. Re-open once, deferred, to mimic + -- the known-working manual `:e test.docx` path. + local delay = should_retry and 0 or 30 + vim.defer_fn(function() cmd.edit(vim.fn.fnameescape(arg0)) end, delay) + end, + }) +end -- Better terminal UX inside fzf-lua: allow Esc to abort. api.nvim_create_autocmd('FileType', { diff --git a/files/.config/nvim/plugin/colors.lua b/files/.config/nvim/plugin/colors.lua index 352af4a..80554be 100644 --- a/files/.config/nvim/plugin/colors.lua +++ b/files/.config/nvim/plugin/colors.lua @@ -592,8 +592,7 @@ augroup('UserHighlights', { command = function() user_highlights() end, }, { -- Run once after plugins load, so plugin highlight overrides don't win. - event = 'User', - pattern = 'LazyDone', + event = 'VimEnter', once = true, command = function() user_highlights() end, }, { diff --git a/files/.config/tmux/statusbar.conf b/files/.config/tmux/statusbar.conf index 31e956a..96d3d8f 100644 --- a/files/.config/tmux/statusbar.conf +++ b/files/.config/tmux/statusbar.conf @@ -14,7 +14,14 @@ set -g status-left-length 30 set -g status-right-length 30 SESSION_ICON="󱂬" -BELL_ICON="⚘" +SESSION_ICON="󰙀" +SESSION_INNER_BORDER="" +BELL_ICON="" +LBORDER="" +RBORDER="" +LBORDER="█" +RBORDER="█" +# FULL_BLOCK="█" # }}} @@ -92,7 +99,7 @@ STATUS_RIGHT="#[fg=$SESSION_BUBBLE_FG_COLOR bg=$SESSION_BUBBLE_BG_COLOR]$LBORDER "#[fg=$SESSION_BUBBLE_BG_COLOR bg=$SESSION_BUBBLE_FG_COLOR]$STATUS_RIGHT"\ "#[fg=$SESSION_BUBBLE_FG_COLOR bg=$SESSION_BUBBLE_BG_COLOR]$RBORDER" -set-option -g status-right "$STATUS_RIGHT#[default] " +set-option -g status-right "$STATUS_RIGHT" # }}} @@ -101,22 +108,24 @@ set-option -g status-right "$STATUS_RIGHT#[default] " # Window formatting {{{ # ------------------------------------------------------------------------------ -LICON="$WINDOW_INNER_BORDER#{?window_bell_flag,#[fg=$ACTIVE_FG_COLOR]$BELL_ICON, }" -RICON="#{?window_active,#{?window_zoomed_flag,⧉, }, }$WINDOW_INNER_BORDER" +LICON="#{?window_bell_flag,#[fg=$ACTIVE_FG_COLOR]$BELL_ICON, }" +RICON="#{?window_active,#{?window_zoomed_flag,⧉, }, }" WNUM='#($HOME/.config/tmux/helpers/window_to_num #I) ' WINDOW_INACTIVE=""\ -"#[bg=$WINDOW_BUBBLE_BG_COLOR fg=$WINDOW_BUBBLE_FG_COLOR]"\ +"#[bg=$WINDOW_BUBBLE_BG_COLOR fg=$WINDOW_BUBBLE_FG_COLOR]$LBORDER"\ "#[bg=$WINDOW_BUBBLE_FG_COLOR fg=$WINDOW_BUBBLE_BG_COLOR]$LICON"\ -"#[dim]${WNUM}#W"\ -"$RICON#[bg=$WINDOW_BUBBLE_BG_COLOR,fg=$WINDOW_BUBBLE_FG_COLOR,nodim]" +"#[dim]${WNUM}#W#[nodim]"\ +"#[bg=$WINDOW_BUBBLE_FG_COLOR fg=$WINDOW_BUBBLE_BG_COLOR]$RICON"\ +"#[bg=$WINDOW_BUBBLE_BG_COLOR,fg=$WINDOW_BUBBLE_FG_COLOR]$RBORDER" WINDOW_ACTIVE=""\ -"#[bg=$WINDOW_BUBBLEON_BG_COLOR fg=$WINDOW_BUBBLEON_FG_COLOR]"\ +"#[bg=$WINDOW_BUBBLEON_BG_COLOR fg=$WINDOW_BUBBLEON_FG_COLOR]$LBORDER"\ "#[bg=$WINDOW_BUBBLEON_FG_COLOR fg=$WINDOW_BUBBLEON_BG_COLOR]$LICON"\ -"#[bold]${WNUM}#W"\ -"$RICON#[bg=$WINDOW_BUBBLEON_BG_COLOR fg=$WINDOW_BUBBLEON_FG_COLOR]" +"#[bold]${WNUM}#W#[nobold]"\ +"#[bg=$WINDOW_BUBBLEON_FG_COLOR fg=$WINDOW_BUBBLEON_BG_COLOR]$RICON"\ +"#[bg=$WINDOW_BUBBLEON_BG_COLOR,fg=$WINDOW_BUBBLEON_FG_COLOR]$RBORDER" set-window-option -g window-status-format "$WINDOW_INACTIVE" set-window-option -g window-status-current-format "$WINDOW_ACTIVE" diff --git a/files/.config/zsh/rc.d/10-plugins.zsh b/files/.config/zsh/rc.d/10-plugins.zsh index 6c3b824..5b00c24 100644 --- a/files/.config/zsh/rc.d/10-plugins.zsh +++ b/files/.config/zsh/rc.d/10-plugins.zsh @@ -57,9 +57,10 @@ setopt MENU_COMPLETE setopt no_list_ambiguous # syntax highlighting — deferred to first precmd to not block startup -if [[ -f $HOME/.local/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]]; then +__DOTS[zsh_syntax_highlighting]="$HOME/.local/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" +if [[ -f "${__DOTS[zsh_syntax_highlighting]}" ]]; then _load_zsh_syntax_highlighting() { - source $HOME/.local/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh + [[ -f "${__DOTS[zsh_syntax_highlighting]}" ]] && source "${__DOTS[zsh_syntax_highlighting]}" add-zsh-hook -d precmd _load_zsh_syntax_highlighting } add-zsh-hook precmd _load_zsh_syntax_highlighting diff --git a/scripts/igfae b/scripts/igfae deleted file mode 100755 index e66ddbf..0000000 --- a/scripts/igfae +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -echo "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "⠀⠀⠀⠀⠀⠀⠀⢀⡠⣴⡔⡶⡷⡶⡒⣴⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "⠀⠀⠀⠀⢀⣤⣮⡻⣳⢹⢽⠜⡯⡏⡪⣟⢞⢵⣻⢶⣄⡀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⠀⠀⠀" -echo "⠀⠀⠀⣰⢻⣳⣳⡫⣖⠕⢭⢣⠣⡃⡎⢇⣞⣝⢾⢽⡺⢷⡀⠀⠀⠀⠀⠀⢹⡧⠀⠀⠀⠀⢀⣶⠟⠋⠉⠉⠉⠉⠋⠀⠀⠀⠀⣿⠍⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⣸⡝⢿⡄⠀⠀⠀⠀⠀⠀⢐⣿⠉⠉⠉⠉⠉⠉⠀⠀⠀" -echo "⠀⠀⢰⣛⡳⡲⢎⣚⠜⡍⢆⠑⠌⡐⠨⡪⡢⡓⣹⡸⣪⣷⡻⡀⠀⠀⠀⠀⢹⡗⠀⠀⠀⠀⣯⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠅⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡟⠀⠈⣿⡄⠀⠀⠀⠀⠀⢐⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "⠀⠀⣫⣫⡫⡫⣚⠔⢅⠊⠄⠁⠁⠀⡁⡂⠆⠣⡓⡭⣕⢶⢽⡆⠀⠀⠀⠀⣹⣏⠀⠀⠀⢈⣿⠂⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⣿⠗⠗⠗⠗⠗⠷⠀⠀⠀⢠⡷⠁⢀⠀⡘⣷⡀⠀⠀⠀⠀⢐⣯⠷⠳⠗⠗⠗⠗⠀⠀⠀" -echo "⠀⠀⣽⣕⡭⡝⡌⡍⡌⢌⠐⡀⠀⡀⢀⢐⢘⠜⡜⣖⣖⣗⡷⡇⠀⠀⠀⠀⢼⣇⠀⠀⠀⠀⢻⣅⠀⠀⠀⠀⠀⢸⣗⠀⠀⠀⠠⣿⠅⠀⠀⠀⠀⠀⠀⠀⢠⣿⠁⠐⠛⠙⠋⠻⣳⡀⠀⠀⠀⢐⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "⠀⠀⢱⣵⢞⣞⢮⡣⢇⢕⢌⠂⠄⠢⡐⢄⢢⢱⠱⢦⣣⣓⢿⠁⠀⠀⠀⠀⢺⡧⠀⠀⠀⠀⠈⠛⢷⣤⣄⣄⣠⣹⣗⠀⠀⠀⠀⣿⠅⠀⠀⠀⠀⠀⠀⢀⣾⠃⠀⠀⠀⠀⠀⠀⢹⣧⠀⠀⠀⢐⣿⣄⣄⣄⣄⣄⣄⡀⠀⠀" -echo "⠀⠀⠀⢿⣽⡺⡕⣕⢧⣣⢃⢎⠬⡸⣐⢵⡱⣌⠝⢶⣕⠯⠇⠀⠀⠀⠀⠀⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁⠉⠁⠁⠀⠀⠀⠀⠀⠉⠁⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠉⠁⠀⠀⠀⠁⠁⠉⠈⠁⠁⠉⠀⠀⠀" -echo "⠀⠀⠀⠀⠙⢼⣽⣺⢕⡵⡽⡐⡽⣌⢞⢜⣞⡮⣟⡦⠝⠉⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "⠀⠀⠀⠀⠀⠀⠈⠃⠿⢽⡽⡸⣽⢾⡜⣇⠷⠻⠉⠀⠀⠀⠀⠀⠀⠀ Instituto Galego de Fisica de Altas Enerxias " -echo "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" -echo "================================================================================" - - -# Parse arguments -HOST=$1 - -# Check whether lemonade is running -# ps cax | grep lemonade> /dev/null -# if [ $? -eq 0 ]; then -# echo "= lemonade is running. =" -# else -# echo "= lemonade was not running... lemonade was launched. =" -# nohup lemonade server -allow 127.0.0.1 & -# fi - -# Set display variable -export DISPLAY=:0.0 -echo "= export display variable. =" - -# Command to attach tmux session -CMND="/home3/marcos.romero/.linuxbrew/bin/tmux attach -t IGFAE" - -# Connect and attach -echo "Connection to diskpool1.igfae.usc.es is opened." -# ssh -R 2489:127.0.0.1:2489 -t $HOST $cmnd -ssh -t $HOST $CMND - -echo "================================================================================" - - - - -mp3p () { - youtube-dl --ignore-errors --sleep-interval 30 -i -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 -o '%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s' "$1" -} - -# vim:ft=sh From 69b4fcc50085701c00eb679830ab9c40b9978474 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Tue, 12 May 2026 18:29:19 +0200 Subject: [PATCH 3/7] fix: minimal changes into after --- files/.config/nvim/after/ftplugin/markdown.lua | 9 ++++++++- files/.config/nvim/after/ftplugin/qf.lua | 4 ++-- files/.config/nvim/after/ftplugin/tex.lua | 9 ++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/files/.config/nvim/after/ftplugin/markdown.lua b/files/.config/nvim/after/ftplugin/markdown.lua index da31014..2b44133 100644 --- a/files/.config/nvim/after/ftplugin/markdown.lua +++ b/files/.config/nvim/after/ftplugin/markdown.lua @@ -1 +1,8 @@ -vim.opt_local.wrap = false +vim.opt_local.wrap = true +vim.opt_local.textwidth = 80 +vim.opt_local.colorcolumn = '80' + +-- Simulate 80-col display by resizing the current window. +-- Accounts for sign column (2) + line numbers (up to 4 digits = 4) + 1 separator = 7 +local padding = vim.opt_local.number:get() and 7 or 2 +vim.api.nvim_win_set_width(0, 80 + padding) diff --git a/files/.config/nvim/after/ftplugin/qf.lua b/files/.config/nvim/after/ftplugin/qf.lua index e016475..c4d63f7 100644 --- a/files/.config/nvim/after/ftplugin/qf.lua +++ b/files/.config/nvim/after/ftplugin/qf.lua @@ -1,6 +1,6 @@ -- CUSTOM QUICKFIX WINDOW -local T = require('tools') +local T = _G.T vim.opt_local.wrap = false vim.opt_local.number = false @@ -38,7 +38,7 @@ vim.keymap.set( 'v', 'd', qf_delete, - { buffer = 0, desc = '[qf] delete selected quickfix entry' } + { buffer = 0, desc = '[qf] delete selected quickfix entries' } ) vim.keymap.set( 'n', diff --git a/files/.config/nvim/after/ftplugin/tex.lua b/files/.config/nvim/after/ftplugin/tex.lua index da31014..2b44133 100644 --- a/files/.config/nvim/after/ftplugin/tex.lua +++ b/files/.config/nvim/after/ftplugin/tex.lua @@ -1 +1,8 @@ -vim.opt_local.wrap = false +vim.opt_local.wrap = true +vim.opt_local.textwidth = 80 +vim.opt_local.colorcolumn = '80' + +-- Simulate 80-col display by resizing the current window. +-- Accounts for sign column (2) + line numbers (up to 4 digits = 4) + 1 separator = 7 +local padding = vim.opt_local.number:get() and 7 or 2 +vim.api.nvim_win_set_width(0, 80 + padding) From 21d3eed9d43788bbf8375bf4d505d86483296270 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Thu, 14 May 2026 00:52:54 +0200 Subject: [PATCH 4/7] feat: minor files added --- files/.config/flutter/tool_state | 3 + files/.config/nvim/after/syntax/gitcommit.vim | 6 + files/.config/nvim/lsp/copilot.lua | 8 + files/.config/python/pythonrc.py | 0 files/.config/tmux/tmux.conf | 3 + install/install_dependencies.sh | 1 + scripts/net-analyzer | 1043 ++++++++++++----- test_nerd_font.sh | 14 + 8 files changed, 777 insertions(+), 301 deletions(-) create mode 100644 files/.config/flutter/tool_state create mode 100644 files/.config/nvim/after/syntax/gitcommit.vim create mode 100644 files/.config/nvim/lsp/copilot.lua create mode 100644 files/.config/python/pythonrc.py create mode 100644 test_nerd_font.sh diff --git a/files/.config/flutter/tool_state b/files/.config/flutter/tool_state new file mode 100644 index 0000000..29278ce --- /dev/null +++ b/files/.config/flutter/tool_state @@ -0,0 +1,3 @@ +{ + "is-bot": false +} diff --git a/files/.config/nvim/after/syntax/gitcommit.vim b/files/.config/nvim/after/syntax/gitcommit.vim new file mode 100644 index 0000000..872be85 --- /dev/null +++ b/files/.config/nvim/after/syntax/gitcommit.vim @@ -0,0 +1,6 @@ +" Runs after runtime/syntax/gitcommit.vim. +" gitcommitSummary already links the whole first line to Keyword (a distinctive +" color). We leave that intact and add the prefix (word:) linked to a bolder +" group so it stands out from the rest of the summary line. +syn match gitcommitConventionalType '^\w\+!*:' contained containedin=gitcommitSummary +hi link gitcommitConventionalType DiagnosticWarn diff --git a/files/.config/nvim/lsp/copilot.lua b/files/.config/nvim/lsp/copilot.lua new file mode 100644 index 0000000..f7f32d0 --- /dev/null +++ b/files/.config/nvim/lsp/copilot.lua @@ -0,0 +1,8 @@ +local server_path = vim.api.nvim_get_runtime_file('copilot/js/language-server.js', false)[1] + +return { + cmd = { 'node', server_path, '--stdio' }, + filetypes = { '*' }, + root_dir = vim.fn.getcwd, + settings = {}, +} diff --git a/files/.config/python/pythonrc.py b/files/.config/python/pythonrc.py new file mode 100644 index 0000000..e69de29 diff --git a/files/.config/tmux/tmux.conf b/files/.config/tmux/tmux.conf index 4a744c3..7e0aeed 100644 --- a/files/.config/tmux/tmux.conf +++ b/files/.config/tmux/tmux.conf @@ -258,3 +258,6 @@ run -b '$HOME/.local/share/tmux/plugins/tpm/tpm' # }}} # vim: fdm=marker ft=tmux + +# Codex skills selector popup +bind-key C-h display-popup -w 85% -h 85% -E "cd /Users/marcos/Workspaces/personal/ai-skills && /Users/marcos/Workspaces/personal/ai-skills/scripts/select-codex-skills.sh" diff --git a/install/install_dependencies.sh b/install/install_dependencies.sh index c49b5c3..bff9131 100644 --- a/install/install_dependencies.sh +++ b/install/install_dependencies.sh @@ -308,6 +308,7 @@ BREW_LINUX=( "pandoc" "pkg-config" "python" + "uv" "readline" "ripgrep" "rlue/utils/timer" diff --git a/scripts/net-analyzer b/scripts/net-analyzer index 6d5a63f..41d305a 100755 --- a/scripts/net-analyzer +++ b/scripts/net-analyzer @@ -1,324 +1,765 @@ -#!/bin/bash - -SUBNET="192.168.1.0/24" -OUTPUT="text" -VENDOR_LOOKUP=1 -IDENTIFY=1 -DEEP=0 -REPORT_RE='for[[:space:]]+([^[:space:]]+)[[:space:]]+\(([^)]+)\)' -IS_ROOT=0 -if [[ $(id -u) -eq 0 ]]; then - IS_ROOT=1 -fi - -while [[ $# -gt 0 ]]; do - case "$1" in - --json) - OUTPUT="json" - shift - ;; - --no-vendor) - VENDOR_LOOKUP=0 - shift - ;; - --identify) - IDENTIFY=1 - shift - ;; - --no-identify) - IDENTIFY=0 - shift - ;; - --deep) - DEEP=1 - shift - ;; - *) - SUBNET="$1" - shift - ;; - esac -done - -needs() { - local cmd="$1" - local pkg="$2" - if command -v "$cmd" >/dev/null 2>&1; then - return 0 - fi - if command -v brew >/dev/null 2>&1; then - brew install "$pkg" - else - echo "Missing $cmd and Homebrew is not installed." - return 1 - fi -} +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich>=13", +# "zeroconf>=0.131", +# "requests>=2.31", +# ] +# /// +"""LAN device scanner inspired by the iOS Net Analyzer app. -DEVICE_LIST="$(mktemp)" -ARP_TABLE="$(mktemp)" -VENDOR_CACHE="$(mktemp)" -IDENTIFY_OUT="$(mktemp)" -MDNS_INFO="$(mktemp)" -SSDP_SERVER="$(mktemp)" -SSDP_LOCATION="$(mktemp)" -UPNP_INFO="$(mktemp)" -trap 'rm -f "$DEVICE_LIST" "$ARP_TABLE" "$VENDOR_CACHE" "$IDENTIFY_OUT" "$MDNS_INFO" "$SSDP_SERVER" "$SSDP_LOCATION" "$UPNP_INFO"' EXIT - -refresh_arp() { - if ! command -v arp >/dev/null 2>&1; then - : >"$ARP_TABLE" - return - fi - arp -a 2>/dev/null | awk '{ - host=$1; - ip=$2; - gsub(/[()]/,"",ip); - mac=$4; - if (mac ~ /incomplete/ || mac == "") mac=""; - print ip "\t" host "\t" mac; - }' >"$ARP_TABLE" -} +Lists hosts on the current network with hostname, MAC, vendor, advertised +Bonjour services, SSDP/UPnP identity, and (optionally) OS fingerprint. +""" -normalize_field() { - local value="$1" - value="$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" - if [[ -z $value || $value == "?" ]]; then - echo "unknown" - else - echo "$value" - fi -} +from __future__ import annotations -normalize_mac() { - local mac="$1" - if [[ -z $mac || $mac == "?" || $mac == "unknown" || $mac == *"incomplete"* ]]; then - echo "unknown" - return - fi - echo "$mac" | awk -F: '{ - if (NF==6) { - for (i=1;i<=6;i++) { - if (length($i)==1) $i="0"$i; - } - printf "%s:%s:%s:%s:%s:%s\n", $1,$2,$3,$4,$5,$6; - } else { - print $0; - } - }' -} +import argparse +import ipaddress +import json +import os +import re +import socket +import subprocess +import sys +import time +import xml.etree.ElementTree as ET +from concurrent.futures import ThreadPoolExecutor, as_completed +from dataclasses import dataclass, field +from datetime import datetime, timezone +from pathlib import Path +from typing import Optional -lookup_field() { - local ip="$1" - local file="$2" - awk -v ip="$ip" '$1==ip { $1=""; sub(/^\t/,""); print; exit }' "$file" -} +import requests +from rich.console import Console +from rich.progress import Progress, SpinnerColumn, TextColumn +from rich.table import Table +from rich import box +from zeroconf import ServiceBrowser, ServiceListener, Zeroconf + +# ---------- constants --------------------------------------------------------- + +MACVENDORS_URL = "https://api.macvendors.com/{}" +CACHE_DIR = Path(os.environ.get("XDG_CACHE_HOME", str(Path.home() / ".cache"))) / "net-analyzer" +CACHE_PATH = CACHE_DIR / "vendors.json" +CACHE_TTL_SECONDS = 30 * 24 * 3600 -lookup_arp_host() { - local ip="$1" - awk -v ip="$ip" '$1==ip {print $2; exit}' "$ARP_TABLE" +BROADCAST_MACS = {"ff:ff:ff:ff:ff:ff"} +MULTICAST_MAC_PREFIXES = ("01:00:5e:", "33:33:", "01:80:c2:") + +# Curated mDNS service types — matches the badge set the iOS app shows. +MDNS_SERVICE_TYPES = [ + "_airplay._tcp.local.", + "_raop._tcp.local.", + "_companion-link._tcp.local.", + "_homekit._tcp.local.", + "_hap._tcp.local.", + "_googlecast._tcp.local.", + "_spotify-connect._tcp.local.", + "_printer._tcp.local.", + "_ipp._tcp.local.", + "_ipps._tcp.local.", + "_smb._tcp.local.", + "_afpovertcp._tcp.local.", + "_ssh._tcp.local.", + "_http._tcp.local.", + "_device-info._tcp.local.", + "_workstation._tcp.local.", + "_matter._tcp.local.", + "_sonos._tcp.local.", + "_amzn-wplay._tcp.local.", + "_nvstream._tcp.local.", +] + +SERVICE_LABELS = { + "_airplay._tcp.local.": "AirPlay", + "_raop._tcp.local.": "AirTunes", + "_companion-link._tcp.local.": "Companion", + "_homekit._tcp.local.": "HomeKit", + "_hap._tcp.local.": "HomeKit", + "_googlecast._tcp.local.": "Cast", + "_spotify-connect._tcp.local.": "Spotify", + "_printer._tcp.local.": "Printer", + "_ipp._tcp.local.": "IPP", + "_ipps._tcp.local.": "IPPS", + "_smb._tcp.local.": "SMB", + "_afpovertcp._tcp.local.": "AFP", + "_ssh._tcp.local.": "SSH", + "_http._tcp.local.": "HTTP", + "_device-info._tcp.local.": "Info", + "_workstation._tcp.local.": "Workstation", + "_matter._tcp.local.": "Matter", + "_sonos._tcp.local.": "Sonos", + "_amzn-wplay._tcp.local.": "Amazon", + "_nvstream._tcp.local.": "NVIDIA", } -lookup_arp_mac() { - local ip="$1" - awk -v ip="$ip" '$1==ip {print $3; exit}' "$ARP_TABLE" +# OUI fallback so cold-start (no network for macvendors) still gives useful output. +OUI_FALLBACK = { + "00:03:93": "Apple, Inc.", + "00:05:02": "Apple, Inc.", + "00:0a:27": "Apple, Inc.", + "00:0a:95": "Apple, Inc.", + "00:50:e4": "Apple, Inc.", + "00:1b:63": "Apple, Inc.", + "00:1f:f3": "Apple, Inc.", + "00:25:00": "Apple, Inc.", + "3c:22:fb": "Apple, Inc.", + "a4:83:e7": "Apple, Inc.", + "f0:18:98": "Apple, Inc.", + "f4:0f:24": "Apple, Inc.", + "f8:1e:df": "Apple, Inc.", + "b8:27:eb": "Raspberry Pi Foundation", + "dc:a6:32": "Raspberry Pi Trading Ltd", + "e4:5f:01": "Raspberry Pi Trading Ltd", + "d8:3a:dd": "Raspberry Pi Trading Ltd", + "f0:ef:86": "Google, Inc.", + "1c:f2:9a": "Google, Inc.", + "44:07:0b": "Google, Inc.", + "f4:f5:d8": "Google, Inc.", + "ac:63:be": "Amazon Technologies Inc.", + "fc:65:de": "Amazon Technologies Inc.", + "00:1a:11": "Google, Inc.", } -lookup_vendor() { - local mac="$1" - if [[ -z $mac || $VENDOR_LOOKUP -ne 1 ]] || ! command -v curl >/dev/null 2>&1; then - echo "unknown" +SSDP_MX = 2 +SSDP_GROUP = ("239.255.255.250", 1900) +SSDP_M_SEARCH = ( + "M-SEARCH * HTTP/1.1\r\n" + "HOST: 239.255.255.250:1900\r\n" + 'MAN: "ssdp:discover"\r\n' + f"MX: {SSDP_MX}\r\n" + "ST: ssdp:all\r\n\r\n" +).encode("ascii") + +console = Console(stderr=True) + +# ---------- model ------------------------------------------------------------- + + +@dataclass +class Host: + ip: str + hostname: Optional[str] = None + mac: Optional[str] = None + vendor: Optional[str] = None + os_: Optional[str] = None + mdns_services: set[str] = field(default_factory=set) + ssdp: bool = False + friendly_name: Optional[str] = None + manufacturer: Optional[str] = None + model: Optional[str] = None + ssdp_location: Optional[str] = None + + +# ---------- default route / CIDR --------------------------------------------- + + +def detect_default_cidr() -> tuple[str, Optional[str]]: + """Return (cidr, local_ip). Falls back to 192.168.1.0/24 with a warning.""" + try: + if sys.platform == "darwin": + out = subprocess.check_output(["route", "-n", "get", "default"], text=True, timeout=3) + iface_m = re.search(r"interface:\s*(\S+)", out) + if not iface_m: + raise RuntimeError("no default interface") + iface = iface_m.group(1) + ifc = subprocess.check_output(["ifconfig", iface], text=True, timeout=3) + m = re.search(r"inet (\S+) netmask (0x[0-9a-f]+)", ifc) + if not m: + raise RuntimeError("no inet on iface") + ip = m.group(1) + mask = bin(int(m.group(2), 16)).count("1") + net = ipaddress.IPv4Network(f"{ip}/{mask}", strict=False) + return str(net), ip + # linux / wsl + out = subprocess.check_output( + ["ip", "-o", "-4", "route", "show", "default"], text=True, timeout=3 + ) + parts = out.split() + iface = parts[parts.index("dev") + 1] + addr = subprocess.check_output( + ["ip", "-o", "-4", "addr", "show", "dev", iface], text=True, timeout=3 + ) + m = re.search(r"inet (\S+)/(\d+)", addr) + if not m: + raise RuntimeError("no inet/prefix") + ip, prefix = m.group(1), m.group(2) + net = ipaddress.IPv4Network(f"{ip}/{prefix}", strict=False) + return str(net), ip + except Exception as exc: + console.print( + f"[yellow][warn][/] could not auto-detect CIDR ({exc}); falling back to 192.168.1.0/24" + ) + return "192.168.1.0/24", None + + +# ---------- nmap host discovery ---------------------------------------------- + + +def nmap_ping_scan(cidr: str, *, unprivileged: bool) -> list[Host]: + if not _have("nmap"): + console.print("[yellow][warn][/] nmap not found; skipping active host discovery") + return [] + args = ["nmap", "-sn", "-oX", "-"] + if unprivileged: + args.append("--unprivileged") + args.append(cidr) + try: + out = subprocess.check_output(args, text=True, timeout=120) + except subprocess.CalledProcessError as exc: + console.print(f"[yellow][warn][/] nmap failed: {exc}") + return [] + return _parse_nmap_xml(out) + + +def _parse_nmap_xml(xml_text: str) -> list[Host]: + hosts: list[Host] = [] + try: + root = ET.fromstring(xml_text) + except ET.ParseError: + return hosts + for host_el in root.findall("host"): + status = host_el.find("status") + if status is not None and status.get("state") != "up": + continue + ip: Optional[str] = None + mac: Optional[str] = None + for addr in host_el.findall("address"): + kind = addr.get("addrtype") + if kind == "ipv4": + ip = addr.get("addr") + elif kind == "mac": + mac = (addr.get("addr") or "").lower() or None + if not ip: + continue + hostname = None + hn_el = host_el.find("hostnames/hostname") + if hn_el is not None: + hostname = hn_el.get("name") or None + hosts.append(Host(ip=ip, hostname=hostname, mac=mac)) + return hosts + + +# ---------- ARP table --------------------------------------------------------- + +_ARP_RE = re.compile(r"\(([\d.]+)\) at ([0-9a-fA-F:]{11,17})") + + +def read_arp_table() -> dict[str, str]: + if not _have("arp"): + return {} + try: + out = subprocess.check_output(["arp", "-an"], text=True, timeout=5) + except subprocess.CalledProcessError: + return {} + result: dict[str, str] = {} + for ip, mac in _ARP_RE.findall(out): + mac = _normalize_mac(mac) + if not mac: + continue + if mac in BROADCAST_MACS or mac.startswith(MULTICAST_MAC_PREFIXES): + continue + result[ip] = mac + return result + + +def _normalize_mac(mac: str) -> str: + mac = mac.lower().strip() + if "incomplete" in mac or not mac: + return "" + parts = mac.split(":") + if len(parts) != 6: + return "" + return ":".join(p.zfill(2) for p in parts) + + +# ---------- vendor cache ------------------------------------------------------ + + +def _load_vendor_cache() -> dict: + if not CACHE_PATH.exists(): + return {} + try: + data = json.loads(CACHE_PATH.read_text()) + return data if isinstance(data, dict) else {} + except (OSError, json.JSONDecodeError): + return {} + + +def _save_vendor_cache(cache: dict) -> None: + try: + CACHE_DIR.mkdir(parents=True, exist_ok=True) + CACHE_PATH.write_text(json.dumps(cache, separators=(",", ":"))) + except OSError as exc: + console.print(f"[yellow][warn][/] could not save vendor cache: {exc}") + + +def _is_locally_administered(mac: str) -> bool: + """Random/privacy MAC — never in the OUI registry. The U/L bit is bit 1 of byte 0.""" + try: + first_byte = int(mac.split(":")[0], 16) + except (ValueError, IndexError): + return False + return bool(first_byte & 0b10) + + +def lookup_vendor(mac: str, cache: dict, *, use_cache: bool = True) -> Optional[str]: + if not mac: + return None + oui = ":".join(mac.split(":")[:3]) + if use_cache: + entry = cache.get(oui) + if entry and isinstance(entry, dict): + if time.time() - entry.get("ts", 0) < CACHE_TTL_SECONDS: + return entry.get("vendor") or None + if oui in OUI_FALLBACK: + vendor = OUI_FALLBACK[oui] + cache[oui] = {"vendor": vendor, "ts": int(time.time())} + return vendor + if _is_locally_administered(mac): + cache[oui] = {"vendor": None, "ts": int(time.time())} + return None + backoffs = (0.0, 0.8, 2.0, 4.0) + vendor: Optional[str] = None + for delay in backoffs: + if delay: + time.sleep(delay) + try: + r = requests.get(MACVENDORS_URL.format(mac), timeout=4) + except requests.RequestException: + continue + if r.status_code == 429: + continue + if r.status_code == 404: + cache[oui] = {"vendor": None, "ts": int(time.time())} + return None + if r.ok: + vendor = r.text.strip() or None + cache[oui] = {"vendor": vendor, "ts": int(time.time())} + return vendor + break + return None + + +# ---------- mDNS (zeroconf) --------------------------------------------------- + + +class _MDNSCollector(ServiceListener): + def __init__(self, zc: Zeroconf, sink: dict[str, set[str]]) -> None: + self.zc = zc + self.sink = sink + + def add_service(self, zc: Zeroconf, type_: str, name: str) -> None: # noqa: D401 + try: + info = zc.get_service_info(type_, name, timeout=2000) + except Exception: + return + if not info: + return + try: + addrs = info.parsed_addresses() + except Exception: + addrs = [] + for addr in addrs: + if ":" in addr: # skip IPv6 for now + continue + self.sink.setdefault(addr, set()).add(type_) + + def update_service(self, *args, **kwargs) -> None: return - fi - local cached - cached=$(awk -v mac="$mac" '$1==mac { $1=""; sub(/^\t/,""); print; exit }' "$VENDOR_CACHE") - if [[ -n $cached ]]; then - echo "$cached" + def remove_service(self, *args, **kwargs) -> None: return - fi - local vendor - vendor=$(curl -fsS "https://api.macvendors.com/$mac" 2>/dev/null | tr -d '\r' || true) - vendor=$(normalize_field "$vendor") - printf "%s\t%s\n" "$mac" "$vendor" >>"$VENDOR_CACHE" - echo "$vendor" -} -lookup_os() { - local ip="$1" - if [[ $DEEP -ne 1 ]] || ! command -v nmap >/dev/null 2>&1; then - echo "unknown" +def discover_mdns(timeout: float) -> dict[str, set[str]]: + sink: dict[str, set[str]] = {} + try: + zc = Zeroconf() + except OSError as exc: + console.print(f"[yellow][warn][/] zeroconf init failed ({exc}); skipping mDNS") + return sink + try: + listener = _MDNSCollector(zc, sink) + browsers = [ServiceBrowser(zc, t, listener) for t in MDNS_SERVICE_TYPES] + time.sleep(timeout) + for b in browsers: + try: + b.cancel() + except Exception: + pass + finally: + try: + zc.close() + except Exception: + pass + return sink + + +# ---------- SSDP -------------------------------------------------------------- + + +def discover_ssdp(timeout: float, local_ip: Optional[str]) -> dict[str, dict]: + """Returns ip -> {server, location}.""" + results: dict[str, dict] = {} + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + try: + if local_ip: + try: + sock.bind((local_ip, 0)) + except OSError: + sock.bind(("", 0)) + else: + sock.bind(("", 0)) + sock.settimeout(timeout) + try: + sock.sendto(SSDP_M_SEARCH, SSDP_GROUP) + except OSError as exc: + console.print(f"[yellow][warn][/] SSDP send failed ({exc}); skipping") + return results + deadline = time.time() + timeout + while time.time() < deadline: + sock.settimeout(max(0.1, deadline - time.time())) + try: + data, (peer_ip, _port) = sock.recvfrom(4096) + except socket.timeout: + break + except OSError: + break + text = data.decode("utf-8", errors="replace") + server = _http_header(text, "Server") + location = _http_header(text, "Location") + entry = results.setdefault(peer_ip, {}) + if server: + entry.setdefault("server", server) + if location: + entry.setdefault("location", location) + finally: + sock.close() + return results + + +def _http_header(text: str, name: str) -> Optional[str]: + pat = re.compile(rf"^{re.escape(name)}\s*:\s*(.+?)\s*$", re.IGNORECASE | re.MULTILINE) + m = pat.search(text) + return m.group(1) if m else None + + +def fetch_upnp_descriptor(location: str) -> dict[str, Optional[str]]: + try: + r = requests.get(location, timeout=3) + if not r.ok: + return {} + xml = r.text + except requests.RequestException: + return {} + + def grab(tag: str) -> Optional[str]: + m = re.search(rf"<{tag}>([^<]+)", xml) + return m.group(1).strip() if m else None + + return { + "friendly_name": grab("friendlyName"), + "manufacturer": grab("manufacturer"), + "model": grab("modelName"), + } + + +# ---------- deep scan --------------------------------------------------------- + + +def nmap_deep_scan(hosts: list[Host]) -> None: + if not _have("nmap"): return - fi + with Progress( + SpinnerColumn(), + TextColumn("[progress.description]{task.description}"), + console=console, + ) as progress: + task = progress.add_task("deep scan", total=len(hosts)) + for h in hosts: + progress.update(task, description=f"deep scan {h.ip}") + try: + out = subprocess.check_output( + [ + "nmap", + "-O", + "-sV", + "--osscan-guess", + "--host-timeout", + "30s", + "-oX", + "-", + h.ip, + ], + text=True, + timeout=45, + stderr=subprocess.DEVNULL, + ) + h.os_ = _parse_os_from_xml(out) + except (subprocess.CalledProcessError, subprocess.TimeoutExpired): + pass + progress.advance(task) - local os - os=$(nmap -O -sV --osscan-guess --host-timeout 30s "$ip" 2>/dev/null | awk -F': ' \ - '/OS details:|Running:|Service Info: OS:/{print $2; exit}') - echo "$(normalize_field "$os")" -} -parse_mdns() { - awk ' - /^\| mdns-discovery:/ {in_block=1; next} - in_block && $1 == "|" && $2 ~ /^[0-9]+\./ {ip=$2; next} - in_block && $1 == "|" && $2 == "Hostname:" && ip != "" { - $1=""; $2=""; - sub(/^[[:space:]]+/, "", $0); - print ip "\t" $0; - next - } - ' "$IDENTIFY_OUT" >"$MDNS_INFO" -} +def _parse_os_from_xml(xml_text: str) -> Optional[str]: + try: + root = ET.fromstring(xml_text) + except ET.ParseError: + return None + for host_el in root.findall("host"): + for match in host_el.findall("os/osmatch"): + name = match.get("name") + if name: + return name + info = host_el.find(".//service") + if info is not None and info.get("ostype"): + return info.get("ostype") + return None + + +# ---------- output ------------------------------------------------------------ + + +def build_table(hosts: list[Host], *, wide: bool) -> Table: + if wide: + table = Table(box=box.SIMPLE_HEAVY, show_lines=False, expand=False) + for col in ( + "IP", + "Hostname", + "MAC", + "Vendor", + "OS", + "mDNS", + "SSDP", + "Friendly", + "Manufacturer", + "Model", + ): + table.add_column(col, overflow="fold") + for h in hosts: + mdns = ", ".join(sorted(_label(s) for s in h.mdns_services)) or "-" + table.add_row( + h.ip, + h.hostname or "-", + h.mac or "-", + h.vendor or "-", + h.os_ or "-", + mdns, + "yes" if h.ssdp else "-", + h.friendly_name or "-", + h.manufacturer or "-", + h.model or "-", + ) + return table -parse_ssdp() { - awk ' - /^\| broadcast-upnp-discovery:/ {in_block=1; next} - in_block && $1 == "|" && $2 == "Server:" { - $1=""; $2=""; - sub(/^[[:space:]]+/, "", $0); - server=$0; - next - } - in_block && $1 == "|" && $2 == "Location:" { - loc=$3; - ip=loc; - sub(/^https?:\/\//, "", ip); - sub(/[:\/].*$/, "", ip); - if (ip != "") { - print ip "\t" server > "'"$SSDP_SERVER"'"; - print ip "\t" loc > "'"$SSDP_LOCATION"'"; + table = Table(box=box.SIMPLE_HEAVY, show_lines=False, expand=False) + for col in ("IP", "Hostname", "MAC", "Vendor", "OS", "Services", "Friendly Name"): + table.add_column(col, overflow="fold") + for h in hosts: + labels = sorted({_label(s) for s in h.mdns_services}) + if h.ssdp: + labels.append("+UPnP") + services = ", ".join(labels) or "-" + table.add_row( + h.ip, + h.hostname or "-", + h.mac or "-", + h.vendor or "-", + h.os_ or "-", + services, + h.friendly_name or "-", + ) + return table + + +def _label(service_type: str) -> str: + return SERVICE_LABELS.get(service_type, service_type.rstrip(".").split(".")[0].lstrip("_")) + + +def to_json(hosts: list[Host], cidr: str) -> str: + payload = { + "cidr": cidr, + "scanned_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), + "hosts": [ + { + "ip": h.ip, + "hostname": h.hostname, + "mac": h.mac, + "vendor": h.vendor, + "os": h.os_, + "mdns_services": sorted(h.mdns_services), + "ssdp": h.ssdp, + "friendly_name": h.friendly_name, + "manufacturer": h.manufacturer, + "model": h.model, } - server=""; - next - } - ' "$IDENTIFY_OUT" -} + for h in hosts + ], + } + return json.dumps(payload, indent=2) -fetch_upnp_details() { - local location="$1" - if [[ -z $location ]] || ! command -v curl >/dev/null 2>&1; then - printf "%s\t%s\t%s\n" "unknown" "unknown" "unknown" - return - fi - local xml - xml=$(curl -fsS --max-time 2 "$location" 2>/dev/null | tr -d '\r' || true) - local friendly manufacturer model - friendly=$(echo "$xml" | sed -n 's:.*\(.*\).*:\1:p' | head -n 1) - manufacturer=$(echo "$xml" | sed -n 's:.*\(.*\).*:\1:p' | head -n 1) - model=$(echo "$xml" | sed -n 's:.*\(.*\).*:\1:p' | head -n 1) - printf "%s\t%s\t%s\n" "$(normalize_field "$friendly")" "$(normalize_field "$manufacturer")" "$(normalize_field "$model")" -} -if [[ $DEEP -eq 1 && $IS_ROOT -ne 1 ]]; then - echo "Deep scans require sudo on macOS. Disabling --deep." >&2 - DEEP=0 -fi - -echo "Scanning network $SUBNET..." - -needs nmap nmap || true - -if command -v nmap >/dev/null 2>&1; then - nmap_args=("-sn") - if [[ $IS_ROOT -ne 1 ]]; then - nmap_args+=("--unprivileged") - fi - nmap "${nmap_args[@]}" "$SUBNET" 2>/dev/null | while read -r line; do - if [[ $line == *"Nmap scan report for"* ]]; then - if [[ $line =~ $REPORT_RE ]]; then - host="${BASH_REMATCH[1]}" - ip="${BASH_REMATCH[2]}" - else - ip="${line##*for }" - host="unknown" - fi - printf "%s\t%s\n" "$ip" "$host" - fi - done >"$DEVICE_LIST" - refresh_arp - if [[ ! -s $DEVICE_LIST ]]; then - awk '$3 != "" {print $1 "\t" $2}' "$ARP_TABLE" >"$DEVICE_LIST" - fi -else - refresh_arp - awk '$3 != "" {print $1 "\t" $2}' "$ARP_TABLE" >"$DEVICE_LIST" -fi - -if [[ $IDENTIFY -eq 1 ]] && command -v nmap >/dev/null 2>&1; then - if [[ $IS_ROOT -eq 1 ]]; then - nmap -sU -p 1900,5353 --script broadcast-upnp-discovery,mdns-discovery --script-timeout 10s \ - 2>/dev/null >"$IDENTIFY_OUT" || true - parse_mdns - parse_ssdp - else - echo "Skipping UDP discovery (requires sudo for nmap -sU on macOS)." >&2 - fi -fi - -if [[ $DEEP -eq 1 && -s "$SSDP_LOCATION" ]]; then - while IFS=$'\t' read -r ip location; do - if grep -q "^$ip\t" "$UPNP_INFO" 2>/dev/null; then - continue - fi - IFS=$'\t' read -r friendly manufacturer model < <(fetch_upnp_details "$location") - printf "%s\t%s\t%s\t%s\n" "$ip" "$friendly" "$manufacturer" "$model" >>"$UPNP_INFO" - done <"$SSDP_LOCATION" -fi - -if [[ $OUTPUT == "text" ]]; then - echo -e "IP Address\tHostname\tMAC Address\tVendor\tOS\tmDNS\tSSDP\tFriendly\tManufacturer\tModel" -else - echo "[" -fi - -is_ignored_mac() { - local mac="$1" - case "$mac" in - ff:ff:ff:ff:ff:ff | 01:00:5e:* | 33:33:*) +# ---------- helpers ----------------------------------------------------------- + + +def _have(cmd: str) -> bool: + from shutil import which + + return which(cmd) is not None + + +def _sort_key(h: Host) -> tuple: + try: + return tuple(int(p) for p in h.ip.split(".")) + except ValueError: + return (0,) + + +# ---------- main -------------------------------------------------------------- + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Scan the local network and list devices, services, and identity (iOS Net Analyzer-style)." + ) + parser.add_argument("cidr", nargs="?", help="CIDR to scan (default: auto-detect)") + parser.add_argument("--json", action="store_true", help="emit JSON instead of a table") + parser.add_argument("--wide", action="store_true", help="show all 10 columns (parity with old bash version)") + parser.add_argument("--no-vendor", action="store_true", help="skip MAC vendor lookup") + parser.add_argument("--identify", dest="identify", action="store_true", default=True, help="run mDNS + SSDP discovery (default)") + parser.add_argument("--no-identify", dest="identify", action="store_false", help="skip mDNS + SSDP discovery") + parser.add_argument("--deep", action="store_true", help="run nmap OS fingerprint (requires sudo)") + parser.add_argument("--timeout-mdns", type=float, default=8.0, help="mDNS browse duration in seconds (default: 8)") + parser.add_argument("--timeout-ssdp", type=float, default=5.0, help="SSDP listen duration in seconds (default: 5)") + parser.add_argument("--no-cache", action="store_true", help="ignore the on-disk vendor cache for this run") + parser.add_argument("--clear-cache", action="store_true", help="wipe the vendor cache and exit") + parser.add_argument("--quiet", action="store_true", help="suppress progress messages on stderr") + args = parser.parse_args() + + if args.quiet: + console.quiet = True + + if args.clear_cache: + try: + CACHE_PATH.unlink() + console.print(f"[green]cleared[/] {CACHE_PATH}") + except FileNotFoundError: + console.print(f"[dim]no cache at {CACHE_PATH}[/]") return 0 - ;; - esac - return 1 -} -first=1 -while IFS=$'\t' read -r ip host; do - [[ -z $ip ]] && continue - arp_host=$(lookup_arp_host "$ip") - if [[ $host == "unknown" || $host == "?" || -z $host ]]; then - host="$arp_host" - fi - host=$(normalize_field "$host") - mac=$(normalize_mac "$(lookup_arp_mac "$ip")") - if is_ignored_mac "$mac"; then - continue - fi - vendor=$(lookup_vendor "$mac") - os=$(lookup_os "$ip") - mdns=$(normalize_field "$(lookup_field "$ip" "$MDNS_INFO")") - ssdp=$(normalize_field "$(lookup_field "$ip" "$SSDP_SERVER")") - upnp_line=$(lookup_field "$ip" "$UPNP_INFO") - IFS=$'\t' read -r friendly manufacturer model <<<"$upnp_line" - friendly=$(normalize_field "$friendly") - manufacturer=$(normalize_field "$manufacturer") - model=$(normalize_field "$model") - - if [[ $OUTPUT == "json" ]]; then - if [[ $first -eq 0 ]]; then - echo "," - fi - first=0 - printf ' {"ip":"%s","hostname":"%s","mac":"%s","vendor":"%s","os":"%s","mdns":"%s","ssdp":"%s","friendly":"%s","manufacturer":"%s","model":"%s"}' \ - "$ip" "$host" "$mac" "$vendor" "$os" "$mdns" "$ssdp" "$friendly" "$manufacturer" "$model" - else - printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ - "$ip" "$host" "$mac" "$vendor" "$os" "$mdns" "$ssdp" "$friendly" "$manufacturer" "$model" - fi -done <"$DEVICE_LIST" - -if [[ $OUTPUT == "json" ]]; then - echo - echo "]" -fi - -# vim: ft=bash + is_root = hasattr(os, "geteuid") and os.geteuid() == 0 + if args.deep and not is_root: + console.print("[yellow][warn][/] --deep requires root; ignoring. Re-run with sudo.") + args.deep = False + + cidr = args.cidr + local_ip: Optional[str] = None + if not cidr: + cidr, local_ip = detect_default_cidr() + console.print(f"[bold]Scanning[/] {cidr} …") + + hosts = nmap_ping_scan(cidr, unprivileged=not is_root) + + arp = read_arp_table() + by_ip: dict[str, Host] = {h.ip: h for h in hosts} + for ip, mac in arp.items(): + if ip in by_ip: + if not by_ip[ip].mac: + by_ip[ip].mac = mac + else: + try: + if ipaddress.ip_address(ip) in ipaddress.ip_network(cidr): + by_ip[ip] = Host(ip=ip, mac=mac) + except ValueError: + continue + + # parallel: vendor + SSDP + cache = {} if args.no_cache else _load_vendor_cache() + + ssdp_results: dict[str, dict] = {} + with ThreadPoolExecutor(max_workers=4) as pool: + vendor_futures = {} + if not args.no_vendor: + for h in by_ip.values(): + if h.mac: + vendor_futures[pool.submit(lookup_vendor, h.mac, cache, use_cache=not args.no_cache)] = h + ssdp_future = None + if args.identify: + ssdp_future = pool.submit(discover_ssdp, args.timeout_ssdp, local_ip) + for fut in as_completed(vendor_futures): + host = vendor_futures[fut] + try: + host.vendor = fut.result() + except Exception: + pass + if ssdp_future: + ssdp_results = ssdp_future.result() + + # merge SSDP into hosts, then fetch descriptors in parallel + if ssdp_results: + for ip, entry in ssdp_results.items(): + host = by_ip.get(ip) + if host is None: + try: + if ipaddress.ip_address(ip) not in ipaddress.ip_network(cidr): + continue + except ValueError: + continue + host = Host(ip=ip) + by_ip[ip] = host + host.ssdp = True + host.ssdp_location = entry.get("location") + with ThreadPoolExecutor(max_workers=8) as pool: + futs = {} + for host in by_ip.values(): + if host.ssdp_location: + futs[pool.submit(fetch_upnp_descriptor, host.ssdp_location)] = host + for fut in as_completed(futs): + host = futs[fut] + try: + desc = fut.result() + except Exception: + desc = {} + host.friendly_name = desc.get("friendly_name") + host.manufacturer = desc.get("manufacturer") + host.model = desc.get("model") + + # mDNS pass (zeroconf runs its own threads) + if args.identify: + mdns_results = discover_mdns(args.timeout_mdns) + for ip, types in mdns_results.items(): + host = by_ip.get(ip) + if host is None: + try: + if ipaddress.ip_address(ip) not in ipaddress.ip_network(cidr): + continue + except ValueError: + continue + host = Host(ip=ip) + by_ip[ip] = host + host.mdns_services |= types + + if args.deep and is_root: + nmap_deep_scan(list(by_ip.values())) + + hosts_sorted = sorted(by_ip.values(), key=_sort_key) + + if args.json: + sys.stdout.write(to_json(hosts_sorted, cidr) + "\n") + else: + out_console = Console() + out_console.print(build_table(hosts_sorted, wide=args.wide)) + + if not args.no_cache: + _save_vendor_cache(cache) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/test_nerd_font.sh b/test_nerd_font.sh new file mode 100644 index 0000000..994b32a --- /dev/null +++ b/test_nerd_font.sh @@ -0,0 +1,14 @@ +curl -fsSL https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/glyphnames.json | +python3 -c ' +import sys, json + +data = json.load(sys.stdin) + +for name, info in data.items(): + if name == "METADATA": + continue + glyph = info.get("char") + if glyph: + print(f"{glyph} U+{ord(glyph):04X} {name}") +' > nerdfont-icons.txt +cat nerdfont-icons.txt From 2ba69f3a11b9379ab81c155aaef7815d0017ed7a Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Thu, 14 May 2026 00:56:16 +0200 Subject: [PATCH 5/7] chore: move config --- files/.config/nvim/after/plugin/nvim-bqf.lua | 49 -- files/.config/nvim/lazy-lock.json | 110 ---- files/.config/nvim/lua/dracula-pro/colors.lua | 104 ---- files/.config/nvim/lua/dracula-pro/config.lua | 25 - .../nvim/lua/dracula-pro/groups/base.lua | 126 ----- .../nvim/lua/dracula-pro/groups/plugins.lua | 531 ------------------ .../lua/dracula-pro/groups/treesitter.lua | 141 ----- files/.config/nvim/lua/dracula-pro/init.lua | 63 --- files/.config/nvim/neovim.logo | 136 ----- files/.config/nvim/nvim-pack-lock.json | 356 +----------- .../nvim/tests/integration/test_keymaps.lua | 55 -- .../nvim/tests/integration/test_lsp.lua | 135 ----- .../nvim/tests/integration/test_options.lua | 45 -- .../tests/integration/test_plugins_load.lua | 33 -- files/.config/nvim/tests/minimal_init.lua | 34 -- files/.config/nvim/tests/run_tests.sh | 23 - .../nvim/tests/unit/test_highlight.lua | 109 ---- .../.config/nvim/tests/unit/test_strings.lua | 53 -- files/.config/nvim/tests/unit/test_tools.lua | 113 ---- nvim_old/.stylua.toml | 8 + {files/.config/nvim => nvim_old}/LICENSE | 0 {files/.config/nvim => nvim_old}/README.md | 0 nvim_old/after/ftplugin/gitcommit.lua | 4 + nvim_old/after/ftplugin/help.lua | 35 ++ nvim_old/after/ftplugin/markdown.lua | 8 + nvim_old/after/ftplugin/qf.lua | 58 ++ nvim_old/after/ftplugin/tex.lua | 8 + nvim_old/after/ftplugin/xml.lua | 48 ++ nvim_old/after/plugin/nvim-bqf.lua | 49 ++ .../after/syntax/dap-repl.vim | 0 .../nvim => nvim_old}/colors/carbon-mist.lua | 0 {files/.config/nvim => nvim_old}/filetype.lua | 0 nvim_old/init.lua | 41 ++ .../nvim => nvim_old}/lua/external_grep.lua | 1 + .../nvim => nvim_old}/lua/highlight.lua | 0 .../.config/nvim => nvim_old}/lua/keymaps.lua | 3 + .../.config/nvim => nvim_old}/lua/options.lua | 1 + .../nvim => nvim_old}/lua/packloader.lua | 0 .../lua/packs/bufferline.lua | 0 .../lua/packs/colorscheme.lua | 0 .../nvim => nvim_old}/lua/packs/comment.lua | 1 + .../lua/packs/completion.lua | 0 .../nvim => nvim_old}/lua/packs/copilot.lua | 0 .../nvim => nvim_old}/lua/packs/dadbod.lua | 0 .../nvim => nvim_old}/lua/packs/debug.lua | 0 .../nvim => nvim_old}/lua/packs/filetype.lua | 0 .../nvim => nvim_old}/lua/packs/format.lua | 0 .../nvim => nvim_old}/lua/packs/fzf.lua | 0 .../nvim => nvim_old}/lua/packs/gaming.lua | 0 .../nvim => nvim_old}/lua/packs/git.lua | 0 .../nvim => nvim_old}/lua/packs/init.lua | 0 .../nvim => nvim_old}/lua/packs/linting.lua | 0 .../nvim => nvim_old}/lua/packs/lsp.lua | 0 .../nvim => nvim_old}/lua/packs/mini.lua | 0 .../lua/packs/navigation.lua | 0 .../nvim => nvim_old}/lua/packs/noice.lua | 0 .../nvim => nvim_old}/lua/packs/obsidian.lua | 0 .../nvim => nvim_old}/lua/packs/remote.lua | 0 .../nvim => nvim_old}/lua/packs/repl.lua | 0 .../nvim => nvim_old}/lua/packs/terminal.lua | 0 .../nvim => nvim_old}/lua/packs/testing.lua | 0 .../nvim => nvim_old}/lua/packs/todo.lua | 0 .../lua/packs/treesitter.lua | 0 .../nvim => nvim_old}/lua/packs/ui.lua | 0 .../nvim => nvim_old}/lua/packs/vimtex.lua | 0 .../nvim => nvim_old}/lua/packs/whichkey.lua | 0 .../.config/nvim => nvim_old}/lua/tools.lua | 1 + nvim_old/nvim-pack-lock.json | 456 +++++++++++++++ .../nvim => nvim_old}/plugin/autocommands.lua | 0 .../nvim => nvim_old}/plugin/colors.lua | 0 .../nvim => nvim_old}/plugin/lastplace.lua | 0 .../.config/nvim => nvim_old}/plugin/lsp.lua | 0 .../.config/nvim => nvim_old}/plugin/root.lua | 0 .../nvim => nvim_old}/plugin/statuscolumn.lua | 0 .../nvim => nvim_old}/plugin/statusline.lua | 0 .../queries/html/rainbow-tags.scm | 0 .../queries/vim/highlights.scm | 0 .../nvim => nvim_old}/skeleton/skel.beamer | 0 .../.config/nvim => nvim_old}/skeleton/skel.c | 0 .../nvim => nvim_old}/skeleton/skel.cpp | 0 .../.config/nvim => nvim_old}/skeleton/skel.h | 0 .../nvim => nvim_old}/skeleton/skel.hpp | 0 .../nvim => nvim_old}/skeleton/skel.lua | 0 .../nvim => nvim_old}/skeleton/skel.py | 0 .../nvim => nvim_old}/skeleton/skel.sh | 0 .../nvim => nvim_old}/skeleton/skel.tex | 0 86 files changed, 750 insertions(+), 2213 deletions(-) delete mode 100644 files/.config/nvim/lazy-lock.json delete mode 100644 files/.config/nvim/lua/dracula-pro/colors.lua delete mode 100644 files/.config/nvim/lua/dracula-pro/config.lua delete mode 100644 files/.config/nvim/lua/dracula-pro/groups/base.lua delete mode 100644 files/.config/nvim/lua/dracula-pro/groups/plugins.lua delete mode 100644 files/.config/nvim/lua/dracula-pro/groups/treesitter.lua delete mode 100644 files/.config/nvim/lua/dracula-pro/init.lua delete mode 100644 files/.config/nvim/neovim.logo delete mode 100644 files/.config/nvim/tests/integration/test_keymaps.lua delete mode 100644 files/.config/nvim/tests/integration/test_lsp.lua delete mode 100644 files/.config/nvim/tests/integration/test_options.lua delete mode 100644 files/.config/nvim/tests/integration/test_plugins_load.lua delete mode 100644 files/.config/nvim/tests/minimal_init.lua delete mode 100755 files/.config/nvim/tests/run_tests.sh delete mode 100644 files/.config/nvim/tests/unit/test_highlight.lua delete mode 100644 files/.config/nvim/tests/unit/test_strings.lua delete mode 100644 files/.config/nvim/tests/unit/test_tools.lua create mode 100644 nvim_old/.stylua.toml rename {files/.config/nvim => nvim_old}/LICENSE (100%) rename {files/.config/nvim => nvim_old}/README.md (100%) create mode 100644 nvim_old/after/ftplugin/gitcommit.lua create mode 100644 nvim_old/after/ftplugin/help.lua create mode 100644 nvim_old/after/ftplugin/markdown.lua create mode 100644 nvim_old/after/ftplugin/qf.lua create mode 100644 nvim_old/after/ftplugin/tex.lua create mode 100644 nvim_old/after/ftplugin/xml.lua create mode 100644 nvim_old/after/plugin/nvim-bqf.lua rename {files/.config/nvim => nvim_old}/after/syntax/dap-repl.vim (100%) rename {files/.config/nvim => nvim_old}/colors/carbon-mist.lua (100%) rename {files/.config/nvim => nvim_old}/filetype.lua (100%) create mode 100644 nvim_old/init.lua rename {files/.config/nvim => nvim_old}/lua/external_grep.lua (99%) rename {files/.config/nvim => nvim_old}/lua/highlight.lua (100%) rename {files/.config/nvim => nvim_old}/lua/keymaps.lua (99%) rename {files/.config/nvim => nvim_old}/lua/options.lua (99%) rename {files/.config/nvim => nvim_old}/lua/packloader.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/bufferline.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/colorscheme.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/comment.lua (99%) rename {files/.config/nvim => nvim_old}/lua/packs/completion.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/copilot.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/dadbod.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/debug.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/filetype.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/format.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/fzf.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/gaming.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/git.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/init.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/linting.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/lsp.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/mini.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/navigation.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/noice.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/obsidian.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/remote.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/repl.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/terminal.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/testing.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/todo.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/treesitter.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/ui.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/vimtex.lua (100%) rename {files/.config/nvim => nvim_old}/lua/packs/whichkey.lua (100%) rename {files/.config/nvim => nvim_old}/lua/tools.lua (99%) create mode 100644 nvim_old/nvim-pack-lock.json rename {files/.config/nvim => nvim_old}/plugin/autocommands.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/colors.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/lastplace.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/lsp.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/root.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/statuscolumn.lua (100%) rename {files/.config/nvim => nvim_old}/plugin/statusline.lua (100%) rename {files/.config/nvim => nvim_old}/queries/html/rainbow-tags.scm (100%) rename {files/.config/nvim => nvim_old}/queries/vim/highlights.scm (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.beamer (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.c (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.cpp (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.h (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.hpp (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.lua (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.py (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.sh (100%) rename {files/.config/nvim => nvim_old}/skeleton/skel.tex (100%) diff --git a/files/.config/nvim/after/plugin/nvim-bqf.lua b/files/.config/nvim/after/plugin/nvim-bqf.lua index 766a01e..e69de29 100644 --- a/files/.config/nvim/after/plugin/nvim-bqf.lua +++ b/files/.config/nvim/after/plugin/nvim-bqf.lua @@ -1,49 +0,0 @@ --------------------------------------------------------------------------------- --- prettify QF window pannel --------------------------------------------------------------------------------- - -function _G.qftf(info) - local items - local ret = {} - if info.quickfix == 1 then - items = vim.fn.getqflist({ id = info.id, items = 0 }).items - else - items = vim.fn.getloclist(info.winid, { id = info.id, items = 0 }).items - end - local limit = 31 - local fname_fmt1, fname_fmt2 = - '%-' .. limit .. 's', '…%.' .. (limit - 1) .. 's' - local valid_fmt = '%s │%5d:%-3d│%s %s' - for i = info.start_idx, info.end_idx do - local e = items[i] - local fname = '' - local str - if e.valid == 1 then - if e.bufnr > 0 then - fname = vim.fn.bufname(e.bufnr) - if fname == '' then - fname = '[No Name]' - else - fname = fname:gsub('^' .. vim.env.HOME, '~') - end - -- char in fname may occur more than 1 width, ignore this issue in - -- order to keep performance - if #fname <= limit then - fname = fname_fmt1:format(fname) - else - fname = fname_fmt2:format(fname:sub(1 - limit)) - end - end - local lnum = e.lnum > 99999 and -1 or e.lnum - local col = e.col > 999 and -1 or e.col - local qtype = e.type == '' and '' or ' ' .. e.type:sub(1, 1):upper() - str = valid_fmt:format(fname, lnum, col, qtype, e.text) - else - str = e.text - end - table.insert(ret, str) - end - return ret -end - -vim.o.qftf = '{info -> v:lua._G.qftf(info)}' diff --git a/files/.config/nvim/lazy-lock.json b/files/.config/nvim/lazy-lock.json deleted file mode 100644 index be76751..0000000 --- a/files/.config/nvim/lazy-lock.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, - "blink-cmp-avante": { "branch": "master", "commit": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5" }, - "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, - "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "ccc.nvim": { "branch": "main", "commit": "9d1a256e006decc574789dfc7d628ca11644d4c2" }, - "codecompanion.nvim": { "branch": "main", "commit": "9827dbdde55217e7b4185e744eae15f74e9c5e8b" }, - "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, - "copilot.lua": { "branch": "master", "commit": "0552b44fceedf0c4cba2cd4953d3976633b2509a" }, - "crates.nvim": { "branch": "main", "commit": "ac9fa498a9edb96dc3056724ff69d5f40b898453" }, - "csvview.nvim": { "branch": "main", "commit": "7022e18a0fbae9aecf99a3ba02b2a541edc2b8a1" }, - "debugprint.nvim": { "branch": "main", "commit": "4f29196c5fe32752bb7a3e8bc83d4a4d2f3b7922" }, - "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, - "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, - "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, - "file-line": { "branch": "main", "commit": "559088afaf10124ea663ee0f4f73b1de48fb1632" }, - "fold-cycle.nvim": { "branch": "main", "commit": "6144567b3307bbcfed0e5b2dd23acb9576575d9e" }, - "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "fzf-lua": { "branch": "main", "commit": "8a79ee54d6216d10b2f153921a12b152be0c1a20" }, - "git-conflict.nvim": { "branch": "main", "commit": "a1badcd070d176172940eb55d9d59029dad1c5a6" }, - "git-worktree.nvim": { "branch": "master", "commit": "f247308e68dab9f1133759b05d944569ad054546" }, - "gitgraph.nvim": { "branch": "main", "commit": "c16daa7d7dd597caf9085644c009cfa80b75db8e" }, - "gitlinker.nvim": { "branch": "master", "commit": "cc59f732f3d043b626c8702cb725c82e54d35c25" }, - "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, - "glance.nvim": { "branch": "master", "commit": "bf86d8b79dce808e65fdb6e9269d0b4ed6d2eefc" }, - "grapple.nvim": { "branch": "main", "commit": "b41ddfc1c39f87f3d1799b99c2f0f1daa524c5f7" }, - "image.nvim": { "branch": "master", "commit": "da2be65c153ba15a14a342b05591652a6df70d58" }, - "inc-rename.nvim": { "branch": "main", "commit": "0074b551a17338ccdcd299bd86687cc651bcb33d" }, - "incline.nvim": { "branch": "main", "commit": "8b54c59bcb23366645ae10edca6edfb9d3a0853e" }, - "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, - "key-analyzer.nvim": { "branch": "main", "commit": "4e4bef34498e821bcbd5203f44db8b67e4f10e04" }, - "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, - "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, - "lspkind.nvim": { "branch": "master", "commit": "c7274c48137396526b59d86232eabcdc7fed8a32" }, - "markdown-table-mode.nvim": { "branch": "main", "commit": "bb1ea9b76c1b29e15e14806fdfbb2319df5c06f1" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "a979821a975897b88493843301950c456a725982" }, - "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, - "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, - "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, - "mcphub.nvim": { "branch": "main", "commit": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f" }, - "mini.ai": { "branch": "main", "commit": "4b0a6207341d895b6cfe9bcb1e4d3e8607bfe4f4" }, - "mini.align": { "branch": "main", "commit": "4d45e0e4f1fd8baefb6ae52a44659704fe7ebe8b" }, - "mini.animate": { "branch": "main", "commit": "0365de8b69331c25d0d0d7573407a7dc7719e578" }, - "mini.bufremove": { "branch": "main", "commit": "10857aa39160c127694151828914df3131ba83b6" }, - "mini.diff": { "branch": "main", "commit": "ff3cd5e76e812fa18bde0f8126d6f3bb62008c79" }, - "mini.hipatterns": { "branch": "main", "commit": "2c5dce6dc7443de814d16f7470549811ee86e664" }, - "mini.icons": { "branch": "main", "commit": "5b9076dae1bfbe47ba4a14bc8b967cde0ab5d77e" }, - "mini.indentscope": { "branch": "main", "commit": "0308f949f31769e509696af5d5f91cebb2159c69" }, - "mini.misc": { "branch": "main", "commit": "de8947231c29012271722651aa07f6749c41d1ed" }, - "mini.move": { "branch": "main", "commit": "b8ba0b77e91b5f0fe8e014e03f7f59799dec1d96" }, - "mini.pairs": { "branch": "main", "commit": "b7fde3719340946feb75017ef9d75edebdeb0566" }, - "mini.splitjoin": { "branch": "main", "commit": "8112e794cbb022b9d4b7af60b64e9896930f1697" }, - "mini.starter": { "branch": "main", "commit": "cdf909e5bda577e09c61fa6d9a36bb2a88dbc636" }, - "mini.surround": { "branch": "main", "commit": "d205d1741d1fcc1f3117b4e839bf00f74ad72fa2" }, - "mini.trailspace": { "branch": "main", "commit": "27acb69562a4742256ab3e4b0127391fcb49dbb3" }, - "neotest": { "branch": "master", "commit": "deadfb1af5ce458742671ad3a013acb9a6b41178" }, - "neotest-plenary": { "branch": "master", "commit": "3523adcf9ffaad1911960c5813b0136c1b63a2ec" }, - "neotest-python": { "branch": "master", "commit": "b0d3a861bd85689d8ed73f0590c47963a7eb1bf9" }, - "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, - "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "numb.nvim": { "branch": "master", "commit": "12ef3913dea8727d4632c6f2ed47957a993de627" }, - "nvim-dap": { "branch": "master", "commit": "a9d8cb68ee7184111dc66156c4a2ebabfbe01bc5" }, - "nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" }, - "nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" }, - "nvim-dev-container": { "branch": "main", "commit": "87ea57f420b3460d0c45e239057ffc38fa32f886" }, - "nvim-lightbulb": { "branch": "master", "commit": "aa3a8b0f4305b25cfe368f6c9be9923a7c9d0805" }, - "nvim-lint": { "branch": "master", "commit": "606b823a57b027502a9ae00978ebf4f5d5158098" }, - "nvim-lspconfig": { "branch": "master", "commit": "841c6d4139aedb8a3f2baf30cef5327371385b93" }, - "nvim-lspimport": { "branch": "main", "commit": "9c1c61a5020faeb1863bb66eb4b2a9107e641876" }, - "nvim-navic": { "branch": "master", "commit": "f5eba192f39b453675d115351808bd51276d9de5" }, - "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, - "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-treesitter-context": { "branch": "master", "commit": "9a8e39993e3b895601bf8227124a48ea8268149e" }, - "nvim-treesitter-textobjects": { "branch": "main", "commit": "7359dfcefa38db632541e1f9b5b5f291626a1d47" }, - "nvim-ts-autotag": { "branch": "main", "commit": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595" }, - "nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" }, - "obsidian.nvim": { "branch": "main", "commit": "14e0427bef6c55da0d63f9a313fd9941be3a2479" }, - "oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" }, - "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, - "rainbow-delimiters.nvim": { "branch": "master", "commit": "607a438d8c647a355749973fd295e33505afafde" }, - "render-markdown.nvim": { "branch": "main", "commit": "e3c18ddd27a853f85a6f513a864cf4f2982b9f26" }, - "sidekick.nvim": { "branch": "main", "commit": "8ad0ede3ff9065878a853e4b037ba6ac88231fb0" }, - "sonarqube.nvim": { "branch": "master", "commit": "811bf8f46e0aa5ed9c9b5783aaf6f87640df553a" }, - "symbol-usage.nvim": { "branch": "main", "commit": "e07c07dfe7504295a369281e95a24e1afa14b243" }, - "symbols-outline.nvim": { "branch": "master", "commit": "564ee65dfc9024bdde73a6621820866987cbb256" }, - "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" }, - "tiny-inline-diagnostic.nvim": { "branch": "main", "commit": "ba133b3e932416e4b9507095731a6d7276878fe8" }, - "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, - "toggleterm.nvim": { "branch": "main", "commit": "9a88eae817ef395952e08650b3283726786fb5fb" }, - "treesj": { "branch": "main", "commit": "26bc2a8432ba3ea79ed6aa346fba780a3d372570" }, - "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, - "undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" }, - "vim-apathy": { "branch": "master", "commit": "27128a0f55189724c841843ba41cd33cf7186032" }, - "vim-dadbod": { "branch": "master", "commit": "6d1d41da4873a445c5605f2005ad2c68c99d8770" }, - "vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" }, - "vim-dadbod-ui": { "branch": "master", "commit": "07e92e22114cc5b1ba4938d99897d85b58e20475" }, - "vim-dirdiff": { "branch": "master", "commit": "84bc8999fde4b3c2d8b228b560278ab30c7ea4c9" }, - "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, - "vim-kitty": { "branch": "main", "commit": "cd72f2d9cfee8d6aba5a180a5ac3ca265b5d3a46" }, - "vim-ledger": { "branch": "master", "commit": "4f2d93dd914f625e2d3db47d97bd9f428fedd68f" }, - "vim-log-highlighting": { "branch": "master", "commit": "1037e26f3120e6a6a2c0c33b14a84336dee2a78f" }, - "vim-markdown": { "branch": "master", "commit": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397" }, - "vim-repeat": { "branch": "master", "commit": "65846025c15494983dafe5e3b46c8f88ab2e9635" }, - "vim-rzip": { "branch": "master", "commit": "f65400fed27b27c7cff7ef8d428c4e5ff749bf28" }, - "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, - "vim-snakemake": { "branch": "master", "commit": "d0015a0f86150c59fb55f65b41529e6ff4469e18" }, - "vim-surround": { "branch": "master", "commit": "3d188ed2113431cf8dac77be61b842acb64433d9" }, - "vimtex": { "branch": "master", "commit": "82d2305ff71dfb3bd91602534cc9bb9a195bcb38" }, - "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } -} diff --git a/files/.config/nvim/lua/dracula-pro/colors.lua b/files/.config/nvim/lua/dracula-pro/colors.lua deleted file mode 100644 index a172942..0000000 --- a/files/.config/nvim/lua/dracula-pro/colors.lua +++ /dev/null @@ -1,104 +0,0 @@ --- Color palette for Dracula Pro - -local M = {} - -M.default = { - none = 'NONE', - - -- Base colors - bg = '#22212C', - bg_dark = '#010010', - bg_darker = '#010010', - bg_light = '#43414E', - bg_highlight = '#43414E', - bg_visual = '#454158', - bg_search = '#43414E', - bg_sidebar = '#010010', - bg_statusline = '#010010', - bg_float = '#43414E', - bg_popup = '#43414E', - - fg = '#F8F8F2', - fg_dark = '#CDCDC8', - fg_gutter = '#504C67', - fg_sidebar = '#F8F8F2', - fg_float = '#F8F8F2', - - -- Accent colors - black = '#010010', - border = '#504C67', - border_highlight = '#9580FF', - comment = '#7970A9', - - -- Syntax colors - red = '#FF9580', - orange = '#FFFF80', - yellow = '#FFFF80', - green = '#8AFF80', - cyan = '#80FFEA', - blue = '#9580FF', - blue0 = '#9580FF', - blue1 = '#9580FF', - blue2 = '#80FFEA', - blue5 = '#FF80BF', - blue6 = '#99FFEE', - blue7 = '#9580FF', - magenta = '#FF80BF', - magenta2 = '#FF99CC', - purple = '#FF80BF', - teal = '#80FFEA', - dark3 = '#CDCDC8', - dark5 = '#CDCDC8', - green1 = '#8AFF80', - green2 = '#8AFF80', - red1 = '#FF9580', - - -- Bright variants - bright_red = '#FFAA99', - bright_green = '#A2FF99', - bright_yellow = '#FFFF99', - bright_blue = '#AA99FF', - bright_magenta = '#FF99CC', - bright_cyan = '#99FFEE', - - -- Terminal colors - terminal_black = '#22212C', - - -- Semantic syntax colors (for accurate theme reproduction) - syntax_string = '#FFFF80', - syntax_function = '#8AFF80', - syntax_variable = '#F8F8F2', - syntax_keyword = '#FF80BF', - syntax_class = '#9580FF', - syntax_constant = '#80FFEA', - - -- Diagnostic colors - error = '#FF9580', - warning = '#FFFF80', - info = '#80FFEA', - hint = '#504C67', - todo = '#9580FF', - - -- Git colors - git = { - add = '#8AFF80', - change = '#FFFF80', - delete = '#FF9580', - ignore = '#504C67', - }, - - -- Diff colors - diff = { - add = '#5DD458', - delete = '#D16D5B', - change = '#D3D457', - text = '#FFFF80', - }, -} - -function M.setup(opts) - opts = opts or {} - return M.default -end - -return M diff --git a/files/.config/nvim/lua/dracula-pro/config.lua b/files/.config/nvim/lua/dracula-pro/config.lua deleted file mode 100644 index 3630fa5..0000000 --- a/files/.config/nvim/lua/dracula-pro/config.lua +++ /dev/null @@ -1,25 +0,0 @@ --- Configuration for Dracula Pro - -local M = {} - -M.defaults = { - transparent = false, - terminal_colors = true, - styles = { - comments = { italic = true }, - keywords = { italic = false }, - functions = {}, - variables = {}, - }, - dim_inactive = false, -} - -M.options = {} - -function M.setup(options) - M.options = vim.tbl_deep_extend('force', {}, M.defaults, options or {}) -end - -M.setup() - -return M diff --git a/files/.config/nvim/lua/dracula-pro/groups/base.lua b/files/.config/nvim/lua/dracula-pro/groups/base.lua deleted file mode 100644 index abb5764..0000000 --- a/files/.config/nvim/lua/dracula-pro/groups/base.lua +++ /dev/null @@ -1,126 +0,0 @@ --- Base Vim highlight groups for Dracula Pro - -local M = {} - -function M.get(c, opts) - return { - Comment = { fg = c.comment, style = opts.styles.comments }, - ColorColumn = { bg = c.black }, - Conceal = { fg = c.fg_dark }, - Cursor = { fg = c.bg, bg = c.fg }, - lCursor = { fg = c.bg, bg = c.fg }, - CursorIM = { fg = c.bg, bg = c.fg }, - CursorColumn = { bg = c.bg_highlight }, - CursorLine = { bg = c.bg_highlight }, - Directory = { fg = c.blue }, - DiffAdd = { bg = c.diff.add }, - DiffChange = { bg = c.diff.change }, - DiffDelete = { bg = c.diff.delete }, - DiffText = { bg = c.diff.text }, - EndOfBuffer = { fg = c.bg }, - ErrorMsg = { fg = c.error }, - VertSplit = { fg = c.border }, - WinSeparator = { fg = c.border, bold = true }, - Folded = { fg = c.blue, bg = c.fg_gutter }, - FoldColumn = { bg = opts.transparent and c.none or c.bg, fg = c.comment }, - SignColumn = { bg = opts.transparent and c.none or c.bg, fg = c.fg_gutter }, - SignColumnSB = { bg = c.bg_sidebar, fg = c.fg_gutter }, - Substitute = { bg = c.red, fg = c.black }, - LineNr = { fg = c.fg_gutter }, - CursorLineNr = { fg = c.orange, bold = true }, - LineNrAbove = { fg = c.fg_gutter }, - LineNrBelow = { fg = c.fg_gutter }, - MatchParen = { fg = c.orange, bold = true }, - ModeMsg = { fg = c.fg_dark, bold = true }, - MsgArea = { fg = c.fg_dark }, - MoreMsg = { fg = c.blue }, - NonText = { fg = c.fg_dark }, - Normal = { fg = c.fg, bg = opts.transparent and c.none or c.bg }, - NormalNC = { - fg = c.fg, - bg = opts.transparent and c.none - or opts.dim_inactive and c.bg_dark - or c.bg, - }, - NormalSB = { fg = c.fg_sidebar, bg = c.bg_sidebar }, - NormalFloat = { fg = c.fg_float, bg = c.bg_float }, - FloatBorder = { fg = c.border_highlight, bg = c.bg_float }, - FloatTitle = { fg = c.border_highlight, bg = c.bg_float }, - Pmenu = { bg = c.bg_popup, fg = c.fg }, - PmenuSel = { bg = c.bg_visual }, - PmenuSbar = { bg = c.bg_popup }, - PmenuThumb = { bg = c.fg_gutter }, - Question = { fg = c.blue }, - QuickFixLine = { bg = c.bg_visual, bold = true }, - Search = { bg = c.bg_search, fg = c.fg }, - IncSearch = { bg = c.orange, fg = c.black }, - CurSearch = 'IncSearch', - SpecialKey = { fg = c.fg_dark }, - SpellBad = { sp = c.error, undercurl = true }, - SpellCap = { sp = c.warning, undercurl = true }, - SpellLocal = { sp = c.info, undercurl = true }, - SpellRare = { sp = c.hint, undercurl = true }, - StatusLine = { fg = c.fg_sidebar, bg = c.bg_statusline }, - StatusLineNC = { fg = c.fg_gutter, bg = c.bg_statusline }, - TabLine = { bg = c.bg_statusline, fg = c.fg_gutter }, - TabLineFill = { bg = opts.transparent and c.none or c.black }, - TabLineSel = { fg = c.black, bg = c.blue }, - Title = { fg = c.blue, bold = true }, - Visual = { bg = c.bg_visual }, - VisualNOS = { bg = c.bg_visual }, - WarningMsg = { fg = c.warning }, - Whitespace = { fg = c.fg_gutter }, - WildMenu = { bg = c.bg_visual }, - WinBar = 'StatusLine', - WinBarNC = 'StatusLineNC', - - Bold = { bold = true, fg = c.fg }, - Character = { fg = c.syntax_string }, - Constant = { fg = c.syntax_constant }, - Debug = { fg = c.orange }, - Delimiter = 'Special', - Error = { fg = c.error }, - Function = { fg = c.syntax_function, style = opts.styles.functions }, - Identifier = { fg = c.syntax_variable, style = opts.styles.variables }, - Italic = { italic = true, fg = c.fg }, - Keyword = { fg = c.syntax_keyword, style = opts.styles.keywords }, - Operator = { fg = c.blue5 }, - PreProc = { fg = c.cyan }, - Special = { fg = c.blue1 }, - Statement = { fg = c.magenta }, - String = { fg = c.syntax_string }, - Todo = { bg = c.yellow, fg = c.bg }, - Type = { fg = c.syntax_class }, - Underlined = { underline = true }, - - DiagnosticError = { fg = c.error }, - DiagnosticWarn = { fg = c.warning }, - DiagnosticInfo = { fg = c.info }, - DiagnosticHint = { fg = c.hint }, - DiagnosticUnnecessary = { fg = c.comment }, - DiagnosticVirtualTextError = { fg = c.error, bg = c.none }, - DiagnosticVirtualTextWarn = { fg = c.warning, bg = c.none }, - DiagnosticVirtualTextInfo = { fg = c.info, bg = c.none }, - DiagnosticVirtualTextHint = { fg = c.hint, bg = c.none }, - DiagnosticUnderlineError = { undercurl = true, sp = c.error }, - DiagnosticUnderlineWarn = { undercurl = true, sp = c.warning }, - DiagnosticUnderlineInfo = { undercurl = true, sp = c.info }, - DiagnosticUnderlineHint = { undercurl = true, sp = c.hint }, - - LspReferenceText = { bg = c.bg_highlight }, - LspReferenceRead = { bg = c.bg_highlight }, - LspReferenceWrite = { bg = c.bg_highlight }, - LspSignatureActiveParameter = { bg = c.bg_visual, bold = true }, - LspCodeLens = { fg = c.comment }, - LspInlayHint = { fg = c.comment, bg = c.none }, - - GitGutterAdd = { fg = c.git.add }, - GitGutterChange = { fg = c.git.change }, - GitGutterDelete = { fg = c.git.delete }, - GitSignsAdd = { fg = c.git.add }, - GitSignsChange = { fg = c.git.change }, - GitSignsDelete = { fg = c.git.delete }, - } -end - -return M diff --git a/files/.config/nvim/lua/dracula-pro/groups/plugins.lua b/files/.config/nvim/lua/dracula-pro/groups/plugins.lua deleted file mode 100644 index 72f7cca..0000000 --- a/files/.config/nvim/lua/dracula-pro/groups/plugins.lua +++ /dev/null @@ -1,531 +0,0 @@ --- Plugin-specific highlight groups for Dracula Pro - -local M = {} - --- Helper function to tint colors (darken/brighten) -local function tint(color, percent) - if not color or color == 'NONE' then return 'NONE' end - local r = tonumber(color:sub(2, 3), 16) - local g = tonumber(color:sub(4, 5), 16) - local b = tonumber(color:sub(6), 16) - if not r or not g or not b then return 'NONE' end - - local blend = function(component) - component = math.floor(component * (1 + percent)) - return math.min(math.max(component, 0), 255) - end - - return string.format('#%02x%02x%02x', blend(r), blend(g), blend(b)) -end - -function M.get(c, opts) - -- Custom derived colors for plugins - local custom = { - error_bg = tint(c.error, -0.8), - warn_bg = tint(c.orange, -0.8), - info_bg = tint(c.blue, -0.7), - hint_bg = tint(c.purple, -0.7), - purple1 = tint(c.purple, -0.2), - gray = c.comment, - gold = c.yellow, - blue_bg = tint(c.blue, -0.8), - diff_change_bg = tint(c.blue, -0.85), - diff_text_bg = tint(c.blue, -0.75), - } - - -- LSP Kind highlights (for completion items, breadcrumbs, etc.) - local lsp_kinds = { - ['module'] = { fg = c.orange }, - ['snippet'] = { fg = c.purple }, - ['folder'] = { fg = c.fg }, - ['color'] = { fg = c.fg }, - ['file'] = 'Directory', - ['text'] = '@string', - ['method'] = '@method', - ['function'] = '@function', - ['constructor'] = '@constructor', - ['field'] = '@field', - ['variable'] = '@variable', - ['property'] = '@property', - ['unit'] = '@constant', - ['value'] = '@variable', - ['enum'] = '@type', - ['keyword'] = '@keyword', - ['reference'] = '@parameter.reference', - ['constant'] = '@constant', - ['struct'] = '@structure', - ['event'] = '@variable', - ['operator'] = '@operator', - ['namespace'] = '@namespace', - ['package'] = '@include', - ['string'] = '@string', - ['number'] = '@number', - ['boolean'] = '@boolean', - ['array'] = '@repeat', - ['object'] = '@type', - ['key'] = '@field', - ['null'] = '@symbol', - ['enumMember'] = '@field', - ['class'] = '@lsp.type.class', - ['interface'] = '@lsp.type.interface', - ['typeParameter'] = '@lsp.type.parameter', - } - - return { - -- WhichKey - WhichKey = { fg = c.purple }, - WhichKeySeperator = { fg = c.blue }, - WhichKeyGroup = { fg = c.cyan }, - WhichKeyDesc = { fg = c.fg }, - WhichKeyFloat = { bg = c.bg_float }, - - -- GitSigns - SignAdd = { fg = c.git.add }, - SignChange = { fg = c.git.change }, - SignDelete = { fg = c.git.delete }, - GitSignsAdd = { fg = c.git.add }, - GitSignsChange = { fg = c.git.change }, - GitSignsDelete = { fg = c.git.delete }, - GitSignsUntracked = { fg = c.git.ignore }, - GitSignsAddInline = 'DiffText', - GitSignsChangeInline = 'DiffChange', - GitSignsDeleteInline = 'DiffDelete', - - -- Telescope - TelescopeSelection = { bg = custom.blue_bg }, - TelescopeSelectionCaret = { fg = c.cyan, bg = custom.blue_bg }, - TelescopeMatching = { fg = c.orange, bold = true, italic = true }, - TelescopeBorder = { fg = c.border }, - TelescopeNormal = { fg = c.fg, bg = c.bg }, - TelescopePromptTitle = { fg = c.orange }, - TelescopePromptPrefix = { fg = c.blue }, - TelescopeResultsTitle = { fg = c.orange }, - TelescopePreviewTitle = { fg = c.orange }, - TelescopePromptCounter = { fg = c.cyan }, - TelescopePreviewHyphen = { fg = c.cyan }, - - -- NvimTree - NvimTreeFolderIcon = { fg = custom.gold }, - NvimTreeIndentMarker = { fg = custom.gray }, - NvimTreeNormal = { fg = c.fg_sidebar, bg = c.bg_sidebar }, - NvimTreeVertSplit = { fg = c.bg_sidebar, bg = c.bg_sidebar }, - NvimTreeFolderName = { fg = c.fg_sidebar }, - NvimTreeOpenedFolderName = { fg = c.fg_sidebar, bold = true, italic = true }, - NvimTreeEmptyFolderName = { fg = c.comment, italic = true }, - NvimTreeGitIgnored = { fg = c.comment, italic = true }, - NvimTreeImageFile = { fg = c.fg }, - NvimTreeSpecialFile = { fg = c.orange }, - NvimTreeEndOfBuffer = { fg = c.comment }, - NvimTreeCursorLine = { bg = c.bg_highlight }, - NvimTreeGitStaged = { fg = c.git.add }, - NvimTreeGitNew = { fg = c.git.ignore }, - NvimTreeGitRenamed = { fg = c.git.change }, - NvimTreeGitDeleted = { fg = c.git.delete }, - NvimTreeGitMerge = { fg = c.git.change }, - NvimTreeGitDirty = { fg = c.git.ignore }, - NvimTreeSymlink = { fg = c.blue }, - NvimTreeRootFolder = { fg = c.fg, bold = true }, - NvimTreeExecFile = { fg = c.green }, - NvimTreeLspDiagnosticsError = 'DiagnosticError', - NvimTreeLspDiagnosticsWarning = 'DiagnosticWarn', - NvimTreeLspDiagnosticsInformation = 'DiagnosticInfo', - NvimTreeLspDiagnosticsInfo = 'DiagnosticInfo', - NvimTreeLspDiagnosticsHint = 'DiagnosticHint', - - -- Neo-tree - NeoTreeFolderIcon = { fg = custom.gold }, - NeoTreeIndentMarker = { fg = custom.gray }, - NeoTreeNormal = { fg = c.fg_sidebar, bg = c.bg_sidebar }, - NeoTreeFileName = { fg = c.fg_sidebar }, - NeoTreeFileNameOpened = { fg = c.fg, bold = true, italic = true }, - NeoTreeDirectoryName = { fg = c.fg_sidebar }, - NeoTreeDirectoryIcon = { fg = custom.gold }, - NeoTreeVertSplit = { fg = c.bg_sidebar, bg = c.bg_sidebar }, - NeoTreeWinSeparator = { fg = c.bg_sidebar, bg = c.bg_sidebar }, - NeoTreeOpenedFolderName = { fg = c.fg, bold = true, italic = true }, - NeoTreeEmptyFolderName = { fg = c.comment, italic = true }, - NeoTreeGitIgnored = { fg = c.comment, italic = true }, - NeoTreeDotfile = { fg = c.comment, italic = true }, - NeoTreeHiddenByName = { fg = c.comment, italic = true }, - NeoTreeEndOfBuffer = { fg = c.comment }, - NeoTreeCursorLine = { bg = c.bg_highlight }, - NeoTreeGitStaged = { fg = c.git.add }, - NeoTreeGitUntracked = { fg = c.git.ignore }, - NeoTreeGitDeleted = { fg = c.git.delete }, - NeoTreeGitModified = { fg = c.git.change }, - NeoTreeSymbolicLinkTarget = { fg = c.blue }, - NeoTreeRootName = { fg = c.fg, bold = true }, - NeoTreeTitleBar = { fg = c.bg, bg = c.fg, bold = true }, - - -- Barbar (buffer tabs) - BufferCurrent = { fg = c.fg, bg = c.bg }, - BufferCurrentIndex = { fg = c.fg, bg = c.bg }, - BufferCurrentMod = { fg = c.warning, bg = c.bg }, - BufferCurrentSign = { fg = c.blue, bg = c.bg }, - BufferCurrentTarget = { fg = c.cyan, bg = c.bg, bold = true }, - BufferVisible = { fg = c.fg, bg = c.bg }, - BufferVisibleIndex = { fg = c.fg, bg = c.bg }, - BufferVisibleMod = { fg = c.warning, bg = c.bg }, - BufferVisibleSign = { fg = custom.gray, bg = c.bg }, - BufferVisibleTarget = { fg = c.cyan, bg = c.bg, bold = true }, - BufferInactive = { fg = custom.gray, bg = c.bg_dark }, - BufferInactiveIndex = { fg = custom.gray, bg = c.bg_dark }, - BufferInactiveMod = { fg = c.warning, bg = c.bg_dark }, - BufferInactiveSign = { fg = custom.gray, bg = c.bg_dark }, - BufferInactiveTarget = { fg = c.cyan, bg = c.bg_dark, bold = true }, - - -- Indent Blankline - IndentBlanklineContextChar = { fg = c.fg_gutter }, - IndentBlanklineContextStart = { sp = c.fg_gutter, underline = true }, - IndentBlanklineChar = { fg = c.bg_highlight }, - IblIndent = { fg = c.bg_highlight }, - IblScope = { fg = c.fg_gutter }, - - -- nvim-cmp (completion menu) - CmpItemAbbrMatch = { fg = c.blue, bold = true }, - CmpItemAbbrMatchFuzzy = { fg = c.blue, italic = true }, - CmpItemAbbrDeprecated = { fg = custom.gray, strikethrough = true }, - CmpItemKindVariable = lsp_kinds['variable'], - CmpItemKindModule = lsp_kinds['module'], - CmpItemKindSnippet = lsp_kinds['snippet'], - CmpItemKindFolder = lsp_kinds['folder'], - CmpItemKindColor = lsp_kinds['color'], - CmpItemKindFile = lsp_kinds['file'], - CmpItemKindText = lsp_kinds['text'], - CmpItemKindMethod = lsp_kinds['method'], - CmpItemKindFunction = lsp_kinds['function'], - CmpItemKindConstructor = lsp_kinds['constructor'], - CmpItemKindField = lsp_kinds['field'], - CmpItemKindProperty = lsp_kinds['property'], - CmpItemKindUnit = lsp_kinds['unit'], - CmpItemKindValue = lsp_kinds['value'], - CmpItemKindEnum = lsp_kinds['enum'], - CmpItemKindKeyword = lsp_kinds['keyword'], - CmpItemKindReference = lsp_kinds['reference'], - CmpItemKindConstant = lsp_kinds['constant'], - CmpItemKindStruct = lsp_kinds['struct'], - CmpItemKindEvent = lsp_kinds['event'], - CmpItemKindOperator = lsp_kinds['operator'], - CmpItemKindNamespace = lsp_kinds['namespace'], - CmpItemKindPackage = lsp_kinds['package'], - CmpItemKindString = lsp_kinds['string'], - CmpItemKindNumber = lsp_kinds['number'], - CmpItemKindBoolean = lsp_kinds['boolean'], - CmpItemKindArray = lsp_kinds['array'], - CmpItemKindObject = lsp_kinds['object'], - CmpItemKindKey = lsp_kinds['key'], - CmpItemKindNull = lsp_kinds['null'], - CmpItemKindEnumMember = lsp_kinds['enumMember'], - CmpItemKindClass = lsp_kinds['class'], - CmpItemKindInterface = lsp_kinds['interface'], - CmpItemKindTypeParameter = lsp_kinds['typeParameter'], - - -- Navic (breadcrumbs) - NavicIconsFile = lsp_kinds['file'], - NavicIconsModule = lsp_kinds['module'], - NavicIconsNamespace = lsp_kinds['namespace'], - NavicIconsPackage = lsp_kinds['package'], - NavicIconsClass = lsp_kinds['class'], - NavicIconsMethod = lsp_kinds['method'], - NavicIconsProperty = lsp_kinds['property'], - NavicIconsField = lsp_kinds['field'], - NavicIconsConstructor = lsp_kinds['constructor'], - NavicIconsEnum = lsp_kinds['enum'], - NavicIconsInterface = lsp_kinds['interface'], - NavicIconsFunction = lsp_kinds['function'], - NavicIconsVariable = lsp_kinds['variable'], - NavicIconsConstant = lsp_kinds['constant'], - NavicIconsString = lsp_kinds['string'], - NavicIconsNumber = lsp_kinds['number'], - NavicIconsBoolean = lsp_kinds['boolean'], - NavicIconsArray = lsp_kinds['array'], - NavicIconsObject = lsp_kinds['object'], - NavicIconsKey = lsp_kinds['key'], - NavicIconsKeyword = lsp_kinds['keyword'], - NavicIconsNull = lsp_kinds['null'], - NavicIconsEnumMember = lsp_kinds['enumMember'], - NavicIconsStruct = lsp_kinds['struct'], - NavicIconsEvent = lsp_kinds['event'], - NavicIconsOperator = lsp_kinds['operator'], - NavicIconsTypeParameter = lsp_kinds['typeParameter'], - NavicText = { fg = c.fg }, - NavicSeparator = { fg = c.fg }, - - -- Packer - packerString = { fg = custom.gold }, - packerHash = { fg = c.blue }, - packerOutput = { fg = custom.purple1 }, - packerRelDate = { fg = custom.gray }, - packerSuccess = { fg = c.green }, - packerStatusSuccess = { fg = c.blue }, - - -- Symbols Outline - SymbolsOutlineConnector = { fg = custom.gray }, - FocusedSymbol = { bg = c.bg_highlight }, - - -- nvim-notify - NotifyERRORBorder = { fg = tint(c.error, -0.6) }, - NotifyWARNBorder = { fg = tint(c.warning, -0.4) }, - NotifyINFOBorder = { fg = tint(c.info, -0.4) }, - NotifyDEBUGBorder = { fg = tint(c.hint, -0.4) }, - NotifyTRACEBorder = { fg = c.border }, - NotifyERRORIcon = { fg = c.error }, - NotifyWARNIcon = { fg = c.warning }, - NotifyINFOIcon = { fg = c.info }, - NotifyDEBUGIcon = { fg = c.hint }, - NotifyTRACEIcon = { fg = c.border }, - NotifyERRORTitle = { fg = c.error }, - NotifyWARNTitle = { fg = c.warning }, - NotifyINFOTitle = { fg = c.info }, - NotifyDEBUGTitle = { fg = c.hint }, - NotifyTRACETitle = { fg = c.border }, - - -- Rainbow Delimiters - RainbowDelimiterRed = { fg = c.red }, - RainbowDelimiterYellow = { fg = c.yellow }, - RainbowDelimiterBlue = { fg = c.blue }, - RainbowDelimiterOrange = { fg = c.orange }, - RainbowDelimiterGreen = { fg = c.green }, - RainbowDelimiterViolet = { fg = c.purple }, - RainbowDelimiterCyan = { fg = c.cyan }, - - -- TS Rainbow (legacy) - TSRainbowRed = { fg = c.red }, - TSRainbowYellow = { fg = c.yellow }, - TSRainbowBlue = { fg = c.blue }, - TSRainbowOrange = { fg = c.orange }, - TSRainbowGreen = { fg = c.green }, - TSRainbowViolet = { fg = c.purple }, - TSRainbowCyan = { fg = c.cyan }, - - -- Hop - HopNextKey = { fg = c.cyan, bold = true }, - HopNextKey1 = { fg = c.magenta, bold = true }, - HopNextKey2 = { fg = c.purple }, - HopPreview = { fg = c.yellow }, - HopUnmatched = { fg = custom.gray }, - - -- Flash - FlashLabel = { fg = c.cyan, bold = true, italic = true }, - FlashCurrent = { fg = c.magenta, underline = true }, - FlashMatch = { fg = c.purple }, - FlashBackdrop = { fg = custom.gray }, - - -- Crates.nvim (Rust crate versions) - CratesNvimLoading = { fg = c.blue }, - CratesNvimVersion = { fg = c.blue }, - - -- Lazy.nvim - LazyH1 = { bg = c.blue, fg = c.bg, bold = true }, - LazyButton = { bg = c.bg_highlight, fg = c.fg }, - LazyButtonActive = { bg = c.bg_visual, fg = c.fg, bold = true }, - LazyComment = { fg = c.comment }, - LazyCommit = { fg = c.green }, - LazyCommitIssue = { fg = c.blue }, - LazyCommitScope = { fg = c.purple }, - LazyCommitType = { fg = c.cyan }, - LazyDimmed = { fg = c.comment }, - LazyDir = { fg = c.blue }, - LazyH2 = { fg = c.cyan, bold = true }, - LazyLocal = { fg = c.magenta }, - LazyNoCond = { fg = c.comment }, - LazyNormal = { fg = c.fg, bg = c.bg_float }, - LazyProgressDone = { fg = c.green, bold = true }, - LazyProgressTodo = { fg = c.fg_gutter }, - LazyProp = { fg = c.orange }, - LazyReasonCmd = { fg = c.yellow }, - LazyReasonEvent = { fg = c.purple }, - LazyReasonFt = { fg = c.blue }, - LazyReasonKeys = { fg = c.cyan }, - LazyReasonPlugin = { fg = c.green }, - LazyReasonRuntime = { fg = c.orange }, - LazyReasonSource = { fg = c.magenta }, - LazyReasonStart = { fg = c.green }, - LazySpecial = { fg = c.blue }, - LazyTaskError = { fg = c.error }, - LazyTaskOutput = { fg = c.fg }, - LazyUrl = { fg = c.blue, underline = true }, - LazyValue = { fg = c.orange }, - - -- Mini.nvim - MiniCompletionActiveParameter = { underline = true }, - MiniCursorword = { bg = c.bg_highlight }, - MiniCursorwordCurrent = { bg = c.bg_highlight }, - MiniIndentscopeSymbol = { fg = c.blue }, - MiniIndentscopePrefix = { nocombine = true }, - MiniJump = { bg = c.magenta, fg = c.bg }, - MiniJump2dSpot = { fg = c.magenta, bold = true, nocombine = true }, - MiniStarterCurrent = { nocombine = true }, - MiniStarterFooter = { fg = c.yellow, italic = true }, - MiniStarterHeader = { fg = c.blue }, - MiniStarterInactive = { fg = c.comment }, - MiniStarterItem = { fg = c.fg, bg = c.bg }, - MiniStarterItemBullet = { fg = c.border }, - MiniStarterItemPrefix = { fg = c.warning }, - MiniStarterSection = { fg = c.cyan }, - MiniStarterQuery = { fg = c.info }, - MiniStatuslineDevinfo = { fg = c.fg_dark, bg = c.bg_highlight }, - MiniStatuslineFileinfo = { fg = c.fg_dark, bg = c.bg_highlight }, - MiniStatuslineFilename = { fg = c.fg_dark, bg = c.bg_dark }, - MiniStatuslineInactive = { fg = c.blue, bg = c.bg_statusline }, - MiniStatuslineModeCommand = { fg = c.black, bg = c.yellow, bold = true }, - MiniStatuslineModeInsert = { fg = c.black, bg = c.green, bold = true }, - MiniStatuslineModeNormal = { fg = c.black, bg = c.blue, bold = true }, - MiniStatuslineModeOther = { fg = c.black, bg = c.cyan, bold = true }, - MiniStatuslineModeReplace = { fg = c.black, bg = c.red, bold = true }, - MiniStatuslineModeVisual = { fg = c.black, bg = c.magenta, bold = true }, - MiniSurround = { bg = c.orange, fg = c.black }, - MiniTablineCurrent = { fg = c.fg, bg = c.bg_highlight }, - MiniTablineFill = { bg = c.black }, - MiniTablineHidden = { fg = c.fg_dark, bg = c.bg_statusline }, - MiniTablineModifiedCurrent = { fg = c.warning, bg = c.bg_highlight }, - MiniTablineModifiedHidden = { fg = c.warning, bg = c.bg_statusline }, - MiniTablineModifiedVisible = { fg = c.warning, bg = c.bg_statusline }, - MiniTablineTabpagesection = { fg = c.bg_statusline, bg = c.fg_gutter }, - MiniTablineVisible = { fg = c.fg, bg = c.bg_statusline }, - MiniTestEmphasis = { bold = true }, - MiniTestFail = { fg = c.red, bold = true }, - MiniTestPass = { fg = c.green, bold = true }, - MiniTrailspace = { bg = c.red }, - - -- Noice - NoiceCompletionItemKindDefault = { fg = c.fg_dark, bg = c.none }, - NoiceCompletionItemKindVariable = lsp_kinds['variable'], - NoiceCompletionItemKindModule = lsp_kinds['module'], - NoiceCompletionItemKindSnippet = lsp_kinds['snippet'], - NoiceCompletionItemKindFolder = lsp_kinds['folder'], - NoiceCompletionItemKindColor = lsp_kinds['color'], - NoiceCompletionItemKindFile = lsp_kinds['file'], - NoiceCompletionItemKindText = lsp_kinds['text'], - NoiceCompletionItemKindMethod = lsp_kinds['method'], - NoiceCompletionItemKindFunction = lsp_kinds['function'], - NoiceCompletionItemKindConstructor = lsp_kinds['constructor'], - NoiceCompletionItemKindField = lsp_kinds['field'], - NoiceCompletionItemKindProperty = lsp_kinds['property'], - NoiceCompletionItemKindUnit = lsp_kinds['unit'], - NoiceCompletionItemKindValue = lsp_kinds['value'], - NoiceCompletionItemKindEnum = lsp_kinds['enum'], - NoiceCompletionItemKindKeyword = lsp_kinds['keyword'], - NoiceCompletionItemKindReference = lsp_kinds['reference'], - NoiceCompletionItemKindConstant = lsp_kinds['constant'], - NoiceCompletionItemKindStruct = lsp_kinds['struct'], - NoiceCompletionItemKindEvent = lsp_kinds['event'], - NoiceCompletionItemKindOperator = lsp_kinds['operator'], - NoiceCompletionItemKindNamespace = lsp_kinds['namespace'], - NoiceCompletionItemKindPackage = lsp_kinds['package'], - NoiceCompletionItemKindString = lsp_kinds['string'], - NoiceCompletionItemKindNumber = lsp_kinds['number'], - NoiceCompletionItemKindBoolean = lsp_kinds['boolean'], - NoiceCompletionItemKindArray = lsp_kinds['array'], - NoiceCompletionItemKindObject = lsp_kinds['object'], - NoiceCompletionItemKindKey = lsp_kinds['key'], - NoiceCompletionItemKindNull = lsp_kinds['null'], - NoiceCompletionItemKindEnumMember = lsp_kinds['enumMember'], - NoiceCompletionItemKindClass = lsp_kinds['class'], - NoiceCompletionItemKindInterface = lsp_kinds['interface'], - NoiceCompletionItemKindTypeParameter = lsp_kinds['typeParameter'], - - -- Trouble - TroubleText = { fg = c.fg_dark }, - TroubleCount = { fg = c.magenta, bg = c.bg_highlight }, - TroubleNormal = { fg = c.fg, bg = c.bg_sidebar }, - - -- Illuminate - IlluminatedWordText = { bg = c.bg_highlight }, - IlluminatedWordRead = { bg = c.bg_highlight }, - IlluminatedWordWrite = { bg = c.bg_highlight }, - - -- diff - diffAdded = { fg = c.git.add }, - diffRemoved = { fg = c.git.delete }, - diffChanged = { fg = c.git.change }, - diffOldFile = { fg = c.yellow }, - diffNewFile = { fg = c.orange }, - diffFile = { fg = c.blue }, - diffLine = { fg = c.comment }, - diffIndexLine = { fg = c.magenta }, - - -- Neogit - NeogitBranch = { fg = c.magenta }, - NeogitRemote = { fg = c.purple }, - NeogitHunkHeader = { bg = c.bg_highlight, fg = c.fg }, - NeogitHunkHeaderHighlight = { bg = c.bg_visual, fg = c.blue }, - NeogitDiffContextHighlight = { bg = c.bg_dark, fg = c.fg_dark }, - NeogitDiffDeleteHighlight = { fg = c.git.delete, bg = c.diff.delete }, - NeogitDiffAddHighlight = { fg = c.git.add, bg = c.diff.add }, - - -- Leap - LeapMatch = { bg = c.magenta, fg = c.bg, bold = true }, - LeapLabelPrimary = { fg = c.cyan, bold = true }, - LeapLabelSecondary = { fg = c.green, bold = true }, - LeapBackdrop = { fg = c.comment }, - - -- Dashboard - DashboardShortCut = { fg = c.cyan }, - DashboardHeader = { fg = c.blue }, - DashboardCenter = { fg = c.magenta }, - DashboardFooter = { fg = c.yellow, italic = true }, - DashboardKey = { fg = c.orange }, - DashboardDesc = { fg = c.cyan }, - DashboardIcon = { fg = c.cyan, bold = true }, - - -- Alpha (dashboard) - AlphaShortcut = { fg = c.orange }, - AlphaHeader = { fg = c.blue }, - AlphaHeaderLabel = { fg = c.cyan }, - AlphaFooter = { fg = c.yellow, italic = true }, - AlphaButtons = { fg = c.cyan }, - - -- Aerial - AerialLine = { bg = c.bg_visual, bold = true }, - AerialGuide = { fg = c.fg_gutter }, - AerialArrayIcon = lsp_kinds['array'], - AerialBooleanIcon = lsp_kinds['boolean'], - AerialClassIcon = lsp_kinds['class'], - AerialConstantIcon = lsp_kinds['constant'], - AerialConstructorIcon = lsp_kinds['constructor'], - AerialEnumIcon = lsp_kinds['enum'], - AerialEnumMemberIcon = lsp_kinds['enumMember'], - AerialEventIcon = lsp_kinds['event'], - AerialFieldIcon = lsp_kinds['field'], - AerialFileIcon = lsp_kinds['file'], - AerialFunctionIcon = lsp_kinds['function'], - AerialInterfaceIcon = lsp_kinds['interface'], - AerialKeyIcon = lsp_kinds['key'], - AerialKeywordIcon = lsp_kinds['keyword'], - AerialMethodIcon = lsp_kinds['method'], - AerialModuleIcon = lsp_kinds['module'], - AerialNamespaceIcon = lsp_kinds['namespace'], - AerialNullIcon = lsp_kinds['null'], - AerialNumberIcon = lsp_kinds['number'], - AerialObjectIcon = lsp_kinds['object'], - AerialOperatorIcon = lsp_kinds['operator'], - AerialPackageIcon = lsp_kinds['package'], - AerialPropertyIcon = lsp_kinds['property'], - AerialStringIcon = lsp_kinds['string'], - AerialStructIcon = lsp_kinds['struct'], - AerialTypeParameterIcon = lsp_kinds['typeParameter'], - AerialVariableIcon = lsp_kinds['variable'], - - -- Neotest - NeotestPassed = { fg = c.green }, - NeotestRunning = { fg = c.yellow }, - NeotestFailed = { fg = c.red }, - NeotestSkipped = { fg = c.blue }, - NeotestTest = { fg = c.fg_sidebar }, - NeotestNamespace = { fg = c.cyan }, - NeotestFocused = { bold = true }, - NeotestFile = { fg = c.cyan }, - NeotestDir = { fg = c.blue }, - NeotestBorder = { fg = c.border }, - NeotestIndent = { fg = c.fg_sidebar }, - NeotestExpandMarker = { fg = c.fg_sidebar }, - NeotestAdapterName = { fg = c.purple, bold = true }, - NeotestWinSelect = { fg = c.blue, bold = true }, - NeotestMarked = { fg = c.orange, bold = true }, - NeotestTarget = { fg = c.blue }, - NeotestUnknown = { fg = c.fg_dark }, - } -end - -return M diff --git a/files/.config/nvim/lua/dracula-pro/groups/treesitter.lua b/files/.config/nvim/lua/dracula-pro/groups/treesitter.lua deleted file mode 100644 index 841dfc1..0000000 --- a/files/.config/nvim/lua/dracula-pro/groups/treesitter.lua +++ /dev/null @@ -1,141 +0,0 @@ --- Treesitter highlight groups for Dracula Pro - -local M = {} - -function M.get(c, opts) - return { - ['@annotation'] = 'PreProc', - ['@attribute'] = 'PreProc', - ['@boolean'] = 'Boolean', - ['@character'] = 'Character', - ['@character.printf'] = 'SpecialChar', - ['@character.special'] = 'SpecialChar', - ['@comment'] = 'Comment', - ['@comment.error'] = { fg = c.error }, - ['@comment.hint'] = { fg = c.hint }, - ['@comment.info'] = { fg = c.info }, - ['@comment.note'] = { fg = c.hint }, - ['@comment.todo'] = { fg = c.todo }, - ['@comment.warning'] = { fg = c.warning }, - ['@constant'] = 'Constant', - ['@constant.builtin'] = 'Special', - ['@constant.macro'] = 'Define', - ['@constructor'] = { fg = c.magenta }, - ['@constructor.tsx'] = { fg = c.blue1 }, - ['@diff.delta'] = 'DiffChange', - ['@diff.minus'] = 'DiffDelete', - ['@diff.plus'] = 'DiffAdd', - ['@function'] = 'Function', - ['@function.builtin'] = 'Special', - ['@function.call'] = '@function', - ['@function.macro'] = 'Macro', - ['@function.method'] = 'Function', - ['@function.method.call'] = '@function.method', - ['@keyword'] = { fg = c.purple, style = opts.styles.keywords }, - ['@keyword.conditional'] = 'Conditional', - ['@keyword.coroutine'] = '@keyword', - ['@keyword.debug'] = 'Debug', - ['@keyword.directive'] = 'PreProc', - ['@keyword.directive.define'] = 'Define', - ['@keyword.exception'] = 'Exception', - ['@keyword.function'] = { fg = c.magenta, style = opts.styles.functions }, - ['@keyword.import'] = 'Include', - ['@keyword.operator'] = '@operator', - ['@keyword.repeat'] = 'Repeat', - ['@keyword.return'] = '@keyword', - ['@keyword.storage'] = 'StorageClass', - ['@label'] = { fg = c.blue }, - ['@markup'] = '@none', - ['@markup.emphasis'] = { italic = true }, - ['@markup.environment'] = 'Macro', - ['@markup.environment.name'] = 'Type', - ['@markup.heading'] = 'Title', - ['@markup.italic'] = { italic = true }, - ['@markup.link'] = { fg = c.teal }, - ['@markup.link.label'] = 'SpecialChar', - ['@markup.link.label.symbol'] = 'Identifier', - ['@markup.link.url'] = 'Underlined', - ['@markup.list'] = { fg = c.blue5 }, - ['@markup.list.checked'] = { fg = c.green }, - ['@markup.list.markdown'] = { fg = c.orange, bold = true }, - ['@markup.list.unchecked'] = { fg = c.blue }, - ['@markup.math'] = 'Special', - ['@markup.raw'] = 'String', - ['@markup.raw.markdown_inline'] = { bg = c.terminal_black, fg = c.blue }, - ['@markup.strikethrough'] = { strikethrough = true }, - ['@markup.strong'] = { bold = true }, - ['@markup.underline'] = { underline = true }, - ['@module'] = 'Include', - ['@module.builtin'] = { fg = c.red }, - ['@namespace.builtin'] = '@variable.builtin', - ['@none'] = {}, - ['@number'] = 'Number', - ['@number.float'] = 'Float', - ['@operator'] = { fg = c.blue5 }, - ['@property'] = { fg = c.cyan }, - ['@punctuation.bracket'] = { fg = c.fg_dark }, - ['@punctuation.delimiter'] = { fg = c.blue5 }, - ['@punctuation.special'] = { fg = c.blue5 }, - ['@string'] = 'String', - ['@string.documentation'] = { fg = c.green }, - ['@string.escape'] = { fg = c.magenta }, - ['@string.regexp'] = { fg = c.blue }, - ['@tag'] = { fg = c.red }, - ['@tag.attribute'] = { fg = c.cyan }, - ['@tag.delimiter'] = { fg = c.fg_dark }, - ['@tag.delimiter.tsx'] = { fg = c.blue }, - ['@tag.tsx'] = { fg = c.red }, - ['@type'] = 'Type', - ['@type.builtin'] = { fg = c.cyan }, - ['@type.definition'] = 'Typedef', - ['@type.qualifier'] = '@keyword', - ['@variable'] = { fg = c.fg, style = opts.styles.variables }, - ['@variable.builtin'] = { fg = c.red }, - ['@variable.member'] = { fg = c.cyan }, - ['@variable.parameter'] = { fg = c.orange }, - - ['@lsp.type.boolean'] = '@boolean', - ['@lsp.type.builtinType'] = '@type.builtin', - ['@lsp.type.comment'] = '@comment', - ['@lsp.type.decorator'] = '@attribute', - ['@lsp.type.deriveHelper'] = '@attribute', - ['@lsp.type.enum'] = '@type', - ['@lsp.type.enumMember'] = '@constant', - ['@lsp.type.escapeSequence'] = '@string.escape', - ['@lsp.type.formatSpecifier'] = '@markup.list', - ['@lsp.type.generic'] = '@variable', - ['@lsp.type.interface'] = { fg = c.blue1 }, - ['@lsp.type.keyword'] = '@keyword', - ['@lsp.type.lifetime'] = '@storageclass', - ['@lsp.type.namespace'] = '@namespace', - ['@lsp.type.number'] = '@number', - ['@lsp.type.operator'] = '@operator', - ['@lsp.type.parameter'] = '@variable.parameter', - ['@lsp.type.property'] = '@property', - ['@lsp.type.selfKeyword'] = '@variable.builtin', - ['@lsp.type.selfTypeKeyword'] = '@variable.builtin', - ['@lsp.type.string'] = '@string', - ['@lsp.type.typeAlias'] = '@type.definition', - ['@lsp.type.unresolvedReference'] = { undercurl = true, sp = c.error }, - ['@lsp.type.variable'] = {}, - ['@lsp.typemod.class.defaultLibrary'] = '@type.builtin', - ['@lsp.typemod.enum.defaultLibrary'] = '@type.builtin', - ['@lsp.typemod.enumMember.defaultLibrary'] = '@constant.builtin', - ['@lsp.typemod.function.defaultLibrary'] = '@function.builtin', - ['@lsp.typemod.keyword.async'] = '@keyword.coroutine', - ['@lsp.typemod.keyword.injected'] = '@keyword', - ['@lsp.typemod.macro.defaultLibrary'] = '@function.builtin', - ['@lsp.typemod.method.defaultLibrary'] = '@function.builtin', - ['@lsp.typemod.operator.injected'] = '@operator', - ['@lsp.typemod.string.injected'] = '@string', - ['@lsp.typemod.struct.defaultLibrary'] = '@type.builtin', - ['@lsp.typemod.type.defaultLibrary'] = { fg = c.cyan }, - ['@lsp.typemod.typeAlias.defaultLibrary'] = { fg = c.cyan }, - ['@lsp.typemod.variable.callable'] = '@function', - ['@lsp.typemod.variable.defaultLibrary'] = '@variable.builtin', - ['@lsp.typemod.variable.injected'] = '@variable', - ['@lsp.typemod.variable.static'] = '@constant', - } -end - -return M diff --git a/files/.config/nvim/lua/dracula-pro/init.lua b/files/.config/nvim/lua/dracula-pro/init.lua deleted file mode 100644 index 9fec7d7..0000000 --- a/files/.config/nvim/lua/dracula-pro/init.lua +++ /dev/null @@ -1,63 +0,0 @@ --- Dracula Pro Neovim theme --- Main entry point - -local M = {} - -function M.load() - local config = require('dracula-pro.config') - local colors = require('dracula-pro.colors').setup(config.options) - - -- Clear existing highlights - if vim.g.colors_name then vim.cmd('hi clear') end - - vim.o.termguicolors = true - vim.g.colors_name = 'dracula-pro' - - -- Load highlight groups - local groups = { - require('dracula-pro.groups.base').get(colors, config.options), - require('dracula-pro.groups.treesitter').get(colors, config.options), - require('dracula-pro.groups.plugins').get(colors, config.options), - } - - for _, group in ipairs(groups) do - for hl, spec in pairs(group) do - if type(spec) == 'string' then - vim.api.nvim_set_hl(0, hl, { link = spec }) - else - -- Resolve style table into highlight attributes - if type(spec.style) == 'table' then - for k, v in pairs(spec.style) do - spec[k] = v - end - spec.style = nil - end - vim.api.nvim_set_hl(0, hl, spec) - end - end - end - - -- Terminal colors - if config.options.terminal_colors then - vim.g.terminal_color_0 = '#22212C' - vim.g.terminal_color_1 = '#FF9580' - vim.g.terminal_color_2 = '#8AFF80' - vim.g.terminal_color_3 = '#FFFF80' - vim.g.terminal_color_4 = '#9580FF' - vim.g.terminal_color_5 = '#FF80BF' - vim.g.terminal_color_6 = '#80FFEA' - vim.g.terminal_color_7 = '#F8F8F2' - vim.g.terminal_color_8 = '#504C67' - vim.g.terminal_color_9 = '#FFAA99' - vim.g.terminal_color_10 = '#A2FF99' - vim.g.terminal_color_11 = '#FFFF99' - vim.g.terminal_color_12 = '#AA99FF' - vim.g.terminal_color_13 = '#FF99CC' - vim.g.terminal_color_14 = '#99FFEE' - vim.g.terminal_color_15 = '#FFFFFF' - end -end - -function M.setup(opts) require('dracula-pro.config').setup(opts) end - -return M diff --git a/files/.config/nvim/neovim.logo b/files/.config/nvim/neovim.logo deleted file mode 100644 index 6734188..0000000 --- a/files/.config/nvim/neovim.logo +++ /dev/null @@ -1,136 +0,0 @@ - - -█████████████ █████████████ █████████████ ███ ██ ███ █████████████ -███ ███ ███ ███ ███ ███ ███ ██ ███ ███ ███ ███ -███ ███ █████████████ ███ ███ ███ ██ ███ ███ ███ ███ -███ ███ ███ ███ ███ ███ ██ ███ ███ ███ ███ -███ ███ █████████████ █████████████ ████████ ███ ███ ███ ███ - -█████████████ █████████████ █████████████ █████████████ █████████████ █████████████ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -█████████████ █████████████ █████████████ █████████████ █████████████ █████████████ - - -██████████ █████████ ██████████ ███ ██ ███ █████████████ -███ ███ ███ ███ ███ ███ ███ ██ ███ ███ ███ ███ -███ ███ █████████ ███ ███ ███ ██ ███ ███ ███ ███ -███ ███ ███ ███ ███ █████ ███ ███ ███ ███ -███ ███ █████████ ██████████ █████ ███ ███ ███ ███ - -██████████ ██████████ ██████████ ██████████ ██████████ ██████████ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ -██████████ ██████████ ██████████ ██████████ ██████████ ██████████ - -   - ██ █ - ████ ██ - ██████ ███ - ████████ ████ - █████████ █████ - █████ ████ █████ - █████ ████ █████ - █████ ████ █████ - █████ █████████ - ████ ████████ - ███ ██████ - ██ ████ - █ ██ -   - - - - - ███████ ██ ███ - ███ ██ ██ ███ - ███ ██ ██ ███ - ███ ██ ██ ███ - ███ ██ ██ ███ - ███ ██ ███████ - - - █████ ██ ███ - █████ ██ ███ - ███ ██ ██ ███ - ███ ██ ██ ███ - ███ ██ █████ - ███ ██ █████ - - - - - - - ███ ██ ███████ ███████ ███ █████ ██ ██ ██ █████████████ - ████ ██ ██ ██ ██ ███ ██████████ ██ ██ ███ ███ ███ - ████ ██ ██████ ██ ██ ███ ██████████ ██ ██ ███ ███ ███ - ██ ████ ██ ██ ██ █████████  ██ ██ ██ ███ ███ ███ -██ ████ ███████ ███████ █████████ ██ ██ ██ ███ ███ ███ - - - - -█████████████ -███ ███ -█████████████ -███ -█████████████ - - -█████████████ -███ ███ -███ ███ -███ ███ -█████████████ - - - - -█████████████ -███ ███ ███ -███ ███ ███ -███ ███ ███ -███ ███ ███ - - - - - - - - -§ -write neovim using full blocks - -# create a gradient of eight hex colors from each of them a bit darker -starting with #194f7a and ending with #3f2f4b -#194f7a, -#1e4a75, -#23456f, -#28406a, -#2d3b65, -#323660, -#37315a, -#3c2c55, -#3f2f4b - - -create a gradient of eight hex colors from each of them a bit darker -starting with #458588 and ending with #83a598 -#458588 -#3f7e7e -#397474 -#336a6a -#2d6060 -#275656 -#214c4c -#1b4242 -#154838 -#0f3e3e -#093434 -#032a2a - - diff --git a/files/.config/nvim/nvim-pack-lock.json b/files/.config/nvim/nvim-pack-lock.json index 69eb5c9..cbf0ef6 100644 --- a/files/.config/nvim/nvim-pack-lock.json +++ b/files/.config/nvim/nvim-pack-lock.json @@ -1,277 +1,89 @@ { "plugins": { - "Comment.nvim": { - "rev": "e30b7f2008e52442154b66f7c519bfd2f1e32acb", - "src": "https://github.com/numToStr/Comment.nvim" - }, - "blink-cmp-avante": { - "rev": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5", - "src": "https://github.com/Kaiser-Yang/blink-cmp-avante" - }, "blink.cmp": { - "rev": "456d38d1cd3743926f329204c2340f3e7840aad6", + "rev": "2ef3db111181c5eef22a462aa0122349a6027f28", "src": "https://github.com/saghen/blink.cmp" }, - "bufferline.nvim": { - "rev": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3", - "src": "https://github.com/akinsho/bufferline.nvim" - }, - "ccc.nvim": { - "rev": "9d1a256e006decc574789dfc7d628ca11644d4c2", - "src": "https://github.com/uga-rosa/ccc.nvim" - }, - "codecompanion.nvim": { - "rev": "fe792b30974893d8809b06c5e31c5c876c14bbc7", - "src": "https://github.com/olimorris/codecompanion.nvim" + "blink.lib": { + "rev": "f29d8bac6549bc1e7d699c83f680823d7def98bd", + "src": "https://github.com/saghen/blink.lib" }, "conform.nvim": { - "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", + "rev": "dca1a190aa85f9065979ef35802fb77131911106", "src": "https://github.com/stevearc/conform.nvim" }, "copilot.lua": { - "rev": "07aa57148ac28986bab9f55e87ee3d929e2726b1", + "rev": "7e9c269bf40dea86b44e64bd746f1808e991e419", "src": "https://github.com/zbirenbaum/copilot.lua" }, - "crates.nvim": { - "rev": "0f536967abd097d9a4275087483f15d012418740", - "src": "https://github.com/saecki/crates.nvim" - }, "csvview.nvim": { - "rev": "7022e18a0fbae9aecf99a3ba02b2a541edc2b8a1", + "rev": "5c22774c3ecc7f8883af5d143b366e45b1f0875d", "src": "https://github.com/hat0uma/csvview.nvim" }, - "debugprint.nvim": { - "rev": "01ff4d03e623243dc9302cdddc14b08bc2fbb7be", - "src": "https://github.com/andrewferrier/debugprint.nvim" - }, - "diffview.nvim": { - "rev": "4516612fe98ff56ae0415a259ff6361a89419b0a", - "src": "https://github.com/sindrets/diffview.nvim" - }, - "dressing.nvim": { - "rev": "2d7c2db2507fa3c4956142ee607431ddb2828639", - "src": "https://github.com/stevearc/dressing.nvim" + "dracula.nvim": { + "rev": "ae752c13e95fb7c5f58da4b5123cb804ea7568ee", + "src": "https://github.com/Mofiqul/dracula.nvim" }, "fidget.nvim": { "rev": "889e2e96edef4e144965571d46f7a77bcc4d0ddf", "src": "https://github.com/j-hui/fidget.nvim" }, - "file-line": { - "rev": "559088afaf10124ea663ee0f4f73b1de48fb1632", - "src": "https://github.com/bogado/file-line" - }, - "fold-cycle.nvim": { - "rev": "6144567b3307bbcfed0e5b2dd23acb9576575d9e", - "src": "https://github.com/jghauser/fold-cycle.nvim" - }, "friendly-snippets": { "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", "src": "https://github.com/rafamadriz/friendly-snippets" }, "fzf-lua": { - "rev": "4deeecf611c0beba6455e6cf06e2c051a6169dd4", + "rev": "97376e364f51f1b5ae3efaa3eb2e929430ca8419", "src": "https://github.com/ibhagwan/fzf-lua" }, - "git-conflict.nvim": { - "rev": "a1badcd070d176172940eb55d9d59029dad1c5a6", - "src": "https://github.com/akinsho/git-conflict.nvim" - }, - "git-worktree.nvim": { - "rev": "f247308e68dab9f1133759b05d944569ad054546", - "src": "https://github.com/ThePrimeagen/git-worktree.nvim" - }, - "gitgraph.nvim": { - "rev": "c16daa7d7dd597caf9085644c009cfa80b75db8e", - "src": "https://github.com/isakbm/gitgraph.nvim" - }, - "gitlinker.nvim": { - "rev": "cc59f732f3d043b626c8702cb725c82e54d35c25", - "src": "https://github.com/ruifm/gitlinker.nvim" - }, "gitsigns.nvim": { - "rev": "8d82c240f190fc33723d48c308ccc1ed8baad69d", + "rev": "dd3f588bacbeb041be6facf1742e42097f62165d", "src": "https://github.com/lewis6991/gitsigns.nvim" }, - "glance.nvim": { - "rev": "bf86d8b79dce808e65fdb6e9269d0b4ed6d2eefc", - "src": "https://github.com/DNLHC/glance.nvim" - }, - "grapple.nvim": { - "rev": "b41ddfc1c39f87f3d1799b99c2f0f1daa524c5f7", - "src": "https://github.com/cbochs/grapple.nvim" - }, - "image.nvim": { - "rev": "da2be65c153ba15a14a342b05591652a6df70d58", - "src": "https://github.com/3rd/image.nvim" - }, "inc-rename.nvim": { "rev": "0074b551a17338ccdcd299bd86687cc651bcb33d", "src": "https://github.com/smjonas/inc-rename.nvim" }, - "incline.nvim": { - "rev": "8b54c59bcb23366645ae10edca6edfb9d3a0853e", - "src": "https://github.com/b0o/incline.nvim" - }, "indent-blankline.nvim": { "rev": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03", "src": "https://github.com/lukas-reineke/indent-blankline.nvim" }, - "key-analyzer.nvim": { - "rev": "4e4bef34498e821bcbd5203f44db8b67e4f10e04", - "src": "https://github.com/meznaric/key-analyzer.nvim" - }, - "kitty-repl.nvim": { - "rev": "6a280e0cb80c5644c982ffc79e902f7e318a718f", - "src": "https://github.com/marromlam/kitty-repl.nvim" - }, - "lazydev.nvim": { - "rev": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d", - "src": "https://github.com/folke/lazydev.nvim" - }, "lspkind.nvim": { "rev": "c7274c48137396526b59d86232eabcdc7fed8a32", "src": "https://github.com/onsails/lspkind.nvim" }, - "markdown-table-mode.nvim": { - "rev": "bb1ea9b76c1b29e15e14806fdfbb2319df5c06f1", - "src": "https://github.com/Kicamon/markdown-table-mode.nvim" - }, - "mason-lspconfig.nvim": { - "rev": "63a3c6a80538de1003373a619e29aeda27809ad3", - "src": "https://github.com/mason-org/mason-lspconfig.nvim" - }, - "mason-nvim-dap.nvim": { - "rev": "9a10e096703966335bd5c46c8c875d5b0690dade", - "src": "https://github.com/jay-babu/mason-nvim-dap.nvim" - }, "mason-tool-installer.nvim": { "rev": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc", "src": "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim" }, "mason.nvim": { - "rev": "b03fb0f20bc1d43daf558cda981a2be22e73ac42", + "rev": "e54f5bf5f12c560da31c17eee5b3e1bd369f3ff9", "src": "https://github.com/mason-org/mason.nvim" }, - "mcphub.nvim": { - "rev": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f", - "src": "https://github.com/ravitemer/mcphub.nvim" - }, - "mini.ai": { - "rev": "43eb2074843950a3a25aae56a5f41362ec043bfa", - "src": "https://github.com/echasnovski/mini.ai" - }, - "mini.align": { - "rev": "6f3c69cd57134ad8fbf1e85dcdc90cb37a8c75c8", - "src": "https://github.com/echasnovski/mini.align" - }, - "mini.animate": { - "rev": "0f2117aa519ec238846223d581272a9205fef7c2", - "src": "https://github.com/echasnovski/mini.animate" - }, - "mini.bufremove": { - "rev": "8603490905fdfa31943cf2ede7ef4475e3dbac9a", - "src": "https://github.com/echasnovski/mini.bufremove" - }, - "mini.diff": { - "rev": "ab11575a6c147ecfba894d676d0c93e855021d34", - "src": "https://github.com/echasnovski/mini.diff" - }, - "mini.hipatterns": { - "rev": "a3ffba45e4119917b254c372df82e79f7d8c4aad", - "src": "https://github.com/echasnovski/mini.hipatterns" - }, - "mini.icons": { - "rev": "7fdae2443a0e2910015ca39ad74b50524ee682d3", - "src": "https://github.com/echasnovski/mini.icons" - }, - "mini.misc": { - "rev": "4157b1f4cf28525c3c498ce82b1f3480d034a375", - "src": "https://github.com/echasnovski/mini.misc" - }, - "mini.move": { - "rev": "74d140143b1bb905c3d0aebcfc2f216fd237080e", - "src": "https://github.com/echasnovski/mini.move" - }, - "mini.pairs": { - "rev": "42387c7fe68fc0b6e95eaf37f1bb76e7bffaa0d9", - "src": "https://github.com/echasnovski/mini.pairs" - }, - "mini.splitjoin": { - "rev": "8bd5a3d581b9f3dd3bc91fe495e210b8b0ee981d", - "src": "https://github.com/echasnovski/mini.splitjoin" - }, - "mini.starter": { - "rev": "7bdc9decc8b623f245c1e42a64bc41e61d574c5e", - "src": "https://github.com/echasnovski/mini.starter" - }, - "mini.surround": { - "rev": "2715e04bea3ec9244f15b421dc5b18c0fe326210", - "src": "https://github.com/echasnovski/mini.surround" - }, - "mini.trailspace": { - "rev": "b362246495d18c29b4545a8f1c47f627f8011b7c", - "src": "https://github.com/echasnovski/mini.trailspace" - }, - "neogit": { - "rev": "e06745228600a585b88726fc9fba44a373c15a47", - "src": "https://github.com/NeogitOrg/neogit" - }, "neotest": { - "rev": "fd0b7986dd0ae04e38ec7dc0c78a432e3820839c", + "rev": "ad991822b7076b1d940b33a9d6d0d30416d5df81", "src": "https://github.com/nvim-neotest/neotest" }, - "neotest-plenary": { - "rev": "3523adcf9ffaad1911960c5813b0136c1b63a2ec", - "src": "https://github.com/rcarriga/neotest-plenary" - }, "neotest-python": { "rev": "e6df4f1892f6137f58135917db24d1655937d831", "src": "https://github.com/nvim-neotest/neotest-python" }, - "noice.nvim": { - "rev": "7bfd942445fb63089b59f97ca487d605e715f155", - "src": "https://github.com/folke/noice.nvim" - }, - "nui.nvim": { - "rev": "de740991c12411b663994b2860f1a4fd0937c130", - "src": "https://github.com/MunifTanjim/nui.nvim" - }, - "numb.nvim": { - "rev": "12ef3913dea8727d4632c6f2ed47957a993de627", - "src": "https://github.com/nacro90/numb.nvim" - }, "nvim-dap": { "rev": "45a69eba683a2c448dd9ecfc4de89511f0646b5f", "src": "https://github.com/mfussenegger/nvim-dap" }, - "nvim-dap-go": { - "rev": "b4421153ead5d726603b02743ea40cf26a51ed5f", - "src": "https://github.com/leoluz/nvim-dap-go" - }, "nvim-dap-ui": { "rev": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49", "src": "https://github.com/rcarriga/nvim-dap-ui" }, - "nvim-dev-container": { - "rev": "87ea57f420b3460d0c45e239057ffc38fa32f886", - "src": "https://codeberg.org/esensar/nvim-dev-container" - }, "nvim-lightbulb": { - "rev": "e974b1a93c917c840545f51b9a66cfd72c520522", + "rev": "b8c08c5f3b1586dfcdd9f34d7d54fe6982e01ac9", "src": "https://github.com/kosayoda/nvim-lightbulb" }, "nvim-lint": { - "rev": "eab58b48eb11d7745c11c505e0f3057165902461", + "rev": "665525810630701b84181e4d9eefd24b49845b29", "src": "https://github.com/mfussenegger/nvim-lint" }, - "nvim-lspconfig": { - "rev": "c588db330592fa477a70d2fee6ba20a57194bdc3", - "src": "https://github.com/neovim/nvim-lspconfig" - }, - "nvim-lspimport": { - "rev": "9c1c61a5020faeb1863bb66eb4b2a9107e641876", - "src": "https://github.com/stevanmilic/nvim-lspimport" - }, "nvim-navic": { "rev": "f5eba192f39b453675d115351808bd51276d9de5", "src": "https://github.com/SmiteshP/nvim-navic" @@ -280,174 +92,62 @@ "rev": "21f5324bfac14e22ba26553caf69ec76ae8a7662", "src": "https://github.com/nvim-neotest/nvim-nio" }, - "nvim-notify": { - "rev": "8701bece920b38ea289b457f902e2ad184131a5d", - "src": "https://github.com/rcarriga/nvim-notify" - }, - "nvim-surround": { - "rev": "9291040de8cd8a4439eb64c441e8d5d2bf884a5a", - "src": "https://github.com/kylechui/nvim-surround" - }, "nvim-treesitter": { "rev": "4916d6592ede8c07973490d9322f187e07dfefac", "src": "https://github.com/nvim-treesitter/nvim-treesitter" }, "nvim-treesitter-context": { - "rev": "b0c45cefe2c8f7b55fc46f34e563bc428ef99636", + "rev": "b311b30818951d01f7b4bf650521b868b3fece16", "src": "https://github.com/nvim-treesitter/nvim-treesitter-context" }, "nvim-treesitter-textobjects": { "rev": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e", "src": "https://github.com/nvim-treesitter/nvim-treesitter-textobjects" }, - "nvim-ts-autotag": { - "rev": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595", - "src": "https://github.com/windwp/nvim-ts-autotag" - }, - "nvim-ts-context-commentstring": { - "rev": "6141a40173c6efa98242dc951ed4b6f892c97027", - "src": "https://github.com/JoosepAlviste/nvim-ts-context-commentstring" - }, - "obsidian.nvim": { - "rev": "14e0427bef6c55da0d63f9a313fd9941be3a2479", - "src": "https://github.com/epwalsh/obsidian.nvim" + "nvim-web-devicons": { + "rev": "2795c26c916bb3c57dde308b82be51971fa92747", + "src": "https://github.com/nvim-tree/nvim-web-devicons" }, "oil.nvim": { "rev": "0fcc83805ad11cf714a949c98c605ed717e0b83e", "src": "https://github.com/stevearc/oil.nvim" }, - "one-small-step-for-vimkind": { - "rev": "1af6ffb9b5229a856e8090fa2f690e0931a5aace", - "src": "https://github.com/jbyuki/one-small-step-for-vimkind" - }, "plenary.nvim": { - "rev": "b9fd5226c2f76c951fc8ed5923d85e4de065e509", + "rev": "74b06c6c75e4eeb3108ec01852001636d85a932b", "src": "https://github.com/nvim-lua/plenary.nvim" }, "rainbow-delimiters.nvim": { - "rev": "aab6caaffd79b8def22ec4320a5344f7c42f58d2", + "rev": "08783ec022e7ddefe0f12a16f1ac4968f55478b0", "src": "https://github.com/HiPhish/rainbow-delimiters.nvim" }, - "render-markdown.nvim": { - "rev": "54d4b5431e9634ee3d8d30784e017239b5b89d41", - "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" - }, - "sailor.vim": { - "rev": "f035b34b655ed7328cbe26b472792894c9b0ccb4", - "src": "https://github.com/marromlam/sailor.vim" - }, "sidekick.nvim": { - "rev": "17447a05f9385e5f8372b61530f6f9329cb82421", + "rev": "208e1c5b8170c01fd1d07df0139322a76479b235", "src": "https://github.com/folke/sidekick.nvim" }, "sonarqube.nvim": { "rev": "811bf8f46e0aa5ed9c9b5783aaf6f87640df553a", "src": "https://github.com/iamkarasik/sonarqube.nvim" }, - "symbol-usage.nvim": { - "rev": "6a449e6b37be61a110606e9a67a7a308774f120f", - "src": "https://github.com/Wansmer/symbol-usage.nvim" - }, - "symbols-outline.nvim": { - "rev": "564ee65dfc9024bdde73a6621820866987cbb256", - "src": "https://github.com/simrat39/symbols-outline.nvim" - }, - "tex-kitty": { - "rev": "ccab91cdb4f69aa9db9751df74dd2163ed2183b4", - "src": "https://github.com/marromlam/tex-kitty" - }, "tiny-inline-diagnostic.nvim": { - "rev": "57a0eb84b2008c76e77930639890d9874195b1e1", + "rev": "147af4e49f51dd48f41972de26552872b8ba7b25", "src": "https://github.com/rachartier/tiny-inline-diagnostic.nvim" }, - "todo-comments.nvim": { - "rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668", - "src": "https://github.com/folke/todo-comments.nvim" - }, - "toggleterm.nvim": { - "rev": "9a88eae817ef395952e08650b3283726786fb5fb", - "src": "https://github.com/akinsho/toggleterm.nvim" - }, - "treesj": { - "rev": "26bc2a8432ba3ea79ed6aa346fba780a3d372570", - "src": "https://github.com/Wansmer/treesj" - }, - "trouble.nvim": { - "rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a", - "src": "https://github.com/folke/trouble.nvim" + "tokyonight.nvim": { + "rev": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6", + "src": "https://github.com/folke/tokyonight.nvim" }, "undotree": { "rev": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d", "src": "https://github.com/mbbill/undotree" }, "vague.nvim": { - "rev": "4f52c75bce7411f64dacbd1bff2a2fce5bdd59e9", + "rev": "fd58046b9d64259d9785e4aeb6d6f494c6943cad", "src": "https://github.com/vague2k/vague.nvim" }, - "vim-apathy": { - "rev": "27128a0f55189724c841843ba41cd33cf7186032", - "src": "https://github.com/tpope/vim-apathy" - }, - "vim-dadbod": { - "rev": "6d1d41da4873a445c5605f2005ad2c68c99d8770", - "src": "https://github.com/tpope/vim-dadbod" - }, - "vim-dadbod-completion": { - "rev": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6", - "src": "https://github.com/kristijanhusak/vim-dadbod-completion" - }, - "vim-dadbod-ui": { - "rev": "07e92e22114cc5b1ba4938d99897d85b58e20475", - "src": "https://github.com/kristijanhusak/vim-dadbod-ui" - }, - "vim-dirdiff": { - "rev": "84bc8999fde4b3c2d8b228b560278ab30c7ea4c9", - "src": "https://github.com/will133/vim-dirdiff" - }, "vim-fugitive": { "rev": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0", "src": "https://github.com/tpope/vim-fugitive" }, - "vim-kitty": { - "rev": "cd72f2d9cfee8d6aba5a180a5ac3ca265b5d3a46", - "src": "https://github.com/fladson/vim-kitty" - }, - "vim-ledger": { - "rev": "4f2d93dd914f625e2d3db47d97bd9f428fedd68f", - "src": "https://github.com/ledger/vim-ledger" - }, - "vim-log-highlighting": { - "rev": "1037e26f3120e6a6a2c0c33b14a84336dee2a78f", - "src": "https://github.com/mtdl9/vim-log-highlighting" - }, - "vim-markdown": { - "rev": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397", - "src": "https://github.com/plasticboy/vim-markdown" - }, - "vim-repeat": { - "rev": "65846025c15494983dafe5e3b46c8f88ab2e9635", - "src": "https://github.com/tpope/vim-repeat" - }, - "vim-rzip": { - "rev": "f65400fed27b27c7cff7ef8d428c4e5ff749bf28", - "src": "https://github.com/lbrayner/vim-rzip" - }, - "vim-sleuth": { - "rev": "be69bff86754b1aa5adcbb527d7fcd1635a84080", - "src": "https://github.com/tpope/vim-sleuth" - }, - "vim-snakemake": { - "rev": "d0015a0f86150c59fb55f65b41529e6ff4469e18", - "src": "https://github.com/raivivek/vim-snakemake" - }, - "vim-surround": { - "rev": "3d188ed2113431cf8dac77be61b842acb64433d9", - "src": "https://github.com/tpope/vim-surround" - }, - "vimtex": { - "rev": "9306903316c3ddd250676b7cf97c84a84c9c8f99", - "src": "https://github.com/lervag/vimtex" - }, "which-key.nvim": { "rev": "3aab2147e74890957785941f0c1ad87d0a44c15a", "src": "https://github.com/folke/which-key.nvim" diff --git a/files/.config/nvim/tests/integration/test_keymaps.lua b/files/.config/nvim/tests/integration/test_keymaps.lua deleted file mode 100644 index 3728123..0000000 --- a/files/.config/nvim/tests/integration/test_keymaps.lua +++ /dev/null @@ -1,55 +0,0 @@ --- Integration test: verify that key bindings from keymaps.lua are registered. --- Boots a child Neovim with the real config root on rtp, loads options.lua --- (which patches vim.keymap.set) then keymaps.lua, and checks that specific --- maps exist. - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - -local config_root = - vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':h:h:h') - -T['keymaps'] = MiniTest.new_set({ - hooks = { - pre_once = function() - T.child = MiniTest.new_child_neovim() - T.child.start({ '-u', 'NONE' }) - T.child.lua(('vim.opt.rtp:prepend(%q)'):format(config_root)) - -- options.lua patches vim.keymap.set; keymaps.lua uses it - T.child.lua("require('options')") - T.child.lua("require('keymaps')") - end, - post_once = function() T.child.stop() end, - }, -}) - ---- Check that a keymap is registered for the given mode and lhs. -local function has_map(mode, lhs) - return T.child.lua_get( - ( - '(function() ' - .. 'local maps = vim.fn.maparg(%q, %q, false, true); ' - .. 'return maps ~= nil and maps.lhs ~= nil ' - .. 'end)()' - ):format(lhs, mode) - ) -end - -T['keymaps'][' saves in normal mode'] = function() - eq(has_map('n', ''), true) -end -T['keymaps'][']q moves to next quickfix item'] = function() - eq(has_map('n', ']q'), true) -end -T['keymaps']['[q moves to prev quickfix item'] = function() - eq(has_map('n', '[q'), true) -end -T['keymaps'][']l moves to next loclist item'] = function() - eq(has_map('n', ']l'), true) -end -T['keymaps']['[l moves to prev loclist item'] = function() - eq(has_map('n', '[l'), true) -end -T['keymaps']['g> shows messages'] = function() eq(has_map('n', 'g>'), true) end - -return T diff --git a/files/.config/nvim/tests/integration/test_lsp.lua b/files/.config/nvim/tests/integration/test_lsp.lua deleted file mode 100644 index d377276..0000000 --- a/files/.config/nvim/tests/integration/test_lsp.lua +++ /dev/null @@ -1,135 +0,0 @@ --- Integration tests for LSP / Mason setup. --- --- Tier 1 — Mason registry. --- Loads mason.nvim directly in this test process (using the real lazy data --- dir so the registry index is available) and asserts that each expected --- package name is known to mason-registry. --- --- Tier 2 — On-disk binaries. --- Checks ~/.local/share/nvim/mason/ to confirm every tool was actually --- installed. Skipped gracefully when the directory doesn't exist. - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - --- ─── Tool / server lists (keep in sync with lua/custom/plugins/lsp.lua) ────── - -local LSP_SERVERS = { - 'basedpyright', - 'ruff', - 'lua_ls', -} - -local EXTRA_TOOLS = { - 'stylua', - 'black', - 'isort', - 'flake8', - 'mypy', - 'shfmt', - 'prettier', - 'prettierd', - 'eslint_d', - 'hadolint', - 'jsonlint', - 'vale', - 'tflint', - 'sonarlint-language-server', -} - --- mason-lspconfig package names (differ from server names for some servers) -local SERVER_TO_PACKAGE = { - lua_ls = 'lua-language-server', - basedpyright = 'basedpyright', - ruff = 'ruff', -} - --- ─── Tier 1: mason-registry knows every package ─────────────────────────────── --- We load mason.nvim into this process using the real lazy install path. --- We must temporarily override XDG_DATA_HOME so mason reads its cached registry --- from the real data dir, not the isolated tmp dir set by minimal_init.lua. - -local real_data = vim.fn.expand('~/.local/share/nvim') -local mason_plugin_path = real_data .. '/lazy/mason.nvim' -local mason_exists = vim.loop.fs_stat(mason_plugin_path) ~= nil - --- Load mason once, restoring the real data dir for its setup -local mason_registry -if mason_exists then - -- Temporarily point XDG_DATA_HOME at the real nvim data parent so mason - -- can find its cached registry index (under ~/.local/share/nvim/mason/) - local old_xdg = vim.env.XDG_DATA_HOME - vim.env.XDG_DATA_HOME = vim.fn.expand('~/.local/share') - - vim.opt.rtp:prepend(mason_plugin_path) - local ok, reg = pcall(function() - require('mason').setup() - return require('mason-registry') - end) - - vim.env.XDG_DATA_HOME = old_xdg - - if ok then mason_registry = reg end -end - -T['mason registry'] = MiniTest.new_set() - -local function registry_has(pkg_name) - if not mason_registry then - MiniTest.skip('mason.nvim not available — skipping registry checks') - end - local ok = pcall(function() return mason_registry.get_package(pkg_name) end) - return ok -end - -for _, tool in ipairs(EXTRA_TOOLS) do - local name = tool - T['mason registry']['tool: ' .. name] = function() - eq(registry_has(name), true) - end -end - -for _, server in ipairs(LSP_SERVERS) do - local pkg = SERVER_TO_PACKAGE[server] or server - local sname = server - T['mason registry']['lsp: ' .. sname] = function() eq(registry_has(pkg), true) end -end - --- ─── Tier 2: on-disk presence ───────────────────────────────────────────────── - -local mason_root = real_data .. '/mason' -local mason_bin = mason_root .. '/bin' -local mason_pkgs = mason_root .. '/packages' -local mason_bin_exists = vim.loop.fs_stat(mason_bin) ~= nil - -T['mason installed tools'] = MiniTest.new_set() - -local function bin_exists(name) - return vim.loop.fs_stat(mason_bin .. '/' .. name) ~= nil -end -local function pkg_exists(name) - return vim.loop.fs_stat(mason_pkgs .. '/' .. name) ~= nil -end - -for _, tool in ipairs(EXTRA_TOOLS) do - local name = tool - T['mason installed tools']['bin: ' .. name] = function() - if not mason_bin_exists then - MiniTest.skip('Mason not installed on this machine') - end - eq(bin_exists(name), true) - end -end - -for _, server in ipairs(LSP_SERVERS) do - local pkg = SERVER_TO_PACKAGE[server] or server - local sname = server - T['mason installed tools']['lsp: ' .. sname] = function() - if not mason_bin_exists then - MiniTest.skip('Mason not installed on this machine') - end - eq(pkg_exists(pkg), true) - end -end - -return T diff --git a/files/.config/nvim/tests/integration/test_options.lua b/files/.config/nvim/tests/integration/test_options.lua deleted file mode 100644 index 6af5085..0000000 --- a/files/.config/nvim/tests/integration/test_options.lua +++ /dev/null @@ -1,45 +0,0 @@ --- Integration test: verify vim options are set by options.lua. --- Boots a child Neovim, loads options.lua from the config root, then asserts --- key option values. - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - --- Resolve the config root relative to this file's location: --- this file lives at /tests/integration/test_options.lua -local config_root = vim.fn.fnamemodify( - debug.getinfo(1, 'S').source:sub(2), -- strip leading '@' - ':h:h:h' -) - -T['options'] = MiniTest.new_set({ - hooks = { - pre_once = function() - T.child = MiniTest.new_child_neovim() - T.child.start({ '-u', 'NONE' }) - -- Put the config lua/ directory on rtp so require() works - T.child.lua(('vim.opt.rtp:prepend(%q)'):format(config_root)) - T.child.lua("require('options')") - end, - post_once = function() T.child.stop() end, - }, -}) - -local function get_opt(name) return T.child.lua_get(('vim.o[%q]'):format(name)) end - -T['options']['number is set'] = function() eq(get_opt('number'), true) end -T['options']['relativenumber is set'] = function() - eq(get_opt('relativenumber'), true) -end -T['options']['splitbelow is set'] = function() eq(get_opt('splitbelow'), true) end -T['options']['splitright is set'] = function() eq(get_opt('splitright'), true) end -T['options']['undofile is set'] = function() eq(get_opt('undofile'), true) end -T['options']['termguicolors is set'] = function() - eq(get_opt('termguicolors'), true) -end -T['options']['ignorecase is set'] = function() eq(get_opt('ignorecase'), true) end -T['options']['smartcase is set'] = function() eq(get_opt('smartcase'), true) end -T['options']['expandtab is set'] = function() eq(get_opt('expandtab'), true) end -T['options']['showtabline is 0'] = function() eq(get_opt('showtabline'), 0) end - -return T diff --git a/files/.config/nvim/tests/integration/test_plugins_load.lua b/files/.config/nvim/tests/integration/test_plugins_load.lua deleted file mode 100644 index d49271e..0000000 --- a/files/.config/nvim/tests/integration/test_plugins_load.lua +++ /dev/null @@ -1,33 +0,0 @@ --- Smoke tests: verify core Lua modules can be require()'d without errors. --- Catches import-time syntax errors or broken module structure independently --- of whether plugins are installed. - -local T = MiniTest.new_set() - -local config_root = - vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':h:h:h') - -vim.opt.rtp:prepend(config_root) - -local function loads(mod_name) - T[mod_name .. ' loads without error'] = function() - local ok, result = pcall(require, mod_name) - MiniTest.expect.equality(ok, true) - MiniTest.expect.no_equality(result, nil) - end -end - -loads('tools') -- core utilities + ui + strings + colors -loads('highlight') -- highlight helpers (depends on tools) - --- options.lua has side effects but returns nothing; just check it doesn't error -T['options.lua executes without error'] = function() - local ok, err = pcall(require, 'options') - if not ok then - if type(err) == 'string' and err:match('already') then return end - error(err) - end - MiniTest.expect.equality(ok, true) -end - -return T diff --git a/files/.config/nvim/tests/minimal_init.lua b/files/.config/nvim/tests/minimal_init.lua deleted file mode 100644 index 88bbda8..0000000 --- a/files/.config/nvim/tests/minimal_init.lua +++ /dev/null @@ -1,34 +0,0 @@ --- Minimal init for running tests with mini.test. --- Does NOT load the full lazy.nvim stack — only bootstraps mini.test itself. - -local tmp = vim.fn.fnamemodify('/tmp/nvim-test', ':p') -vim.env.XDG_CONFIG_HOME = tmp .. '/config' -vim.env.XDG_DATA_HOME = tmp .. '/data' -vim.env.XDG_STATE_HOME = tmp .. '/state' -vim.env.XDG_CACHE_HOME = tmp .. '/cache' - --- Bootstrap mini.test into a dedicated data dir -local mini_test_path = tmp .. '/data/mini-test/mini.test' -if not vim.loop.fs_stat(mini_test_path) then - vim.fn.system({ - 'git', - 'clone', - '--filter=blob:none', - 'https://github.com/echasnovski/mini.test', - mini_test_path, - }) -end - --- Add mini.test to runtimepath -vim.opt.rtp:prepend(mini_test_path) - --- Add the nvim config root so tests can `require('tools')`, `require('highlight')`, etc. -local config_root = - vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':h:h') -vim.opt.rtp:prepend(config_root) - --- Stub out vim.notify to avoid noise during unit tests -vim.notify = function() end - --- Set up MiniTest global so test files can reference MiniTest.* at file scope -require('mini.test').setup() diff --git a/files/.config/nvim/tests/run_tests.sh b/files/.config/nvim/tests/run_tests.sh deleted file mode 100755 index 44afcc0..0000000 --- a/files/.config/nvim/tests/run_tests.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# Run the full Neovim test suite using mini.test. -# Usage: bash tests/run_tests.sh [directory] -# -# When run from the repo root: -# bash files/.config/nvim/tests/run_tests.sh -# Or from the nvim config root: -# bash tests/run_tests.sh - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -NVIM_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -TEST_DIR="${1:-$SCRIPT_DIR}" - -cd "$NVIM_ROOT" - -echo "Running tests in: $TEST_DIR" -echo "Neovim config root: $NVIM_ROOT" - -nvim --headless --noplugin -u "$SCRIPT_DIR/minimal_init.lua" \ - -c "lua require('mini.test').run({ execute = { reporter = require('mini.test').gen_reporter.stdout({ group_depth = 2 }) } })" \ - -c "qa!" diff --git a/files/.config/nvim/tests/unit/test_highlight.lua b/files/.config/nvim/tests/unit/test_highlight.lua deleted file mode 100644 index 721f1e1..0000000 --- a/files/.config/nvim/tests/unit/test_highlight.lua +++ /dev/null @@ -1,109 +0,0 @@ --- Unit tests for lua/highlight.lua exported pure functions: --- tint, blend, darken_hsl --- --- These functions are pure (no Neovim UI API required at call time) so they --- can run in a plain headless Neovim without a display. - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - --- tint, blend, darken_hsl live in tools.lua (pure, no Neovim UI API at call time). -local hl = require('tools') - --- tint {{{ -T['tint'] = MiniTest.new_set() - -T['tint']['brightens a color with positive percent'] = function() - -- #808080 brightened by 0% should stay #808080 - local result = hl.tint('#808080', 0) - eq(result, '#808080') -end -T['tint']['darkens a color with negative percent'] = function() - -- #ffffff darkened by -50% => #7f7f7f (floor(255 * 0.5) = 127 = 0x7f) - local result = hl.tint('#ffffff', -0.5) - eq(result, '#7f7f7f') -end -T['tint']['clamps to black'] = function() - local result = hl.tint('#101010', -2.0) - eq(result, '#000000') -end -T['tint']['clamps to white'] = function() - local result = hl.tint('#f0f0f0', 100) - eq(result, '#ffffff') -end -T['tint']['returns NONE for invalid color'] = function() - local result = hl.tint('notacolor', 0.1) - eq(result, 'NONE') -end - --- }}} - --- blend {{{ -T['blend'] = MiniTest.new_set() - -T['blend']['alpha=0 returns bg'] = function() - eq(hl.blend('#000000', '#ffffff', 0), '#000000') -end -T['blend']['alpha=1 returns fg'] = function() - eq(hl.blend('#000000', '#ffffff', 1), '#ffffff') -end -T['blend']['50% blend of black and white is grey'] = function() - -- floor((1-0.5)*0 + 0.5*255 + 0.5) = floor(127.5 + 0.5) = 128 = 0x80 - eq(hl.blend('#000000', '#ffffff', 0.5), '#808080') -end -T['blend']['returns NONE when bg is NONE'] = function() - eq(hl.blend('NONE', '#ffffff', 0.5), 'NONE') -end -T['blend']['returns NONE when fg is NONE'] = function() - eq(hl.blend('#000000', 'NONE', 0.5), 'NONE') -end -T['blend']['returns NONE for invalid hex'] = function() - eq(hl.blend('invalid', '#ffffff', 0.5), 'NONE') -end -T['blend']['clamps alpha below 0'] = function() - eq(hl.blend('#000000', '#ffffff', -1), '#000000') -end -T['blend']['clamps alpha above 1'] = function() - eq(hl.blend('#000000', '#ffffff', 2), '#ffffff') -end - --- }}} - --- darken_hsl {{{ -T['darken_hsl'] = MiniTest.new_set() - -T['darken_hsl']['factor=0 returns original color'] = function() - -- darken with factor 0 => ll * (1+0) = ll unchanged - local result = hl.darken_hsl('#ff0000', 0) - eq(result, '#ff0000') -end -T['darken_hsl']['darkens a color'] = function() - -- Any negative factor should produce a darker (lower lightness) result. - -- We just check it differs from the original and is a valid hex. - local result = hl.darken_hsl('#ffffff', -0.5) - MiniTest.expect.no_equality(result, '#ffffff') - MiniTest.expect.no_equality(result, 'NONE') - eq(result:sub(1, 1), '#') - eq(#result, 7) -end -T['darken_hsl']['lightens a color'] = function() - local result = hl.darken_hsl('#333333', 0.5) - MiniTest.expect.no_equality(result, '#333333') - MiniTest.expect.no_equality(result, 'NONE') - eq(result:sub(1, 1), '#') - eq(#result, 7) -end -T['darken_hsl']['returns NONE for invalid hex'] = function() - eq(hl.darken_hsl('notacolor', -0.2), 'NONE') -end -T['darken_hsl']['pure black stays black when darkened'] = function() - eq(hl.darken_hsl('#000000', -0.5), '#000000') -end -T['darken_hsl']['pure white stays white when lightened'] = function() - -- lightness is already 1.0; moving toward 1.0 keeps it there - eq(hl.darken_hsl('#ffffff', 0.5), '#ffffff') -end - --- }}} - -return T diff --git a/files/.config/nvim/tests/unit/test_strings.lua b/files/.config/nvim/tests/unit/test_strings.lua deleted file mode 100644 index c4bd269..0000000 --- a/files/.config/nvim/tests/unit/test_strings.lua +++ /dev/null @@ -1,53 +0,0 @@ --- Unit tests for statusline string utilities (tools.strings). --- spacer, section - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - -local S = require('tools').strings - --- spacer {{{ -T['spacer'] = MiniTest.new_set() - -T['spacer']['returns nil for size < 1'] = function() - eq(S.spacer(0), nil) - eq(S.spacer(-1), nil) -end -T['spacer']['returns nil when size is absent'] = function() eq(S.spacer(), nil) end -T['spacer']['returns a component with correct padding'] = function() - local result = S.spacer(3) - MiniTest.expect.no_equality(result, nil) - local chunks = result[1] - MiniTest.expect.no_equality(chunks, nil) - eq(chunks[1][1], ' ') -end -T['spacer']['respects custom filler'] = function() - local result = S.spacer(2, { filler = '-' }) - local chunks = result[1] - eq(chunks[1][1], '--') -end - --- }}} - --- section {{{ -T['section'] = MiniTest.new_set() - -T['section']['new creates a table with provided args'] = function() - local s = S.section:new('a', 'b', 'c') - eq(s[1], 'a') - eq(s[2], 'b') - eq(s[3], 'c') -end -T['section']['addition concatenates two sections'] = function() - local s1 = S.section:new('a', 'b') - local s2 = S.section:new('c', 'd') - local combined = s1 + s2 - eq(combined[1], 'a') - eq(combined[2], 'b') - eq(combined[3], 'c') - eq(combined[4], 'd') -end - --- }}} - -return T diff --git a/files/.config/nvim/tests/unit/test_tools.lua b/files/.config/nvim/tests/unit/test_tools.lua deleted file mode 100644 index 9664f0d..0000000 --- a/files/.config/nvim/tests/unit/test_tools.lua +++ /dev/null @@ -1,113 +0,0 @@ --- Unit tests for lua/tools.lua pure functions. --- Requires: mini.test (bootstrapped by minimal_init.lua) - -local T = MiniTest.new_set() -local eq = MiniTest.expect.equality - --- `tools` is on the rtp via minimal_init.lua -local tools = require('tools') - --- falsy {{{ -T['falsy'] = MiniTest.new_set() - -T['falsy']['nil returns true'] = function() eq(tools.falsy(nil), true) end -T['falsy']['false returns true'] = function() eq(tools.falsy(false), true) end -T['falsy']['true returns false'] = function() eq(tools.falsy(true), false) end -T['falsy']['empty string returns true'] = function() eq(tools.falsy(''), true) end -T['falsy']['non-empty string returns false'] = function() - eq(tools.falsy('hello'), false) -end -T['falsy']['zero returns true'] = function() eq(tools.falsy(0), true) end -T['falsy']['negative number returns true'] = function() - eq(tools.falsy(-1), true) -end -T['falsy']['positive number returns false'] = function() - eq(tools.falsy(1), false) -end -T['falsy']['empty table returns true'] = function() eq(tools.falsy({}), true) end -T['falsy']['non-empty table returns false'] = function() - eq(tools.falsy({ 1 }), false) -end - --- }}} - --- any {{{ -T['any'] = MiniTest.new_set() - -T['any']['matches item in list'] = function() - eq(tools.any('foo', { 'foo', 'bar' }), true) -end -T['any']['returns false when no match'] = function() - eq(tools.any('baz', { 'foo', 'bar' }), false) -end -T['any']['supports pattern matching'] = function() - eq(tools.any('hello.lua', { '%.lua$' }), true) -end -T['any']['empty list returns false'] = function() - eq(tools.any('foo', {}), false) -end - --- }}} - --- find {{{ -T['find'] = MiniTest.new_set() - -T['find']['returns matching item'] = function() - local result = tools.find(function(x) return x > 2 end, { 1, 2, 3, 4 }) - eq(result, 3) -end -T['find']['returns nil when no match'] = function() - local result = tools.find(function(x) return x > 10 end, { 1, 2, 3 }) - eq(result, nil) -end -T['find']['returns first match'] = function() - local result = tools.find(function(x) return x % 2 == 0 end, { 1, 2, 4, 6 }) - eq(result, 2) -end - --- }}} - --- fold {{{ -T['fold'] = MiniTest.new_set() - -T['fold']['sums a list'] = function() - local sum = tools.fold(function(acc, v) return acc + v end, { 1, 2, 3, 4 }, 0) - eq(sum, 10) -end -T['fold']['concatenates strings'] = function() - local result = tools.fold( - function(acc, v) return acc .. v end, - { 'a', 'b', 'c' }, - '' - ) - eq(result, 'abc') -end -T['fold']['uses empty table as default accumulator'] = function() - local result = tools.fold(function(acc, v) - acc[#acc + 1] = v * 2 - return acc - end, { 1, 2, 3 }) - eq(result, { 2, 4, 6 }) -end - --- }}} - --- map {{{ -T['map'] = MiniTest.new_set() - -T['map']['doubles each element'] = function() - local result = tools.map(function(v) return v * 2 end, { 1, 2, 3 }) - eq(result, { 2, 4, 6 }) -end -T['map']['maps strings to uppercase'] = function() - local result = tools.map(function(v) return v:upper() end, { 'a', 'b', 'c' }) - eq(result, { 'A', 'B', 'C' }) -end -T['map']['returns empty table for empty input'] = function() - local result = tools.map(function(v) return v end, {}) - eq(result, {}) -end - --- }}} - -return T diff --git a/nvim_old/.stylua.toml b/nvim_old/.stylua.toml new file mode 100644 index 0000000..2943768 --- /dev/null +++ b/nvim_old/.stylua.toml @@ -0,0 +1,8 @@ +column_width = 80 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferSingle" +call_parentheses = 'Always' +collapse_simple_statement = 'Always' + diff --git a/files/.config/nvim/LICENSE b/nvim_old/LICENSE similarity index 100% rename from files/.config/nvim/LICENSE rename to nvim_old/LICENSE diff --git a/files/.config/nvim/README.md b/nvim_old/README.md similarity index 100% rename from files/.config/nvim/README.md rename to nvim_old/README.md diff --git a/nvim_old/after/ftplugin/gitcommit.lua b/nvim_old/after/ftplugin/gitcommit.lua new file mode 100644 index 0000000..eee2fe7 --- /dev/null +++ b/nvim_old/after/ftplugin/gitcommit.lua @@ -0,0 +1,4 @@ +vim.opt_local.colorcolumn = '72' +vim.opt_local.spell = true +vim.opt_local.spelllang = 'en_us' +vim.opt_local.textwidth = 72 diff --git a/nvim_old/after/ftplugin/help.lua b/nvim_old/after/ftplugin/help.lua new file mode 100644 index 0000000..dcf1f97 --- /dev/null +++ b/nvim_old/after/ftplugin/help.lua @@ -0,0 +1,35 @@ +-- CUSTOM HELP WINDOW +-- +-- References: +-- https://vim.fandom.com/wiki/Learn_to_use_help + +vim.opt_local.list = false +vim.opt_local.wrap = false +vim.opt_local.spell = true +vim.opt_local.textwidth = 78 + +-- If this is a vim help file, create mappings to make navigation easier +-- Otherwise enable preferred editing settings +if + vim.startswith(vim.fn.expand('%'), vim.env.VIMRUNTIME) or vim.bo.readonly +then + vim.opt_local.spell = false + vim.api.nvim_create_autocmd('BufWinEnter', { + buffer = 0, + command = 'wincmd L | vertical resize 80', + }) + vim.keymap.set('n', '', '', { buffer = 0, desc = 'Follow help tag' }) + vim.keymap.set( + 'n', + '', + '', + { buffer = 0, desc = 'Go back in help tag stack' } + ) +else + vim.keymap.set( + 'n', + 'ml', + 'maGovim:tw=78:ts=8:noet:ft=help:norl:`a', + { buffer = 0, desc = 'Add help modeline' } + ) +end diff --git a/nvim_old/after/ftplugin/markdown.lua b/nvim_old/after/ftplugin/markdown.lua new file mode 100644 index 0000000..2b44133 --- /dev/null +++ b/nvim_old/after/ftplugin/markdown.lua @@ -0,0 +1,8 @@ +vim.opt_local.wrap = true +vim.opt_local.textwidth = 80 +vim.opt_local.colorcolumn = '80' + +-- Simulate 80-col display by resizing the current window. +-- Accounts for sign column (2) + line numbers (up to 4 digits = 4) + 1 separator = 7 +local padding = vim.opt_local.number:get() and 7 or 2 +vim.api.nvim_win_set_width(0, 80 + padding) diff --git a/nvim_old/after/ftplugin/qf.lua b/nvim_old/after/ftplugin/qf.lua new file mode 100644 index 0000000..e016475 --- /dev/null +++ b/nvim_old/after/ftplugin/qf.lua @@ -0,0 +1,58 @@ +-- CUSTOM QUICKFIX WINDOW + +local T = require('tools') + +vim.opt_local.wrap = false +vim.opt_local.number = false +vim.opt_local.signcolumn = 'yes' +vim.opt_local.buflisted = false +vim.opt_local.winfixheight = true + +-- @see: https://vi.stackexchange.ctrueom/a/21255 +local function qf_delete(buf) + buf = buf or vim.api.nvim_get_current_buf() + local qflist = vim.fn.getqflist() + local line = vim.api.nvim_win_get_cursor(0)[1] + local mode = vim.api.nvim_get_mode().mode + if mode:match('[vV]') then + local first_line = vim.fn.getpos("'<")[2] + local last_line = vim.fn.getpos("'>")[2] + qflist = T.fold(function(accum, item, i) + if i < first_line or i > last_line then accum[#accum + 1] = item end + return accum + end, qflist) + else + table.remove(qflist, line) + end + vim.fn.setqflist({}, 'r', { items = qflist }) + vim.fn.setpos('.', { buf, line, 1, 0 }) +end + +vim.keymap.set( + 'n', + 'dd', + qf_delete, + { buffer = 0, desc = '[qf] delete current quickfix entry' } +) +vim.keymap.set( + 'v', + 'd', + qf_delete, + { buffer = 0, desc = '[qf] delete selected quickfix entry' } +) +vim.keymap.set( + 'n', + 'H', + ':colder', + { buffer = 0, desc = '[qf] older quickfix list' } +) +vim.keymap.set( + 'n', + 'L', + ':cnewer', + { buffer = 0, desc = '[qf] newer quickfix list' } +) + +-- force quickfix to open beneath all other splits +vim.cmd.wincmd('J') +T.adjust_split_height(3, 10) diff --git a/nvim_old/after/ftplugin/tex.lua b/nvim_old/after/ftplugin/tex.lua new file mode 100644 index 0000000..2b44133 --- /dev/null +++ b/nvim_old/after/ftplugin/tex.lua @@ -0,0 +1,8 @@ +vim.opt_local.wrap = true +vim.opt_local.textwidth = 80 +vim.opt_local.colorcolumn = '80' + +-- Simulate 80-col display by resizing the current window. +-- Accounts for sign column (2) + line numbers (up to 4 digits = 4) + 1 separator = 7 +local padding = vim.opt_local.number:get() and 7 or 2 +vim.api.nvim_win_set_width(0, 80 + padding) diff --git a/nvim_old/after/ftplugin/xml.lua b/nvim_old/after/ftplugin/xml.lua new file mode 100644 index 0000000..a5ff8f6 --- /dev/null +++ b/nvim_old/after/ftplugin/xml.lua @@ -0,0 +1,48 @@ +-- XML-specific options +vim.opt_local.wrap = true +vim.opt_local.breakindent = true +vim.opt_local.showbreak = string.rep(' ', 8) -- Make it so that long lines wrap smartly +vim.opt_local.linebreak = true + +-- Formatter +vim.keymap.set( + 'n', + 'lf', + ':%!xmlformat', + { buffer = 0, desc = 'Format XML' } +) + +-- Remap for dealing with word wrap +vim.keymap.set( + 'n', + 'k', + "v:count == 0 ? 'gk' : 'k'", + { expr = true, buffer = 0, desc = 'Move up (respect wrap)' } +) +vim.keymap.set( + 'n', + 'j', + "v:count == 0 ? 'gj' : 'j'", + { expr = true, buffer = 0, desc = 'Move down (respect wrap)' } +) + +-- Helper function for MS Word reload +local function reload_word() + vim.api.nvim_command('write') + local bufname = vim.api.nvim_buf_get_name(0) + require('docxedit').reload_docx(bufname) + require('docxedit').watch_edit(bufname) +end + +vim.keymap.set( + { 'n', 'i' }, + 'X', + reload_word, + { buffer = 0, desc = 'Reload MS Word' } +) +vim.keymap.set( + { 'n', 'i' }, + '', + reload_word, + { buffer = 0, desc = 'Reload MS Word' } +) diff --git a/nvim_old/after/plugin/nvim-bqf.lua b/nvim_old/after/plugin/nvim-bqf.lua new file mode 100644 index 0000000..766a01e --- /dev/null +++ b/nvim_old/after/plugin/nvim-bqf.lua @@ -0,0 +1,49 @@ +-------------------------------------------------------------------------------- +-- prettify QF window pannel +-------------------------------------------------------------------------------- + +function _G.qftf(info) + local items + local ret = {} + if info.quickfix == 1 then + items = vim.fn.getqflist({ id = info.id, items = 0 }).items + else + items = vim.fn.getloclist(info.winid, { id = info.id, items = 0 }).items + end + local limit = 31 + local fname_fmt1, fname_fmt2 = + '%-' .. limit .. 's', '…%.' .. (limit - 1) .. 's' + local valid_fmt = '%s │%5d:%-3d│%s %s' + for i = info.start_idx, info.end_idx do + local e = items[i] + local fname = '' + local str + if e.valid == 1 then + if e.bufnr > 0 then + fname = vim.fn.bufname(e.bufnr) + if fname == '' then + fname = '[No Name]' + else + fname = fname:gsub('^' .. vim.env.HOME, '~') + end + -- char in fname may occur more than 1 width, ignore this issue in + -- order to keep performance + if #fname <= limit then + fname = fname_fmt1:format(fname) + else + fname = fname_fmt2:format(fname:sub(1 - limit)) + end + end + local lnum = e.lnum > 99999 and -1 or e.lnum + local col = e.col > 999 and -1 or e.col + local qtype = e.type == '' and '' or ' ' .. e.type:sub(1, 1):upper() + str = valid_fmt:format(fname, lnum, col, qtype, e.text) + else + str = e.text + end + table.insert(ret, str) + end + return ret +end + +vim.o.qftf = '{info -> v:lua._G.qftf(info)}' diff --git a/files/.config/nvim/after/syntax/dap-repl.vim b/nvim_old/after/syntax/dap-repl.vim similarity index 100% rename from files/.config/nvim/after/syntax/dap-repl.vim rename to nvim_old/after/syntax/dap-repl.vim diff --git a/files/.config/nvim/colors/carbon-mist.lua b/nvim_old/colors/carbon-mist.lua similarity index 100% rename from files/.config/nvim/colors/carbon-mist.lua rename to nvim_old/colors/carbon-mist.lua diff --git a/files/.config/nvim/filetype.lua b/nvim_old/filetype.lua similarity index 100% rename from files/.config/nvim/filetype.lua rename to nvim_old/filetype.lua diff --git a/nvim_old/init.lua b/nvim_old/init.lua new file mode 100644 index 0000000..a347d74 --- /dev/null +++ b/nvim_old/init.lua @@ -0,0 +1,41 @@ +-- Init lua + +-- Enable vim.loader for faster startup (Folke's pattern) +if vim.loader then vim.loader.enable() end + +vim.g.os = vim.loop.os_uname().sysname +vim.g.open_command = vim.g.os == 'Darwin' and 'open' or 'xdg-open' +vim.g.dev_environ = '' + +vim.g.dotfiles = vim.env.DOTFILES or vim.fn.expand('~/.dotfiles') +vim.g.vim_dir = vim.g.dotfiles .. '/.config/nvim' + +-- vim.g.projects_directory = vim.fn.expand('~/Projects') +vim.g.projects_directory = vim.fn.expand('~/Workspaces/') +vim.g.personal_directory = vim.g.projects_directory .. '/personal' +vim.g.work_directory = vim.g.projects_directory .. '/work' + +vim.g.icloud = vim.fn.expand('~') .. '/Library/Mobile Documents' +vim.g.obsidian = vim.g.icloud .. '/iCloud~md~obsidian/Documents/Marcos' + +-- Leader bindings +vim.g.mapleader = ' ' -- Remap leader key +vim.g.maplocalleader = '\\' -- Local leader is + + +-------------------------------------------------------------------------------- +-- Load modules {{{ +-------------------------------------------------------------------------------- + +require('tools') -- has to be loaded before plugins (bootstraps ui, strings, colors) +require('keymaps') +require('options') +require('packloader') + +-- Defer non-critical modules for faster startup +vim.defer_fn(function() require('external_grep') end, 0) + +-- }}} +-------------------------------------------------------------------------------- + +-- vim: ts=2 sts=2 sw=2 et fdm=marker fol diff --git a/files/.config/nvim/lua/external_grep.lua b/nvim_old/lua/external_grep.lua similarity index 99% rename from files/.config/nvim/lua/external_grep.lua rename to nvim_old/lua/external_grep.lua index d65c29b..7e45d32 100644 --- a/files/.config/nvim/lua/external_grep.lua +++ b/nvim_old/lua/external_grep.lua @@ -1,3 +1,4 @@ +-- DONE vim.cmd([[ set grepprg=rg\ --vimgrep diff --git a/files/.config/nvim/lua/highlight.lua b/nvim_old/lua/highlight.lua similarity index 100% rename from files/.config/nvim/lua/highlight.lua rename to nvim_old/lua/highlight.lua diff --git a/files/.config/nvim/lua/keymaps.lua b/nvim_old/lua/keymaps.lua similarity index 99% rename from files/.config/nvim/lua/keymaps.lua rename to nvim_old/lua/keymaps.lua index 3faf4a6..a005d39 100644 --- a/files/.config/nvim/lua/keymaps.lua +++ b/nvim_old/lua/keymaps.lua @@ -1,3 +1,4 @@ +-- DONE local T = require('tools') local noremap_silent = { noremap = true, silent = true } @@ -676,6 +677,8 @@ nnoremap S :keeppatterns substitute/\s*\%#\s*/\r/e normal! == ]]) -- move arround +vim.keymap.set({ 'n', 'v' }, 'j', 'gj', { desc = 'move down by display line' }) +vim.keymap.set({ 'n', 'v' }, 'k', 'gk', { desc = 'move up by display line' }) vim.keymap.set('n', '', 'zz') vim.keymap.set('n', '', 'zz') vim.keymap.set('n', 'n', 'nzzzv') diff --git a/files/.config/nvim/lua/options.lua b/nvim_old/lua/options.lua similarity index 99% rename from files/.config/nvim/lua/options.lua rename to nvim_old/lua/options.lua index 3534f07..1f204e9 100644 --- a/files/.config/nvim/lua/options.lua +++ b/nvim_old/lua/options.lua @@ -1,3 +1,4 @@ +-- DONE -- Suppress deprecation warnings from plugins (e.g. client.notify) vim.deprecate = function() end diff --git a/files/.config/nvim/lua/packloader.lua b/nvim_old/lua/packloader.lua similarity index 100% rename from files/.config/nvim/lua/packloader.lua rename to nvim_old/lua/packloader.lua diff --git a/files/.config/nvim/lua/packs/bufferline.lua b/nvim_old/lua/packs/bufferline.lua similarity index 100% rename from files/.config/nvim/lua/packs/bufferline.lua rename to nvim_old/lua/packs/bufferline.lua diff --git a/files/.config/nvim/lua/packs/colorscheme.lua b/nvim_old/lua/packs/colorscheme.lua similarity index 100% rename from files/.config/nvim/lua/packs/colorscheme.lua rename to nvim_old/lua/packs/colorscheme.lua diff --git a/files/.config/nvim/lua/packs/comment.lua b/nvim_old/lua/packs/comment.lua similarity index 99% rename from files/.config/nvim/lua/packs/comment.lua rename to nvim_old/lua/packs/comment.lua index 4790f68..65426e6 100644 --- a/files/.config/nvim/lua/packs/comment.lua +++ b/nvim_old/lua/packs/comment.lua @@ -1,3 +1,4 @@ +-- DONE -- packs/comment.lua -- Patch ts_context_commentstring's update_commentstring to guard against diff --git a/files/.config/nvim/lua/packs/completion.lua b/nvim_old/lua/packs/completion.lua similarity index 100% rename from files/.config/nvim/lua/packs/completion.lua rename to nvim_old/lua/packs/completion.lua diff --git a/files/.config/nvim/lua/packs/copilot.lua b/nvim_old/lua/packs/copilot.lua similarity index 100% rename from files/.config/nvim/lua/packs/copilot.lua rename to nvim_old/lua/packs/copilot.lua diff --git a/files/.config/nvim/lua/packs/dadbod.lua b/nvim_old/lua/packs/dadbod.lua similarity index 100% rename from files/.config/nvim/lua/packs/dadbod.lua rename to nvim_old/lua/packs/dadbod.lua diff --git a/files/.config/nvim/lua/packs/debug.lua b/nvim_old/lua/packs/debug.lua similarity index 100% rename from files/.config/nvim/lua/packs/debug.lua rename to nvim_old/lua/packs/debug.lua diff --git a/files/.config/nvim/lua/packs/filetype.lua b/nvim_old/lua/packs/filetype.lua similarity index 100% rename from files/.config/nvim/lua/packs/filetype.lua rename to nvim_old/lua/packs/filetype.lua diff --git a/files/.config/nvim/lua/packs/format.lua b/nvim_old/lua/packs/format.lua similarity index 100% rename from files/.config/nvim/lua/packs/format.lua rename to nvim_old/lua/packs/format.lua diff --git a/files/.config/nvim/lua/packs/fzf.lua b/nvim_old/lua/packs/fzf.lua similarity index 100% rename from files/.config/nvim/lua/packs/fzf.lua rename to nvim_old/lua/packs/fzf.lua diff --git a/files/.config/nvim/lua/packs/gaming.lua b/nvim_old/lua/packs/gaming.lua similarity index 100% rename from files/.config/nvim/lua/packs/gaming.lua rename to nvim_old/lua/packs/gaming.lua diff --git a/files/.config/nvim/lua/packs/git.lua b/nvim_old/lua/packs/git.lua similarity index 100% rename from files/.config/nvim/lua/packs/git.lua rename to nvim_old/lua/packs/git.lua diff --git a/files/.config/nvim/lua/packs/init.lua b/nvim_old/lua/packs/init.lua similarity index 100% rename from files/.config/nvim/lua/packs/init.lua rename to nvim_old/lua/packs/init.lua diff --git a/files/.config/nvim/lua/packs/linting.lua b/nvim_old/lua/packs/linting.lua similarity index 100% rename from files/.config/nvim/lua/packs/linting.lua rename to nvim_old/lua/packs/linting.lua diff --git a/files/.config/nvim/lua/packs/lsp.lua b/nvim_old/lua/packs/lsp.lua similarity index 100% rename from files/.config/nvim/lua/packs/lsp.lua rename to nvim_old/lua/packs/lsp.lua diff --git a/files/.config/nvim/lua/packs/mini.lua b/nvim_old/lua/packs/mini.lua similarity index 100% rename from files/.config/nvim/lua/packs/mini.lua rename to nvim_old/lua/packs/mini.lua diff --git a/files/.config/nvim/lua/packs/navigation.lua b/nvim_old/lua/packs/navigation.lua similarity index 100% rename from files/.config/nvim/lua/packs/navigation.lua rename to nvim_old/lua/packs/navigation.lua diff --git a/files/.config/nvim/lua/packs/noice.lua b/nvim_old/lua/packs/noice.lua similarity index 100% rename from files/.config/nvim/lua/packs/noice.lua rename to nvim_old/lua/packs/noice.lua diff --git a/files/.config/nvim/lua/packs/obsidian.lua b/nvim_old/lua/packs/obsidian.lua similarity index 100% rename from files/.config/nvim/lua/packs/obsidian.lua rename to nvim_old/lua/packs/obsidian.lua diff --git a/files/.config/nvim/lua/packs/remote.lua b/nvim_old/lua/packs/remote.lua similarity index 100% rename from files/.config/nvim/lua/packs/remote.lua rename to nvim_old/lua/packs/remote.lua diff --git a/files/.config/nvim/lua/packs/repl.lua b/nvim_old/lua/packs/repl.lua similarity index 100% rename from files/.config/nvim/lua/packs/repl.lua rename to nvim_old/lua/packs/repl.lua diff --git a/files/.config/nvim/lua/packs/terminal.lua b/nvim_old/lua/packs/terminal.lua similarity index 100% rename from files/.config/nvim/lua/packs/terminal.lua rename to nvim_old/lua/packs/terminal.lua diff --git a/files/.config/nvim/lua/packs/testing.lua b/nvim_old/lua/packs/testing.lua similarity index 100% rename from files/.config/nvim/lua/packs/testing.lua rename to nvim_old/lua/packs/testing.lua diff --git a/files/.config/nvim/lua/packs/todo.lua b/nvim_old/lua/packs/todo.lua similarity index 100% rename from files/.config/nvim/lua/packs/todo.lua rename to nvim_old/lua/packs/todo.lua diff --git a/files/.config/nvim/lua/packs/treesitter.lua b/nvim_old/lua/packs/treesitter.lua similarity index 100% rename from files/.config/nvim/lua/packs/treesitter.lua rename to nvim_old/lua/packs/treesitter.lua diff --git a/files/.config/nvim/lua/packs/ui.lua b/nvim_old/lua/packs/ui.lua similarity index 100% rename from files/.config/nvim/lua/packs/ui.lua rename to nvim_old/lua/packs/ui.lua diff --git a/files/.config/nvim/lua/packs/vimtex.lua b/nvim_old/lua/packs/vimtex.lua similarity index 100% rename from files/.config/nvim/lua/packs/vimtex.lua rename to nvim_old/lua/packs/vimtex.lua diff --git a/files/.config/nvim/lua/packs/whichkey.lua b/nvim_old/lua/packs/whichkey.lua similarity index 100% rename from files/.config/nvim/lua/packs/whichkey.lua rename to nvim_old/lua/packs/whichkey.lua diff --git a/files/.config/nvim/lua/tools.lua b/nvim_old/lua/tools.lua similarity index 99% rename from files/.config/nvim/lua/tools.lua rename to nvim_old/lua/tools.lua index a462836..a0bf80a 100644 --- a/files/.config/nvim/lua/tools.lua +++ b/nvim_old/lua/tools.lua @@ -1,3 +1,4 @@ +-- DONE local fn, api, fmt = vim.fn, vim.api, string.format local M = {} diff --git a/nvim_old/nvim-pack-lock.json b/nvim_old/nvim-pack-lock.json new file mode 100644 index 0000000..69eb5c9 --- /dev/null +++ b/nvim_old/nvim-pack-lock.json @@ -0,0 +1,456 @@ +{ + "plugins": { + "Comment.nvim": { + "rev": "e30b7f2008e52442154b66f7c519bfd2f1e32acb", + "src": "https://github.com/numToStr/Comment.nvim" + }, + "blink-cmp-avante": { + "rev": "4f494c6e124acbe31a8f5d58effa0c14aa38a6d5", + "src": "https://github.com/Kaiser-Yang/blink-cmp-avante" + }, + "blink.cmp": { + "rev": "456d38d1cd3743926f329204c2340f3e7840aad6", + "src": "https://github.com/saghen/blink.cmp" + }, + "bufferline.nvim": { + "rev": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3", + "src": "https://github.com/akinsho/bufferline.nvim" + }, + "ccc.nvim": { + "rev": "9d1a256e006decc574789dfc7d628ca11644d4c2", + "src": "https://github.com/uga-rosa/ccc.nvim" + }, + "codecompanion.nvim": { + "rev": "fe792b30974893d8809b06c5e31c5c876c14bbc7", + "src": "https://github.com/olimorris/codecompanion.nvim" + }, + "conform.nvim": { + "rev": "086a40dc7ed8242c03be9f47fbcee68699cc2395", + "src": "https://github.com/stevearc/conform.nvim" + }, + "copilot.lua": { + "rev": "07aa57148ac28986bab9f55e87ee3d929e2726b1", + "src": "https://github.com/zbirenbaum/copilot.lua" + }, + "crates.nvim": { + "rev": "0f536967abd097d9a4275087483f15d012418740", + "src": "https://github.com/saecki/crates.nvim" + }, + "csvview.nvim": { + "rev": "7022e18a0fbae9aecf99a3ba02b2a541edc2b8a1", + "src": "https://github.com/hat0uma/csvview.nvim" + }, + "debugprint.nvim": { + "rev": "01ff4d03e623243dc9302cdddc14b08bc2fbb7be", + "src": "https://github.com/andrewferrier/debugprint.nvim" + }, + "diffview.nvim": { + "rev": "4516612fe98ff56ae0415a259ff6361a89419b0a", + "src": "https://github.com/sindrets/diffview.nvim" + }, + "dressing.nvim": { + "rev": "2d7c2db2507fa3c4956142ee607431ddb2828639", + "src": "https://github.com/stevearc/dressing.nvim" + }, + "fidget.nvim": { + "rev": "889e2e96edef4e144965571d46f7a77bcc4d0ddf", + "src": "https://github.com/j-hui/fidget.nvim" + }, + "file-line": { + "rev": "559088afaf10124ea663ee0f4f73b1de48fb1632", + "src": "https://github.com/bogado/file-line" + }, + "fold-cycle.nvim": { + "rev": "6144567b3307bbcfed0e5b2dd23acb9576575d9e", + "src": "https://github.com/jghauser/fold-cycle.nvim" + }, + "friendly-snippets": { + "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", + "src": "https://github.com/rafamadriz/friendly-snippets" + }, + "fzf-lua": { + "rev": "4deeecf611c0beba6455e6cf06e2c051a6169dd4", + "src": "https://github.com/ibhagwan/fzf-lua" + }, + "git-conflict.nvim": { + "rev": "a1badcd070d176172940eb55d9d59029dad1c5a6", + "src": "https://github.com/akinsho/git-conflict.nvim" + }, + "git-worktree.nvim": { + "rev": "f247308e68dab9f1133759b05d944569ad054546", + "src": "https://github.com/ThePrimeagen/git-worktree.nvim" + }, + "gitgraph.nvim": { + "rev": "c16daa7d7dd597caf9085644c009cfa80b75db8e", + "src": "https://github.com/isakbm/gitgraph.nvim" + }, + "gitlinker.nvim": { + "rev": "cc59f732f3d043b626c8702cb725c82e54d35c25", + "src": "https://github.com/ruifm/gitlinker.nvim" + }, + "gitsigns.nvim": { + "rev": "8d82c240f190fc33723d48c308ccc1ed8baad69d", + "src": "https://github.com/lewis6991/gitsigns.nvim" + }, + "glance.nvim": { + "rev": "bf86d8b79dce808e65fdb6e9269d0b4ed6d2eefc", + "src": "https://github.com/DNLHC/glance.nvim" + }, + "grapple.nvim": { + "rev": "b41ddfc1c39f87f3d1799b99c2f0f1daa524c5f7", + "src": "https://github.com/cbochs/grapple.nvim" + }, + "image.nvim": { + "rev": "da2be65c153ba15a14a342b05591652a6df70d58", + "src": "https://github.com/3rd/image.nvim" + }, + "inc-rename.nvim": { + "rev": "0074b551a17338ccdcd299bd86687cc651bcb33d", + "src": "https://github.com/smjonas/inc-rename.nvim" + }, + "incline.nvim": { + "rev": "8b54c59bcb23366645ae10edca6edfb9d3a0853e", + "src": "https://github.com/b0o/incline.nvim" + }, + "indent-blankline.nvim": { + "rev": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03", + "src": "https://github.com/lukas-reineke/indent-blankline.nvim" + }, + "key-analyzer.nvim": { + "rev": "4e4bef34498e821bcbd5203f44db8b67e4f10e04", + "src": "https://github.com/meznaric/key-analyzer.nvim" + }, + "kitty-repl.nvim": { + "rev": "6a280e0cb80c5644c982ffc79e902f7e318a718f", + "src": "https://github.com/marromlam/kitty-repl.nvim" + }, + "lazydev.nvim": { + "rev": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d", + "src": "https://github.com/folke/lazydev.nvim" + }, + "lspkind.nvim": { + "rev": "c7274c48137396526b59d86232eabcdc7fed8a32", + "src": "https://github.com/onsails/lspkind.nvim" + }, + "markdown-table-mode.nvim": { + "rev": "bb1ea9b76c1b29e15e14806fdfbb2319df5c06f1", + "src": "https://github.com/Kicamon/markdown-table-mode.nvim" + }, + "mason-lspconfig.nvim": { + "rev": "63a3c6a80538de1003373a619e29aeda27809ad3", + "src": "https://github.com/mason-org/mason-lspconfig.nvim" + }, + "mason-nvim-dap.nvim": { + "rev": "9a10e096703966335bd5c46c8c875d5b0690dade", + "src": "https://github.com/jay-babu/mason-nvim-dap.nvim" + }, + "mason-tool-installer.nvim": { + "rev": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc", + "src": "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim" + }, + "mason.nvim": { + "rev": "b03fb0f20bc1d43daf558cda981a2be22e73ac42", + "src": "https://github.com/mason-org/mason.nvim" + }, + "mcphub.nvim": { + "rev": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f", + "src": "https://github.com/ravitemer/mcphub.nvim" + }, + "mini.ai": { + "rev": "43eb2074843950a3a25aae56a5f41362ec043bfa", + "src": "https://github.com/echasnovski/mini.ai" + }, + "mini.align": { + "rev": "6f3c69cd57134ad8fbf1e85dcdc90cb37a8c75c8", + "src": "https://github.com/echasnovski/mini.align" + }, + "mini.animate": { + "rev": "0f2117aa519ec238846223d581272a9205fef7c2", + "src": "https://github.com/echasnovski/mini.animate" + }, + "mini.bufremove": { + "rev": "8603490905fdfa31943cf2ede7ef4475e3dbac9a", + "src": "https://github.com/echasnovski/mini.bufremove" + }, + "mini.diff": { + "rev": "ab11575a6c147ecfba894d676d0c93e855021d34", + "src": "https://github.com/echasnovski/mini.diff" + }, + "mini.hipatterns": { + "rev": "a3ffba45e4119917b254c372df82e79f7d8c4aad", + "src": "https://github.com/echasnovski/mini.hipatterns" + }, + "mini.icons": { + "rev": "7fdae2443a0e2910015ca39ad74b50524ee682d3", + "src": "https://github.com/echasnovski/mini.icons" + }, + "mini.misc": { + "rev": "4157b1f4cf28525c3c498ce82b1f3480d034a375", + "src": "https://github.com/echasnovski/mini.misc" + }, + "mini.move": { + "rev": "74d140143b1bb905c3d0aebcfc2f216fd237080e", + "src": "https://github.com/echasnovski/mini.move" + }, + "mini.pairs": { + "rev": "42387c7fe68fc0b6e95eaf37f1bb76e7bffaa0d9", + "src": "https://github.com/echasnovski/mini.pairs" + }, + "mini.splitjoin": { + "rev": "8bd5a3d581b9f3dd3bc91fe495e210b8b0ee981d", + "src": "https://github.com/echasnovski/mini.splitjoin" + }, + "mini.starter": { + "rev": "7bdc9decc8b623f245c1e42a64bc41e61d574c5e", + "src": "https://github.com/echasnovski/mini.starter" + }, + "mini.surround": { + "rev": "2715e04bea3ec9244f15b421dc5b18c0fe326210", + "src": "https://github.com/echasnovski/mini.surround" + }, + "mini.trailspace": { + "rev": "b362246495d18c29b4545a8f1c47f627f8011b7c", + "src": "https://github.com/echasnovski/mini.trailspace" + }, + "neogit": { + "rev": "e06745228600a585b88726fc9fba44a373c15a47", + "src": "https://github.com/NeogitOrg/neogit" + }, + "neotest": { + "rev": "fd0b7986dd0ae04e38ec7dc0c78a432e3820839c", + "src": "https://github.com/nvim-neotest/neotest" + }, + "neotest-plenary": { + "rev": "3523adcf9ffaad1911960c5813b0136c1b63a2ec", + "src": "https://github.com/rcarriga/neotest-plenary" + }, + "neotest-python": { + "rev": "e6df4f1892f6137f58135917db24d1655937d831", + "src": "https://github.com/nvim-neotest/neotest-python" + }, + "noice.nvim": { + "rev": "7bfd942445fb63089b59f97ca487d605e715f155", + "src": "https://github.com/folke/noice.nvim" + }, + "nui.nvim": { + "rev": "de740991c12411b663994b2860f1a4fd0937c130", + "src": "https://github.com/MunifTanjim/nui.nvim" + }, + "numb.nvim": { + "rev": "12ef3913dea8727d4632c6f2ed47957a993de627", + "src": "https://github.com/nacro90/numb.nvim" + }, + "nvim-dap": { + "rev": "45a69eba683a2c448dd9ecfc4de89511f0646b5f", + "src": "https://github.com/mfussenegger/nvim-dap" + }, + "nvim-dap-go": { + "rev": "b4421153ead5d726603b02743ea40cf26a51ed5f", + "src": "https://github.com/leoluz/nvim-dap-go" + }, + "nvim-dap-ui": { + "rev": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49", + "src": "https://github.com/rcarriga/nvim-dap-ui" + }, + "nvim-dev-container": { + "rev": "87ea57f420b3460d0c45e239057ffc38fa32f886", + "src": "https://codeberg.org/esensar/nvim-dev-container" + }, + "nvim-lightbulb": { + "rev": "e974b1a93c917c840545f51b9a66cfd72c520522", + "src": "https://github.com/kosayoda/nvim-lightbulb" + }, + "nvim-lint": { + "rev": "eab58b48eb11d7745c11c505e0f3057165902461", + "src": "https://github.com/mfussenegger/nvim-lint" + }, + "nvim-lspconfig": { + "rev": "c588db330592fa477a70d2fee6ba20a57194bdc3", + "src": "https://github.com/neovim/nvim-lspconfig" + }, + "nvim-lspimport": { + "rev": "9c1c61a5020faeb1863bb66eb4b2a9107e641876", + "src": "https://github.com/stevanmilic/nvim-lspimport" + }, + "nvim-navic": { + "rev": "f5eba192f39b453675d115351808bd51276d9de5", + "src": "https://github.com/SmiteshP/nvim-navic" + }, + "nvim-nio": { + "rev": "21f5324bfac14e22ba26553caf69ec76ae8a7662", + "src": "https://github.com/nvim-neotest/nvim-nio" + }, + "nvim-notify": { + "rev": "8701bece920b38ea289b457f902e2ad184131a5d", + "src": "https://github.com/rcarriga/nvim-notify" + }, + "nvim-surround": { + "rev": "9291040de8cd8a4439eb64c441e8d5d2bf884a5a", + "src": "https://github.com/kylechui/nvim-surround" + }, + "nvim-treesitter": { + "rev": "4916d6592ede8c07973490d9322f187e07dfefac", + "src": "https://github.com/nvim-treesitter/nvim-treesitter" + }, + "nvim-treesitter-context": { + "rev": "b0c45cefe2c8f7b55fc46f34e563bc428ef99636", + "src": "https://github.com/nvim-treesitter/nvim-treesitter-context" + }, + "nvim-treesitter-textobjects": { + "rev": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e", + "src": "https://github.com/nvim-treesitter/nvim-treesitter-textobjects" + }, + "nvim-ts-autotag": { + "rev": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595", + "src": "https://github.com/windwp/nvim-ts-autotag" + }, + "nvim-ts-context-commentstring": { + "rev": "6141a40173c6efa98242dc951ed4b6f892c97027", + "src": "https://github.com/JoosepAlviste/nvim-ts-context-commentstring" + }, + "obsidian.nvim": { + "rev": "14e0427bef6c55da0d63f9a313fd9941be3a2479", + "src": "https://github.com/epwalsh/obsidian.nvim" + }, + "oil.nvim": { + "rev": "0fcc83805ad11cf714a949c98c605ed717e0b83e", + "src": "https://github.com/stevearc/oil.nvim" + }, + "one-small-step-for-vimkind": { + "rev": "1af6ffb9b5229a856e8090fa2f690e0931a5aace", + "src": "https://github.com/jbyuki/one-small-step-for-vimkind" + }, + "plenary.nvim": { + "rev": "b9fd5226c2f76c951fc8ed5923d85e4de065e509", + "src": "https://github.com/nvim-lua/plenary.nvim" + }, + "rainbow-delimiters.nvim": { + "rev": "aab6caaffd79b8def22ec4320a5344f7c42f58d2", + "src": "https://github.com/HiPhish/rainbow-delimiters.nvim" + }, + "render-markdown.nvim": { + "rev": "54d4b5431e9634ee3d8d30784e017239b5b89d41", + "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" + }, + "sailor.vim": { + "rev": "f035b34b655ed7328cbe26b472792894c9b0ccb4", + "src": "https://github.com/marromlam/sailor.vim" + }, + "sidekick.nvim": { + "rev": "17447a05f9385e5f8372b61530f6f9329cb82421", + "src": "https://github.com/folke/sidekick.nvim" + }, + "sonarqube.nvim": { + "rev": "811bf8f46e0aa5ed9c9b5783aaf6f87640df553a", + "src": "https://github.com/iamkarasik/sonarqube.nvim" + }, + "symbol-usage.nvim": { + "rev": "6a449e6b37be61a110606e9a67a7a308774f120f", + "src": "https://github.com/Wansmer/symbol-usage.nvim" + }, + "symbols-outline.nvim": { + "rev": "564ee65dfc9024bdde73a6621820866987cbb256", + "src": "https://github.com/simrat39/symbols-outline.nvim" + }, + "tex-kitty": { + "rev": "ccab91cdb4f69aa9db9751df74dd2163ed2183b4", + "src": "https://github.com/marromlam/tex-kitty" + }, + "tiny-inline-diagnostic.nvim": { + "rev": "57a0eb84b2008c76e77930639890d9874195b1e1", + "src": "https://github.com/rachartier/tiny-inline-diagnostic.nvim" + }, + "todo-comments.nvim": { + "rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668", + "src": "https://github.com/folke/todo-comments.nvim" + }, + "toggleterm.nvim": { + "rev": "9a88eae817ef395952e08650b3283726786fb5fb", + "src": "https://github.com/akinsho/toggleterm.nvim" + }, + "treesj": { + "rev": "26bc2a8432ba3ea79ed6aa346fba780a3d372570", + "src": "https://github.com/Wansmer/treesj" + }, + "trouble.nvim": { + "rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a", + "src": "https://github.com/folke/trouble.nvim" + }, + "undotree": { + "rev": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d", + "src": "https://github.com/mbbill/undotree" + }, + "vague.nvim": { + "rev": "4f52c75bce7411f64dacbd1bff2a2fce5bdd59e9", + "src": "https://github.com/vague2k/vague.nvim" + }, + "vim-apathy": { + "rev": "27128a0f55189724c841843ba41cd33cf7186032", + "src": "https://github.com/tpope/vim-apathy" + }, + "vim-dadbod": { + "rev": "6d1d41da4873a445c5605f2005ad2c68c99d8770", + "src": "https://github.com/tpope/vim-dadbod" + }, + "vim-dadbod-completion": { + "rev": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6", + "src": "https://github.com/kristijanhusak/vim-dadbod-completion" + }, + "vim-dadbod-ui": { + "rev": "07e92e22114cc5b1ba4938d99897d85b58e20475", + "src": "https://github.com/kristijanhusak/vim-dadbod-ui" + }, + "vim-dirdiff": { + "rev": "84bc8999fde4b3c2d8b228b560278ab30c7ea4c9", + "src": "https://github.com/will133/vim-dirdiff" + }, + "vim-fugitive": { + "rev": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0", + "src": "https://github.com/tpope/vim-fugitive" + }, + "vim-kitty": { + "rev": "cd72f2d9cfee8d6aba5a180a5ac3ca265b5d3a46", + "src": "https://github.com/fladson/vim-kitty" + }, + "vim-ledger": { + "rev": "4f2d93dd914f625e2d3db47d97bd9f428fedd68f", + "src": "https://github.com/ledger/vim-ledger" + }, + "vim-log-highlighting": { + "rev": "1037e26f3120e6a6a2c0c33b14a84336dee2a78f", + "src": "https://github.com/mtdl9/vim-log-highlighting" + }, + "vim-markdown": { + "rev": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397", + "src": "https://github.com/plasticboy/vim-markdown" + }, + "vim-repeat": { + "rev": "65846025c15494983dafe5e3b46c8f88ab2e9635", + "src": "https://github.com/tpope/vim-repeat" + }, + "vim-rzip": { + "rev": "f65400fed27b27c7cff7ef8d428c4e5ff749bf28", + "src": "https://github.com/lbrayner/vim-rzip" + }, + "vim-sleuth": { + "rev": "be69bff86754b1aa5adcbb527d7fcd1635a84080", + "src": "https://github.com/tpope/vim-sleuth" + }, + "vim-snakemake": { + "rev": "d0015a0f86150c59fb55f65b41529e6ff4469e18", + "src": "https://github.com/raivivek/vim-snakemake" + }, + "vim-surround": { + "rev": "3d188ed2113431cf8dac77be61b842acb64433d9", + "src": "https://github.com/tpope/vim-surround" + }, + "vimtex": { + "rev": "9306903316c3ddd250676b7cf97c84a84c9c8f99", + "src": "https://github.com/lervag/vimtex" + }, + "which-key.nvim": { + "rev": "3aab2147e74890957785941f0c1ad87d0a44c15a", + "src": "https://github.com/folke/which-key.nvim" + } + } +} diff --git a/files/.config/nvim/plugin/autocommands.lua b/nvim_old/plugin/autocommands.lua similarity index 100% rename from files/.config/nvim/plugin/autocommands.lua rename to nvim_old/plugin/autocommands.lua diff --git a/files/.config/nvim/plugin/colors.lua b/nvim_old/plugin/colors.lua similarity index 100% rename from files/.config/nvim/plugin/colors.lua rename to nvim_old/plugin/colors.lua diff --git a/files/.config/nvim/plugin/lastplace.lua b/nvim_old/plugin/lastplace.lua similarity index 100% rename from files/.config/nvim/plugin/lastplace.lua rename to nvim_old/plugin/lastplace.lua diff --git a/files/.config/nvim/plugin/lsp.lua b/nvim_old/plugin/lsp.lua similarity index 100% rename from files/.config/nvim/plugin/lsp.lua rename to nvim_old/plugin/lsp.lua diff --git a/files/.config/nvim/plugin/root.lua b/nvim_old/plugin/root.lua similarity index 100% rename from files/.config/nvim/plugin/root.lua rename to nvim_old/plugin/root.lua diff --git a/files/.config/nvim/plugin/statuscolumn.lua b/nvim_old/plugin/statuscolumn.lua similarity index 100% rename from files/.config/nvim/plugin/statuscolumn.lua rename to nvim_old/plugin/statuscolumn.lua diff --git a/files/.config/nvim/plugin/statusline.lua b/nvim_old/plugin/statusline.lua similarity index 100% rename from files/.config/nvim/plugin/statusline.lua rename to nvim_old/plugin/statusline.lua diff --git a/files/.config/nvim/queries/html/rainbow-tags.scm b/nvim_old/queries/html/rainbow-tags.scm similarity index 100% rename from files/.config/nvim/queries/html/rainbow-tags.scm rename to nvim_old/queries/html/rainbow-tags.scm diff --git a/files/.config/nvim/queries/vim/highlights.scm b/nvim_old/queries/vim/highlights.scm similarity index 100% rename from files/.config/nvim/queries/vim/highlights.scm rename to nvim_old/queries/vim/highlights.scm diff --git a/files/.config/nvim/skeleton/skel.beamer b/nvim_old/skeleton/skel.beamer similarity index 100% rename from files/.config/nvim/skeleton/skel.beamer rename to nvim_old/skeleton/skel.beamer diff --git a/files/.config/nvim/skeleton/skel.c b/nvim_old/skeleton/skel.c similarity index 100% rename from files/.config/nvim/skeleton/skel.c rename to nvim_old/skeleton/skel.c diff --git a/files/.config/nvim/skeleton/skel.cpp b/nvim_old/skeleton/skel.cpp similarity index 100% rename from files/.config/nvim/skeleton/skel.cpp rename to nvim_old/skeleton/skel.cpp diff --git a/files/.config/nvim/skeleton/skel.h b/nvim_old/skeleton/skel.h similarity index 100% rename from files/.config/nvim/skeleton/skel.h rename to nvim_old/skeleton/skel.h diff --git a/files/.config/nvim/skeleton/skel.hpp b/nvim_old/skeleton/skel.hpp similarity index 100% rename from files/.config/nvim/skeleton/skel.hpp rename to nvim_old/skeleton/skel.hpp diff --git a/files/.config/nvim/skeleton/skel.lua b/nvim_old/skeleton/skel.lua similarity index 100% rename from files/.config/nvim/skeleton/skel.lua rename to nvim_old/skeleton/skel.lua diff --git a/files/.config/nvim/skeleton/skel.py b/nvim_old/skeleton/skel.py similarity index 100% rename from files/.config/nvim/skeleton/skel.py rename to nvim_old/skeleton/skel.py diff --git a/files/.config/nvim/skeleton/skel.sh b/nvim_old/skeleton/skel.sh similarity index 100% rename from files/.config/nvim/skeleton/skel.sh rename to nvim_old/skeleton/skel.sh diff --git a/files/.config/nvim/skeleton/skel.tex b/nvim_old/skeleton/skel.tex similarity index 100% rename from files/.config/nvim/skeleton/skel.tex rename to nvim_old/skeleton/skel.tex From 9295a26c396249c5894e193b7fa4ed1792090094 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Thu, 14 May 2026 00:56:51 +0200 Subject: [PATCH 6/7] feat: new simple config --- files/.config/nvim/init.lua | 4275 ++++++++++++++++++++++++++++++++++- 1 file changed, 4265 insertions(+), 10 deletions(-) diff --git a/files/.config/nvim/init.lua b/files/.config/nvim/init.lua index a347d74..31e49ce 100644 --- a/files/.config/nvim/init.lua +++ b/files/.config/nvim/init.lua @@ -12,8 +12,8 @@ vim.g.vim_dir = vim.g.dotfiles .. '/.config/nvim' -- vim.g.projects_directory = vim.fn.expand('~/Projects') vim.g.projects_directory = vim.fn.expand('~/Workspaces/') -vim.g.personal_directory = vim.g.projects_directory .. '/personal' -vim.g.work_directory = vim.g.projects_directory .. '/work' +vim.g.personal_directory = vim.g.projects_directory .. 'personal/' +vim.g.work_directory = vim.g.projects_directory .. 'work/' vim.g.icloud = vim.fn.expand('~') .. '/Library/Mobile Documents' vim.g.obsidian = vim.g.icloud .. '/iCloud~md~obsidian/Documents/Marcos' @@ -22,20 +22,4275 @@ vim.g.obsidian = vim.g.icloud .. '/iCloud~md~obsidian/Documents/Marcos' vim.g.mapleader = ' ' -- Remap leader key vim.g.maplocalleader = '\\' -- Local leader is +-- database +vim.g.db_ui_use_nerd_fonts = 1 +------------------------------------------------------------------------------- +-- Tools {{{ lua/tools.lua +------------------------------------------------------------------------------- + +local fn, api, cmd, fmt = vim.fn, vim.api, vim.cmd, string.format + +local T = {} +_G.T = T -- expose for ftplugins and after/ scripts + +-- User commands +function T.command(name, rhs, opts) + api.nvim_create_user_command(name, rhs, opts or {}) +end + +-- Autocommand group: T.augroup('Name', { event=..., pattern=..., command=fn }, ...) +do + local autocmd_keys = { + 'event', + 'buffer', + 'pattern', + 'desc', + 'command', + 'group', + 'once', + 'nested', + } + function T.augroup(name, ...) + local commands = { ... } + assert(name ~= 'User', 'augroup name cannot be User') + assert(#commands > 0, fmt('augroup %s needs at least one autocmd', name)) + local id = api.nvim_create_augroup(name, { clear = true }) + for _, autocmd in ipairs(commands) do + local bad = {} + for k in pairs(autocmd) do + if not vim.tbl_contains(autocmd_keys, k) then bad[#bad + 1] = k end + end + if #bad > 0 then + vim.schedule( + function() + vim.notify( + 'Unknown keys: ' .. table.concat(bad, ', '), + vim.log.levels.ERROR, + { title = fmt('Autocmd: %s', name) } + ) + end + ) + end + local is_fn = type(autocmd.command) == 'function' + api.nvim_create_autocmd(autocmd.event, { + group = name, + pattern = autocmd.pattern, + desc = autocmd.desc, + callback = is_fn and autocmd.command or nil, + command = not is_fn and autocmd.command or nil, + once = autocmd.once, + nested = autocmd.nested, + buffer = autocmd.buffer, + }) + end + return id + end +end + +-- Falsy check (nil, false, '', 0, {}) +function T.falsy(item) + if not item then return true end + local t = type(item) + if t == 'boolean' then return not item end + if t == 'string' then return item == '' end + if t == 'number' then return item <= 0 end + if t == 'table' then return vim.tbl_isempty(item) end + return false +end + +function T.foreach(callback, list) + for k, v in pairs(list) do + callback(v, k) + end +end + +function T.fold(callback, list, accum) + accum = accum or {} + for k, v in pairs(list) do + accum = callback(accum, v, k) + assert(accum ~= nil, 'accumulator must be returned on each iteration') + end + return accum +end + +function T.map(callback, list) + return T.fold(function(acc, v, k) + acc[#acc + 1] = callback(v, k, acc) + return acc + end, list, {}) +end + +-- Pattern-aware membership: T.any('foo.lua', {'%.lua$', '%.vim$'}) +function T.any(target, list) + for _, item in ipairs(list) do + if target:match(item) then return true end + end + return false +end + +function T.find(matcher, haystack) + for _, needle in ipairs(haystack) do + if matcher(needle) then return needle end + end +end + +function T.adjust_split_height(min, max) + local lines = math.max(min, math.min(max, vim.fn.line('$'))) + vim.cmd('resize ' .. lines) +end + +-- Table with pattern-fallback __index +function T.p_table(map) + return setmetatable(map, { + __index = function(tbl, key) + if not key then return end + for k, v in pairs(tbl) do + if key:match(k) then return v end + end + end, + }) +end + +-- pcall that notifies on error via vim.notify +function T.pcall(msg, func, ...) + local args = { ... } + if type(msg) == 'function' then + local arg = func + args, func, msg = { arg, unpack(args) }, msg, nil + end + return xpcall(func, function(err) + msg = debug.traceback( + msg and fmt('%s:\n%s\n%s', msg, vim.inspect(args), err) or err + ) + vim.schedule( + function() vim.notify(msg, vim.log.levels.ERROR, { title = 'ERROR' }) end + ) + end, unpack(args)) +end + +-- Display-width-aware truncation +function T.truncate(str, max_len) + assert(str and max_len, 'truncate: string and max_len required') + return api.nvim_strwidth(str) > max_len and str:sub(1, max_len) .. '…' + or str +end + +-- Highlight group as hex strings +function T.get_hi(name) + local hi = api.nvim_get_hl(0, { name = name }) + for k, v in pairs(hi) do + if type(v) == 'number' then hi[k] = ('#%06x'):format(v) end + end + return hi +end + +-- Brighten (+) or darken (-) a hex color by a percentage +function T.tint(color, percent) + assert(color and percent, 'tint: color and percent required') + local r = tonumber(color:sub(2, 3), 16) + local g = tonumber(color:sub(4, 5), 16) + local b = tonumber(color:sub(6, 7), 16) + if not r or not g or not b then return 'NONE' end + local function blend(c) + return math.min(math.max(math.floor(c * (1 + percent)), 0), 255) + end + return fmt('#%02x%02x%02x', blend(r), blend(g), blend(b)) +end + +-- Blend two hex colors; alpha=0 → bg, alpha=1 → fg +function T.blend(bg, fg, alpha) + assert(bg and fg and alpha ~= nil, 'blend: bg, fg, alpha required') + if type(bg) ~= 'string' or type(fg) ~= 'string' then return 'NONE' end + if not bg:match('^#%x%x%x%x%x%x$') or not fg:match('^#%x%x%x%x%x%x$') then + return 'NONE' + end + alpha = math.min(math.max(alpha, 0), 1) + local br, bg2, bb = + tonumber(bg:sub(2, 3), 16), + tonumber(bg:sub(4, 5), 16), + tonumber(bg:sub(6, 7), 16) + local fr, fg2, fb = + tonumber(fg:sub(2, 3), 16), + tonumber(fg:sub(4, 5), 16), + tonumber(fg:sub(6, 7), 16) + if not br or not bg2 or not bb or not fr or not fg2 or not fb then + return 'NONE' + end + local function mix(b, f) return math.floor((1 - alpha) * b + alpha * f + 0.5) end + return fmt('#%02x%02x%02x', mix(br, fr), mix(bg2, fg2), mix(bb, fb)) +end + +-- Icons {{{ + +local _icons = { + separators = { + left_thin_block = '▏', + right_thin_block = '▕', + vert_bottom_half_block = '▄', + vert_top_half_block = '▀', + right_block = '🮉', + light_shade_block = '░', + right_chubby_block = '▓', + }, + scrollbar = '█', + lsp = { + error = '', + warn = '', + info = '󰋼', + hint = '󰌵', + }, + git = { + add = '', + mod = '', + remove = '', + ignore = '', + rename = '', + untracked = '', + ignored = '', + unstaged = '', + staged = '', + conflict = '', + diff = '', + repo = '', + logo = '󰊢', + branch = '', + }, + documents = { + file = '', + files = '', + folder = '', + open_folder = '', + }, + misc = { + plus = '', + ellipsis = '…', + up = '⇡', + down = '⇣', + line = '', + indent = 'Ξ', + tab = '⇥', + bug = '', + question = '', + bell = '󰂚', + clock = '󰥔', + cmd = '⌘', + lock = '', + shaded_lock = '', + circle = '', + project = '', + dashboard = '', + history = '󰄉', + comment = '󰅺', + robot = '󰚩', + copilot = '', + lightbulb = '󰌵', + search = '󰍉', + code = '', + telescope = '', + gear = '', + chat = '󰭻', + package = '', + list = '', + sign_in = '', + check = '󰄬', + fire = '󰈸', + note = '󰎞', + bookmark = '', + pencil = '󰏫', + tools = '', + arrow_right = '', + caret_right = '', + chevron_right = '', + double_chevron_right = '»', + table = '󰓫', + calendar = '󰃭', + block = '▏', + clippy = '󰅏', + puzzle = '', + settings = '⚙', + key = '', + config = '', + box = '', + moon = '󰤄', + source = '󰈙', + sleep = '󰒲', + rocket = '', + task = '󰐃', + runtime = '', + }, +} + +-- }}} + +-- }}} +------------------------------------------------------------------------------- + +-- Highlights {{{ + +local function _stl_hl() + -- Undercurl for diagnostics (must set sp= for the curl colour) + api.nvim_set_hl( + 0, + 'DiagnosticUnderlineError', + { undercurl = true, sp = T.get_hi('DiagnosticError').fg } + ) + api.nvim_set_hl( + 0, + 'DiagnosticUnderlineWarn', + { undercurl = true, sp = T.get_hi('DiagnosticWarn').fg } + ) + api.nvim_set_hl( + 0, + 'DiagnosticUnderlineInfo', + { undercurl = true, sp = T.get_hi('DiagnosticInfo').fg } + ) + api.nvim_set_hl( + 0, + 'DiagnosticUnderlineHint', + { undercurl = true, sp = T.get_hi('DiagnosticHint').fg } + ) + + local stl_bg = T.get_hi('StatusLine').bg or 'NONE' + local function stl(name, opts) + opts.bg = opts.bg or stl_bg + api.nvim_set_hl(0, name, opts) + end + stl('StSeparator', { fg = 'NONE', bg = 'NONE' }) + stl('StTitle', { fg = T.get_hi('Normal').fg }) + stl('StFaded', { fg = T.get_hi('Comment').fg }) + stl('StFilename', { fg = T.get_hi('Normal').fg, bold = true }) + stl('StDirectory', { fg = T.get_hi('Comment').fg, italic = true }) + stl('StParent', { fg = T.get_hi('DiagnosticWarn').fg, italic = true }) + stl( + 'StEnv', + { fg = T.get_hi('DiagnosticError').fg, bold = true, italic = true } + ) + stl('StBranch', { fg = T.get_hi('DiagnosticInfo').fg }) + stl('StGitAdd', { fg = T.get_hi('GitSignsAdd').fg }) + stl('StGitDelete', { fg = T.get_hi('GitSignsDelete').fg }) + stl('StGitModified', { fg = T.get_hi('DiagnosticWarn').fg }) + stl('StInfo', { fg = T.get_hi('DiagnosticInfo').fg }) + stl('StWarn', { fg = T.get_hi('DiagnosticWarn').fg }) + stl('StError', { fg = T.get_hi('DiagnosticError').fg }) + stl( + 'StDevEnv', + { fg = T.get_hi('StatusLine').bg, bg = T.get_hi('Comment').fg } + ) + api.nvim_set_hl(0, 'StSearchCount', { + fg = T.get_hi('Normal').bg, + bg = T.get_hi('Normal').fg, + }) + api.nvim_set_hl( + 0, + 'CursorLineNr', + { fg = T.get_hi('CursorLineNr').fg, bold = true } + ) + api.nvim_set_hl(0, 'StatusColGitAdd', { fg = T.get_hi('GitSignsAdd').fg }) + api.nvim_set_hl( + 0, + 'StatusColGitChange', + { fg = T.get_hi('GitSignsChange').fg } + ) + api.nvim_set_hl( + 0, + 'StatusColGitDelete', + { fg = T.get_hi('GitSignsDelete').fg } + ) + api.nvim_set_hl( + 0, + 'StatusColGitUntracked', + { fg = T.get_hi('DiagnosticWarn').fg } + ) + api.nvim_set_hl(0, 'StatusColGitNone', { fg = T.get_hi('Comment').fg }) + -- Build a named palette from the ANSI 16-color terminal slots. + -- Index semantics are fixed by convention; every colorscheme that sets terminal_colors honors them. + local palette = { + { 'black', 0 }, { 'red', 1 }, + { 'green', 2 }, { 'yellow', 3 }, + { 'blue', 4 }, { 'purple', 5 }, + { 'cyan', 6 }, { 'white', 7 }, + { 'bright_black', 8 }, { 'bright_red', 9 }, + { 'bright_green', 10 }, { 'bright_yellow', 11 }, + { 'bright_blue', 12 }, { 'bright_purple', 13 }, + { 'bright_cyan', 14 }, { 'bright_white', 15 }, + } + for _, p in ipairs(palette) do + local fg = vim.g['terminal_color_' .. p[2]] + if fg then api.nvim_set_hl(0, p[1], { fg = fg }) end + end + -- Rainbow delimiters pull from the palette by hue name. + local rd_map = { + { 'RainbowDelimiterViolet', 'purple' }, + { 'RainbowDelimiterBlue', 'blue' }, + { 'RainbowDelimiterCyan', 'cyan' }, + { 'RainbowDelimiterGreen', 'green' }, + { 'RainbowDelimiterYellow', 'yellow' }, + { 'RainbowDelimiterOrange', 'bright_yellow'}, + { 'RainbowDelimiterRed', 'red' }, + } + for _, pair in ipairs(rd_map) do + api.nvim_set_hl(0, pair[1], { link = pair[2] }) + end +end + +T.augroup('StlHighlights', { + event = 'ColorScheme', + command = _stl_hl, +}, { + event = 'VimEnter', + once = true, + command = _stl_hl, +}) + +-- }}} + +-- Statuscolumn {{{ +do + local function _hl(group, text) + if not group or group == '' then return text end + return ('%%#%s#%s%%*'):format(group, text) + end + + local function fold_mark(lnum) + local fcs = vim.opt.fillchars:get() + if fn.foldlevel(lnum) <= fn.foldlevel(lnum - 1) then return '' end + return fn.foldclosed(lnum) == -1 and (fcs.foldopen or '▾') + or (fcs.foldclose or '▸') + end + + local function get_signs(buf, lnum0) + return api.nvim_buf_get_extmarks( + buf, + -1, + { lnum0, 0 }, + { lnum0, -1 }, + { details = true, type = 'sign' } + ) + end + + local _git_hl = { + Add = 'StatusColGitAdd', + Change = 'StatusColGitChange', + Changedelete = 'StatusColGitChange', + Delete = 'StatusColGitDelete', + Topdelete = 'StatusColGitDelete', + Untracked = 'StatusColGitUntracked', + } + + local _git_bar_thick = _icons.separators.right_block .. ' ' + local _git_bar_thin = _icons.separators.right_thin_block .. ' ' + + local function git_col(buf, lnum0) + for _, m in ipairs(get_signs(buf, lnum0)) do + local hlg = (m[4] or {}).sign_hl_group or '' + if hlg:match('^GitSigns') then + for key, grp in pairs(_git_hl) do + if hlg:match(key) then return _hl(grp, _git_bar_thick) end + end + return _hl('StatusColGitChange', _git_bar_thick) + end + end + return _hl('StatusColGitNone', _git_bar_thin) + end + + local function diag_col(buf, lnum0, cursor_lnum, lnum) + if lnum == cursor_lnum then return ' ' end + local best_text, best_hl, best_sev = '', nil, 99 + for _, m in ipairs(get_signs(buf, lnum0)) do + local hlg = (m[4] or {}).sign_hl_group or '' + if hlg:match('^DiagnosticSign') then + local sev = hlg:match('Error') and 1 or hlg:match('Warn') and 2 or nil + if sev and sev < best_sev then + best_text = sev == 1 and _icons.lsp.error or _icons.lsp.warn + best_hl, best_sev = hlg, sev + end + end + end + return best_text == '' and ' ' or _hl(best_hl, best_text) + end + + local function render() + local win = tonumber(vim.g.statusline_winid) or api.nvim_get_current_win() + local buf = api.nvim_win_get_buf(win) + if vim.bo[buf].buftype ~= '' then return '' end + + local lnum, relnum, virtnum = vim.v.lnum, vim.v.relnum, vim.v.virtnum + local cursor_lnum = api.nvim_win_get_cursor(win)[1] + local w = + math.max(api.nvim_strwidth(tostring(api.nvim_buf_line_count(buf))), 3) + + local num_str + if virtnum ~= 0 then + num_str = (' '):rep(w - 1) .. _icons.separators.light_shade_block + else + local n = tostring( + (vim.wo[win].relativenumber and relnum ~= 0) and relnum or lnum + ) + num_str = (' '):rep(w - #n) .. n + end + + local lnum0 = lnum - 1 + local is_cursor = (lnum == cursor_lnum and virtnum == 0) + local num_hl = is_cursor and 'CursorLineNr' or 'LineNr' + local parts = table.concat({ + diag_col(buf, lnum0, cursor_lnum, lnum), + _hl(num_hl, num_str), + git_col(buf, lnum0), + fold_mark(lnum), + }) + return is_cursor and ('%%#CursorLine#%s%%*'):format(parts) or parts + end + + _G._stlcol = render + vim.o.statuscolumn = '%{%v:lua._stlcol()%}' + + T.augroup('StatusColumn', { + event = { 'BufEnter', 'FileType' }, + command = function() + local win = api.nvim_get_current_win() + local buf = api.nvim_win_get_buf(win) + if + vim.bo[buf].buftype == 'terminal' + or (vim.wo[win].winhl or ''):match('FzfLua') + then + vim.wo[win].statuscolumn = '' + vim.wo[win].signcolumn = 'no' + end + end, + }) +end +-- }}} + +-- Options {{{ +-- Suppress deprecation warnings from plugins (e.g. client.notify) +vim.deprecate = function() end + +-- Make all keymaps silent by default (Folke's pattern) +local keymap_set = vim.keymap.set +vim.keymap.set = function(mode, lhs, rhs, opts) + opts = opts or {} + opts.silent = opts.silent ~= false + return keymap_set(mode, lhs, rhs, opts) +end + +-- Disable unused providers (Folke's pattern) +vim.g.loaded_python3_provider = 0 +vim.g.loaded_perl_provider = 0 +vim.g.loaded_ruby_provider = 0 +vim.g.loaded_node_provider = 0 + +-- Message output on vim actions {{{ +vim.opt.shortmess = { + t = true, -- truncate file messages at start + A = true, -- ignore annoying swap file messages + o = true, -- file-read message overwrites previous + O = true, -- file-read message overwrites previous + T = true, -- truncate non-file messages in middle + f = true, -- (file x of x) instead of just (x of x + F = true, -- Don't give file info when editing, NOTE: this breaks autocommand messages + s = true, + c = true, + W = true, -- Don't show [w] or written when writing +} +vim.o.background = 'dark' -- or "light" +-- }}} + +-- Timings {{{ +vim.opt.updatetime = 1000 -- Increased from 500 to reduce CursorHold frequency (improves scrolling perf) +vim.opt.timeout = true +vim.opt.timeoutlen = 500 +-- }}} + +-- Window splitting and buffers {{{ + +vim.opt.splitkeep = 'screen' +vim.opt.splitbelow = true +vim.opt.splitright = true +vim.opt.eadirection = 'hor' +-- exclude usetab pde we do not want to jump to buffers in already open tabs +--- do not use split or vsplit to ensure we don't open any new windows +vim.opt.switchbuf = 'useopen,uselast' +vim.opt.fillchars = { + eob = ' ', -- suppress ~ at EndOfBuffer + diff = '╱', -- alternatives = ⣿ ░ ─ + msgsep = ' ', -- alternatives: ‾ ─ + fold = ' ', + foldopen = '▽', -- '▼' + foldclose = '▷', -- '▶' + foldsep = 's', +} + +-- do not show tabline +vim.opt.showtabline = 0 + +vim.opt.nu = true +vim.opt.relativenumber = true + +-- }}} + +-- Diff {{{ +-- Use in vertical diff mode, blank lines to keep sides aligned, Ignore +-- whitespace changes +vim.opt.diffopt = vim.opt.diffopt + + { + 'vertical', + 'iwhite', + 'hiddenoff', + 'foldcolumn:0', + 'context:4', + 'algorithm:myers', + 'indent-heuristic', + 'linematch:60', + } +if vim.fn.has('nvim-0.12') == 1 then + vim.cmd([[ + set diffopt+=inline:char + ]]) +end +-- }}} + +-- Format Options {{{ + +vim.opt.formatoptions = { + ['1'] = true, + ['2'] = true, -- Use indent from 2nd line of a paragraph + q = true, -- continue comments with gq" + c = true, -- Auto-wrap comments using textwidth + r = true, -- Continue comments when pressing Enter + n = true, -- Recognize numbered lists + t = false, -- autowrap lines using text width value + j = true, -- remove a comment leader when joining lines. + -- Only break if the line was not longer than 'textwidth' when the insert + -- started and only at a white character that has been entered during the + -- current insert command. + l = true, + v = true, +} + +-- }}} + +-- Folds {{{ +-- unfortunately folding in (n)vim is a mess, if you set the fold level to start +-- at X then it will auto fold anything at that level, all good so far. If you then +-- try to edit the content of your fold and the foldmethod=manual then it will +-- recompute the fold which when using nvim-ufo means it will be closed again... + +vim.opt.foldlevelstart = 999 + +-- Grepprg +vim.opt.grepprg = [[rg --glob "!.git" --no-heading --vimgrep --follow $*]] +vim.opt.grepformat = vim.opt.grepformat ^ { '%f:%l:%c:%m' } + +-- Display +vim.opt.conceallevel = 2 +vim.opt.breakindent = true +vim.opt.breakindentopt = 'sbr' +vim.opt.linebreak = true -- lines wrap at words rather than random characters +-- If we render signs inside `statuscolumn`, disable the built-in signcolumn to +-- avoid duplicated icons. +vim.opt.signcolumn = 'no' -- statuscolumn.lua manages signs +vim.opt.ruler = false +vim.opt.cmdheight = 0 +vim.opt.showbreak = [[↪ ]] -- Options include -> '…', '↳ ', '→','↪ ' + +-- List chars +vim.opt.list = true -- invisible chars +vim.opt.listchars = { + eol = nil, + extends = '…', -- Alternatives: … » › + precedes = '░', -- Alternatives: … « ‹ + tab = '» ', + trail = '·', + nbsp = '␣', +} + +-- Indentation +vim.opt.wrap = false +vim.opt.tabstop = 4 +vim.opt.softtabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.wrapmargin = 8 +vim.opt.textwidth = 80 +vim.opt.autoindent = true +vim.opt.shiftround = true +vim.opt.expandtab = true + +vim.opt.pumheight = 15 +vim.opt.confirm = true -- make vim prompt me to save before doing destructive things +vim.opt.completeopt = { 'menuone', 'noselect' } +vim.opt.hlsearch = true +vim.opt.autowriteall = true -- automatically :write before running commands and changing files +-- Defer clipboard setup to avoid startup cost from provider discovery. +vim.schedule(function() vim.opt.clipboard = { 'unnamedplus' } end) +vim.o.laststatus = 3 +vim.o.termguicolors = true +vim.o.guifont = 'CartographCF Nerd Font Mono:h14,codicon' +vim.opt.inccommand = 'split' +vim.g.have_nerd_font = true + +-- Emoji +vim.opt.emoji = false + +-- Cursor +vim.opt.guicursor = { + 'n-v-c-sm:block-Cursor', + 'i-ci-ve:ver25-iCursor', + 'r-cr-o:hor20-Cursor', + 'a:blinkon0', +} +vim.opt.cursorline = true +vim.opt.cursorlineopt = { 'both', 'number' } + +-- Title +vim.opt.title = true +vim.opt.titlelen = 70 + +-- Utilities +vim.opt.showmode = false +vim.opt.sessionoptions = { + 'globals', + 'buffers', + 'curdir', + 'winpos', + 'winsize', + 'help', + 'tabpages', + 'terminal', +} +vim.opt.viewoptions = { 'cursor', 'folds' } -- save/restore just these (with `:{mk,load}view`) +vim.opt.virtualedit = 'block' -- allow cursor to move where there is no text in visual block mode + +-- Jumplist +vim.opt.jumpoptions = { 'stack' } -- make the jumplist behave like a browser stack + +-- Backup and swaps +vim.opt.backup = false +vim.opt.undofile = true +vim.opt.undodir = vim.fn.stdpath('state') .. '/undo' +vim.opt.swapfile = false + +-- Match and search +vim.opt.ignorecase = true +vim.opt.smartcase = true +vim.opt.wrapscan = true -- Searches wrap around the end of the file +vim.opt.scrolloff = 9 +vim.opt.sidescrolloff = 10 +vim.opt.sidescroll = 1 + +-- }}} + +-- Spelling {{{ + +vim.opt.spellsuggest:prepend({ 12 }) +vim.opt.spelloptions:append({ 'camel', 'noplainbuffer' }) +vim.opt.spellcapcheck = '' -- don't check for capital letters at start of sentence + +-- }}} + +-- Mouse {{{ + +vim.opt.mouse = 'a' +vim.opt.mousefocus = true +vim.opt.mousemoveevent = true +vim.opt.mousescroll = 'ver:1,hor:4' + +-- }}} + +-- Netrw {{{ + +vim.g.netrw_browse_split = 0 +vim.g.netrw_banner = 0 +vim.g.netrw_winsize = 25 + +-- }}} + +-- vim.opt.isfname:append('@-@') + +-- Diagnostics +local _S = vim.diagnostic.severity +vim.diagnostic.config({ + underline = true, + update_in_insert = false, + severity_sort = true, + virtual_text = false, + float = { border = 'rounded' }, + signs = { + severity = { min = _S.WARN }, + text = { + [_S.ERROR] = _icons.lsp.error, + [_S.WARN] = _icons.lsp.warn, + [_S.INFO] = _icons.lsp.info, + [_S.HINT] = _icons.lsp.hint, + }, + }, +}) + +-- }}} + +-- Filetypes {{{ + +vim.filetype.add({ + extension = { + lock = 'yaml', + scpt = 'applescript', + applescript = 'applescript', + }, + filename = { + ['.psqlrc'] = 'conf', + ['launch.json'] = 'jsonc', + Podfile = 'ruby', + Brewfile = 'ruby', + Snakefile = 'snakemake', + }, + pattern = { + ['.*%.map'] = 'xml', + ['.*%.cnk'] = 'xml', + ['.*%.avsc'] = 'json', + ['.*%.avro'] = 'json', + ['.*%.conf'] = 'conf', + ['.*%.theme'] = 'conf', + ['.*%.gradle'] = 'groovy', + ['^.env%..*'] = 'bash', + }, +}) + +-- }}} + +------------------------------------------------------------------------------- +-- Plugin add {{{ lua/packloader.lua +------------------------------------------------------------------------------- + +-- Dev plugins {{{ +local _sailor_dev = '/Users/marcos/Workspaces/personal/sailor.vim' +if vim.uv.fs_stat(_sailor_dev) then + vim.opt.runtimepath:prepend(_sailor_dev) + vim.cmd('source ' .. _sailor_dev .. '/plugin/sailor.lua') +else + vim.pack.add({ 'https://github.com/marromlam/sailor.vim' }) +end +-- }}} + +-- Rainbow delimiters config must be set before vim.pack.add loads the plugin +vim.g.rainbow_delimiters = { + highlight = { + 'RainbowDelimiterRed', + 'RainbowDelimiterYellow', + 'RainbowDelimiterBlue', + 'RainbowDelimiterOrange', + 'RainbowDelimiterGreen', + 'RainbowDelimiterViolet', + 'RainbowDelimiterCyan', + }, +} + +-- General plugins {{{ +vim.pack.add({ + -- Colorschemes + 'https://github.com/folke/tokyonight.nvim', + + -- LSP + -- 'https://github.com/neovim/nvim-lspconfig', + 'https://github.com/mason-org/mason.nvim', + -- 'https://github.com/mason-org/mason-lspconfig.nvim', + 'https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim', + 'https://github.com/j-hui/fidget.nvim', + -- 'https://github.com/folke/lazydev.nvim', + -- 'https://github.com/stevanmilic/nvim-lspimport', + -- 'https://github.com/simrat39/symbols-outline.nvim', + 'https://github.com/rachartier/tiny-inline-diagnostic.nvim', + 'https://github.com/iamkarasik/sonarqube.nvim', + 'https://github.com/kosayoda/nvim-lightbulb', + -- 'https://github.com/DNLHC/glance.nvim', + 'https://github.com/smjonas/inc-rename.nvim', + + -- Completion {{{ + 'https://github.com/saghen/blink.lib', + 'https://github.com/saghen/blink.cmp', + 'https://github.com/rafamadriz/friendly-snippets', + 'https://github.com/onsails/lspkind.nvim', + -- }}} + -- 'https://github.com/MeanderingProgrammer/render-markdown.nvim', + + -- Treesitter + 'https://github.com/nvim-treesitter/nvim-treesitter', + 'https://github.com/nvim-treesitter/nvim-treesitter-textobjects', + 'https://github.com/nvim-treesitter/nvim-treesitter-context', + -- 'https://github.com/JoosepAlviste/nvim-ts-context-commentstring', + -- 'https://github.com/Wansmer/treesj', + -- 'https://github.com/windwp/nvim-ts-autotag', + + -- Fuzzy finder + 'https://github.com/ibhagwan/fzf-lua', + + -- Git + 'https://github.com/lewis6991/gitsigns.nvim', + -- 'https://github.com/ruifm/gitlinker.nvim', + -- 'https://github.com/akinsho/git-conflict.nvim', + 'https://github.com/tpope/vim-fugitive', + -- 'https://github.com/sindrets/diffview.nvim', + -- 'https://github.com/isakbm/gitgraph.nvim', + -- 'https://github.com/ThePrimeagen/git-worktree.nvim', + + -- UI + -- 'https://github.com/akinsho/bufferline.nvim', + 'https://github.com/lukas-reineke/indent-blankline.nvim', + 'https://github.com/SmiteshP/nvim-navic', + 'https://github.com/nvim-tree/nvim-web-devicons', + -- 'https://github.com/b0o/incline.nvim', + -- 'https://github.com/uga-rosa/ccc.nvim', + -- 'https://github.com/Wansmer/symbol-usage.nvim', + 'https://github.com/mbbill/undotree', + -- 'https://github.com/nacro90/numb.nvim', + 'https://github.com/HiPhish/rainbow-delimiters.nvim', + + -- Noice + -- 'https://github.com/folke/noice.nvim', + -- 'https://github.com/MunifTanjim/nui.nvim', + + -- Format / Lint {{{ + 'https://github.com/stevearc/conform.nvim', + 'https://github.com/mfussenegger/nvim-lint', + -- }}} + + -- Debug + 'https://github.com/mfussenegger/nvim-dap', + 'https://github.com/rcarriga/nvim-dap-ui', + 'https://github.com/nvim-neotest/nvim-nio', + -- 'https://github.com/jay-babu/mason-nvim-dap.nvim', + -- 'https://github.com/leoluz/nvim-dap-go', + + -- Testing + 'https://github.com/nvim-lua/plenary.nvim', + 'https://github.com/nvim-neotest/neotest', + -- 'https://github.com/rcarriga/neotest-plenary', + 'https://github.com/nvim-neotest/neotest-python', + + -- Navigation + 'https://github.com/stevearc/oil.nvim', + -- 'https://github.com/cbochs/grapple.nvim', + + -- Terminal + -- 'https://github.com/akinsho/toggleterm.nvim', + + -- Copilot / AI {{{ + 'https://github.com/zbirenbaum/copilot.lua', + 'https://github.com/folke/sidekick.nvim', + -- }}} + + -- Database + -- 'https://github.com/tpope/vim-dadbod', + -- 'https://github.com/kristijanhusak/vim-dadbod-ui', + -- 'https://github.com/kristijanhusak/vim-dadbod-completion', + + -- Todo / Folke + -- 'https://github.com/folke/todo-comments.nvim', + -- 'https://github.com/folke/trouble.nvim', + + -- Whichkey + 'https://github.com/folke/which-key.nvim', + + -- Comment + -- 'https://github.com/numToStr/Comment.nvim', + + -- Obsidian + -- 'https://github.com/epwalsh/obsidian.nvim', + + -- REPL (loaded conditionally below) + + -- Remote / containers + -- 'https://codeberg.org/esensar/nvim-dev-container', + + -- Filetype support {{{ + 'https://github.com/hat0uma/csvview.nvim', + -- }}} +}) + +-- }}} + +-- }}} +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Plugin setup {{{ +------------------------------------------------------------------------------- + +-- Colorscheme {{{ + +require('tokyonight').setup({ + style = 'night', -- 'storm', 'moon', 'night', 'day' + transparent = false, + terminal_colors = true, + styles = { + comments = { italic = true }, + keywords = { italic = true }, + functions = {}, + variables = {}, + }, + sidebars = { 'qf', 'help', 'terminal' }, + day_brightness = 0.3, +}) +vim.cmd('colorscheme tokyonight') + +-- }}} + +-- Treesitter {{{ + +-- context highlights (set before plugin loads so ColorScheme refreshes them) +T.augroup('TsContextHighlights', { + event = 'ColorScheme', + command = function() + api.nvim_set_hl(0, 'TreesitterContext', { link = 'Normal' }) + api.nvim_set_hl(0, 'TreesitterContextSeparator', { link = 'Comment' }) + api.nvim_set_hl(0, 'TreesitterContextLineNumber', { link = 'LineNr' }) + end, +}, { + event = 'VimEnter', + once = true, + command = function() + api.nvim_set_hl(0, 'TreesitterContext', { link = 'Normal' }) + api.nvim_set_hl(0, 'TreesitterContextSeparator', { link = 'Comment' }) + api.nvim_set_hl(0, 'TreesitterContextLineNumber', { link = 'LineNr' }) + end, +}) + +vim.keymap.set( + 'n', + 'sc', + 'TSContext toggle', + { desc = 'toggle treesitter context' } +) + +vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlTreesitter', { clear = true }), + callback = function() + -- nvim-treesitter v1 (main branch) API + require('nvim-treesitter').setup({ + ensure_installed = { + 'bash', + 'c', + 'cpp', + 'css', + 'diff', + 'dockerfile', + 'git_config', + 'git_rebase', + 'gitcommit', + 'gitignore', + 'go', + 'graphql', + 'html', + 'javascript', + 'json', + 'jsonc', + 'lua', + 'luadoc', + 'luap', + 'markdown', + 'markdown_inline', + 'python', + 'query', + 'regex', + 'rust', + 'toml', + 'tsx', + 'typescript', + 'vim', + 'vimdoc', + 'xml', + 'yaml', + }, + }) + + require('nvim-treesitter-textobjects').setup({ + select = { + enable = true, + lookahead = true, + include_surrounding_whitespace = true, + keymaps = { + ['af'] = { query = '@function.outer', desc = 'ts: all function' }, + ['if'] = { query = '@function.inner', desc = 'ts: inner function' }, + ['ac'] = { query = '@class.outer', desc = 'ts: all class' }, + ['ic'] = { query = '@class.inner', desc = 'ts: inner class' }, + ['aC'] = { + query = '@conditional.outer', + desc = 'ts: all conditional', + }, + ['iC'] = { + query = '@conditional.inner', + desc = 'ts: inner conditional', + }, + ['aL'] = { query = '@assignment.lhs', desc = 'ts: assignment lhs' }, + ['aR'] = { query = '@assignment.rhs', desc = 'ts: assignment rhs' }, + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + [']m'] = '@function.outer', + [']M'] = '@class.outer', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[M'] = '@class.outer', + }, + }, + }) + + require('treesitter-context').setup({ + enable = false, + max_lines = 3, + multiline_threshold = 10, + separator = '─', + mode = 'cursor', + }) + end, +}) + +-- Treesitter folds (opt-in per buffer; foldlevelstart=999 keeps them open) +vim.api.nvim_create_autocmd('FileType', { + group = vim.api.nvim_create_augroup('MrlTsFolds', { clear = true }), + callback = function(ev) + local ok, parser = pcall(vim.treesitter.get_parser, ev.buf) + if not ok or not parser then return end + vim.wo.foldmethod = 'expr' + vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' + end, +}) + +-- }}} + +require('csvview').setup() + +require('nvim-web-devicons').setup({ default = true }) + +require('nvim-navic').setup({ + lsp = { auto_attach = false }, + highlight = true, + separator = ' › ', + depth_limit = 5, + depth_limit_indicator = '…', + safe_output = true, +}) + +-- blink.cmp {{{ + +require('blink.cmp').setup({ + keymap = { + preset = 'none', + [''] = { 'show', 'show_documentation', 'hide_documentation' }, + [''] = { 'cancel', 'fallback' }, + [''] = { 'accept', 'fallback' }, + [''] = { + 'select_next', + 'snippet_forward', + function() return require('sidekick').nes_jump_or_apply() end, + 'fallback', + }, + [''] = { 'select_prev', 'snippet_backward', 'fallback' }, + [''] = { 'select_prev', 'fallback' }, + [''] = { 'select_next', 'fallback' }, + [''] = { 'select_prev', 'fallback' }, + [''] = { 'select_next', 'fallback' }, + [''] = { 'scroll_documentation_up', 'fallback' }, + [''] = { 'scroll_documentation_down', 'fallback' }, + }, + + appearance = { + nerd_font_variant = 'mono', + use_nvim_cmp_as_default = true, + }, + + fuzzy = { + frecency = { enabled = true }, + use_proximity = true, + sorts = { 'score', 'sort_text' }, + }, + + sources = { + default = { 'lsp', 'path', 'snippets', 'buffer' }, + per_filetype = { + lua = { 'lsp', 'path', 'snippets', 'buffer' }, + python = { 'lsp', 'path', 'snippets', 'buffer' }, + gitcommit = { 'buffer' }, + }, + providers = { + lsp = { + name = 'LSP', + module = 'blink.cmp.sources.lsp', + min_keyword_length = 0, + score_offset = 100, + fallbacks = { 'snippets' }, + }, + path = { + name = 'Path', + module = 'blink.cmp.sources.path', + score_offset = 3, + opts = { + trailing_slash = true, + label_trailing_slash = false, + get_cwd = function(context) + return vim.fn.expand(('#%d:p:h'):format(context.bufnr)) + end, + }, + }, + snippets = { + name = 'Snippets', + module = 'blink.cmp.sources.snippets', + min_keyword_length = 2, + score_offset = -3, + }, + buffer = { + name = 'Buffer', + module = 'blink.cmp.sources.buffer', + min_keyword_length = 5, + max_items = 5, + }, + }, + }, + + signature = { + enabled = true, + window = { border = 'rounded' }, + }, + + completion = { + ghost_text = { enabled = true }, + trigger = { + show_in_snippet = true, + show_on_keyword = true, + show_on_trigger_character = true, + show_on_insert_on_trigger_character = true, + }, + list = { + max_items = 200, + cycle = { from_bottom = true, from_top = true }, + selection = { + preselect = true, + auto_insert = function(ctx) return ctx.mode == 'cmdline' end, + }, + }, + menu = { + -- border = 'rounded', + cmdline_position = function() + if vim.g.ui_cmdline_pos ~= nil then + local pos = vim.g.ui_cmdline_pos + return { pos[1] - 1, pos[2] } + end + local height = (vim.o.cmdheight == 0) and 1 or vim.o.cmdheight + return { vim.o.lines - height, 0 } + end, + draw = { + columns = { + { 'kind_icon', 'label', gap = 1 }, + { 'kind' }, + }, + components = { + kind_icon = { + text = function(item) + return (require('lspkind').symbol_map[item.kind] or '') .. ' ' + end, + highlight = 'CmpItemKind', + }, + label = { + width = { fill = true, max = 60 }, + text = function(item) + return item.label .. (item.label_detail or '') + end, + highlight = 'CmpItemAbbr', + }, + kind = { + width = { max = 20 }, + text = function(item) return item.kind end, + highlight = 'CmpItemKind', + }, + }, + }, + }, + documentation = { + auto_show = true, + auto_show_delay_ms = 200, + update_delay_ms = 50, + treesitter_highlighting = true, + window = { + border = 'rounded', + winhighlight = 'Normal:BlinkCmpDoc,FloatBorder:BlinkCmpDocBorder,CursorLine:BlinkCmpDocCursorLine,Search:None', + }, + }, + accept = { + auto_brackets = { enabled = true }, + }, + }, +}) + +vim.api.nvim_set_hl(0, 'BlinkCmpDoc', { bg = '#2a2a2a' }) +vim.api.nvim_set_hl(0, 'BlinkCmpDocBorder', { bg = '#2a2a2a', fg = '#2a2a2a' }) +vim.api.nvim_set_hl(0, 'BlinkCmpDocSeparator', { fg = '#333333' }) + +-- }}} + +-- Copilot {{{ + +require('copilot').setup({ + panel = { + enabled = true, + auto_refresh = false, + keymap = { + jump_prev = '[[', + jump_next = ']]', + accept = '', + refresh = 'gr', + open = '', + }, + layout = { + position = 'bottom', + ratio = 0.4, + }, + }, + suggestion = { + enabled = true, + auto_trigger = true, + hide_during_completion = true, + debounce = 75, + keymap = { + accept = '', + accept_word = false, + accept_line = false, + next = '', + prev = '', + dismiss = '', + }, + }, + filetypes = { + yaml = false, + markdown = false, + help = false, + gitcommit = false, + gitrebase = false, + hgcommit = false, + svn = false, + cvs = false, + ['.'] = false, + }, + copilot_node_command = 'node', + server_opts_overrides = {}, +}) + +-- }}} + +-- Sidekick +vim.keymap.set( + 'n', + 'aa', + function() require('sidekick.cli').toggle() end, + { + desc = 'Sidekick Toggle CLI', + } +) +vim.keymap.set( + 'n', + 'as', + function() require('sidekick.cli').select() end, + { + desc = 'Select CLI', + } +) +vim.keymap.set( + { 'x', 'n' }, + 'at', + function() require('sidekick.cli').send({ msg = '{this}' }) end, + { desc = 'Send This' } +) +vim.keymap.set( + 'x', + 'av', + function() require('sidekick.cli').send({ msg = '{selection}' }) end, + { desc = 'Send Visual Selection' } +) +vim.keymap.set( + { 'n', 'x' }, + 'ap', + function() require('sidekick.cli').prompt() end, + { desc = 'Sidekick Select Prompt' } +) +vim.keymap.set( + { 'n', 'x', 'i', 't' }, + '', + function() require('sidekick.cli').focus() end, + { desc = 'Sidekick Switch Focus' } +) +vim.keymap.set( + 'n', + 'ac', + function() require('sidekick.cli').toggle({ name = 'claude', focus = true }) end, + { desc = 'Sidekick Toggle Claude' } +) + +vim.api.nvim_create_autocmd('VimEnter', { + once = true, + callback = function() + require('sidekick').setup({ + cli = { + mux = { + enabled = true, + create = 'terminal', + backend = 'tmux', + }, + tools = {}, + }, + }) + end, +}) + +-- fzf-lua {{{ + +local has_bat = vim.fn.executable('bat') == 1 + or vim.fn.executable('batcat') == 1 +local has_delta = vim.fn.executable('delta') == 1 + +local function open_files_in_cwd(cwd) + if type(cwd) == 'string' and vim.fn.isdirectory(cwd) == 1 then + require('fzf-lua').files({ cwd = cwd }) + else + require('fzf-lua').files() + end +end + +require('fzf-lua').setup({ + winopts = { + split = 'botright new', + preview = { + default = has_bat and 'bat' or 'builtin', + scrollbar = 'float', + }, + }, + fzf_opts = { ['--info'] = 'default' }, + files = { + rg_opts = [[--color=never --files --hidden -g "!.git"]], + fd_opts = [[--color=never --type f --type l --hidden --exclude .git]], + }, + grep = { + rg_opts = '--column --line-number --no-heading --color=always --smart-case --max-columns=4096 --hidden -e', + }, + keymap = { + builtin = { + [''] = 'toggle-preview', + [''] = 'preview-page-down', + [''] = 'preview-page-up', + }, + fzf = { + ['esc'] = 'abort', + ['ctrl-q'] = 'select-all+accept', + }, + }, + git = { + status = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' or nil, + }, + commits = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' or nil, + }, + bcommits = { + preview_pager = has_delta and 'delta --width=$FZF_PREVIEW_COLUMNS' or nil, + }, + }, +}) + +vim.keymap.set( + 'n', + '', + 'FzfLua git_files', + { desc = 'fzf: git files' } +) +vim.keymap.set( + 'n', + 'ff', + 'FzfLua files', + { desc = 'fzf: git files' } +) +-- vim.keymap.set('n', 'ff', function() +-- local ok = vim.fn.systemlist('git rev-parse --is-inside-work-tree 2>/dev/null')[1] +-- if ok == 'true' then require('fzf-lua').git_files({ show_untracked = true }) +-- else require('fzf-lua').files() end +-- end, { desc = 'fzf: find files' }) +vim.keymap.set( + 'n', + 'fa', + 'FzfLua', + { desc = 'fzf: all builtins' } +) +vim.keymap.set( + 'n', + 'fb', + 'FzfLua grep_curbuf', + { desc = 'fzf: current buffer' } +) +vim.keymap.set( + 'n', + 'fr', + 'FzfLua resume', + { desc = 'fzf: resume' } +) +vim.keymap.set( + 'n', + 'fo', + 'FzfLua buffers', + { desc = 'fzf: open buffers' } +) +vim.keymap.set( + 'n', + 'fh', + 'FzfLua oldfiles', + { desc = 'fzf: recent files' } +) +vim.keymap.set( + 'n', + 'fs', + 'FzfLua live_grep', + { desc = 'fzf: live grep' } +) +vim.keymap.set('n', 'fw', function() + local word = vim.fn.expand('') + if word == '' then return end + vim.cmd('silent grep! ' .. word) +end, { desc = 'grep word under cursor → qf' }) +vim.keymap.set('n', 'fW', function() + local word = vim.fn.expand('') + if word == '' then return end + vim.cmd('silent grep! ' .. word) +end, { desc = 'grep WORD under cursor → qf' }) +vim.keymap.set('n', 'fS', function() + local word = vim.fn.input('rg> ') + if word == '' then return end + vim.cmd('silent grep! ' .. word) +end, { desc = 'ripgrep prompt → qf' }) +vim.keymap.set( + 'n', + 'f?', + 'FzfLua help_tags', + { desc = 'fzf: help' } +) +vim.keymap.set( + 'n', + 'fva', + 'FzfLua autocmds', + { desc = 'fzf: autocmds' } +) +vim.keymap.set( + 'n', + 'fvh', + 'FzfLua highlights', + { desc = 'fzf: highlights' } +) +vim.keymap.set( + 'n', + 'fvk', + 'FzfLua keymaps', + { desc = 'fzf: keymaps' } +) +vim.keymap.set( + 'n', + 'fle', + 'FzfLua diagnostics_workspace', + { desc = 'fzf: diagnostics' } +) +vim.keymap.set( + 'n', + 'fld', + 'FzfLua lsp_document_symbols', + { desc = 'fzf: document symbols' } +) +vim.keymap.set( + 'n', + 'fls', + 'FzfLua lsp_live_workspace_symbols', + { desc = 'fzf: workspace symbols' } +) +vim.keymap.set( + 'n', + 'fgb', + 'FzfLua git_branches', + { desc = 'fzf: git branches' } +) +vim.keymap.set( + 'n', + 'fgs', + 'FzfLua git_status', + { desc = 'fzf: git status' } +) +vim.keymap.set( + 'n', + 'fgc', + 'FzfLua git_commits', + { desc = 'fzf: git commits' } +) +vim.keymap.set( + 'n', + 'fgB', + 'FzfLua git_bcommits', + { desc = 'fzf: buffer commits' } +) +vim.keymap.set( + 'n', + 'p', + 'FzfLua registers', + { desc = 'fzf: registers' } +) +vim.keymap.set( + 'n', + 'fd', + function() open_files_in_cwd(vim.g.dotfiles) end, + { desc = 'fzf: dotfiles' } +) +vim.keymap.set( + 'n', + 'fp', + function() open_files_in_cwd(vim.g.projects_directory) end, + { desc = 'fzf: projects' } +) +vim.keymap.set( + 'n', + 'fc', + function() open_files_in_cwd(vim.g.vim_dir) end, + { desc = 'fzf: nvim config' } +) +vim.keymap.set('n', 'f.', function() + local name = vim.api.nvim_buf_get_name(0) + local dir = name ~= '' and vim.fn.fnamemodify(name, ':p:h') or vim.loop.cwd() + open_files_in_cwd(dir) +end, { desc = 'fzf: current file dir' }) + +-- }}} + +-- Gitsigns {{{ + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlGitsigns', { clear = true }), + callback = function() + require('gitsigns').setup({ + signs = { + add = { text = '▎' }, + change = { text = '▎' }, + delete = { text = '▎' }, + topdelete = { text = '▎' }, + changedelete = { text = '▎' }, + untracked = { text = '░' }, + }, + on_attach = function(bufnr) + local gs = require('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', ']c', function() + if vim.wo.diff then + vim.cmd.normal({ ']c', bang = true }) + else + gs.nav_hunk('next') + end + end, { desc = 'Next git change' }) + map('n', '[c', function() + if vim.wo.diff then + vim.cmd.normal({ '[c', bang = true }) + else + gs.nav_hunk('prev') + end + end, { desc = 'Prev git change' }) + + -- Hunk actions + map( + 'v', + 'hs', + function() gs.stage_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, + { desc = '[git] Stage hunk' } + ) + map( + 'v', + 'hr', + function() gs.reset_hunk({ vim.fn.line('.'), vim.fn.line('v') }) end, + { desc = '[git] Reset hunk' } + ) + map('n', 'hs', gs.stage_hunk, { desc = '[git] Stage hunk' }) + map('n', 'hr', gs.reset_hunk, { desc = '[git] Reset hunk' }) + map('n', 'hS', gs.stage_buffer, { desc = '[git] Stage buffer' }) + map( + 'n', + 'hu', + gs.undo_stage_hunk, + { desc = '[git] Undo stage hunk' } + ) + map('n', 'hR', gs.reset_buffer, { desc = '[git] Reset buffer' }) + map('n', 'hp', gs.preview_hunk, { desc = '[git] Preview hunk' }) + map('n', 'hb', gs.blame_line, { desc = '[git] Blame line' }) + map('n', 'hd', gs.diffthis, { desc = '[git] Diff index' }) + map( + 'n', + 'hD', + function() gs.diffthis('@') end, + { desc = '[git] Diff last commit' } + ) + + -- Toggles + map( + 'n', + 'tb', + gs.toggle_current_line_blame, + { desc = '[git] Toggle blame line' } + ) + map( + 'n', + 'tD', + gs.toggle_deleted, + { desc = '[git] Toggle deleted' } + ) + end, + }) + end, +}) + +-- }}} + +-- Fugitive {{{ + +vim.api.nvim_create_autocmd('DirChanged', { + group = vim.api.nvim_create_augroup( + 'FugitiveWorktreeDetect', + { clear = true } + ), + callback = function() vim.fn.FugitiveDetect(vim.fn.getcwd()) end, +}) + +vim.keymap.set('n', 'gs', function() + local cur_common = vim.fn.FugitiveCommonDir(vim.api.nvim_get_current_buf()) + if cur_common == '' then + vim.cmd('tab Git') + return + end + for _, tabnr in ipairs(vim.api.nvim_list_tabpages()) do + for _, winnr in ipairs(vim.api.nvim_tabpage_list_wins(tabnr)) do + local buf = vim.api.nvim_win_get_buf(winnr) + local name = vim.api.nvim_buf_get_name(buf) + if name:match('^fugitive://') then + local tab_common = vim.fn.FugitiveCommonDir(buf) + if tab_common ~= '' and tab_common == cur_common then + vim.api.nvim_set_current_tabpage(tabnr) + return + end + end + end + end + vim.cmd('tab Git') +end, { desc = '[git] Status' }) + +vim.keymap.set( + 'n', + 'g-', + function() require('gitsigns').blame_line() end, + { desc = '[git] Blame line' } +) +vim.keymap.set( + 'n', + 'gB', + 'Git blame', + { desc = '[git] Blame' } +) +vim.keymap.set( + 'n', + 'gb', + 'FzfLua git_branches', + { desc = '[git] Checkout branch' } +) +vim.keymap.set( + 'n', + 'gc', + 'FzfLua git_commits', + { desc = '[git] Checkout commit' } +) +vim.keymap.set( + 'n', + 'gC', + 'FzfLua git_bcommits', + { desc = '[git] Checkout commit (current file)' } +) +vim.keymap.set( + 'n', + 'gf', + 'Git fetch --all', + { desc = '[git] Fetch all branches' } +) +vim.keymap.set( + 'n', + 'gj', + function() require('gitsigns').next_hunk() end, + { desc = '[git] Next hunk' } +) +vim.keymap.set( + 'n', + 'gk', + function() require('gitsigns').prev_hunk() end, + { desc = '[git] Prev hunk' } +) +vim.keymap.set( + 'n', + 'gh', + 'diffget //2', + { desc = '[git] Get diff from left' } +) +vim.keymap.set( + 'n', + 'gH', + '0Gclog', + { desc = '[git] History for current file' } +) +vim.keymap.set( + 'n', + 'gl', + 'diffget //3', + { desc = '[git] Get diff from right' } +) +vim.keymap.set('n', 'gP', 'Git push', { desc = '[git] Push' }) +vim.keymap.set( + 'n', + 'gp', + 'Git pull --rebase', + { desc = '[git] Pull rebase' } +) +vim.keymap.set( + 'n', + 'gt', + ':Git push -u origin ', + { desc = '[git] Set target branch' } +) + +-- }}} + +-- Oil {{{ + +require('oil').setup({ + default_file_explorer = true, + delete_to_trash = true, + skip_confirm_for_simple_edits = true, + view_options = { + show_hidden = true, + }, + win_options = { + wrap = false, + signcolumn = 'no', + cursorcolumn = false, + foldcolumn = '0', + spell = false, + list = false, + conceallevel = 3, + concealcursor = 'nvic', + }, + keymaps = { + [''] = false, -- free up for tmux + [''] = false, -- free up for tmux + }, +}) + +vim.keymap.set('n', '-', 'Oil', { desc = 'Open parent directory' }) + +-- }}} + +-- Mason {{{ + +require('mason').setup({ + ui = { border = 'rounded', width = 0.8, height = 0.8 }, +}) + +require('mason-tool-installer').setup({ + ensure_installed = { + -- LSP servers + 'lua-language-server', + 'basedpyright', + 'ruff', + 'typescript-language-server', + 'texlab', + 'vim-language-server', + -- Formatters + 'stylua', + 'prettier', + 'prettierd', + 'black', + 'isort', + 'shfmt', + -- Linters + 'eslint_d', + 'flake8', + 'mypy', + 'luacheck', + 'hadolint', + 'jsonlint', + 'vale', + 'tflint', + -- Other + 'debugpy', + 'sonarlint-language-server', + }, + auto_update = false, + run_on_start = true, +}) + +-- }}} + +-- LSP {{{ + +-- Rounded borders on all LSP floats +do + local orig = vim.lsp.util.open_floating_preview + ---@diagnostic disable-next-line: duplicate-set-field + function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) + opts = opts or {} + opts.border = opts.border or 'rounded' + local bufnr, winnr = orig(contents, syntax, opts, ...) + if winnr and vim.api.nvim_win_is_valid(winnr) then + vim.wo[winnr].statuscolumn = '' + vim.wo[winnr].signcolumn = 'no' + vim.wo[winnr].foldcolumn = '0' + vim.wo[winnr].number = false + vim.wo[winnr].relativenumber = false + vim.wo[winnr].winhighlight = + 'Normal:BlinkCmpDoc,FloatBorder:BlinkCmpDocBorder' + vim.wo[winnr].wrap = false + vim.wo[winnr].colorcolumn = '' + end + return bufnr, winnr + end +end + +local function _with_border(handler) + return function(err, result, ctx, config) + config = vim.tbl_extend('force', config or {}, { border = 'rounded' }) + return handler(err, result, ctx, config) + end +end +vim.lsp.handlers['textDocument/hover'] = + _with_border(vim.lsp.handlers['textDocument/hover']) +vim.lsp.handlers['textDocument/signatureHelp'] = + _with_border(vim.lsp.handlers['textDocument/signatureHelp']) + +-- Capabilities (blink.cmp injects its extras) +local _lsp_caps = require('blink.cmp').get_lsp_capabilities( + vim.lsp.protocol.make_client_capabilities() +) +_lsp_caps.workspace = _lsp_caps.workspace or {} +_lsp_caps.workspace.didChangeWatchedFiles = { dynamicRegistration = false } + +-- Server configurations +vim.lsp.config('lua_ls', { + cmd = { 'lua-language-server' }, + filetypes = { 'lua' }, + root_dir = function(_, cb) cb(vim.fn.getcwd()) end, + capabilities = _lsp_caps, + settings = { + Lua = { + runtime = { version = 'LuaJIT' }, + workspace = { + checkThirdParty = false, + library = vim.api.nvim_get_runtime_file('', true), + }, + diagnostics = { globals = { 'vim' } }, + completion = { callSnippet = 'Replace' }, + }, + }, +}) + +vim.lsp.config('basedpyright', { + cmd = { 'basedpyright-langserver', '--stdio' }, + filetypes = { 'python' }, + root_dir = function(_, cb) cb(vim.fn.getcwd()) end, + capabilities = _lsp_caps, + on_attach = function(client, _) + client.server_capabilities.diagnosticProvider = false -- ruff owns diagnostics + end, + settings = { + python = { + analysis = { + typeCheckingMode = 'off', + autoSearchPaths = true, + useLibraryCodeForTypes = true, + }, + }, + basedpyright = { disableOrganizeImports = true }, + }, +}) + +vim.lsp.config('ruff', { + cmd = { 'ruff', 'server' }, + filetypes = { 'python' }, + root_dir = function(_, cb) cb(vim.fn.getcwd()) end, + capabilities = _lsp_caps, +}) + +vim.lsp.config('ts_ls', { + cmd = { 'typescript-language-server', '--stdio' }, + filetypes = { + 'javascript', + 'javascriptreact', + 'typescript', + 'typescriptreact', + }, + root_dir = function(_, cb) cb(vim.fn.getcwd()) end, + capabilities = _lsp_caps, +}) + +vim.lsp.config('texlab', { + cmd = { 'texlab' }, + filetypes = { 'tex', 'plaintex', 'bib' }, + root_dir = function(_, cb) cb(vim.fn.getcwd()) end, + capabilities = _lsp_caps, + settings = { + texlab = { + build = { onSave = true }, + chktex = { onOpenAndSave = true }, + }, + }, +}) + +vim.lsp.config('vimls', { + cmd = { 'vim-language-server', '--stdio' }, + filetypes = { 'vim' }, + root_dir = vim.fn.getcwd, + capabilities = _lsp_caps, + initializationOptions = { isNeovim = true }, +}) + +vim.lsp.enable({ + 'lua_ls', + 'basedpyright', + 'ruff', + 'ts_ls', + 'texlab', + 'vimls', + 'copilot', +}) + +-- Per-buffer keymaps on attach +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('mrl_lsp_attach', { clear = true }), + callback = function(event) + if vim.b[event.buf].lsp_keymaps_attached then return end + vim.b[event.buf].lsp_keymaps_attached = true + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client.server_capabilities.documentSymbolProvider then + require('nvim-navic').attach(client, event.buf) + end + local map = function(keys, func, desc) + vim.keymap.set( + 'n', + keys, + func, + { buffer = event.buf, desc = 'LSP: ' .. desc } + ) + end + map('gh', vim.lsp.buf.hover, 'hover docs') + local function scroll_hover(delta) + local float = T.find( + function(w) return vim.api.nvim_win_get_config(w).relative ~= '' end, + vim.api.nvim_list_wins() + ) + if float then + vim.api.nvim_win_call( + float, + function() vim.api.nvim_feedkeys(delta, 'n', false) end + ) + end + end + -- map('', function() scroll_hover(vim.api.nvim_replace_termcodes('', true, false, true)) end, 'scroll hover down') + -- map('', function() scroll_hover(vim.api.nvim_replace_termcodes('', true, false, true)) end, 'scroll hover up') + map('gd', vim.lsp.buf.definition, 'goto definition') + map('gD', vim.lsp.buf.declaration, 'goto declaration') + map('gr', vim.lsp.buf.references, 'references') + map('gy', vim.lsp.buf.type_definition, 'type definition') + map('gm', vim.lsp.buf.implementation, 'implementation') + vim.keymap.set('n', 'rn', function() + return ':IncRename ' .. vim.fn.expand('') + end, { expr = true, silent = false, buffer = event.buf, desc = 'rename' }) + map('ca', vim.lsp.buf.code_action, 'code action') + map( + 'th', + function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) end, + 'toggle inlay hints' + ) + end, +}) + +vim.api.nvim_create_autocmd('LspDetach', { + group = vim.api.nvim_create_augroup('mrl_lsp_detach', { clear = true }), + callback = function(event) vim.lsp.buf.clear_references() end, +}) + +-- }}} + +-- Fidget {{{ + +require('fidget').setup({}) + +-- }}} + +-- Tiny inline diagnostic {{{ + +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlTinyInlineDiag', { clear = true }), + callback = function() + require('tiny-inline-diagnostic').setup({ + preset = 'simple', + transparent_bg = false, + hi = { + error = 'DiagnosticError', + warn = 'DiagnosticWarn', + info = 'DiagnosticInfo', + hint = 'DiagnosticHint', + arrow = 'NonText', + background = 'CursorLine', + mixing_color = 'None', + }, + options = { + show_source = true, + use_icons_from_diagnostic = false, + add_messages = true, + throttle = 100, + softwrap = 30, + multilines = { enabled = false, always_show = false }, + show_all_diags_on_cursorline = false, + enable_on_insert = false, + overflow = { mode = 'wrap', padding = 0 }, + virt_texts = { priority = 2048 }, + severity = { + vim.diagnostic.severity.ERROR, + vim.diagnostic.severity.WARN, + vim.diagnostic.severity.INFO, + vim.diagnostic.severity.HINT, + }, + }, + }) + end, +}) + +-- }}} + +-- Lightbulb {{{ + +vim.api.nvim_create_autocmd('LspAttach', { + once = true, + group = vim.api.nvim_create_augroup('MrlLightbulb', { clear = true }), + callback = function() + require('nvim-lightbulb').setup({ + autocmd = { enabled = true }, + sign = { enabled = false }, + virtual_text = { + enabled = true, + text = _icons.misc.lightbulb, + hl = 'DiagnosticWarn', + }, + }) + end, +}) + +-- }}} + +-- Inc-rename {{{ + +require('inc_rename').setup({ + hl_group = 'Visual', + preview_empty_name = true, +}) + +-- }}} + +-- Undotree {{{ + +vim.g.undotree_TreeNodeShape = '◉' +vim.g.undotree_SetFocusWhenToggle = 1 + +vim.keymap.set('n', 'u', 'UndotreeToggle', { desc = 'undotree: toggle' }) + +-- }}} + +-- Indent blankline {{{ + +vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlIndentBlankline', { clear = true }), + callback = function() + require('ibl').setup({ + indent = { char = '┊' }, + scope = { enabled = false }, + }) + end, +}) + +-- }}} + +-- Rainbow delimiters {{{ + +vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlRainbowDelimiters', { clear = true }), + callback = function() + local ok, rainbow_delimiters = pcall(require, 'rainbow-delimiters') + if not ok then return end + local rd = vim.g.rainbow_delimiters or {} + rd.strategy = { [''] = rainbow_delimiters.strategy['global'] } + rd.query = { [''] = 'rainbow-delimiters' } + vim.g.rainbow_delimiters = rd + end, +}) + +-- }}} + +-- Debug {{{ + +vim.keymap.set('n', '', function() require('dap').continue() end, { desc = 'debug: continue' }) +vim.keymap.set('n', '', function() require('dap').step_into() end, { desc = 'debug: step into' }) +vim.keymap.set('n', '', function() require('dap').step_over() end, { desc = 'debug: step over' }) +vim.keymap.set('n', '', function() require('dap').step_out() end, { desc = 'debug: step out' }) +vim.keymap.set('n', 'db', function() require('dap').toggle_breakpoint() end, { desc = 'debug: toggle breakpoint' }) +vim.keymap.set('n', '', function() require('dapui').toggle() end, { desc = 'debug: toggle UI' }) + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlDebug', { clear = true }), + callback = function() + local dap = require('dap') + local dapui = require('dapui') + + dap.adapters.python = { + type = 'executable', + command = vim.fn.stdpath('data') .. '/mason/packages/debugpy/venv/bin/python', + args = { '-m', 'debugpy.adapter' }, + } + dap.configurations.python = { + { + type = 'python', + request = 'launch', + name = 'Launch file', + program = '${file}', + pythonPath = function() + local venv = os.getenv('VIRTUAL_ENV') or os.getenv('CONDA_PREFIX') + if venv then return venv .. '/bin/python' end + return vim.fn.exepath('python3') or 'python' + end, + }, + } + + dapui.setup({ + icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, + controls = { + icons = { + pause = '', play = '', step_into = '󱆭', + step_over = '', step_out = '󰙣', run_last = '󰙡', + terminate = '', disconnect = '', + }, + }, + }) + + 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 + end, +}) + +-- }}} + +-- Testing {{{ + +local function nt() return require('neotest') end +vim.keymap.set('n', 'ts', function() nt().summary.toggle() end, { desc = 'neotest: summary' }) +vim.keymap.set('n', 'to', function() nt().output.open({ enter = true }) end, { desc = 'neotest: output' }) +vim.keymap.set('n', 'tn', function() nt().run.run() end, { desc = 'neotest: run nearest' }) +vim.keymap.set('n', 'tf', function() nt().run.run(vim.fn.expand('%')) end, { desc = 'neotest: run file' }) +vim.keymap.set('n', 'tc', function() nt().run.stop() end, { desc = 'neotest: cancel' }) +vim.keymap.set('n', '[n', function() nt().jump.prev({ status = 'failed' }) end, { desc = 'prev failed test' }) +vim.keymap.set('n', ']n', function() nt().jump.next({ status = 'failed' }) end, { desc = 'next failed test' }) + +vim.api.nvim_create_autocmd({ 'BufReadPre', 'BufNewFile' }, { + once = true, + group = vim.api.nvim_create_augroup('MrlNeotest', { clear = true }), + callback = function() + vim.cmd.packadd('plenary.nvim') + require('neotest').setup({ + discovery = { enabled = true }, + diagnostic = { enabled = true }, + floating = { border = 'rounded' }, + quickfix = { enabled = false }, + adapters = { + require('neotest-python')({ runner = 'pytest' }), + }, + }) + end, +}) + +-- }}} + +-- Formatting {{{ + +local _conform = require('conform') + +_conform.setup({ + notify_on_error = true, + format_on_save = function(bufnr) + if vim.g.disable_autoformat or vim.g.formatting_disabled then return nil end + if vim.b[bufnr] and vim.b[bufnr].formatting_disabled then return nil end + local disable_filetypes = + { c = true, cpp = true, xml = true, cnk = true, map = true } + return { + timeout_ms = 5000, + lsp_format = disable_filetypes[vim.bo[bufnr].filetype] and 'never' + or 'fallback', + } + end, + default_format_opts = { lsp_format = 'fallback' }, + formatters_by_ft = { + bash = { 'shfmt' }, + javascript = { 'prettier' }, + typescript = { 'prettier' }, + javascriptreact = { 'prettier' }, + typescriptreact = { 'prettier' }, + css = { 'prettier' }, + html = { 'prettier' }, + json = { 'prettier' }, + jsonc = { 'prettier' }, + yaml = { 'prettier' }, + markdown = { 'prettier' }, + graphql = { 'prettier' }, + lua = { 'stylua' }, + python = { 'isort', 'black' }, + }, + formatters = { + shfmt = { prepend_args = { '-i', '2' } }, + }, +}) + +T.command('Format', function(args) + local range = nil + if args.count ~= -1 then + local end_line = + vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1] + range = + { start = { args.line1, 0 }, ['end'] = { args.line2, end_line:len() } } + end + _conform.format({ async = true, lsp_format = 'fallback', range = range }) +end, { range = true }) + +T.command( + 'FormatDisable', + function() vim.g.disable_autoformat = true end, + { desc = 'Disable autoformat-on-save' } +) +T.command( + 'FormatEnable', + function() vim.g.disable_autoformat = false end, + { desc = 'Enable autoformat-on-save' } +) + +-- }}} + +-- Linting {{{ + +do + local lint = require('lint') + local _fn = vim.fn + + local function _exe(cmd) + return type(cmd) == 'string' and cmd ~= '' and _fn.executable(cmd) == 1 + end + + local function _can_lint(bufnr) + if not vim.api.nvim_buf_is_valid(bufnr) then return false end + if vim.bo[bufnr].buftype ~= '' then return false end + local ft = vim.bo[bufnr].filetype or '' + if ft == '' or ft:match('^fugitive') or ft == 'diff' then return false end + local names = lint.linters_by_ft[ft] + if type(names) ~= 'table' or #names == 0 then return false end + for _, name in ipairs(names) do + local linter = lint.linters[name] + local cmd = linter and (linter.cmd or linter.command) + if _exe(cmd) then return true end + end + return false + end + + lint.linters_by_ft = { + javascript = { 'eslint_d' }, + typescript = { 'eslint_d' }, + javascriptreact = { 'eslint_d' }, + typescriptreact = { 'eslint_d' }, + python = { 'flake8', 'mypy' }, + lua = _exe('luacheck') and { 'luacheck' } or nil, + dockerfile = { 'hadolint' }, + json = { 'jsonlint' }, + markdown = { 'vale' }, + rst = { 'vale' }, + text = { 'vale' }, + ruby = { 'ruby' }, + terraform = { 'tflint' }, + } + + -- Guard: ensure linter tables exist so nvim-lint doesn't error on missing tools + lint.linters.flake8 = lint.linters.flake8 or {} + lint.linters.mypy = lint.linters.mypy or {} + lint.linters.eslint_d = lint.linters.eslint_d or {} + lint.linters.luacheck = lint.linters.luacheck or {} + + vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, { + group = vim.api.nvim_create_augroup('MrlLint', { clear = true }), + callback = function(args) + if not _can_lint(args.buf) then return end + pcall(lint.try_lint) + end, + }) +end + +vim.keymap.set( + 'n', + 'll', + function() require('lint').try_lint() end, + { desc = 'lint current buffer' } +) + +-- }}} +-- }}} +------------------------------------------------------------------------------- + +-- SonarLint {{{ + +vim.api.nvim_create_autocmd('FileType', { + pattern = { + 'python', + 'javascript', + 'typescript', + 'java', + 'go', + 'html', + 'xml', + }, + once = true, + group = vim.api.nvim_create_augroup('MrlSonarqube', { clear = true }), + callback = function() + if vim.fn.executable('java') ~= 1 then return end + local ext = vim.fn.stdpath('data') + .. '/mason/packages/sonarlint-language-server/extension' + if vim.fn.isdirectory(ext) == 0 then return end + local a = ext .. '/analyzers/' + require('sonarqube').setup({ + lsp = { + cmd = { + vim.fn.exepath('java'), + '-jar', + ext .. '/server/sonarlint-ls.jar', + '-stdio', + '-analyzers', + a .. 'sonargo.jar', + a .. 'sonarhtml.jar', + a .. 'sonariac.jar', + a .. 'sonarjava.jar', + a .. 'sonarjavasymbolicexecution.jar', + a .. 'sonarjs.jar', + a .. 'sonarphp.jar', + a .. 'sonarpython.jar', + a .. 'sonartext.jar', + a .. 'sonarxml.jar', + }, + }, + python = { enabled = true }, + javascript = { enabled = true }, + typescript = { enabled = true }, + }) + end, +}) + +-- }}} + +-- Navic breadcrumb {{{ + +local function get_navic_breadcrumb(bufnr) + local ok, navic = pcall(require, 'nvim-navic') + if not ok then return nil end + if not navic.is_available(bufnr) then return nil end + local location = navic.get_location({}, bufnr) + if not location or location == '' then return nil end + local parts = {} + for content in location:gmatch('%%#[^#]*#([^%%]*)%%%*') do + local text = content:match('^%s*(.-)%s*$') + if text and text ~= '' and text:match('^[%w_]+$') and #text > 1 then + table.insert(parts, text) + end + end + if #parts == 0 then return nil end + return { + { + { ' :: ', 'StFaded' }, + { table.concat(parts, ' › '), 'StFaded' }, + { ' ', 'StSeparator' }, + }, + priority = 4, + } +end + +-- }}} + +------------------------------------------------------------------------------- +-- Plugins plugins/ +------------------------------------------------------------------------------- + +-- Last place {{{ + +vim.api.nvim_create_autocmd({ 'BufWinEnter', 'FileType' }, { + group = vim.api.nvim_create_augroup('LastPlace', { clear = true }), + callback = function() + local ignore_buftype = { 'quickfix', 'nofile', 'help', 'terminal' } + local ignore_filetype = { 'gitcommit', 'gitrebase', 'svn', 'hgcommit' } + + if vim.tbl_contains(ignore_buftype, vim.bo.buftype) then return end + if vim.tbl_contains(ignore_filetype, vim.bo.filetype) then + vim.cmd('normal! gg') + return + end + + if vim.fn.line('.') > 1 then return end + + local last_line = vim.fn.line([['"]]) + local buff_last_line = vim.fn.line('$') + + if last_line > 0 and last_line <= buff_last_line then + local win_last_line = vim.fn.line('w$') + local win_first_line = vim.fn.line('w0') + if win_last_line == buff_last_line then + vim.cmd('normal! g`"') + elseif + buff_last_line - last_line + > ((win_last_line - win_first_line) / 2) - 1 + then + vim.cmd('normal! g`"zz') + else + vim.cmd([[normal! G'"]]) + end + end + end, +}) + +-- }}} + +-- Project root {{{ + +local _root_names = { + '.git', + 'Makefile', + 'go.mod', + 'go.sum', + 'package.json', + 'pyproject.toml', + 'requirements.txt', + 'Cargo.toml', + 'composer.json', +} +local _root_cache = {} +local _root_cache_max = 100 + +local function _get_lsp_root(buf) + local clients = vim.lsp.get_clients({ bufnr = buf }) + if not next(clients) then return end + for _, client in pairs(clients) do + local filetypes = client.config.filetypes + if filetypes and vim.tbl_contains(filetypes, vim.bo[buf].ft) then + return client.config.root_dir, client.name + end + end +end + +vim.api.nvim_create_autocmd('BufEnter', { + group = vim.api.nvim_create_augroup('FindProjectRoot', { clear = true }), + callback = function(args) + local path = vim.api.nvim_buf_get_name(args.buf) + if path == '' then return end + path = vim.fs.dirname(path) + + local root = _root_cache[path] + if not root then + local root_file = + vim.fs.find(_root_names, { path = path, upward = true })[1] + root = vim.fs.dirname(root_file) or _get_lsp_root(args.buf) + end + if not root or not path then return end + if vim.tbl_count(_root_cache) >= _root_cache_max then _root_cache = {} end + _root_cache[path] = root + if root == vim.fn.getcwd() then return end + vim.fn.chdir(root) + end, +}) + +-- }}} + +------------------------------------------------------------------------------- +-- Autocommands {{{ + +-- Yank highlight +T.augroup('YankHighlight', { + event = 'TextYankPost', + desc = 'Highlight when yanking text', + command = function() vim.highlight.on_yank() end, +}) + +-- Smart hlsearch: clear when cursor moves off the match +local function _stop_hl() + if vim.v.hlsearch == 0 or api.nvim_get_mode().mode ~= 'n' then return end + vim.cmd('nohlsearch') +end + +local function _hl_search() + local col = api.nvim_win_get_cursor(0)[2] + local curr_line = api.nvim_get_current_line() + local ok, match = pcall(fn.matchstrpos, curr_line, fn.getreg('/'), 0) + if not ok then return end + local _, p_start, p_end = unpack(match) + if col < p_start or col > p_end then _stop_hl() end +end + +T.augroup('IncSearchHighlight', { + event = 'CursorMoved', + command = _hl_search, +}, { + event = 'InsertEnter', + command = _stop_hl, +}, { + event = 'OptionSet', + pattern = 'hlsearch', + command = function() + vim.schedule(function() cmd.redrawstatus() end) + end, +}, { + event = 'RecordingEnter', + command = function() + vim.o.hlsearch = false + vim.g.macro_recording = 'macro @' .. fn.reg_recording() + vim.cmd('redrawstatus') + end, +}, { + event = 'RecordingLeave', + command = function() + vim.o.hlsearch = true + vim.g.macro_recording = '' + vim.cmd('redrawstatus') + end, +}) + +-- Equalise windows on resize +T.augroup('UpdateVim', { + event = 'VimResized', + pattern = '*', + command = 'wincmd =', +}) + +-- Disable columns in floating windows and tool panels +do + local _no_col_fts = { + 'lazy', + 'mason', + 'noice', + 'notify', + 'trouble', + 'aerial', + 'dap-repl', + 'dapui_console', + 'dapui_watches', + 'dapui_stacks', + 'dapui_breakpoints', + 'dapui_scopes', + } + + local function _no_cols(win) + vim.wo[win].statuscolumn = '' + vim.wo[win].signcolumn = 'no' + vim.wo[win].foldcolumn = '0' + end + + T.augroup('DisableColumnsInFloats', { + event = 'WinEnter', + command = function() + local win = api.nvim_get_current_win() + if api.nvim_win_get_config(win).relative ~= '' then _no_cols(win) end + end, + }, { + event = 'FileType', + pattern = _no_col_fts, + command = function() + local win = api.nvim_get_current_win() + _no_cols(win) + vim.opt_local.number = false + vim.opt_local.relativenumber = false + end, + }) +end + +-- Sidebar panels: strip line numbers and remap highlights +T.augroup('SidebarPanelHighlights', { + event = 'FileType', + pattern = { + 'undotree', + 'diff', + 'Outline', + 'dbui', + 'neotest-summary', + 'fugitive', + 'AvanteSidebar', + 'AvanteInput', + 'Avante', + 'AvanteSelectedFiles', + }, + command = function() + vim.opt_local.number = false + vim.opt_local.relativenumber = false + vim.opt_local.winhighlight:append({ + Normal = 'PanelDarkBackground', + EndOfBuffer = 'PanelDarkBackground', + SignColumn = 'PanelDarkBackground', + WinSeparator = 'PanelWinSeparator', + }) + end, +}) + +-- Cursorline only in the active window +T.augroup('AutoCursorline', { + event = { 'InsertLeave', 'WinEnter' }, + command = function() + if vim.w.auto_cursorline then + vim.wo.cursorline = true + vim.w.auto_cursorline = nil + end + end, +}, { + event = { 'InsertEnter', 'WinLeave' }, + command = function() + if vim.wo.cursorline then + vim.w.auto_cursorline = true + vim.wo.cursorline = false + end + end, +}) + +-- Auto-create parent dirs on save +T.augroup('AutoCreateDir', { + event = 'BufWritePre', + command = function(event) + if event.match:match('^%w%w+:[\\/][\\/]') then return end + local file = vim.uv.fs_realpath(event.match) or event.match + fn.mkdir(fn.fnamemodify(file, ':p:h'), 'p') + end, +}) + +-- Reload file when it changes on disk +T.augroup('CheckAutoReload', { + event = { 'FocusGained', 'TermClose', 'TermLeave' }, + command = function() + if vim.o.buftype ~= 'nofile' then vim.cmd('checktime') end + end, +}) + +-- Formatting guardrail: disable formatting in third-party/runtime code +do + local function _startswith(s, prefix) + return type(s) == 'string' + and type(prefix) == 'string' + and prefix ~= '' + and s:sub(1, #prefix) == prefix + end + + local function _should_disable(bufnr) + if not api.nvim_buf_is_valid(bufnr) then return false end + if vim.bo[bufnr].buftype ~= '' then return false end + if not vim.bo[bufnr].modifiable then return false end + if vim.bo[bufnr].filetype == '' then return false end + local path = api.nvim_buf_get_name(bufnr) + if path == '' then return false end + + local allow = { + vim.g.personal_directory, + vim.g.work_directory, + vim.g.dotfiles, + vim.g.vim_dir, + vim.env.HOME, + } + for _, p in ipairs(allow) do + if p and _startswith(path, p) then + if p ~= vim.env.HOME then return false end + end + end + + if vim.env.VIMRUNTIME and _startswith(path, vim.env.VIMRUNTIME) then + return true + end + + for _, dir in ipairs(vim.split(vim.o.runtimepath, ',', { plain = true })) do + if dir ~= '' and _startswith(path, dir) then + if vim.g.vim_dir and _startswith(path, vim.g.vim_dir) then + return false + end + return true + end + end + return false + end + + T.augroup('FormattingGuardrail', { + event = 'BufEnter', + command = function(args) + vim.b[args.buf].formatting_disabled = _should_disable(args.buf) + end, + }) +end + +-- }}} + +------------------------------------------------------------------------------- +-- Keymaps {{{ lua/keymaps.lua +------------------------------------------------------------------------------- + +-- Quickfix and Location List {{{ + +local list = { qf = {}, loc = {} } + +local silence = { mods = { silent = true, emsg_silent = true } } + +local function is_list_open(list_type) + for _, win in ipairs(vim.fn.getwininfo()) do + if win[list_type] ~= 0 then return true end + end + return false +end + +local function preserve_window(callback, ...) + local win = vim.api.nvim_get_current_win() + callback(...) + if win ~= vim.api.nvim_get_current_win() then vim.cmd.wincmd('p') end +end + +-- Auto-size the list window: clamp between 3 and 10 lines. +local function autosize_list(items) + local h = math.max(3, math.min(#items, 10)) + vim.api.nvim_win_set_height(0, h) +end + +function list.qf.toggle() + if is_list_open('quickfix') then + vim.cmd.cclose(silence) + else + local items = vim.fn.getqflist() + if #items > 0 then + preserve_window(function() + vim.cmd.copen(silence) + autosize_list(items) + end) + end + end +end + +function list.loc.toggle() + if is_list_open('loclist') then + vim.cmd.lclose(silence) + else + local items = vim.fn.getloclist(0) + if #items > 0 then + preserve_window(function() + vim.cmd.lopen(silence) + autosize_list(items) + end) + end + end +end + +function list.qf.delete(buf) + buf = buf or vim.api.nvim_get_current_buf() + local qflist = vim.fn.getqflist() + local line = vim.api.nvim_win_get_cursor(0)[1] + local mode = vim.api.nvim_get_mode().mode + if mode:match('[vV]') then + local first_line = vim.fn.getpos("'<")[2] + local last_line = vim.fn.getpos("'>")[2] + local filtered = {} + for i, item in ipairs(qflist) do + if i < first_line or i > last_line then filtered[#filtered + 1] = item end + end + qflist = filtered + else + table.remove(qflist, line) + end + vim.fn.setqflist({}, 'r', { items = qflist }) + vim.fn.setpos('.', { buf, line, 1, 0 }) +end + +-- }}} + +-- Quickfix formatter {{{ +do + local home = vim.env.HOME + local limit = 31 + local fname_fmt1 = '%-' .. limit .. 's' + local fname_fmt2 = '…%.' .. (limit - 1) .. 's' + local valid_fmt = '%s │%5d:%-3d│%s %s' + local type_icons = { + E = _icons.lsp.error .. ' ', + W = _icons.lsp.warn .. ' ', + I = _icons.lsp.info .. ' ', + N = _icons.lsp.hint .. ' ', + } + + function _G.qftf(info) + local items + local ret = {} + if info.quickfix == 1 then + items = vim.fn.getqflist({ id = info.id, items = 0 }).items + else + items = vim.fn.getloclist(info.winid, { id = info.id, items = 0 }).items + end + for i = info.start_idx, info.end_idx do + local e = items[i] + local str + if e.valid == 1 then + local fname = '' + if e.bufnr > 0 then + fname = vim.fn.bufname(e.bufnr) + if fname == '' then + fname = '[No Name]' + else + fname = fname:gsub('^' .. home, '~') + fname = vim.fn.pathshorten(fname) + end + local w = vim.api.nvim_strwidth(fname) + if w <= limit then + fname = fname_fmt1:format(fname) + else + fname = fname_fmt2:format(fname:sub(1 - limit)) + end + end + local lnum = e.lnum > 99999 and -1 or e.lnum + local col = e.col > 999 and -1 or e.col + local qtype = type_icons[e.type:sub(1, 1):upper()] + or (e.type ~= '' and ' ' .. e.type:sub(1, 1):upper() or '') + str = valid_fmt:format(fname, lnum, col, qtype, e.text) + else + str = e.text + end + table.insert(ret, str) + end + return ret + end +end + +vim.o.qftf = '{info -> v:lua._G.qftf(info)}' +-- }}} + +vim.keymap.set( + 'n', + 'g>', + [[set nomore40messagesset more]], + { desc = 'show message history' } +) +vim.keymap.set( + 'n', + '', + [[@=(foldlevel('.')?'za':"\")]], + { desc = 'toggle fold under cursor' } +) +vim.keymap.set('n', 'z', [[zMzvzz]], { desc = 'center viewport' }) +vim.keymap.set('n', 'zO', [[zCzO]]) + +-- Buffers +vim.keymap.set( + 'n', + 'on', + [[w %bd e#]], + { desc = 'close all other buffers' } +) +vim.keymap.set( + 'n', + '', + [[:b ]], + { silent = false, desc = 'open buffer list' } +) + +-- Windows +vim.keymap.set( + 'n', + 'wh', + 't K', + { desc = 'change horizontal splits to vertical' } +) +vim.keymap.set( + 'n', + 'wv', + 't H', + { desc = 'change vertical splits to horizontal' } +) +vim.keymap.set( + 'n', + 'f', + 'vgf', + { desc = 'open file in vertical split' } +) + +-- New files +vim.keymap.set( + 'n', + 'nf', + [[:e =expand("%:p:h") . "/" ]], + { silent = false, desc = 'new file in same directory' } +) +vim.keymap.set( + 'n', + 'ns', + [[:vsp =expand("%:p:h") . "/" ]], + { silent = false, desc = 'vertical split new file in same directory' } +) + +-- Save / quit +vim.keymap.set('n', '', 'silent! write ++p') +vim.keymap.set('n', 'qa', 'qa') + +-- Quickfix / loclist nav +vim.keymap.set('n', ']q', 'cnextzz') +vim.keymap.set('n', '[q', 'cprevzz') +vim.keymap.set('n', ']l', 'lnextzz') +vim.keymap.set('n', '[l', 'lprevzz') + +-- Tab navigation +vim.keymap.set('n', 'tn', 'tabedit %') +vim.keymap.set('n', 'tc', 'tabclose') +vim.keymap.set('n', 'to', 'tabonly') +vim.keymap.set('n', 'tm', 'tabmove') +vim.keymap.set('n', ']t', 'tabprev') +vim.keymap.set('n', '[t', 'tabnext') + +-- Entire buffer text object +vim.keymap.set('x', 'ie', [[gg0oG$]]) + +-- Smart center +vim.keymap.set( + 'n', + 'zz', + [[(winline() == (winheight(0) + 1)/ 2) ? 'zt' : (winline() == 1)? 'zb' : 'zz']], + { expr = true } +) + +-- Open common config files +vim.keymap.set( + 'n', + 'ev', + [[edit $MYVIMRC]], + { desc = 'open $VIMRC' } +) +vim.keymap.set( + 'n', + 'ez', + 'edit $ZDOTDIR/.zshrc', + { desc = 'open zshrc' } +) +vim.keymap.set( + 'n', + 'et', + 'edit $XDG_CONFIG_HOME/tmux/tmux.conf', + { desc = 'edit tmux.conf' } +) +vim.keymap.set( + 'n', + 'sv', + [[source $MYVIMRC :lua vim.notify('Sourced init.vim')]], + { desc = 'source $VIMRC' } +) + +vim.keymap.set('n', 'pU', function() + -- Auto-accept the confirmation buffer that vim.pack.update opens + vim.api.nvim_create_autocmd('BufAdd', { + once = true, + pattern = 'nvim-pack://confirm#*', + callback = function(ev) + vim.schedule(function() + if vim.api.nvim_buf_is_valid(ev.buf) then + vim.api.nvim_buf_call(ev.buf, function() vim.cmd('write') end) + end + end) + end, + }) + vim.pack.update(nil, { summary = true }) +end, { desc = 'pack: update all plugins (auto-accept)' }) + +-- Quote surrounds +vim.keymap.set( + 'n', + [["]], + [[ciw"""]], + { desc = 'surround with double quotes' } +) +vim.keymap.set( + 'n', + '`', + [[ciw`"`]], + { desc = 'surround with backticks' } +) +vim.keymap.set( + 'n', + "'", + [[ciw'"']], + { desc = 'surround with single quotes' } +) +vim.keymap.set( + 'n', + ')', + [[ciw(")]], + { desc = 'surround with parentheses' } +) +vim.keymap.set( + 'n', + '}', + [[ciw{"}]], + { desc = 'surround with curly braces' } +) + +-- gx: open URL or github link +local function open(path) + fn.jobstart({ vim.g.open_command, path }, { detach = true }) + vim.notify(fmt('Opening %s', path)) +end + +vim.keymap.set('n', 'gx', function() + local file = fn.expand('') + if not file or fn.isdirectory(file) > 0 then return vim.cmd.edit(file) end + if file:match('http[s]?://') then return open(file) end + local link = file:match('[%a%d%-%.%_]*%/[%a%d%-%.%_]*') + if link then return open(fmt('https://www.github.com/%s', link)) end +end) + +vim.keymap.set('n', 'gf', 'e ') + +-- Quickfix / loclist toggles +vim.keymap.set('n', '', list.qf.toggle, { desc = 'toggle quickfix list' }) +vim.keymap.set('n', '', list.loc.toggle, { desc = 'toggle location list' }) + +-- Tab / shift-tab cycle completion menu (normal mode only — blink owns insert mode) +vim.keymap.set( + 'i', + '', + [[pumvisible() ? "\" : "\"]], + { expr = true } +) +vim.keymap.set( + 'i', + '', + [[pumvisible() ? "\" : "\"]], + { expr = true } +) + +-- Commands +cmd.cabbrev('options', 'vert options') + +-- :Grep / :LGrep — rg into quickfix/loclist (for bulk ops; use live_grep for exploration) +T.command( + 'Grep', + function(o) vim.cmd('silent grep! ' .. o.args) end, + { nargs = '+', complete = 'file_in_path', bar = true } +) +T.command( + 'LGrep', + function(o) vim.cmd('silent lgrep! ' .. o.args) end, + { nargs = '+', complete = 'file_in_path', bar = true } +) + +vim.api.nvim_create_autocmd('QuickFixCmdPost', { + group = vim.api.nvim_create_augroup('grep_qf', { clear = true }), + pattern = { 'grep', 'grep!', 'Grep' }, + callback = function() list.qf.toggle() end, +}) +vim.api.nvim_create_autocmd('QuickFixCmdPost', { + group = vim.api.nvim_create_augroup('grep_lf', { clear = true }), + pattern = { 'lgrep', 'lgrep!', 'LGrep' }, + callback = function() list.loc.toggle() end, +}) + +T.command( + 'ToggleBackground', + function() vim.o.background = vim.o.background == 'dark' and 'light' or 'dark' end +) + +T.command('Todo', [[noautocmd silent! grep! 'TODO\|FIXME\|BUG\|HACK' | copen]]) + +T.command( + 'MoveWrite', + [[,write | ,delete _]], + { + nargs = 1, + bang = true, + range = true, + complete = 'file', + } +) + +T.command( + 'MoveAppend', + [[,write >> | ,delete _]], + { + nargs = 1, + bang = true, + range = true, + complete = 'file', + } +) + +T.command( + 'Reverse', + ',g/^/m-1', + { range = '%', bar = true } +) + +T.command('Exrc', function() + local cwd = fn.getcwd() + local p1 = ('%s/.nvim.lua'):format(cwd) + local p2 = ('%s/.nvimrc'):format(cwd) + local path = vim.loop.fs_stat(p1) and p1 or vim.loop.fs_stat(p2) and p2 + if not path then + local fh, err = io.open(p1, 'w') + if err then + vim.notify( + 'Cannot create ' .. p1 .. ': ' .. err, + vim.log.levels.ERROR, + { title = 'Exrc' } + ) + return + end + fh:close() + path = p1 + end + local ok, err = pcall(vim.cmd.edit, path) + if not ok then + vim.notify(err, vim.log.levels.ERROR, { title = 'Exrc Opener' }) + end +end) + +T.command('ClearRegisters', function() + local regs = + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-' + for r in regs:gmatch('.') do + fn.setreg(r, {}) + end +end) + +-- Toggle keymaps +vim.keymap.set( + 'n', + 'Ob', + 'ToggleBackground', + { desc = 'toggle background' } +) +vim.keymap.set('n', 'Ow', function() + vim.wo.wrap = not vim.wo.wrap + vim.notify('wrap ' .. (vim.o.wrap and 'on' or 'off')) +end, { desc = 'toggle wrap' }) +vim.keymap.set( + 'n', + 'Tc', + 'ClearRegisters', + { desc = 'clear registers' } +) +vim.keymap.set( + 'n', + 'Tr', + 'Reverse', + { desc = 'reverse buffer' } +) +vim.keymap.set('n', '', 'Todo', { desc = 'todo search' }) + +-- Editing +vim.keymap.set('n', 'U', 'gUiw`]', { desc = 'capitalize word' }) +vim.keymap.set('v', '.', ':norm.') +vim.keymap.set('n', 'J', 'mzJ`z') +vim.keymap.set('v', 'J', ":m '>+1gv=gv") +vim.keymap.set('v', 'K', ":m '<-2gv=gv") +vim.cmd( + [[nnoremap S :keeppatterns substitute/\s*\%#\s*/\r/e normal! ==]] +) + +-- Motion +vim.keymap.set({ 'n', 'v' }, 'j', 'gj', { desc = 'move down by display line' }) +vim.keymap.set({ 'n', 'v' }, 'k', 'gk', { desc = 'move up by display line' }) +vim.keymap.set('n', '', 'zz') +vim.keymap.set('n', '', 'zz') +vim.keymap.set('n', 'n', 'nzzzv') +vim.keymap.set('n', 'N', 'Nzzzv') +vim.keymap.set('n', "'", '`') + +-- Clipboard +vim.keymap.set({ 'n', 'v' }, 'y', [["+y]]) +vim.keymap.set('n', 'Y', [["+Y]]) +vim.keymap.set({ 'n', 'v' }, 'd', [["_d]]) + +-- LSP / format +vim.keymap.set( + 'n', + 'lf', + 'Format', + { desc = 'format current buffer' } +) + +-- Clear search highlight +vim.keymap.set('n', '', function() + vim.cmd('nohlsearch') + vim.v.hlsearch = false +end, { desc = 'clear highlight' }) + +-- Diagnostics +vim.keymap.set( + 'n', + '[d', + vim.diagnostic.goto_prev, + { desc = 'prev diagnostic' } +) +vim.keymap.set( + 'n', + ']d', + vim.diagnostic.goto_next, + { desc = 'next diagnostic' } +) +vim.keymap.set( + 'n', + '[D', + function() vim.diagnostic.goto_prev({ count = 999999, wrap = false }) end, + { desc = 'first diagnostic' } +) +vim.keymap.set( + 'n', + ']D', + function() vim.diagnostic.goto_next({ count = 999999, wrap = false }) end, + { desc = 'last diagnostic' } +) +vim.keymap.set( + 'n', + 'se', + vim.diagnostic.open_float, + { desc = 'show diagnostic float' } +) +vim.keymap.set( + 'n', + 'ls', + vim.diagnostic.open_float, + { desc = 'show diagnostic float' } +) + +-- Terminal +vim.keymap.set( + 't', + '', + '', + { desc = 'exit terminal mode' } +) + +-- Buffer navigation +vim.keymap.set('n', '', ':bnext', { noremap = true, silent = true }) +vim.keymap.set( + 'n', + '', + ':bprevious', + { noremap = true, silent = true } +) +vim.keymap.set('n', '', ':bnext', { noremap = true, silent = true }) +vim.keymap.set( + 'n', + '', + ':bprevious', + { noremap = true, silent = true } +) + +-- Splits +vim.keymap.set('n', '|', 'vsp', { desc = 'vertical split' }) +vim.keymap.set('n', '-', 'sp', { desc = 'horizontal split' }) + +-- Resize with arrows +vim.keymap.set('n', '', ':resize -2', { silent = true }) +vim.keymap.set('n', '', ':resize +2', { silent = true }) +vim.keymap.set('n', '', ':vertical resize -2', { silent = true }) +vim.keymap.set('n', '', ':vertical resize +2', { silent = true }) + +-- Visual indent / paste +vim.keymap.set('x', '<', '', '>gv', { desc = 'indent right' }) +vim.keymap.set('x', 'p', 'pgvy') +vim.keymap.set( + 'v', + 'p', + '"_dP', + { desc = 'paste without overwriting clipboard' } +) + +-- Buffer management +vim.keymap.set('n', 'bo', ':only', { desc = 'buffer only' }) +vim.keymap.set( + 'n', + 'bD', + ':bd!', + { desc = 'force delete buffer' } +) +vim.keymap.set( + 'n', + 'z', + '%bdelete', + { desc = 'close all buffers' } +) +vim.keymap.set( + 'n', + 'Z', + '%bdelete!', + { desc = 'force close all buffers' } +) +vim.keymap.set('n', 'q', ':q', { desc = 'quit' }) +vim.keymap.set('n', 'Q', 'q!', { desc = 'force quit' }) + +-- }}} -------------------------------------------------------------------------------- --- Load modules {{{ + +-------------------------------------------------------------------------------- +-- Statusline {{{ -------------------------------------------------------------------------------- -require('tools') -- has to be loaded before plugins (bootstraps ui, strings, colors) -require('keymaps') -require('options') -require('packloader') +do + -- ── Rendering primitives ───────────────────────────────────────────── + + local CLICK_END = '%X' + + local function sl_separator() + return { component = '%=', length = 0, priority = 0 } + end + + local function sl_get_click_start(func_name, id) + if not id then + vim.schedule( + function() + vim.notify_once( + fmt('An ID is needed to enable click handler %s', func_name), + vim.log.levels.ERROR, + { title = 'Statusline' } + ) + end + ) + return '' + end + return ('%%%d@%s@'):format(id, func_name) + end + + local function sl_normalize_chunks(chunks) + if type(chunks) ~= 'table' then return end + if vim.islist(chunks) then return chunks end + local keys = {} + for k in pairs(chunks) do + if type(k) == 'number' and k >= 1 and math.floor(k) == k then + keys[#keys + 1] = k + end + end + if #keys == 0 then return end + table.sort(keys) + local dense = {} + for _, k in ipairs(keys) do + local v = chunks[k] + if v ~= nil then dense[#dense + 1] = v end + end + return dense + end + + local function sl_truncate_string(str, max_size) + if not max_size or api.nvim_strwidth(str) < max_size then return str end + local match, count = str:gsub('([\'"]).*%1', '%1…%1') + return count > 0 and match or str:sub(1, max_size - 1) .. '…' + end + + local function sl_chunks_to_string(chunks) + chunks = sl_normalize_chunks(chunks) + if not chunks then return '' end + local strings = {} + for _, item in ipairs(chunks) do + local text, hl = unpack(item) + if not T.falsy(text) then + if type(text) ~= 'string' then text = tostring(text) end + if item.max_size then text = sl_truncate_string(text, item.max_size) end + text = text:gsub('%%', '%%%1') + strings[#strings + 1] = not T.falsy(hl) + and ('%%#%s#%s%%*'):format(hl, text) + or text + end + end + return table.concat(strings, '') + end + + local function sl_component(opts) + assert(opts, 'component options are required') + if opts.cond ~= nil and T.falsy(opts.cond) then return end + local item = sl_normalize_chunks(opts[1]) + if not item then + error( + fmt( + 'component options are required but got %s instead', + vim.inspect(opts[1]) + ) + ) + end + if not opts.priority then opts.priority = 10 end + local item_str = sl_chunks_to_string(item) + if #item_str == 0 then return end + local click_start = opts.click + and sl_get_click_start(opts.click, tostring(opts.id)) + or '' + local click_end = opts.click and CLICK_END or '' + local component_str = click_start .. item_str .. click_end + return { + component = component_str, + length = api.nvim_eval_statusline(component_str, { maxwidth = 0 }).width, + priority = opts.priority, + } + end + + local function sl_sum_lengths(list) + return T.fold( + function(acc, item) return acc + (item.length or 0) end, + list, + 0 + ) + end + + local function sl_is_lowest(item, lowest) + if not lowest or not lowest.length then return true end + if not item.priority or not item.length then return false end + if item.priority == lowest.priority then + return item.length > lowest.length + end + return item.priority > lowest.priority + end + + local function sl_prioritize(statusline, space, length) + length = length or sl_sum_lengths(statusline) + if length <= space then return statusline end + local lowest, idx_rm + for idx, c in ipairs(statusline) do + if sl_is_lowest(c, lowest) then + lowest, idx_rm = c, idx + end + end + table.remove(statusline, idx_rm) + return sl_prioritize(statusline, space, length - lowest.length) + end + + local section = {} + function section:new(...) + local o = { ... } + self.__index = self + self.__add = function(l, r) + local rt = { unpack(l) } + for _, v in ipairs(r) do + rt[#rt + 1] = v + end + return rt + end + return setmetatable(o, self) + end + + local function display(sections, available_space) + local components = T.fold(function(acc, sec, count) + if #sec == 0 then + table.insert(acc, sl_separator()) + return acc + end + T.foreach(function(args, index) + if not args then return end + local ok, str = T.pcall('Error creating component', sl_component, args) + if not ok then return end + table.insert(acc, str) + if #sec == index and count ~= #sections then + table.insert(acc, sl_separator()) + end + end, sec) + return acc + end, sections) + local items = available_space and sl_prioritize(components, available_space) + or components + local strs = vim.tbl_map(function(item) return item.component end, items) + return table.concat(strs) + end + + -- ── Minimal-mode detection ──────────────────────────────────────────── + + local _minimal_ft = T.p_table({ + ['startuptime'] = true, + ['checkhealth'] = true, + ['log'] = true, + ['help'] = true, + ['^copilot.*'] = true, + ['dbout'] = true, + ['dbui'] = true, + ['minimap'] = true, + ['Trouble'] = true, + ['tsplayground'] = true, + ['list'] = true, + ['netrw'] = true, + ['NvimTree'] = true, + ['neo-tree'] = true, + ['undotree'] = true, + ['dap-repl'] = true, + ['neotest.*'] = true, + ['DiffviewFiles'] = true, + ['toggleterm'] = true, + ['org'] = true, + ['norg'] = true, + ['markdown'] = true, + ['gitcommit'] = true, + ['fzf'] = true, + ['fzf-lua'] = true, + ['noice'] = true, + }) + local _minimal_bt = + { quickfix = true, nofile = true, nowrite = true, terminal = true } + + local function is_plain(ctx) + if ctx.filetype == 'fzf' then return false end + return ( + _minimal_ft[ctx.filetype] + or _minimal_bt[ctx.buftype] + or ctx.preview + ) == true + end + + -- ── State & helpers ─────────────────────────────────────────────────── + + _G.Stl = {} + local _stl_state = { lsp_clients_visible = false } + local LSP_COMPONENT_ID = 2000 + local space = ' ' + local _sep = package.config:sub(1, 1) + + local _stl_ft_icon = T.p_table({ + ['fzf'] = '󱁴', + ['fzf-lua'] = '󱁴', + ['log'] = '', + ['org'] = '', + ['mail'] = '', + ['dbui'] = '', + ['DiffviewFiles'] = '', + ['Trouble'] = '', + ['norg'] = '', + ['help'] = '', + ['undotree'] = '󰔱', + ['NvimTree'] = '󰔱', + ['neo-tree'] = '󰔱', + ['neotest.*'] = '', + ['dapui_.*'] = '', + ['dap-repl'] = '', + ['toggleterm'] = '', + ['Avante.*'] = _icons.misc.chat, + }) + + local _stl_names = T.p_table({ + ['fzf'] = 'FZF', + ['fzf-lua'] = 'FZF', + ['orgagenda'] = 'Org', + ['mail'] = 'Mail', + ['dbui'] = 'Dadbod UI', + ['tsplayground'] = 'Treesitter', + ['Trouble'] = 'Lsp Trouble', + ['gitcommit'] = 'Git commit', + ['help'] = 'help', + ['undotree'] = 'UndoTree', + ['NvimTree'] = 'Nvim Tree', + ['dap-repl'] = 'Debugger REPL', + ['Diffview.*'] = 'Diff view', + ['neotest.*'] = 'Testing', + ['Avante.*'] = 'avante', + ['log'] = function(fname) return fmt('Log(%s)', vim.fs.basename(fname)) end, + ['dapui_.*'] = function(fname) return fname end, + ['neo-tree'] = function(fname) + local parts = vim.split(fname, ' ') + return fmt('Explorer(%s)', parts[2]) + end, + }) + + -- ── Terminal display name (cached 1 s) ──────────────────────────────── + + local function _trim(s) + return type(s) == 'string' and (s:gsub('^%s+', ''):gsub('%s+$', '')) or '' + end + local function _sysline(c) + local ok, out = pcall(fn.systemlist, c) + return (ok and out and out[1]) and _trim(out[1]) or '' + end + + local function _tmux_server_args(pid) + local args = _trim(_sysline({ 'ps', '-o', 'args=', '-p', tostring(pid) })) + local result = {} + local sock, label = args:match('%-S%s+(%S+)'), args:match('%-L%s+(%S+)') + if sock then + result[#result + 1] = '-S' + result[#result + 1] = sock + elseif label then + result[#result + 1] = '-L' + result[#result + 1] = label + end + return result + end + + local function _tmux_pane_cmd(tmux_args, client_pid) + tmux_args = tmux_args or {} + local base = vim.list_extend({ 'tmux' }, tmux_args) + local clients = fn.systemlist(vim.list_extend(vim.deepcopy(base), { + 'list-clients', + '-F', + '#{client_pid}\t#{client_name}', + })) + if type(clients) ~= 'table' then return '' end + local name + for _, line in ipairs(clients) do + local cpid, cname = line:match('^(%d+)\t([^\t]*)$') + if cpid and tonumber(cpid) == client_pid then + name = cname + break + end + end + if not name and #clients == 1 then + local _, cname = clients[1]:match('^(%d+)\t([^\t]*)$') + name = cname + end + if not name or name == '' then return '' end + return _sysline(vim.list_extend(vim.deepcopy(base), { + 'display-message', + '-p', + '-t', + name, + '#{pane_current_command}', + })) + end + + local function _term_display_name(buf) + local cached = vim.b[buf].mrl_term_display + local now = (vim.uv and vim.uv.now and vim.uv.now()) or 0 + if + type(cached) == 'table' + and type(cached.value) == 'string' + and now > 0 + and (now - (cached.ts or 0)) < 1000 + then + return cached.value + end + local job = vim.b[buf].terminal_job_id or vim.bo[buf].channel + local pid = 0 + local jid = tonumber(job) + if jid and jid > 0 then + local ok, p = pcall(fn.jobpid, jid) + if ok and type(p) == 'number' and p > 0 then pid = p end + end + local comm = pid > 0 + and _sysline({ 'ps', '-o', 'comm=', '-p', tostring(pid) }) + or '' + local value = comm ~= '' and comm + or fn.fnamemodify(vim.env.SHELL or '', ':t') + if type(value) == 'string' and value:match('^tmux') and pid > 0 then + value = 'tmux' + local pane = _tmux_pane_cmd(_tmux_server_args(pid), pid) + if pane ~= '' then value = pane end + end + vim.b[buf].mrl_term_display = { value = value, ts = now } + return value + end + + -- ── Special buffer label ────────────────────────────────────────────── + + local function _special_buf(ctx) + if ctx.preview then return 'preview' end + if ctx.buftype == 'quickfix' then return 'Quickfix List' end + if ctx.filetype == 'fzf' or (ctx.bufname and ctx.bufname:match('^fzf')) then + return 'FZF' + end + if + ctx.filetype == 'AvanteInput' + or ctx.filetype == 'AvanteSelectedFiles' + or ctx.filetype == 'Avante' + then + return 'Avante' + end + if ctx.buftype == 'terminal' then + return ('Terminal(%s)'):format(_term_display_name(ctx.bufnum)) + end + if fn.getloclist(0, { filewinid = 0 }).filewinid > 0 then + return 'Location List' + end + return nil + end + + -- ── Filename decomposition ──────────────────────────────────────────── + + local function _with_sep(path) + return (not T.falsy(path) and path:sub(-1) ~= _sep) and path .. _sep or path + end + + local function _dir_env(directory) + if not directory then return '', '' end + local paths = { + [vim.g.dotfiles] = '$DOTFILES', + [vim.g.personal_directory .. 'dotfiles'] = '$DOTFILES', + [vim.g.work_directory] = '$WORK', + [vim.env.VIMRUNTIME] = '$VIMRUNTIME', + [vim.g.projects_directory] = '$WORKSPACES', + [vim.g.obsidian] = '$OBSIDIAN', + [vim.env.HOME] = '~', + } + local result, env, prev = directory, '', '' + for dir, alias in pairs(paths) do + if dir then + local match, count = + vim.fs.normalize(directory):gsub(vim.pesc(_with_sep(dir)), '') + if count == 1 and #dir > #prev then + result, env, prev = match, alias, dir + end + end + end + return result, env + end + + local function _get_ft_icon(buf) + local path = api.nvim_buf_get_name(buf) + if fn.isdirectory(path) == 1 then return '', nil end + local ok, devicons = pcall(require, 'nvim-web-devicons') + if not ok then return '', nil end + local name, ext = fn.fnamemodify(path, ':t'), fn.fnamemodify(path, ':e') + return devicons.get_icon(name, ext, { default = true }) + end + + local _bt_icon = { terminal = '', quickfix = '󰁨' } + + local function _filetype_icon(ctx) + return _stl_ft_icon[ctx.filetype] + or _bt_icon[ctx.buftype] + or _get_ft_icon(ctx.bufnum) + end + + local function _filename(ctx) + local special = _special_buf(ctx) + if special then return { fname = special } end + local path = api.nvim_buf_get_name(ctx.bufnum) + if T.falsy(path) then return { fname = '' } end + local parts = vim.split(path, _sep) + local fname = table.remove(parts) + local name = _stl_names[ctx.filetype] + if name then + return { + fname = vim.is_callable(name) and name(fname, ctx.bufnum) or name, + } + end + local parent = table.remove(parts) + fname = fn.isdirectory(fname) == 1 and fname .. _sep or fname + if T.falsy(parent) then return { fname = fname } end + local dir = _with_sep(table.concat(parts, _sep)) + local new_dir, env = _dir_env(dir) + local max_dir_width = math.floor(vim.o.columns / 3) + if api.nvim_strwidth(env .. new_dir) > max_dir_width then + new_dir = fn.pathshorten(new_dir) + end + return { + env = _with_sep(env), + dir = _with_sep(new_dir), + parent = _with_sep(parent), + fname = fname, + } + end + + local function _stl_file(ctx) + local ft_icon = _filetype_icon(ctx) + local file_opts = { {}, before = '', after = ' ', priority = 0 } + local parent_opts = { {}, before = '', after = '', priority = 2 } + local dir_opts = { {}, before = '', after = '', priority = 3 } + local env_opts = { {}, before = '', after = '', priority = 4 } + local p = _filename(ctx) + local env_empty, dir_empty, parent_empty = + T.falsy(p.env), T.falsy(p.dir), T.falsy(p.parent) + local to_update = (env_empty and dir_empty and parent_empty) and file_opts + or (env_empty and dir_empty) and parent_opts + or env_empty and dir_opts + or env_opts + table.insert(to_update[1], { ' ' .. ft_icon .. ' ', 'StTitle' }) + table.insert(env_opts[1], { p.env or '', 'StEnv' }) + table.insert(dir_opts[1], { p.dir or '', 'StDirectory' }) + table.insert(file_opts[1], { p.fname or '', 'StFilename' }) + table.insert(parent_opts[1], { p.parent or '', 'StParent' }) + return { + env = env_opts, + file = file_opts, + dir = dir_opts, + parent = parent_opts, + } + end + + -- ── Diagnostics ─────────────────────────────────────────────────────── + + local function _diagnostics(buf) + local sev = vim.diagnostic.severity + local icons = _icons.lsp + local result = { + error = { count = 0, icon = icons.error }, + warn = { count = 0, icon = icons.warn }, + info = { count = 0, icon = icons.info }, + hint = { count = 0, icon = icons.hint }, + } + for _, item in ipairs(vim.diagnostic.get(buf)) do + local s = sev[item.severity]:lower() + result[s].count = result[s].count + 1 + end + return result + end + + -- ── Search count ────────────────────────────────────────────────────── + + local function _search_count() + local ok, r = pcall(fn.searchcount, { recompute = 1 }) + if not ok or vim.tbl_isempty(r) then return '' end + if r.incomplete == 1 then return ' ?/?? ' end + if r.incomplete == 2 then + if r.total > r.maxcount and r.current > r.maxcount then + return fmt(' >%d/>%d ', r.current, r.total) + elseif r.total > r.maxcount then + return fmt(' %d/>%d ', r.current, r.total) + end + end + return fmt(' %d/%d ', r.current, r.total) + end + + -- ── LSP clients ─────────────────────────────────────────────────────── + + function Stl.lsp_client_click() + _stl_state.lsp_clients_visible = not _stl_state.lsp_clients_visible + vim.cmd('redrawstatus') + end + + local function _lsp_clients(ctx) + local clients = vim.lsp.get_clients({ bufnr = ctx.bufnum }) or {} + if #clients == 0 then return false, {} end + local has_copilot = false + local names = {} + for _, client in ipairs(clients) do + local name = client.name or '' + if name == 'copilot' or name:match('copilot') then + has_copilot = true + else + table.insert(names, name) + end + end + table.sort(names) + return has_copilot, names + end + + -- ── Git update timer ────────────────────────────────────────────────── + + local function _update_git_status() + local cwd = fn.getcwd() + if not (cwd and vim.uv.fs_stat(cwd .. '/.git')) then return end + local result = {} + fn.jobstart('git rev-list --count --left-right @{upstream}...HEAD', { + stdout_buffered = true, + on_stdout = function(_, data) + for _, item in ipairs(data) do + if item and item ~= '' then result[#result + 1] = item end + end + end, + on_exit = function(_, code) + if code == 0 and result[1] then + local parts = vim.split(result[1], '\t') + if #parts == 2 then + vim.g.git_statusline_updates = + { behind = parts[1], ahead = parts[2] } + end + end + end, + }) + end + + local function _git_updates() + local timer = vim.uv.new_timer() + if not timer then return end + local pending + local fail = timer:start( + 0, + 10000, + vim.schedule_wrap(function() + if pending then fn.jobstop(pending) end + pending = _update_git_status() + end) + ) + if fail ~= 0 then + vim.schedule( + function() + vim.notify( + 'Failed to start git update timer: ' .. fail, + vim.log.levels.WARN + ) + end + ) + end + end + + -- Render {{{ + + function Stl.render() + local curwin = api.nvim_get_current_win() + local curbuf = api.nvim_win_get_buf(curwin) + local available = vim.o.columns + + local ctx = { + bufnum = curbuf, + win = curwin, + bufname = api.nvim_buf_get_name(curbuf), + preview = vim.wo[curwin].previewwindow, + readonly = vim.bo[curbuf].readonly, + filetype = vim.bo[curbuf].ft, + buftype = vim.bo[curbuf].bt, + modified = vim.bo[curbuf].modified, + shiftwidth = vim.bo[curbuf].shiftwidth, + expandtab = vim.bo[curbuf].expandtab, + } + + local plain = is_plain(ctx) + local focused = vim.g.vim_in_focus ~= false + local path = _stl_file(ctx) + + local l1 = section:new({ + { { '' .. vim.g.dev_environ .. '', 'StDevEnv' } }, + priority = 1, + cond = true, + }) + + if plain or not focused then + local l2 = section:new( + { { { ctx.readonly and ' ' or '', 'StFaded' } }, priority = 1 }, + path.env, + path.dir, + path.parent, + path.file + ) + return display({ l1 + l2 }, available) + end + + local lnum, col = unpack(api.nvim_win_get_cursor(curwin)) + col = col + 1 + local line_count = api.nvim_buf_line_count(curbuf) + local status = vim.b[curbuf].gitsigns_status_dict or {} + local updates = vim.g.git_statusline_updates or {} + local ahead = updates.ahead and tonumber(updates.ahead) or 0 + local behind = updates.behind and tonumber(updates.behind) or 0 + local diag = _diagnostics(curbuf) + local has_copilot, lsp_names = _lsp_clients(ctx) + local lsp_count = #lsp_names + + local lsp_components = { + { + { + { space, 'StSeparator' }, + has_copilot and { _icons.misc.copilot .. space, 'StTitle' } or nil, + { space, 'StSeparator' }, + { _icons.misc.puzzle, 'StTitle' }, + { space, 'StSeparator' }, + { tostring(lsp_count), 'StFaded' }, + { space, 'StSeparator' }, + }, + priority = 2, + id = LSP_COMPONENT_ID, + click = 'v:lua.Stl.lsp_client_click', + }, + } + if _stl_state.lsp_clients_visible and lsp_count > 0 then + table.insert(lsp_components, { + { + { space, 'StSeparator' }, + { table.concat(lsp_names, ', '), 'StFaded' }, + }, + priority = 9, + }) + end + + -- Left + local l2 = section:new( + { + { { ' ' .. _icons.misc.pencil, 'StFaded' }, { space, 'StSeparator' } }, + cond = ctx.modified, + priority = 1, + }, + { + { { _search_count(), 'StSearchCount' } }, + cond = vim.v.hlsearch > 0, + priority = 1, + }, + path.env, + path.dir, + path.parent, + path.file, + -- get_navic_breadcrumb(ctx.bufnum), + { + { + { space, 'StSeparator' }, + }, + cond = true, + priority = 1, + }, + { + { + { diag.warn.icon, 'StWarn' }, + { space, 'StSeparator' }, + { diag.warn.count .. ' ', 'StWarn' }, + }, + cond = diag.warn.count > 0, + priority = 3, + }, + { + { + { diag.error.icon, 'StError' }, + { space, 'StSeparator' }, + { diag.error.count .. ' ', 'StError' }, + }, + cond = diag.error.count > 0, + priority = 1, + }, + { + { + { diag.info.icon, 'StInfo' }, + { space, 'StSeparator' }, + { diag.info.count .. ' ', 'StInfo' }, + }, + cond = diag.info.count > 0, + priority = 3, + }, + { + { { _icons.misc.shaded_lock, 'StFaded' } }, + cond = vim.b[ctx.bufnum].formatting_disabled == true + or vim.g.formatting_disabled == true, + priority = 5, + }, + { { { space, 'StSeparator' } }, cond = true, priority = 1 } + ) + + -- Middle (macro recording) + local m1 = section:new({ + { { vim.g.macro_recording or '', 'StWarn' } }, + priority = 1, + }) + + -- Right + local r1 = section:new( + { { { space, 'StSeparator' } }, priority = 3, cond = true }, + unpack(lsp_components) + ) + + local r2 = section:new({ + { + { _icons.git.branch, 'StTitle' }, + { space, 'StSeparator' }, + { status.head, 'StBranch' }, + { space, 'StSeparator' }, + }, + priority = 1, + cond = not T.falsy(status.head), + }, { + { + { _icons.git.mod, 'StGitModified' }, + { space, 'StGitModified' }, + { status.changed, 'StTitle' }, + { space, 'StSeparator' }, + }, + priority = 5, + cond = not T.falsy(status.changed), + }, { + { + { _icons.git.remove, 'StGitDelete' }, + { space, 'StGitDelete' }, + { status.removed, 'StTitle' }, + { space, 'StSeparator' }, + }, + priority = 5, + cond = not T.falsy(status.removed), + }, { + { + { _icons.git.add, 'StGitAdd' }, + { space, 'StGitAdd' }, + { status.added, 'StTitle' }, + { space, 'StSeparator' }, + }, + priority = 5, + cond = not T.falsy(status.added), + }, { + { + { _icons.misc.up, 'StGitAdd' }, + { space, 'StSeparator' }, + { ahead, 'StTitle' }, + }, + cond = ahead > 0, + before = '', + priority = 5, + }, { + { + { _icons.misc.down, 'StGitDelete' }, + { space, 'StSeparator' }, + { behind, 'StTitle' }, + }, + cond = behind > 0, + after = ' ', + priority = 5, + }, { + { + { space, 'StSeparator' }, + { lnum .. ':' .. col, 'StTitle' }, + { space, 'StSeparator' }, + { fmt('%d', 100 * lnum / line_count) .. '%', 'StFaded' }, + { space, 'StSeparator' }, + }, + priority = 2, + }, { + { + { ctx.expandtab and _icons.misc.indent or _icons.misc.tab, 'StTitle' }, + { space, 'StSeparator' }, + { ctx.shiftwidth, 'StTitle' }, + { space, 'StSeparator' }, + }, + cond = ctx.shiftwidth > 2 or not ctx.expandtab, + priority = 6, + }) + + return display({ l1 + l2, m1, r1 + r2 }, available - 5) + end + + -- }}} + + -- Wire up {{{ + + vim.g.qf_disable_statusline = 1 + vim.o.statusline = '%{%v:lua.Stl.render()%}' + + T.augroup('CustomStatusline', { + event = 'FocusGained', + command = function() vim.g.vim_in_focus = true end, + }, { + event = 'FocusLost', + command = function() vim.g.vim_in_focus = false end, + }, { + event = 'BufReadPre', + once = true, + command = _git_updates, + }, { + event = 'DiagnosticChanged', + command = function() vim.cmd('redrawstatus') end, + }, { + event = { 'WinEnter', 'WinLeave', 'BufWinEnter' }, + command = function() vim.cmd('redrawstatus') end, + }) --- Defer non-critical modules for faster startup -vim.defer_fn(function() require('external_grep') end, 0) + -- }}} +end -- }}} -------------------------------------------------------------------------------- --- vim: ts=2 sts=2 sw=2 et fdm=marker fol +-- vim: ft=lua fdm=marker From 17d9c4c785a79b2db122ae9124584eb2e7222416 Mon Sep 17 00:00:00 2001 From: Marcos Romero Lamas Date: Thu, 14 May 2026 01:06:47 +0200 Subject: [PATCH 7/7] perf: improve rendering in statuscolumn and statusline --- files/.config/nvim/init.lua | 83 +++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/files/.config/nvim/init.lua b/files/.config/nvim/init.lua index 31e49ce..83b621f 100644 --- a/files/.config/nvim/init.lua +++ b/files/.config/nvim/init.lua @@ -452,12 +452,12 @@ do return ('%%#%s#%s%%*'):format(group, text) end - local function fold_mark(lnum) - local fcs = vim.opt.fillchars:get() - if fn.foldlevel(lnum) <= fn.foldlevel(lnum - 1) then return '' end - return fn.foldclosed(lnum) == -1 and (fcs.foldopen or '▾') - or (fcs.foldclose or '▸') - end + local _fcs = vim.opt.fillchars:get() + T.augroup('StatusColFillchars', { + event = 'OptionSet', + pattern = 'fillchars', + command = function() _fcs = vim.opt.fillchars:get() end, + }) local function get_signs(buf, lnum0) return api.nvim_buf_get_extmarks( @@ -481,8 +481,8 @@ do local _git_bar_thick = _icons.separators.right_block .. ' ' local _git_bar_thin = _icons.separators.right_thin_block .. ' ' - local function git_col(buf, lnum0) - for _, m in ipairs(get_signs(buf, lnum0)) do + local function git_col(signs) + for _, m in ipairs(signs) do local hlg = (m[4] or {}).sign_hl_group or '' if hlg:match('^GitSigns') then for key, grp in pairs(_git_hl) do @@ -494,10 +494,15 @@ do return _hl('StatusColGitNone', _git_bar_thin) end - local function diag_col(buf, lnum0, cursor_lnum, lnum) + local function diag_col(signs, cursor_lnum, lnum) if lnum == cursor_lnum then return ' ' end + -- Fold header: show fold icon in this cell instead of diagnostic sign. + if fn.foldlevel(lnum) > fn.foldlevel(lnum - 1) then + local icon = fn.foldclosed(lnum) == -1 and (_fcs.foldopen or '▾') or (_fcs.foldclose or '▸') + return _hl('FoldColumn', icon) + end local best_text, best_hl, best_sev = '', nil, 99 - for _, m in ipairs(get_signs(buf, lnum0)) do + for _, m in ipairs(signs) do local hlg = (m[4] or {}).sign_hl_group or '' if hlg:match('^DiagnosticSign') then local sev = hlg:match('Error') and 1 or hlg:match('Warn') and 2 or nil @@ -531,13 +536,13 @@ do end local lnum0 = lnum - 1 + local signs = get_signs(buf, lnum0) local is_cursor = (lnum == cursor_lnum and virtnum == 0) local num_hl = is_cursor and 'CursorLineNr' or 'LineNr' local parts = table.concat({ - diag_col(buf, lnum0, cursor_lnum, lnum), + diag_col(signs, cursor_lnum, lnum), _hl(num_hl, num_str), - git_col(buf, lnum0), - fold_mark(lnum), + git_col(signs), }) return is_cursor and ('%%#CursorLine#%s%%*'):format(parts) or parts end @@ -3930,20 +3935,31 @@ do -- ── Diagnostics ─────────────────────────────────────────────────────── - local function _diagnostics(buf) + local _diag_cache = {} + + local function _refresh_diag(buf) local sev = vim.diagnostic.severity local icons = _icons.lsp local result = { error = { count = 0, icon = icons.error }, - warn = { count = 0, icon = icons.warn }, - info = { count = 0, icon = icons.info }, - hint = { count = 0, icon = icons.hint }, + warn = { count = 0, icon = icons.warn }, + info = { count = 0, icon = icons.info }, + hint = { count = 0, icon = icons.hint }, } for _, item in ipairs(vim.diagnostic.get(buf)) do local s = sev[item.severity]:lower() result[s].count = result[s].count + 1 end - return result + _diag_cache[buf] = result + end + + local _diag_zero = { + error = { count = 0 }, warn = { count = 0 }, + info = { count = 0 }, hint = { count = 0 }, + } + + local function _diagnostics(buf) + return _diag_cache[buf] or _diag_zero end -- ── Search count ────────────────────────────────────────────────────── @@ -3969,13 +3985,14 @@ do vim.cmd('redrawstatus') end - local function _lsp_clients(ctx) - local clients = vim.lsp.get_clients({ bufnr = ctx.bufnum }) or {} - if #clients == 0 then return false, {} end - local has_copilot = false - local names = {} - for _, client in ipairs(clients) do - local name = client.name or '' + local _lsp_cache = {} + + local function _refresh_lsp(buf) + local clients = vim.lsp.get_clients({ bufnr = buf }) or {} + if #clients == 0 then _lsp_cache[buf] = { false, {} }; return end + local has_copilot, names = false, {} + for _, c in ipairs(clients) do + local name = c.name or '' if name == 'copilot' or name:match('copilot') then has_copilot = true else @@ -3983,7 +4000,13 @@ do end end table.sort(names) - return has_copilot, names + _lsp_cache[buf] = { has_copilot, names } + end + + local function _lsp_clients(ctx) + local cached = _lsp_cache[ctx.bufnum] + if cached then return cached[1], cached[2] end + return false, {} end -- ── Git update timer ────────────────────────────────────────────────── @@ -4281,7 +4304,13 @@ do command = _git_updates, }, { event = 'DiagnosticChanged', - command = function() vim.cmd('redrawstatus') end, + command = function(ev) _refresh_diag(ev.buf); vim.cmd('redrawstatus') end, + }, { + event = { 'LspAttach', 'LspDetach' }, + command = function(ev) _refresh_lsp(ev.buf); vim.cmd('redrawstatus') end, + }, { + event = 'BufDelete', + command = function(ev) _diag_cache[ev.buf] = nil; _lsp_cache[ev.buf] = nil end, }, { event = { 'WinEnter', 'WinLeave', 'BufWinEnter' }, command = function() vim.cmd('redrawstatus') end,