Claude updates

This commit is contained in:
Nurzhan Sarzhan 2026-05-12 14:01:29 +02:00
parent 831cd284aa
commit 47fcf0bef5
No known key found for this signature in database
24 changed files with 696 additions and 490 deletions

42
CLAUDE.md Normal file
View File

@ -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 <plugin>` 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, `<leader>.` code action, `gb` blame, `<leader>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** (`<C-h/j/k/l>`) 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`, `<leader>rn`, `<leader>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**: `<A-1>`..`<A-9>` jump to `vim.t.bufs[i]` (populated by `mini.bufremove`/`mini.tabline` from `mini.lua`).
- **`;` is remapped to `:`** in normal mode. `<Esc>` 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 `<leader>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).

380
README.md
View File

@ -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
```
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
```
**NOT** a Neovim distribution, but instead a starting point for your configuration.
No build/test step. Changes take effect on `nvim` restart (or `:source %` / `:Lazy reload <plugin>`). Lua is formatted by `stylua` per `.stylua.toml` (2-space, single quotes, 160-col).
## Installation
## Install
### 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/<your_github_username>/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 `<your_github_username>` in the commands below
<details><summary> Linux and Mac </summary>
```sh
git clone https://github.com/nvim-lua/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim
```
</details>
<details><summary> Windows </summary>
If you're using `cmd.exe`:
```
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"
```
</details>
### 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 <your-fork> "${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.
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.
#### Read The Friendly Documentation
## Editor defaults (`init.lua`)
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.
- 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.
> [!NOTE]
> For more information about a particular plugin check its repository's documentation.
## 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 <dir>`) |
| `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` | `<C-hjkl>` 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 `<M-Tab>`) |
| `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 |
### Getting Started
## Keymaps
[The Only Video You Need to Get Started with Neovim](https://youtu.be/m8C0Cq9Uv9o)
### Movement & editing (`init.lua` / `zed-keymaps.lua`)
| Key | Mode | Action |
| :--- | :--- | :--- |
| `;` | n | `:` (command mode) |
| `<Esc>` | n | Clear search highlight |
| `oo` / `OO` | n | Open blank line below/above without entering insert |
| `<leader>p` | x | Paste without clobbering register |
| `<A-j>` / `<A-k>` | n/v | Move line/selection down/up |
| `<C-h/j/k/l>` | i | Arrow keys in insert |
| `<C-h/l/b/f/k/j>` | c | Word/char nav in command line |
| `<C-w>` | i | Delete previous word |
| `s` / `S` / `r` / `R` | n/x/o | flash.nvim jump / treesitter / remote |
### FAQ
### Windows, buffers, tasks
| Key | Action |
| :--- | :--- |
| `<C-h/j/k/l>` | Focus split — falls through to zellij pane |
| `<A-1>`..`<A-9>` | Jump to buffer slot 1..9 (`vim.t.bufs[i]`) |
| `<leader>x` | Close current buffer |
| `<leader>t` / `<leader>T` | Floating / horizontal toggleterm |
| `<C-\>` | Open mapping for toggleterm |
| `<leader>gh` | `gh dash` in floating pane |
| `<leader>kk` | `k9s` |
| `<leader>bb` | bruno tests |
| `<leader>uu` / `<leader>dd` | `make up` / `make down` in `restopay/` |
| `<leader>aa` | Refresh Athenz cert + AWS creds for `external-factory` |
* 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)
### Finder (`<leader>f…`)
| Key | Action |
| :--- | :--- |
| `<leader>ff` | Files |
| `<leader>fg` | Live grep |
| `<leader>fw` | Grep current word |
| `<leader>fd` | Diagnostics |
| `<leader>fh` | Help tags |
| `<leader>fk` | Keymaps |
| `<leader>fs` | Telescope builtins |
| `<leader>fr` | Resume last picker |
| `<leader>f.` | Recent files |
| `<leader>fc` | Commands |
| `<leader>fe` | Workspace symbols |
| `<leader><leader>` | Buffers |
| `<leader>/` | Fuzzy find in current buffer |
| `<leader>s/` | Live grep in open buffers |
| `<leader>sn` | Find files in nvim config |
### Install Recipes
### LSP (set on `LspAttach`, plus zed-parity)
| Key | Action |
| :--- | :--- |
| `gd` / `gr` / `gI` | Definitions / refs / implementations (telescope) |
| `gi` | Implementations (lowercase zed-style) |
| `gD` | Declaration |
| `<leader>D` | Type definition |
| `<leader>ds` / `<leader>ws` | Document / workspace symbols |
| `<leader>rn` or `F2` | Rename |
| `<leader>ca` or `<leader>.` | Code action |
| `<leader>th` | Toggle inlay hints (on by default for Go) |
| `<leader>q` | Diagnostics → loclist |
| `<leader>f` | Format buffer (conform) |
Below you can find OS specific install instructions for Neovim and dependencies.
### Git
| Key | Action |
| :--- | :--- |
| `]c` / `[c` | Next / prev hunk |
| `<leader>hs` / `<leader>hr` | Stage / reset hunk (works in visual) |
| `<leader>hS` / `<leader>hR` | Stage / reset buffer |
| `<leader>hu` | Undo stage hunk |
| `<leader>hp` | Preview hunk |
| `<leader>hb` | Blame current line |
| `<leader>hd` / `<leader>hD` | Diff vs index / last commit |
| `<leader>tb` / `<leader>tD` | Toggle inline blame / deleted markers |
| `gb` | Full-buffer blame |
After installing all the dependencies continue with the [Install Kickstart](#Install-Kickstart) step.
### Harpoon
| Key | Action |
| :--- | :--- |
| `<leader>ha` | Add current file |
| `<leader>hh` | Toggle harpoon menu |
| `<leader>1`..`<leader>4` | Jump to slot 1..4 |
| `[h` / `]h` | Prev / next entry |
#### Windows Installation
### Trouble (`<leader>x…`)
| Key | Action |
| :--- | :--- |
| `<leader>xx` | Workspace diagnostics |
| `<leader>xX` | Buffer diagnostics |
| `<leader>xs` | Symbols |
| `<leader>xr` | LSP refs/defs (right) |
| `<leader>xl` / `<leader>xq` | Loclist / quickfix |
<details><summary>Windows with Microsoft C++ Build Tools and CMake</summary>
Installation may require installing build tools and updating the run command for `telescope-fzf-native`
### Neo-tree
| Key | Action |
| :--- | :--- |
| `\` or `<leader>e` | Reveal file in tree |
| (inside tree) `h` / `l` / `<tab>` | Collapse / expand+open / smart-toggle |
| (inside tree) `T` | Trash file (via `trash` CLI) |
See `telescope-fzf-native` documentation for [more details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation)
### Treesitter textobjects
`af`/`if` function, `ac`/`ic` class, `aa`/`ia` parameter, `al`/`il` loop; `]m`/`[m`/`]M`/`[M` move between functions.
This requires:
### Copilot / chat
| Key | Action |
| :--- | :--- |
| `<M-Tab>` (insert) | Accept Copilot suggestion |
| `<leader>cc` / `<leader>ce` / `<leader>cf` / `<leader>cr` / `<leader>ct` / `<leader>cm` | Chat / explain / fix / review / tests / commit-msg |
- Install CMake and the Microsoft C++ Build Tools on Windows
### Sessions (persistence.nvim)
| Key | Action |
| :--- | :--- |
| `<leader>qs` | Load session for cwd |
| `<leader>ql` | Load last session |
| `<leader>qd` | Stop saving current session |
```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' }
```
</details>
<details><summary>Windows with gcc/make using chocolatey</summary>
Alternatively, one can install gcc and make which don't require changing the config,
the easiest way is to use choco:
## LSP & formatting notes
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
```
- `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`.
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
```
</details>
<details><summary>WSL (Windows Subsystem for Linux)</summary>
## Adding a plugin
```
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
```
</details>
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.
#### Linux Install
<details><summary>Ubuntu Install Steps</summary>
```
sudo add-apt-repository ppa:neovim-ppa/unstable -y
sudo apt update
sudo apt install make gcc ripgrep unzip git xclip neovim
```
</details>
<details><summary>Debian Install Steps</summary>
```
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/
```
</details>
<details><summary>Fedora Install Steps</summary>
```
sudo dnf install -y gcc make git ripgrep fd-find unzip neovim
```
</details>
<details><summary>Arch Install Steps</summary>
```
sudo pacman -S --noconfirm --needed gcc make git ripgrep fd unzip neovim
```
</details>
## 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 `<C-h/j/k/l>` 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`.

View File

@ -4,13 +4,19 @@ vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
vim.g.have_nerd_font = true
-- 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'
vim.opt.relativenumber = true
vim.opt.mouse = 'a'
vim.opt.showmode = false
vim.opt.smartindent = true
vim.opt.spelllang = 'en_us'
vim.o.spell = true
vim.o.colorcolumn = '80'
-- 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.
@ -97,18 +103,22 @@ vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>')
-- Diagnostic keymaps
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { 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()`
@ -132,39 +142,7 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then
end ---@diagnostic disable-next-line: undefined-field
vim.opt.rtp:prepend(lazypath)
local floating_win = nil
function FloatingTerm()
if floating_win and vim.api.nvim_win_is_valid(floating_win) then
vim.api.nvim_win_close(floating_win, true)
floating_win = nil
return
end
local buf = vim.api.nvim_create_buf(false, true)
local width = math.floor(vim.o.columns * 0.8)
local height = math.floor(vim.o.lines * 0.8)
local row = math.floor((vim.o.lines - height) / 2)
local col = math.floor((vim.o.columns - width) / 2)
floating_win = vim.api.nvim_open_win(buf, true, {
relative = 'editor',
width = width,
height = height,
row = row,
col = col,
style = 'minimal',
border = 'rounded',
})
vim.fn.termopen(vim.o.shell)
vim.cmd 'startinsert'
-- Map <Esc> to close the floating terminal when inside it
vim.api.nvim_buf_set_keymap(buf, 't', '<Esc>', '<C-\\><C-n>:lua FloatingTerm()<CR>', { noremap = true, silent = true })
end
vim.api.nvim_set_keymap('n', '<leader>t', ':lua FloatingTerm()<CR>', { noremap = true, silent = true })
require('custom.zed-keymaps')
require('lazy').setup({ { import = 'custom.plugins' } }, {
ui = {

View File

@ -1,115 +1,39 @@
return { -- Autocompletion
'hrsh7th/nvim-cmp',
event = 'InsertEnter',
-- 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 = {
-- 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,
-- },
'rafamadriz/friendly-snippets',
},
opts = {
-- Use the 'enter' preset: <CR> confirms, <Tab>/<S-Tab> cycle items.
keymap = {
preset = 'enter',
['<Tab>'] = { 'select_next', 'snippet_forward', 'fallback' },
['<S-Tab>'] = { 'select_prev', 'snippet_backward', 'fallback' },
['<C-Space>'] = { '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,
},
},
},
'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
-- ['<C-n>'] = cmp.mapping.select_next_item(),
-- Select the [p]revious item
-- ['<C-p>'] = cmp.mapping.select_prev_item(),
-- Scroll the documentation window [b]ack / [f]orward
['<C-b>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = 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.
-- ['<C-y>'] = cmp.mapping.confirm { select = true },
-- If you prefer more traditional completion keymaps,
-- you can uncomment the following lines
['<CR>'] = cmp.mapping.confirm { select = true },
['<Tab>'] = cmp.mapping.select_next_item(),
['<S-Tab>'] = 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.
['<C-Space>'] = cmp.mapping.complete {},
-- Think of <c-l> as moving to the right of your snippet expansion.
-- So if you have a snippet that's like:
-- function $name($args)
-- $body
-- end
--
-- <c-l> will move you to the right of each of the expansion locations.
-- <c-h> is similar, except moving you backwards.
['<C-l>'] = cmp.mapping(function()
if luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
end
end, { 'i', 's' }),
['<C-h>'] = 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,
}

View File

@ -18,7 +18,7 @@ return { -- Autoformat
-- 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 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'
@ -35,7 +35,7 @@ return { -- Autoformat
terraform = { 'terraform_fmt' },
xml = { 'xmlformatter', 'prettier' },
lua = { 'stylua' },
python = { 'isort', 'black' },
python = { 'ruff_organize_imports', 'ruff_format' },
javascript = { 'prettierd', 'prettier', stop_after_first = true },
},
},

View File

@ -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 = {
{ '<leader>cc', '<cmd>CopilotChatToggle<cr>', mode = { 'n', 'x' }, desc = '[C]opilot [C]hat' },
{ '<leader>ce', '<cmd>CopilotChatExplain<cr>', mode = { 'n', 'x' }, desc = '[C]opilot [E]xplain' },
{ '<leader>cf', '<cmd>CopilotChatFix<cr>', mode = { 'n', 'x' }, desc = '[C]opilot [F]ix' },
{ '<leader>cr', '<cmd>CopilotChatReview<cr>', mode = { 'n', 'x' }, desc = '[C]opilot [R]eview' },
{ '<leader>ct', '<cmd>CopilotChatTests<cr>', mode = { 'n', 'x' }, desc = '[C]opilot [T]ests' },
{ '<leader>cm', '<cmd>CopilotChatCommit<cr>', desc = '[C]opilot co[M]mit msg' },
},
}

View File

@ -0,0 +1,6 @@
-- Replace the ugly default vim.ui.input/select with a floating UI.
return {
'stevearc/dressing.nvim',
event = 'VeryLazy',
opts = {},
}

View File

@ -2,6 +2,8 @@ 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'

View File

@ -1,6 +0,0 @@
return {
'ellisonleao/glow.nvim',
config = function()
require('glow').setup()
end,
}

View File

@ -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', '<leader>ha', function() harpoon:list():add() end, { desc = '[H]arpoon [A]dd file' })
vim.keymap.set('n', '<leader>hh', function() harpoon.ui:toggle_quick_menu(harpoon:list()) end, { desc = '[H]arpoon toggle list' })
-- Jump to harpoon slots 1..4. (<C-h..> reserved for smart-splits pane nav.)
for i = 1, 4 do
vim.keymap.set('n', '<leader>' .. 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,
}

View File

@ -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,
}

View File

@ -1,9 +1,13 @@
-- flash.nvim: smarter `s`/`S` jump with treesitter-aware selection and
-- remote operations (e.g. `yr<motion>` to yank a remote region).
return {
'ggandor/leap.nvim',
'folke/flash.nvim',
event = 'VeryLazy',
config = function()
vim.keymap.set({ 'n', 'x', 'o' }, 's', '<Plug>(leap-forward)', { noremap = true, silent = true })
vim.keymap.set({ 'n', 'x', 'o' }, 'S', '<Plug>(leap-backward)', { noremap = true, silent = true })
vim.keymap.set({ 'n', 'x', 'o' }, 'gs', '<Plug>(leap-from-window)', { noremap = true, silent = true })
end,
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' },
},
}

View File

@ -25,8 +25,8 @@ return {
-- Useful status updates for LSP.
{ 'j-hui/fidget.nvim', opts = {} },
-- Allows extra capabilities provided by nvim-cmp
'hrsh7th/cmp-nvim-lsp',
-- Completion capabilities from blink.cmp.
'saghen/blink.cmp',
},
config = function()
-- Brief aside: **What is LSP?**
@ -114,7 +114,7 @@ return {
--
-- 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
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,
@ -141,10 +141,32 @@ return {
-- 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
if client and client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then
map('<leader>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,
})
@ -163,8 +185,7 @@ return {
-- 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())
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.
@ -181,6 +202,8 @@ return {
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 = {
@ -190,13 +213,38 @@ return {
},
gofumpt = true,
staticcheck = true,
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,
compositeLiteralTypes = true,
constantValues = true,
functionTypeParameters = true,
parameterNames = true,
rangeVariableTypes = true,
},
},
},
env = {
GOEXPERIMENT = 'rangefunc',
},
pyright = {
settings = {
pyright = {
-- Disable pyright's import organizer; let ruff handle it.
disableOrganizeImports = true,
},
python = {
analysis = {
-- ignore lint errors; ruff handles linting.
ignore = { '*' },
},
},
},
},
pyright = {},
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
--
@ -239,8 +287,10 @@ return {
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 }

View File

@ -1,7 +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',
build = 'cd app && npm install',
config = function()
vim.g.mkdp_auto_start = 1
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 = {
{ '<leader>mp', '<cmd>MarkdownPreviewToggle<cr>', desc = '[M]arkdown [P]review' },
},
}

View File

@ -5,7 +5,6 @@ return { -- Collection of various small independent plugins/modules
require('mini.move').setup()
require('mini.notify').setup()
require('mini.starter').setup()
require('mini.tabline').setup()
require('mini.statusline').setup {
use_icons = vim.g.have_nerd_font,
}

View File

@ -8,56 +8,30 @@ return {
'saifulapm/neotree-file-nesting-config',
},
cmd = 'Neotree',
opts = {
-- recommended config for better UI
hide_root_node = true,
retain_hidden_root_indent = true,
filesystem = {
filtered_items = {
show_hidden_count = false,
never_show = {
'.DS_Store',
},
},
},
default_component_configs = {
indent = {
with_expanders = true,
expander_collapsed = '',
expander_expanded = '',
},
},
},
-- 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<CR>', desc = 'NeoTree reveal', silent = true },
{
'<leader>b',
function()
require('neo-tree.command').execute { toggle = true, source = 'buffers', position = 'left' }
end,
desc = 'Buffers (root dir)',
},
{
'<leader>e',
function()
require('neo-tree.command').execute { toggle = true, source = 'filesystem', position = 'left' }
end,
desc = 'Filesystem (root dir)',
},
{
'<leader>g',
function()
require('neo-tree.command').execute { toggle = true, source = 'git_status', position = 'left' }
end,
desc = 'Filesystem (root dir)',
},
{ '<leader>e', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
},
config = function(_, opts)
opts.nesting_rules = require('neotree-file-nesting-config').nesting_rules
require('neo-tree').setup(opts)
config = function()
local inputs = require 'neo-tree.ui.inputs'
-- Trash the target
local function trash(state)
local node = state.tree:get_node()
if node.type == 'message' then
@ -74,7 +48,6 @@ return {
end)
end
-- Trash the selections (visual mode)
local function trash_visual(state, selected_nodes)
local paths_to_trash = {}
for _, node in ipairs(selected_nodes) do
@ -95,6 +68,25 @@ return {
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',

View File

@ -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 = {
{ '<leader>qs', function() require('persistence').load() end, desc = 'Restore session for cwd' },
{ '<leader>ql', function() require('persistence').load({ last = true }) end, desc = 'Restore last session' },
{ '<leader>qd', function() require('persistence').stop() end, desc = "Don't save current session" },
},
}

View File

@ -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 } },
},
}

View File

@ -1,18 +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 {
'christoomey/vim-tmux-navigator',
event = 'VeryLazy',
cmd = {
'TmuxNavigateLeft',
'TmuxNavigateDown',
'TmuxNavigateUp',
'TmuxNavigateRight',
'TmuxNavigatePrevious',
'mrjones2014/smart-splits.nvim',
lazy = false,
opts = {
multiplexer_integration = 'zellij',
},
keys = {
{ '<c-h>', '<cmd><C-U>TmuxNavigateLeft<cr>' },
{ '<c-j>', '<cmd><C-U>TmuxNavigateDown<cr>' },
{ '<c-k>', '<cmd><C-U>TmuxNavigateUp<cr>' },
{ '<c-l>', '<cmd><C-U>TmuxNavigateRight<cr>' },
{ '<c-\\>', '<cmd><C-U>TmuxNavigatePrevious<cr>' },
{ '<C-h>', function() require('smart-splits').move_cursor_left() end, desc = 'Focus left split/pane' },
{ '<C-j>', function() require('smart-splits').move_cursor_down() end, desc = 'Focus down split/pane' },
{ '<C-k>', function() require('smart-splits').move_cursor_up() end, desc = 'Focus up split/pane' },
{ '<C-l>', function() require('smart-splits').move_cursor_right() end, desc = 'Focus right split/pane' },
},
}

View File

@ -0,0 +1,28 @@
-- Persistent floating/split terminals. Replaces the hand-rolled FloatingTerm.
return {
'akinsho/toggleterm.nvim',
version = '*',
cmd = { 'ToggleTerm', 'TermExec', 'ToggleTermSendCurrentLine', 'ToggleTermSendVisualLines' },
keys = {
{ '<leader>t', '<cmd>ToggleTerm direction=float<cr>', desc = 'Toggle floating terminal' },
{ '<leader>T', '<cmd>ToggleTerm direction=horizontal<cr>', 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 = [[<c-\>]],
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,
},
}

View File

@ -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,
},
},
}

View File

@ -1,50 +1,70 @@
return { -- Highlight, edit, and navigate code
-- 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',
main = 'nvim-treesitter.configs', -- Sets main module to use for opts
-- [[ Configure Treesitter ]] See `:help nvim-treesitter`
opts = {
ensure_installed = {
'go',
'gowork',
'gomod',
'gosum',
'terraform',
'bash',
'c',
'diff',
'html',
'lua',
'luadoc',
'markdown',
'markdown_inline',
'query',
'vim',
'vimdoc',
'java',
'json',
'markdown',
'nginx',
'sql',
'tmux',
'typescript',
'yaml',
},
-- 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' } },
dependencies = {
{ 'nvim-treesitter/nvim-treesitter-textobjects', branch = 'main' },
},
-- 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
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,
}

View File

@ -0,0 +1,14 @@
-- Pretty diagnostics / LSP refs / TODO / quickfix lists.
return {
'folke/trouble.nvim',
cmd = 'Trouble',
opts = {},
keys = {
{ '<leader>xx', '<cmd>Trouble diagnostics toggle<cr>', desc = '[T]rouble diagnostics' },
{ '<leader>xX', '<cmd>Trouble diagnostics toggle filter.buf=0<cr>', desc = '[T]rouble buffer diagnostics' },
{ '<leader>xs', '<cmd>Trouble symbols toggle focus=false<cr>', desc = '[T]rouble symbols' },
{ '<leader>xr', '<cmd>Trouble lsp toggle focus=false win.position=right<cr>', desc = '[T]rouble LSP refs/defs' },
{ '<leader>xl', '<cmd>Trouble loclist toggle<cr>', desc = '[T]rouble loclist' },
{ '<leader>xq', '<cmd>Trouble qflist toggle<cr>', desc = '[T]rouble quickfix' },
},
}

View File

@ -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', '<A-j>', ':m .+1<CR>==', { desc = 'Move line down', silent = true })
vim.keymap.set('n', '<A-k>', ':m .-2<CR>==', { desc = 'Move line up', silent = true })
vim.keymap.set('v', '<A-j>', ":m '>+1<CR>gv=gv", { desc = 'Move selection down', silent = true })
vim.keymap.set('v', '<A-k>', ":m '<-2<CR>gv=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, <leader>. for code action (mirrors cmd-.),
-- <leader>fc for command palette.
vim.keymap.set('n', '<F2>', vim.lsp.buf.rename, { desc = 'LSP rename' })
vim.keymap.set('n', '<leader>.', vim.lsp.buf.code_action, { desc = 'Code action' })
vim.keymap.set('n', '<leader>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', '<leader>x', '<cmd>bd<cr>', { desc = 'Close buffer' })
-- Workspace symbols (Zed: space f e).
vim.keymap.set('n', '<leader>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', '<leader>gh', task('gh dash'), { desc = '[G]itHub das[H]board' })
vim.keymap.set('n', '<leader>kk', task('k9s'), { desc = '[K]9s' })
vim.keymap.set('n', '<leader>bb', task('cd bruno && bru run --env Local --insecure --tests-only'), { desc = '[B]runo tests' })
vim.keymap.set('n', '<leader>uu', task('cd restopay && make up'), { desc = 'Make [U]p' })
vim.keymap.set('n', '<leader>dd', task('cd restopay && make down'), { desc = 'Make Do[w]n' })
vim.keymap.set('n', '<leader>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' })