From d701e7cd8bdbb435795f2d2d57f449cb397b0b99 Mon Sep 17 00:00:00 2001 From: RiverMatsumoto Date: Tue, 30 Jun 2026 00:38:54 -1000 Subject: [PATCH] modernize config --- .github/workflows/ci.yml | 24 +++ .github/workflows/update-plugins.yml | 52 ++++++ .gitignore | 3 +- .nvim-version | 1 + README.md | 240 ++++----------------------- init.lua | 224 ++++++++++++------------- lazy-lock.json | 62 +++++++ lua/bootstrap/pacman.lua | 111 ------------- scripts/nvim-test.sh | 39 +++++ 9 files changed, 318 insertions(+), 438 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/update-plugins.yml create mode 100644 .nvim-version create mode 100644 lazy-lock.json delete mode 100644 lua/bootstrap/pacman.lua create mode 100755 scripts/nvim-test.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..dc8f9dc9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: Neovim config + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + smoke-test: + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v6 + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y build-essential curl git ripgrep + - name: Install Neovim 0.12.2 + run: | + curl -fL https://github.com/neovim/neovim/releases/download/v0.12.2/nvim-linux-x86_64.tar.gz -o /tmp/nvim.tar.gz + tar -xzf /tmp/nvim.tar.gz -C /tmp + echo "/tmp/nvim-linux-x86_64/bin" >> "$GITHUB_PATH" + - name: Restore locked plugins and start Neovim + run: scripts/nvim-test.sh restore diff --git a/.github/workflows/update-plugins.yml b/.github/workflows/update-plugins.yml new file mode 100644 index 00000000..a54f2fd8 --- /dev/null +++ b/.github/workflows/update-plugins.yml @@ -0,0 +1,52 @@ +name: Update locked plugins + +on: + schedule: + - cron: '17 7 * * 1' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + update: + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y build-essential curl git ripgrep + - name: Install Neovim 0.12.2 + run: | + curl -fL https://github.com/neovim/neovim/releases/download/v0.12.2/nvim-linux-x86_64.tar.gz -o /tmp/nvim.tar.gz + tar -xzf /tmp/nvim.tar.gz -C /tmp + echo "/tmp/nvim-linux-x86_64/bin" >> "$GITHUB_PATH" + - name: Update plugins and smoke test the result + run: scripts/nvim-test.sh update + - name: Open or refresh the update pull request + env: + GH_TOKEN: ${{ github.token }} + run: | + if git diff --quiet -- lazy-lock.json; then + echo "Plugin lockfile is already current." + exit 0 + fi + + branch=automation/plugin-updates + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + git fetch origin "$branch" || true + git switch -C "$branch" + git add lazy-lock.json + git commit -m "chore: update locked plugins" + git push --force-with-lease origin "$branch" + + gh pr create \ + --base "${GITHUB_REF_NAME}" \ + --head "$branch" \ + --title "chore: update locked Neovim plugins" \ + --body "Automated weekly plugin update. Merge only after the Neovim config check passes." \ + || gh pr edit "$branch" --body "Automated weekly plugin update. Merge only after the Neovim config check passes." diff --git a/.gitignore b/.gitignore index 005b535b..f7ba1915 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ test.sh nvim spell/ -lazy-lock.json +# The plugin lockfile is intentionally committed. It is the rollback point for +# safe updates and must not be ignored. diff --git a/.nvim-version b/.nvim-version new file mode 100644 index 00000000..60d68b23 --- /dev/null +++ b/.nvim-version @@ -0,0 +1 @@ +v0.12.2 diff --git a/README.md b/README.md index bb20f57b..de239a73 100644 --- a/README.md +++ b/README.md @@ -1,222 +1,50 @@ -# kickstart.nvim +# River's Neovim config -# install: -`git clone https://github.com/RiverMatsumoto/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim` +This configuration targets **Neovim 0.12.x** and pins the complete plugin graph +in `lazy-lock.json`. Normal editor startup never updates plugins. A weekly GitHub +Actions job proposes lockfile updates in a pull request, and the same isolated +smoke test runs on every push and pull request. -## Introduction +That gives updates a rollback point and keeps upstream breaking changes out of +the working editor until they pass CI. It cannot make arbitrary upstream +changes risk-free, but it turns them into reviewed, reversible changes instead +of surprise startup failures. -A starting point for Neovim that is: +## Install -* Small -* Single-file -* Completely Documented - -**NOT** a Neovim distribution, but instead a starting point for your configuration. - -## Installation - -### Install Neovim - -Kickstart.nvim targets *only* the latest -['stable'](https://github.com/neovim/neovim/releases/tag/stable) and latest -['nightly'](https://github.com/neovim/neovim/releases/tag/nightly) of Neovim. -If you are experiencing issues, please make sure you have the latest versions. - -### Install External Dependencies - -> **NOTE** -> [Backup](#FAQ) your previous configuration (if any exists) - -External Requirements: -- Basic utils: `git`, `make`, `unzip`, C Compiler (`gcc`) -- [ripgrep](https://github.com/BurntSushi/ripgrep#installation) -- Language Setup: - - If want to write Typescript, you need `npm` - - If want to write Golang, you will need `go` - - etc. - -> **NOTE** -> See [Windows Installation](#Windows-Installation) to double check any additional Windows notes - -Neovim's configurations are located under the following paths, depending on your OS: - -| OS | PATH | -| :- | :--- | -| Linux, MacOS | `$XDG_CONFIG_HOME/nvim`, `~/.config/nvim` | -| Windows (cmd)| `%userprofile%\AppData\Local\nvim\` | -| Windows (powershell)| `$env:USERPROFILE\AppData\Local\nvim\` | - -### Install Kickstart - -Clone kickstart.nvim: - -
Linux and Mac - -```sh -git clone https://github.com/nvim-lua/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim -``` - -
- -
Windows - -If you're using `cmd.exe`: - -``` -git clone https://github.com/nvim-lua/kickstart.nvim.git %userprofile%\AppData\Local\nvim\ -``` - -If you're using `powershell.exe` - -``` -git clone https://github.com/nvim-lua/kickstart.nvim.git $env:USERPROFILE\AppData\Local\nvim\ -``` - -
- -### Post Installation - -Start Neovim +Required: Neovim 0.12.x, Git, a C compiler, `make`, `unzip`, and `ripgrep`. A Nerd +Font is recommended. Language servers, formatters, and debuggers are installed +through Mason on first interactive startup. ```sh +git clone https://github.com/RiverMatsumoto/kickstart.nvim.git \ + "${XDG_CONFIG_HOME:-$HOME/.config}/nvim" nvim ``` -That's it! Lazy will install all the plugins you have. Use `:Lazy` to view -current plugin status. +To try it without replacing another config: -Read through the `init.lua` file in your configuration folder for more -information about extending and exploring Neovim. - -### Getting Started - -See [Effective Neovim: Instant IDE](https://youtu.be/stqUbv-5u2s), covering the -previous version. Note: The install via init.lua is outdated, please follow the -install instructions in this file instead. An updated video is coming soon. - -### Recommended Steps - -[Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) this repo -(so that you have your own copy that you can modify) and then installing you -can install to your machine using the methods above. - -> **NOTE** -> Your fork's url will be something like this: `https://github.com//kickstart.nvim.git` - -#### Examples of adding popularly requested plugins - -NOTE: You'll need to uncomment the line in the init.lua that turns on loading custom plugins. - -
- Adding autopairs - -This will automatically install [windwp/nvim-autopairs](https://github.com/windwp/nvim-autopairs) and enable it on startup. For more information, see documentation for [lazy.nvim](https://github.com/folke/lazy.nvim). - -In the file: `lua/custom/plugins/autopairs.lua`, add: - -```lua --- File: lua/custom/plugins/autopairs.lua - -return { - "windwp/nvim-autopairs", - -- Optional dependency - dependencies = { 'hrsh7th/nvim-cmp' }, - config = function() - require("nvim-autopairs").setup {} - -- If you want to automatically add `(` after selecting a function or method - local cmp_autopairs = require('nvim-autopairs.completion.cmp') - local cmp = require('cmp') - cmp.event:on( - 'confirm_done', - cmp_autopairs.on_confirm_done() - ) - end, -} +```sh +git clone https://github.com/RiverMatsumoto/kickstart.nvim.git ~/.config/nvim-river +NVIM_APPNAME=nvim-river nvim ``` -
-
- Adding a file tree plugin +## Updates -This will install the tree plugin and add the command `:Neotree` for you. You can explore the documentation at [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim) for more information. +- Do not use `:Lazy update` on the main branch for routine updates. +- Merge the automated `chore: update locked Neovim plugins` pull request after + its checks pass. +- To test an update locally, run `scripts/nvim-test.sh update`. This uses + isolated data/cache directories and changes only `lazy-lock.json`. +- Restore the committed versions at any time with `:Lazy restore`. -In the file: `lua/custom/plugins/filetree.lua`, add: +The Neovim version is pinned in `.nvim-version`. Upgrade Neovim separately from +plugin updates so failures have one clear cause. -```lua --- Unless you are still migrating, remove the deprecated commands from v1.x -vim.cmd([[ let g:neo_tree_remove_legacy_commands = 1 ]]) +## Design choices -return { - "nvim-neo-tree/neo-tree.nvim", - version = "*", - dependencies = { - "nvim-lua/plenary.nvim", - "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended - "MunifTanjim/nui.nvim", - }, - config = function () - require('neo-tree').setup {} - end, -} -``` - -
- -### FAQ - -* What should I do if I already have a pre-existing neovim configuration? - * You should back it up, then delete all files associated with it. - * This includes your existing init.lua and the neovim files in `~/.local` which can be deleted with `rm -rf ~/.local/share/nvim/` -* Can I keep my existing configuration in parallel to kickstart? - * Yes! You can use [NVIM_APPNAME](https://neovim.io/doc/user/starting.html#%24NVIM_APPNAME)`=nvim-NAME` to maintain multiple configurations. For example you can install the kickstart configuration in `~/.config/nvim-kickstart` and create an alias: - ``` - alias nvim-kickstart='NVIM_APPNAME="nvim-kickstart" nvim' - ``` - When you run Neovim using `nvim-kickstart` alias it will use the alternative config directory and the matching local directory `~/.local/share/nvim-kickstart`. You can apply this approach to any Neovim distribution that you would like to try out. -* What if I want to "uninstall" this configuration: - * See [lazy.nvim uninstall](https://github.com/folke/lazy.nvim#-uninstalling) information -* Why is the kickstart `init.lua` a single file? Wouldn't it make sense to split it into multiple files? - * The main purpose of kickstart is to serve as a teaching tool and a reference - configuration that someone can easily `git clone` as a basis for their own. - As you progress in learning Neovim and Lua, you might consider splitting `init.lua` - into smaller parts. A fork of kickstart that does this while maintaining the exact - same functionality is available here: - * [kickstart-modular.nvim](https://github.com/dam9000/kickstart-modular.nvim) - * Discussions on this topic can be found here: - * [Restructure the configuration](https://github.com/nvim-lua/kickstart.nvim/issues/218) - * [Reorganize init.lua into a multi-file setup](https://github.com/nvim-lua/kickstart.nvim/pull/473) - -### Windows Installation - -Installation may require installing build tools, and updating the run command for `telescope-fzf-native` - -See `telescope-fzf-native` documentation for [more details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation) - -This requires: - -- Install CMake, and the Microsoft C++ Build Tools on Windows - -```lua -{'nvim-telescope/telescope-fzf-native.nvim', build = 'cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release && cmake --install build --prefix build' } -``` - -Alternatively one can install gcc and make which don't require changing the config, -the easiest way is to use choco: - -1. install [chocolatey](https://chocolatey.org/install) -either follow the instructions on the page or use winget, -run in cmd as **admin**: -``` -winget install --accept-source-agreements chocolatey.chocolatey -``` - -2. install all requirements using choco, exit previous cmd and -open a new one so that choco path is set, run in cmd as **admin**: -``` -choco install -y neovim git ripgrep wget fd unzip gzip mingw make -``` - -Then continue with the [Install Kickstart](#Install-Kickstart) step. - - ->>>>>>> afed39f595301147188dac2c5453bce8515d5325 +The version guard, modular setup conventions, native `vim.lsp.config` API, and +current Treesitter `main` API follow the useful compatibility patterns in +[jdhao/nvim-config](https://github.com/jdhao/nvim-config). The system package +installer is intentionally not run from Neovim; editor startup should never ask +for administrator privileges or mutate the operating system. diff --git a/init.lua b/init.lua index d19f6cb9..81872dc7 100644 --- a/init.lua +++ b/init.lua @@ -1,22 +1,29 @@ vim.g.maplocalleader = ' ' vim.g.mapleader = ' ' --- install deps if need to -require 'bootstrap.pacman' +vim.loader.enable() + +local version = vim.version() +if version.major ~= 0 or version.minor ~= 12 then + error(('This config supports Neovim 0.12.x (found %s)'):format(tostring(version))) +end -- ========================= -- Lazy.nvim bootstrap -- ========================= local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' -if not vim.loop.fs_stat(lazypath) then - vim.fn.system { +if not vim.uv.fs_stat(lazypath) then + local result = vim.system({ 'git', 'clone', '--filter=blob:none', 'https://github.com/folke/lazy.nvim.git', '--branch=stable', lazypath, - } + }, { text = true }):wait() + if result.code ~= 0 then + error(('Unable to install lazy.nvim:\n%s'):format(result.stderr or 'unknown error')) + end end vim.opt.rtp:prepend(lazypath) @@ -91,43 +98,46 @@ require('lazy').setup({ { 'nvim-treesitter/nvim-treesitter', + branch = 'main', lazy = false, build = ':TSUpdate', - opts = { - ensure_installed = { - 'lua', - 'rust', - 'python', - 'javascript', - 'typescript', - 'c', - 'c_sharp', - 'cpp', - 'bash', - 'json', - 'yaml', - 'toml', - }, - highlight = { - enable = true, - }, - }, }, { 'MeanderingProgrammer/treesitter-modules.nvim', dependencies = { 'nvim-treesitter/nvim-treesitter' }, - opts = { - incremental_selection = { - enable = true, - keymaps = { - init_selection = '', -- Alt+Space - node_incremental = '', -- Alt+Space (expand) - node_decremental = '', -- Alt+Backspace (shrink) - scope_incremental = '', -- Alt+Shift+Space (scope expand) + config = function() + local parsers = { + 'bash', + 'c', + 'c_sharp', + 'cpp', + 'gdscript', + 'javascript', + 'json', + 'lua', + 'markdown', + 'python', + 'rust', + 'toml', + 'typescript', + 'yaml', + } + + require('treesitter-modules').setup { + ensure_installed = vim.env.NVIM_SKIP_TOOL_INSTALL == '1' and {} or parsers, + highlight = { enable = true }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = '', + node_incremental = '', + node_decremental = '', + scope_incremental = '', + }, }, - }, - }, + } + end, }, 'rhysd/git-messenger.vim', @@ -404,34 +414,6 @@ require('lazy').setup({ end, }, - -- Tooling installer - { - 'WhoIsSethDaniel/mason-tool-installer.nvim', - dependencies = { 'williamboman/mason.nvim' }, - opts = { - ensure_installed = { - 'clangd', - 'clang-format', - 'codelldb', - 'cpplint', - 'cpptools', - 'csharpier', - 'csharp-language-server', - 'lua-language-server', - 'netcoredbg', - 'omnisharp', - 'omnisharp-mono', - 'prettier', - 'ruff', - 'rust-analyzer', - 'sonarlint-language-server', - 'stylua', - }, - auto_update = false, - run_on_start = true, - }, - }, - -- Terminal UX { 'akinsho/toggleterm.nvim', @@ -459,7 +441,7 @@ require('lazy').setup({ function _G.set_terminal_keymaps() local opts = { noremap = true } - vim.diagnostic.disable(0) + vim.diagnostic.enable(false, { bufnr = 0 }) vim.api.nvim_buf_set_keymap(0, 't', '', [[]], opts) end vim.cmd 'autocmd! TermOpen term://* lua set_terminal_keymaps()' @@ -473,7 +455,7 @@ require('lazy').setup({ float_opts = { width = vim.o.columns, height = vim.o.lines }, on_open = function(term) vim.cmd 'startinsert!' - vim.diagnostic.disable(0) + vim.diagnostic.enable(false, { bufnr = 0 }) vim.api.nvim_buf_set_keymap(0, 't', '', 'close', { silent = false, noremap = true }) if vim.fn.mapcheck('', 't') ~= '' then vim.api.nvim_buf_del_keymap(term.bufnr, 't', '') @@ -592,8 +574,8 @@ require('lazy').setup({ { 'neovim/nvim-lspconfig', dependencies = { - { 'williamboman/mason.nvim', config = true }, - 'williamboman/mason-lspconfig.nvim', + { 'mason-org/mason.nvim', config = true }, + 'mason-org/mason-lspconfig.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim', { 'j-hui/fidget.nvim', @@ -660,12 +642,14 @@ require('lazy').setup({ }, }, pyright = { - python = { - analysis = { - autoSearchPaths = true, - diagnosticMode = 'openFilesOnly', - useLibraryCodeForTypes = true, - reportDuplicateImport = true, + settings = { + python = { + analysis = { + autoSearchPaths = true, + diagnosticMode = 'openFilesOnly', + useLibraryCodeForTypes = true, + reportDuplicateImport = true, + }, }, }, }, @@ -692,30 +676,38 @@ require('lazy').setup({ capabilities.textDocument.foldingRange = { dynamicRegistration = false, lineFoldingOnly = true } require('mason').setup { ui = { border = 'rounded' } } + for server_name, server in pairs(servers) do + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + vim.lsp.config(server_name, server) + end + require('mason-lspconfig').setup { - handlers = { - function(server_name) - local server = servers[server_name] or {} - server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - require('lspconfig')[server_name].setup(server) - end, - }, + ensure_installed = vim.env.NVIM_SKIP_TOOL_INSTALL == '1' and {} or vim.tbl_keys(servers), + automatic_enable = true, } require('mason-tool-installer').setup { ensure_installed = { 'clangd', + 'clang-format', 'lua_ls', 'pyright', 'ruff', 'codelldb', 'cpptools', 'cpplint', + 'csharpier', + 'csharp-language-server', + 'netcoredbg', + 'omnisharp', + 'omnisharp-mono', + 'rust-analyzer', + 'sonarlint-language-server', 'stylua', 'prettier', }, auto_update = false, - run_on_start = true, + run_on_start = vim.env.NVIM_SKIP_TOOL_INSTALL ~= '1', start_delay = 3000, debounce_hours = 5, } @@ -801,25 +793,18 @@ require('lazy').setup({ }), }) - require('lspconfig.ui.windows').default_options.border = 'rounded' - vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(vim.lsp.handlers.hover, { border = 'rounded' }) - vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(vim.lsp.handlers.signature_help, { border = 'rounded' }) - - local diagnostic_signs = { - { name = 'DiagnosticSignError', text = ' ' }, - { name = 'DiagnosticSignWarn', text = ' ' }, - { name = 'DiagnosticSignHint', text = ' ' }, - { name = 'DiagnosticSignInfo', text = ' ' }, - } - for _, sign in ipairs(diagnostic_signs) do - vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name }) - end - vim.diagnostic.config { virtual_text = { prefix = '●' }, severity_sort = true, float = { source = 'always' }, - signs = true, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = ' ', + [vim.diagnostic.severity.WARN] = ' ', + [vim.diagnostic.severity.HINT] = ' ', + [vim.diagnostic.severity.INFO] = ' ', + }, + }, } end, }, @@ -862,11 +847,11 @@ require('lazy').setup({ ['end'] = { args.line2, end_line:len() }, } end - require('conform').format { async = true, lsp_fallback = true, range = range } + require('conform').format { async = true, lsp_format = 'fallback', range = range } end, { range = true }) vim.keymap.set('', 'fa', function() - require('conform').format { async = true, lsp_fallback = true } + require('conform').format { async = true, lsp_format = 'fallback' } end, { desc = '[F]ormat [a]ll' }) end, }, @@ -1032,18 +1017,7 @@ require('lazy').setup({ { 'MeanderingProgrammer/render-markdown.nvim', dependencies = { - { - 'nvim-treesitter/nvim-treesitter', - branch = 'main', - config = function() - vim.api.nvim_create_autocmd('FileType', { - pattern = { 'llm', 'markdown' }, - callback = function() - vim.treesitter.start(0, 'markdown') - end, - }) - end, - }, + 'nvim-treesitter/nvim-treesitter', 'nvim-mini/mini.icons', }, -- if you use standalone mini plugins ft = { 'markdown', 'llm' }, @@ -1170,7 +1144,12 @@ require('lazy').setup({ vim.api.nvim_create_user_command('DapResetUI', ":lua require('dapui').open({reset = true})", { desc = 'Reset DAP UI Layout' }) end, }, -}, {}) +}, { + lockfile = vim.fn.stdpath 'config' .. '/lazy-lock.json', + checker = { enabled = false }, + change_detection = { enabled = false, notify = false }, + install = { colorscheme = { 'gruvbox-material', 'habamax' } }, +}) -- ========================================= -- ============ START SMEAR PROFILE ======== @@ -1533,12 +1512,20 @@ vim.keymap.set('x', 'p', [["_dP]], { desc = 'Paste without overwriting r vim.keymap.set('n', 'ya', ':%y+', { desc = 'Yank entire buffer to clipboard' }) -- diagnostics -vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Previous diagnostic' }) -vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Next diagnostic' }) +vim.keymap.set('n', '[d', function() + vim.diagnostic.jump { count = -1, float = true } +end, { desc = 'Previous diagnostic' }) +vim.keymap.set('n', ']d', function() + vim.diagnostic.jump { count = 1, float = true } +end, { desc = 'Next diagnostic' }) vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Show diagnostic under cursor' }) vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Diagnostics to loclist' }) -vim.keymap.set('n', 'dd', vim.diagnostic.disable, { desc = 'Disable diagnostics' }) -vim.keymap.set('n', 'de', vim.diagnostic.enable, { desc = 'Enable diagnostics' }) +vim.keymap.set('n', 'dd', function() + vim.diagnostic.enable(false) +end, { desc = 'Disable diagnostics' }) +vim.keymap.set('n', 'de', function() + vim.diagnostic.enable(true) +end, { desc = 'Enable diagnostics' }) -- misc vim.keymap.set('n', 'cw', ':cd %:p:h:pwd', { desc = 'cd to current file directory' }) @@ -1586,9 +1573,9 @@ vim.keymap.set('n', 'me', ':!chmod +x %:p', { desc = 'Make file exec vim.keymap.set('n', 'P', require('spectre').open, { desc = 'Open Spectre search/replace' }) -- Trouble -vim.keymap.set('n', 'xx', 'TroubleToggle', { silent = true, noremap = true, desc = 'Toggle Trouble' }) -vim.keymap.set('n', 'xw', 'TroubleToggle workspace_diagnostics', { silent = true, noremap = true, desc = 'Workspace diagnostics (Trouble)' }) -vim.keymap.set('n', 'xd', 'TroubleToggle document_diagnostics', { silent = true, noremap = true, desc = 'Document diagnostics (Trouble)' }) +vim.keymap.set('n', 'xx', 'Trouble diagnostics toggle', { silent = true, desc = 'Toggle Trouble diagnostics' }) +vim.keymap.set('n', 'xw', 'Trouble diagnostics toggle', { silent = true, desc = 'Workspace diagnostics (Trouble)' }) +vim.keymap.set('n', 'xd', 'Trouble diagnostics toggle filter.buf=0', { silent = true, desc = 'Document diagnostics (Trouble)' }) -- DAP vim.keymap.set('n', 'dap', ":lua require('dapui').toggle()", { desc = 'Toggle DAP UI' }) @@ -1693,9 +1680,6 @@ vim.api.nvim_set_keymap('i', '', '', { noremap = true }) -- git coauthors vim.keymap.set('n', 'ga', ':Telescope coauthors') --- install treesitter parsers -require('nvim-treesitter').install { 'c', 'rust', 'gdscript', 'c_sharp' } - -- ======== LSP settings =========== -- signature help vim.api.nvim_set_keymap('i', '', 'lua vim.lsp.buf.signature_help()', { noremap = true, silent = true }) diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 00000000..0902ef67 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,62 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "0abc8f390b278c3b4aabc4c004ac8a088b65cf24" }, + "barbar.nvim": { "branch": "master", "commit": "337ecfadb8bf005050990bf2f624dc4fc828dabd" }, + "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, + "cmp-cmdline": { "branch": "main", "commit": "d126061b624e0af6c3a556428712dd4d4194ec6d" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" }, + "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, + "conflict-marker.vim": { "branch": "master", "commit": "62742b2ffe7a433988759c67b5c5a22eff74a14b" }, + "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, + "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, + "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, + "fidget.nvim": { "branch": "main", "commit": "6f793b2bcd2d35e201c09520f698bb763220908a" }, + "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "git-coauthors.nvim": { "branch": "main", "commit": "a31352a63a99e0aff613aa7961d4f5fa955b3d87" }, + "git-messenger.vim": { "branch": "master", "commit": "fd124457378a295a5d1036af4954b35d6b807385" }, + "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, + "gruvbox-material": { "branch": "master", "commit": "5b45305389cac6db2dba0eff338fcae19b867703" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, + "llm.nvim": { "branch": "main", "commit": "a36ef8065fd97e774c90dfde63ff5cfb732958ec" }, + "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, + "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "47059d71b42d74b0a1e9f61c1d99d301039c3b5b" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, + "mini.icons": { "branch": "main", "commit": "e56797f90192d81f1fda02e662fc3e8e3d775027" }, + "neo-tree.nvim": { "branch": "v3.x", "commit": "ebd66767191714e008ce73b769518a763ff31bdc" }, + "neodev.nvim": { "branch": "main", "commit": "46aa467dca16cf3dfe27098042402066d2ae242d" }, + "neoscroll.nvim": { "branch": "master", "commit": "c8d29979cb0cb3a2437a8e0ae683fd82f340d3b8" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" }, + "nvim-cmp": { "branch": "main", "commit": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca" }, + "nvim-dap": { "branch": "master", "commit": "9e848e09a697ee95302a3ef2dd43fd6eb709e570" }, + "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, + "nvim-dap-ui": { "branch": "master", "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" }, + "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, + "nvim-lspconfig": { "branch": "master", "commit": "3371bf298c1f56efc26771ee961f461176958fb5" }, + "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, + "nvim-spectre": { "branch": "master", "commit": "72f56f7585903cd7bf92c665351aa585e150af0f" }, + "nvim-surround": { "branch": "main", "commit": "8b47db616ef658b8fc27e61db2896aa2f40134de" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-web-devicons": { "branch": "master", "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" }, + "onedark.nvim": { "branch": "master", "commit": "df4792accde9db0043121f32628bcf8e645d9aea" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" }, + "smear-cursor.nvim": { "branch": "main", "commit": "9e9378d6ee34bb3782e0e8c63d9ec8ca618b479b" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" }, + "telescope-live-grep-args.nvim": { "branch": "master", "commit": "53e9df55b3651dd7cf77e172f1e8c9a17407acca" }, + "telescope-luasnip.nvim": { "branch": "master", "commit": "07a2a2936a7557404c782dba021ac0a03165b343" }, + "telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "9a88eae817ef395952e08650b3283726786fb5fb" }, + "treesitter-modules.nvim": { "branch": "main", "commit": "290eec96bfc43ed28264661dd30e894a60c4b99c" }, + "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, + "vim-floaterm": { "branch": "master", "commit": "bb4ba7952e906408e1f83b215f55ffe57efcade6" }, + "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, + "vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/lua/bootstrap/pacman.lua b/lua/bootstrap/pacman.lua deleted file mode 100644 index 2dbbf123..00000000 --- a/lua/bootstrap/pacman.lua +++ /dev/null @@ -1,111 +0,0 @@ --- ~/.config/nvim/lua/bootstrap/pacman.lua --- Fix1: run pacman inside a Neovim terminal so sudo has a real TTY. - -local M = {} - -local function has_exe(exe) - return vim.fn.executable(exe) == 1 -end - -local function pacman_has(pkg) - local out = vim.fn.system({ "pacman", "-Qi", pkg }) - return vim.v.shell_error == 0 and out ~= nil and out ~= "" -end - -local function missing_pkgs(pkgs) - local missing = {} - for _, p in ipairs(pkgs) do - if not pacman_has(p) then - table.insert(missing, p) - end - end - return missing -end - -local function shell_escape_arg(s) - -- minimal quoting for a shell command string - return "'" .. tostring(s):gsub("'", [['"'"']]) .. "'" -end - -local function open_install_terminal(pkgs) - if #pkgs == 0 then - return true - end - - if not has_exe("sudo") then - vim.notify("Missing `sudo`; cannot auto-install pacman deps.", vim.log.levels.ERROR) - return false - end - - -- Build a single shell command so sudo prompts normally. - local parts = { "sudo", "pacman", "-S", "--needed" } - for _, p in ipairs(pkgs) do - table.insert(parts, shell_escape_arg(p)) - end - local cmd = table.concat(parts, " ") - - vim.notify("Opening terminal to install:\n" .. table.concat(pkgs, ", "), vim.log.levels.WARN) - - -- Open a terminal split and run the command. User can enter sudo password normally. - vim.cmd("botright 15split") - vim.cmd("terminal " .. cmd) - vim.cmd("startinsert") - - return true -end - -function M.check() - if not has_exe("pacman") then - vim.notify("pacman not found. This bootstrap is Arch-specific.", vim.log.levels.WARN) - return {} - end - local deps = require("bootstrap.deps") - return missing_pkgs(deps) -end - -function M.install(opts) - opts = opts or {} - local miss = M.check() - if #miss == 0 then - if not opts.quiet then - vim.notify("All system deps already installed.", vim.log.levels.INFO) - end - return true - end - - local prompt = "Missing system deps:\n\n" - .. table.concat(miss, "\n") - .. "\n\nOpen a terminal and run sudo pacman to install them?" - - local ok = true - if not opts.force then - ok = (vim.fn.confirm(prompt, "&Yes\n&No", 1) == 1) - end - if not ok then - return false - end - - return open_install_terminal(miss) -end - --- Commands -vim.api.nvim_create_user_command("DepsCheck", function() - local miss = M.check() - if #miss == 0 then - vim.notify("DepsCheck: OK (no missing packages).", vim.log.levels.INFO) - else - vim.notify("DepsCheck missing:\n" .. table.concat(miss, ", "), vim.log.levels.WARN) - end -end, {}) - -vim.api.nvim_create_user_command("DepsInstall", function() - M.install({ force = true }) -end, {}) - --- Run once per session (prompt-based) -if vim.g.__deps_bootstrap_ran ~= true then - vim.g.__deps_bootstrap_ran = true - M.install({ force = false, quiet = true }) -end - -return M diff --git a/scripts/nvim-test.sh b/scripts/nvim-test.sh new file mode 100755 index 00000000..7f7b95dc --- /dev/null +++ b/scripts/nvim-test.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +mode="${1:-restore}" +if [[ "$mode" != "restore" && "$mode" != "update" ]]; then + echo "usage: $0 [restore|update]" >&2 + exit 2 +fi + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +nvim="${NVIM_BIN:-nvim}" +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT + +mkdir -p "$tmp/config" +ln -s "$root" "$tmp/config/nvim" + +export XDG_CONFIG_HOME="$tmp/config" +export XDG_DATA_HOME="$tmp/data" +export XDG_STATE_HOME="$tmp/state" +export XDG_CACHE_HOME="$tmp/cache" +export NVIM_SKIP_TOOL_INSTALL=1 + +"$nvim" --headless "+Lazy! $mode" +qa +"$nvim" --headless \ + "+Lazy load all" \ + "+lua assert(vim.fn.exists(':Lazy') == 2, 'lazy.nvim did not load')" \ + "+lua if vim.v.errmsg ~= '' then print(vim.v.errmsg); vim.cmd('cquit 1') end" \ + +qa + +"$nvim" --headless \ + "+checkhealth vim.deprecated" \ + "+silent write! $tmp/deprecated.txt" \ + +qa + +if grep -q 'WARNING\|ERROR' "$tmp/deprecated.txt"; then + cat "$tmp/deprecated.txt" + exit 1 +fi