diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000000..4f3412e8853 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,42 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this repo is + +A personal Neovim config forked from [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim). Loaded by Neovim from `~/.config/nvim`. There is no build/test step — changes take effect by restarting `nvim` (or `:source %` / `:Lazy reload ` for some edits). + +## Architecture + +- `init.lua` — entrypoint. Sets options, global keymaps, autocmds, bootstraps `lazy.nvim`, then loads every file under `lua/custom/plugins/` via `{ import = 'custom.plugins' }`. The kickstart single-file model has been broken out: only base options/keymaps live here; plugin specs live in their own files. +- `lua/custom/plugins/*.lua` — one file per plugin (or tightly related group). Each returns a lazy.nvim spec table (or list of specs). Adding a new plugin = create a new file here; it is picked up automatically. No central manifest to update. +- `lua/custom/zed-keymaps.lua` — mirrors Zed bindings (alt-j/k line move, F2 rename, `.` code action, `gb` blame, `x` close buffer, task spawners). Required directly from `init.lua` before lazy setup. Task spawner prefers a floating zellij pane (`$ZELLIJ` set) and falls back to an `nvim` split terminal. +- `lua/custom/health.lua` — backs `:checkhealth kickstart`. +- `lazy-lock.json` — committed; pin plugin versions. Update via `:Lazy update` then commit. +- `lua/kickstart/` does **not** exist in this fork (upstream kickstart had it). Don't add files there; everything custom lives under `lua/custom/`. + +### Key conventions baked into the config + +- **Leader = Space** (both `mapleader` and `maplocalleader`). +- **Window navigation** (``) is owned by `smart-splits.nvim` (`lua/custom/plugins/tmux.lua`) with `multiplexer_integration = 'zellij'` — at a split edge it forwards focus to the zellij pane. Don't re-bind these in `init.lua`. +- **LSP** is wired in `lua/custom/plugins/lsp.lua`. Servers configured: `clangd`, `gopls`, `pyright` (organize-imports disabled, lint suppressed — `ruff` handles both), `ruff` (hover disabled — `pyright` handles), `lua_ls`. Mason auto-installs them plus `stylua`, `jdtls`, `google-java-format`. Buffer-local LSP keymaps (`gd`, `gr`, `gI`, `rn`, `ca`, …) are set in the `LspAttach` autocmd — add new LSP keybindings there, not globally. Inlay hints are forced on for Go buffers. +- **Go imports** are organized on `BufWritePre` for `*.go` via a `source.organizeImports` code action (`lsp.lua`). +- **Formatting** is `conform.nvim` (`conform.lua`); `format_on_save` runs with `timeout_ms = 500` and LSP fallback (disabled for `c`/`cpp`). Per-ft formatters: `stylua` (lua), `ruff_organize_imports`+`ruff_format` (python), `google-java-format` (java), `terraform_fmt`, prettier (js/xml). +- **Per-filetype `colorcolumn`** is set by a `FileType` autocmd in `init.lua` (python 80, lua 100, go 120, rust 100, java 120). Other filetypes have no ruler. +- **Buffer switching**: ``..`` jump to `vim.t.bufs[i]` (populated by `mini.bufremove`/`mini.tabline` from `mini.lua`). +- **`;` is remapped to `:`** in normal mode. `` clears search highlight. + +## Formatting / lint for files in this repo + +Lua files are formatted with **stylua** using `.stylua.toml` (2-space indent, single quotes preferred, 160-col width, no call parens). Run via `f` or `:Format`, or from a shell: `stylua .`. There is no test suite. + +## Adding / modifying plugins + +- New plugin → new file in `lua/custom/plugins/`, return a lazy spec. No need to edit `init.lua`. +- After edits: `:Lazy sync` (install/update/clean) or restart Neovim. Commit `lazy-lock.json` along with spec changes so the lock stays reproducible. +- Use `:checkhealth` and `:Mason` to verify tool installation. + +## Repo-specific style notes + +- `.stylua.toml` enforces single quotes and no call parens — keep `require 'foo'` style (not `require('foo')`) in plain calls; conform/lazy spec tables of course still use parens where required. +- Existing files have heavy kickstart-original tutorial comments. When editing those files, leave the surrounding teaching comments intact unless the user asks for cleanup; for new files, follow the global comment policy (terse, only when WHY is non-obvious). diff --git a/README.md b/README.md index aa5f4fc8f1e..bf8a3a787af 100644 --- a/README.md +++ b/README.md @@ -1,238 +1,208 @@ -# kickstart.nvim +# nvim -## Introduction +Personal Neovim config, originally forked from [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim) and broken into per-plugin files. Lives at `~/.config/nvim`. -A starting point for Neovim that is: +## Layout -* Small -* Single-file -* Completely Documented - -**NOT** a Neovim distribution, but instead a starting point for your configuration. - -## Installation - -### Install Neovim - -Kickstart.nvim targets *only* the latest -['stable'](https://github.com/neovim/neovim/releases/tag/stable) and latest -['nightly'](https://github.com/neovim/neovim/releases/tag/nightly) of Neovim. -If you are experiencing issues, please make sure you have the latest versions. - -### Install External Dependencies - -External Requirements: -- Basic utils: `git`, `make`, `unzip`, C Compiler (`gcc`) -- [ripgrep](https://github.com/BurntSushi/ripgrep#installation) -- Clipboard tool (xclip/xsel/win32yank or other depending on the platform) -- A [Nerd Font](https://www.nerdfonts.com/): optional, provides various icons - - if you have it set `vim.g.have_nerd_font` in `init.lua` to true -- Language Setup: - - If you want to write Typescript, you need `npm` - - If you want to write Golang, you will need `go` - - etc. - -> **NOTE** -> See [Install Recipes](#Install-Recipes) for additional Windows and Linux specific notes -> and quick install snippets - -### Install Kickstart - -> **NOTE** -> [Backup](#FAQ) your previous configuration (if any exists) - -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)| `%localappdata%\nvim\` | -| Windows (powershell)| `$env:LOCALAPPDATA\nvim\` | - -#### Recommended Step - -[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, then install by cloning the -fork to your machine using one of the commands below, depending on your OS. - -> **NOTE** -> Your fork's URL will be something like this: -> `https://github.com//kickstart.nvim.git` - -You likely want to remove `lazy-lock.json` from your fork's `.gitignore` file -too - it's ignored in the kickstart repo to make maintenance easier, but it's -[recommended to track it in version control](https://lazy.folke.io/usage/lockfile). - -#### Clone kickstart.nvim -> **NOTE** -> If following the recommended step above (i.e., forking the repo), replace -> `nvim-lua` with `` in the commands below - -
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`: - +init.lua -- options, global keymaps, autocmds, lazy bootstrap +lua/custom/ +├── zed-keymaps.lua -- Zed-parity bindings + task spawners +├── health.lua -- :checkhealth kickstart +└── plugins/*.lua -- one file per plugin; auto-imported by lazy +lazy-lock.json -- committed, pinned plugin versions ``` -git clone https://github.com/nvim-lua/kickstart.nvim.git "%localappdata%\nvim" -``` - -If you're using `powershell.exe` -``` -git clone https://github.com/nvim-lua/kickstart.nvim.git "${env:LOCALAPPDATA}\nvim" -``` +No build/test step. Changes take effect on `nvim` restart (or `:source %` / `:Lazy reload `). Lua is formatted by `stylua` per `.stylua.toml` (2-space, single quotes, 160-col). -
+## Install -### Post Installation - -Start Neovim +Requires Neovim stable or nightly, plus: `git`, `make`, a C compiler, `ripgrep`, a clipboard tool, and a [Nerd Font](https://www.nerdfonts.com/). Optional: `npm`, `go`, `python`, `java` for the respective LSPs. ```sh +git clone "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim nvim ``` -That's it! Lazy will install all the plugins you have. Use `:Lazy` to view -the current plugin status. Hit `q` to close the window. - -#### Read The Friendly Documentation - -Read through the `init.lua` file in your configuration folder for more -information about extending and exploring Neovim. That also includes -examples of adding popularly requested plugins. - -> [!NOTE] -> For more information about a particular plugin check its repository's documentation. - - -### Getting Started - -[The Only Video You Need to Get Started with Neovim](https://youtu.be/m8C0Cq9Uv9o) - -### FAQ - -* What should I do if I already have a pre-existing Neovim configuration? - * You should back it up and then delete all associated files. - * 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://lazy.folke.io/usage#-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 use to `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 - 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) - -### Install Recipes - -Below you can find OS specific install instructions for Neovim and dependencies. - -After installing all the dependencies continue with the [Install Kickstart](#Install-Kickstart) step. - -#### Windows Installation - -
Windows with Microsoft C++ Build Tools and CMake -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' } -``` -
-
Windows with gcc/make using chocolatey -Alternatively, one can install gcc and make which don't require changing the config, -the easiest way is to use choco: - -1. install [chocolatey](https://chocolatey.org/install) -either follow the instructions on the page or use winget, -run in cmd as **admin**: -``` -winget install --accept-source-agreements chocolatey.chocolatey -``` - -2. install all requirements using choco, exit the previous cmd and -open a new one so that choco path is set, and run in cmd as **admin**: -``` -choco install -y neovim git ripgrep wget fd unzip gzip mingw make -``` -
-
WSL (Windows Subsystem for Linux) - -``` -wsl --install -wsl -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip neovim -``` -
- -#### Linux Install -
Ubuntu Install Steps - -``` -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip neovim -``` -
-
Debian Install Steps - -``` -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip curl - -# Now we install nvim -curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz -sudo rm -rf /opt/nvim-linux64 -sudo mkdir -p /opt/nvim-linux64 -sudo chmod a+rX /opt/nvim-linux64 -sudo tar -C /opt -xzf nvim-linux64.tar.gz - -# make it available in /usr/local/bin, distro installs to /usr/bin -sudo ln -sf /opt/nvim-linux64/bin/nvim /usr/local/bin/ -``` -
-
Fedora Install Steps - -``` -sudo dnf install -y gcc make git ripgrep fd-find unzip neovim -``` -
- -
Arch Install Steps - -``` -sudo pacman -S --noconfirm --needed gcc make git ripgrep fd unzip neovim -``` -
- +On first launch `lazy.nvim` installs every plugin under `lua/custom/plugins/`, and Mason installs the LSPs/formatters listed in `lsp.lua`. Run `:Lazy`, `:Mason`, `:checkhealth` to verify. + +## Editor defaults (`init.lua`) + +- Leader and localleader are **Space**. +- `relativenumber`, `cursorline`, `signcolumn=yes`, `scrolloff=8`, `splitright`/`splitbelow`. +- `spell` on (`en_us`); `undofile` on; `inccommand=split` for live substitution preview. +- `ignorecase` + `smartcase`; `timeoutlen=300`, `updatetime=250`. +- Per-filetype `colorcolumn`: python 80, lua 100, rust 100, go 120, java 120. Off everywhere else. +- Yank highlight on `TextYankPost`; clipboard synced to `unnamedplus` after UI ready. + +## Plugins + +| File | Plugin | Purpose | +| :--- | :--- | :--- | +| `lsp.lua` | `nvim-lspconfig` + Mason + `fidget.nvim` + `lazydev` | LSP for `clangd`, `gopls`, `pyright`, `ruff`, `lua_ls`; auto-installs `stylua`, `jdtls`, `google-java-format` | +| `cmp.lua` | `blink.cmp` | Completion (capabilities fed to LSP) | +| `conform.lua` | `conform.nvim` | Format on save (500ms timeout, LSP fallback; off for c/cpp/json/xml/html) | +| `lint.lua` | `nvim-lint` | Linting | +| `treesitter.lua` | `nvim-treesitter` (`main` branch) + textobjects | Highlight, indent, function/class/param motions | +| `treesitter-context.lua` | `nvim-treesitter-context` | Sticky context header | +| `telescope.lua` | `telescope.nvim` + `fzf-native` + `ui-select` | Fuzzy finder | +| `neo-tree.lua` | `neo-tree.nvim` | File tree (auto-opens on `nvim` / `nvim `) | +| `harpoon.lua` | `harpoon2` | Quick file marks | +| `gitsigns.lua` | `gitsigns.nvim` | Gutter signs, line blame (300ms), hunk actions | +| `lazygit.lua` | `lazygit.nvim` | Lazygit popup | +| `trouble.lua` | `trouble.nvim` | Diagnostics / refs / qflist panel | +| `todo.lua` | `todo-comments` | Highlight `TODO/FIX/HACK/...` | +| `toggleterm.lua` | `toggleterm.nvim` | Float / split terminals | +| `tmux.lua` | `smart-splits.nvim` | `` nav across nvim splits ↔ zellij panes | +| `mini.lua` | `mini.ai`, `mini.move`, `mini.notify`, `mini.starter`, `mini.statusline` | Misc utilities + statusline | +| `leap.lua` | `flash.nvim` | `s`/`S` motions, remote ops | +| `persistence.lua` | `persistence.nvim` | Per-cwd auto session | +| `which-key.lua` | `which-key.nvim` | Keybind popup | +| `copilot.lua` | `copilot.vim` | Inline suggestions (accept on ``) | +| `copilot-chat.lua` | `CopilotChat.nvim` | In-editor chat | +| `render-markdown.lua` | `render-markdown.nvim` | Pretty markdown in buffer | +| `markdown-preview.lua` | `markdown-preview.nvim` | Browser preview | +| `gruvbox.lua` | gruvbox | Colorscheme | +| `neoscroll.lua` | `neoscroll.nvim` | Smooth scrolling | +| `illuminate.lua` | `vim-illuminate` | Highlight word under cursor | +| `indent_line.lua` | `indent-blankline` | Indent guides | +| `autopairs.lua` | `nvim-autopairs` | Bracket pairs | +| `nvim-surround.lua` | `nvim-surround` | Surround motions | +| `dressing.lua` | `dressing.nvim` | Better `vim.ui` prompts | +| `sleuth.lua` | `vim-sleuth` | Auto-detect indent | +| `java.lua` | `nvim-jdtls` | Java LSP wrapper | +| `debug.lua` | `nvim-dap` + UI | Debugger | + +## Keymaps + +### Movement & editing (`init.lua` / `zed-keymaps.lua`) +| Key | Mode | Action | +| :--- | :--- | :--- | +| `;` | n | `:` (command mode) | +| `` | n | Clear search highlight | +| `oo` / `OO` | n | Open blank line below/above without entering insert | +| `p` | x | Paste without clobbering register | +| `` / `` | n/v | Move line/selection down/up | +| `` | i | Arrow keys in insert | +| `` | c | Word/char nav in command line | +| `` | i | Delete previous word | +| `s` / `S` / `r` / `R` | n/x/o | flash.nvim jump / treesitter / remote | + +### Windows, buffers, tasks +| Key | Action | +| :--- | :--- | +| `` | Focus split — falls through to zellij pane | +| ``..`` | Jump to buffer slot 1..9 (`vim.t.bufs[i]`) | +| `x` | Close current buffer | +| `t` / `T` | Floating / horizontal toggleterm | +| `` | Open mapping for toggleterm | +| `gh` | `gh dash` in floating pane | +| `kk` | `k9s` | +| `bb` | bruno tests | +| `uu` / `dd` | `make up` / `make down` in `restopay/` | +| `aa` | Refresh Athenz cert + AWS creds for `external-factory` | + +### Finder (`f…`) +| Key | Action | +| :--- | :--- | +| `ff` | Files | +| `fg` | Live grep | +| `fw` | Grep current word | +| `fd` | Diagnostics | +| `fh` | Help tags | +| `fk` | Keymaps | +| `fs` | Telescope builtins | +| `fr` | Resume last picker | +| `f.` | Recent files | +| `fc` | Commands | +| `fe` | Workspace symbols | +| `` | Buffers | +| `/` | Fuzzy find in current buffer | +| `s/` | Live grep in open buffers | +| `sn` | Find files in nvim config | + +### LSP (set on `LspAttach`, plus zed-parity) +| Key | Action | +| :--- | :--- | +| `gd` / `gr` / `gI` | Definitions / refs / implementations (telescope) | +| `gi` | Implementations (lowercase zed-style) | +| `gD` | Declaration | +| `D` | Type definition | +| `ds` / `ws` | Document / workspace symbols | +| `rn` or `F2` | Rename | +| `ca` or `.` | Code action | +| `th` | Toggle inlay hints (on by default for Go) | +| `q` | Diagnostics → loclist | +| `f` | Format buffer (conform) | + +### Git +| Key | Action | +| :--- | :--- | +| `]c` / `[c` | Next / prev hunk | +| `hs` / `hr` | Stage / reset hunk (works in visual) | +| `hS` / `hR` | Stage / reset buffer | +| `hu` | Undo stage hunk | +| `hp` | Preview hunk | +| `hb` | Blame current line | +| `hd` / `hD` | Diff vs index / last commit | +| `tb` / `tD` | Toggle inline blame / deleted markers | +| `gb` | Full-buffer blame | + +### Harpoon +| Key | Action | +| :--- | :--- | +| `ha` | Add current file | +| `hh` | Toggle harpoon menu | +| `1`..`4` | Jump to slot 1..4 | +| `[h` / `]h` | Prev / next entry | + +### Trouble (`x…`) +| Key | Action | +| :--- | :--- | +| `xx` | Workspace diagnostics | +| `xX` | Buffer diagnostics | +| `xs` | Symbols | +| `xr` | LSP refs/defs (right) | +| `xl` / `xq` | Loclist / quickfix | + +### Neo-tree +| Key | Action | +| :--- | :--- | +| `\` or `e` | Reveal file in tree | +| (inside tree) `h` / `l` / `` | Collapse / expand+open / smart-toggle | +| (inside tree) `T` | Trash file (via `trash` CLI) | + +### Treesitter textobjects +`af`/`if` function, `ac`/`ic` class, `aa`/`ia` parameter, `al`/`il` loop; `]m`/`[m`/`]M`/`[M` move between functions. + +### Copilot / chat +| Key | Action | +| :--- | :--- | +| `` (insert) | Accept Copilot suggestion | +| `cc` / `ce` / `cf` / `cr` / `ct` / `cm` | Chat / explain / fix / review / tests / commit-msg | + +### Sessions (persistence.nvim) +| Key | Action | +| :--- | :--- | +| `qs` | Load session for cwd | +| `ql` | Load last session | +| `qd` | Stop saving current session | + +## LSP & formatting notes + +- `gopls` uses `-tags=integration`, `gofumpt`, `staticcheck`, full inlay hints; `useany`/`unusedparams` on, `shadow` off. +- Go imports run as a `source.organizeImports` code action on `BufWritePre` for `*.go`. +- `pyright` lint is suppressed and its organize-imports disabled; `ruff` handles lint + organize + format. `ruff`'s hover is disabled — `pyright` provides hover. +- `lua_ls`: `callSnippet = 'Replace'`; `lazydev` loads `vim.uv` types. +- Per-ft formatters: `stylua` (lua), `ruff_organize_imports` + `ruff_format` (python), `google-java-format` (java), `terraform_fmt`, `prettier`/`xmlformatter` (xml), `prettierd`/`prettier` (js). Format-on-save off for `c`/`cpp`/`json`/`xml`/`html`. + +## Adding a plugin + +Drop a new file in `lua/custom/plugins/` returning a lazy spec. No central manifest. After edits, run `:Lazy sync` (or restart) and commit `lazy-lock.json` alongside the spec. + +## FAQ + +- **Where do LSP keymaps live?** In the `LspAttach` autocmd in `lsp.lua`. Add new buffer-local LSP bindings there, not globally. +- **Why doesn't `` move splits in some configs?** They're owned by `smart-splits.nvim`; at a split edge they forward to the zellij pane (`multiplexer_integration = 'zellij'`). +- **Uninstall:** see [lazy.nvim uninstall](https://lazy.folke.io/usage#-uninstalling). +- **Run alongside another config:** `NVIM_APPNAME=nvim-other nvim`. diff --git a/init.lua b/init.lua index 4eae8e7d95a..412db1d5e20 100644 --- a/init.lua +++ b/init.lua @@ -1,114 +1,22 @@ ---[[ - -===================================================================== -==================== READ THIS BEFORE CONTINUING ==================== -===================================================================== -======== .-----. ======== -======== .----------------------. | === | ======== -======== |.-""""""""""""""""""-.| |-----| ======== -======== || || | === | ======== -======== || KICKSTART.NVIM || |-----| ======== -======== || || | === | ======== -======== || || |-----| ======== -======== ||:Tutor || |:::::| ======== -======== |'-..................-'| |____o| ======== -======== `"")----------------(""` ___________ ======== -======== /::::::::::| |::::::::::\ \ no mouse \ ======== -======== /:::========| |==hjkl==:::\ \ required \ ======== -======== '""""""""""""' '""""""""""""' '""""""""""' ======== -======== ======== -===================================================================== -===================================================================== - -What is Kickstart? - - Kickstart.nvim is *not* a distribution. - - 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. - - 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! - - 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/ - - 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 - -Kickstart Guide: - - TODO: The very first thing you should do is to run the command `:Tutor` in Neovim. - - If you don't know what this means, type the following: - - - - : - - Tutor - - - - (If you already know the Neovim basics, you can skip this step.) - - Once you've completed that, you can continue working through **AND READING** the rest - of the kickstart init.lua. - - 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. - - 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. - - MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, - which is very useful when you're not exactly sure of what you're looking for. - - 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. - - NOTE: Look for lines like this - - Throughout the file. These are for you, the reader, to help you 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 Neovim config. - -If you experience any errors while trying to install kickstart, run `:checkhealth` for more info. - -I hope you enjoy your Neovim journey, -- TJ - -P.S. You can delete this when you're done too. It's your config now! :) ---]] - --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' +vim.g.have_nerd_font = true --- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false - --- [[ Setting options ]] --- See `:help vim.opt` --- NOTE: You can change these options as you wish! --- For more options, you can see `:help option-list` +-- Skip nvim's OSC 11/DSR terminal probe (zellij sometimes delays the response, +-- producing the "Did not detect DSR response" warning + 100ms slower startup). +-- Setting background explicitly tells defaults.lua to bypass the query. +vim.opt.background = 'dark' --- Make line numbers default -vim.opt.number = true --- You can also add relative line numbers, to help with jumping. --- Experiment for yourself to see if you like it! --- vim.opt.relativenumber = true - --- Enable mouse mode, can be useful for resizing splits for example! +vim.opt.relativenumber = true vim.opt.mouse = 'a' - --- Don't show the mode, since it's already in the status line vim.opt.showmode = false +vim.opt.smartindent = true +vim.opt.spelllang = 'en_us' +vim.o.spell = true +-- colorcolumn set per-filetype (see autocmd below); default off. +vim.o.colorcolumn = '' -- Sync clipboard between OS and Neovim. -- Schedule the setting after `UiEnter` because it can increase startup-time. @@ -154,44 +62,63 @@ vim.opt.inccommand = 'split' vim.opt.cursorline = true -- Minimal number of screen lines to keep above and below the cursor. -vim.opt.scrolloff = 10 - --- [[ Basic Keymaps ]] --- See `:help vim.keymap.set()` +vim.opt.scrolloff = 8 + +vim.keymap.set('n', 'oo', 'o', { noremap = false, silent = true }) +vim.keymap.set('n', 'OO', 'O', { noremap = false, silent = true }) + +-- Don't replace yanked text in register. +vim.keymap.set('x', 'p', [["_dP]]) + +-- map alt-number to buffers +for i = 1, 9, 1 do + vim.keymap.set('n', string.format('', i), function() + vim.api.nvim_set_current_buf(vim.t.bufs[i]) + end) +end + +-- Move with home row in command mode +vim.cmd [[ + cnoremap + cnoremap + cnoremap + cnoremap + cnoremap + cnoremap +]] + +-- Move with home row in insert mode +vim.keymap.set('i', '', '') +vim.keymap.set('i', '', '') +vim.keymap.set('i', '', '') +vim.keymap.set('i', '', '') +vim.keymap.set('i', '', 'b') +vim.keymap.set('i', '', 'db') -- Clear highlights on search when pressing in normal mode -- See `:help hlsearch` +vim.keymap.set('n', ';', ':') vim.keymap.set('n', '', 'nohlsearch') -- Diagnostic keymaps 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' }) +-- Window-nav Ctrl-h/j/k/l owned by smart-splits.nvim (custom/plugins/tmux.lua). +-- Falls through to zellij when at a split edge. -- [[ Basic Autocommands ]] -- See `:help lua-guide-autocommands` +-- Per-filetype colorcolumn (Go allows long lines; markdown shouldn't have a ruler). +vim.api.nvim_create_autocmd('FileType', { + group = vim.api.nvim_create_augroup('per-ft-colorcolumn', { clear = true }), + callback = function(args) + local widths = { python = '80', lua = '100', go = '120', rust = '100', java = '120' } + vim.bo[args.buf].textwidth = 0 + vim.wo.colorcolumn = widths[vim.bo[args.buf].filetype] or '' + end, +}) + -- Highlight when yanking (copying) text -- Try it with `yap` in normal mode -- See `:help vim.highlight.on_yank()` @@ -215,740 +142,9 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then end ---@diagnostic disable-next-line: undefined-field vim.opt.rtp:prepend(lazypath) --- [[ 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. - -- - - -- 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 = '~' }, - }, - }, - }, - - -- 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 `opts` key (recommended), the configuration runs - -- after the plugin has been loaded as `require(MODULE).setup(opts)`. - - { -- Useful plugin to show you pending keybinds. - 'folke/which-key.nvim', - event = 'VimEnter', -- Sets the loading event to 'VimEnter' - opts = { - -- delay between pressing a key and opening which-key (milliseconds) - -- this setting is independent of vim.opt.timeoutlen - delay = 0, - icons = { - -- set icon mappings to true if you have a Nerd Font - mappings = vim.g.have_nerd_font, - -- If you are using a Nerd Font: set icons.keys to an empty table which will use the - -- default which-key.nvim defined Nerd Font icons, otherwise define a string table - keys = vim.g.have_nerd_font and {} or { - Up = ' ', - Down = ' ', - Left = ' ', - Right = ' ', - C = ' ', - M = ' ', - D = ' ', - S = ' ', - CR = ' ', - Esc = ' ', - ScrollWheelDown = ' ', - ScrollWheelUp = ' ', - NL = ' ', - BS = ' ', - Space = ' ', - Tab = ' ', - F1 = '', - F2 = '', - F3 = '', - F4 = '', - F5 = '', - F6 = '', - F7 = '', - F8 = '', - F9 = '', - F10 = '', - F11 = '', - F12 = '', - }, - }, - - -- Document existing key chains - spec = { - { 'c', group = '[C]ode', mode = { 'n', 'x' } }, - { 'd', group = '[D]ocument' }, - { 'r', group = '[R]ename' }, - { 's', group = '[S]earch' }, - { 'w', group = '[W]orkspace' }, - { 't', group = '[T]oggle' }, - { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, - }, - }, - }, - - -- 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 - - { -- Fuzzy Finder (files, lsp, etc) - 'nvim-telescope/telescope.nvim', - event = 'VimEnter', - branch = '0.1.x', - dependencies = { - 'nvim-lua/plenary.nvim', - { -- If encountering errors, see telescope-fzf-native README for installation 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 a Nerd Font. - { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font }, - }, - 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()` - 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 = {} - extensions = { - ['ui-select'] = { - require('telescope.themes').get_dropdown(), - }, - }, - } - - -- 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 the theme, layout, etc. - builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { - winblend = 10, - previewer = false, - }) - end, { desc = '[/] Fuzzily search in current buffer' }) - - -- It's 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' }) - end, - }, - - -- LSP Plugins - { - -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins - -- used for completion, annotations and signatures of Neovim apis - 'folke/lazydev.nvim', - ft = 'lua', - opts = { - library = { - -- Load luvit types when the `vim.uv` word is found - { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, - }, - }, - }, - { - -- Main LSP Configuration - 'neovim/nvim-lspconfig', - dependencies = { - -- Automatically install LSPs and related tools to stdpath for Neovim - -- Mason must be loaded before its dependents so we need to set it up here. - -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` - { 'williamboman/mason.nvim', opts = {} }, - 'williamboman/mason-lspconfig.nvim', - 'WhoIsSethDaniel/mason-tool-installer.nvim', +require('custom.zed-keymaps') - -- Useful status updates for LSP. - { 'j-hui/fidget.nvim', opts = {} }, - - -- Allows extra capabilities provided by nvim-cmp - 'hrsh7th/cmp-nvim-lsp', - }, - config = function() - -- Brief aside: **What is LSP?** - -- - -- LSP is an initialism you've probably heard, but might not understand what it is. - -- - -- LSP stands for Language Server Protocol. It's a protocol that helps editors - -- and language tooling communicate in a standardized fashion. - -- - -- In general, you have a "server" which is some tool built to understand a particular - -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers - -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone - -- processes that communicate with some "client" - in this case, Neovim! - -- - -- LSP provides Neovim with features like: - -- - Go to definition - -- - Find references - -- - Autocompletion - -- - Symbol Search - -- - and more! - -- - -- Thus, Language Servers are external tools that must be installed separately from - -- Neovim. This is where `mason` and related plugins come into play. - -- - -- If you're wondering about lsp vs treesitter, you can check out the wonderfully - -- and elegantly composed help section, `:help lsp-vs-treesitter` - - -- This function gets run when an LSP attaches to a particular buffer. - -- That is to say, every time a new file is opened that is associated with - -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this - -- function will be executed to configure the current buffer - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), - callback = function(event) - -- NOTE: Remember that Lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local map = function(keys, func, desc, mode) - mode = mode or 'n' - vim.keymap.set(mode, 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 entire 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', { 'n', 'x' }) - - -- 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.supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight) then - local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) - vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { - buffer = event.buf, - group = highlight_augroup, - callback = vim.lsp.buf.document_highlight, - }) - - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - buffer = event.buf, - group = highlight_augroup, - callback = vim.lsp.buf.clear_references, - }) - - vim.api.nvim_create_autocmd('LspDetach', { - group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), - callback = function(event2) - vim.lsp.buf.clear_references() - vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } - end, - }) - end - - -- The following code creates a keymap to toggle inlay hints in your - -- code, if the language server you are using supports them - -- - -- This may be unwanted, since they displace some of your code - if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then - map('th', function() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) - end, '[T]oggle Inlay [H]ints') - end - end, - }) - - -- Change diagnostic symbols in the sign column (gutter) - -- if vim.g.have_nerd_font then - -- local signs = { ERROR = '', WARN = '', INFO = '', HINT = '' } - -- local diagnostic_signs = {} - -- for type, icon in pairs(signs) do - -- diagnostic_signs[vim.diagnostic.severity[type]] = icon - -- end - -- vim.diagnostic.config { signs = { text = diagnostic_signs } } - -- 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 (`ts_ls`) will work just fine - -- ts_ls = {}, - -- - - lua_ls = { - -- cmd = { ... }, - -- filetypes = { ... }, - -- capabilities = {}, - settings = { - Lua = { - completion = { - callSnippet = 'Replace', - }, - -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings - -- diagnostics = { disable = { 'missing-fields' } }, - }, - }, - }, - } - - -- Ensure the servers and tools above are installed - -- - -- To check the current status of installed tools and/or manually install - -- other tools, you can run - -- :Mason - -- - -- You can press `g?` for help in this menu. - -- - -- `mason` had to be setup earlier: to configure its options see the - -- `dependencies` table for `nvim-lspconfig` above. - -- - -- 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 } - - 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 ts_ls) - server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - require('lspconfig')[server_name].setup(server) - end, - }, - } - end, - }, - - { -- Autoformat - 'stevearc/conform.nvim', - event = { 'BufWritePre' }, - cmd = { 'ConformInfo' }, - keys = { - { - 'f', - function() - require('conform').format { async = true, lsp_format = 'fallback' } - end, - mode = '', - desc = '[F]ormat buffer', - }, - }, - opts = { - notify_on_error = false, - format_on_save = function(bufnr) - -- Disable "format_on_save lsp_fallback" for languages that don't - -- have a well standardized coding style. You can add additional - -- languages here or re-enable it for the disabled ones. - local disable_filetypes = { c = true, cpp = true } - local lsp_format_opt - if disable_filetypes[vim.bo[bufnr].filetype] then - lsp_format_opt = 'never' - else - lsp_format_opt = 'fallback' - end - return { - timeout_ms = 500, - lsp_format = lsp_format_opt, - } - end, - formatters_by_ft = { - lua = { 'stylua' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use 'stop_after_first' to run the first available formatter from the list - -- javascript = { "prettierd", "prettier", stop_after_first = true }, - }, - }, - }, - - { -- 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)(), - dependencies = { - -- `friendly-snippets` contains a variety of premade snippets. - -- See the README about individual language/framework/plugin snippets: - -- https://github.com/rafamadriz/friendly-snippets - -- { - -- 'rafamadriz/friendly-snippets', - -- config = function() - -- require('luasnip.loaders.from_vscode').lazy_load() - -- 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', - }, - config = function() - -- See `:help cmp` - local cmp = require 'cmp' - local luasnip = require 'luasnip' - luasnip.config.setup {} - - cmp.setup { - snippet = { - expand = function(args) - 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(), - - -- Scroll the documentation window [b]ack / [f]orward - [''] = cmp.mapping.scroll_docs(-4), - [''] = cmp.mapping.scroll_docs(4), - - -- 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 }, - - -- If you prefer more traditional completion keymaps, - -- you can uncomment the following lines - --[''] = cmp.mapping.confirm { select = true }, - --[''] = cmp.mapping.select_next_item(), - --[''] = cmp.mapping.select_prev_item(), - - -- 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 - luasnip.expand_or_jump() - end - end, { 'i', 's' }), - [''] = cmp.mapping(function() - if luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - end - end, { 'i', 's' }), - - -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: - -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps - }, - sources = { - { - name = 'lazydev', - -- set group index to 0 to skip loading LuaLS completions as lazydev recommends it - group_index = 0, - }, - { name = 'nvim_lsp' }, - { name = 'luasnip' }, - { name = 'path' }, - }, - } - 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', - priority = 1000, -- Make sure to load this before all the other start plugins. - init = function() - -- Load the colorscheme here. - -- Like many other themes, this one has different styles, and you could load - -- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'. - vim.cmd.colorscheme 'tokyonight-night' - - -- You can configure highlights by doing something like: - vim.cmd.hi 'Comment gui=none' - end, - }, - - -- Highlight todo, notes, etc in comments - { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, - - { -- Collection of various small independent plugins/modules - 'echasnovski/mini.nvim', - config = function() - -- Better Around/Inside textobjects - -- - -- Examples: - -- - va) - [V]isually select [A]round [)]paren - -- - yinq - [Y]ank [I]nside [N]ext [Q]uote - -- - 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' - -- set use_icons to true if you have a Nerd Font - statusline.setup { use_icons = vim.g.have_nerd_font } - - -- You can configure sections in the statusline by overriding their - -- default behavior. For example, here we set the section for - -- cursor location to LINE:COLUMN - ---@diagnostic disable-next-line: duplicate-set-field - statusline.section_location = function() - return '%2l:%-2v' - end - - -- ... and there is more! - -- Check out: https://github.com/echasnovski/mini.nvim - end, - }, - { -- Highlight, edit, and navigate code - 'nvim-treesitter/nvim-treesitter', - build = ':TSUpdate', - main = 'nvim-treesitter.configs', -- Sets main module to use for opts - -- [[ Configure Treesitter ]] See `:help nvim-treesitter` - opts = { - ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }, - -- Autoinstall languages that are not installed - auto_install = true, - highlight = { - enable = true, - -- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. - -- If you are experiencing weird indenting issues, add the language to - -- the list of additional_vim_regex_highlighting and disabled languages for indent. - additional_vim_regex_highlighting = { 'ruby' }, - }, - indent = { enable = true, disable = { 'ruby' } }, - }, - -- 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 - }, - - -- The following 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 - -- place them in the correct locations. - - -- 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', - -- require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', - -- require 'kickstart.plugins.neo-tree', - -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommend keymaps - - -- 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. - -- { import = 'custom.plugins' }, - -- - -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` - -- Or use telescope! - -- In normal mode type `sh` then write `lazy.nvim-plugin` - -- you can continue same window with `sr` which resumes last telescope search -}, { +require('lazy').setup({ { import = 'custom.plugins' } }, { ui = { -- If you are using a Nerd Font: set icons to an empty table which will use the -- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table @@ -969,6 +165,3 @@ require('lazy').setup({ }, }, }) - --- The line beneath this is called `modeline`. See `:help modeline` --- vim: ts=2 sts=2 sw=2 et diff --git a/lua/kickstart/health.lua b/lua/custom/health.lua similarity index 100% rename from lua/kickstart/health.lua rename to lua/custom/health.lua diff --git a/lua/kickstart/plugins/autopairs.lua b/lua/custom/plugins/autopairs.lua similarity index 88% rename from lua/kickstart/plugins/autopairs.lua rename to lua/custom/plugins/autopairs.lua index 87a7e5ffa2e..3807819d893 100644 --- a/lua/kickstart/plugins/autopairs.lua +++ b/lua/custom/plugins/autopairs.lua @@ -1,6 +1,3 @@ --- autopairs --- https://github.com/windwp/nvim-autopairs - return { 'windwp/nvim-autopairs', event = 'InsertEnter', diff --git a/lua/custom/plugins/cmp.lua b/lua/custom/plugins/cmp.lua new file mode 100644 index 00000000000..0a1937ebec8 --- /dev/null +++ b/lua/custom/plugins/cmp.lua @@ -0,0 +1,39 @@ +-- blink.cmp: faster Rust-based completion (replaces nvim-cmp). +-- Provides LSP, path, snippet, and lazydev sources via single plugin. +return { + 'saghen/blink.cmp', + version = '*', + event = { 'InsertEnter', 'CmdlineEnter' }, + dependencies = { + 'rafamadriz/friendly-snippets', + }, + opts = { + -- Use the 'enter' preset: confirms, / cycle items. + keymap = { + preset = 'enter', + [''] = { 'select_next', 'snippet_forward', 'fallback' }, + [''] = { 'select_prev', 'snippet_backward', 'fallback' }, + [''] = { 'show', 'show_documentation', 'hide_documentation' }, + }, + appearance = { + use_nvim_cmp_as_default = true, + nerd_font_variant = 'mono', + }, + completion = { + accept = { auto_brackets = { enabled = true } }, + documentation = { auto_show = true, auto_show_delay_ms = 200 }, + menu = { border = 'rounded' }, + }, + signature = { enabled = true, window = { border = 'rounded' } }, + sources = { + default = { 'lsp', 'path', 'snippets', 'buffer', 'lazydev' }, + providers = { + lazydev = { + name = 'LazyDev', + module = 'lazydev.integrations.blink', + score_offset = 100, + }, + }, + }, + }, +} diff --git a/lua/custom/plugins/conform.lua b/lua/custom/plugins/conform.lua new file mode 100644 index 00000000000..886a835c9d2 --- /dev/null +++ b/lua/custom/plugins/conform.lua @@ -0,0 +1,42 @@ +return { -- Autoformat + 'stevearc/conform.nvim', + event = { 'BufWritePre' }, + cmd = { 'ConformInfo' }, + keys = { + { + 'f', + function() + require('conform').format { async = true, lsp_format = 'fallback' } + end, + mode = '', + desc = '[F]ormat buffer', + }, + }, + opts = { + notify_on_error = false, + format_on_save = function(bufnr) + -- Disable "format_on_save lsp_fallback" for languages that don't + -- have a well standardized coding style. You can add additional + -- languages here or re-enable it for the disabled ones. + local disable_filetypes = { c = true, cpp = true, json = true, xml = true, html = true } + local lsp_format_opt + if disable_filetypes[vim.bo[bufnr].filetype] then + lsp_format_opt = 'never' + else + lsp_format_opt = 'fallback' + end + return { + timeout_ms = 500, + lsp_format = lsp_format_opt, + } + end, + formatters_by_ft = { + java = { 'google-java-format' }, + terraform = { 'terraform_fmt' }, + xml = { 'xmlformatter', 'prettier' }, + lua = { 'stylua' }, + python = { 'ruff_organize_imports', 'ruff_format' }, + javascript = { 'prettierd', 'prettier', stop_after_first = true }, + }, + }, +} diff --git a/lua/custom/plugins/copilot-chat.lua b/lua/custom/plugins/copilot-chat.lua new file mode 100644 index 00000000000..1de49d58501 --- /dev/null +++ b/lua/custom/plugins/copilot-chat.lua @@ -0,0 +1,29 @@ +-- CopilotChat: in-nvim chat using your existing GitHub Copilot auth. +return { + 'CopilotC-Nvim/CopilotChat.nvim', + dependencies = { + 'github/copilot.vim', + 'nvim-lua/plenary.nvim', + }, + build = 'make tiktoken', + cmd = { 'CopilotChat', 'CopilotChatOpen', 'CopilotChatToggle', 'CopilotChatExplain', 'CopilotChatReview', 'CopilotChatFix', 'CopilotChatTests', 'CopilotChatCommit' }, + opts = { + model = 'gpt-4o', + window = { + layout = 'float', + width = 0.8, + height = 0.8, + border = 'rounded', + }, + show_help = true, + auto_follow_cursor = false, + }, + keys = { + { 'cc', 'CopilotChatToggle', mode = { 'n', 'x' }, desc = '[C]opilot [C]hat' }, + { 'ce', 'CopilotChatExplain', mode = { 'n', 'x' }, desc = '[C]opilot [E]xplain' }, + { 'cf', 'CopilotChatFix', mode = { 'n', 'x' }, desc = '[C]opilot [F]ix' }, + { 'cr', 'CopilotChatReview', mode = { 'n', 'x' }, desc = '[C]opilot [R]eview' }, + { 'ct', 'CopilotChatTests', mode = { 'n', 'x' }, desc = '[C]opilot [T]ests' }, + { 'cm', 'CopilotChatCommit', desc = '[C]opilot co[M]mit msg' }, + }, +} diff --git a/lua/custom/plugins/copilot.lua b/lua/custom/plugins/copilot.lua new file mode 100644 index 00000000000..36857ada849 --- /dev/null +++ b/lua/custom/plugins/copilot.lua @@ -0,0 +1,7 @@ +return { + 'github/copilot.vim', + config = function() + vim.keymap.set('i', '', 'copilot#Accept("\\")', { expr = true, replace_keycodes = false }) + vim.g.copilot_no_tab_map = true + end, +} diff --git a/lua/kickstart/plugins/debug.lua b/lua/custom/plugins/debug.lua similarity index 94% rename from lua/kickstart/plugins/debug.lua rename to lua/custom/plugins/debug.lua index 753cb0cedd3..03dccd53efe 100644 --- a/lua/kickstart/plugins/debug.lua +++ b/lua/custom/plugins/debug.lua @@ -1,11 +1,3 @@ --- debug.lua --- --- Shows how to use the DAP plugin to debug your code. --- --- Primarily focused on configuring the debugger for Go, but can --- be extended to other languages as well. That's why it's called --- kickstart.nvim and not kitchen-sink.nvim ;) - return { -- NOTE: Yes, you can install new plugins here! 'mfussenegger/nvim-dap', diff --git a/lua/custom/plugins/dressing.lua b/lua/custom/plugins/dressing.lua new file mode 100644 index 00000000000..7f4147becce --- /dev/null +++ b/lua/custom/plugins/dressing.lua @@ -0,0 +1,6 @@ +-- Replace the ugly default vim.ui.input/select with a floating UI. +return { + 'stevearc/dressing.nvim', + event = 'VeryLazy', + opts = {}, +} diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/custom/plugins/gitsigns.lua similarity index 91% rename from lua/kickstart/plugins/gitsigns.lua rename to lua/custom/plugins/gitsigns.lua index c269bc06e15..826619c238f 100644 --- a/lua/kickstart/plugins/gitsigns.lua +++ b/lua/custom/plugins/gitsigns.lua @@ -1,11 +1,9 @@ --- Adds git related signs to the gutter, as well as utilities for managing changes --- NOTE: gitsigns is already included in init.lua but contains only the base --- config. This will add also the recommended keymaps. - return { { 'lewis6991/gitsigns.nvim', opts = { + current_line_blame = true, + current_line_blame_opts = { delay = 300, virt_text_pos = 'eol' }, on_attach = function(bufnr) local gitsigns = require 'gitsigns' diff --git a/lua/custom/plugins/gruvbox.lua b/lua/custom/plugins/gruvbox.lua new file mode 100644 index 00000000000..4f943b3a098 --- /dev/null +++ b/lua/custom/plugins/gruvbox.lua @@ -0,0 +1,15 @@ +return { -- 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`. + 'ellisonleao/gruvbox.nvim', + priority = 1000, -- Make sure to load this before all the other start plugins. + opts = { + transparent_mode = true, + }, + config = function() + vim.o.background = 'dark' -- or "light" for light mode + vim.cmd [[colorscheme gruvbox]] + end, +} diff --git a/lua/custom/plugins/harpoon.lua b/lua/custom/plugins/harpoon.lua new file mode 100644 index 00000000000..0c81784c9ed --- /dev/null +++ b/lua/custom/plugins/harpoon.lua @@ -0,0 +1,21 @@ +return { + 'ThePrimeagen/harpoon', + branch = 'harpoon2', + dependencies = { 'nvim-lua/plenary.nvim' }, + config = function() + local harpoon = require 'harpoon' + harpoon:setup() + + vim.keymap.set('n', 'ha', function() harpoon:list():add() end, { desc = '[H]arpoon [A]dd file' }) + vim.keymap.set('n', 'hh', function() harpoon.ui:toggle_quick_menu(harpoon:list()) end, { desc = '[H]arpoon toggle list' }) + + -- Jump to harpoon slots 1..4. ( reserved for smart-splits pane nav.) + for i = 1, 4 do + vim.keymap.set('n', '' .. i, function() harpoon:list():select(i) end, { desc = 'Harpoon slot ' .. i }) + end + + -- Prev/next harpoon entries. + vim.keymap.set('n', '[h', function() harpoon:list():prev() end, { desc = 'Harpoon prev' }) + vim.keymap.set('n', ']h', function() harpoon:list():next() end, { desc = 'Harpoon next' }) + end, +} diff --git a/lua/custom/plugins/illuminate.lua b/lua/custom/plugins/illuminate.lua new file mode 100644 index 00000000000..1dd406d56a7 --- /dev/null +++ b/lua/custom/plugins/illuminate.lua @@ -0,0 +1,33 @@ +return { + -- 'RRethy/vim-illuminate', + -- event = 'VeryLazy', + -- config = function() + -- require('illuminate').configure { + -- providers = { + -- 'lsp', + -- 'treesitter', + -- 'regex', + -- }, + -- delay = 100, + -- filetype_overrides = {}, + -- filetypes_denylist = { + -- 'dirbuf', + -- 'dirvish', + -- 'fugitive', + -- }, + -- filetypes_allowlist = {}, + -- modes_denylist = {}, + -- modes_allowlist = {}, + -- providers_regex_syntax_denylist = {}, + -- providers_regex_syntax_allowlist = {}, + -- under_cursor = true, + -- large_file_cutoff = nil, + -- large_file_overrides = nil, + -- min_count_to_highlight = 1, + -- should_enable = function(_) + -- return true + -- end, + -- case_insensitive_regex = false, + -- } + -- end, +} diff --git a/lua/custom/plugins/indent_line.lua b/lua/custom/plugins/indent_line.lua new file mode 100644 index 00000000000..8963287f426 --- /dev/null +++ b/lua/custom/plugins/indent_line.lua @@ -0,0 +1,7 @@ +return { + 'lukas-reineke/indent-blankline.nvim', + -- Enable `lukas-reineke/indent-blankline.nvim` + -- See `:help ibl` + main = 'ibl', + opts = {}, +} diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua deleted file mode 100644 index be0eb9d8d7a..00000000000 --- a/lua/custom/plugins/init.lua +++ /dev/null @@ -1,5 +0,0 @@ --- You can add your own plugins here or in other files in this directory! --- I promise not to create any merge conflicts in this directory :) --- --- See the kickstart.nvim README for more information -return {} diff --git a/lua/custom/plugins/java.lua b/lua/custom/plugins/java.lua new file mode 100644 index 00000000000..1593a3de8f2 --- /dev/null +++ b/lua/custom/plugins/java.lua @@ -0,0 +1,23 @@ +return { + -- 'mfussenegger/nvim-jdtls', + -- ft = { 'java' }, + -- config = function() + -- local jdtls = require 'jdtls' + -- local home = os.getenv 'HOME' + -- local workspace_dir = home .. '~/.cache/jdtls/workspace/' .. vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t') + -- + -- require('jdtls').start_or_attach { + -- cmd = { 'jdtls' }, + -- root_dir = require('jdtls.setup').find_root { '.git', 'mvnw', 'gradlew' }, + -- settings = { + -- java = { + -- format = { + -- enabled = true, + -- settings = home .. '/.config/nvim/eclipse-java-style.xml', -- Use your exported formatter + -- }, + -- }, + -- }, + -- workspace_dir = workspace_dir, + -- } + -- end, +} diff --git a/lua/custom/plugins/lazygit.lua b/lua/custom/plugins/lazygit.lua new file mode 100644 index 00000000000..dc1a44a29f1 --- /dev/null +++ b/lua/custom/plugins/lazygit.lua @@ -0,0 +1,20 @@ +return { + 'kdheepak/lazygit.nvim', + lazy = true, + cmd = { + 'LazyGit', + 'LazyGitConfig', + 'LazyGitCurrentFile', + 'LazyGitFilter', + 'LazyGitFilterCurrentFile', + }, + -- optional for floating window border decoration + dependencies = { + 'nvim-lua/plenary.nvim', + }, + -- setting the keybinding for LazyGit with 'keys' is recommended in + -- order to load the plugin when the command is run for the first time + keys = { + { 'gg', 'LazyGit', desc = 'LazyGit' }, + }, +} diff --git a/lua/custom/plugins/leap.lua b/lua/custom/plugins/leap.lua new file mode 100644 index 00000000000..030515470ed --- /dev/null +++ b/lua/custom/plugins/leap.lua @@ -0,0 +1,13 @@ +-- flash.nvim: smarter `s`/`S` jump with treesitter-aware selection and +-- remote operations (e.g. `yr` to yank a remote region). +return { + 'folke/flash.nvim', + event = 'VeryLazy', + opts = {}, + keys = { + { 's', mode = { 'n', 'x', 'o' }, function() require('flash').jump() end, desc = 'Flash' }, + { 'S', mode = { 'n', 'x', 'o' }, function() require('flash').treesitter() end, desc = 'Flash Treesitter' }, + { 'r', mode = 'o', function() require('flash').remote() end, desc = 'Remote Flash' }, + { 'R', mode = { 'o', 'x' }, function() require('flash').treesitter_search() end, desc = 'Treesitter Search' }, + }, +} diff --git a/lua/custom/plugins/lint.lua b/lua/custom/plugins/lint.lua new file mode 100644 index 00000000000..e057edaeeac --- /dev/null +++ b/lua/custom/plugins/lint.lua @@ -0,0 +1,57 @@ +return { + 'mfussenegger/nvim-lint', + event = { 'BufReadPre', 'BufNewFile' }, + config = function() + local lint = require 'lint' + lint.linters_by_ft = { + markdown = { 'vale' }, + } + + -- To allow other plugins to add linters to require('lint').linters_by_ft, + -- instead set linters_by_ft like this: + -- lint.linters_by_ft = lint.linters_by_ft or {} + -- lint.linters_by_ft['markdown'] = { 'markdownlint' } + -- + -- However, note that this will enable a set of default linters, + -- which will cause errors unless these tools are available: + -- { + -- clojure = { "clj-kondo" }, + -- dockerfile = { "hadolint" }, + -- inko = { "inko" }, + -- janet = { "janet" }, + -- json = { "jsonlint" }, + -- markdown = { "vale" }, + -- rst = { "vale" }, + -- ruby = { "ruby" }, + -- terraform = { "tflint" }, + -- text = { "vale" } + -- } + -- + -- You can disable the default linters by setting their filetypes to nil: + -- lint.linters_by_ft['clojure'] = nil + -- lint.linters_by_ft['dockerfile'] = nil + -- lint.linters_by_ft['inko'] = nil + -- lint.linters_by_ft['janet'] = nil + -- lint.linters_by_ft['json'] = nil + -- lint.linters_by_ft['markdown'] = nil + -- lint.linters_by_ft['rst'] = nil + -- lint.linters_by_ft['ruby'] = nil + -- lint.linters_by_ft['terraform'] = nil + -- lint.linters_by_ft['text'] = nil + + -- Create autocommand which carries out the actual linting + -- on the specified events. + local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true }) + vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, { + group = lint_augroup, + callback = function() + -- Only run the linter in buffers that you can modify in order to + -- avoid superfluous noise, notably within the handy LSP pop-ups that + -- describe the hovered symbol using Markdown. + if vim.opt_local.modifiable:get() then + lint.try_lint() + end + end, + }) + end, +} diff --git a/lua/custom/plugins/lsp.lua b/lua/custom/plugins/lsp.lua new file mode 100644 index 00000000000..c9caca58191 --- /dev/null +++ b/lua/custom/plugins/lsp.lua @@ -0,0 +1,311 @@ +return { + { + -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins + -- used for completion, annotations and signatures of Neovim apis + 'folke/lazydev.nvim', + ft = 'lua', + opts = { + library = { + -- Load luvit types when the `vim.uv` word is found + { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, + }, + }, + }, + { + -- Main LSP Configuration + 'neovim/nvim-lspconfig', + dependencies = { + -- Automatically install LSPs and related tools to stdpath for Neovim + -- Mason must be loaded before its dependents so we need to set it up here. + -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` + { 'williamboman/mason.nvim', opts = {} }, + 'williamboman/mason-lspconfig.nvim', + 'WhoIsSethDaniel/mason-tool-installer.nvim', + + -- Useful status updates for LSP. + { 'j-hui/fidget.nvim', opts = {} }, + + -- Completion capabilities from blink.cmp. + 'saghen/blink.cmp', + }, + config = function() + -- Brief aside: **What is LSP?** + -- + -- LSP is an initialism you've probably heard, but might not understand what it is. + -- + -- LSP stands for Language Server Protocol. It's a protocol that helps editors + -- and language tooling communicate in a standardized fashion. + -- + -- In general, you have a "server" which is some tool built to understand a particular + -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers + -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone + -- processes that communicate with some "client" - in this case, Neovim! + -- + -- LSP provides Neovim with features like: + -- - Go to definition + -- - Find references + -- - Autocompletion + -- - Symbol Search + -- - and more! + -- + -- Thus, Language Servers are external tools that must be installed separately from + -- Neovim. This is where `mason` and related plugins come into play. + -- + -- If you're wondering about lsp vs treesitter, you can check out the wonderfully + -- and elegantly composed help section, `:help lsp-vs-treesitter` + + -- This function gets run when an LSP attaches to a particular buffer. + -- That is to say, every time a new file is opened that is associated with + -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this + -- function will be executed to configure the current buffer + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), + callback = function(event) + -- NOTE: Remember that Lua is a real programming language, and as such it is possible + -- to define small helper and utility functions so you don't have to repeat yourself. + -- + -- In this case, we create a function that lets us more easily define mappings specific + -- for LSP related items. It sets the mode, buffer and description for us each time. + local map = function(keys, func, desc, mode) + mode = mode or 'n' + vim.keymap.set(mode, 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 entire 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', { 'n', 'x' }) + + -- 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:supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight) then + local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) + vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.document_highlight, + }) + + vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.clear_references, + }) + + vim.api.nvim_create_autocmd('LspDetach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), + callback = function(event2) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } + end, + }) + end + + -- The following code creates a keymap to toggle inlay hints in your + -- code, if the language server you are using supports them + -- + -- This may be unwanted, since they displace some of your code + if client and client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then + map('th', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) + end, '[T]oggle Inlay [H]ints') + -- Inlay hints on by default for Go. + if vim.bo[event.buf].filetype == 'go' then + vim.lsp.inlay_hint.enable(true, { bufnr = event.buf }) + end + end + end, + }) + + -- Go: organize imports on save via gopls code action. + vim.api.nvim_create_autocmd('BufWritePre', { + group = vim.api.nvim_create_augroup('go-organize-imports', { clear = true }), + pattern = '*.go', + callback = function() + local params = vim.lsp.util.make_range_params(0, 'utf-8') + params.context = { only = { 'source.organizeImports' } } + local result = vim.lsp.buf_request_sync(0, 'textDocument/codeAction', params, 1000) + for _, res in pairs(result or {}) do + for _, action in pairs(res.result or {}) do + if action.edit then + vim.lsp.util.apply_workspace_edit(action.edit, 'utf-8') + end + end + end + end, + }) + + -- Change diagnostic symbols in the sign column (gutter) + -- if vim.g.have_nerd_font then + -- local signs = { ERROR = '', WARN = '', INFO = '', HINT = '' } + -- local diagnostic_signs = {} + -- for type, icon in pairs(signs) do + -- diagnostic_signs[vim.diagnostic.severity[type]] = icon + -- end + -- vim.diagnostic.config { signs = { text = diagnostic_signs } } + -- 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 = require('blink.cmp').get_lsp_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 = { + filetypes = { 'go', 'go.mod', 'go.work' }, + settings = { + gopls = { + -- Resolve files behind `//go:build integration`. Matches Zed's gopls config. + buildFlags = { '-tags=integration' }, + completeUnimported = true, + usePlaceholders = true, + analyses = { + shadow = false, + useany = true, + unusedparams = true, + }, + gofumpt = true, + staticcheck = true, + hints = { + assignVariableTypes = true, + compositeLiteralFields = true, + compositeLiteralTypes = true, + constantValues = true, + functionTypeParameters = true, + parameterNames = true, + rangeVariableTypes = true, + }, + }, + }, + }, + pyright = { + settings = { + pyright = { + -- Disable pyright's import organizer; let ruff handle it. + disableOrganizeImports = true, + }, + python = { + analysis = { + -- ignore lint errors; ruff handles linting. + ignore = { '*' }, + }, + }, + }, + }, + ruff = { + -- Disable ruff's hover; pyright provides better hover. + on_attach = function(client, _) + client.server_capabilities.hoverProvider = false + end, + }, + -- 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 (`ts_ls`) will work just fine + -- ts_ls = {}, + -- + + lua_ls = { + -- cmd = { ... }, + -- filetypes = { ... }, + -- capabilities = {}, + settings = { + Lua = { + completion = { + callSnippet = 'Replace', + }, + -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings + -- diagnostics = { disable = { 'missing-fields' } }, + }, + }, + }, + } + + -- Ensure the servers and tools above are installed + -- + -- To check the current status of installed tools and/or manually install + -- other tools, you can run + -- :Mason + -- + -- You can press `g?` for help in this menu. + -- + -- `mason` had to be setup earlier: to configure its options see the + -- `dependencies` table for `nvim-lspconfig` above. + -- + -- 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 + 'jdtls', -- Java LSP + 'gopls', + 'pyright', + 'ruff', -- Python linter/formatter LSP. + }) + require('mason-tool-installer').setup { ensure_installed = ensure_installed } + + require('mason-lspconfig').setup { + handlers = { + function(server_name) + local server = servers[server_name] or {} + -- This handles overriding only values explicitly passed + -- by the server configuration above. Useful when disabling + -- certain features of an LSP (for example, turning off formatting for ts_ls) + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + require('lspconfig')[server_name].setup(server) + end, + }, + } + end, + }, +} diff --git a/lua/custom/plugins/markdown-preview.lua b/lua/custom/plugins/markdown-preview.lua new file mode 100644 index 00000000000..7baf82f6f7d --- /dev/null +++ b/lua/custom/plugins/markdown-preview.lua @@ -0,0 +1,17 @@ +-- Live browser preview on `:MarkdownPreview`. +-- Build via the plugin's helper so it doesn't dirty yarn.lock and break Lazy updates. +return { + 'iamcco/markdown-preview.nvim', + ft = { 'markdown' }, + build = function() + vim.fn['mkdp#util#install']() + end, + cmd = { 'MarkdownPreview', 'MarkdownPreviewStop', 'MarkdownPreviewToggle' }, + init = function() + vim.g.mkdp_auto_start = 0 + vim.g.mkdp_filetypes = { 'markdown' } + end, + keys = { + { 'mp', 'MarkdownPreviewToggle', desc = '[M]arkdown [P]review' }, + }, +} diff --git a/lua/custom/plugins/mini.lua b/lua/custom/plugins/mini.lua new file mode 100644 index 00000000000..b5ac322fc55 --- /dev/null +++ b/lua/custom/plugins/mini.lua @@ -0,0 +1,12 @@ +return { -- Collection of various small independent plugins/modules + 'echasnovski/mini.nvim', + config = function() + require('mini.ai').setup { n_lines = 500 } + require('mini.move').setup() + require('mini.notify').setup() + require('mini.starter').setup() + require('mini.statusline').setup { + use_icons = vim.g.have_nerd_font, + } + end, +} diff --git a/lua/custom/plugins/neo-tree.lua b/lua/custom/plugins/neo-tree.lua new file mode 100644 index 00000000000..d72d64122d9 --- /dev/null +++ b/lua/custom/plugins/neo-tree.lua @@ -0,0 +1,145 @@ +return { + 'nvim-neo-tree/neo-tree.nvim', + version = '*', + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-tree/nvim-web-devicons', + 'MunifTanjim/nui.nvim', + 'saifulapm/neotree-file-nesting-config', + }, + cmd = 'Neotree', + -- Auto-open on startup when nvim is launched without a file or on a directory. + init = function() + vim.api.nvim_create_autocmd('VimEnter', { + group = vim.api.nvim_create_augroup('neo-tree-auto-open', { clear = true }), + callback = function() + local argc = vim.fn.argc() + local arg = argc > 0 and vim.fn.argv(0) or '' + if argc == 0 or vim.fn.isdirectory(arg) == 1 then + vim.schedule(function() + -- `reveal_force_cwd` roots at cwd and avoids the + -- expand_to_node recursion that `show` can hit. + vim.cmd('Neotree reveal_force_cwd') + end) + end + end, + }) + end, + keys = { + { '\\', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, + { 'e', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, + }, + config = function() + local inputs = require 'neo-tree.ui.inputs' + + local function trash(state) + local node = state.tree:get_node() + if node.type == 'message' then + return + end + local _, name = require('neo-tree.utils').split_path(node.path) + local msg = string.format("Are you sure you want to trash '%s'?", name) + inputs.confirm(msg, function(confirmed) + if not confirmed then + return + end + vim.api.nvim_command('silent !trash -F ' .. node.path) + require('neo-tree.sources.manager').refresh(state) + end) + end + + local function trash_visual(state, selected_nodes) + local paths_to_trash = {} + for _, node in ipairs(selected_nodes) do + if node.type ~= 'message' then + table.insert(paths_to_trash, node.path) + end + end + local msg = 'Are you sure you want to trash ' .. #paths_to_trash .. ' items?' + inputs.confirm(msg, function(confirmed) + if not confirmed then + return + end + for _, path in ipairs(paths_to_trash) do + vim.api.nvim_command('silent !trash -F ' .. path) + end + require('neo-tree.sources.manager').refresh(state) + end) + end + + require('neo-tree').setup { + -- hide_root_node + follow_current_file used to cause an infinite + -- expand_to_node/restore recursion at startup; both disabled here. + nesting_rules = require('neotree-file-nesting-config').nesting_rules, + filesystem = { + filtered_items = { + show_hidden_count = false, + never_show = { '.DS_Store' }, + }, + follow_current_file = { + enabled = false, + }, + }, + default_component_configs = { + indent = { + with_expanders = true, + expander_collapsed = '', + expander_expanded = '', + }, + }, + event_handlers = { + { + event = 'neo_tree_buffer_enter', + handler = function() + vim.cmd 'highlight! Cursor blend=100' + end, + }, + { + event = 'neo_tree_buffer_leave', + handler = function() + vim.cmd 'highlight! Cursor guibg=#5f87af blend=0' + end, + }, + }, + window = { + mappings = { + ['T'] = 'trash', + ['h'] = function(state) + local node = state.tree:get_node() + if node.type == 'directory' and node:is_expanded() then + require('neo-tree.sources.filesystem').toggle_directory(state, node) + else + require('neo-tree.ui.renderer').focus_node(state, node:get_parent_id()) + end + end, + ['l'] = function(state) + local node = state.tree:get_node() + if node.type == 'directory' then + if not node:is_expanded() then + require('neo-tree.sources.filesystem').toggle_directory(state, node) + elseif node:has_children() then + require('neo-tree.ui.renderer').focus_node(state, node:get_child_ids()[1]) + end + else + state.commands['open'](state) + vim.cmd 'Neotree reveal' + end + end, + [''] = function(state) + local node = state.tree:get_node() + if require('neo-tree.utils').is_expandable(node) then + state.commands['toggle_node'](state) + else + state.commands['open'](state) + vim.cmd 'Neotree reveal' + end + end, + }, + }, + commands = { + trash = trash, + trash_visual = trash_visual, + }, + } + end, +} diff --git a/lua/custom/plugins/neoscroll.lua b/lua/custom/plugins/neoscroll.lua new file mode 100644 index 00000000000..9ad1d29d6e6 --- /dev/null +++ b/lua/custom/plugins/neoscroll.lua @@ -0,0 +1,31 @@ +return { + 'karb94/neoscroll.nvim', + event = 'VeryLazy', + config = function() + require('neoscroll').setup { + mappings = { -- Keys to be mapped to their corresponding default scrolling animation + '', + '', + '', + '', + '', + '', + 'zt', + 'zz', + 'zb', + }, + hide_cursor = true, -- Hide cursor while scrolling + stop_eof = true, -- Stop at when scrolling downwards + respect_scrolloff = false, -- 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 + easing = 'linear', -- Default easing function + pre_hook = nil, -- Function to run before the scrolling animation starts + post_hook = nil, -- Function to run after the scrolling animation ends + performance_mode = false, -- Disable "Performance Mode" on all buffers. + ignored_events = { -- Events ignored while scrolling + 'WinScrolled', + 'CursorMoved', + }, + } + end, +} diff --git a/lua/custom/plugins/nvim-surround.lua b/lua/custom/plugins/nvim-surround.lua new file mode 100644 index 00000000000..c12b30968b4 --- /dev/null +++ b/lua/custom/plugins/nvim-surround.lua @@ -0,0 +1,8 @@ +return { + 'kylechui/nvim-surround', + version = '*', + event = 'VeryLazy', + config = function() + require('nvim-surround').setup {} + end, +} diff --git a/lua/custom/plugins/persistence.lua b/lua/custom/plugins/persistence.lua new file mode 100644 index 00000000000..c5e7b641042 --- /dev/null +++ b/lua/custom/plugins/persistence.lua @@ -0,0 +1,12 @@ +-- Auto session per cwd. Run `:lua require('persistence').load()` to restore +-- the most recent session, or use the keymaps below. +return { + 'folke/persistence.nvim', + event = 'BufReadPre', + opts = {}, + keys = { + { 'qs', function() require('persistence').load() end, desc = 'Restore session for cwd' }, + { 'ql', function() require('persistence').load({ last = true }) end, desc = 'Restore last session' }, + { 'qd', function() require('persistence').stop() end, desc = "Don't save current session" }, + }, +} diff --git a/lua/custom/plugins/render-markdown.lua b/lua/custom/plugins/render-markdown.lua new file mode 100644 index 00000000000..07616818c4d --- /dev/null +++ b/lua/custom/plugins/render-markdown.lua @@ -0,0 +1,11 @@ +-- In-buffer markdown rendering (headings, lists, code blocks, tables). +-- Applies to markdown buffers, LSP hover docs, and noice popups. +return { + 'MeanderingProgrammer/render-markdown.nvim', + dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, + ft = { 'markdown', 'codecompanion' }, + opts = { + file_types = { 'markdown', 'codecompanion' }, + completions = { lsp = { enabled = true } }, + }, +} diff --git a/lua/custom/plugins/sleuth.lua b/lua/custom/plugins/sleuth.lua new file mode 100644 index 00000000000..ad6149e845a --- /dev/null +++ b/lua/custom/plugins/sleuth.lua @@ -0,0 +1 @@ +return { 'tpope/vim-sleuth' } diff --git a/lua/custom/plugins/telescope.lua b/lua/custom/plugins/telescope.lua new file mode 100644 index 00000000000..efbda46415e --- /dev/null +++ b/lua/custom/plugins/telescope.lua @@ -0,0 +1,114 @@ +return { -- Fuzzy Finder (files, lsp, etc) + 'nvim-telescope/telescope.nvim', + event = 'VimEnter', + branch = '0.1.x', + dependencies = { + 'nvim-lua/plenary.nvim', + { -- If encountering errors, see telescope-fzf-native README for installation 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 a Nerd Font. + { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font }, + }, + 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()` + 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()` + -- + pickers = { + buffers = { + show_all_buffers = true, + sort_mru = true, + mappings = { + i = { + [''] = 'delete_buffer', + }, + }, + }, + }, + -- defaults = { + -- mappings = { + -- i = { [''] = 'to_fuzzy_refine' }, + -- }, + -- }, + extensions = { + ['ui-select'] = { + require('telescope.themes').get_dropdown(), + }, + }, + } + + -- 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', 'fh', builtin.help_tags, { desc = '[S]earch [H]elp' }) + vim.keymap.set('n', 'fk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) + vim.keymap.set('n', 'ff', builtin.find_files, { desc = '[S]earch [F]iles' }) + vim.keymap.set('n', 'fs', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) + vim.keymap.set('n', 'fw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) + vim.keymap.set('n', 'fg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) + vim.keymap.set('n', 'fd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) + vim.keymap.set('n', 'fr', builtin.resume, { desc = '[S]earch [R]esume' }) + vim.keymap.set('n', 'f.', 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 the theme, layout, etc. + builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) + end, { desc = '[/] Fuzzily search in current buffer' }) + + -- It's 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' }) + end, +} diff --git a/lua/custom/plugins/tmux.lua b/lua/custom/plugins/tmux.lua new file mode 100644 index 00000000000..129abd1d635 --- /dev/null +++ b/lua/custom/plugins/tmux.lua @@ -0,0 +1,16 @@ +-- Seamless nvim-split + zellij-pane navigation. +-- Replaces vim-tmux-navigator. smart-splits owns Ctrl-h/j/k/l and falls +-- through to `zellij action move-focus` when at a vim split edge. +return { + 'mrjones2014/smart-splits.nvim', + lazy = false, + opts = { + multiplexer_integration = 'zellij', + }, + keys = { + { '', function() require('smart-splits').move_cursor_left() end, desc = 'Focus left split/pane' }, + { '', function() require('smart-splits').move_cursor_down() end, desc = 'Focus down split/pane' }, + { '', function() require('smart-splits').move_cursor_up() end, desc = 'Focus up split/pane' }, + { '', function() require('smart-splits').move_cursor_right() end, desc = 'Focus right split/pane' }, + }, +} diff --git a/lua/custom/plugins/todo.lua b/lua/custom/plugins/todo.lua new file mode 100644 index 00000000000..15bc4f1ed00 --- /dev/null +++ b/lua/custom/plugins/todo.lua @@ -0,0 +1,6 @@ +return { + 'folke/todo-comments.nvim', + event = 'VimEnter', + dependencies = { 'nvim-lua/plenary.nvim' }, + opts = { signs = false }, +} diff --git a/lua/custom/plugins/toggleterm.lua b/lua/custom/plugins/toggleterm.lua new file mode 100644 index 00000000000..201435c49d5 --- /dev/null +++ b/lua/custom/plugins/toggleterm.lua @@ -0,0 +1,28 @@ +-- Persistent floating/split terminals. Replaces the hand-rolled FloatingTerm. +return { + 'akinsho/toggleterm.nvim', + version = '*', + cmd = { 'ToggleTerm', 'TermExec', 'ToggleTermSendCurrentLine', 'ToggleTermSendVisualLines' }, + keys = { + { 't', 'ToggleTerm direction=float', desc = 'Toggle floating terminal' }, + { 'T', 'ToggleTerm direction=horizontal', desc = 'Toggle horizontal terminal' }, + }, + opts = { + size = function(term) + if term.direction == 'horizontal' then + return math.floor(vim.o.lines * 0.3) + else + return math.floor(vim.o.columns * 0.4) + end + end, + open_mapping = [[]], + direction = 'float', + float_opts = { border = 'rounded' }, + start_in_insert = true, + insert_mappings = true, + terminal_mappings = true, + persist_size = true, + persist_mode = true, + shade_terminals = true, + }, +} diff --git a/lua/custom/plugins/treesitter-context.lua b/lua/custom/plugins/treesitter-context.lua new file mode 100644 index 00000000000..492766bd11e --- /dev/null +++ b/lua/custom/plugins/treesitter-context.lua @@ -0,0 +1,22 @@ +-- Sticky-scroll style context shown at the top of the buffer. +-- Mirrors Zed's `sticky_scroll` feature. +return { + 'nvim-treesitter/nvim-treesitter-context', + event = 'BufReadPost', + opts = { + max_lines = 3, + min_window_height = 20, + mode = 'cursor', + trim_scope = 'outer', + }, + keys = { + { + '[c', + function() + require('treesitter-context').go_to_context(vim.v.count1) + end, + desc = 'Jump to context', + silent = true, + }, + }, +} diff --git a/lua/custom/plugins/treesitter.lua b/lua/custom/plugins/treesitter.lua new file mode 100644 index 00000000000..d5861c10d29 --- /dev/null +++ b/lua/custom/plugins/treesitter.lua @@ -0,0 +1,70 @@ +-- nvim-treesitter `main` branch (required for nvim 0.11+). +-- No more `require('nvim-treesitter.configs').setup{}`. Highlighting is +-- enabled per buffer via vim.treesitter.start() in a FileType autocmd. +return { + 'nvim-treesitter/nvim-treesitter', + branch = 'main', + lazy = false, + build = ':TSUpdate', + dependencies = { + { 'nvim-treesitter/nvim-treesitter-textobjects', branch = 'main' }, + }, + config = function() + -- Parsers we want installed. + local parsers = { + 'go', 'gowork', 'gomod', 'gosum', + 'terraform', 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', + 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc', + 'java', 'json', 'nginx', 'sql', 'tmux', 'typescript', 'yaml', + 'python', 'rust', 'toml', + } + require('nvim-treesitter').install(parsers) + + -- Start treesitter highlighting + indent for any filetype with a parser. + vim.api.nvim_create_autocmd('FileType', { + group = vim.api.nvim_create_augroup('ts-start', { clear = true }), + callback = function(ev) + local ft = vim.bo[ev.buf].filetype + local lang = vim.treesitter.language.get_lang(ft) + if not lang then return end + local ok = pcall(vim.treesitter.start, ev.buf, lang) + if ok then + vim.bo[ev.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end + end, + }) + + -- Treesitter-aware textobjects + motion. + local move = require('nvim-treesitter-textobjects.move') + local select = require('nvim-treesitter-textobjects.select') + + -- Select: vif/vaf (function inner/outer), vac/vic (class), vaa/via (parameter). + local function map_select(key, query) + vim.keymap.set({ 'x', 'o' }, key, function() + select.select_textobject(query, 'textobjects') + end, { desc = 'TS select ' .. query }) + end + map_select('af', '@function.outer') + map_select('if', '@function.inner') + map_select('ac', '@class.outer') + map_select('ic', '@class.inner') + map_select('aa', '@parameter.outer') + map_select('ia', '@parameter.inner') + map_select('al', '@loop.outer') + map_select('il', '@loop.inner') + + -- Move: ]m / [m / ]M / [M between functions. + vim.keymap.set({ 'n', 'x', 'o' }, ']m', + function() move.goto_next_start('@function.outer', 'textobjects') end, + { desc = 'TS next function start' }) + vim.keymap.set({ 'n', 'x', 'o' }, ']M', + function() move.goto_next_end('@function.outer', 'textobjects') end, + { desc = 'TS next function end' }) + vim.keymap.set({ 'n', 'x', 'o' }, '[m', + function() move.goto_previous_start('@function.outer', 'textobjects') end, + { desc = 'TS prev function start' }) + vim.keymap.set({ 'n', 'x', 'o' }, '[M', + function() move.goto_previous_end('@function.outer', 'textobjects') end, + { desc = 'TS prev function end' }) + end, +} diff --git a/lua/custom/plugins/trouble.lua b/lua/custom/plugins/trouble.lua new file mode 100644 index 00000000000..c9ccbb89550 --- /dev/null +++ b/lua/custom/plugins/trouble.lua @@ -0,0 +1,14 @@ +-- Pretty diagnostics / LSP refs / TODO / quickfix lists. +return { + 'folke/trouble.nvim', + cmd = 'Trouble', + opts = {}, + keys = { + { 'xx', 'Trouble diagnostics toggle', desc = '[T]rouble diagnostics' }, + { 'xX', 'Trouble diagnostics toggle filter.buf=0', desc = '[T]rouble buffer diagnostics' }, + { 'xs', 'Trouble symbols toggle focus=false', desc = '[T]rouble symbols' }, + { 'xr', 'Trouble lsp toggle focus=false win.position=right', desc = '[T]rouble LSP refs/defs' }, + { 'xl', 'Trouble loclist toggle', desc = '[T]rouble loclist' }, + { 'xq', 'Trouble qflist toggle', desc = '[T]rouble quickfix' }, + }, +} diff --git a/lua/custom/plugins/which-key.lua b/lua/custom/plugins/which-key.lua new file mode 100644 index 00000000000..d9679af7595 --- /dev/null +++ b/lua/custom/plugins/which-key.lua @@ -0,0 +1,56 @@ +return { -- Useful plugin to show you pending keybinds. + 'folke/which-key.nvim', + event = 'VimEnter', -- Sets the loading event to 'VimEnter' + opts = { + -- delay between pressing a key and opening which-key (milliseconds) + -- this setting is independent of vim.opt.timeoutlen + delay = 500, + icons = { + -- set icon mappings to true if you have a Nerd Font + mappings = vim.g.have_nerd_font, + -- If you are using a Nerd Font: set icons.keys to an empty table which will use the + -- default which-key.nvim defined Nerd Font icons, otherwise define a string table + keys = vim.g.have_nerd_font and {} or { + Up = ' ', + Down = ' ', + Left = ' ', + Right = ' ', + C = ' ', + M = ' ', + D = ' ', + S = ' ', + CR = ' ', + Esc = ' ', + ScrollWheelDown = ' ', + ScrollWheelUp = ' ', + NL = ' ', + BS = ' ', + Space = ' ', + Tab = ' ', + F1 = '', + F2 = '', + F3 = '', + F4 = '', + F5 = '', + F6 = '', + F7 = '', + F8 = '', + F9 = '', + F10 = '', + F11 = '', + F12 = '', + }, + }, + + -- Document existing key chains + spec = { + { 'c', group = '[C]ode', mode = { 'n', 'x' } }, + { 'd', group = '[D]ocument' }, + { 'r', group = '[R]ename' }, + { 's', group = '[S]earch' }, + { 'w', group = '[W]orkspace' }, + { 't', group = '[T]oggle' }, + { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + }, + }, +} diff --git a/lua/custom/zed-keymaps.lua b/lua/custom/zed-keymaps.lua new file mode 100644 index 00000000000..2b2bab756cc --- /dev/null +++ b/lua/custom/zed-keymaps.lua @@ -0,0 +1,57 @@ +-- Mirrors common Zed bindings for muscle-memory continuity. +-- Source from init.lua: require('custom.zed-keymaps'). + +-- Move lines (Zed: alt-j / alt-k). +vim.keymap.set('n', '', ':m .+1==', { desc = 'Move line down', silent = true }) +vim.keymap.set('n', '', ':m .-2==', { desc = 'Move line up', silent = true }) +vim.keymap.set('v', '', ":m '>+1gv=gv", { desc = 'Move selection down', silent = true }) +vim.keymap.set('v', '', ":m '<-2gv=gv", { desc = 'Move selection up', silent = true }) + +-- Lowercase gi for implementation (Zed: g i; existing gI still works). +vim.keymap.set('n', 'gi', function() + require('telescope.builtin').lsp_implementations() +end, { desc = '[G]oto [I]mplementation' }) + +-- Zed-parity: F2 to rename, . for code action (mirrors cmd-.), +-- fc for command palette. +vim.keymap.set('n', '', vim.lsp.buf.rename, { desc = 'LSP rename' }) +vim.keymap.set('n', '.', vim.lsp.buf.code_action, { desc = 'Code action' }) +vim.keymap.set('n', 'fc', function() require('telescope.builtin').commands() end, { desc = '[F]ind [C]ommand' }) + +-- Full-buffer git blame (Zed: g b). +vim.keymap.set('n', 'gb', function() + require('gitsigns').blame() +end, { desc = '[G]it [B]lame buffer' }) + +-- Close current buffer (Zed: space x). +vim.keymap.set('n', 'x', 'bd', { desc = 'Close buffer' }) + +-- Workspace symbols (Zed: space f e). +vim.keymap.set('n', 'fe', function() + require('telescope.builtin').lsp_dynamic_workspace_symbols() +end, { desc = '[F]ind workspace symbols' }) + +-- Task spawner: floating zellij pane when in zellij, fallback to nvim split term. +local function task(cmd) + return function() + if vim.env.ZELLIJ ~= nil and vim.env.ZELLIJ ~= '' then + vim.fn.jobstart({ + 'zellij', 'action', 'new-pane', '--floating', + '--close-on-exit', '--', '/bin/zsh', '-lc', cmd, + }, { detach = true }) + else + vim.cmd('botright 15split | terminal ' .. cmd) + vim.cmd('startinsert') + end + end +end + +-- Task bindings (mirror Zed's tasks.json). +vim.keymap.set('n', 'gh', task('gh dash'), { desc = '[G]itHub das[H]board' }) +vim.keymap.set('n', 'kk', task('k9s'), { desc = '[K]9s' }) +vim.keymap.set('n', 'bb', task('cd bruno && bru run --env Local --insecure --tests-only'), { desc = '[B]runo tests' }) +vim.keymap.set('n', 'uu', task('cd restopay && make up'), { desc = 'Make [U]p' }) +vim.keymap.set('n', 'dd', task('cd restopay && make down'), { desc = 'Make Do[w]n' }) +vim.keymap.set('n', 'aa', task( + 'hv athenz user-cert --system=public && awscreds -d vespa.external.factory -r admin -p external-factory -z public' +), { desc = 'Update certs for External-Factory' }) diff --git a/lua/kickstart/plugins/indent_line.lua b/lua/kickstart/plugins/indent_line.lua deleted file mode 100644 index ed7f269399f..00000000000 --- a/lua/kickstart/plugins/indent_line.lua +++ /dev/null @@ -1,9 +0,0 @@ -return { - { -- Add indentation guides even on blank lines - 'lukas-reineke/indent-blankline.nvim', - -- Enable `lukas-reineke/indent-blankline.nvim` - -- See `:help ibl` - main = 'ibl', - opts = {}, - }, -} diff --git a/lua/kickstart/plugins/lint.lua b/lua/kickstart/plugins/lint.lua deleted file mode 100644 index 907c6bf3e31..00000000000 --- a/lua/kickstart/plugins/lint.lua +++ /dev/null @@ -1,60 +0,0 @@ -return { - - { -- Linting - 'mfussenegger/nvim-lint', - event = { 'BufReadPre', 'BufNewFile' }, - config = function() - local lint = require 'lint' - lint.linters_by_ft = { - markdown = { 'markdownlint' }, - } - - -- To allow other plugins to add linters to require('lint').linters_by_ft, - -- instead set linters_by_ft like this: - -- lint.linters_by_ft = lint.linters_by_ft or {} - -- lint.linters_by_ft['markdown'] = { 'markdownlint' } - -- - -- However, note that this will enable a set of default linters, - -- which will cause errors unless these tools are available: - -- { - -- clojure = { "clj-kondo" }, - -- dockerfile = { "hadolint" }, - -- inko = { "inko" }, - -- janet = { "janet" }, - -- json = { "jsonlint" }, - -- markdown = { "vale" }, - -- rst = { "vale" }, - -- ruby = { "ruby" }, - -- terraform = { "tflint" }, - -- text = { "vale" } - -- } - -- - -- You can disable the default linters by setting their filetypes to nil: - -- lint.linters_by_ft['clojure'] = nil - -- lint.linters_by_ft['dockerfile'] = nil - -- lint.linters_by_ft['inko'] = nil - -- lint.linters_by_ft['janet'] = nil - -- lint.linters_by_ft['json'] = nil - -- lint.linters_by_ft['markdown'] = nil - -- lint.linters_by_ft['rst'] = nil - -- lint.linters_by_ft['ruby'] = nil - -- lint.linters_by_ft['terraform'] = nil - -- lint.linters_by_ft['text'] = nil - - -- Create autocommand which carries out the actual linting - -- on the specified events. - local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true }) - vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, { - group = lint_augroup, - callback = function() - -- Only run the linter in buffers that you can modify in order to - -- avoid superfluous noise, notably within the handy LSP pop-ups that - -- describe the hovered symbol using Markdown. - if vim.opt_local.modifiable:get() then - lint.try_lint() - end - end, - }) - end, - }, -} diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/kickstart/plugins/neo-tree.lua deleted file mode 100644 index bd4422695aa..00000000000 --- a/lua/kickstart/plugins/neo-tree.lua +++ /dev/null @@ -1,25 +0,0 @@ --- Neo-tree is a Neovim plugin to browse the file system --- https://github.com/nvim-neo-tree/neo-tree.nvim - -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', - }, - cmd = 'Neotree', - keys = { - { '\\', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, - }, - opts = { - filesystem = { - window = { - mappings = { - ['\\'] = 'close_window', - }, - }, - }, - }, -}