diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 2ad4d31ddb0..00000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - - - -## Describe the bug - - -## To Reproduce - -1. ... - -## Desktop - -- OS: -- Terminal: - -## Neovim Version - - -``` -``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..dc8f9dc9fe3 --- /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/stylua.yml b/.github/workflows/stylua.yml deleted file mode 100644 index 75db6c3355b..00000000000 --- a/.github/workflows/stylua.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Check Lua Formatting -name: Check Lua Formatting -on: pull_request_target - -jobs: - stylua-check: - if: github.repository == 'nvim-lua/kickstart.nvim' - name: Stylua Check - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: Stylua Check - uses: JohnnyMorganz/stylua-action@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - version: latest - args: --check . - diff --git a/.github/workflows/update-plugins.yml b/.github/workflows/update-plugins.yml new file mode 100644 index 00000000000..a54f2fd832e --- /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 005b535b606..f7ba19154cb 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 00000000000..60d68b2300b --- /dev/null +++ b/.nvim-version @@ -0,0 +1 @@ +v0.12.2 diff --git a/README.md b/README.md index b6d19f49787..de239a73469 100644 --- a/README.md +++ b/README.md @@ -1,218 +1,50 @@ -# kickstart.nvim +# River's Neovim config -## Introduction +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. -A starting point for Neovim that is: +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. -* Small -* Single-file -* Completely Documented +## Install -**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. - -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, -} -``` - -
-
- Adding a file tree plugin +To try it without replacing another config: -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. - -In the file: `lua/custom/plugins/filetree.lua`, add: - -```lua --- Unless you are still migrating, remove the deprecated commands from v1.x -vim.cmd([[ let g:neo_tree_remove_legacy_commands = 1 ]]) - -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' } +```sh +git clone https://github.com/RiverMatsumoto/kickstart.nvim.git ~/.config/nvim-river +NVIM_APPNAME=nvim-river nvim ``` -Alternatively one can install gcc and make which don't require changing the config, -the easiest way is to use choco: +## Updates -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 -``` +- 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`. -Then continue with the [Install Kickstart](#Install-Kickstart) step. +The Neovim version is pinned in `.nvim-version`. Upgrade Neovim separately from +plugin updates so failures have one clear cause. +## Design choices +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 292ec0779a9..81872dc77cc 100644 --- a/init.lua +++ b/init.lua @@ -1,511 +1,627 @@ ---[[ +vim.g.maplocalleader = ' ' +vim.g.mapleader = ' ' -===================================================================== -==================== READ THIS BEFORE CONTINUING ==================== -===================================================================== -======== .-----. ======== -======== .----------------------. | === | ======== -======== |.-""""""""""""""""""-.| |-----| ======== -======== || || | === | ======== -======== || KICKSTART.NVIM || |-----| ======== -======== || || | === | ======== -======== || || |-----| ======== -======== ||:Tutor || |:::::| ======== -======== |'-..................-'| |____o| ======== -======== `"")----------------(""` ___________ ======== -======== /::::::::::| |::::::::::\ \ no mouse \ ======== -======== /:::========| |==hjkl==:::\ \ required \ ======== -======== '""""""""""""' '""""""""""""' '""""""""""' ======== -======== ======== -===================================================================== -===================================================================== +vim.loader.enable() -What is Kickstart? +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 - Kickstart.nvim is *not* a distribution. +-- ========================= +-- Lazy.nvim bootstrap +-- ========================= +local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' +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) - Kickstart.nvim is a starting point for your own configuration. - The goal is that you can read every line of code, top-to-bottom, understand - what your configuration is doing, and modify it to suit your needs. +-- ========================= +-- PLUGINS +-- ========================= +require('lazy').setup({ + 'voldikss/vim-floaterm', - Once you've done that, you can start exploring, configuring and tinkering to - make Neovim your own! That might mean leaving kickstart just the way it is for a while - or immediately breaking it into modular pieces. It's up to you! + 'tpope/vim-fugitive', - If you don't know anything about Lua, I recommend taking some time to read through - a guide. One possible example which will only take 10-15 minutes: - - https://learnxinyminutes.com/docs/lua/ + 'rhysd/conflict-marker.vim', - After understanding a bit more about Lua, you can use `:help lua-guide` as a - reference for how Neovim integrates Lua. - - :help lua-guide - - (or HTML version): https://neovim.io/doc/user/lua-guide.html + { 'kylechui/nvim-surround', config = true }, -Kickstart Guide: + { 'numToStr/Comment.nvim', opts = {} }, - TODO: The very first thing you should do is to run the command `:Tutor` in Neovim. + { + 'karb94/neoscroll.nvim', + opts = {}, + config = function() + local neoscroll = require 'neoscroll' + + neoscroll.setup { + -- remove / from defaults so your custom maps win + mappings = { + '', + '', + '', + '', + 'zt', + 'zz', + 'zb', + }, + hide_cursor = true, -- Hide cursor while scrolling + stop_eof = true, -- Stop at when scrolling downwards + respect_scrolloff = true, -- Stop scrolling when the cursor reaches the scrolloff margin of the file + cursor_scrolls_alone = true, -- The cursor will keep on scrolling even if the window cannot scroll further + duration_multiplier = 0.3, -- Global duration multiplier + easing = 'quadratic', -- Default easing function + pre_hook = function(info) + if info == 'center' then + vim.cmd 'normal! M' + end + end, + post_hook = nil, + } + local function near_file_edge() + local line = vim.api.nvim_win_get_cursor(0)[1] + local last = vim.api.nvim_buf_line_count(0) + local so = vim.wo.scrolloff + return line <= so + 1 or line >= last - so + end - If you don't know what this means, type the following: - - - - : - - Tutor - - + local modes = { 'n', 'v', 'x' } + + vim.keymap.set(modes, '', function() + neoscroll.ctrl_d { duration = 300 } + if not near_file_edge() then + vim.cmd 'normal! M' + end + end) + + vim.keymap.set(modes, '', function() + neoscroll.ctrl_u { duration = 300 } + if not near_file_edge() then + vim.cmd 'normal! M' + end + end) + end, + }, - (If you already know how the Neovim basics, you can skip this step) + { + 'nvim-treesitter/nvim-treesitter', + branch = 'main', + lazy = false, + build = ':TSUpdate', + }, - Once you've completed that, you can continue working through **AND READING** the rest - of the kickstart init.lua + { + 'MeanderingProgrammer/treesitter-modules.nvim', + dependencies = { 'nvim-treesitter/nvim-treesitter' }, + config = function() + local parsers = { + 'bash', + 'c', + 'c_sharp', + 'cpp', + 'gdscript', + 'javascript', + 'json', + 'lua', + 'markdown', + 'python', + 'rust', + 'toml', + 'typescript', + 'yaml', + } - Next, run AND READ `:help`. - This will open up a help window with some basic information - about reading, navigating and searching the builtin help documentation. + 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, + }, - This should be the first place you go to look when you're stuck or confused - with something. It's one of my favorite neovim features. + 'rhysd/git-messenger.vim', - MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, - which is very useful when you're not sure exactly what you're looking for. + { + 'lewis6991/gitsigns.nvim', + event = 'VeryLazy', + config = function() + require('gitsigns').setup { + signs = { + add = { text = '│' }, + change = { text = '│' }, + delete = { text = '_' }, + topdelete = { text = '‾' }, + changedelete = { text = '~' }, + untracked = { text = '┆' }, + }, + } + end, + }, - I have left several `:help X` comments throughout the init.lua - These are hints about where to find more information about the relevant settings, - plugins or neovim features used in kickstart. + { + 'sindrets/diffview.nvim', + event = 'VeryLazy', + dependencies = { 'nvim-lua/plenary.nvim' }, + }, - NOTE: Look for lines like this + { + 'ErickKramer/git-coauthors.nvim', + dependencies = { 'nvim-telescope/telescope.nvim' }, + }, - Throughout the file. These are for you, the reader, to help understand what is happening. - Feel free to delete them once you know what you're doing, but they should serve as a guide - for when you are first encountering a few different constructs in your nvim config. + -- Editor UX + { + 'windwp/nvim-autopairs', + config = function() + require('nvim-autopairs').setup {} + end, + }, -If you experience any errors while trying to install kickstart, run `:checkhealth` for more info + { + 'iamcco/markdown-preview.nvim', + build = function() + vim.fn['mkdp#util#install']() + end, + config = function() + vim.g.mkdp_refresh_slow = 1 + vim.g.mkdp_page_title = '「${name}」' + vim.g.mkdp_theme = 'dark' + vim.g.mkdp_auto_close = 0 + vim.g.mkdp_combine_preview = 1 + vim.g.mkdp_combine_preview_auto_refresh = 1 + end, + }, -I hope you enjoy your Neovim journey, -- TJ + { + 'sphamba/smear-cursor.nvim', + opts = { + time_interval = 3, + cursor_color = '#ff4000', + particles_enabled = true, + stiffness = 0.5, + trailing_stiffness = 0.2, + trailing_exponent = 5, + damping = 0.6, + gradient_exponent = 0, + gamma = 1, + never_draw_over_target = true, + hide_target_hack = true, + particle_spread = 1, + particles_per_second = 500, + particles_per_length = 50, + particle_max_lifetime = 800, + particle_max_initial_velocity = 20, + particle_velocity_from_cursor = 0.5, + particle_damping = 0.15, + particle_gravity = -50, + min_distance_emit_particles = 0, + }, + }, -P.S. You can delete this when you're done too. It's your config now! :) ---]] + { + 'f4z3r/gruvbox-material.nvim', + name = 'gruvbox-material', + lazy = false, + priority = 1000, + opts = {}, + }, --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) -vim.g.mapleader = ' ' -vim.g.maplocalleader = ' ' + 'mg979/vim-visual-multi', --- [[ Setting options ]] --- See `:help vim.opt` --- NOTE: You can change these options as you wish! --- For more options, you can see `:help option-list` + -- File tree + { + 'nvim-neo-tree/neo-tree.nvim', + branch = 'v3.x', + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-tree/nvim-web-devicons', + 'MunifTanjim/nui.nvim', + }, + opts = { + enable_preview = true, + + filesystem = { + -- open images (and anything else) externally + commands = { + system_open = function(state) + local node = state.tree:get_node() + local path = node:get_id() -- absolute path + vim.fn.jobstart({ 'xdg-open', path }, { detach = true }) + end, + }, + window = { + mappings = { + ['P'] = 'toggle_preview', + ['O'] = 'system_open', -- press O to open with external viewer + }, + }, --- Make line numbers default -vim.opt.number = true --- You can also add relative line numbers, for help with jumping. --- Experiment for yourself to see if you like it! --- vim.opt.relativenumber = true + filtered_items = { + visible = false, + hide_dotfiles = true, + hide_gitignored = true, + hide_by_name = { '.git', '.elc' }, + hide_by_pattern = { '*.uid', 'node_modules' }, + }, + }, + }, + }, --- Enable mouse mode, can be useful for resizing splits for example! -vim.opt.mouse = 'a' + -- LAZY PLUGIN SPEC (replace bufferline with barbar) + { + 'romgrk/barbar.nvim', + dependencies = { + 'nvim-tree/nvim-web-devicons', + 'lewis6991/gitsigns.nvim', -- optional, for git status icons + }, + init = function() + vim.g.barbar_auto_setup = false + end, + opts = { + animation = true, + auto_hide = false, + tabpages = false, -- show buffers, not Vim tabpages + clickable = true, + icons = { + preset = 'slanted', + button = '󰅖', + }, --- Don't show the mode, since it's already in status line -vim.opt.showmode = false + -- Treat neo-tree as a sidebar so it doesn't become a "tab" and layout stays sane + sidebar_filetypes = { + ['neo-tree'] = { event = 'BufWipeout' }, + }, + }, + }, --- Sync clipboard between OS and Neovim. --- Remove this option if you want your OS clipboard to remain independent. --- See `:help 'clipboard'` -vim.opt.clipboard = 'unnamedplus' + 'nvim-tree/nvim-web-devicons', --- Enable break indent -vim.opt.breakindent = true + { + 'folke/todo-comments.nvim', + dependencies = 'nvim-lua/plenary.nvim', + opts = {}, + }, --- Save undo history -vim.opt.undofile = true + -- Flash (treesitter features removed) + { + 'folke/flash.nvim', + event = 'VeryLazy', + opts = {}, + keys = { + { + 'r', + mode = 'o', + function() + require('flash').remote() + end, + desc = 'Remote Flash', + }, + -- NOTE: removed: flash.treesitter(), flash.treesitter_search() + }, + }, --- Case-insensitive searching UNLESS \C or capital in search -vim.opt.ignorecase = true -vim.opt.smartcase = true + { + 'folke/trouble.nvim', + dependencies = 'nvim-tree/nvim-web-devicons', + config = function() + require('trouble').setup { + signs = { + error = '', + warning = '', + hint = '', + information = '', + other = '﫠', + }, + } + end, + }, --- Keep signcolumn on by default -vim.opt.signcolumn = 'yes' + { 'folke/which-key.nvim', opts = {} }, --- Decrease update time -vim.opt.updatetime = 250 -vim.opt.timeoutlen = 300 + { + 'nvim-lualine/lualine.nvim', + config = function() + local function get_venv() + local venv = vim.env.VIRTUAL_ENV + if venv then + local env = string.match(venv, '[^/]+$') + return ' ' .. env + end + return '' + end --- Configure how new splits should be opened -vim.opt.splitright = true -vim.opt.splitbelow = true + require('lualine').setup { + options = { + icons_enabled = true, + theme = 'gruvbox-material', + component_separators = '|', + section_separators = '', + ignore_focus = { + 'dapui_watches', + 'dapui_breakpoints', + 'dapui_scopes', + 'dapui_console', + 'dapui_stacks', + 'dap-repl', + }, + disabled_filetypes = { 'NvimTree' }, + }, + sections = { + lualine_a = { 'mode' }, + lualine_b = { 'branch', 'diff', 'diagnostics' }, + lualine_c = { 'filename' }, + lualine_x = { { get_venv }, 'fileformat', 'filetype' }, + lualine_y = { 'progress' }, + lualine_z = { 'location' }, + }, + } + end, + }, --- Sets how neovim will display certain whitespace in the editor. --- See `:help 'list'` --- and `:help 'listchars'` -vim.opt.list = true -vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } + { 'nvim-pack/nvim-spectre', opts = {} }, --- Preview substitutions live, as you type! -vim.opt.inccommand = 'split' + { + 'lukas-reineke/indent-blankline.nvim', + main = 'ibl', + opts = {}, + config = function() + local highlight = { + 'RainbowRed', + 'RainbowYellow', + 'RainbowBlue', + 'RainbowOrange', + 'RainbowGreen', + 'RainbowViolet', + 'RainbowCyan', + } --- Show which line your cursor is on -vim.opt.cursorline = true + local hooks = require 'ibl.hooks' + hooks.register(hooks.type.HIGHLIGHT_SETUP, function() + vim.api.nvim_set_hl(0, 'RainbowRed', { fg = '#E06C75' }) + vim.api.nvim_set_hl(0, 'RainbowYellow', { fg = '#E5C07B' }) + vim.api.nvim_set_hl(0, 'RainbowBlue', { fg = '#61AFEF' }) + vim.api.nvim_set_hl(0, 'RainbowOrange', { fg = '#D19A66' }) + vim.api.nvim_set_hl(0, 'RainbowGreen', { fg = '#98C379' }) + vim.api.nvim_set_hl(0, 'RainbowViolet', { fg = '#C678DD' }) + vim.api.nvim_set_hl(0, 'RainbowCyan', { fg = '#56B6C2' }) + end) + + require('ibl').setup { + indent = { highlight = highlight, char = '┊' }, + scope = { enabled = false }, + } + end, + }, --- Minimal number of screen lines to keep above and below the cursor. -vim.opt.scrolloff = 10 - --- [[ Basic Keymaps ]] --- See `:help vim.keymap.set()` - --- Set highlight on search, but clear on pressing in normal mode -vim.opt.hlsearch = true -vim.keymap.set('n', '', 'nohlsearch') - --- Diagnostic keymaps -vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous [D]iagnostic message' }) -vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next [D]iagnostic message' }) -vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Show diagnostic [E]rror messages' }) -vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) - --- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier --- for people to discover. Otherwise, you normally need to press , which --- is not what someone will guess without a bit more experience. --- --- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping --- or just use to exit terminal mode -vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) - --- TIP: Disable arrow keys in normal mode --- vim.keymap.set('n', '', 'echo "Use h to move!!"') --- vim.keymap.set('n', '', 'echo "Use l to move!!"') --- vim.keymap.set('n', '', 'echo "Use k to move!!"') --- vim.keymap.set('n', '', 'echo "Use j to move!!"') - --- Keybinds to make split navigation easier. --- Use CTRL+ to switch between windows --- --- See `:help wincmd` for a list of all window commands -vim.keymap.set('n', '', '', { desc = 'Move focus to the left window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the right window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the lower window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the upper window' }) - --- [[ Basic Autocommands ]] --- See `:help lua-guide-autocommands` - --- Highlight when yanking (copying) text --- Try it with `yap` in normal mode --- See `:help vim.highlight.on_yank()` -vim.api.nvim_create_autocmd('TextYankPost', { - desc = 'Highlight when yanking (copying) text', - group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }), - callback = function() - vim.highlight.on_yank() - end, -}) + -- Terminal UX + { + 'akinsho/toggleterm.nvim', + opts = {}, + config = function() + require('toggleterm').setup { + size = 20, + open_mapping = [[]], + hide_numbers = true, + shade_filetypes = {}, + shade_terminals = true, + shading_factor = 2, + start_in_insert = true, + insert_mappings = true, + persist_size = true, + direction = 'float', + close_on_exit = true, + shell = vim.o.shell, + float_opts = { + border = 'curved', + winblend = 0, + highlights = { border = 'Normal', background = 'Normal' }, + }, + } --- [[ 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) + function _G.set_terminal_keymaps() + local opts = { noremap = true } + 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()' + + local Terminal = require('toggleterm.terminal').Terminal + + local lazygit = Terminal:new { + cmd = 'lazygit', + hidden = true, + direction = 'float', + float_opts = { width = vim.o.columns, height = vim.o.lines }, + on_open = function(term) + vim.cmd 'startinsert!' + 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', '') + end + end, + } --- [[ Configure and install plugins ]] --- --- To check the current status of your plugins, run --- :Lazy --- --- You can press `?` in this menu for help. Use `:q` to close the window --- --- To update plugins, you can run --- :Lazy update --- --- NOTE: Here is where you install your plugins. -require('lazy').setup { - -- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). - 'tpope/vim-sleuth', -- Detect tabstop and shiftwidth automatically - - -- NOTE: Plugins can also be added by using a table, - -- with the first argument being the link and the following - -- keys can be used to configure plugin behavior/loading/etc. - -- - -- Use `opts = {}` to force a plugin to be loaded. - -- - -- This is equivalent to: - -- require('Comment').setup({}) - - -- "gc" to comment visual regions/lines - { 'numToStr/Comment.nvim', opts = {} }, + function _G._lazygit_toggle() + lazygit.dir = vim.fn.expand '%:p:h' + lazygit:toggle() + end - -- Here is a more advanced example where we pass configuration - -- options to `gitsigns.nvim`. This is equivalent to the following lua: - -- require('gitsigns').setup({ ... }) - -- - -- See `:help gitsigns` to understand what the configuration keys do - { -- Adds git related signs to the gutter, as well as utilities for managing changes - 'lewis6991/gitsigns.nvim', - opts = { - signs = { - add = { text = '+' }, - change = { text = '~' }, - delete = { text = '_' }, - topdelete = { text = '‾' }, - changedelete = { text = '~' }, - }, - }, + local python = Terminal:new { + cmd = 'ipython3', + direction = 'horizontal', + hidden = true, + hidden_numbers = true, + } + function _G._python_toggle() + python:toggle() + end + + vim.api.nvim_set_keymap('n', 'lg', 'lua _lazygit_toggle()', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('n', 'ip', 'lua _python_toggle()', { noremap = true, silent = true }) + end, }, - -- NOTE: Plugins can also be configured to run lua code when they are loaded. - -- - -- This is often very useful to both group configuration, as well as handle - -- lazy loading plugins that don't need to be loaded immediately at startup. - -- - -- For example, in the following configuration, we use: - -- event = 'VimEnter' - -- - -- which loads which-key before all the UI elements are loaded. Events can be - -- normal autocommands events (`:help autocmd-events`). - -- - -- Then, because we use the `config` key, the configuration only runs - -- after the plugin has been loaded: - -- config = function() ... end - - { -- Useful plugin to show you pending keybinds. - 'folke/which-key.nvim', - event = 'VimEnter', -- Sets the loading event to 'VimEnter' - config = function() -- This is the function that runs, AFTER loading - require('which-key').setup() - - -- Document existing key chains - require('which-key').register { - ['c'] = { name = '[C]ode', _ = 'which_key_ignore' }, - ['d'] = { name = '[D]ocument', _ = 'which_key_ignore' }, - ['r'] = { name = '[R]ename', _ = 'which_key_ignore' }, - ['s'] = { name = '[S]earch', _ = 'which_key_ignore' }, - ['w'] = { name = '[W]orkspace', _ = 'which_key_ignore' }, + { + 'stevearc/dressing.nvim', + opts = {}, + config = function() + require('dressing').setup { + input = { + get_config = function() + return { + title_pos = 'center', + win_options = { sidescrolloff = 10 }, + insert_only = false, + } + end, + }, } end, }, - -- NOTE: Plugins can specify dependencies. - -- - -- The dependencies are proper plugin specifications as well - anything - -- you do for a plugin at the top level, you can do for a dependency. - -- - -- Use the `dependencies` key to specify the dependencies of a particular plugin + { 'navarasu/onedark.nvim', priority = 1000 }, - { -- Fuzzy Finder (files, lsp, etc) + -- Telescope + { 'nvim-telescope/telescope.nvim', - event = 'VimEnter', - branch = '0.1.x', + branch = 'master', dependencies = { 'nvim-lua/plenary.nvim', - { -- If encountering errors, see telescope-fzf-native README for install instructions + { 'nvim-telescope/telescope-fzf-native.nvim', - - -- `build` is used to run some command when the plugin is installed/updated. - -- This is only run then, not every time Neovim starts up. build = 'make', - - -- `cond` is a condition used to determine whether this plugin should be - -- installed and loaded. cond = function() return vim.fn.executable 'make' == 1 end, }, - { 'nvim-telescope/telescope-ui-select.nvim' }, - - -- Useful for getting pretty icons, but requires special font. - -- If you already have a Nerd Font, or terminal set up with fallback fonts - -- you can enable this - -- { 'nvim-tree/nvim-web-devicons' } + 'benfowler/telescope-luasnip.nvim', + 'nvim-telescope/telescope-live-grep-args.nvim', }, config = function() - -- Telescope is a fuzzy finder that comes with a lot of different things that - -- it can fuzzy find! It's more than just a "file finder", it can search - -- many different aspects of Neovim, your workspace, LSP, and more! - -- - -- The easiest way to use telescope, is to start by doing something like: - -- :Telescope help_tags - -- - -- After running this command, a window will open up and you're able to - -- type in the prompt window. You'll see a list of help_tags options and - -- a corresponding preview of the help. - -- - -- Two important keymaps to use while in telescope are: - -- - Insert mode: - -- - Normal mode: ? - -- - -- This opens a window that shows you all of the keymaps for the current - -- telescope picker. This is really useful to discover what Telescope can - -- do as well as how to actually do it! - - -- [[ Configure Telescope ]] - -- See `:help telescope` and `:help telescope.setup()` + local actions = require 'telescope.actions' require('telescope').setup { - -- You can put your default mappings / updates / etc. in here - -- All the info you're looking for is in `:help telescope.setup()` - -- - -- defaults = { - -- mappings = { - -- i = { [''] = 'to_fuzzy_refine' }, - -- }, - -- }, - -- pickers = {} + defaults = { + prompt_prefix = '🔍 ', + vimgrep_arguments = { + 'rg', + '--color=never', + '--no-heading', + '--with-filename', + '--line-number', + '--column', + '--smart-case', + '--follow', + }, + path_display = { truncate = 3 }, + mappings = { + i = { + [''] = actions.select_tab, + [''] = actions.select_vertical, + [''] = actions.select_horizontal, + }, + n = { + [''] = actions.select_tab, + [''] = actions.select_vertical, + [''] = actions.select_horizontal, + }, + }, + }, + pickers = { + find_files = { + find_command = { 'rg', '--files', '--hidden', '-g', '!.git' }, + follow = true, + }, + lsp_document_symbols = { show_line = true }, + }, extensions = { - ['ui-select'] = { - require('telescope.themes').get_dropdown(), + fzf = { + fuzzy = true, + override_generic_sorter = true, + override_file_sorter = true, + case_mode = 'smart_case', }, }, } - - -- Enable telescope extensions, if they are installed - pcall(require('telescope').load_extension, 'fzf') - pcall(require('telescope').load_extension, 'ui-select') - - -- See `:help telescope.builtin` - local builtin = require 'telescope.builtin' - vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) - vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) - vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) - vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) - vim.keymap.set('n', 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) - vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) - vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) - vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) - vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) - vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) - - -- Slightly advanced example of overriding default behavior and theme - vim.keymap.set('n', '/', function() - -- You can pass additional configuration to telescope to change theme, layout, etc. - builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { - winblend = 10, - previewer = false, - }) - end, { desc = '[/] Fuzzily search in current buffer' }) - - -- Also possible to pass additional configuration options. - -- See `:help telescope.builtin.live_grep()` for information about particular keys - vim.keymap.set('n', 's/', function() - builtin.live_grep { - grep_open_files = true, - prompt_title = 'Live Grep in Open Files', - } - end, { desc = '[S]earch [/] in Open Files' }) - - -- Shortcut for searching your neovim configuration files - vim.keymap.set('n', 'sn', function() - builtin.find_files { cwd = vim.fn.stdpath 'config' } - end, { desc = '[S]earch [N]eovim files' }) + require('telescope').load_extension 'fzf' + require('telescope').load_extension 'luasnip' + require('telescope').load_extension 'live_grep_args' end, }, - { -- LSP Configuration & Plugins + -- LSP + { 'neovim/nvim-lspconfig', dependencies = { - -- Automatically install LSPs and related tools to stdpath for neovim - 'williamboman/mason.nvim', - 'williamboman/mason-lspconfig.nvim', + { 'mason-org/mason.nvim', config = true }, + 'mason-org/mason-lspconfig.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim', - - -- Useful status updates for LSP. - -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})` - { 'j-hui/fidget.nvim', opts = {} }, + { + 'j-hui/fidget.nvim', + config = function() + require('fidget').setup { + notification = { + window = { + normal_hl = 'Comment', + border = 'rounded', + zindex = 45, + max_width = 0, + max_height = 0, + x_padding = 1, + y_padding = 0, + align = 'bottom', + relative = 'editor', + }, + }, + } + end, + }, }, config = function() - -- Brief Aside: **What is LSP?** - -- - -- LSP is an acronym 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 }), + group = vim.api.nvim_create_augroup('personal-lsp-attach', { clear = true }), callback = function(event) - -- 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 - -- many times. - -- - -- 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. local map = function(keys, func, desc) vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) end - - -- Jump to the definition of the word under your cursor. - -- This is where a variable was first declared, or where a function is defined, etc. - -- To jump back, press . map('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') - - -- Find references for the word under your cursor. map('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') - - -- Jump to the implementation of the word under your cursor. - -- Useful when your language has ways of declaring types without an actual implementation. map('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') - - -- Jump to the type of the word under your cursor. - -- Useful when you're not sure what type a variable is and you want to see - -- the definition of its *type*, not where it was *defined*. map('D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition') - - -- Fuzzy find all the symbols in your current document. - -- Symbols are things like variables, functions, types, etc. map('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') - - -- Fuzzy find all the symbols in your current workspace - -- Similar to document symbols, except searches over your whole project. map('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') - - -- 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') + map('T', vim.lsp.buf.hover, 'Hover Documentation') + map('', vim.lsp.buf.signature_help, 'Signature Documentation') - -- Opens a popup that displays documentation about the word under your cursor - -- See `:help K` for why this keymap - map('K', 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') - - -- The following two autocommands are used to highlight references of the - -- word under your cursor when your cursor rests there for a little while. - -- See `:help CursorHold` for information about when this is executed - -- - -- When you move your cursor, the highlights will be cleared (the second autocommand). local client = vim.lsp.get_client_by_id(event.data.client_id) if client and client.server_capabilities.documentHighlightProvider then vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { buffer = event.buf, callback = vim.lsp.buf.document_highlight, }) - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { buffer = event.buf, callback = vim.lsp.buf.clear_references, @@ -514,151 +630,90 @@ require('lazy').setup { 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 capabilities = vim.lsp.protocol.make_client_capabilities() - capabilities = vim.tbl_deep_extend('force', capabilities, require('cmp_nvim_lsp').default_capabilities()) - - -- 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 = {}, - -- pyright = {}, - -- 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 = {}, - -- - + clangd = { + cmd = { + 'clangd', + '--background-index', + '--clang-tidy', + '--completion-style=bundled', + '--cross-file-rename', + '--header-insertion=iwyu', + }, + }, + pyright = { + settings = { + python = { + analysis = { + autoSearchPaths = true, + diagnosticMode = 'openFilesOnly', + useLibraryCodeForTypes = true, + reportDuplicateImport = true, + }, + }, + }, + }, lua_ls = { - -- cmd = {...}, - -- filetypes { ...}, - -- capabilities = {}, settings = { Lua = { runtime = { version = 'LuaJIT' }, workspace = { checkThirdParty = false, - -- Tells lua_ls where to find all the Lua files that you have loaded - -- for your neovim configuration. - library = { - '${3rd}/luv/library', - unpack(vim.api.nvim_get_runtime_file('', true)), - }, - -- If lua_ls is really slow on your computer, you can try this instead: - -- library = { vim.env.VIMRUNTIME }, + library = { '${3rd}/luv/library', unpack(vim.api.nvim_get_runtime_file('', true)) }, }, - completion = { - callSnippet = 'Replace', - }, - -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings - -- diagnostics = { disable = { 'missing-fields' } }, + completion = { callSnippet = 'Replace' }, + diagnostics = { globals = { 'vim', 'require' } }, }, }, }, + rust_analyzer = {}, } - -- 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, { - 'stylua', -- Used to format lua code - }) - require('mason-tool-installer').setup { ensure_installed = ensure_installed } + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + capabilities.offsetEncoding = { 'utf-16' } + capabilities.textDocument.completion.completionItem.snippetSupport = true + 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 {} - -- 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, - }, + ensure_installed = vim.env.NVIM_SKIP_TOOL_INSTALL == '1' and {} or vim.tbl_keys(servers), + automatic_enable = true, } - end, - }, - { -- Autoformat - 'stevearc/conform.nvim', - opts = { - notify_on_error = false, - format_on_save = { - timeout_ms = 500, - lsp_fallback = true, - }, - formatters_by_ft = { - lua = { 'stylua' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use a sub-list to tell conform to run *until* a formatter - -- is found. - -- javascript = { { "prettierd", "prettier" } }, - }, - }, - }, - - { -- Autocompletion - 'hrsh7th/nvim-cmp', - event = 'InsertEnter', - dependencies = { - -- Snippet Engine & its associated nvim-cmp source - { - 'L3MON4D3/LuaSnip', - build = (function() - -- Build Step is needed for regex support in snippets - -- This step is not supported in many windows environments - -- Remove the below condition to re-enable on windows - if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then - return - end - return 'make install_jsregexp' - end)(), - }, - 'saadparwaiz1/cmp_luasnip', - - -- Adds other completion capabilities. - -- nvim-cmp does not ship with all sources by default. They are split - -- into multiple repos for maintenance purposes. - 'hrsh7th/cmp-nvim-lsp', - 'hrsh7th/cmp-path', + 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 = vim.env.NVIM_SKIP_TOOL_INSTALL ~= '1', + start_delay = 3000, + debounce_hours = 5, + } - -- If you want to add a bunch of pre-configured snippets, - -- you can use this plugin to help you. It even has snippets - -- for various frameworks/libraries/etc. but you will have to - -- set up the ones that are useful for you. - -- 'rafamadriz/friendly-snippets', - }, - config = function() - -- See `:help cmp` local cmp = require 'cmp' local luasnip = require 'luasnip' - luasnip.config.setup {} cmp.setup { snippet = { @@ -666,156 +721,978 @@ require('lazy').setup { luasnip.lsp_expand(args.body) end, }, - completion = { completeopt = 'menu,menuone,noinsert' }, - - -- For an understanding of why these mappings were - -- chosen, you will need to read `:help ins-completion` - -- - -- No, but seriously. Please read `:help ins-completion`, it is really good! mapping = cmp.mapping.preset.insert { - -- Select the [n]ext item [''] = cmp.mapping.select_next_item(), - -- Select the [p]revious item [''] = cmp.mapping.select_prev_item(), - - -- Accept ([y]es) the completion. - -- This will auto-import if your LSP supports it. - -- This will expand snippets if the LSP sent a snippet. - [''] = cmp.mapping.confirm { select = true }, - - -- Manually trigger a completion from nvim-cmp. - -- Generally you don't need this, because nvim-cmp will display - -- completions whenever it has completion options available. - [''] = cmp.mapping.complete {}, - - -- Think of as moving to the right of your snippet expansion. - -- So if you have a snippet that's like: - -- function $name($args) - -- $body - -- end - -- - -- will move you to the right of each of the expansion locations. - -- is similar, except moving you backwards. - [''] = cmp.mapping(function() - if luasnip.expand_or_locally_jumpable() then + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.abort(), + [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true }, + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump() + else + fallback() end end, { 'i', 's' }), - [''] = cmp.mapping(function() - if luasnip.locally_jumpable(-1) then + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then luasnip.jump(-1) + else + fallback() end end, { 'i', 's' }), }, sources = { - { name = 'nvim_lsp' }, + { name = 'nvim_lsp', max_item_count = 10 }, { name = 'luasnip' }, - { name = 'path' }, + { name = 'path', max_item_count = 5 }, + { name = 'buffer', max_item_count = 5 }, + }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, + } + + function _G.leave_snippet() + if + ((vim.v.event.old_mode == 's' and vim.v.event.new_mode == 'n') or vim.v.event.old_mode == 'i') + and require('luasnip').session.current_nodes[vim.api.nvim_get_current_buf()] + and not require('luasnip').session.jump_active + then + require('luasnip').unlink_current() + end + end + vim.api.nvim_command [[ autocmd ModeChanged * lua leave_snippet() ]] + + local cmp_enabled = true + vim.api.nvim_create_user_command('ToggleAutoComplete', function() + if cmp_enabled then + require('cmp').setup.buffer { enabled = false } + cmp_enabled = false + else + require('cmp').setup.buffer { enabled = true } + cmp_enabled = true + end + end, {}) + + cmp.setup.cmdline('/', { + mapping = cmp.mapping.preset.cmdline(), + sources = { { name = 'buffer' } }, + }) + cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ { name = 'path' } }, { + { name = 'cmdline', option = { ignore_cmds = { 'Man', '!' } } }, + }), + }) + + vim.diagnostic.config { + virtual_text = { prefix = '●' }, + severity_sort = true, + float = { source = 'always' }, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = ' ', + [vim.diagnostic.severity.WARN] = ' ', + [vim.diagnostic.severity.HINT] = ' ', + [vim.diagnostic.severity.INFO] = ' ', + }, }, } end, }, - { -- You can easily change to a different colorscheme. - -- Change the name of the colorscheme plugin below, and then - -- change the command in the config to whatever the name of that colorscheme is - -- - -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme` - 'folke/tokyonight.nvim', - lazy = false, -- make sure we load this during startup if it is your main colorscheme - priority = 1000, -- make sure to load this before all the other start plugins + -- Formatter + { + 'stevearc/conform.nvim', config = function() - -- Load the colorscheme here - vim.cmd.colorscheme 'tokyonight-night' + require('conform').setup { + formatters_by_ft = { + json = { { 'prettierd', 'prettier' } }, + lua = { 'stylua' }, + markdown = { 'prettier' }, + python = function(bufnr) + if require('conform').get_formatter_info('ruff_format', bufnr).available then + return { 'ruff_format' } + end + return { 'isort', 'black' } + end, + yaml = { 'prettier' }, + rust = { 'rustfmt' }, + ['*'] = { 'injected' }, + }, + ignore_errors = true, + -- NOTE: removed treesitter mapping; keep only what you need + lang_to_ext = { + bash = 'sh', + latex = 'tex', + markdown = 'md', + python = 'py', + }, + } - -- You can configure highlights by doing something like - vim.cmd.hi 'Comment gui=none' + 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 + require('conform').format { async = true, lsp_format = 'fallback', range = range } + end, { range = true }) + + vim.keymap.set('', 'fa', function() + require('conform').format { async = true, lsp_format = 'fallback' } + end, { desc = '[F]ormat [a]ll' }) end, }, - -- Highlight todo, notes, etc in comments - { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, + -- Completion + { + 'hrsh7th/nvim-cmp', + dependencies = { + 'L3MON4D3/LuaSnip', + 'saadparwaiz1/cmp_luasnip', + 'hrsh7th/cmp-nvim-lsp', + 'hrsh7th/cmp-buffer', + 'hrsh7th/cmp-path', + 'hrsh7th/cmp-cmdline', + }, + }, + { + 'rafamadriz/friendly-snippets', + config = function() + require('luasnip.loaders.from_vscode').lazy_load() + require('luasnip/loaders/from_vscode').lazy_load { + paths = { vim.fn.stdpath 'config' .. '/snippets' }, + } + end, + }, - { -- Collection of various small independent plugins/modules - 'echasnovski/mini.nvim', + { + 'Kurama622/llm.nvim', + dependencies = { 'nvim-lua/plenary.nvim', 'MunifTanjim/nui.nvim' }, + cmd = { 'LLMSessionToggle', 'LLMSelectedTextHandler', 'LLMAppHandler' }, config = function() - -- Better Around/Inside textobjects - -- - -- Examples: - -- - va) - [V]isually select [A]round [)]paren - -- - yinq - [Y]ank [I]nside [N]ext [']quote - -- - ci' - [C]hange [I]nside [']quote - require('mini.ai').setup { n_lines = 500 } - - -- Add/delete/replace surroundings (brackets, quotes, etc.) - -- - -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren - -- - sd' - [S]urround [D]elete [']quotes - -- - sr)' - [S]urround [R]eplace [)] ['] - require('mini.surround').setup() - - -- Simple and easy statusline. - -- You could remove this setup call if you don't like it, - -- and try some other statusline plugin - local statusline = require 'mini.statusline' - statusline.setup() - - -- You can configure sections in the statusline by overriding their - -- default behavior. For example, here we disable the section for - -- cursor information because line numbers are already enabled - ---@diagnostic disable-next-line: duplicate-set-field - statusline.section_location = function() - return '' - end + require('llm').setup { + -- GitHub Models (Azure inference) + url = 'https://api.openai.com/v1/chat/completions', + api_type = 'openai', + + -- Set this to what you want to use (must support /chat/completions) + model = _G.chatgpt_model or 'gpt-5-nano', + + -- Sensible coding defaults + --max_tokens = 4095, + --temperature = 0.2, + --top_p = 0.1, + + -- Keep it code-focused + prompt = 'You are a helpful programming assistant. Be concise, show code when needed, and prefer practical fixes.', + -- Visual selection -> context prompt + selected_text_handler = { + prompt = function(selection) + return string.format( + 'You are a helpful programming assistant.\n\n' .. 'Context (selected text):\n' .. '```text\n%s\n```\n\n' .. 'Task:\n', + selection + ) + end, + }, + + -- Optional cosmetics (minimal) + spinner = { + text = { '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' }, + hl = 'Title', + }, + prefix = { + user = { text = 'You: ', hl = 'Title' }, + assistant = { text = 'AI: ', hl = 'Added' }, + }, + + -- Persist chat history + save_session = true, + max_history = 30, + max_history_name_length = 40, + + -- Keymaps inside the session UI + keys = { + -- Input window + ['Input:Submit'] = { mode = 'i', key = '' }, -- Enter sends (your issue) + ['Input:Cancel'] = { mode = { 'n', 'i' }, key = '' }, + ['Input:Resend'] = { mode = { 'n', 'i' }, key = '' }, + + -- History (only if save_session=true) + ['Input:HistoryNext'] = { mode = { 'n', 'i' }, key = '' }, + ['Input:HistoryPrev'] = { mode = { 'n', 'i' }, key = '' }, + + -- Output window ("split" style) + ['Output:Ask'] = { mode = 'n', key = 'i' }, + ['Output:Cancel'] = { mode = 'n', key = '' }, + ['Output:Resend'] = { mode = 'n', key = '' }, + + -- Session window ("float" style) + ['Session:Toggle'] = { mode = 'n', key = 'ai' }, -- your chosen toggle + ['Session:Close'] = { mode = 'n', key = { '', 'Q' } }, + }, + + -- Optional diff display used by some tools/handlers + display = { + diff = { + layout = 'vertical', + opts = { + 'internal', + 'filler', + 'closeoff', + 'algorithm:patience', + 'followwrap', + 'linematch:120', + }, + provider = 'mini_diff', + disable_diagnostic = true, + }, + }, - -- ... and there is more! - -- Check out: https://github.com/echasnovski/mini.nvim + callbacks = { + on_response = function(resp) + local usage = resp and resp.usage + if usage then + vim.notify( + string.format( + 'LLM tokens — prompt: %d, completion: %d, total: %d', + usage.prompt_tokens or 0, + usage.completion_tokens or 0, + usage.total_tokens or 0 + ), + vim.log.levels.INFO + ) + end + end, + }, + + -- If you later add tools: + app_handler = { + -- Visual-select text -> run this -> output in a floating result window. + AskWithContext = { + handler = 'attach_to_chat_handler', + prompt = [[ + Answer the user’s question (likely code related) using the context very briefly and concisely: + ]], + opts = { + -- this is the key part: append the visual selection after the prompt + apply_visual_selection = true, -- described in docs for flexi_handler :contentReference[oaicite:2]{index=2} + is_codeblock = true, + enter_input = true, + enter_flexible_window = false, + --exit_on_move = true, + }, + }, + CodeExplain = { + handler = 'flexi_handler', + prompt = 'Explain the following code very briefly, please only return the explanation', + opts = { + enter_flexible_window = true, + }, + }, + }, + } end, + keys = { + { 'ai', 'LLMSessionToggle', mode = 'n', silent = true, desc = 'LLM: toggle session' }, + { 'as', 'LLMSelectedTextHandler', mode = 'x', silent = true, desc = 'LLM: send selection' }, + -- If you add tools: + { 'ax', 'LLMAppHandler CodeExplain', mode = 'x', silent = true, desc = 'LLM tool: Explain' }, + { 'ai', 'LLMAppHandler AskWithContext', mode = 'x', silent = true, desc = 'LLM tool: Ask with context' }, + }, }, - { -- Highlight, edit, and navigate code - 'nvim-treesitter/nvim-treesitter', - build = ':TSUpdate', + { + 'MeanderingProgrammer/render-markdown.nvim', + dependencies = { + 'nvim-treesitter/nvim-treesitter', + 'nvim-mini/mini.icons', + }, -- if you use standalone mini plugins + ft = { 'markdown', 'llm' }, + + config = function() + require('render-markdown').setup { + restart_highlighter = true, + heading = { + enabled = true, + sign = false, + position = 'overlay', -- inline | overlay + icons = { '󰎤 ', '󰎧 ', '󰎪 ', '󰎭 ', '󰎱 ', '󰎳 ' }, + signs = { '󰫎 ' }, + width = 'block', + left_margin = 0, + left_pad = 0, + right_pad = 0, + min_width = 0, + border = false, + border_virtual = false, + border_prefix = false, + above = '▄', + below = '▀', + backgrounds = {}, + foregrounds = { + 'RenderMarkdownH1', + 'RenderMarkdownH2', + 'RenderMarkdownH3', + 'RenderMarkdownH4', + 'RenderMarkdownH5', + 'RenderMarkdownH6', + }, + }, + dash = { + enabled = true, + icon = '─', + width = 0.5, + left_margin = 0.5, + highlight = 'RenderMarkdownDash', + }, + code = { style = 'normal' }, + } + end, + }, + + -- DAP + { + 'mfussenegger/nvim-dap', + dependencies = { + 'mfussenegger/nvim-dap-python', + 'rcarriga/nvim-dap-ui', + 'theHamsta/nvim-dap-virtual-text', + 'nvim-neotest/nvim-nio', + 'folke/neodev.nvim', + }, config = function() - -- [[ Configure Treesitter ]] See `:help nvim-treesitter` + require('neodev').setup { library = { plugins = { 'nvim-dap-ui' }, types = true } } + + local dap = require 'dap' + local sign = vim.fn.sign_define + + sign('DapBreakpoint', { text = ' ', texthl = 'DapBreakpoint', linehl = '', numhl = '' }) + sign('DapBreakpointCondition', { text = ' ', texthl = 'DapBreakpointCondition', linehl = '', numhl = '' }) + sign('DapLogPoint', { text = '◆ ', texthl = 'DapLogPoint', linehl = '', numhl = '' }) + sign('DapStoppedLine', { text = '󰁕 ', texthl = 'DapLogPoint', linehl = '', numhl = '' }) + sign('DapBreakpointRejected', { text = ' ', texthl = 'DapBreakpointRejected', linehl = '', numhl = '' }) + + dap.adapters.codelldb = { + type = 'server', + port = '${port}', + executable = { + command = vim.fn.expand '$HOME/.local/share/nvim/mason/bin/codelldb', + args = { '--port', '${port}' }, + }, + } - ---@diagnostic disable-next-line: missing-fields - require('nvim-treesitter.configs').setup { - ensure_installed = { 'bash', 'c', 'html', 'lua', 'markdown', 'vim', 'vimdoc' }, - -- Autoinstall languages that are not installed - auto_install = true, - highlight = { enable = true }, - indent = { enable = true }, + dap.configurations.cpp = { + { + name = 'C++: Run file', + type = 'codelldb', + request = 'launch', + program = function() + return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') + end, + cwd = '${workspaceFolder}', + stopOnEntry = false, + }, + { + name = 'C++: Attach to process', + type = 'codelldb', + request = 'attach', + pid = require('dap.utils').pick_process, + args = {}, + }, } - -- There are additional nvim-treesitter modules that you can use to interact - -- with nvim-treesitter. You should go explore a few and see what interests you: - -- - -- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod` - -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context - -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects + require('dapui').setup { + controls = { icons = { pause = '⏸ ', play = '▶ ', terminate = '⏹ ' } }, + floating = { border = 'rounded' }, + layouts = { + { + elements = { + { id = 'stacks', size = 0.30 }, + { id = 'breakpoints', size = 0.20 }, + { id = 'scopes', size = 0.50 }, + }, + position = 'left', + size = 40, + }, + { + elements = { { id = 'console', size = 0.50 }, { id = 'repl', size = 0.50 } }, + position = 'bottom', + size = 10, + }, + }, + } + + require('nvim-dap-virtual-text').setup() + require('dap-python').setup() + require('dap-python').test_runner = 'pytest' + + vim.api.nvim_create_user_command('DapUIToggle', ":lua require('dapui').toggle()", {}) + vim.api.nvim_create_user_command('DapPytestMethod', ":lua require('dap-python').test_method()", {}) + 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 ======== +-- ========================================= +local smear = require 'smear_cursor' + +local smear_profiles = { + silver_blade = { + -- General + cursor_color = '#ffe6b2', + smear_between_buffers = true, + smear_between_neighbor_lines = true, + min_horizontal_distance_smear = 0, + min_vertical_distance_smear = 0, + smear_horizontally = true, + smear_vertically = true, + smear_diagonally = true, + smear_to_cmd = true, + scroll_buffer_space = true, + + legacy_computing_symbols_support = false, + legacy_computing_symbols_support_vertical_bars = false, + use_diagonal_blocks = true, + + vertical_bar_cursor = false, + smear_insert_mode = true, + vertical_bar_cursor_insert_mode = true, + smear_replace_mode = false, + smear_terminal_mode = false, + horizontal_bar_cursor_replace_mode = true, + + never_draw_over_target = false, + hide_target_hack = false, + + max_kept_windows = 50, + windows_zindex = 300, + filetypes_disabled = {}, + + -- High FPS (smooth) + time_interval = 7, + delay_disable = nil, + delay_event_to_smear = 1, + delay_after_key = 6, + + -- Physics: fast head, laggy tail, smooth decay + stiffness = 0.95, + trailing_stiffness = 0.33, + anticipation = 0.06, + damping = 0.90, + trailing_exponent = 5.5, + distance_stop_animating = 0.06, + + -- Insert mode: match feel + stiffness_insert_mode = 0.95, + trailing_stiffness_insert_mode = 0.7, + damping_insert_mode = 0.92, + trailing_exponent_insert_mode = 5.5, + distance_stop_animating_vertical_bar = 0.25, + + -- Diagonal + shading tuned for “pretty” + max_slope_horizontal = (1 / 3) / 1.7, + min_slope_vertical = 2 * 1.7, + max_angle_difference_diagonal = math.pi / 18, + max_offset_diagonal = 0.18, + min_shade_no_diagonal = 0.22, + min_shade_no_diagonal_vertical_bar = 0.55, + + -- Rich blending (costly but nice) + color_levels = 24, + gamma = 2.2, + gradient_exponent = 2.8, + max_shade_no_matrix = 0.78, + matrix_pixel_threshold = 0.72, + matrix_pixel_threshold_vertical_bar = 0.28, + matrix_pixel_min_factor = 0.55, + volume_reduction_exponent = 0.22, + minimum_volume_factor = 0.78, + + -- Longer trail + max_length = 34, + max_length_insert_mode = 2, + + -- Particles off + particles_enabled = false, + particle_max_num = 100, + particle_spread = 0.5, + particles_per_second = 200, + particles_per_length = 1.0, + particle_max_lifetime = 300, + particle_lifetime_distribution_exponent = 5, + particle_max_initial_velocity = 10, + particle_velocity_from_cursor = 0.2, + particle_random_velocity = 100, + particle_damping = 0.2, + particle_gravity = 20, + min_distance_emit_particles = 1.5, + particle_switch_octant_braille = 0.3, + particles_over_text = false, + }, + -- 1) Frost Mist + eco_smear = { + -- General (keep core behavior) + cursor_color = '#ffe6b2', + smear_between_buffers = true, + smear_between_neighbor_lines = true, + min_horizontal_distance_smear = 1, -- reduces tiny smears + min_vertical_distance_smear = 1, + smear_horizontally = true, + smear_vertically = true, + smear_diagonally = false, -- big CPU win + smear_to_cmd = true, + scroll_buffer_space = false, -- cheaper on scroll + + legacy_computing_symbols_support = false, + legacy_computing_symbols_support_vertical_bars = false, + use_diagonal_blocks = true, + + vertical_bar_cursor = false, + smear_insert_mode = true, + vertical_bar_cursor_insert_mode = true, + smear_replace_mode = false, + smear_terminal_mode = false, + horizontal_bar_cursor_replace_mode = true, + + never_draw_over_target = false, + hide_target_hack = false, + + max_kept_windows = 20, -- fewer render windows kept + windows_zindex = 300, + filetypes_disabled = {}, + + -- Lower FPS (much cheaper) + time_interval = 14, + delay_disable = nil, + delay_event_to_smear = 2, + delay_after_key = 10, + + -- Physics: still fast head, shorter/cheaper tail + stiffness = 0.90, + trailing_stiffness = 0.28, + anticipation = 0.04, + damping = 0.88, + trailing_exponent = 3.0, + distance_stop_animating = 0.12, + + -- Insert mode: keep it tight + stiffness_insert_mode = 0.90, + trailing_stiffness_insert_mode = 0.28, + damping_insert_mode = 0.90, + trailing_exponent_insert_mode = 3.0, + distance_stop_animating_vertical_bar = 0.30, + + -- Simpler shading (cheaper) + max_slope_horizontal = (1 / 3) / 1.6, + min_slope_vertical = 2 * 1.6, + max_angle_difference_diagonal = math.pi / 16, + max_offset_diagonal = 0.2, + min_shade_no_diagonal = 0.30, + min_shade_no_diagonal_vertical_bar = 0.60, + + -- Reduced blending cost + color_levels = 16, + gamma = 2.2, + gradient_exponent = 1.3, + max_shade_no_matrix = 0.80, + matrix_pixel_threshold = 0.80, + matrix_pixel_threshold_vertical_bar = 0.35, + matrix_pixel_min_factor = 0.65, + volume_reduction_exponent = 0.35, + minimum_volume_factor = 0.82, + + -- Shorter trail + max_length = 18, + max_length_insert_mode = 1, + + -- Particles off + particles_enabled = false, + particle_max_num = 100, + particle_spread = 0.5, + particles_per_second = 200, + particles_per_length = 1.0, + particle_max_lifetime = 300, + particle_lifetime_distribution_exponent = 5, + particle_max_initial_velocity = 10, + particle_velocity_from_cursor = 0.2, + particle_random_velocity = 100, + particle_damping = 0.2, + particle_gravity = 20, + min_distance_emit_particles = 1.5, + particle_switch_octant_braille = 0.3, + particles_over_text = false, + }, +} - -- The following two comments only work if you have downloaded the kickstart repo, not just copy pasted the - -- init.lua. If you want these files, they are in the repository, so you can just download them and - -- put them in the right spots if you want. - - -- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for kickstart - -- - -- Here are some example plugins that I've included in the kickstart repository. - -- Uncomment any of the lines below to enable them (you will need to restart nvim). - -- - -- require 'kickstart.plugins.debug', - -- require 'kickstart.plugins.indent_line', - - -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` - -- This is the easiest way to modularize your config. - -- - -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- For additional information, see `:help lazy.nvim-lazy.nvim-structuring-your-plugins` - -- { import = 'custom.plugins' }, +-- smear settings +local smear_profile_order = { + 'silver_blade', + 'eco_smear', } --- The line beneath this is called `modeline`. See `:help modeline` --- vim: ts=2 sts=2 sw=2 et +local current_idx = 1 + +local function apply_smear_profile(name) + local p = smear_profiles[name] + if not p then + vim.notify('Unknown smear profile: ' .. tostring(name), vim.log.levels.ERROR) + return + end + smear.setup(vim.deepcopy(p)) + vim.g.smear_cursor_profile = name + vim.notify('smear-cursor → ' .. name) +end + +-- Commands +vim.api.nvim_create_user_command('SmearProfile', function(opts) + apply_smear_profile(opts.args) +end, { + nargs = 1, + complete = function() + return smear_profile_order + end, +}) +-- Apply a default on startup (pick one) +apply_smear_profile 'silver_blade' + +vim.api.nvim_create_user_command('SmearProfileNext', function() + current_idx = (current_idx % #smear_profile_order) + 1 + apply_smear_profile(smear_profile_order[current_idx]) +end, {}) + +vim.api.nvim_create_user_command('SmearProfilePrev', function() + current_idx = ((current_idx - 2) % #smear_profile_order) + 1 + apply_smear_profile(smear_profile_order[current_idx]) +end, {}) + +-- Keybindings (edit if you want) +vim.keymap.set('n', 'pn', 'SmearProfileNext', { desc = 'Smear profile: next' }) +vim.keymap.set('n', 'pp', 'SmearProfilePrev', { desc = 'Smear profile: prev' }) + +-- ========================================= +-- ============ END SMEAR PROFILE ========== +-- ========================================= + +-- ========================= +-- Editor settings +-- ========================= +vim.o.hlsearch = false +vim.opt.nu = true +vim.opt.relativenumber = true +vim.o.mouse = 'a' +vim.o.breakindent = true +vim.o.undofile = true +vim.o.ignorecase = true +vim.o.smartcase = true +vim.o.updatetime = 250 +vim.o.timeoutlen = 300 +vim.opt.splitright = true +vim.opt.splitbelow = true +vim.opt.inccommand = 'split' +vim.wo.signcolumn = 'yes' +vim.opt.signcolumn = 'yes:1' +vim.opt.cursorline = true +vim.opt.colorcolumn = '100' +vim.opt.tabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = true +vim.opt.listchars = { trail = '⇲', tab = '◦ ' } +vim.opt.list = true +vim.opt.clipboard = 'unnamedplus' +vim.o.completeopt = 'menuone,noselect' +vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) +vim.opt.termguicolors = true + +-- ============================ +-- ====== TABSTOP START ======= +-- ============================ +local function set_indent(ts) + vim.opt_local.expandtab = true + vim.opt_local.tabstop = ts + vim.opt_local.shiftwidth = ts + vim.opt_local.softtabstop = ts +end + +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'lua', 'javascript', 'typescript', 'tsx', 'json', 'yaml', 'toml', 'html', 'css' }, + callback = function() + set_indent(2) + end, +}) + +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'python', 'sh', 'bash', 'zsh', 'go', 'rust', 'cpp', 'c' }, + callback = function() + set_indent(4) + end, +}) + +-- Makefiles must use real tabs +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'make' }, + callback = function() + vim.opt_local.expandtab = false + vim.opt_local.tabstop = 8 + vim.opt_local.shiftwidth = 8 + vim.opt_local.softtabstop = 0 + end, +}) +-- ============================ +-- ====== TABSTOP END ========= +-- ============================ + +local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true }) +vim.api.nvim_create_autocmd('TextYankPost', { + callback = function() + vim.highlight.on_yank() + end, + group = highlight_group, + pattern = '*', +}) + +local numtogGrp = vim.api.nvim_create_augroup('NumberToggle', { clear = true }) +vim.api.nvim_create_autocmd({ 'BufEnter', 'InsertLeave', 'FocusGained' }, { + pattern = '*', + callback = function() + vim.opt.relativenumber = true + end, + group = numtogGrp, +}) +vim.api.nvim_create_autocmd({ 'BufLeave', 'InsertEnter', 'FocusLost' }, { + pattern = '*', + callback = function() + vim.opt.relativenumber = false + end, + group = numtogGrp, +}) + +-- ========================= +-- Keymaps (treesitter keymaps removed) +-- ========================= + +-- scrolling / search centering, disabled for neoscroll +-- vim.keymap.set('n', '', 'zz', { desc = 'Scroll down and center cursor' }) +-- vim.keymap.set('n', '', 'zz', { desc = 'Scroll up and center cursor' }) +-- vim.keymap.set('n', 'n', 'nzzzv', { desc = 'Next search result and center' }) +-- vim.keymap.set('n', 'N', 'Nzzzv', { desc = 'Previous search result and center' }) + +-- move selected lines +vim.keymap.set('v', 'J', ":m '>+1gv=gv", { desc = 'Move selection down' }) +vim.keymap.set('v', 'K', ":m '<-2gv=gv", { desc = 'Move selection up' }) + +-- window navigation +vim.keymap.set('n', '', 'h', { desc = 'Go to left window' }) +vim.keymap.set('n', '', 'j', { desc = 'Go to lower window' }) +vim.keymap.set('n', '', 'k', { desc = 'Go to upper window' }) +vim.keymap.set('n', '', 'l', { desc = 'Go to right window' }) + +-- clipboard / yank +vim.keymap.set('x', 'p', [["_dP]], { desc = 'Paste without overwriting register' }) +vim.keymap.set('n', 'ya', ':%y+', { desc = 'Yank entire buffer to clipboard' }) + +-- diagnostics +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', 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' }) +vim.keymap.set('n', '', '', { noremap = true, desc = 'Jump forward in jumplist' }) +vim.keymap.set('n', '', ':write', { desc = 'Save file' }) +vim.keymap.set('i', '', ':write', { desc = 'Save file' }) +vim.keymap.set('n', 'cd', ':ToggleAutoComplete', { desc = 'Toggle autocomplete' }) +vim.keymap.set('n', 'ce', ':ToggleAutoComplete', { desc = 'Toggle autocomplete (alias)' }) + +-- Telescope +vim.keymap.set('n', '?', require('telescope.builtin').oldfiles, { desc = 'Find recently opened files' }) +vim.keymap.set('n', '', require('telescope.builtin').buffers, { desc = 'List open buffers' }) +vim.keymap.set('n', '/', function() + require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + previewer = false, + sorting_strategy = 'ascending', + }) +end, { desc = 'Fuzzy search in current buffer' }) + +vim.keymap.set('n', 'sf', require('telescope.builtin').find_files, { desc = 'Find files' }) +vim.keymap.set('n', 'sh', require('telescope.builtin').help_tags, { desc = 'Search help tags' }) +vim.keymap.set('n', 'sw', require('telescope.builtin').grep_string, { desc = 'Search word under cursor' }) +vim.keymap.set('n', 'sg', require('telescope.builtin').live_grep, { desc = 'Live grep' }) +vim.keymap.set('n', 'sd', require('telescope.builtin').diagnostics, { desc = 'Search diagnostics' }) +vim.keymap.set('n', 'sp', require('telescope.builtin').spell_suggest, { desc = 'Spell suggestions' }) +vim.keymap.set('n', 'sk', require('telescope.builtin').keymaps, { desc = 'Search keymaps' }) +vim.keymap.set('n', 'gf', require('telescope.builtin').git_files, { desc = 'Find git files' }) +vim.keymap.set('n', 'sc', require('telescope.builtin').git_commits, { desc = 'Search git commits' }) +vim.keymap.set('n', 'sr', require('telescope.builtin').resume, { desc = 'Resume last Telescope picker' }) + +vim.keymap.set('n', 's/', function() + require('telescope.builtin').live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } +end, { desc = 'Live grep in open files' }) + +vim.keymap.set('n', 'sn', function() + require('telescope.builtin').find_files { cwd = vim.fn.stdpath 'config' } +end, { desc = 'Search Neovim config files' }) + +-- run / permissions +vim.keymap.set('n', 'ru', ':w:!%:p', { desc = 'Save and run current file' }) +vim.keymap.set('n', 'me', ':!chmod +x %:p', { desc = 'Make file executable' }) +vim.keymap.set('n', 'P', require('spectre').open, { desc = 'Open Spectre search/replace' }) + +-- 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' }) +vim.keymap.set('n', 'dc', ":lua require('dap').continue()", { desc = 'DAP continue' }) +vim.keymap.set('n', 'do', ":lua require('dap').step_over()", { desc = 'DAP step over' }) +vim.keymap.set('n', 'di', ":lua require('dap').step_into()", { desc = 'DAP step into' }) +vim.keymap.set('n', 'dk', function() + require('dap.ui.widgets').hover() +end, { desc = 'DAP hover value' }) +vim.keymap.set('n', 'd?', function() + local widgets = require 'dap.ui.widgets' + widgets.centered_float(widgets.scopes) +end, { desc = 'DAP scopes' }) +vim.keymap.set('n', 'du', ":lua require('dap').step_out()", { desc = 'DAP step out' }) +vim.keymap.set('n', 'dl', ":lua require('dapui').float_element()", { silent = true, noremap = true, desc = 'DAP floating window' }) +vim.keymap.set('n', 'dt', ":lua require('dap').toggle_breakpoint()", { silent = true, noremap = true, desc = 'Toggle breakpoint' }) +vim.keymap.set('n', 'dm', ":lua require('dap-python').test_method()", { silent = true, noremap = true, desc = 'DAP test method' }) +vim.keymap.set('n', 'df', ":lua require('dap-python').test_class()", { silent = true, noremap = true, desc = 'DAP test class' }) + +-- bufferline + +local opts = { noremap = true, silent = true } + +-- KEYMAPS (Barbar) +local opts = { noremap = true, silent = true } + +vim.keymap.set('n', '', 'BufferGoto 1', vim.tbl_extend('force', opts, { desc = 'Go to buffer 1' })) +vim.keymap.set('n', '', 'BufferGoto 2', vim.tbl_extend('force', opts, { desc = 'Go to buffer 2' })) +vim.keymap.set('n', '', 'BufferGoto 3', vim.tbl_extend('force', opts, { desc = 'Go to buffer 3' })) +vim.keymap.set('n', '', 'BufferGoto 4', vim.tbl_extend('force', opts, { desc = 'Go to buffer 4' })) +vim.keymap.set('n', '', 'BufferGoto 5', vim.tbl_extend('force', opts, { desc = 'Go to buffer 5' })) +vim.keymap.set('n', '', 'BufferGoto 6', vim.tbl_extend('force', opts, { desc = 'Go to buffer 6' })) +vim.keymap.set('n', '', 'BufferGoto 7', vim.tbl_extend('force', opts, { desc = 'Go to buffer 7' })) +vim.keymap.set('n', '', 'BufferGoto 8', vim.tbl_extend('force', opts, { desc = 'Go to buffer 8' })) +vim.keymap.set('n', '', 'BufferGoto 9', vim.tbl_extend('force', opts, { desc = 'Go to buffer 9' })) +vim.keymap.set('n', '', 'BufferLast', vim.tbl_extend('force', opts, { desc = 'Go to last buffer' })) +-- Close current buffer (Barbar) +vim.keymap.set('n', '', 'BufferClose', vim.tbl_extend('force', opts, { desc = 'Close buffer' })) + +-- Close current window/split +vim.keymap.set('n', '', 'close', vim.tbl_extend('force', opts, { desc = 'Close window' })) + +vim.keymap.set('n', '', 'BufferNext', { desc = 'Go to next buffer' }) +vim.keymap.set('n', '', 'BufferPrevious', { desc = 'Go to previous buffer' }) + +-- barbar colors + +-- quickfix +vim.keymap.set('n', 'cn', ':cnext', { desc = 'Next quickfix item' }) +vim.keymap.set('n', 'cp', ':cprevious', { desc = 'Previous quickfix item' }) + +-- markdown +vim.keymap.set('n', 'mp', ':MarkdownPreview', { desc = 'Markdown preview' }) + +-- git +vim.keymap.set('n', 'ga', ':Telescope coauthors', { desc = 'Select git co-authors' }) + +-- delete backwards +vim.keymap.set({ 'i', 'c' }, '', '', { noremap = true, desc = 'Delete previous word' }) + +vim.keymap.set('n', 'tc', ':tabclose', { desc = 'Close current tab' }) +vim.keymap.set('n', 'fk', ':FloatermKill!', { desc = 'Kill all floaterm terminals' }) +vim.keymap.set('x', 'S', '(nvim-surround-visual)', { remap = true }, { desc = 'Surround selected text' }) + +-- yank binding +vim.api.nvim_set_keymap('n', 'Y', 'yy', { noremap = true, silent = true }) + +-- exit and save +vim.keymap.set('n', '', 'wqa') + +-- split views +vim.keymap.set('n', 'sv', 'vsplit') +vim.keymap.set('n', 'sh', 'split') + +-- toggle neotree +local function toggle_neotree() + local manager = require 'neo-tree.sources.manager' + local renderer = require 'neo-tree.ui.renderer' + local state = manager.get_state 'filesystem' + local window_exists = renderer.window_exists(state) + if window_exists then + vim.cmd 'Neotree close' + else + vim.cmd 'Neotree show' + end +end +_G.toggle_neotree = toggle_neotree +vim.api.nvim_set_keymap('n', '', ':lua toggle_neotree()', { noremap = true, silent = true }) + +-- Floaterm +vim.api.nvim_set_keymap('n', '', ':FloatermToggle', { noremap = true }) +vim.api.nvim_set_keymap('i', '', ':FloatermToggle', { noremap = true }) +vim.api.nvim_set_keymap('t', '', ':FloatermToggle', { noremap = true, silent = true }) + +-- Comment.nvim keymaps +vim.api.nvim_set_keymap('n', '', 'lua require("Comment.api").toggle.linewise.current()', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('n', '', 'lua require("Comment.api").toggle.blockwise.current()', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('v', '', 'lua require("Comment.api").toggle.linewise(vim.fn.visualmode())', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('v', '', 'lua require("Comment.api").toggle.blockwise(vim.fn.visualmode())', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('i', '', '', { noremap = true }) + +-- git coauthors +vim.keymap.set('n', 'ga', ':Telescope coauthors') + +-- ======== LSP settings =========== +-- signature help +vim.api.nvim_set_keymap('i', '', 'lua vim.lsp.buf.signature_help()', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('n', '', 'lua vim.lsp.buf.signature_help()', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('i', '', 'lua vim.lsp.buf.hover()', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('n', '', 'lua vim.lsp.buf.hover()', { noremap = true, silent = true }) +-- code actions (normal + insert) +vim.keymap.set({ 'n', 'i' }, '', vim.lsp.buf.code_action, { silent = true, desc = 'Code Action' }) +-- rename bindings +vim.keymap.set('n', '', vim.lsp.buf.rename, { silent = true, desc = 'LSP: Rename' }) +vim.keymap.set('n', '', vim.lsp.buf.definition, { silent = true, desc = 'LSP: Go To Defintion' }) + +-- put after colorscheme load +vim.api.nvim_set_hl(0, '@lsp.type.typeAlias', { link = 'Type' }) +vim.api.nvim_set_hl(0, '@lsp.type.type', { link = 'Type' }) +vim.api.nvim_set_hl(0, '@lsp.type.struct', { link = 'Type' }) diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 00000000000..0902ef6795c --- /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/deps.lua b/lua/bootstrap/deps.lua new file mode 100644 index 00000000000..d80c82fba39 --- /dev/null +++ b/lua/bootstrap/deps.lua @@ -0,0 +1,33 @@ +-- lua/bootstrap/deps.lua +-- System-level deps for this config (Arch / pacman names) + +return { + -- bootstrap + "neovim", + "git", + + -- telescope / grep + "ripgrep", + "fd", + + -- builds native plugins (telescope-fzf-native, treesitter parsers, etc.) + "base-devel", + + -- clipboard (Wayland) + "wl-clipboard", + -- X11 alternative (optional): "xclip", + + -- markdown-preview.nvim build/runtime + "nodejs", + "npm", + + -- toggleterm custom commands + "lazygit", + + -- neo-tree external opener + "imv", + + -- -- treesitter + -- "tree-sitter-cli", +} + diff --git a/lua/custom/plugins/autopairs.lua b/lua/custom/plugins/autopairs.lua new file mode 100644 index 00000000000..529c3308ed5 --- /dev/null +++ b/lua/custom/plugins/autopairs.lua @@ -0,0 +1,12 @@ +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, +} diff --git a/lua/custom/plugins/filetree.lua b/lua/custom/plugins/filetree.lua new file mode 100644 index 00000000000..bec15faaf7a --- /dev/null +++ b/lua/custom/plugins/filetree.lua @@ -0,0 +1,15 @@ +-- Unless you are still migrating, remove the deprecated commands from v1.x +vim.cmd [[ let g:neo_tree_remove_legacy_commands = 1 ]] + +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, +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..b7ea3d5e12b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "nvim", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/package.json b/package.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/package.json @@ -0,0 +1 @@ +{} diff --git a/scripts/nvim-test.sh b/scripts/nvim-test.sh new file mode 100755 index 00000000000..7f7b95dc629 --- /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