From d7f52c9aaee49f62f9e3a2a410ca21eb5e4b1649 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Thu, 10 Sep 2026 21:54:47 +0200 Subject: Add standalone Neovim Lua config Replace the neovim stow package's symlink into vim/.vim with a real, independent Lua config: init.lua + lua/config/* (options, keymaps, autocmds, lazy.nvim bootstrap) + lua/plugins/*.lua (one file per plugin group). - Plugin manager: lazy.nvim (self-bootstrapping, no submodule needed). - Carries over every plugin from the vimrc as-is: vim-airline (+ themes, tmuxline), vim-janah colorscheme, nerdtree, vim-signify, nerdcommenter, ale, vim-fugitive, quick-scope, ctrlp.vim, claude-code.nvim, plus vim-ansible-yaml/vim-terraform gated the same way the vimrc gated them (executable() checks, now as lazy.nvim `cond` functions). - Replaces YouCompleteMe + jedi-vim entirely with nvim-lspconfig + mason.nvim + mason-lspconfig.nvim (ensure_installed: pyright, lua_ls, bashls, terraformls, yamlls, ts_ls, cssls, html; clangd enabled directly since it's already on PATH via Xcode CLT) and blink.cmp for completion (+ friendly-snippets), with blink's LSP capabilities merged into every server's default config. - ALE stays as a pure linter/fixer (g:ale_disable_lsp = 1) so it doesn't duplicate nvim-lspconfig's diagnostics/hover/go-to-definition. - Ports the vimrc's general settings/functions (options, window-nav keymaps, arrow-key disabling, StripTrailingWhitespace, AppendModeline, the git->Git abbreviation) to Lua; drops the w!! sudo-save abbreviation (vimrc's own comment notes it doesn't work under Neovim) and the reload-vimrc-on-save autocmd (no clean Lua equivalent). Vim's own vimrc, ftplugin/python.vim, and plugin installs are completely untouched and unaffected by this change. --- neovim/.config/nvim | 1 - neovim/.config/nvim/.gitignore | 1 + neovim/.config/nvim/ftplugin/python.lua | 5 ++++ neovim/.config/nvim/init.lua | 8 ++++++ neovim/.config/nvim/lua/config/autocmds.lua | 22 +++++++++++++++ neovim/.config/nvim/lua/config/keymaps.lua | 37 +++++++++++++++++++++++++ neovim/.config/nvim/lua/config/lazy.lua | 17 ++++++++++++ neovim/.config/nvim/lua/config/options.lua | 36 ++++++++++++++++++++++++ neovim/.config/nvim/lua/plugins/ale.lua | 9 ++++++ neovim/.config/nvim/lua/plugins/claude-code.lua | 8 ++++++ neovim/.config/nvim/lua/plugins/colorscheme.lua | 11 ++++++++ neovim/.config/nvim/lua/plugins/completion.lua | 11 ++++++++ neovim/.config/nvim/lua/plugins/editing.lua | 13 +++++++++ neovim/.config/nvim/lua/plugins/filetree.lua | 33 ++++++++++++++++++++++ neovim/.config/nvim/lua/plugins/fuzzyfinder.lua | 10 +++++++ neovim/.config/nvim/lua/plugins/git.lua | 4 +++ neovim/.config/nvim/lua/plugins/langs.lua | 14 ++++++++++ neovim/.config/nvim/lua/plugins/lsp.lua | 36 ++++++++++++++++++++++++ neovim/.config/nvim/lua/plugins/statusline.lua | 23 +++++++++++++++ 19 files changed, 298 insertions(+), 1 deletion(-) delete mode 120000 neovim/.config/nvim create mode 100644 neovim/.config/nvim/.gitignore create mode 100644 neovim/.config/nvim/ftplugin/python.lua create mode 100644 neovim/.config/nvim/init.lua create mode 100644 neovim/.config/nvim/lua/config/autocmds.lua create mode 100644 neovim/.config/nvim/lua/config/keymaps.lua create mode 100644 neovim/.config/nvim/lua/config/lazy.lua create mode 100644 neovim/.config/nvim/lua/config/options.lua create mode 100644 neovim/.config/nvim/lua/plugins/ale.lua create mode 100644 neovim/.config/nvim/lua/plugins/claude-code.lua create mode 100644 neovim/.config/nvim/lua/plugins/colorscheme.lua create mode 100644 neovim/.config/nvim/lua/plugins/completion.lua create mode 100644 neovim/.config/nvim/lua/plugins/editing.lua create mode 100644 neovim/.config/nvim/lua/plugins/filetree.lua create mode 100644 neovim/.config/nvim/lua/plugins/fuzzyfinder.lua create mode 100644 neovim/.config/nvim/lua/plugins/git.lua create mode 100644 neovim/.config/nvim/lua/plugins/langs.lua create mode 100644 neovim/.config/nvim/lua/plugins/lsp.lua create mode 100644 neovim/.config/nvim/lua/plugins/statusline.lua (limited to 'neovim') diff --git a/neovim/.config/nvim b/neovim/.config/nvim deleted file mode 120000 index bf0d817..0000000 --- a/neovim/.config/nvim +++ /dev/null @@ -1 +0,0 @@ -../../vim/.vim \ No newline at end of file diff --git a/neovim/.config/nvim/.gitignore b/neovim/.config/nvim/.gitignore new file mode 100644 index 0000000..f84e7ed --- /dev/null +++ b/neovim/.config/nvim/.gitignore @@ -0,0 +1 @@ +spell/ diff --git a/neovim/.config/nvim/ftplugin/python.lua b/neovim/.config/nvim/ftplugin/python.lua new file mode 100644 index 0000000..f100b93 --- /dev/null +++ b/neovim/.config/nvim/ftplugin/python.lua @@ -0,0 +1,5 @@ +-- Ported from vim/.vim/ftplugin/python.vim (shared source of truth for Vim) +vim.bo.tabstop = 8 +vim.bo.expandtab = true +vim.bo.shiftwidth = 4 +vim.bo.softtabstop = 4 diff --git a/neovim/.config/nvim/init.lua b/neovim/.config/nvim/init.lua new file mode 100644 index 0000000..dded909 --- /dev/null +++ b/neovim/.config/nvim/init.lua @@ -0,0 +1,8 @@ +-- Set the leader before anything else: lazy.nvim resolves plugin specs +-- (including any `keys` tables) at setup time and needs it already set. +vim.g.mapleader = " " + +require("config.options") +require("config.keymaps") +require("config.autocmds") +require("config.lazy") diff --git a/neovim/.config/nvim/lua/config/autocmds.lua b/neovim/.config/nvim/lua/config/autocmds.lua new file mode 100644 index 0000000..7bc4f6b --- /dev/null +++ b/neovim/.config/nvim/lua/config/autocmds.lua @@ -0,0 +1,22 @@ +-- Remove trailing spaces on save, preserving cursor and search pattern +local function strip_trailing_whitespace() + if vim.list_contains({ "markdown", "diff" }, vim.bo.filetype) then + return + end + local view = vim.fn.winsaveview() + vim.cmd([[keeppatterns %s/\s\+$//e]]) + vim.fn.winrestview(view) +end + +vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*", + callback = strip_trailing_whitespace, +}) + +-- Note: the colorscheme (with its "desert" fallback) is applied from +-- lua/plugins/colorscheme.lua's own `config` function, not here — under +-- lazy.nvim that's the natural place to react to "the plugin is now loaded". +-- +-- Note: the vimrc's "reload vimrc on save" autocmd has no clean Lua +-- equivalent (module caching means `require()`-based configs aren't simply +-- re-sourceable) and is deliberately not ported. diff --git a/neovim/.config/nvim/lua/config/keymaps.lua b/neovim/.config/nvim/lua/config/keymaps.lua new file mode 100644 index 0000000..f0bfbec --- /dev/null +++ b/neovim/.config/nvim/lua/config/keymaps.lua @@ -0,0 +1,37 @@ +local map = vim.keymap.set + +-- Switch windows with +map("n", "", "j") +map("n", "", "k") +map("n", "", "h") +map("n", "", "l") + +-- Never use the arrow keys +for _, key in ipairs({ "", "", "", "" }) do + map({ "n", "i" }, key, "") +end + +-- Disable ex mode +map("n", "Q", "") + +-- Expand :git to fugitive's :Git, but only as a whole command. +-- (No Lua-native abbreviation API exists, so this stays a thin vim.cmd call.) +vim.cmd([[cnoreabbrev git (getcmdtype() ==# ':' && getcmdline() ==# 'git') ? 'Git' : 'git']]) + +-- Note: the vimrc's `w!!` sudo-save abbreviation is deliberately NOT ported +-- here — its own comment says it doesn't work under Neovim (sudo can't +-- prompt for a password there). + +-- Append modeline when pressing ml +local function append_modeline() + local modeline = string.format( + " vim: set ts=%d sw=%d tw=%d %set :", + vim.bo.tabstop, + vim.bo.shiftwidth, + vim.bo.textwidth, + vim.bo.expandtab and "" or "no" + ) + modeline = vim.bo.commentstring:gsub("%%s", modeline) + vim.api.nvim_buf_set_lines(0, -1, -1, false, { modeline }) +end +map("n", "ml", append_modeline, { silent = true }) diff --git a/neovim/.config/nvim/lua/config/lazy.lua b/neovim/.config/nvim/lua/config/lazy.lua new file mode 100644 index 0000000..5a645c1 --- /dev/null +++ b/neovim/.config/nvim/lua/config/lazy.lua @@ -0,0 +1,17 @@ +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.uv.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup("plugins", { + install = { colorscheme = { "janah", "desert" } }, + checker = { enabled = false }, +}) diff --git a/neovim/.config/nvim/lua/config/options.lua b/neovim/.config/nvim/lua/config/options.lua new file mode 100644 index 0000000..be614e1 --- /dev/null +++ b/neovim/.config/nvim/lua/config/options.lua @@ -0,0 +1,36 @@ +-- Ported from vim/.vim/vimrc's "DEFAULT VIM SETTINGS" block. `syntax on` and +-- `filetype plugin indent on` are intentionally omitted: both are Neovim +-- defaults (see `:help nvim-defaults`). + +local opt = vim.opt + +opt.number = true +opt.relativenumber = true +opt.list = true +opt.modeline = true +opt.background = "dark" +opt.foldmethod = "indent" +opt.listchars = { trail = "·", tab = "▸ ", eol = "¬" } +opt.scrolloff = 1 +opt.backspace = { "indent", "eol", "start" } +opt.cursorline = true +opt.hidden = true -- already Neovim's default; set explicitly for parity with the vimrc +opt.wildmenu = true -- already Neovim's default; set explicitly for parity with the vimrc + +-- Faster gutter updates (signify) and snappier +opt.updatetime = 100 +opt.ttimeoutlen = 10 + +-- Persistent undo across sessions +local undodir = vim.fn.stdpath("data") .. "/undo" +if vim.fn.isdirectory(undodir) == 0 then + vim.fn.mkdir(undodir, "p", "0700") +end +opt.undofile = true +opt.undodir = undodir + +-- Search-related things +opt.hlsearch = true +opt.incsearch = true +opt.ignorecase = true +opt.smartcase = true diff --git a/neovim/.config/nvim/lua/plugins/ale.lua b/neovim/.config/nvim/lua/plugins/ale.lua new file mode 100644 index 0000000..10a680c --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/ale.lua @@ -0,0 +1,9 @@ +return { + "dense-analysis/ale", + event = { "BufReadPre", "BufNewFile" }, + init = function() + -- nvim-lspconfig owns LSP-protocol features (diagnostics, hover, + -- go-to-definition) here; keep ALE to its own linters/fixers only. + vim.g.ale_disable_lsp = 1 + end, +} diff --git a/neovim/.config/nvim/lua/plugins/claude-code.lua b/neovim/.config/nvim/lua/plugins/claude-code.lua new file mode 100644 index 0000000..0390852 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/claude-code.lua @@ -0,0 +1,8 @@ +return { + "greggh/claude-code.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + cmd = { "ClaudeCode", "ClaudeCodeContinue", "ClaudeCodeResume", "ClaudeCodeVerbose" }, + config = function() + require("claude-code").setup({ window = { position = "vertical botright" } }) + end, +} diff --git a/neovim/.config/nvim/lua/plugins/colorscheme.lua b/neovim/.config/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..457dc71 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,11 @@ +return { + "mhinz/vim-janah", + lazy = false, + priority = 1000, + config = function() + local ok = pcall(vim.cmd.colorscheme, "janah") + if not ok then + vim.cmd.colorscheme("desert") + end + end, +} diff --git a/neovim/.config/nvim/lua/plugins/completion.lua b/neovim/.config/nvim/lua/plugins/completion.lua new file mode 100644 index 0000000..9eed355 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/completion.lua @@ -0,0 +1,11 @@ +return { + "saghen/blink.cmp", + version = "*", -- use a release with a prebuilt fuzzy-matcher binary + dependencies = { "rafamadriz/friendly-snippets" }, + opts = { + keymap = { preset = "super-tab" }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + }, + }, +} diff --git a/neovim/.config/nvim/lua/plugins/editing.lua b/neovim/.config/nvim/lua/plugins/editing.lua new file mode 100644 index 0000000..c1d5567 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/editing.lua @@ -0,0 +1,13 @@ +return { + { + "preservim/nerdcommenter", + init = function() + vim.g.NERDSpaceDelims = 1 + vim.g.NERDCompactSexyComs = 1 + vim.g.NERDDefaultAlign = "left" + vim.g.NERDCommentEmptyLines = 1 + vim.g.NERDTrimTrailingWhitespace = 1 + end, + }, + "unblevable/quick-scope", +} diff --git a/neovim/.config/nvim/lua/plugins/filetree.lua b/neovim/.config/nvim/lua/plugins/filetree.lua new file mode 100644 index 0000000..cdee9f7 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/filetree.lua @@ -0,0 +1,33 @@ +return { + "preservim/nerdtree", + lazy = false, + config = function() + -- Open NERDTree when no file is specified; quit when it's the last window + local augroup = vim.api.nvim_create_augroup("nerdtree_auto", { clear = true }) + + vim.api.nvim_create_autocmd("StdinReadPre", { + group = augroup, + callback = function() + vim.g.std_in = 1 + end, + }) + + vim.api.nvim_create_autocmd("VimEnter", { + group = augroup, + callback = function() + if vim.fn.argc() == 0 and vim.g.std_in == nil then + vim.cmd("NERDTree") + end + end, + }) + + vim.api.nvim_create_autocmd("BufEnter", { + group = augroup, + callback = function() + if vim.fn.winnr("$") == 1 and vim.bo.filetype == "nerdtree" then + vim.cmd("quit") + end + end, + }) + end, +} diff --git a/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua b/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua new file mode 100644 index 0000000..444d9ff --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua @@ -0,0 +1,10 @@ +return { + "ctrlpvim/ctrlp.vim", + init = function() + -- Use ripgrep for listing files (fast, respects .gitignore) + if vim.fn.executable("rg") == 1 then + vim.g.ctrlp_user_command = 'rg %s --files --color=never --glob ""' + vim.g.ctrlp_use_caching = 0 + end + end, +} diff --git a/neovim/.config/nvim/lua/plugins/git.lua b/neovim/.config/nvim/lua/plugins/git.lua new file mode 100644 index 0000000..8402905 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/git.lua @@ -0,0 +1,4 @@ +return { + "tpope/vim-fugitive", + "mhinz/vim-signify", +} diff --git a/neovim/.config/nvim/lua/plugins/langs.lua b/neovim/.config/nvim/lua/plugins/langs.lua new file mode 100644 index 0000000..7bf22d4 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/langs.lua @@ -0,0 +1,14 @@ +return { + { + "chase/vim-ansible-yaml", + cond = function() + return vim.fn.executable("ansible") == 1 + end, + }, + { + "hashivim/vim-terraform", + cond = function() + return vim.fn.executable("terraform") == 1 + end, + }, +} diff --git a/neovim/.config/nvim/lua/plugins/lsp.lua b/neovim/.config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..0463dde --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,36 @@ +return { + "mason-org/mason-lspconfig.nvim", + dependencies = { + { "mason-org/mason.nvim", opts = {} }, + "neovim/nvim-lspconfig", + "saghen/blink.cmp", + }, + opts = { + ensure_installed = { + "pyright", + "lua_ls", + "bashls", + "terraformls", + "yamlls", + "ts_ls", + "cssls", + "html", + }, + -- default true: auto-calls vim.lsp.enable() for every Mason-installed + -- server as it finishes installing. + }, + config = function(_, opts) + -- Merge blink.cmp's LSP capabilities into every server's default config + -- (Mason-managed or not) before any server gets enabled. + vim.lsp.config("*", { + capabilities = require("blink.cmp").get_lsp_capabilities(), + }) + + require("mason-lspconfig").setup(opts) + + -- clangd ships with Xcode Command Line Tools already, so it's not + -- Mason-managed — nvim-lspconfig provides its default config, we just + -- need to turn it on. + vim.lsp.enable("clangd") + end, +} diff --git a/neovim/.config/nvim/lua/plugins/statusline.lua b/neovim/.config/nvim/lua/plugins/statusline.lua new file mode 100644 index 0000000..b93b34c --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/statusline.lua @@ -0,0 +1,23 @@ +return { + "bling/vim-airline", + lazy = false, + dependencies = { + "vim-airline/vim-airline-themes", + "edkolev/tmuxline.vim", + }, + init = function() + -- On arch linux install the following: + -- otf-powerline-symbols-git + -- powerline-fonts-git + vim.g.airline_powerline_fonts = 1 + vim.g["airline#extensions#tabline#enabled"] = 1 + + -- vim.g dict reads return a copy, not a live reference, so the nested + -- field has to be set via a local table and reassigned. + local symbols = vim.g.airline_symbols or {} + symbols.space = "\u{a0}" + vim.g.airline_symbols = symbols + + vim.opt.laststatus = 2 + end, +} -- cgit v1.3