diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-06-25 07:44:15 +0200 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-06-25 07:44:15 +0200 |
| commit | fb3587e51e0908c3d43722c55741cf6a386e39ce (patch) | |
| tree | 248c42999260ab6c9175aea90365aab08bd68c9d /plugin | |
| parent | c22fab35706facfa780b800b4dc72559f0ac6c60 (diff) | |
| download | nvim-config-fb3587e51e0908c3d43722c55741cf6a386e39ce.tar.gz nvim-config-fb3587e51e0908c3d43722c55741cf6a386e39ce.zip | |
refactor(nvim): restructure plugin configs, fix OSV launch port
- rewrite the file headers as block comments and regroup the
autocompletion and dap files into Settings / Autocommands / Keymaps
sections
- fix `OSVLaunch`: `dap.configurations.lua.port` was nil (the field is
a list), so the server ignored 8086; share an `OSV_PORT` constant
between the launch call and the attach configuration
- `.luarc.json`: list each plugin directory explicitly so lua_ls loads
their type annotations
- use `vim.fs.basename` instead of `vim.fn.fnamemodify(…, ":t")`
Diffstat (limited to 'plugin')
| -rw-r--r-- | plugin/00-plugin.lua | 10 | ||||
| -rw-r--r-- | plugin/50-autocompletion.lua | 112 | ||||
| -rw-r--r-- | plugin/50-autopairs.lua | 13 | ||||
| -rw-r--r-- | plugin/50-color.lua | 114 | ||||
| -rw-r--r-- | plugin/50-dap.lua | 57 |
5 files changed, 155 insertions, 151 deletions
diff --git a/plugin/00-plugin.lua b/plugin/00-plugin.lua index def11c0..ac34066 100644 --- a/plugin/00-plugin.lua +++ b/plugin/00-plugin.lua @@ -1,8 +1,8 @@ --- --- 00-plugin.lua --- --- * Installs third-party plugins. --- +--[[ 00-plugin.lua — install third-party plugins via vim.pack. + +Plugins are pinned in nvim-pack-lock.json; this file must load first so later plugin/ files can +require() them. +]] vim.pack.add({ "https://github.com/airblade/vim-gitgutter", diff --git a/plugin/50-autocompletion.lua b/plugin/50-autocompletion.lua index 853a528..a8b7f4b 100644 --- a/plugin/50-autocompletion.lua +++ b/plugin/50-autocompletion.lua @@ -1,18 +1,17 @@ --- --- 50-autocompletion.lua --- --- * Configures autocompletion for insert mode and command-line mode. --- In both modes: --- * The list of completions shows up automatically --- * Tab/Shift+Tab selects (and inserts) the next/previous item --- In cmd-line mode: --- * Tab selects a lone match outright, inserts it, closes the menu --- (Useful when completing file names) --- * CTRL+Y inserts the selection; with no selection it dismisses the menu --- +--[[ 50-autocompletion.lua — automatic completion for insert and command-line mode. + +In both modes the menu shows up automatically and `<Tab>`/`<S-Tab>` select the next/previous item. +In command-line mode `<Tab>` accepts a lone match outright and `<C-y>` accepts the selection (or +dismisses the menu when nothing is selected). + +Keymaps: + `<Tab>` / `<S-Tab>` (insert) select next / previous menu item + `<Tab>` (cmdline) accept a lone match, else select next + `<C-y>` (cmdline) accept the selection, else dismiss +]] ---------------------------------------------------------------------------------------------------- --- Insert mode autocompletion +-- Insert mode ------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- local function i_select_next_menu_item() @@ -24,36 +23,18 @@ local function i_select_previous_menu_item() end ---------------------------------------------------------------------------------------------------- - -vim.opt.autocomplete = true -- Show completion menu automatically -vim.opt.completeopt = { - "noselect", -- No item selected initially - "menuone", -- Show matches in a menu, even if there's only one match - "popup", -- Menu items show extra info in the popup window - "fuzzy", -} --- Completion sources (in order of priority) -vim.opt.complete = { - "o", -- 'omnifunc' -} - -vim.keymap.set("i", "<Tab>", i_select_next_menu_item, { expr = true }) -vim.keymap.set("i", "<S-Tab>", i_select_previous_menu_item, { expr = true }) - ----------------------------------------------------------------------------------------------------- --- Command-line mode autocompletion +-- Command-line mode ------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- --- `<Space><BS>` is a self-cancelling edit: it closes the menu, then `CmdLineChanged` fires and --- tries to perform completion on the text before the cursor. +--[[ `<Space><BS>` is a self-cancelling edit: it closes the menu, then `CmdlineChanged` fires and +tries to perform completion on the text before the cursor. ]] local function c_insert_unique_or_wildtrigger() local complete_info = vim.fn.cmdcomplete_info() if complete_info.pum_visible == 1 then return #complete_info.matches == 1 and "<C-n><Space><BS>" or "<C-n>" end -- After navigating the command-line history, it takes two `wildtrigger()` calls to show the - -- menu. The first is performed by the `CmdLineChanged` autocommand, the second is performed - -- here. + -- menu. The first is performed by the `CmdlineChanged` autocommand, the second is performed here. vim.fn.wildtrigger() return nil end @@ -66,33 +47,54 @@ local function c_accept_selection_or_dismiss() return "<C-y>" end +-- Show the command-line completion menu automatically. +local function trigger_wildmenu() + vim.fn.wildtrigger() +end + +---------------------------------------------------------------------------------------------------- +-- Settings ---------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------- + +-- Insert mode. +vim.opt.autocomplete = true -- Show the completion menu automatically. +--[[ Completion menu behaviour: do not preselect an item (`noselect`), show a menu even for a single +match (`menuone`), show extra info in a popup window (`popup`), and match fuzzily (`fuzzy`). ]] +vim.opt.completeopt = { "noselect", "menuone", "popup", "fuzzy" } +-- Completion sources, in order of priority: `omnifunc` (`o`). +vim.opt.complete = { "o" } + +-- Command-line mode. +vim.opt.wildmenu = true -- Show completions in a menu. +vim.opt.wildchar = 9 -- Char code (`<Tab>`) assigned to command-line wildcard expansion. +--[[ Wildmenu behaviour: discard regex artifacts in search-pattern completion (`exacttext`), use a +popup menu (`pum`), show tag kind and file (`tagfile`), and match fuzzily except for files/dirs, +which use patterns (`fuzzy`). ]] +vim.opt.wildoptions = { "exacttext", "pum", "tagfile", "fuzzy" } +--[[ Completion modes triggered in order by `wildtrigger()` or `wildchar`: list matches without +inserting (`noselect`), then list matches and insert the first full match (`full`). ]] +vim.opt.wildmode = { "noselect", "full" } + +---------------------------------------------------------------------------------------------------- +-- Autocommands ------------------------------------------------------------------------------------ ---------------------------------------------------------------------------------------------------- --- Show completion menu automatically -vim.api.nvim_create_autocmd({ "CmdLineChanged", "CmdlineEnter" }, { +-- The `pattern` matches `:` commands plus `/` and `?` searches, but not `=` and `@`. +vim.api.nvim_create_autocmd({ "CmdlineChanged", "CmdlineEnter" }, { desc = "Autocompletion", group = vim.g.dotfiles.augroup, - pattern = "[:\\/\\?]", -- Matches : commands plus / and ? searches, but not = and @ - callback = function() - vim.fn.wildtrigger() - end, + pattern = "[:\\/\\?]", + callback = trigger_wildmenu, }) -vim.opt.wildmenu = true -- Show completions in a menu -vim.opt.wildchar = 9 -- Char code (`<Tab>`) assigned to command-line wildcard expansion -vim.opt.wildoptions = { - "exacttext", -- Discard regex artifacts when performing search pattern completion - "pum", -- Show completions in a popup menu - "tagfile", -- Show tag kind and file - "fuzzy", -- Fuzzy matching (except for files/dirs, use patterns) -} --- Completion modes triggered in order by `wildtrigger()` or 'wildchar' -vim.opt.wildmode = { - "noselect", -- List matches without inserting - "full", -- List matches and insert first full match -} +---------------------------------------------------------------------------------------------------- +-- Keymaps ----------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------- --- Converts `vim.opt.wildchar` char code into a key string that can be used by `vim.keymap.set()`. +-- Convert the `vim.o.wildchar` char code into a key string usable by `vim.keymap.set()`. local wildchar_key = string.format("%c", vim.o.wildchar) + +vim.keymap.set("i", "<Tab>", i_select_next_menu_item, { expr = true }) +vim.keymap.set("i", "<S-Tab>", i_select_previous_menu_item, { expr = true }) vim.keymap.set("c", wildchar_key, c_insert_unique_or_wildtrigger, { expr = true }) vim.keymap.set("c", "<C-y>", c_accept_selection_or_dismiss, { expr = true }) diff --git a/plugin/50-autopairs.lua b/plugin/50-autopairs.lua index aa19967..64b5609 100644 --- a/plugin/50-autopairs.lua +++ b/plugin/50-autopairs.lua @@ -1,13 +1,16 @@ --- --- 50-autopairs.lua --- --- * Adds autopairs for markdown (`**` and `~~`) --- +--[[ 50-autopairs.lua — autopairs rules for markdown. + +Pairs `*` and `~` so that `**bold**` and `~~strike~~` auto-close, via nvim-autopairs. +]] local Rule = require("nvim-autopairs.rule") local npairs = require("nvim-autopairs") local cond = require("nvim-autopairs.conds") + npairs.setup() + +--[[ Auto-close `*` and `~` in markdown, but only when not already before the same char (so `**`/`~~` +nest cleanly), and never expand them on `<CR>`. ]] npairs.add_rules({ Rule("*", "*", "markdown"):with_move(cond.not_before_regex("%*")):with_cr(cond.none()), Rule("~", "~", "markdown"):with_move(cond.not_before_regex("~")):with_cr(cond.none()), diff --git a/plugin/50-color.lua b/plugin/50-color.lua index ede41ee..f95711c 100644 --- a/plugin/50-color.lua +++ b/plugin/50-color.lua @@ -1,18 +1,15 @@ --- --- 50-color.lua --- --- * Highlight tweaks for the solarized colorscheme, plus popup-menu and tabpage-title styling. --- * The lualine statusline (https://github.com/nvim-lualine/lualine.nvim), themed to match. --- * Registers both into dotfiles.color, which re-applies them on colorscheme / 'background' changes --- and once after startup. --- * Sets the default colorscheme (solarized) and background (dark). --- --- User commands: --- `ColorsBgToggle`: toggle light/dark background --- `TabRename`: rename current tab --- `TabRenameFileName`: rename current tab to the active buffer's file name --- `LualineConfig`: show the resolved lualine configuration --- +--[[ 50-color.lua — solarized highlight tweaks, a matching lualine statusline, and the custom tabline. + +Registers highlight and statusline appliers into dotfiles.color, which re-applies them on colorscheme +/ 'background' changes and once after startup. Also styles the popup menu and tabpage titles, and sets +the default colorscheme (solarized) and background (dark). + +User commands: + `ColorsBgToggle`: toggle light/dark background + `TabRename`: rename the current tab + `TabRenameFileName`: rename the current tab to the active buffer's file name + `LualineConfig`: show the resolved lualine configuration +]] local color = require("dotfiles.color") local lualine = require("lualine") @@ -20,41 +17,40 @@ local lualine = require("lualine") local solarized = { blue = "#268bd2" } ---------------------------------------------------------------------------------------------------- --- Highlights +-- Highlights -------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- --- Highlight applier: adjust the solarized groups to fit my personal tastes. No-ops unless solarized --- is the active colorscheme. +--[[ Highlight applier: adjust the solarized groups to fit my personal tastes. No-ops unless solarized +is the active colorscheme. ]] local function apply_solarized_highlights() if vim.g.colors_name ~= "solarized" then return end - -- Window bar style + -- Window bar style. vim.api.nvim_set_hl(0, "WinBarCwd", { fg = solarized.blue, italic = true }) vim.api.nvim_set_hl(0, "WinBarFilePath", { italic = true }) - -- Matching delimiter + -- Matching delimiter. vim.api.nvim_set_hl(0, "MatchParen", { link = "CurSearch" }) - -- Floating windows and popup menu windows follow the editor background, their borders too so - -- that the popup menu border draws a clean separation. + -- Floating windows and popup menu windows follow the editor background, their borders too so that + -- the popup menu border draws a clean separation. vim.opt.pumborder = "rounded" - vim.opt.pumwidth = 25 -- Minimum popup menu width + vim.opt.pumwidth = 25 -- Minimum popup menu width. vim.api.nvim_set_hl(0, "NormalFloat", { link = "Normal" }) local normal_bg = vim.api.nvim_get_hl(0, { name = "Normal", link = false }).bg vim.api.nvim_set_hl(0, "FloatBorder", { bg = normal_bg, update = true }) vim.api.nvim_set_hl(0, "Pmenu", { bg = normal_bg, update = true }) vim.api.nvim_set_hl(0, "PmenuSbar", { bg = normal_bg, update = true }) - -- Currently selected tabpage + -- Currently selected tabpage. vim.api.nvim_set_hl(0, "TabLineSel", { bold = true, italic = true, update = true }) - -- Todo hl group + -- `Todo` highlight group. vim.api.nvim_set_hl(0, "Todo", { bg = "Yellow", fg = "Black", bold = true }) - -- Fold lines being the same color as the cursor line (default) make unfocused windows unreadable - -- Their background is set to blend in, the folds are visible enough with their dotted lines + --[[ Fold lines sharing the cursor-line color (the default) make unfocused windows unreadable, so + their background is set to blend in; the folds stay visible enough through their dotted lines. ]] vim.api.nvim_set_hl(0, "Folded", { bg = normal_bg, underline = true, update = true }) end --- Highlight applier: create custom highlight groups for styling the tabpage title bars: --- * TabLineWinCount: number of open windows in the tabpage --- * TabLineSelWinCount: number of open windows in the currently active tabpage +--[[ Highlight applier: create custom highlight groups for styling the tabpage title bars. +`TabLineWinCount` is the window count of a tabpage, `TabLineSelWinCount` that of the active one. ]] local function apply_tabpage_title_highlights() local normal = vim.api.nvim_get_hl(0, { name = "Normal", link = false }) local tabline = vim.api.nvim_get_hl(0, { name = "TabLine", link = false }) @@ -69,7 +65,7 @@ local function apply_tabpage_title_highlights() end ---------------------------------------------------------------------------------------------------- --- Statusline +-- Statusline -------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- -- Spell flag: which spell languages are enabled, or nil when 'spelllang' matches none of these. @@ -83,8 +79,8 @@ local function spell_status() end end --- Custom status flags: "+F" when formatting is on for the buffer, "+H" when LSP inlay hints are on, --- "+R" when disk-change autoreload is enabled (see 50-autoreload.lua), followed by the spell flag. +--[[ Custom status flags: `+F` when formatting is on for the buffer, `+H` when LSP inlay hints are on, +`+R` when disk-change autoreload is enabled (see 50-autoreload.lua), followed by the spell flag. ]] local function statuses() return (vim.b.format and "+F" or "") .. (vim.lsp.inlay_hint.is_enabled({ bufnr = 0 }) and "+H" or "") @@ -92,10 +88,10 @@ local function statuses() .. (vim.o.spell and spell_status() or "") end --- lualine builds its own section-b-backed highlights for the diff/diagnostics components --- (lualine_b_diff_added_normal, lualine_b_diagnostics_error_normal, ...). Stamp bold onto them with --- update=true so only the bold attribute changes — fg and section b's background are left untouched. --- Must run after lualine (re)creates the groups: initial setup, theme switch, colorscheme. +--[[ lualine builds its own section-b-backed highlights for the diff/diagnostics components +(`lualine_b_diff_added_normal`, `lualine_b_diagnostics_error_normal`, ...). Stamp bold onto them with +`update = true` so only the bold attribute changes — fg and section b's background are left untouched. +Must run after lualine (re)creates the groups: initial setup, theme switch, colorscheme. ]] local function bold_diff_diag() for name in pairs(vim.api.nvim_get_hl(0, {})) do if name:find("^lualine_b_diff") or name:find("^lualine_b_diagnostics") then @@ -121,28 +117,28 @@ local function configure_lualine() lualine.setup({ options = lualine_options, sections = lualine_sections }) end --- Statusline applier: re-pick the lualine theme for the current 'background', then re-bold the --- diff/diagnostics groups once lualine has rebuilt them. +--[[ Statusline applier: re-pick the lualine theme for the current 'background', then re-bold the +diff/diagnostics groups once lualine has rebuilt them. ]] local function apply_statusline_highlights() configure_lualine() vim.schedule(bold_diff_diag) end ---------------------------------------------------------------------------------------------------- --- Tabline +-- Tabline ----------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- --- Builds the window-count segment of a tabpage label, e.g. ` (2)[+] ` (no styling). --- `is_modified` appends the `[+]` marker when any window in the tab has pending changes. +--[[ Build the window-count segment of a tabpage label, e.g. ` (2)[+] ` (no styling). +`is_modified` appends the `[+]` marker when any window in the tab has pending changes. ]] local function make_tab_info_label(win_count, is_modified) local tab_win_count = "(" .. (win_count >= 10 and ">9" or tostring(win_count)) .. ")" local tab_win_count_suffix = is_modified and "[+] " or " " return " " .. tab_win_count .. tab_win_count_suffix end --- Builds the title segment of a tabpage label, padded or truncated to `width` (no styling). --- Uses the tab's `tabname` if set, else the active buffer's file name, else `[No Name]`, prefixed --- with `*` for the current tab and `-` for the last-accessed tab. +--[[ Build the title segment of a tabpage label, padded or truncated to `width` (no styling). +Uses the tab's `tabname` if set, else the active buffer's file name, else `[No Name]`, prefixed with +`*` for the current tab and `-` for the last-accessed tab. ]] local function make_tab_label(id, is_current, width) local is_last_accessed = vim.api.nvim_tabpage_get_number(id) == vim.fn.tabpagenr("#") local tab_label_prefix = (is_current and "*" or "") .. (is_last_accessed and "-" or "") @@ -150,7 +146,7 @@ local function make_tab_label(id, is_current, width) if tab_label == nil or tab_label == "" then local win = vim.api.nvim_tabpage_get_win(id) local bufname = vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(win)) - tab_label = vim.fn.fnamemodify(bufname, ":t") + tab_label = vim.fs.basename(bufname) end if tab_label == "" then tab_label = "[No Name]" @@ -161,9 +157,9 @@ local function make_tab_label(id, is_current, width) or (tab_label .. string.rep(" ", width - display_width)) end --- Returns a string compatible with the 'tabline' option, used to set the tabline content and style. --- Declared as a global function to be available as `v:lua.GetTabLine` in the Vimscript engine for --- the 'tabline' option. See `:help 'statusline'`. +--[[ Return a string compatible with the 'tabline' option, used to set the tabline content and style. +Declared as a global function to be available as `v:lua.GetTabLine` in the Vimscript engine for the +'tabline' option. See <nvim-help://%27statusline%27>. ]] function GetTabLine() local max_tab_label_width = 30 local s = "" @@ -178,7 +174,7 @@ function GetTabLine() end end - -- Define start of tabpage label (marks where clickage region begins) + -- Mark the start of the tabpage label (where the clickable region begins). s = s .. "%" .. vim.api.nvim_tabpage_get_number(id) .. "T" local tab_info_label = make_tab_info_label(#wins, is_modified) @@ -204,7 +200,7 @@ local function rename_tab_to_cur_filename() end ---------------------------------------------------------------------------------------------------- --- Commands & init +-- Commands & init --------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- -- Flip between the light and dark backgrounds (the colorscheme reloads, OptionSet re-themes). @@ -222,20 +218,14 @@ color.register(apply_solarized_highlights) color.register(apply_tabpage_title_highlights) color.register(apply_statusline_highlights) -vim.api.nvim_create_user_command( - "ColorsBgToggle", - toggle_theme, - { desc = "Toggle light/dark theme" } -) +-- stylua: ignore start +vim.api.nvim_create_user_command("ColorsBgToggle", toggle_theme, { desc = "Toggle light/dark theme" }) vim.api.nvim_create_user_command("TabRename", rename_tab, { nargs = 1 }) vim.api.nvim_create_user_command("TabRenameFileName", rename_tab_to_cur_filename, { nargs = 0 }) -vim.api.nvim_create_user_command( - "LualineConfig", - show_lualine_config, - { desc = "Show lualine configuration" } -) +vim.api.nvim_create_user_command("LualineConfig", show_lualine_config, { desc = "Show lualine configuration" }) +-- stylua: ignore end --- See `:help stl-%!` +-- See <nvim-help://stl-%25%21>. vim.o.tabline = "%!v:lua.GetTabLine()" vim.cmd.colorscheme("solarized") vim.opt.background = "dark" diff --git a/plugin/50-dap.lua b/plugin/50-dap.lua index 7c715ba..4f07214 100644 --- a/plugin/50-dap.lua +++ b/plugin/50-dap.lua @@ -1,24 +1,46 @@ --- --- 50-dap.lua --- --- * Configures OSV: --- User commands: --- * OSVLaunch: start the OSV server (on the debuggee) --- * OSVStatus: show status of OSV server and client --- +--[[ 50-dap.lua — debug Lua running inside Neovim via OSV (one-small-step-for-vimkind). + +Wires nvim-dap to the OSV adapter so the running Neovim instance can be attached to and debugged. + +User commands: + `OSVLaunch`: start the OSV server (on the debuggee) + `OSVStatus`: show the status of the OSV server and client +]] local dap = require("dap") +local osv = require("osv") + +-- Port shared by the OSV server and the dap attach configuration. +local OSV_PORT = 8086 ---------------------------------------------------------------------------------------------------- --- OSV (Lua inside Neovim) +-- OSV (Lua inside Neovim) ------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- -dap.configurations.lua = { +-- Start the OSV server so the running Neovim instance can be attached to. +local function osv_launch() + osv.launch({ port = OSV_PORT }) +end + +-- Report whether the OSV server is running and whether a client is attached. +local function osv_status() + vim.notify("OSV server running: " .. tostring(osv.is_running())) + vim.notify("OSV client attached: " .. tostring(osv.is_attached())) +end + +---------------------------------------------------------------------------------------------------- +-- Configuration & commands ------------------------------------------------------------------------ +---------------------------------------------------------------------------------------------------- + +--[[ The cast restores dap.configurations' own type: with fzf-lua in the lua_ls library its dap +provider cross-merges a `configurations` field, which otherwise mistypes this as a function. ]] +local configurations = dap.configurations --[[@as table<string, dap.Configuration[]>]] +configurations.lua = { { type = "nlua", request = "attach", name = "Attach to running Neovim instance", - port = 8086, + port = OSV_PORT, }, } @@ -26,18 +48,5 @@ dap.adapters.nlua = function(callback, config) callback({ type = "server", host = config.host or "127.0.0.1", port = config.port }) end -local osv = require("osv") - -local function osv_launch() - osv.launch({ port = dap.configurations.lua.port }) -end - -local function osv_status() - vim.notify("OSV server running: " .. tostring(osv.is_running())) - vim.notify("OSV client attached: " .. tostring(osv.is_attached())) -end - ----------------------------------------------------------------------------------------------------- - vim.api.nvim_create_user_command("OSVLaunch", osv_launch, { desc = "Launch OSV server" }) vim.api.nvim_create_user_command("OSVStatus", osv_status, { desc = "Show OSV status" }) |
