From e8b998de5b8e0620bd5c8e0d7f21c218478e764a Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Mon, 15 Jun 2026 20:37:54 -0500 Subject: [PATCH 01/12] feat: Cleanup and add some base plugins Signed-off-by: Tristan Jahnke --- .pre-commit-config.yaml | 60 +-- Makefile | 103 ----- README.md | 273 ------------ autocmds.lua | 101 +++++ config.lua | 80 ++++ docs/KEYBINDINGS.md | 164 ------- docs/PLUGINS.md | 403 ----------------- examples/.editorconfig | 54 --- examples/ruff-config.toml | 33 -- init.lua | 86 +++- install.sh | 420 ----------------- keymaps.lua | 102 +++++ lazy-lock.json | 310 ------------- lua/config/keymaps.lua | 152 ------- lua/config/lazy.lua | 22 - lua/config/options.lua | 52 --- lua/plugins/aerial.lua | 146 ------ lua/plugins/blink-cmp.lua | 108 ----- lua/plugins/catppuccin.lua | 127 ------ lua/plugins/cloak.lua | 22 - lua/plugins/diffview.lua | 230 ---------- lua/plugins/elixir-tools.lua | 44 -- lua/plugins/emoji.lua | 18 - lua/plugins/fidget.lua | 86 ---- lua/plugins/gitlab.lua | 276 ------------ lua/plugins/gitsigns.lua | 34 -- lua/plugins/go-nvim.lua | 64 --- lua/plugins/harpoon.lua | 37 -- lua/plugins/kulala.lua | 24 - lua/plugins/lsp_signature.lua | 47 -- lua/plugins/lspconfig.lua | 247 ---------- lua/plugins/lspkind.lua | 66 --- lua/plugins/lualine.lua | 77 ---- lua/plugins/mason-lspconfig.lua | 18 - lua/plugins/mason-tool-installer.lua | 51 --- lua/plugins/mason.lua | 15 - lua/plugins/neotest.lua | 169 ------- lua/plugins/nvim-autopairs.lua | 30 -- lua/plugins/nvim-colorizer.lua | 23 - lua/plugins/nvim-coverage.lua | 46 -- lua/plugins/nvim-dap-go.lua | 25 -- lua/plugins/nvim-dap-python.lua | 42 -- lua/plugins/nvim-dap.lua | 39 -- lua/plugins/nvim-jqx.lua | 10 - lua/plugins/nvim-lint.lua | 43 -- lua/plugins/nvim-man.lua | 3 - lua/plugins/nvim-navic.lua | 69 --- lua/plugins/nvim-origami.lua | 98 ---- lua/plugins/nvim-silicon.lua | 29 -- lua/plugins/nvim-surround.lua | 6 - lua/plugins/nvim-treesitter-textobjects.lua | 117 ----- lua/plugins/nvim-ufo.lua | 112 ----- lua/plugins/nvim-web-devicons.lua | 4 - lua/plugins/octo.lua | 280 ------------ lua/plugins/overseer.lua | 266 ----------- lua/plugins/package-info.lua | 70 --- lua/plugins/pr-description.lua | 5 - lua/plugins/profile.lua | 32 -- lua/plugins/refactoring.lua | 110 ----- lua/plugins/render-markdown.lua | 147 ------ lua/plugins/scissors.lua | 43 -- lua/plugins/smart-splits.lua | 56 --- lua/plugins/smartcolumn-nvim.lua | 15 - lua/plugins/snacks.lua | 392 ---------------- lua/plugins/spectre.lua | 9 - lua/plugins/terraform-local-modules.lua | 446 ------------------- lua/plugins/terrareg.lua | 16 - lua/plugins/todo-comments.lua | 22 - lua/plugins/trouble.lua | 77 ---- lua/plugins/undotree.lua | 7 - lua/plugins/vim-dadbod-ui.lua | 28 -- lua/plugins/vim-table-mode.lua | 30 -- lua/plugins/which-key.lua | 103 ----- lua/utils/git_repo.lua | 146 ------ lua/utils/keymap_check.lua | 330 -------------- nvim-pack-lock.json | 28 ++ options.lua | 81 ++++ {lua/plugins => plugins}/conform.lua | 9 +- plugins/gitsigns.lua | 56 +++ {lua/plugins => plugins}/nvim-treesitter.lua | 81 ++-- plugins/snacks.lua | 123 +++++ plugins/vim-tmux-navigator.lua | 3 + renovate.json | 32 -- scripts/extract-keybindings.lua | 78 ---- scripts/generate-docs.lua | 46 -- scripts/lib/docgen.lua | 228 ---------- scripts/update-readme.lua | 63 --- scripts/validate.sh | 99 ---- snippets/go.json | 306 ------------- snippets/package.json | 29 -- snippets/python.json | 30 -- snippets/terraform.json | 122 ----- snippets/tf.json | 11 - statusline.lua | 146 ++++++ 94 files changed, 841 insertions(+), 8377 deletions(-) delete mode 100644 Makefile delete mode 100644 README.md create mode 100644 autocmds.lua create mode 100644 config.lua delete mode 100644 docs/KEYBINDINGS.md delete mode 100644 docs/PLUGINS.md delete mode 100644 examples/.editorconfig delete mode 100644 examples/ruff-config.toml delete mode 100755 install.sh create mode 100644 keymaps.lua delete mode 100644 lazy-lock.json delete mode 100644 lua/config/keymaps.lua delete mode 100644 lua/config/lazy.lua delete mode 100644 lua/config/options.lua delete mode 100644 lua/plugins/aerial.lua delete mode 100644 lua/plugins/blink-cmp.lua delete mode 100644 lua/plugins/catppuccin.lua delete mode 100644 lua/plugins/cloak.lua delete mode 100644 lua/plugins/diffview.lua delete mode 100644 lua/plugins/elixir-tools.lua delete mode 100644 lua/plugins/emoji.lua delete mode 100644 lua/plugins/fidget.lua delete mode 100644 lua/plugins/gitlab.lua delete mode 100644 lua/plugins/gitsigns.lua delete mode 100644 lua/plugins/go-nvim.lua delete mode 100644 lua/plugins/harpoon.lua delete mode 100644 lua/plugins/kulala.lua delete mode 100644 lua/plugins/lsp_signature.lua delete mode 100644 lua/plugins/lspconfig.lua delete mode 100644 lua/plugins/lspkind.lua delete mode 100644 lua/plugins/lualine.lua delete mode 100644 lua/plugins/mason-lspconfig.lua delete mode 100644 lua/plugins/mason-tool-installer.lua delete mode 100644 lua/plugins/mason.lua delete mode 100644 lua/plugins/neotest.lua delete mode 100644 lua/plugins/nvim-autopairs.lua delete mode 100644 lua/plugins/nvim-colorizer.lua delete mode 100644 lua/plugins/nvim-coverage.lua delete mode 100644 lua/plugins/nvim-dap-go.lua delete mode 100644 lua/plugins/nvim-dap-python.lua delete mode 100644 lua/plugins/nvim-dap.lua delete mode 100644 lua/plugins/nvim-jqx.lua delete mode 100644 lua/plugins/nvim-lint.lua delete mode 100644 lua/plugins/nvim-man.lua delete mode 100644 lua/plugins/nvim-navic.lua delete mode 100644 lua/plugins/nvim-origami.lua delete mode 100644 lua/plugins/nvim-silicon.lua delete mode 100644 lua/plugins/nvim-surround.lua delete mode 100644 lua/plugins/nvim-treesitter-textobjects.lua delete mode 100644 lua/plugins/nvim-ufo.lua delete mode 100644 lua/plugins/nvim-web-devicons.lua delete mode 100644 lua/plugins/octo.lua delete mode 100644 lua/plugins/overseer.lua delete mode 100644 lua/plugins/package-info.lua delete mode 100644 lua/plugins/pr-description.lua delete mode 100644 lua/plugins/profile.lua delete mode 100644 lua/plugins/refactoring.lua delete mode 100644 lua/plugins/render-markdown.lua delete mode 100644 lua/plugins/scissors.lua delete mode 100644 lua/plugins/smart-splits.lua delete mode 100644 lua/plugins/smartcolumn-nvim.lua delete mode 100644 lua/plugins/snacks.lua delete mode 100644 lua/plugins/spectre.lua delete mode 100644 lua/plugins/terraform-local-modules.lua delete mode 100644 lua/plugins/terrareg.lua delete mode 100644 lua/plugins/todo-comments.lua delete mode 100644 lua/plugins/trouble.lua delete mode 100644 lua/plugins/undotree.lua delete mode 100644 lua/plugins/vim-dadbod-ui.lua delete mode 100644 lua/plugins/vim-table-mode.lua delete mode 100644 lua/plugins/which-key.lua delete mode 100644 lua/utils/git_repo.lua delete mode 100644 lua/utils/keymap_check.lua create mode 100644 nvim-pack-lock.json create mode 100644 options.lua rename {lua/plugins => plugins}/conform.lua (84%) create mode 100644 plugins/gitsigns.lua rename {lua/plugins => plugins}/nvim-treesitter.lua (66%) create mode 100644 plugins/snacks.lua create mode 100644 plugins/vim-tmux-navigator.lua delete mode 100644 renovate.json delete mode 100644 scripts/extract-keybindings.lua delete mode 100644 scripts/generate-docs.lua delete mode 100644 scripts/lib/docgen.lua delete mode 100644 scripts/update-readme.lua delete mode 100755 scripts/validate.sh delete mode 100644 snippets/go.json delete mode 100644 snippets/package.json delete mode 100644 snippets/python.json delete mode 100644 snippets/terraform.json delete mode 100644 snippets/tf.json create mode 100644 statusline.lua diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 47a4c6a..a77f761 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +--- repos: # General file formatting and linting - repo: https://github.com/pre-commit/pre-commit-hooks @@ -19,68 +20,9 @@ repos: - id: stylua-github args: [--config-path=stylua.toml] - # # Lua linting with Luacheck - # - repo: https://github.com/luarocks/luacheck - # rev: v1.2.0 - # hooks: - # - id: luacheck - # args: [--config=.luacheckrc] - # Conventional commit messages - repo: https://github.com/compilerla/conventional-pre-commit rev: v4.4.0 hooks: - id: conventional-pre-commit stages: [commit-msg] - - # Additional security checks - - repo: https://github.com/Yelp/detect-secrets - rev: v1.5.0 - hooks: - - id: detect-secrets - args: [--baseline, .secrets.baseline] - exclude: (package.lock.json|lazy-lock.json) - - # Neovim config validation - - repo: local - hooks: - - id: validate-nvim-config - name: Validate Neovim Config - entry: scripts/validate.sh - language: script - files: ^(lua/.*\.lua|init\.lua)$ - pass_filenames: false - - - id: check-lua-syntax - name: Check Lua Syntax - entry: bash -c 'for f in "$@"; do luac -p "$f" || exit 1; done' -- - language: system - files: \.lua$ - types: [lua] - - # Auto-documentation generation - - repo: local - hooks: - - id: generate-plugin-docs - name: Generate Plugin Documentation - entry: nvim -l scripts/generate-docs.lua - language: system - files: ^lua/plugins/.*\.lua$ - pass_filenames: false - stages: [post-commit] - - - id: update-readme-plugins - name: Update README with Plugin List - entry: nvim -l scripts/update-readme.lua - language: system - files: ^lua/plugins/.*\.lua$ - pass_filenames: false - stages: [post-commit] - - - id: extract-keybindings - name: Extract Keybindings Documentation - entry: nvim -l scripts/extract-keybindings.lua - language: system - files: ^lua/.*\.lua$ - pass_filenames: false - stages: [post-commit] diff --git a/Makefile b/Makefile deleted file mode 100644 index 3e9903d..0000000 --- a/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -.PHONY: help pr-description mr-description github gitlab \ - lint format format-check check validate clean docs update-readme \ - install test health - -# Default target -help: - @echo "Neovim Configuration - Available Commands" - @echo "" - @echo "PR/MR Description:" - @echo " make pr-description Generate GitHub PR description" - @echo " make mr-description Generate GitLab MR description" - @echo "" - @echo "Setup:" - @echo " make install Install dependencies and link config" - @echo "" - @echo "Code Quality:" - @echo " make lint Run luacheck linter" - @echo " make format Format Lua files with stylua" - @echo " make format-check Check Lua formatting (no write)" - @echo " make check Run lint + format check (no write)" - @echo " make validate Run full config validation" - @echo "" - @echo "Documentation:" - @echo " make docs Generate plugin and keybinding docs" - @echo " make update-readme Update README with plugin list" - @echo "" - @echo "Maintenance:" - @echo " make clean Remove cache and generated files" - @echo " make health Run Neovim health checks" - @echo " make test Test Neovim startup" - -#------------------------------------------------------------------------------ -# PR/MR Description -#------------------------------------------------------------------------------ - -pr-description: - @nvim --headless -c "lua print(require('pr-description').generate_description())" -c "qa" - -mr-description: - @nvim --headless -c "lua print(require('pr-description').generate_description({is_gitlab=true}))" -c "qa" - -# Aliases for backwards compatibility -github: pr-description -gitlab: mr-description - -#------------------------------------------------------------------------------ -# Setup -#------------------------------------------------------------------------------ - -# Run the interactive installer: installs dependencies, links this config to -# ~/.config/nvim, installs plugins, and sets up pre-commit hooks. -install: - @./install.sh - -#------------------------------------------------------------------------------ -# Code Quality -#------------------------------------------------------------------------------ - -lint: - @echo "Running luacheck..." - @luacheck lua/ scripts/ --config .luacheckrc - -format: - @echo "Formatting with stylua..." - @stylua --config-path stylua.toml lua/ scripts/ - -format-check: - @stylua --config-path stylua.toml --check lua/ scripts/ - -check: lint format-check - @echo "All checks passed!" - -validate: - @./scripts/validate.sh - -#------------------------------------------------------------------------------ -# Documentation -#------------------------------------------------------------------------------ - -docs: - @nvim -l scripts/generate-docs.lua - @nvim -l scripts/extract-keybindings.lua - -update-readme: - @nvim -l scripts/update-readme.lua - -#------------------------------------------------------------------------------ -# Maintenance -#------------------------------------------------------------------------------ - -clean: - @echo "Cleaning cache files..." - @rm -rf .aider.tags.cache.v4/ - @rm -rf .elixir-tools/ - @rm -f lazy-lock.json.bak - @echo "Done!" - -health: - @nvim --headless -c "checkhealth" -c "qa" - -test: - @echo "Testing Neovim startup..." - @nvim --headless -c "lua print('Startup OK - ' .. #require('lazy').plugins() .. ' plugins loaded')" -c "qa" diff --git a/README.md b/README.md deleted file mode 100644 index 4b4ec04..0000000 --- a/README.md +++ /dev/null @@ -1,273 +0,0 @@ -# ๐Ÿš€ Personal Neovim Configuration - -> A modern, feature-rich Neovim setup built for productivity and development workflow optimization. - -๐Ÿ“Š **Config Stats:** 54 plugins โ€ข 3 core configs โ€ข 9 file templates - -## โœจ Key Features - -### ๐Ÿ”ง Development Tools -- **Language Server Protocol (LSP)** - Full IDE-like features with auto-completion, diagnostics, and code actions -- **Debug Adapter Protocol (DAP)** - Integrated debugging support for multiple languages -- **Tree-sitter** - Advanced syntax highlighting and code understanding -- **Auto-formatting** - Code formatting with conform.nvim and language-specific tools -- **Linting** - Real-time code analysis and error detection - -### ๐ŸŽจ User Interface -- **Catppuccin Theme** - Beautiful, eye-friendly color scheme -- **Enhanced UI** - Custom statusline, bufferline, and floating windows -- **File Explorer** - Feature-rich nvim-tree with git integration -- **Fuzzy Finding** - Telescope for lightning-fast file and content search - -### โšก Productivity -- **Git Integration** - Full git workflow with lazygit, gitsigns, and fugitive -- **Terminal Integration** - Seamless terminal and tmux navigation -- **Session Management** - Project-aware sessions and workspace restoration -- **Snippet System** - Extensive snippet collection for faster coding - -### ๐Ÿงช Testing & Quality -- **Neotest** - Integrated test runner with language-specific adapters -- **Code Coverage** - Visual coverage indicators -- **Pre-commit Hooks** - Automated code quality checks and documentation generation - -## ๐Ÿ› ๏ธ Installation - -### Prerequisites -- **Neovim 0.10.0+** or later -- **Git** for plugin management -- **Node.js** for LSP servers -- **Python** and **pip** for additional tools -- **Ripgrep** for fast searching -- A [Nerd Font](https://www.nerdfonts.com/) for icons - -### Automated Setup (recommended) - -The [`install.sh`](install.sh) script bootstraps everything on a fresh machine. -It is interactive and supports **macOS**, **Arch Linux**, and **Debian/Ubuntu**. - -```bash -# Clone this configuration -git clone https://github.com/remoterabbit/nvim.git ~/.config/nvim -cd ~/.config/nvim - -# Run the installer (or: make install) -./install.sh -``` - -The installer will, with prompts along the way: - -1. Detect your operating system. -2. Install system dependencies (Neovim, ripgrep, fd, fzf, language toolchains, - LSP/formatter tools, a Nerd Font, etc.) via your package manager plus `pipx` - and `npm`. -3. Back up any existing `~/.config/nvim` to a timestamped directory. -4. Symlink this repository to `~/.config/nvim`. -5. Install plugins with lazy.nvim. -6. Install and register the pre-commit hooks. - -> **Note:** the installer uses `sudo` for system packages and for symlinks under -> `/usr/local/bin`. On unsupported systems, install the prerequisites manually -> and use the manual setup below. - -### Manual Setup - -```bash -# Backup existing config (optional) -mv ~/.config/nvim ~/.config/nvim.backup - -# Clone this configuration -git clone https://github.com/remoterabbit/nvim.git ~/.config/nvim - -# Start Neovim (plugins will auto-install) -nvim -``` - -## ๐Ÿ“‚ Structure - -``` -~/.config/nvim/ -โ”œโ”€โ”€ ๐Ÿ“ lua/ -โ”‚ โ”œโ”€โ”€ ๐Ÿ“ config/ # Core configuration -โ”‚ โ”‚ โ”œโ”€โ”€ options.lua # Neovim options -โ”‚ โ”‚ โ”œโ”€โ”€ keymaps.lua # Global keymaps -โ”‚ โ”‚ โ””โ”€โ”€ lazy.lua # Plugin manager setup -โ”‚ โ””โ”€โ”€ ๐Ÿ“ plugins/ # Plugin configurations -โ”œโ”€โ”€ ๐Ÿ“ docs/ # Auto-generated documentation -โ”‚ โ”œโ”€โ”€ KEYBINDINGS.md # Comprehensive keybinding reference -โ”‚ โ””โ”€โ”€ PLUGINS.md # Detailed plugin documentation -โ”œโ”€โ”€ ๐Ÿ“ scripts/ # Automation scripts -โ”œโ”€โ”€ ๐Ÿ“ templates/ # File templates -โ”œโ”€โ”€ init.lua # Entry point -โ””โ”€โ”€ stylua.toml # Code formatting config -``` - -## ๐Ÿ“š Documentation - -- **[Keybindings Reference](docs/KEYBINDINGS.md)** - Complete list of all keybindings organized by mode -- **[Plugin Documentation](docs/PLUGINS.md)** - Detailed information about each plugin -- **[Contributing Guidelines](.github/CONTRIBUTING.md)** - How to contribute to this configuration - -## โŒจ๏ธ Key Mappings - -### Leader Key: `` - -| Category | Key | Description | -|----------|-----|-------------| -| **Files** | `ff` | Find files | -| **Search** | `fg` | Live grep | -| **Git** | `gg` | LazyGit | -| **LSP** | `ca` | Code actions | -| **Debug** | `dt` | Toggle breakpoint | - -> ๐Ÿ’ก **Tip:** Press `` in normal mode to see all available keybindings with which-key. - -## ๐Ÿ”ง Customization - -### Adding New Plugins - -1. Create a new file in `lua/plugins/` -2. Follow the existing plugin structure -3. Run `:Lazy` to manage plugins - -### Language Support - -This configuration includes LSP support for: -- **Python** (Pyright) -- **JavaScript/TypeScript** (ts_ls) -- **Lua** (lua_ls) -- **Go** (gopls) -- **Rust** (rust-analyzer) -- **And many more...** - -## ๐Ÿค Contributing - -Found a bug or want to add a feature? Contributions are welcome! - -1. Fork the repository -2. Create a feature branch -3. Make your changes -4. Run pre-commit hooks: `pre-commit run --all-files` -5. Submit a pull request - -## ๐Ÿ“„ License - -This configuration is released into the public domain under the [Unlicense](LICENSE). - ---- - -โญ **Star this repo if you find it useful!** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -### Installed Plugins (59 total) - -#### ๐Ÿ”ง Language & LSP - -- [mason-org/mason-lspconfig.nvim](https://github.com/mason-org/mason-lspconfig.nvim) -- [mason-org/mason.nvim](https://github.com/mason-org/mason.nvim) -- [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) -- [onsails/lspkind.nvim](https://github.com/onsails/lspkind.nvim) -- [ray-x/lsp_signature.nvim](https://github.com/ray-x/lsp_signature.nvim) - -#### ๐ŸŽจ UI & Themes - -- [NvChad/nvim-colorizer.lua](https://github.com/NvChad/nvim-colorizer.lua) -- [catppuccin/nvim](https://github.com/catppuccin/nvim) -- [kristijanhusak/vim-dadbod-ui](https://github.com/kristijanhusak/vim-dadbod-ui) -- [nvim-lualine/lualine.nvim](https://github.com/nvim-lualine/lualine.nvim) - -#### ๐Ÿ” Navigation & Search - -- [mbbill/undotree](https://github.com/mbbill/undotree) -- [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) -- [nvim-treesitter/nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects) - -#### ๐Ÿ’ก Completion - -- [saghen/blink.cmp](https://github.com/saghen/blink.cmp) - -#### โœ๏ธ Editing - -- [folke/todo-comments.nvim](https://github.com/folke/todo-comments.nvim) -- [kylechui/nvim-surround](https://github.com/kylechui/nvim-surround) -- [windwp/nvim-autopairs](https://github.com/windwp/nvim-autopairs) - -#### ๐Ÿ“ Git Integration - -- [harrisoncramer/gitlab.nvim](https://github.com/harrisoncramer/gitlab.nvim) -- [lewis6991/gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim) - -#### ๐Ÿ› Testing & Debugging - -- [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) -- [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) -- [mfussenegger/nvim-dap-python](https://github.com/mfussenegger/nvim-dap-python) -- [nvim-neotest/neotest](https://github.com/nvim-neotest/neotest) - -#### ๐Ÿ”Œ Other Plugins - -- [MeanderingProgrammer/render-markdown.nvim](https://github.com/MeanderingProgrammer/render-markdown.nvim) -- [RRethy/vim-illuminate](https://github.com/RRethy/vim-illuminate) -- [SmiteshP/nvim-navic](https://github.com/SmiteshP/nvim-navic) -- [ThePrimeagen/harpoon](https://github.com/ThePrimeagen/harpoon) -- [ThePrimeagen/refactoring.nvim](https://github.com/ThePrimeagen/refactoring.nvim) -- [allaman/emoji.nvim](https://github.com/allaman/emoji.nvim) -- [andythigpen/nvim-coverage](https://github.com/andythigpen/nvim-coverage) -- [chrisgrieser/nvim-scissors](https://github.com/chrisgrieser/nvim-scissors) -- [dhruvasagar/vim-table-mode](https://github.com/dhruvasagar/vim-table-mode) -- [elixir-tools/elixir-tools.nvim](https://github.com/elixir-tools/elixir-tools.nvim) -- [folke/snacks.nvim](https://github.com/folke/snacks.nvim) -- [folke/trouble.nvim](https://github.com/folke/trouble.nvim) -- [folke/which-key.nvim](https://github.com/folke/which-key.nvim) -- [gennaro-tedesco/nvim-jqx](https://github.com/gennaro-tedesco/nvim-jqx) -- [j-hui/fidget.nvim](https://github.com/j-hui/fidget.nvim) -- [karb94/neoscroll.nvim](https://github.com/karb94/neoscroll.nvim) -- [kevinhwang91/nvim-ufo](https://github.com/kevinhwang91/nvim-ufo) -- [laytan/cloak.nvim](https://github.com/laytan/cloak.nvim) -- [m4xshen/smartcolumn.nvim](https://github.com/m4xshen/smartcolumn.nvim) -- [mfussenegger/nvim-lint](https://github.com/mfussenegger/nvim-lint) -- [michaelrommel/nvim-silicon](https://github.com/michaelrommel/nvim-silicon) -- [mistweaverco/kulala.nvim](https://github.com/mistweaverco/kulala.nvim) -- [mrjones2014/smart-splits.nvim](https://github.com/mrjones2014/smart-splits.nvim) -- [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- [nvim-pack/nvim-spectre](https://github.com/nvim-pack/nvim-spectre) -- [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) -- [paretje/nvim-man](https://github.com/paretje/nvim-man) -- [pwntester/octo.nvim](https://github.com/pwntester/octo.nvim) -- [ray-x/go.nvim](https://github.com/ray-x/go.nvim) -- [remoterabbit/pr-description.nvim](https://github.com/remoterabbit/pr-description.nvim) -- [sindrets/diffview.nvim](https://github.com/sindrets/diffview.nvim) -- [stevearc/aerial.nvim](https://github.com/stevearc/aerial.nvim) -- [stevearc/conform.nvim](https://github.com/stevearc/conform.nvim) -- [stevearc/overseer.nvim](https://github.com/stevearc/overseer.nvim) -- [stevearc/profile.nvim](https://github.com/stevearc/profile.nvim) -- [vuki656/package-info.nvim](https://github.com/vuki656/package-info.nvim) - - diff --git a/autocmds.lua b/autocmds.lua new file mode 100644 index 0000000..c64fe50 --- /dev/null +++ b/autocmds.lua @@ -0,0 +1,101 @@ +-- ============================================================================ +-- AUTOCMDS +-- ============================================================================ + +local augroup = vim.api.nvim_create_augroup("UserConfig", { clear = true }) + +-- Format on save (ONLY real file buffers, ONLY when efm is attached) +vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + pattern = { + "*.lua", + "*.py", + "*.go", + "*.js", + "*.jsx", + "*.ts", + "*.tsx", + "*.json", + "*.css", + "*.scss", + "*.html", + "*.sh", + "*.bash", + "*.zsh", + "*.c", + "*.cpp", + "*.h", + "*.hpp", + }, + callback = function(args) + -- avoid formatting non-file buffers (helps prevent weird write prompts) + if vim.bo[args.buf].buftype ~= "" then + return + end + if not vim.bo[args.buf].modifiable then + return + end + if vim.api.nvim_buf_get_name(args.buf) == "" then + return + end + + local has_efm = false + for _, c in ipairs(vim.lsp.get_clients({ bufnr = args.buf })) do + if c.name == "efm" then + has_efm = true + break + end + end + if not has_efm then + return + end + + pcall(vim.lsp.buf.format, { + bufnr = args.buf, + timeout_ms = 2000, + filter = function(c) + return c.name == "efm" + end, + }) + end, +}) + +-- highlight yanked text +vim.api.nvim_create_autocmd("TextYankPost", { + group = augroup, + callback = function() + vim.hl.on_yank() + end, +}) + +-- return to last cursor position +vim.api.nvim_create_autocmd("BufReadPost", { + group = augroup, + desc = "Restore last cursor position", + callback = function() + if vim.o.diff then -- except in diff mode + return + end + + local last_pos = vim.api.nvim_buf_get_mark(0, '"') -- {line, col} + local last_line = vim.api.nvim_buf_line_count(0) + + local row = last_pos[1] + if row < 1 or row > last_line then + return + end + + pcall(vim.api.nvim_win_set_cursor, 0, last_pos) + end, +}) + +-- wrap, linebreak and spellcheck on markdown and text files +vim.api.nvim_create_autocmd("FileType", { + group = augroup, + pattern = { "markdown", "text", "gitcommit" }, + callback = function() + vim.opt_local.wrap = true + vim.opt_local.linebreak = true + vim.opt_local.spell = true + end, +}) diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..d7a750c --- /dev/null +++ b/config.lua @@ -0,0 +1,80 @@ +-- ============================================================================ +-- OPTIONS +-- ============================================================================ +vim.opt.number = true -- line number +vim.opt.relativenumber = true -- relative line numbers +vim.opt.cursorline = true -- highlight current line +vim.opt.wrap = false -- do not wrap lines by default +vim.opt.scrolloff = 10 -- keep 10 lines above/below cursor +vim.opt.sidescrolloff = 10 -- keep 10 lines to left/right of cursor +vim.opt.tabstop = 2 -- tabwidth +vim.opt.shiftwidth = 2 -- indent width +vim.opt.softtabstop = 2 -- soft tab stop not tabs on tab/backspace +vim.opt.expandtab = true -- use spaces instead of tabs +vim.opt.smartindent = true -- smart auto-indent +vim.opt.autoindent = true -- copy indent from current line + +vim.opt.ignorecase = true -- case insensitive search +vim.opt.smartcase = true -- case sensitive if uppercase in string +vim.opt.hlsearch = true -- highlight search matches +vim.opt.incsearch = true -- show matches as you type + +vim.opt.signcolumn = "yes" -- always show a sign column +vim.opt.colorcolumn = "100" -- show a column at 100 position chars +vim.opt.showmatch = true -- highlights matching brackets +vim.opt.cmdheight = 1 -- single line command line +vim.opt.completeopt = "menuone,noinsert,noselect" -- completion options +vim.opt.showmode = false -- do not show the mode, instead have it in statusline +vim.opt.pumheight = 10 -- popup menu height +vim.opt.pumblend = 10 -- popup menu transparency +vim.opt.winblend = 0 -- floating window transparency +vim.opt.concealcursor = "" -- do not hide cursorline in markup +vim.opt.synmaxcol = 300 -- syntax highlighting limit +vim.opt.fillchars = { eob = " " } -- hide "~" on empty lines + +local undodir = vim.fn.expand("~/.vim/undodir") +if + vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent +then + vim.fn.mkdir(undodir, "p") +end + +vim.opt.backup = false -- do not create a backup file +vim.opt.writebackup = false -- do not write to a backup file +vim.opt.swapfile = false -- do not create a swapfile +vim.opt.undofile = true -- do create an undo file +vim.opt.undodir = undodir -- set the undo directory +vim.opt.updatetime = 300 -- faster completion +vim.opt.timeoutlen = 500 -- timeout duration +vim.opt.ttimeoutlen = 50 -- key code timeout +vim.opt.autoread = true -- auto-reload changes if outside of neovim +vim.opt.autowrite = false -- do not auto-save + +vim.opt.hidden = true -- allow hidden buffers +vim.opt.errorbells = false -- no error sounds +vim.opt.backspace = "indent,eol,start" -- better backspace behaviour +vim.opt.autochdir = false -- do not autochange directories +vim.opt.iskeyword:append("-") -- include - in words +vim.opt.path:append("**") -- include subdirs in search +vim.opt.selection = "inclusive" -- include last char in selection +vim.opt.mouse = "a" -- enable mouse support +vim.opt.clipboard:append("unnamedplus") -- use system clipboard +vim.opt.modifiable = true -- allow buffer modifications + +-- guicursor: configure cursor shape, blink timing, and highlight per editor mode +vim.opt.guicursor = + "n-v-c:block,i-ci-ve:block,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175" -- cursor blinking and settings + +-- Folding: requires treesitter available at runtime; safe fallback if not +vim.opt.foldmethod = "expr" -- use expression for folding +vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" -- use treesitter for folding +vim.opt.foldlevel = 99 -- start with all folds open + +vim.opt.splitbelow = true -- horizontal splits go below +vim.opt.splitright = true -- vertical splits go right + +vim.opt.wildmenu = true -- tab completion +vim.opt.wildmode = "longest:full,full" -- complete longest common match, full completion list, cycle through with Tab +vim.opt.diffopt:append("linematch:60") -- improve diff display +vim.opt.redrawtime = 10000 -- increase neovim redraw tolerance +vim.opt.maxmempattern = 20000 -- increase max memory diff --git a/docs/KEYBINDINGS.md b/docs/KEYBINDINGS.md deleted file mode 100644 index 88f4e77..0000000 --- a/docs/KEYBINDINGS.md +++ /dev/null @@ -1,164 +0,0 @@ -# Keybindings Reference - -_Auto-generated from configuration files. Do not edit manually._ - -## Insert Mode - -| Key | Description | Source | -|-----|-------------|--------| -| `ub` | Pick box-drawing char | [lua/config/keymaps.lua#L68](lua/config/keymaps.lua#L68) | -| `jk` | Exit insert mode with jk | [lua/config/keymaps.lua#L10](lua/config/keymaps.lua#L10) | - -## Normal Mode - -| Key | Description | Source | -|-----|-------------|--------| -| `` | Next reference | [lua/plugins/vim-illuminate.lua#L32](lua/plugins/vim-illuminate.lua#L32) | -| `` | Previous reference | [lua/plugins/vim-illuminate.lua#L35](lua/plugins/vim-illuminate.lua#L35) | -| `` | Harpoon next | [lua/plugins/harpoon.lua#L33](lua/plugins/harpoon.lua#L33) | -| `` | Harpoon prev | [lua/plugins/harpoon.lua#L30](lua/plugins/harpoon.lua#L30) | -| `+` | Increment number | [lua/config/keymaps.lua#L16](lua/config/keymaps.lua#L16) | -| `-` | Split window below | [lua/config/keymaps.lua#L24](lua/config/keymaps.lua#L24) | -| `` | New Tab | [lua/config/keymaps.lua#L30](lua/config/keymaps.lua#L30) | -| `[` | Previous Tab | [lua/config/keymaps.lua#L33](lua/config/keymaps.lua#L33) | -| `]` | Next Tab | [lua/config/keymaps.lua#L31](lua/config/keymaps.lua#L31) | -| `d` | Close Tab | [lua/config/keymaps.lua#L32](lua/config/keymaps.lua#L32) | -| `f` | First Tab | [lua/config/keymaps.lua#L29](lua/config/keymaps.lua#L29) | -| `l` | Last Tab | [lua/config/keymaps.lua#L28](lua/config/keymaps.lua#L28) | -| `=` | Decrement number | [lua/config/keymaps.lua#L17](lua/config/keymaps.lua#L17) | -| `Df` | Find DB buffer | [lua/plugins/vim-dadbod-ui.lua#L23](lua/plugins/vim-dadbod-ui.lua#L23) | -| `Dq` | Last query info | [lua/plugins/vim-dadbod-ui.lua#L25](lua/plugins/vim-dadbod-ui.lua#L25) | -| `Dr` | Rename DB buffer | [lua/plugins/vim-dadbod-ui.lua#L24](lua/plugins/vim-dadbod-ui.lua#L24) | -| `Du` | Toggle DBUI | [lua/plugins/vim-dadbod-ui.lua#L22](lua/plugins/vim-dadbod-ui.lua#L22) | -| `Gcb` | Coverage browser | [lua/plugins/go-nvim.lua#L57](lua/plugins/go-nvim.lua#L57) | -| `Gcc` | Toggle coverage | [lua/plugins/go-nvim.lua#L56](lua/plugins/go-nvim.lua#L56) | -| `Gch` | Test coverage | [lua/plugins/go-nvim.lua#L55](lua/plugins/go-nvim.lua#L55) | -| `Gse` | Add if err | [lua/plugins/go-nvim.lua#L54](lua/plugins/go-nvim.lua#L54) | -| `Gsf` | Fill struct | [lua/plugins/go-nvim.lua#L53](lua/plugins/go-nvim.lua#L53) | -| `Gsj` | Add JSON tags | [lua/plugins/go-nvim.lua#L50](lua/plugins/go-nvim.lua#L50) | -| `Gsr` | Remove tags | [lua/plugins/go-nvim.lua#L52](lua/plugins/go-nvim.lua#L52) | -| `Gsy` | Add YAML tags | [lua/plugins/go-nvim.lua#L51](lua/plugins/go-nvim.lua#L51) | -| `L` | Lazy | [lua/config/keymaps.lua#L4](lua/config/keymaps.lua#L4) | -| `Oa` | Quick action | [lua/plugins/overseer.lua#L237](lua/plugins/overseer.lua#L237) | -| `Ob` | Build task | [lua/plugins/overseer.lua#L238](lua/plugins/overseer.lua#L238) | -| `Oc` | Clear cache | [lua/plugins/overseer.lua#L239](lua/plugins/overseer.lua#L239) | -| `Or` | Run task | [lua/plugins/overseer.lua#L235](lua/plugins/overseer.lua#L235) | -| `Osf` | Run tfsec Terraform scan | [lua/plugins/overseer.lua#L243](lua/plugins/overseer.lua#L243) | -| `Ost` | Run trivy security scan | [lua/plugins/overseer.lua#L242](lua/plugins/overseer.lua#L242) | -| `Ot` | Toggle task list | [lua/plugins/overseer.lua#L236](lua/plugins/overseer.lua#L236) | -| `Ri` | Inspect REST request | [lua/plugins/kulala.lua#L21](lua/plugins/kulala.lua#L21) | -| `Rl` | Replay last REST request | [lua/plugins/kulala.lua#L15](lua/plugins/kulala.lua#L15) | -| `Rp` | Preview REST request | [lua/plugins/kulala.lua#L14](lua/plugins/kulala.lua#L14) | -| `Rr` | Run REST request | [lua/plugins/kulala.lua#L13](lua/plugins/kulala.lua#L13) | -| `coh` | Hide coverage | [lua/plugins/nvim-coverage.lua#L40](lua/plugins/nvim-coverage.lua#L40) | -| `col` | Load coverage | [lua/plugins/nvim-coverage.lua#L43](lua/plugins/nvim-coverage.lua#L43) | -| `cos` | Coverage summary | [lua/plugins/nvim-coverage.lua#L41](lua/plugins/nvim-coverage.lua#L41) | -| `cot` | Toggle coverage | [lua/plugins/nvim-coverage.lua#L42](lua/plugins/nvim-coverage.lua#L42) | -| `cov` | Show coverage | [lua/plugins/nvim-coverage.lua#L39](lua/plugins/nvim-coverage.lua#L39) | -| `cw` | Change word | [lua/config/keymaps.lua#L7](lua/config/keymaps.lua#L7) | -| `dO` | Step Out | [lua/plugins/nvim-dap.lua#L33](lua/plugins/nvim-dap.lua#L33) | -| `db` | Toggle Breakpoint | [lua/plugins/nvim-dap.lua#L29](lua/plugins/nvim-dap.lua#L29) | -| `dc` | Continue/Start Debugging | [lua/plugins/nvim-dap.lua#L30](lua/plugins/nvim-dap.lua#L30) | -| `dgl` | Debug last Go test | [lua/plugins/nvim-dap-go.lua#L20](lua/plugins/nvim-dap-go.lua#L20) | -| `dgt` | Debug Go test | [lua/plugins/nvim-dap-go.lua#L17](lua/plugins/nvim-dap-go.lua#L17) | -| `di` | Step Into | [lua/plugins/nvim-dap.lua#L31](lua/plugins/nvim-dap.lua#L31) | -| `dl` | Run Last | [lua/plugins/nvim-dap.lua#L35](lua/plugins/nvim-dap.lua#L35) | -| `do` | Step Over | [lua/plugins/nvim-dap.lua#L32](lua/plugins/nvim-dap.lua#L32) | -| `dpr` | Debug Python test method | [lua/plugins/nvim-dap-python.lua#L37](lua/plugins/nvim-dap-python.lua#L37) | -| `dr` | Toggle REPL | [lua/plugins/nvim-dap.lua#L34](lua/plugins/nvim-dap.lua#L34) | -| `dt` | Terminate | [lua/plugins/nvim-dap.lua#L36](lua/plugins/nvim-dap.lua#L36) | -| `du` | Toggle DAP UI | [lua/plugins/nvim-dap.lua#L37](lua/plugins/nvim-dap.lua#L37) | -| `fs` | Sesh tmux sessions | [lua/config/keymaps.lua#L137](lua/config/keymaps.lua#L137) | -| `gCo` | Checkout PR | [lua/plugins/octo.lua#L209](lua/plugins/octo.lua#L209) | -| `gD` | Close diffview | [lua/plugins/diffview.lua#L225](lua/plugins/diffview.lua#L225) | -| `gH` | Current file history | [lua/plugins/diffview.lua#L227](lua/plugins/diffview.lua#L227) | -| `gIl` | List Issues | [lua/plugins/octo.lua#L198](lua/plugins/octo.lua#L198) | -| `gIn` | New Issue | [lua/plugins/octo.lua#L199](lua/plugins/octo.lua#L199) | -| `gIo` | Open Issue | [lua/plugins/octo.lua#L200](lua/plugins/octo.lua#L200) | -| `gIs` | Search Issues | [lua/plugins/octo.lua#L201](lua/plugins/octo.lua#L201) | -| `gPD` | Create Draft PR/MR | [lua/plugins/octo.lua#L185](lua/plugins/octo.lua#L185) | -| `gPR` | Resume Review | [lua/plugins/gitlab.lua#L190](lua/plugins/gitlab.lua#L190) | -| `gPa` | Approve PR/MR | [lua/plugins/gitlab.lua#L198](lua/plugins/gitlab.lua#L198) | -| `gPb` | Open in Browser | [lua/plugins/gitlab.lua#L247](lua/plugins/gitlab.lua#L247) | -| `gPc` | Checkout PR/MR | [lua/plugins/gitlab.lua#L173](lua/plugins/gitlab.lua#L173) | -| `gPd` | Toggle Discussions | [lua/plugins/gitlab.lua#L242](lua/plugins/gitlab.lua#L242) | -| `gPf` | View PR/MR Files | [lua/plugins/gitlab.lua#L214](lua/plugins/gitlab.lua#L214) | -| `gPg` | Generate PR/MR Description | [lua/plugins/gitlab.lua#L117](lua/plugins/gitlab.lua#L117) | -| `gPl` | List PRs/MRs | [lua/plugins/gitlab.lua#L149](lua/plugins/gitlab.lua#L149) | -| `gPm` | Merge PR/MR | [lua/plugins/gitlab.lua#L223](lua/plugins/gitlab.lua#L223) | -| `gPn` | New PR/MR with Conventional Commits | [lua/plugins/octo.lua#L212](lua/plugins/octo.lua#L212) | -| `gPo` | Open Current PR/MR | [lua/plugins/gitlab.lua#L157](lua/plugins/gitlab.lua#L157) | -| `gPp` | View Pipeline | [lua/plugins/gitlab.lua#L232](lua/plugins/gitlab.lua#L232) | -| `gPr` | Create PR/MR with Generated Description | [lua/plugins/gitlab.lua#L84](lua/plugins/gitlab.lua#L84) | -| `gPs` | Search PRs/MRs | [lua/plugins/gitlab.lua#L165](lua/plugins/gitlab.lua#L165) | -| `gPt` | Create PR/MR with Template | [lua/plugins/octo.lua#L175](lua/plugins/octo.lua#L175) | -| `gPu` | Upload File | [lua/plugins/gitlab.lua#L237](lua/plugins/gitlab.lua#L237) | -| `gPv` | Start Review | [lua/plugins/gitlab.lua#L182](lua/plugins/gitlab.lua#L182) | -| `gPx` | Request Changes/Revoke | [lua/plugins/gitlab.lua#L206](lua/plugins/gitlab.lua#L206) | -| `gRb` | Open Repo in Browser | [lua/plugins/octo.lua#L206](lua/plugins/octo.lua#L206) | -| `gRf` | Fork Repo | [lua/plugins/octo.lua#L205](lua/plugins/octo.lua#L205) | -| `gRl` | List Repos | [lua/plugins/octo.lua#L204](lua/plugins/octo.lua#L204) | -| `gd` | Open diffview | [lua/plugins/diffview.lua#L224](lua/plugins/diffview.lua#L224) | -| `gh` | File history | [lua/plugins/diffview.lua#L226](lua/plugins/diffview.lua#L226) | -| `h1` | Harpoon 1 | [lua/plugins/harpoon.lua#L17](lua/plugins/harpoon.lua#L17) | -| `h2` | Harpoon 2 | [lua/plugins/harpoon.lua#L20](lua/plugins/harpoon.lua#L20) | -| `h3` | Harpoon 3 | [lua/plugins/harpoon.lua#L23](lua/plugins/harpoon.lua#L23) | -| `h4` | Harpoon 4 | [lua/plugins/harpoon.lua#L26](lua/plugins/harpoon.lua#L26) | -| `ha` | Add to harpoon | [lua/plugins/harpoon.lua#L10](lua/plugins/harpoon.lua#L10) | -| `he` | Harpoon menu | [lua/plugins/harpoon.lua#L13](lua/plugins/harpoon.lua#L13) | -| `jf` | JQ query | [lua/plugins/nvim-jqx.lua#L7](lua/plugins/nvim-jqx.lua#L7) | -| `jq` | JQ query list | [lua/plugins/nvim-jqx.lua#L6](lua/plugins/nvim-jqx.lua#L6) | -| `mR` | Toggle Markdown Rendering | [lua/plugins/render-markdown.lua#L145](lua/plugins/render-markdown.lua#L145) | -| `mt` | Toggle Table Mode | [lua/plugins/vim-table-mode.lua#L28](lua/plugins/vim-table-mode.lua#L28) | -| `nT` | Toggle dependency versions | [lua/plugins/package-info.lua#L38](lua/plugins/package-info.lua#L38) | -| `nc` | Hide dependency versions | [lua/plugins/package-info.lua#L32](lua/plugins/package-info.lua#L32) | -| `nd` | Delete dependency on line | [lua/plugins/package-info.lua#L50](lua/plugins/package-info.lua#L50) | -| `ni` | Install new dependency | [lua/plugins/package-info.lua#L56](lua/plugins/package-info.lua#L56) | -| `np` | Change dependency version | [lua/plugins/package-info.lua#L62](lua/plugins/package-info.lua#L62) | -| `ns` | Show dependency versions | [lua/plugins/package-info.lua#L26](lua/plugins/package-info.lua#L26) | -| `nu` | Update dependency on line | [lua/plugins/package-info.lua#L44](lua/plugins/package-info.lua#L44) | -| `oA` | Toggle Aerial Navigation | [lua/plugins/aerial.lua#L141](lua/plugins/aerial.lua#L141) | -| `oa` | Toggle Aerial | [lua/plugins/aerial.lua#L140](lua/plugins/aerial.lua#L140) | -| `pm` | Mason | [lua/config/keymaps.lua#L5](lua/config/keymaps.lua#L5) | -| `pp` | Toggle profiling | [lua/plugins/profile.lua#L30](lua/plugins/profile.lua#L30) | -| `rn` | LSP Rename | [lua/plugins/refactoring.lua#L108](lua/plugins/refactoring.lua#L108) | -| `sc` | Screenshot code | [lua/plugins/nvim-silicon.lua#L27](lua/plugins/nvim-silicon.lua#L27) | -| `se` | [S]earch [E]moji | [lua/plugins/emoji.lua#L16](lua/plugins/emoji.lua#L16) | -| `tF` | Run tests in file | [lua/plugins/neotest.lua#L148](lua/plugins/neotest.lua#L148) | -| `tO` | Toggle test output panel | [lua/plugins/neotest.lua#L160](lua/plugins/neotest.lua#L160) | -| `ta` | Run all tests | [lua/plugins/neotest.lua#L151](lua/plugins/neotest.lua#L151) | -| `td` | Debug nearest test | [lua/plugins/neotest.lua#L166](lua/plugins/neotest.lua#L166) | -| `tm` | Insert Module Template | [lua/plugins/terraform-local-modules.lua#L238](lua/plugins/terraform-local-modules.lua#L238) | -| `tn` | Run nearest test | [lua/plugins/neotest.lua#L145](lua/plugins/neotest.lua#L145) | -| `to` | Show test output | [lua/plugins/neotest.lua#L157](lua/plugins/neotest.lua#L157) | -| `ts` | Toggle test summary | [lua/plugins/neotest.lua#L154](lua/plugins/neotest.lua#L154) | -| `tw` | Watch tests | [lua/plugins/neotest.lua#L163](lua/plugins/neotest.lua#L163) | -| `ub` | Pick box-drawing char | [lua/config/keymaps.lua#L68](lua/config/keymaps.lua#L68) | -| `w-` | Split window below | [lua/config/keymaps.lua#L22](lua/config/keymaps.lua#L22) | -| `wd` | Delete window | [lua/config/keymaps.lua#L21](lua/config/keymaps.lua#L21) | -| `ww` | Other window | [lua/config/keymaps.lua#L20](lua/config/keymaps.lua#L20) | -| `w\|` | Split window right | [lua/config/keymaps.lua#L23](lua/config/keymaps.lua#L23) | -| `xL` | Location List (Trouble) | [lua/plugins/trouble.lua#L73](lua/plugins/trouble.lua#L73) | -| `xQ` | Quickfix List (Trouble) | [lua/plugins/trouble.lua#L74](lua/plugins/trouble.lua#L74) | -| `xX` | Buffer Diagnostics (Trouble) | [lua/plugins/trouble.lua#L60](lua/plugins/trouble.lua#L60) | -| `xl` | LSP Definitions / references / ... (Trouble) | [lua/plugins/trouble.lua#L67](lua/plugins/trouble.lua#L67) | -| `xr` | Run linting | [lua/plugins/nvim-lint.lua#L38](lua/plugins/nvim-lint.lua#L38) | -| `xs` | Symbols (Trouble) | [lua/plugins/trouble.lua#L66](lua/plugins/trouble.lua#L66) | -| `xx` | Diagnostics (Trouble) | [lua/plugins/trouble.lua#L59](lua/plugins/trouble.lua#L59) | -| `\|` | Split window right | [lua/config/keymaps.lua#L25](lua/config/keymaps.lua#L25) | -| `K` | Peek fold or hover | [lua/plugins/nvim-ufo.lua#L48](lua/plugins/nvim-ufo.lua#L48) | -| `[S` | Previous symbol | [lua/plugins/aerial.lua#L142](lua/plugins/aerial.lua#L142) | -| `]S` | Next symbol | [lua/plugins/aerial.lua#L143](lua/plugins/aerial.lua#L143) | -| `gT` | Previous Tab | [lua/config/keymaps.lua#L37](lua/config/keymaps.lua#L37) | -| `gt` | Next Tab | [lua/config/keymaps.lua#L36](lua/config/keymaps.lua#L36) | -| `zM` | Close all folds | [lua/plugins/nvim-ufo.lua#L45](lua/plugins/nvim-ufo.lua#L45) | -| `zR` | Open all folds | [lua/plugins/nvim-ufo.lua#L44](lua/plugins/nvim-ufo.lua#L44) | -| `zm` | Close folds with | [lua/plugins/nvim-ufo.lua#L47](lua/plugins/nvim-ufo.lua#L47) | -| `zr` | Open folds except kinds | [lua/plugins/nvim-ufo.lua#L46](lua/plugins/nvim-ufo.lua#L46) | - -## Visual Mode - -| Key | Description | Source | -|-----|-------------|--------| -| `sc` | Screenshot code | [lua/plugins/nvim-silicon.lua#L26](lua/plugins/nvim-silicon.lua#L26) | -| `ub` | Box-wrap selection | [lua/config/keymaps.lua#L134](lua/config/keymaps.lua#L134) | diff --git a/docs/PLUGINS.md b/docs/PLUGINS.md deleted file mode 100644 index e797b56..0000000 --- a/docs/PLUGINS.md +++ /dev/null @@ -1,403 +0,0 @@ -# Neovim Plugins Documentation - -This file is auto-generated by pre-commit hooks. Do not edit manually. - -## Aerial - -- **Repository:** https://github.com/stevearc/aerial.nvim -- **Dependencies:** - - [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Blink Cmp - -- **Repository:** https://github.com/saghen/blink.cmp -- **Dependencies:** - - [allaman/emoji.nvim](https://github.com/allaman/emoji.nvim) - - [rafamadriz/friendly-snippets](https://github.com/rafamadriz/friendly-snippets) - - [saghen/blink.compat](https://github.com/saghen/blink.compat) -- **Configured:** Basic setup - -## Catppuccin - -- **Repository:** https://github.com/catppuccin/nvim -- **Configured:** Yes - -## Cloak - -- **Repository:** https://github.com/laytan/cloak.nvim -- **Configured:** Yes - -## Conform - -- **Repository:** https://github.com/stevearc/conform.nvim -- **Configured:** Yes - -## Diffview - -- **Repository:** https://github.com/sindrets/diffview.nvim -- **Configured:** Yes -- **Has keybindings:** Yes - -## Elixir Tools - -- **Repository:** https://github.com/elixir-tools/elixir-tools.nvim -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Yes - -## Emoji - -- **Repository:** https://github.com/allaman/emoji.nvim -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - - [nvim-telescope/telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) - - [saghen/blink.cmp](https://github.com/saghen/blink.cmp) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Fidget - -- **Repository:** https://github.com/j-hui/fidget.nvim -- **Configured:** Yes - -## Gitlab - -- **Repository:** https://github.com/harrisoncramer/gitlab.nvim -- **Dependencies:** - - [MunifTanjim/nui.nvim](https://github.com/MunifTanjim/nui.nvim) - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - - [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) - - [sindrets/diffview.nvim](https://github.com/sindrets/diffview.nvim) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Gitsigns - -- **Repository:** https://github.com/lewis6991/gitsigns.nvim -- **Configured:** Yes - -## Go Nvim - -- **Repository:** https://github.com/ray-x/go.nvim -- **Dependencies:** - - [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) - - [ray-x/guihua.lua](https://github.com/ray-x/guihua.lua) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Harpoon - -- **Repository:** https://github.com/ThePrimeagen/harpoon -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Kulala - -- **Repository:** https://github.com/mistweaverco/kulala.nvim -- **Configured:** Yes -- **Has keybindings:** Yes - -## Lsp_Signature - -- **Repository:** https://github.com/ray-x/lsp_signature.nvim -- **Configured:** Yes - -## Lspconfig - -- **Repository:** https://github.com/neovim/nvim-lspconfig -- **Dependencies:** - - [saghen/blink.cmp](https://github.com/saghen/blink.cmp) -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Lspkind - -- **Repository:** https://github.com/onsails/lspkind.nvim -- **Configured:** Basic setup - -## Lualine - -- **Repository:** https://github.com/nvim-lualine/lualine.nvim -- **Configured:** Yes - -## Mason Lspconfig - -- **Repository:** https://github.com/mason-org/mason-lspconfig.nvim -- **Dependencies:** - - [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) -- **Configured:** Basic setup - -## Mason - -- **Repository:** https://github.com/mason-org/mason.nvim -- **Configured:** Yes - -## Neoscroll - -- **Repository:** https://github.com/karb94/neoscroll.nvim -- **Configured:** Yes - -## Neotest - -- **Repository:** https://github.com/nvim-neotest/neotest -- **Dependencies:** - - [jfpedroza/neotest-elixir](https://github.com/jfpedroza/neotest-elixir) - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - - [nvim-neotest/neotest-go](https://github.com/nvim-neotest/neotest-go) - - [nvim-neotest/neotest-jest](https://github.com/nvim-neotest/neotest-jest) - - [nvim-neotest/neotest-python](https://github.com/nvim-neotest/neotest-python) - - [nvim-neotest/nvim-nio](https://github.com/nvim-neotest/nvim-nio) - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) - - [rouge8/neotest-rust](https://github.com/rouge8/neotest-rust) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Autopairs - -- **Repository:** https://github.com/windwp/nvim-autopairs -- **Dependencies:** - - [saghen/blink.cmp](https://github.com/saghen/blink.cmp) -- **Configured:** Yes - -## Nvim Colorizer - -- **Repository:** https://github.com/NvChad/nvim-colorizer.lua -- **Configured:** Basic setup - -## Nvim Coverage - -- **Repository:** https://github.com/andythigpen/nvim-coverage -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Dap Go - -- **Repository:** https://github.com/leoluz/nvim-dap-go -- **Dependencies:** - - [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) - - [rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Dap Python - -- **Repository:** https://github.com/mfussenegger/nvim-dap-python -- **Dependencies:** - - [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) - - [rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Dap - -- **Repository:** https://github.com/mfussenegger/nvim-dap -- **Dependencies:** - - [nvim-neotest/nvim-nio](https://github.com/nvim-neotest/nvim-nio) - - [rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Jqx - -- **Repository:** https://github.com/gennaro-tedesco/nvim-jqx -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Nvim Lint - -- **Repository:** https://github.com/mfussenegger/nvim-lint -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Nvim Man - -- **Repository:** https://github.com/paretje/nvim-man -- **Configured:** Basic setup - -## Nvim Navic - -- **Repository:** https://github.com/SmiteshP/nvim-navic -- **Configured:** Yes - -## Nvim Silicon - -- **Repository:** https://github.com/michaelrommel/nvim-silicon -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Surround - -- **Repository:** https://github.com/kylechui/nvim-surround -- **Configured:** Basic setup - -## Nvim Treesitter Textobjects - -- **Repository:** https://github.com/nvim-treesitter/nvim-treesitter-textobjects -- **Dependencies:** - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Treesitter - -- **Repository:** https://github.com/nvim-treesitter/nvim-treesitter -- **Configured:** Yes - -## Nvim Ufo - -- **Repository:** https://github.com/kevinhwang91/nvim-ufo -- **Dependencies:** - - [kevinhwang91/promise-async](https://github.com/kevinhwang91/promise-async) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Nvim Web Devicons - -- **Repository:** https://github.com/nvim-tree/nvim-web-devicons -- **Configured:** Basic setup - -## Octo - -- **Repository:** https://github.com/pwntester/octo.nvim -- **Dependencies:** - - [folke/snacks.nvim](https://github.com/folke/snacks.nvim) - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - - [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Overseer - -- **Repository:** https://github.com/stevearc/overseer.nvim -- **Configured:** Yes -- **Has keybindings:** Yes - -## Package Info - -- **Repository:** https://github.com/vuki656/package-info.nvim -- **Dependencies:** - - [MunifTanjim/nui.nvim](https://github.com/MunifTanjim/nui.nvim) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Pr Description - -- **Repository:** https://github.com/remoterabbit/pr-description.nvim -- **Configured:** Basic setup - -## Profile - -- **Repository:** https://github.com/stevearc/profile.nvim -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Refactoring - -- **Repository:** https://github.com/ThePrimeagen/refactoring.nvim -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Render Markdown - -- **Repository:** https://github.com/MeanderingProgrammer/render-markdown.nvim -- **Dependencies:** - - [echasnovski/mini.nvim](https://github.com/echasnovski/mini.nvim) - - [nvim-treesitter/nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) -- **Configured:** Yes -- **Has keybindings:** Yes - -## Scissors - -- **Repository:** https://github.com/chrisgrieser/nvim-scissors -- **Dependencies:** - - [folke/snacks.nvim](https://github.com/folke/snacks.nvim) -- **Configured:** Basic setup - -## Smart Splits - -- **Repository:** https://github.com/mrjones2014/smart-splits.nvim -- **Configured:** Yes -- **Has keybindings:** Yes - -## Smartcolumn Nvim - -- **Repository:** https://github.com/m4xshen/smartcolumn.nvim -- **Configured:** Basic setup - -## Snacks - -- **Repository:** https://github.com/folke/snacks.nvim -- **Configured:** Basic setup - -## Spectre - -- **Repository:** https://github.com/nvim-pack/nvim-spectre -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Basic setup - -## Terraform Local Modules - -- **Repository:** https://github.com/nvim-lua/plenary.nvim -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Terrareg - -- **Repository:** https://github.com/nvim-lua/plenary.nvim -- **Dependencies:** - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Yes - -## Todo Comments - -- **Repository:** https://github.com/folke/todo-comments.nvim -- **Dependencies:** - - [folke/snacks.nvim](https://github.com/folke/snacks.nvim) - - [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) -- **Configured:** Basic setup - -## Trouble - -- **Repository:** https://github.com/folke/trouble.nvim -- **Configured:** Yes -- **Has keybindings:** Yes - -## Undotree - -- **Repository:** https://github.com/mbbill/undotree -- **Configured:** Basic setup - -## Vim Dadbod Ui - -- **Repository:** https://github.com/kristijanhusak/vim-dadbod-ui -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Vim Illuminate - -- **Repository:** https://github.com/RRethy/vim-illuminate -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Vim Table Mode - -- **Repository:** https://github.com/dhruvasagar/vim-table-mode -- **Configured:** Basic setup -- **Has keybindings:** Yes - -## Which Key - -- **Repository:** https://github.com/folke/which-key.nvim -- **Configured:** Basic setup diff --git a/examples/.editorconfig b/examples/.editorconfig deleted file mode 100644 index 8df51ef..0000000 --- a/examples/.editorconfig +++ /dev/null @@ -1,54 +0,0 @@ -# Example .editorconfig for DevOps projects -root = true - -# Default settings for all files -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_style = space -indent_size = 2 - -# Python files -[*.py] -indent_size = 4 -max_line_length = 88 - -# Go files -[*.go] -indent_style = tab -indent_size = 4 - -# Terraform files -[*.tf] -indent_size = 2 - -# YAML files (Kubernetes, GitHub Actions, etc.) -[*.{yml,yaml}] -indent_size = 2 - -# JSON files -[*.json] -indent_size = 2 - -# Shell scripts -[*.{sh,bash}] -indent_size = 2 - -# Makefile -[Makefile] -indent_style = tab - -# Markdown -[*.md] -trim_trailing_whitespace = false -max_line_length = 80 - -# Docker files -[Dockerfile*] -indent_size = 4 - -# Configuration files -[*.{toml,ini}] -indent_size = 4 diff --git a/examples/ruff-config.toml b/examples/ruff-config.toml deleted file mode 100644 index b0120e9..0000000 --- a/examples/ruff-config.toml +++ /dev/null @@ -1,33 +0,0 @@ -# Example pyproject.toml ruff configuration for your projects -[tool.ruff] -# Same as Black. -line-length = 88 -indent-width = 4 - -# Assume Python 3.8+. -target-version = "py38" - -[tool.ruff.lint] -# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. -select = ["E4", "E7", "E9", "F", "I", "UP", "B", "SIM", "C90"] -ignore = [] - -# Allow fix for all enabled rules (when `--fix`) is provided. -fixable = ["ALL"] -unfixable = [] - -# Allow unused variables when underscore-prefixed. -dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" - -[tool.ruff.format] -# Like Black, use double quotes for strings. -quote-style = "double" - -# Like Black, indent with spaces, rather than tabs. -indent-style = "space" - -# Like Black, respect magic trailing commas. -skip-magic-trailing-comma = false - -# Like Black, automatically detect the appropriate line ending. -line-ending = "auto" diff --git a/init.lua b/init.lua index 33c7223..9578488 100644 --- a/init.lua +++ b/init.lua @@ -1,10 +1,80 @@ --- set leader key to space (must be before lazy setup) -vim.g.mapleader = " " -vim.g.maplocalleader = "," +--- Color and Theme +vim.opt.termguicolors = true +vim.cmd.colorscheme("catppuccin") -require("config.options") -require("config.lazy") -require("config.keymaps") +--- Global options +vim.g.netrw_banner = 0 +vim.g.mapleader = " " -- space for leader +vim.g.maplocalleader = " " -- space for localleader +-- Disable unused language providers (avoids checkhealth noise + startup cost) +vim.g.loaded_python3_provider = 0 +vim.g.loaded_perl_provider = 0 +vim.g.loaded_ruby_provider = 0 +vim.g.loaded_node_provider = 0 --- Setup keymap checking utilities (run :CheckKeymaps to find conflicts) -require("utils.keymap_check").setup() +--- Load +require("autocmds") +require("keymaps") +require("options") +require("statusline") + +--- Plugins +--- Each file in the plugins/ dir returns a spec table: +--- return { +--- src = "https://github.com/owner/repo", -- required +--- version = "v1.2.3" or "main", -- optional (tag/branch/commit) +--- config = function() ... end, -- optional, runs after install/load +--- } +local plugins_dir = vim.fn.stdpath("config") .. "/plugins" +local specs = {} +local configs = {} + +for name, type_ in vim.fs.dir(plugins_dir) do + if type_ == "file" and name:match("%.lua$") then + local ok, plugin = pcall(dofile, plugins_dir .. "/" .. name) + if not ok then + vim.notify( + ("Plugin spec '%s' failed to load (error while executing the file):\n%s"):format(name, tostring(plugin)), + vim.log.levels.ERROR + ) + elseif type(plugin) ~= "table" then + vim.notify( + ("Plugin spec '%s' did not return a table (got %s). Did you forget `return { ... }`?"):format( + name, + type(plugin) + ), + vim.log.levels.ERROR + ) + elseif not plugin.src then + vim.notify(("Plugin spec '%s' is missing the required `src` field."):format(name), vim.log.levels.ERROR) + else + table.insert(specs, { src = plugin.src, version = plugin.version }) + if type(plugin.config) == "function" then + table.insert(configs, { name = name, src = plugin.src, fn = plugin.config }) + elseif plugin.config ~= nil then + vim.notify( + ("Plugin spec '%s' has a `config` that is not a function (got %s); skipping it."):format( + name, + type(plugin.config) + ), + vim.log.levels.WARN + ) + end + end + end +end + +local ok_add, add_err = pcall(vim.pack.add, specs) +if not ok_add then + vim.notify("vim.pack.add failed:\n" .. tostring(add_err), vim.log.levels.ERROR) +end + +for _, config in ipairs(configs) do + local ok, err = pcall(config.fn) + if not ok then + vim.notify( + ("Plugin config error in '%s' (%s):\n%s"):format(config.name, config.src, tostring(err)), + vim.log.levels.ERROR + ) + end +end diff --git a/install.sh b/install.sh deleted file mode 100755 index 1b3af41..0000000 --- a/install.sh +++ /dev/null @@ -1,420 +0,0 @@ -#!/usr/bin/env bash -# -# install.sh - Neovim configuration installer -# -# Interactive bootstrap script that sets up this Neovim configuration on a -# fresh machine. It will, in order: -# 1. Detect the operating system (macOS, Arch, or Debian/Ubuntu). -# 2. Optionally install all system dependencies (Neovim, git, ripgrep, fd, -# fzf, language toolchains, LSP/formatter tools, a Nerd Font, etc.) using -# the platform package manager (brew / pacman / apt) plus pipx and npm. -# 3. Back up any existing ~/.config/nvim to a timestamped directory. -# 4. Symlink this repository to ~/.config/nvim. -# 5. Optionally install plugins via lazy.nvim. -# 6. Install and register pre-commit hooks. -# -# Usage: -# ./install.sh # or: make install -# -# Notes: -# - The script is interactive and will prompt before installing -# dependencies and plugins. -# - It uses sudo for system package installation and for creating -# symlinks under /usr/local/bin. -# - Supported OSes: macOS, Arch Linux, Debian/Ubuntu. Other systems must -# install dependencies manually. - -set -e - -NVIM_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/nvim" -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } -log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } -log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } -log_error() { echo -e "${RED}[ERROR]${NC} $1"; } - -detect_os() { - if [[ "$OSTYPE" == "darwin"* ]]; then - echo "macos" - elif [[ -f /etc/arch-release ]]; then - echo "arch" - elif [[ -f /etc/debian_version ]]; then - echo "debian" - else - echo "unknown" - fi -} - -check_command() { - if command -v "$1" &> /dev/null; then - log_success "$1 is installed" - return 0 - else - log_warning "$1 is not installed" - return 1 - fi -} - -install_dependencies() { - local os="$1" - log_info "Installing dependencies for $os..." - - case "$os" in - arch) - log_info "Updating system packages..." - sudo pacman -Syu --noconfirm - - log_info "Installing required packages..." - - # Check if any nodejs variant is installed - if ! pacman -Qq | grep -q '^nodejs'; then - NODEJS_PKG="nodejs npm" - else - log_info "Node.js already installed, skipping..." - NODEJS_PKG="" - fi - - # Check if tfenv is installed (skip terraform if so) - if pacman -Qq tfenv &> /dev/null; then - log_info "tfenv detected, skipping terraform package..." - TERRAFORM_PKG="" - else - TERRAFORM_PKG="terraform" - fi - - sudo pacman -S --needed --noconfirm \ - neovim \ - git \ - base-devel \ - curl \ - wget \ - ripgrep \ - fd \ - fzf \ - $NODEJS_PKG \ - python \ - python-pip \ - luarocks \ - tree-sitter \ - unzip \ - gzip \ - tar \ - jq \ - shellcheck \ - shfmt \ - stylua \ - go \ - rust \ - elixir \ - erlang \ - $TERRAFORM_PKG - - log_info "Installing GitHub CLI, GitLab CLI, and dev tools..." - sudo pacman -S --needed --noconfirm \ - github-cli \ - rebar3 \ - silicon \ - yamllint \ - golangci-lint - - if command -v yay &> /dev/null || command -v paru &> /dev/null; then - local aur_helper="yay" - command -v paru &> /dev/null && aur_helper="paru" - - log_info "Installing AUR packages..." - $aur_helper -S --needed --noconfirm \ - lazygit \ - glab \ - hadolint-bin \ - tfenv \ - ttf-nerd-fonts-symbols-mono || log_warning "Some AUR packages may have failed" - else - log_warning "No AUR helper found. Install lazygit, glab, hadolint, tfenv, and nerd fonts manually." - fi - ;; - - debian) - log_info "Updating system packages..." - sudo apt update - - log_info "Installing required packages..." - sudo apt install -y \ - git \ - build-essential \ - curl \ - wget \ - ripgrep \ - fd-find \ - fzf \ - nodejs \ - npm \ - python3 \ - python3-pip \ - python3-venv \ - luarocks \ - unzip \ - gzip \ - tar \ - jq \ - shellcheck \ - golang-go \ - elixir \ - erlang \ - yamllint - - # On Debian/Ubuntu the fd binary is installed as "fdfind"; link it to "fd" - if command -v fdfind &> /dev/null && ! command -v fd &> /dev/null; then - log_info "Linking fdfind to fd..." - sudo ln -sf "$(command -v fdfind)" /usr/local/bin/fd - fi - - log_info "Installing/upgrading Neovim..." - if ! check_command nvim || [[ $(nvim --version | head -n1 | grep -oP 'v\K[0-9]+\.[0-9]+' | awk '{print ($1 >= 0.10)}') != "1" ]]; then - log_info "Installing Neovim from GitHub releases..." - NVIM_VERSION="stable" - NVIM_TARBALL="nvim-linux-x86_64.tar.gz" - curl -LO "https://github.com/neovim/neovim/releases/download/$NVIM_VERSION/$NVIM_TARBALL" - sudo tar -C /opt -xzf "$NVIM_TARBALL" - sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim - rm "$NVIM_TARBALL" - fi - - log_info "Installing lazygit..." - LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*') - curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" - tar xf lazygit.tar.gz lazygit - sudo install lazygit /usr/local/bin - rm lazygit lazygit.tar.gz - - log_info "Installing GitHub CLI..." - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg - sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null - sudo apt update - sudo apt install -y gh - - log_info "Installing GitLab CLI..." - GLAB_VERSION=$(curl -s "https://api.github.com/repos/gitlab-org/cli/releases/latest" | grep -Po '"tag_name": "v\K[^"]*') - curl -Lo glab.tar.gz "https://github.com/gitlab-org/cli/releases/latest/download/glab_${GLAB_VERSION}_Linux_x86_64.tar.gz" - tar xf glab.tar.gz bin/glab - sudo install bin/glab /usr/local/bin - rm -rf glab.tar.gz bin - - log_info "Installing rebar3 (Erlang/Elixir build tool)..." - curl -Lo rebar3 https://s3.amazonaws.com/rebar3/rebar3 - chmod +x rebar3 - sudo mv rebar3 /usr/local/bin/ - - log_info "Installing tfenv..." - git clone --depth=1 https://github.com/tfutils/tfenv.git ~/.tfenv - sudo ln -sf ~/.tfenv/bin/* /usr/local/bin - - log_info "Installing Rust..." - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - source "$HOME/.cargo/env" - - log_info "Installing additional tools via cargo and go..." - cargo install stylua silicon - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - go install mvdan.cc/sh/v3/cmd/shfmt@latest - - if ! command -v tfenv &> /dev/null; then - log_info "Installing Terraform..." - wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg - echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list - sudo apt update && sudo apt install -y terraform - else - log_info "tfenv detected, skipping terraform installation..." - fi - - log_info "Installing Terraform tools..." - curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash - curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash - - log_info "Installing Hadolint..." - wget -O /tmp/hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64 - chmod +x /tmp/hadolint - sudo mv /tmp/hadolint /usr/local/bin/hadolint - - log_info "Installing yamlfmt and other formatters..." - go install github.com/google/yamlfmt/cmd/yamlfmt@latest - npm install -g markdownlint-cli jsonlint - - log_warning "Install a Nerd Font manually from https://www.nerdfonts.com/" - ;; - - macos) - if ! check_command brew; then - log_info "Installing Homebrew..." - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - fi - - log_info "Installing required packages..." - - # Build package list, install tfenv instead of terraform - PACKAGES="neovim git ripgrep fd fzf node python3 luarocks tree-sitter lazygit gh glab rebar3 jq shellcheck shfmt stylua go rust elixir erlang silicon hadolint tflint tfsec yamllint golangci-lint yamlfmt markdownlint-cli jsonlint tfenv" - - brew install $PACKAGES - - log_info "Installing Nerd Font..." - brew install --cask font-jetbrains-mono-nerd-font || log_warning "Nerd font installation failed" - ;; - - *) - log_error "Unsupported OS. Please install dependencies manually." - exit 1 - ;; - esac - - log_info "Installing Python packages..." - local os=$(detect_os) - - # Ensure pipx is installed - if ! command -v pipx &> /dev/null; then - log_info "Installing pipx..." - case "$os" in - arch) - sudo pacman -S --needed --noconfirm python-pipx - ;; - debian) - sudo apt install -y python3-pipx - ;; - macos) - brew install pipx - ;; - esac - pipx ensurepath - fi - - # Install libraries needed by neovim - if [[ "$os" == "arch" ]]; then - sudo pacman -S --needed --noconfirm python-pynvim python-debugpy - else - python3 -m pip install --user --upgrade pynvim debugpy - fi - - # Install CLI tools via pipx on all platforms - log_info "Installing Python CLI tools via pipx..." - pipx install ruff || pipx upgrade ruff || log_warning "ruff installation failed" - pipx install mypy || pipx upgrade mypy || log_warning "mypy installation failed" - pipx install pytest || pipx upgrade pytest || log_warning "pytest installation failed" - pipx install codespell || pipx upgrade codespell || log_warning "codespell installation failed" - - # Install Lua tooling via luarocks (used by `make lint`) - log_info "Installing Lua CLI tools via luarocks..." - if command -v luarocks &> /dev/null; then - luarocks install luacheck 2>/dev/null \ - || sudo luarocks install luacheck \ - || log_warning "luacheck installation failed" - else - log_warning "luarocks not found, skipping luacheck installation" - fi - - log_info "Installing Node packages..." - npm install -g neovim tree-sitter-cli - - log_success "Dependencies installed successfully!" -} - -backup_existing_config() { - if [[ -d "$NVIM_CONFIG_DIR" ]] && [[ "$NVIM_CONFIG_DIR" != "$SCRIPT_DIR" ]]; then - local backup_dir="${NVIM_CONFIG_DIR}.backup.$(date +%Y%m%d_%H%M%S)" - log_warning "Existing config found at $NVIM_CONFIG_DIR" - log_info "Creating backup at $backup_dir" - mv "$NVIM_CONFIG_DIR" "$backup_dir" - log_success "Backup created" - fi -} - -link_config() { - if [[ "$SCRIPT_DIR" != "$NVIM_CONFIG_DIR" ]]; then - log_info "Linking config to $NVIM_CONFIG_DIR" - mkdir -p "$(dirname "$NVIM_CONFIG_DIR")" - ln -sf "$SCRIPT_DIR" "$NVIM_CONFIG_DIR" - log_success "Config linked" - else - log_info "Already in config directory, skipping link" - fi -} - -install_plugins() { - log_info "Installing Neovim plugins..." - nvim --headless "+Lazy! sync" +qa - log_success "Plugins installed!" -} - -setup_pre_commit() { - if [[ -f "$SCRIPT_DIR/.pre-commit-config.yaml" ]]; then - log_info "Setting up pre-commit hooks..." - - # Use pipx for pre-commit on all platforms - pipx install pre-commit || pipx upgrade pre-commit || log_warning "Pre-commit installation failed" - - cd "$SCRIPT_DIR" - pre-commit install || log_warning "Pre-commit setup failed" - fi -} - -print_summary() { - echo "" - log_success "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•" - log_success " Neovim configuration installed! ๐Ÿš€" - log_success "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•" - echo "" - log_info "Next steps:" - echo " 1. Close and reopen your terminal" - echo " 2. Run: nvim" - echo " 3. Wait for plugins to finish installing" - echo " 4. Run :checkhealth to verify setup" - echo "" - log_info "Useful commands:" - echo " :Lazy - Manage plugins" - echo " :Mason - Manage LSP servers" - echo " - Show keybindings" - echo "" -} - -main() { - echo "" - log_info "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•" - log_info " Neovim Configuration Installer" - log_info "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•" - echo "" - - OS=$(detect_os) - log_info "Detected OS: $OS" - echo "" - - if [[ "$OS" == "unknown" ]]; then - log_error "Unsupported operating system" - exit 1 - fi - - read -p "Install dependencies? (y/n) " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - install_dependencies "$OS" - fi - - backup_existing_config - link_config - - read -p "Install plugins now? (y/n) " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - install_plugins - fi - - setup_pre_commit - - print_summary -} - -main "$@" diff --git a/keymaps.lua b/keymaps.lua new file mode 100644 index 0000000..cad28da --- /dev/null +++ b/keymaps.lua @@ -0,0 +1,102 @@ +-- ============================================================================ +-- KEYMAPS +-- ============================================================================ + +vim.keymap.set("i", "jk", "", { desc = "Exit insert mode with jk" }) + +-- better movement in wrapped text +vim.keymap.set("n", "j", function() + return vim.v.count == 0 and "gj" or "j" +end, { expr = true, silent = true, desc = "Down (wrap-aware)" }) +vim.keymap.set("n", "k", function() + return vim.v.count == 0 and "gk" or "k" +end, { expr = true, silent = true, desc = "Up (wrap-aware)" }) + +vim.keymap.set("n", "", ":nohlsearch", { desc = "Clear search highlights" }) + +vim.keymap.set("n", "n", "nzzzv", { desc = "Next search result (centered)" }) +vim.keymap.set("n", "N", "Nzzzv", { desc = "Previous search result (centered)" }) +vim.keymap.set("n", "", "zz", { desc = "Half page down (centered)" }) +vim.keymap.set("n", "", "zz", { desc = "Half page up (centered)" }) + +vim.keymap.set("x", "p", '"_dP', { desc = "Paste without yanking" }) +vim.keymap.set({ "n", "v" }, "x", '"_d', { desc = "Delete without yanking" }) + +vim.keymap.set("n", "bn", ":bnext", { desc = "Next buffer" }) +vim.keymap.set("n", "bp", ":bprevious", { desc = "Previous buffer" }) + +vim.keymap.set("n", "", "TmuxNavigateLeft", { desc = "Move to left window/pane" }) +vim.keymap.set("n", "", "TmuxNavigateDown", { desc = "Move to bottom window/pane" }) +vim.keymap.set("n", "", "TmuxNavigateUp", { desc = "Move to top window/pane" }) +vim.keymap.set("n", "", "TmuxNavigateRight", { desc = "Move to right window/pane" }) + +vim.keymap.set("n", "sv", ":vsplit", { desc = "Split window vertically" }) +vim.keymap.set("n", "sh", ":split", { desc = "Split window horizontally" }) +vim.keymap.set("n", "", ":resize +2", { desc = "Increase window height" }) +vim.keymap.set("n", "", ":resize -2", { desc = "Decrease window height" }) +vim.keymap.set("n", "", ":vertical resize -2", { desc = "Decrease window width" }) +vim.keymap.set("n", "", ":vertical resize +2", { desc = "Increase window width" }) + +vim.keymap.set("n", "", ":m .+1==", { desc = "Move line down" }) +vim.keymap.set("n", "", ":m .-2==", { desc = "Move line up" }) +vim.keymap.set("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) +vim.keymap.set("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) + +vim.keymap.set("v", "<", "", ">gv", { desc = "Indent right and reselect" }) + +vim.keymap.set("n", "J", "mzJ`z", { desc = "Join lines and keep cursor position" }) + +vim.keymap.set("n", "pa", function() -- show file path + local path = vim.fn.expand("%:p") + vim.fn.setreg("+", path) + print("file:", path) +end, { desc = "Copy full file path" }) + +vim.keymap.set("n", "td", function() + vim.diagnostic.enable(not vim.diagnostic.is_enabled()) +end, { desc = "Toggle diagnostics" }) + +-- snacks.nvim ---------------------------------------------------------------- +-- Picker (fuzzy finder) +vim.keymap.set("n", "ff", function() + Snacks.picker.files({ hidden = true, ignored = true }) +end, { desc = "Find files" }) +vim.keymap.set("n", "fg", function() + Snacks.picker.grep({ hidden = true, ignored = true }) +end, { desc = "Grep files" }) +vim.keymap.set("n", "fb", function() + Snacks.picker.buffers() +end, { desc = "Find buffers" }) +vim.keymap.set("n", "fr", function() + Snacks.picker.recent() +end, { desc = "Recent files" }) +vim.keymap.set("n", "fh", function() + Snacks.picker.help() +end, { desc = "Help tags" }) +vim.keymap.set("n", "fd", function() + Snacks.picker.diagnostics() +end, { desc = "Diagnostics" }) +vim.keymap.set("n", "fk", function() + Snacks.picker.keymaps() +end, { desc = "Keymaps" }) +vim.keymap.set("n", "fs", function() + Snacks.picker.lsp_symbols() +end, { desc = "Document symbols" }) +vim.keymap.set("n", "/", function() + Snacks.picker.lines() +end, { desc = "Search current buffer" }) +vim.keymap.set("n", "gg", function() + Snacks.lazygit() +end, { desc = "Open Lazygit" }) + +-- Explorer (file tree) +vim.keymap.set("n", "e", function() + Snacks.explorer() +end, { desc = "Toggle file explorer" }) + +-- Terminal +vim.keymap.set("n", "tt", function() + Snacks.terminal.toggle() +end, { desc = "Toggle terminal" }) +vim.keymap.set("t", "", "close", { desc = "Hide terminal" }) diff --git a/lazy-lock.json b/lazy-lock.json deleted file mode 100644 index 4d3ed40..0000000 --- a/lazy-lock.json +++ /dev/null @@ -1,310 +0,0 @@ -{ - "aerial.nvim": { - "branch": "master", - "commit": "28fe6e822ae344544c379d60fcb13c9519a1f08a" - }, - "blink.cmp": { - "branch": "main", - "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" - }, - "blink.compat": { - "branch": "main", - "commit": "1454f14a8d855a578ceeba77c62538fa1459a67c" - }, - "catppuccin": { - "branch": "main", - "commit": "49a926655a2f5579e9c276470fc300baaa49e524" - }, - "cloak.nvim": { - "branch": "main", - "commit": "648aca6d33ec011dc3166e7af3b38820d01a71e4" - }, - "codecompanion.nvim": { - "branch": "main", - "commit": "7cc35b7f7f08d093469fa9ae67d3af716bd729c3" - }, - "conform.nvim": { - "branch": "master", - "commit": "619363c30309d29ffa631e67c8183f2a72caa373" - }, - "diffview.nvim": { - "branch": "main", - "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" - }, - "elixir-tools.nvim": { - "branch": "main", - "commit": "b51b48edc668924a6b2f6610f9a0aff34741d20e" - }, - "emoji.nvim": { - "branch": "main", - "commit": "a79e45d35853bb6446638f4d74c6f778ddebd8e3" - }, - "fidget.nvim": { - "branch": "main", - "commit": "82404b196e73a00b1727a91903beef5ddc319d22" - }, - "friendly-snippets": { - "branch": "main", - "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" - }, - "gitlab.nvim": { - "branch": "main", - "commit": "f01ccbdaef7e8460af72c75be65f5f359928a0b4" - }, - "gitsigns.nvim": { - "branch": "main", - "commit": "25050e4ed39e628282831d4cbecb1850454ce915" - }, - "go.nvim": { - "branch": "master", - "commit": "0768d79bbebdb1a112a845f9cd6293bfbd544dab" - }, - "guihua.lua": { - "branch": "master", - "commit": "f8e06bd8a26dee3377d63c2adf1e57cdb58ac474" - }, - "harpoon": { - "branch": "harpoon2", - "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" - }, - "kulala.nvim": { - "branch": "main", - "commit": "bf50254965aff8228fa51067d79bb16d2124461e" - }, - "lazy.nvim": { - "branch": "main", - "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" - }, - "lsp_signature.nvim": { - "branch": "master", - "commit": "b7ace9ddb1640ce266012a45a672dfdaedfa5ec6" - }, - "lspkind.nvim": { - "branch": "master", - "commit": "c7274c48137396526b59d86232eabcdc7fed8a32" - }, - "lualine.nvim": { - "branch": "master", - "commit": "221ce6b2d999187044529f49da6554a92f740a96" - }, - "mason-lspconfig.nvim": { - "branch": "main", - "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" - }, - "mason-tool-installer.nvim": { - "branch": "main", - "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" - }, - "mason.nvim": { - "branch": "main", - "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" - }, - "mini.nvim": { - "branch": "main", - "commit": "7ed410c73ebb910754c2938a6dae50c51c3a096a" - }, - "minuet-ai.nvim": { - "branch": "main", - "commit": "d29dec4c36be2b41aa10e70938b7b09a03f0bdba" - }, - "neotest": { - "branch": "master", - "commit": "ad991822b7076b1d940b33a9d6d0d30416d5df81" - }, - "neotest-elixir": { - "branch": "master", - "commit": "a242aebeaa6997c1c149138ff77f6cacbe33b6fc" - }, - "neotest-golang": { - "branch": "main", - "commit": "f0ba097d4af098c036aac24cd647480d0d301ad2" - }, - "neotest-jest": { - "branch": "main", - "commit": "0e7979d51301dfae5ef839d771bd28cf593fde3f" - }, - "neotest-python": { - "branch": "master", - "commit": "e6df4f1892f6137f58135917db24d1655937d831" - }, - "neotest-rust": { - "branch": "main", - "commit": "2c9941d4a358839918fac21d20fc8fef0e1ad05f" - }, - "nui.nvim": { - "branch": "main", - "commit": "de740991c12411b663994b2860f1a4fd0937c130" - }, - "nvim-autopairs": { - "branch": "master", - "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" - }, - "nvim-colorizer.lua": { - "branch": "master", - "commit": "664c0b7cea1de71f8b65dfe951b7996fc3e6ccde" - }, - "nvim-coverage": { - "branch": "main", - "commit": "a939e425e363319d952a6c35fb3f38b34041ded2" - }, - "nvim-dap": { - "branch": "master", - "commit": "531771530d4f82ad2d21e436e3cc052d68d7aebb" - }, - "nvim-dap-go": { - "branch": "main", - "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" - }, - "nvim-dap-python": { - "branch": "master", - "commit": "1808458eba2b18f178f990e01376941a42c7f93b" - }, - "nvim-dap-ui": { - "branch": "master", - "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" - }, - "nvim-jqx": { - "branch": "master", - "commit": "07393e80fa8097e82f9038fec05e948fe8a60fd1" - }, - "nvim-lint": { - "branch": "master", - "commit": "99cbc3ca8a76845fca50e496be7212bebf907dd3" - }, - "nvim-lspconfig": { - "branch": "master", - "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" - }, - "nvim-man": { - "branch": "master", - "commit": "7fe6b3b78c71c9ef834c49e3dcbd955f7ed5c6cb" - }, - "nvim-navic": { - "branch": "master", - "commit": "f5eba192f39b453675d115351808bd51276d9de5" - }, - "nvim-nio": { - "branch": "master", - "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" - }, - "nvim-origami": { - "branch": "main", - "commit": "47be2209d09755c0202da1e22a8d67af8f5ae178" - }, - "nvim-scissors": { - "branch": "main", - "commit": "9cc1ba06afa8b23b0d30cadc02c40940df1d701e" - }, - "nvim-silicon": { - "branch": "main", - "commit": "7f66bda8f60c97a5bf4b37e5b8acb0e829ae3c32" - }, - "nvim-spectre": { - "branch": "master", - "commit": "72f56f7585903cd7bf92c665351aa585e150af0f" - }, - "nvim-surround": { - "branch": "main", - "commit": "1098d7b3c34adcfa7feb3289ee434529abd4afd1" - }, - "nvim-treesitter": { - "branch": "main", - "commit": "4916d6592ede8c07973490d9322f187e07dfefac" - }, - "nvim-treesitter-textobjects": { - "branch": "main", - "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" - }, - "nvim-ufo": { - "branch": "main", - "commit": "ab3eb124062422d276fae49e0dd63b3ad1062cfc" - }, - "nvim-web-devicons": { - "branch": "master", - "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" - }, - "octo.nvim": { - "branch": "master", - "commit": "7fed87415c401954f73401bbed0fd736b9611e7c" - }, - "overseer.nvim": { - "branch": "master", - "commit": "a93d9f6d6defdac4bcd6d2c8ba988650e42e0a0e" - }, - "package-info.nvim": { - "branch": "master", - "commit": "9725099fb118bab8360e560c1219bff60763b7e1" - }, - "plenary.nvim": { - "branch": "master", - "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" - }, - "pr-description.nvim": { - "branch": "main", - "commit": "d0af0074d6eec7af2b3724bc92c66163d82b29f3" - }, - "profile.nvim": { - "branch": "master", - "commit": "30433d7513f0d14665c1cfcea501c90f8a63e003" - }, - "refactoring.nvim": { - "branch": "master", - "commit": "7eaa150061ea18fdbe18fbb924d236e3ddccc57d" - }, - "render-markdown.nvim": { - "branch": "main", - "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" - }, - "schemastore.nvim": { - "branch": "main", - "commit": "304d2286752923e3b0eb1ddcb3d4002a69b855ad" - }, - "smart-splits.nvim": { - "branch": "master", - "commit": "2aad9808f289f5d65cfa77840a04b8590e5e34e9" - }, - "smartcolumn.nvim": { - "branch": "main", - "commit": "b9cdbdf42f7ac5a659204cd5926017c7ff724a19" - }, - "snacks.nvim": { - "branch": "main", - "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" - }, - "telescope.nvim": { - "branch": "master", - "commit": "7d324792b7943e4aa16ad007212e6acc6f9fe335" - }, - "todo-comments.nvim": { - "branch": "main", - "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" - }, - "trouble.nvim": { - "branch": "main", - "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" - }, - "undotree": { - "branch": "master", - "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" - }, - "vim-dadbod": { - "branch": "master", - "commit": "6d1d41da4873a445c5605f2005ad2c68c99d8770" - }, - "vim-dadbod-completion": { - "branch": "master", - "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" - }, - "vim-dadbod-ui": { - "branch": "master", - "commit": "07e92e22114cc5b1ba4938d99897d85b58e20475" - }, - "vim-table-mode": { - "branch": "master", - "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" - }, - "which-key.nvim": { - "branch": "main", - "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" - } -} diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua deleted file mode 100644 index 2e16b1f..0000000 --- a/lua/config/keymaps.lua +++ /dev/null @@ -1,152 +0,0 @@ -local keymap = vim.keymap -- for conciseness - --- General Keymaps ------------------- -keymap.set("n", "L", ":Lazy", { desc = "Lazy" }) -keymap.set("n", "pm", ":Mason", { desc = "Mason" }) - -keymap.set("n", "cw", ":%s///g", { desc = "Change word" }) - --- use jk to exit insert mode -keymap.set("i", "jk", "", { desc = "Exit insert mode with jk" }) - --- delete single character without copying into register -keymap.set("n", "x", '"_x') - --- increment/decrement numbers -keymap.set("n", "+", "", { desc = "Increment number" }) -keymap.set("n", "=", "", { desc = "Decrement number" }) - --- windows -keymap.set("n", "ww", "p", { desc = "Other window", remap = true }) -keymap.set("n", "wd", "c", { desc = "Delete window", remap = true }) -keymap.set("n", "w-", "s", { desc = "Split window below", remap = true }) -keymap.set("n", "w|", "v", { desc = "Split window right", remap = true }) -keymap.set("n", "-", "s", { desc = "Split window below", remap = true }) -keymap.set("n", "|", "v", { desc = "Split window right", remap = true }) - --- tabs -keymap.set("n", "l", "tablast", { desc = "Last Tab" }) -keymap.set("n", "f", "tabfirst", { desc = "First Tab" }) -keymap.set("n", "", "tabnew", { desc = "New Tab" }) -keymap.set("n", "]", "tabnext", { desc = "Next Tab" }) -keymap.set("n", "d", "tabclose", { desc = "Close Tab" }) -keymap.set("n", "[", "tabprevious", { desc = "Previous Tab" }) - --- Alternative simple tab navigation -keymap.set("n", "gt", "tabnext", { desc = "Next Tab" }) -keymap.set("n", "gT", "tabprevious", { desc = "Previous Tab" }) - --- Box-drawing & arrow picker (insert at cursor) -local box_chars = { - { text = "โ”€ horizontal", char = "โ”€" }, - { text = "โ”‚ vertical", char = "โ”‚" }, - { text = "โ”Œ corner top-left", char = "โ”Œ" }, - { text = "โ” corner top-right", char = "โ”" }, - { text = "โ”” corner bot-left", char = "โ””" }, - { text = "โ”˜ corner bot-right", char = "โ”˜" }, - { text = "โ”œ tee right", char = "โ”œ" }, - { text = "โ”ค tee left", char = "โ”ค" }, - { text = "โ”ฌ tee down", char = "โ”ฌ" }, - { text = "โ”ด tee up", char = "โ”ด" }, - { text = "โ”ผ cross", char = "โ”ผ" }, - { text = "โ•ญ round top-left", char = "โ•ญ" }, - { text = "โ•ฎ round top-right", char = "โ•ฎ" }, - { text = "โ•ฐ round bot-left", char = "โ•ฐ" }, - { text = "โ•ฏ round bot-right", char = "โ•ฏ" }, - { text = "โ• double horizontal", char = "โ•" }, - { text = "โ•‘ double vertical", char = "โ•‘" }, - { text = "โ–ถ arrow right", char = "โ–ถ" }, - { text = "โ—€ arrow left", char = "โ—€" }, - { text = "โ–ฒ arrow up", char = "โ–ฒ" }, - { text = "โ–ผ arrow down", char = "โ–ผ" }, - { text = "โ†’ thin arrow right", char = "โ†’" }, - { text = "โ† thin arrow left", char = "โ†" }, - { text = "โ†‘ thin arrow up", char = "โ†‘" }, - { text = "โ†“ thin arrow down", char = "โ†“" }, -} - -keymap.set({ "n", "i" }, "ub", function() - local mode = vim.api.nvim_get_mode().mode - Snacks.picker.pick({ - source = "box_chars", - items = box_chars, - format = "text", - layout = { preset = "select" }, - confirm = function(picker, item) - picker:close() - if not item then - return - end - vim.schedule(function() - if mode:sub(1, 1) == "i" then - vim.api.nvim_put({ item.char }, "c", false, true) - vim.cmd("startinsert") - else - vim.api.nvim_put({ item.char }, "c", true, true) - end - end) - end, - }) -end, { desc = "Pick box-drawing char" }) - --- Wrap selected lines in a box -local function box_wrap(opts) - local s_line = opts.line1 - local e_line = opts.line2 - local lines = vim.api.nvim_buf_get_lines(0, s_line - 1, e_line, false) - - local max = 0 - for i, l in ipairs(lines) do - lines[i] = l:gsub("%s+$", "") - local w = vim.fn.strdisplaywidth(lines[i]) - if w > max then - max = w - end - end - - local style = opts.args ~= "" and opts.args or "round" - local styles = { - round = { tl = "โ•ญ", tr = "โ•ฎ", bl = "โ•ฐ", br = "โ•ฏ", h = "โ”€", v = "โ”‚" }, - sharp = { tl = "โ”Œ", tr = "โ”", bl = "โ””", br = "โ”˜", h = "โ”€", v = "โ”‚" }, - double = { tl = "โ•”", tr = "โ•—", bl = "โ•š", br = "โ•", h = "โ•", v = "โ•‘" }, - } - local s = styles[style] or styles.round - - local out = { s.tl .. s.h:rep(max + 2) .. s.tr } - for _, l in ipairs(lines) do - local pad = max - vim.fn.strdisplaywidth(l) - table.insert(out, s.v .. " " .. l .. string.rep(" ", pad) .. " " .. s.v) - end - table.insert(out, s.bl .. s.h:rep(max + 2) .. s.br) - - vim.api.nvim_buf_set_lines(0, s_line - 1, e_line, false, out) -end - -vim.api.nvim_create_user_command("Box", box_wrap, { - range = true, - nargs = "?", - complete = function() - return { "round", "sharp", "double" } - end, - desc = "Wrap selected lines in a box (round|sharp|double)", -}) - -keymap.set("v", "ub", ":Box", { desc = "Box-wrap selection" }) - --- Sesh - tmux session picker -keymap.set("n", "fs", function() - vim.fn.system([[ - tmux display-popup -E -w 55% -h 60% 'sesh connect "$( - sesh list | fzf \ - --no-sort --border-label " sesh " --prompt "โšก " \ - --header "^a all ^t tmux ^x zoxide ^g config ^d kill ^f find" \ - --bind "tab:down,btab:up" \ - --bind "ctrl-a:change-prompt(โšก )+reload(sesh list)" \ - --bind "ctrl-t:change-prompt(๐ŸชŸ )+reload(sesh list -t)" \ - --bind "ctrl-g:change-prompt(โš™๏ธ )+reload(sesh list -c)" \ - --bind "ctrl-x:change-prompt(๐Ÿ“ )+reload(sesh list -z)" \ - --bind "ctrl-f:change-prompt(๐Ÿ”Ž )+reload(fd -H -d 2 -t d -E .Trash . ~)" \ - --bind "ctrl-d:execute(tmux kill-session -t {})+change-prompt(โšก )+reload(sesh list)" - )"' - ]]) -end, { desc = "Sesh tmux sessions" }) diff --git a/lua/config/lazy.lua b/lua/config/lazy.lua deleted file mode 100644 index 008a9ca..0000000 --- a/lua/config/lazy.lua +++ /dev/null @@ -1,22 +0,0 @@ -local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" -if not vim.uv.fs_stat(lazypath) then - vim.fn.system({ - "git", - "clone", - "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", -- latest stable release - lazypath, - }) -end -vim.opt.rtp:prepend(lazypath) - -require("lazy").setup("plugins", { - checker = { - enabled = true, - notify = true, - }, - change_detection = { - notify = true, - }, -}) diff --git a/lua/config/options.lua b/lua/config/options.lua deleted file mode 100644 index d972ee5..0000000 --- a/lua/config/options.lua +++ /dev/null @@ -1,52 +0,0 @@ -local opt = vim.opt -- for conciseness - --- Disable unused language providers (avoids checkhealth noise + startup cost) -vim.g.loaded_python3_provider = 0 -vim.g.loaded_perl_provider = 0 -vim.g.loaded_ruby_provider = 0 -vim.g.loaded_node_provider = 0 - --- line numbers -opt.relativenumber = true -- show relative line numbers -opt.number = true -- shows absolute line number on cursor line (when relative number is on) - --- tabs & indentation -opt.tabstop = 2 -- 2 spaces for tabs (prettier default) -opt.shiftwidth = 2 -- 2 spaces for indent width -opt.expandtab = true -- expand tab to spaces -opt.autoindent = true -- copy indent from current line when starting new one - --- line wrapping -opt.wrap = false -- disable line wrapping - --- search settings -opt.ignorecase = true -- ignore case when searching -opt.smartcase = true -- if you include mixed case in your search, assumes you want case-sensitive - --- cursor line -opt.cursorline = true -- highlight the current cursor line - --- appearance -opt.termguicolors = true -opt.background = "dark" -- colorschemes that can be light or dark will be made dark -opt.signcolumn = "yes" -- show sign column so that text doesn't shift - --- backspace -opt.backspace = "indent,eol,start" -- allow backspace on indent, end of line or insert mode start position - --- clipboard -opt.clipboard:append("unnamedplus") -- use system clipboard as default register - --- split windows -opt.splitright = true -- split vertical window to the right -opt.splitbelow = true -- split horizontal window to the bottom - --- performance -opt.updatetime = 250 -- faster LSP responses - --- quality of life -opt.scrolloff = 8 -- keep cursor centered -opt.undofile = true -- persistent undo - --- turn off swapfile -opt.swapfile = false diff --git a/lua/plugins/aerial.lua b/lua/plugins/aerial.lua deleted file mode 100644 index 7c35534..0000000 --- a/lua/plugins/aerial.lua +++ /dev/null @@ -1,146 +0,0 @@ -return { - { - "stevearc/aerial.nvim", - event = "LspAttach", - cmd = { "AerialToggle", "AerialNavToggle" }, - dependencies = { - "nvim-treesitter/nvim-treesitter", - "nvim-tree/nvim-web-devicons", - }, - config = function() - require("aerial").setup({ - -- Priority list of preferred backends for aerial - backends = { "treesitter", "lsp", "markdown", "asciidoc", "man" }, - - -- Layout and positioning - layout = { - max_width = { 40, 0.2 }, -- 40 columns, or 20% of total width - width = nil, - min_width = 10, - win_opts = {}, - default_direction = "prefer_right", - placement = "window", - preserve_equality = false, - }, - - -- Attach aerial to every buffer by default - attach_mode = "window", - - -- Close aerial automatically when losing focus - close_automatic_events = {}, - - -- Keymaps in aerial window - keymaps = { - ["?"] = "actions.show_help", - ["g?"] = "actions.show_help", - [""] = "actions.jump", - ["<2-LeftMouse>"] = "actions.jump", - [""] = "actions.jump_vsplit", - [""] = "actions.jump_split", - ["p"] = "actions.scroll", - [""] = "actions.down_and_scroll", - [""] = "actions.up_and_scroll", - ["{"] = "actions.prev", - ["}"] = "actions.next", - ["[["] = "actions.prev_up", - ["]]"] = "actions.next_up", - ["q"] = "actions.close", - ["o"] = "actions.tree_toggle", - ["za"] = "actions.tree_toggle", - ["O"] = "actions.tree_toggle_recursive", - ["zA"] = "actions.tree_toggle_recursive", - ["l"] = "actions.tree_open", - ["zo"] = "actions.tree_open", - ["L"] = "actions.tree_open_recursive", - ["zO"] = "actions.tree_open_recursive", - ["h"] = "actions.tree_close", - ["zc"] = "actions.tree_close", - ["H"] = "actions.tree_close_recursive", - ["zC"] = "actions.tree_close_recursive", - ["zr"] = "actions.tree_increase_fold_level", - ["zR"] = "actions.tree_open_all", - ["zm"] = "actions.tree_decrease_fold_level", - ["zM"] = "actions.tree_close_all", - ["zx"] = "actions.tree_sync_folds", - ["zX"] = "actions.tree_sync_folds", - }, - - -- Show box drawing characters for the tree hierarchy - show_guides = true, - - -- Filter symbols to show only relevant ones for DevOps files - filter_kind = { - "Class", - "Constructor", - "Enum", - "Function", - "Interface", - "Module", - "Method", - "Struct", - "Variable", - "Constant", - "String", - "Number", - "Boolean", - "Array", - "Object", - "Key", - "Namespace", - "Package", - "Property", - "Field", - }, - - -- Disable automatic opening for now (use manual toggle) - open_automatic = false, - - -- Close behavior - close_behavior = "persist", - - -- Configure icons - icons = {}, - - -- Ignore certain symbols for cleaner outline - ignore = { - -- Ignore by symbol kind - kind_ignore = {}, - -- Ignore by name - name_ignore = {}, - -- Ignore by treesitter node type - buftypes_ignore = { - "nofile", - "terminal", - }, - wintypes_ignore = { - "autocmd", - "command", - "quickfix", - "loclist", - }, - }, - - -- Highlight the closest symbol - highlight_closest = true, - highlight_on_hover = false, - highlight_on_jump = 300, - - -- Options for telescope extension - lsp = { - diagnostics_trigger_update = true, - update_when_errors = true, - }, - - treesitter = { - update_delay = 300, - }, - }) - - -- Global keymaps - vim.keymap.set("n", "oa", "AerialToggle", { desc = "Toggle Aerial" }) - vim.keymap.set("n", "oA", "AerialNavToggle", { desc = "Toggle Aerial Navigation" }) - vim.keymap.set("n", "[S", "AerialPrev", { desc = "Previous symbol" }) - vim.keymap.set("n", "]S", "AerialNext", { desc = "Next symbol" }) - end, - }, -} diff --git a/lua/plugins/blink-cmp.lua b/lua/plugins/blink-cmp.lua deleted file mode 100644 index 441c168..0000000 --- a/lua/plugins/blink-cmp.lua +++ /dev/null @@ -1,108 +0,0 @@ -return { - "saghen/blink.cmp", - dependencies = { "allaman/emoji.nvim", "saghen/blink.compat", "rafamadriz/friendly-snippets" }, - version = "*", - opts = { - keymap = { - preset = "default", - [""] = { "select_prev", "fallback" }, - [""] = { "select_next", "fallback" }, - [""] = { "scroll_documentation_up", "fallback" }, - [""] = { "scroll_documentation_down", "fallback" }, - [""] = { "hide", "fallback" }, - [""] = { "accept", "fallback" }, - [""] = { "accept", "fallback" }, - [""] = { "snippet_forward", "select_next", "fallback" }, - [""] = { "snippet_backward", "select_prev", "fallback" }, - }, - - appearance = { - use_nvim_cmp_as_default = true, - nerd_font_variant = "mono", - }, - - sources = { - default = { "emoji", "lsp", "path", "snippets", "buffer" }, - providers = { - buffer = { - min_keyword_length = 3, - }, - emoji = { - name = "emoji", - module = "blink.compat.source", - transform_items = function(_, items) - local kind = require("blink.cmp.types").CompletionItemKind.Text - for i = 1, #items do - items[i].kind = kind - end - return items - end, - }, - lsp = { - transform_items = function(_, items) - if vim.bo.filetype == "terraform" then - for i = 1, #items do - local item = items[i] - if item.detail and item.detail:match("variable") then - item.label_description = item.detail - end - end - end - return items - end, - }, - }, - }, - - completion = { - documentation = { - auto_show = true, - auto_show_delay_ms = 500, - update_delay_ms = 50, - window = { - border = "rounded", - }, - }, - menu = { - border = "rounded", - auto_show = true, - max_height = 10, - scrolloff = 2, - scrollbar = true, - draw = { - treesitter = { "lsp" }, - columns = { { "label", "label_description", gap = 1 }, { "kind_icon", "kind" } }, - }, - }, - ghost_text = { - enabled = true, - }, - }, - - signature = { - enabled = false, - }, - }, - opts_extend = { "sources.default" }, - init = function() - local autocmd = vim.api.nvim_create_autocmd - local ui_helpers = vim.api.nvim_create_augroup("UiHelpers", { clear = true }) - - -- disable buggy anims in completion windows - autocmd("User", { - group = ui_helpers, - pattern = "BlinkCmpMenuOpen", - callback = function() - vim.g.snacks_animate = false - end, - }) - - autocmd("User", { - group = ui_helpers, - pattern = "BlinkCmpMenuClose", - callback = function() - vim.g.snacks_animate = true - end, - }) - end, -} diff --git a/lua/plugins/catppuccin.lua b/lua/plugins/catppuccin.lua deleted file mode 100644 index cd753e1..0000000 --- a/lua/plugins/catppuccin.lua +++ /dev/null @@ -1,127 +0,0 @@ -return { - "catppuccin/nvim", - name = "catppuccin", - priority = 1000, - - config = function() - vim.g.catppuccin_flavour = "mocha" - require("catppuccin").setup({ - transparent_background = true, - term_colors = false, - compile = { - enabled = false, - path = vim.fn.stdpath("cache") .. "/catppuccin", - }, - dim_inactive = { - enabled = false, - shade = "dark", - percentage = 0.15, - }, - styles = { - comments = { "italic" }, - conditionals = { "italic" }, - loops = {}, - functions = {}, - keywords = {}, - strings = {}, - variables = {}, - numbers = {}, - booleans = {}, - properties = {}, - types = {}, - operators = {}, - }, - integrations = { - aerial = true, - blink_cmp = true, - diffview = true, - fidget = true, - gitsigns = true, - harpoon = true, - lsp_trouble = true, - mason = true, - neotest = true, - snacks = true, - telescope = { - enabled = true, - }, - treesitter = true, - notify = true, - semantic_tokens = true, - which_key = true, - }, - custom_highlights = function(colors) - return { - -- Enhanced semantic tokens using full Catppuccin palette - ["@lsp.type.namespace"] = { fg = colors.rosewater, style = { "bold" } }, - ["@lsp.type.type"] = { fg = colors.yellow, style = { "bold" } }, - ["@lsp.type.class"] = { fg = colors.peach, style = { "bold" } }, - ["@lsp.type.enum"] = { fg = colors.flamingo, style = { "bold" } }, - ["@lsp.type.interface"] = { fg = colors.sapphire, style = { "bold" } }, - ["@lsp.type.struct"] = { fg = colors.yellow, style = { "italic" } }, - ["@lsp.type.parameter"] = { fg = colors.maroon, style = { "italic" } }, - ["@lsp.type.variable"] = { fg = colors.text }, - ["@lsp.type.property"] = { fg = colors.teal, style = { "italic" } }, - ["@lsp.type.enumMember"] = { fg = colors.sky, style = { "bold" } }, - ["@lsp.type.function"] = { fg = colors.blue, style = { "bold" } }, - ["@lsp.type.method"] = { fg = colors.sapphire, style = { "bold" } }, - ["@lsp.type.macro"] = { fg = colors.mauve, style = { "bold" } }, - ["@lsp.type.decorator"] = { fg = colors.pink, style = { "italic" } }, - ["@lsp.type.keyword"] = { fg = colors.mauve, style = { "bold" } }, - ["@lsp.type.string"] = { fg = colors.green, style = { "italic" } }, - ["@lsp.type.number"] = { fg = colors.peach }, - ["@lsp.type.regexp"] = { fg = colors.pink, style = { "bold" } }, - ["@lsp.type.operator"] = { fg = colors.sky }, - ["@lsp.type.comment"] = { fg = colors.overlay1, style = { "italic" } }, - - -- Language-specific enhancements using Catppuccin palette - - -- Terraform - ["@lsp.type.variable.terraform"] = { fg = colors.flamingo, style = { "bold" } }, - ["@lsp.type.property.terraform"] = { fg = colors.sapphire, style = { "italic" } }, - ["@lsp.type.string.terraform"] = { fg = colors.green, style = { "bold" } }, - ["@lsp.type.keyword.terraform"] = { fg = colors.mauve, style = { "bold" } }, - ["@lsp.type.function.terraform"] = { fg = colors.sky, style = { "bold" } }, - ["@lsp.type.type.terraform"] = { fg = colors.peach, style = { "bold" } }, - ["@lsp.type.parameter.terraform"] = { fg = colors.rosewater, style = { "italic" } }, - ["@lsp.type.namespace.terraform"] = { fg = colors.lavender, style = { "bold" } }, - ["@lsp.type.operator.terraform"] = { fg = colors.pink }, - ["@lsp.type.number.terraform"] = { fg = colors.peach, style = { "bold" } }, - - -- Python - ["@lsp.type.class.python"] = { fg = colors.peach, style = { "bold" } }, - ["@lsp.type.function.python"] = { fg = colors.blue, style = { "bold" } }, - ["@lsp.type.method.python"] = { fg = colors.sapphire, style = { "bold" } }, - ["@lsp.type.decorator.python"] = { fg = colors.pink, style = { "italic" } }, - ["@lsp.type.variable.python"] = { fg = colors.text }, - ["@lsp.type.parameter.python"] = { fg = colors.maroon, style = { "italic" } }, - - -- Go - ["@lsp.type.type.go"] = { fg = colors.yellow, style = { "bold" } }, - ["@lsp.type.function.go"] = { fg = colors.blue, style = { "bold" } }, - ["@lsp.type.method.go"] = { fg = colors.sapphire, style = { "bold" } }, - ["@lsp.type.struct.go"] = { fg = colors.peach, style = { "bold" } }, - ["@lsp.type.interface.go"] = { fg = colors.flamingo, style = { "bold" } }, - - -- Elixir - ["@lsp.type.function.elixir"] = { fg = colors.blue, style = { "bold" } }, - ["@lsp.type.module.elixir"] = { fg = colors.rosewater, style = { "bold" } }, - ["@lsp.type.atom.elixir"] = { fg = colors.lavender, style = { "italic" } }, - ["@lsp.type.variable.elixir"] = { fg = colors.text }, - - -- JSON/YAML - ["@lsp.type.property.json"] = { fg = colors.sky, style = { "italic" } }, - ["@lsp.type.string.json"] = { fg = colors.green }, - ["@lsp.type.property.yaml"] = { fg = colors.teal, style = { "italic" } }, - ["@lsp.type.string.yaml"] = { fg = colors.green }, - - -- Lua - ["@lsp.type.function.lua"] = { fg = colors.blue, style = { "bold" } }, - ["@lsp.type.variable.lua"] = { fg = colors.text }, - ["@lsp.type.property.lua"] = { fg = colors.teal, style = { "italic" } }, - } - end, - }) - vim.cmd([[colorscheme catppuccin]]) - end, -} diff --git a/lua/plugins/cloak.lua b/lua/plugins/cloak.lua deleted file mode 100644 index 56db12e..0000000 --- a/lua/plugins/cloak.lua +++ /dev/null @@ -1,22 +0,0 @@ -return { - "laytan/cloak.nvim", - event = "BufReadPre", - config = function() - require("cloak").setup({ - enabled = true, - cloak_character = "*", - highlight_group = "Comment", - patterns = { - { - file_pattern = { - ".env*", - ".env", - ".edgerc", - ".credentials", - }, - cloak_pattern = "=.+", - }, - }, - }) - end, -} diff --git a/lua/plugins/diffview.lua b/lua/plugins/diffview.lua deleted file mode 100644 index 29f3c27..0000000 --- a/lua/plugins/diffview.lua +++ /dev/null @@ -1,230 +0,0 @@ -return { - { - -- Advanced git analysis - "sindrets/diffview.nvim", - cmd = { "DiffviewOpen", "DiffviewClose", "DiffviewFileHistory" }, - config = function() - require("diffview").setup({ - diff_binaries = false, - enhanced_diff_hl = false, - git_cmd = { "git" }, - use_icons = true, - watch_index = true, - icons = { - folder_closed = "", - folder_open = "", - }, - signs = { - fold_closed = "", - fold_open = "", - done = "โœ“", - }, - view = { - default = { - layout = "diff2_horizontal", - winbar_info = false, - }, - merge_tool = { - layout = "diff3_horizontal", - disable_diagnostics = true, - winbar_info = true, - }, - file_history = { - layout = "diff2_horizontal", - winbar_info = false, - }, - }, - file_panel = { - listing_style = "tree", - tree_options = { - flatten_dirs = true, - folder_statuses = "only_folded", - }, - win_config = { - position = "left", - width = 35, - win_opts = {}, - }, - }, - file_history_panel = { - log_options = { - git = { - single_file = { - diff_merges = "combined", - }, - multi_file = { - diff_merges = "first-parent", - }, - }, - }, - win_config = { - position = "bottom", - height = 16, - win_opts = {}, - }, - }, - commit_log_panel = { - win_config = { - win_opts = {}, - }, - }, - default_args = { - DiffviewOpen = {}, - DiffviewFileHistory = {}, - }, - hooks = {}, - keymaps = { - disable_defaults = false, - view = { - { "n", "", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "gf", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "e", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "g", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - }, - diff1 = { - { "n", "g?", "h diffview-maps-diff1", { desc = "Open help panel" } }, - }, - diff2 = { - { "n", "g?", "h diffview-maps-diff2", { desc = "Open help panel" } }, - }, - diff3 = { - { - "n", - "2do", - "diffget //2", - { desc = "Obtain the diff hunk from the OURS version of the file" }, - }, - { - "n", - "3do", - "diffget //3", - { desc = "Obtain the diff hunk from the THEIRS version of the file" }, - }, - { "n", "g?", "h diffview-maps-diff3", { desc = "Open help panel" } }, - }, - diff4 = { - { - "n", - "1do", - "diffget //1", - { desc = "Obtain the diff hunk from the BASE version of the file" }, - }, - { - "n", - "2do", - "diffget //2", - { desc = "Obtain the diff hunk from the OURS version of the file" }, - }, - { - "n", - "3do", - "diffget //3", - { desc = "Obtain the diff hunk from the THEIRS version of the file" }, - }, - { "n", "g?", "h diffview-maps-diff4", { desc = "Open help panel" } }, - }, - file_panel = { - { "n", "j", "j", { desc = "Next entry" } }, - { "n", "", "j", { desc = "Next entry" } }, - { "n", "k", "k", { desc = "Prev entry" } }, - { "n", "", "k", { desc = "Prev entry" } }, - { "n", "", "DiffviewOpen", { desc = "Open the diff for the selected entry" } }, - { "n", "o", "DiffviewOpen", { desc = "Open the diff for the selected entry" } }, - { "n", "<2-LeftMouse>", "DiffviewOpen", { desc = "Open the diff for the selected entry" } }, - { "n", "-", "DiffviewToggleStage", { desc = "Stage / unstage the selected entry" } }, - { "n", "S", "DiffviewToggleStage", { desc = "Stage / unstage the selected entry" } }, - { - "n", - "U", - "DiffviewRefresh", - { desc = "Update stats and entries in the file list" }, - }, - { - "n", - "X", - "DiffviewRefresh", - { desc = "Update stats and entries in the file list" }, - }, - { - "n", - "R", - "DiffviewRefresh", - { desc = "Update stats and entries in the file list" }, - }, - { "n", "", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "gf", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "e", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "g", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "g?", "h diffview-maps-file-panel", { desc = "Open help panel" } }, - }, - file_history_panel = { - { - "n", - "g!", - "DiffviewRefresh", - { desc = "Update stats and entries in the file list" }, - }, - { - "n", - "", - "DiffviewOpen", - { desc = "Open the diff for the selected entry" }, - }, - { - "n", - "y", - "DiffviewYankHash", - { desc = "Copy the commit hash of the entry under the cursor" }, - }, - { "n", "L", "DiffviewToggleFileFold", { desc = "Toggle fold for selected file" } }, - { "n", "zR", "DiffviewExpandAllFolds", { desc = "Expand all folds" } }, - { "n", "zM", "DiffviewCollapseAllFolds", { desc = "Collapse all folds" } }, - { "n", "j", "j", { desc = "Next entry" } }, - { "n", "", "j", { desc = "Next entry" } }, - { "n", "k", "k", { desc = "Prev entry" } }, - { "n", "", "k", { desc = "Prev entry" } }, - { - "n", - "", - "DiffviewOpen", - { desc = "Open the diff for the selected entry" }, - }, - { - "n", - "o", - "DiffviewOpen", - { desc = "Open the diff for the selected entry" }, - }, - { - "n", - "<2-LeftMouse>", - "DiffviewOpen", - { desc = "Open the diff for the selected entry" }, - }, - { "n", "", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "gf", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "e", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "g", "DiffviewToggleFiles", { desc = "Toggle file panel" } }, - { "n", "g?", "h diffview-maps-file-history-panel", { desc = "Open help panel" } }, - }, - option_panel = { - { "n", "", "DiffviewToggleOption", { desc = "Toggle the current option" } }, - { "n", "q", "DiffviewClose", { desc = "Close diffview" } }, - { "n", "", "DiffviewClose", { desc = "Close diffview" } }, - { "n", "g?", "h diffview-maps-option-panel", { desc = "Open help panel" } }, - }, - help_panel = { - { "n", "q", "DiffviewClose", { desc = "Close diffview" } }, - { "n", "", "DiffviewClose", { desc = "Close diffview" } }, - { "n", "g?", "h diffview-maps-help-panel", { desc = "Open help panel" } }, - }, - }, - }) - - vim.keymap.set("n", "gd", "DiffviewOpen", { desc = "Open diffview" }) - vim.keymap.set("n", "gD", "DiffviewClose", { desc = "Close diffview" }) - vim.keymap.set("n", "gh", "DiffviewFileHistory", { desc = "File history" }) - vim.keymap.set("n", "gH", "DiffviewFileHistory %", { desc = "Current file history" }) - end, - }, -} diff --git a/lua/plugins/elixir-tools.lua b/lua/plugins/elixir-tools.lua deleted file mode 100644 index 437bd7e..0000000 --- a/lua/plugins/elixir-tools.lua +++ /dev/null @@ -1,44 +0,0 @@ -return { - { - -- Elixir tools - "elixir-tools/elixir-tools.nvim", - version = "*", - event = { "BufReadPre", "BufNewFile" }, - config = function() - local elixir = require("elixir") - local elixirls = require("elixir.elixirls") - - elixir.setup({ - nextls = { - enable = true, - init_options = { - mix_env = "dev", - mix_target = "host", - experimental = { - completions = { - enable = true, - }, - }, - }, - }, - credo = { - enable = true, - }, - elixirls = { - enable = true, - settings = elixirls.settings({ - dialyzerEnabled = false, - enableTestLenses = false, - }), - }, - -- Disable lexical to avoid conflicts - lexical = { - enable = false, - }, - }) - end, - dependencies = { - "nvim-lua/plenary.nvim", - }, - }, -} diff --git a/lua/plugins/emoji.lua b/lua/plugins/emoji.lua deleted file mode 100644 index 2b5b4db..0000000 --- a/lua/plugins/emoji.lua +++ /dev/null @@ -1,18 +0,0 @@ -return { - "allaman/emoji.nvim", - version = "5.0.0", - ft = "markdown", - dependencies = { - "nvim-lua/plenary.nvim", - "saghen/blink.cmp", - "nvim-telescope/telescope.nvim", - }, - opts = { - enable_cmp_integration = true, - }, - config = function(_, opts) - require("emoji").setup(opts) - local ts = require("telescope").load_extension("emoji") - vim.keymap.set("n", "se", ts.emoji, { desc = "[S]earch [E]moji" }) - end, -} diff --git a/lua/plugins/fidget.lua b/lua/plugins/fidget.lua deleted file mode 100644 index 375d281..0000000 --- a/lua/plugins/fidget.lua +++ /dev/null @@ -1,86 +0,0 @@ -return { - "j-hui/fidget.nvim", - event = "LspAttach", - config = function() - require("fidget").setup({ - progress = { - poll_rate = 0, - suppress_on_insert = false, - ignore_done_already = false, - ignore_empty_message = false, - clear_on_detach = function(client_id) - local client = vim.lsp.get_client_by_id(client_id) - return client and client.name or nil - end, - notification_group = function(msg) - return msg.lsp_server and msg.lsp_server.name or "lsp" - end, - ignore = {}, - display = { - render_limit = 16, - done_ttl = 3, - done_icon = "โœ“", - done_style = "Constant", - progress_ttl = math.huge, - progress_icon = { pattern = "dots", period = 1 }, - progress_style = "WarningMsg", - group_style = "Title", - icon_style = "Question", - priority = 30, - skip_history = true, - format_message = require("fidget.progress.display").default_format_message, - format_annote = function(msg) - return msg.title - end, - format_group_name = function(group) - return tostring(group) - end, - overrides = { - rust_analyzer = { name = "rust-analyzer" }, - }, - }, - lsp = { - progress_ringbuf_size = 0, - log_handler = false, - }, - }, - notification = { - poll_rate = 10, - filter = vim.log.levels.INFO, - history_size = 128, - override_vim_notify = false, - configs = { default = require("fidget.notification").default_config }, - redirect = function(msg, level, opts) - if opts and opts.on_open then - return require("fidget.integration.nvim-notify").delegate(msg, level, opts) - end - end, - view = { - stack_upwards = true, - icon_separator = " ", - group_separator = "---", - group_separator_hl = "Comment", - }, - window = { - normal_hl = "Comment", - winblend = 100, - border = "none", - zindex = 45, - max_width = 0, - max_height = 0, - x_padding = 1, - y_padding = 0, - align = "bottom", - relative = "editor", - }, - }, - integration = {}, - logger = { - level = vim.log.levels.WARN, - max_size = 10000, - float_precision = 0.01, - path = string.format("%s/fidget.nvim.log", vim.fn.stdpath("cache")), - }, - }) - end, -} diff --git a/lua/plugins/gitlab.lua b/lua/plugins/gitlab.lua deleted file mode 100644 index fd62386..0000000 --- a/lua/plugins/gitlab.lua +++ /dev/null @@ -1,276 +0,0 @@ -return { - "harrisoncramer/gitlab.nvim", - dependencies = { - "MunifTanjim/nui.nvim", - "nvim-lua/plenary.nvim", - "sindrets/diffview.nvim", - "nvim-tree/nvim-web-devicons", - }, - branch = "main", - build = function() - require("gitlab.server").build(true) - end, - event = "VeryLazy", - config = function() - local git_repo = require("utils.git_repo") - - -- Resolve the GitLab instance URL. The Go server derives the - -- namespace/project from the git remote itself, so we only need the host. - -- Priority: explicit `git config gitlab.url` / $GITLAB_URL override, then - -- the host parsed from the origin remote (handles self-hosted instances), - -- then gitlab.com as a last resort. - local function resolve_gitlab_url() - local configured = git_repo.configured_gitlab_url() - if configured ~= "" then - return configured - end - return git_repo.gitlab_url_from_remote() or "https://gitlab.com" - end - - -- gitlab.nvim's Go server uses a custom HTTP transport that does NOT honor - -- the HTTPS_PROXY/HTTP_PROXY env vars on its own (unlike glab/gh). Behind a - -- corporate proxy this makes every API call hang. Pass the proxy explicitly. - local gitlab_proxy = git_repo.proxy_for_host(git_repo.host_from_remote(resolve_gitlab_url())) - - require("gitlab").setup({ - auth_provider = function() - local url = resolve_gitlab_url() - - -- Prefer the token glab already uses for this host (single source of - -- truth โ€” avoids gitlab.nvim running with a stale/expired token). - local token = git_repo.glab_token_for_host(git_repo.host_from_remote(url)) - - if not token or token == "" then - token = vim.fn.system("git config --get gitlab.token 2>/dev/null"):gsub("%s+", "") - end - - if token == "" then - token = os.getenv("GITLAB_TOKEN") - end - - if not token or token == "" then - vim.notify( - "GitLab token not found. Authenticate with `glab auth login` or set `git config --global gitlab.token `.", - vim.log.levels.WARN - ) - return nil, nil, "No GitLab token found" - end - - return token, url, nil - end, - debug = { - request = true, -- Requests to/from Go server - response = true, - gitlab_request = true, -- Requests to/from Gitlab - gitlab_response = true, - }, - connection_settings = { - proxy = gitlab_proxy, - insecure = false, - remote = "origin", - }, - create_mr = { - delete_branch = true, - squash = true, - target = "main", - }, - log_path = vim.fn.stdpath("cache") .. "/gitlab.nvim.log", - }) - - -- Helper function to detect if current repo is GitLab - local is_gitlab_repo = require("utils.git_repo").is_gitlab - - -- Context-aware keymaps that work with both GitHub (octo) and GitLab - vim.keymap.set("n", "gPr", function() - if is_gitlab_repo() then - -- Generate description first, then create MR - local description, error = require("pr-description").generate_description({ is_gitlab = true }) - if error then - print("Error generating description: " .. error) - require("gitlab").create_mr() -- Fallback to basic creation - elseif description then - -- Copy description to clipboard for pasting into MR - vim.fn.setreg("+", description) - print("Generated MR description (copied to clipboard)") - require("gitlab").create_mr() - else - require("gitlab").create_mr() - end - else - -- Generate description for GitHub PR too - local description, error = require("pr-description").generate_description({ is_gitlab = false }) - if error then - print("Error generating description: " .. error) - vim.cmd("Octo pr create") -- Fallback to basic creation - elseif description then - -- Copy description to clipboard for pasting into PR - vim.fn.setreg("+", description) - print("Generated PR description (copied to clipboard)") - vim.cmd("Octo pr create") - else - vim.cmd("Octo pr create") - end - end - end, { desc = "Create PR/MR with Generated Description" }) - - -- Add description generator keymap for GitLab - vim.keymap.set("n", "gPg", function() - if is_gitlab_repo() then - local description, error = require("pr-description").generate_description({ is_gitlab = true }) - if error then - print("Error: " .. error) - elseif description then - -- Copy description to clipboard and show it - vim.fn.setreg("+", description) - vim.cmd("new") - vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(description, "\n")) - vim.bo.filetype = "markdown" - vim.bo.buftype = "nofile" - vim.bo.bufhidden = "wipe" - print("Generated GitLab MR description (copied to clipboard)") - end - else - local description, error = require("pr-description").generate_description({ is_gitlab = false }) - if error then - print("Error: " .. error) - elseif description then - vim.fn.setreg("+", description) - vim.fn.setreg("*", description) - vim.cmd("new") - vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(description, "\n")) - vim.bo.filetype = "markdown" - vim.bo.buftype = "nofile" - vim.bo.bufhidden = "wipe" - print("Generated PR description (copied to clipboard)") - end - end - end, { desc = "Generate PR/MR Description" }) - - vim.keymap.set("n", "gPl", function() - if is_gitlab_repo() then - require("gitlab").choose_merge_request() - else - vim.cmd("Octo pr list") - end - end, { desc = "List PRs/MRs" }) - - vim.keymap.set("n", "gPo", function() - if is_gitlab_repo() then - require("gitlab").review() - else - vim.cmd("Octo pr") - end - end, { desc = "Open Current PR/MR" }) - - vim.keymap.set("n", "gPs", function() - if is_gitlab_repo() then - require("gitlab").choose_merge_request() - else - vim.cmd("Octo pr search") - end - end, { desc = "Search PRs/MRs" }) - - vim.keymap.set("n", "gPc", function() - if is_gitlab_repo() then - require("gitlab").checkout_mr() - else - vim.cmd("Octo pr checkout") - end - end, { desc = "Checkout PR/MR" }) - - -- Review shortcuts - vim.keymap.set("n", "gPv", function() - if is_gitlab_repo() then - require("gitlab").review() - else - vim.cmd("Octo review start") - end - end, { desc = "Start Review" }) - - vim.keymap.set("n", "gPR", function() - if is_gitlab_repo() then - require("gitlab").review() - else - vim.cmd("Octo review resume") - end - end, { desc = "Resume Review" }) - - vim.keymap.set("n", "gPa", function() - if is_gitlab_repo() then - require("gitlab").approve() - else - vim.cmd("Octo review submit approve") - end - end, { desc = "Approve PR/MR" }) - - vim.keymap.set("n", "gPx", function() - if is_gitlab_repo() then - require("gitlab").revoke() - else - vim.cmd("Octo review submit request_changes") - end - end, { desc = "Request Changes/Revoke" }) - - vim.keymap.set("n", "gPf", function() - if is_gitlab_repo() then - require("gitlab").toggle_discussions() - else - vim.cmd("Octo pr files") - end - end, { desc = "View PR/MR Files" }) - - -- Merge operations - vim.keymap.set("n", "gPm", function() - if is_gitlab_repo() then - require("gitlab").merge() - else - vim.cmd("Octo pr merge") - end - end, { desc = "Merge PR/MR" }) - - -- Pipeline management - vim.keymap.set("n", "gPp", function() - require("gitlab").pipeline() - end, { desc = "View Pipeline" }) - - -- Upload files - vim.keymap.set("n", "gPu", function() - require("gitlab").upload_file() - end, { desc = "Upload File" }) - - -- Toggle discussions - vim.keymap.set("n", "gPd", function() - require("gitlab").toggle_discussions() - end, { desc = "Toggle Discussions" }) - - -- Additional utilities - vim.keymap.set("n", "gPb", function() - require("gitlab").open_in_browser() - end, { desc = "Open in Browser" }) - - -- Create user commands for easier access - vim.api.nvim_create_user_command("GitlabMR", function() - require("gitlab").choose_merge_request() - end, { desc = "Choose GitLab Merge Request" }) - - vim.api.nvim_create_user_command("GitlabReview", function() - require("gitlab").review() - end, { desc = "Review Current MR" }) - - vim.api.nvim_create_user_command("GitlabApprove", function() - require("gitlab").approve() - end, { desc = "Approve MR" }) - - vim.api.nvim_create_user_command("GitlabMerge", function() - require("gitlab").merge() - end, { desc = "Merge MR" }) - - vim.api.nvim_create_user_command("GitlabCreateMR", function() - require("gitlab").create_mr() - end, { desc = "Create MR" }) - - vim.api.nvim_create_user_command("GitlabPipeline", function() - require("gitlab").pipeline() - end, { desc = "View Pipeline" }) - end, -} diff --git a/lua/plugins/gitsigns.lua b/lua/plugins/gitsigns.lua deleted file mode 100644 index a4167ca..0000000 --- a/lua/plugins/gitsigns.lua +++ /dev/null @@ -1,34 +0,0 @@ -return { - "lewis6991/gitsigns.nvim", - event = { "BufReadPre", "BufNewFile" }, - config = function() - require("gitsigns").setup({ - signs = { - add = { text = "๐Ÿคฏ" }, - change = { text = "๐Ÿซฃ" }, - delete = { text = "โŒ" }, - topdelete = { text = "" }, - changedelete = { text = "โ–Ž" }, - untracked = { text = "โฐ" }, - }, - signcolumn = true, - current_line_blame = true, - current_line_blame_opts = { - virt_text = true, - virt_text_pos = "right_align", - delay = 1000, - ignore_whitespace = false, - virt_text_priority = 100, - use_focus = true, - }, - current_line_blame_formatter = ", - ", - watch_gitdir = { - follow_files = true, - }, - auto_attach = true, - attach_to_untracked = false, - sign_priority = 6, - update_debounce = 100, - }) - end, -} diff --git a/lua/plugins/go-nvim.lua b/lua/plugins/go-nvim.lua deleted file mode 100644 index d21c1ea..0000000 --- a/lua/plugins/go-nvim.lua +++ /dev/null @@ -1,64 +0,0 @@ -return { - { - -- Go tools - "ray-x/go.nvim", - dependencies = { - "ray-x/guihua.lua", - "neovim/nvim-lspconfig", - "nvim-treesitter/nvim-treesitter", - }, - config = function() - require("go").setup({ - goimport = "gopls", - gofmt = "gofumpt", - max_line_len = 120, - tag_transform = false, - test_template = "", - test_template_dir = "", - comment_placeholder = " ", - -- Let nvim-lspconfig own gopls so settings live in one place. - lsp_cfg = false, - lsp_gofumpt = true, - lsp_on_attach = false, - lsp_keymaps = false, - lsp_codelens = true, - diagnostic = { - hdlr = false, - underline = true, - virtual_text = { space = 0, prefix = "" }, - signs = true, - update_in_insert = false, - }, - lsp_document_formatting = false, -- Let conform.nvim handle formatting - lsp_inlay_hints = { - enable = true, - only_current_line = false, - only_current_line_autocmd = "CursorHold", - show_variable_name = true, - parameter_hints_prefix = "๓ฐŠ• ", - show_parameter_hints = true, - other_hints_prefix = "=> ", - }, - trouble = true, - test_runner = "go", - verbose_tests = true, - run_in_floaterm = false, - luasnip = false, - iferr_vertical_shift = 4, - }) - - -- Keymaps (using G to avoid conflict with git) - vim.keymap.set("n", "Gsj", "GoAddTag json", { desc = "Add JSON tags" }) - vim.keymap.set("n", "Gsy", "GoAddTag yaml", { desc = "Add YAML tags" }) - vim.keymap.set("n", "Gsr", "GoRMTag", { desc = "Remove tags" }) - vim.keymap.set("n", "Gsf", "GoFillStruct", { desc = "Fill struct" }) - vim.keymap.set("n", "Gse", "GoIfErr", { desc = "Add if err" }) - vim.keymap.set("n", "Gch", "GoCoverage", { desc = "Test coverage" }) - vim.keymap.set("n", "Gcc", "GoCoverageToggle", { desc = "Toggle coverage" }) - vim.keymap.set("n", "Gcb", "GoCoverageBrowser", { desc = "Coverage browser" }) - end, - event = { "CmdlineEnter" }, - ft = { "go", "gomod" }, - build = ':lua require("go.install").update_all_sync()', - }, -} diff --git a/lua/plugins/harpoon.lua b/lua/plugins/harpoon.lua deleted file mode 100644 index ba49f5d..0000000 --- a/lua/plugins/harpoon.lua +++ /dev/null @@ -1,37 +0,0 @@ -return { - "ThePrimeagen/harpoon", - branch = "harpoon2", - dependencies = { "nvim-lua/plenary.nvim" }, - event = "VeryLazy", - config = function() - local harpoon = require("harpoon") - harpoon:setup({}) - - vim.keymap.set("n", "ha", function() - harpoon:list():add() - end, { desc = "Add to harpoon" }) - vim.keymap.set("n", "he", function() - harpoon.ui:toggle_quick_menu(harpoon:list()) - end, { desc = "Harpoon menu" }) - - vim.keymap.set("n", "h1", function() - harpoon:list():select(1) - end, { desc = "Harpoon 1" }) - vim.keymap.set("n", "h2", function() - harpoon:list():select(2) - end, { desc = "Harpoon 2" }) - vim.keymap.set("n", "h3", function() - harpoon:list():select(3) - end, { desc = "Harpoon 3" }) - vim.keymap.set("n", "h4", function() - harpoon:list():select(4) - end, { desc = "Harpoon 4" }) - - vim.keymap.set("n", "", function() - harpoon:list():prev() - end, { desc = "Harpoon prev" }) - vim.keymap.set("n", "", function() - harpoon:list():next() - end, { desc = "Harpoon next" }) - end, -} diff --git a/lua/plugins/kulala.lua b/lua/plugins/kulala.lua deleted file mode 100644 index 812f007..0000000 --- a/lua/plugins/kulala.lua +++ /dev/null @@ -1,24 +0,0 @@ -return { - { - -- REST client - "mistweaverco/kulala.nvim", - config = function() - require("kulala").setup({ - default_view = "body", - default_env = "dev", - debug = false, - }) - - -- Keymaps (using R for REST to avoid conflict with run/tasks) - vim.keymap.set("n", "Rr", "lua require('kulala').run()", { desc = "Run REST request" }) - vim.keymap.set("n", "Rp", "lua require('kulala').preview()", { desc = "Preview REST request" }) - vim.keymap.set( - "n", - "Rl", - "lua require('kulala').replay()", - { desc = "Replay last REST request" } - ) - vim.keymap.set("n", "Ri", "lua require('kulala').inspect()", { desc = "Inspect REST request" }) - end, - }, -} diff --git a/lua/plugins/lsp_signature.lua b/lua/plugins/lsp_signature.lua deleted file mode 100644 index 8fb0f85..0000000 --- a/lua/plugins/lsp_signature.lua +++ /dev/null @@ -1,47 +0,0 @@ -return { - { - -- Enhanced signature help - "ray-x/lsp_signature.nvim", - event = "LspAttach", - config = function() - require("lsp_signature").setup({ - bind = true, - doc_lines = 10, - max_height = 12, - max_width = 80, - wrap = true, - floating_window = true, - floating_window_above_cur_line = true, - floating_window_off_x = 1, - floating_window_off_y = 0, - close_timeout = 4000, - fix_pos = false, - hint_enable = true, - hint_prefix = "๐Ÿผ ", - hint_scheme = "String", - hi_parameter = "LspSignatureActiveParameter", - handler_opts = { - border = "rounded", - }, - always_trigger = false, - auto_close_after = nil, - extra_trigger_chars = {}, - zindex = 200, - padding = " ", - transparency = nil, - shadow_blend = 36, - shadow_guibg = "Black", - timer_interval = 200, - toggle_key = nil, - select_signature_key = nil, - move_cursor_key = nil, - -- Filter out terminal buffers to prevent URI errors - filter = function(bufnr) - local buftype = vim.bo[bufnr].buftype - local filetype = vim.bo[bufnr].filetype - return buftype ~= "terminal" and filetype ~= "toggleterm" - end, - }) - end, - }, -} diff --git a/lua/plugins/lspconfig.lua b/lua/plugins/lspconfig.lua deleted file mode 100644 index db8c69c..0000000 --- a/lua/plugins/lspconfig.lua +++ /dev/null @@ -1,247 +0,0 @@ -return { - "neovim/nvim-lspconfig", - dependencies = { - "saghen/blink.cmp", - "b0o/schemastore.nvim", - }, - config = function() - vim.lsp.log.set_level("WARN") - - -- Truncate LSP log if it exceeds 10 MB - local log_path = vim.lsp.log.get_filename() - local stat = vim.uv.fs_stat(log_path) - if stat and stat.size > 10 * 1024 * 1024 then - os.remove(log_path) - end - - local lsp_capabilities = require("blink.cmp").get_lsp_capabilities() - - -- Apply blink capabilities to all LSP servers - vim.lsp.config("*", { - capabilities = lsp_capabilities, - }) - - -- Lua language server configuration - vim.lsp.config("lua_ls", { - root_markers = { ".luarc.json", ".luarc.jsonc", ".luacheckrc", ".stylua.toml", "stylua.toml", ".git" }, - settings = { - Lua = { - runtime = { - version = "LuaJIT", - }, - diagnostics = { - globals = { - "love", - "vim", - }, - }, - workspace = { - checkThirdParty = false, - library = { - vim.env.VIMRUNTIME, - }, - }, - telemetry = { - enable = false, - }, - completion = { - callSnippet = "Replace", - }, - }, - }, - }) - - -- Terraform / HCL language server - vim.lsp.config("terraformls", { - filetypes = { "terraform", "terraform-vars", "tf", "hcl" }, - root_markers = { ".terraform", ".git" }, - }) - - -- Markdown language server (links, headings, references, completion) - vim.lsp.config("marksman", { - filetypes = { "markdown", "markdown.mdx" }, - root_markers = { ".marksman.toml", ".git" }, - }) - - -- JSON language server with SchemaStore (package.json, tsconfig, gh actions...) - vim.lsp.config("jsonls", { - filetypes = { "json", "jsonc" }, - settings = { - json = { - schemas = require("schemastore").json.schemas(), - validate = { enable = true }, - }, - }, - }) - - -- Pyright owns Python type checking - vim.lsp.config("pyright", { - settings = { - python = { - analysis = { - typeCheckingMode = "basic", - autoSearchPaths = true, - useLibraryCodeForTypes = true, - diagnosticMode = "openFilesOnly", - }, - }, - }, - }) - - -- Go language server - vim.lsp.config("gopls", { - root_markers = { "go.work", "go.mod", ".git" }, - settings = { - gopls = { - gofumpt = true, - staticcheck = true, - usePlaceholders = true, - completeUnimported = true, - experimentalPostfixCompletions = true, - analyses = { - unusedparams = true, - unusedwrite = true, - useany = true, - nilness = true, - shadow = true, - }, - codelenses = { - gc_details = true, - generate = true, - regenerate_cgo = true, - test = true, - tidy = true, - upgrade_dependency = true, - vendor = true, - }, - hints = { - assignVariableTypes = true, - compositeLiteralFields = true, - compositeLiteralTypes = true, - constantValues = true, - functionTypeParameters = true, - parameterNames = true, - rangeVariableTypes = true, - }, - semanticTokens = true, - }, - }, - }) - - vim.lsp.enable({ "lua_ls", "pyright", "gopls", "terraformls", "marksman", "jsonls" }) - - -- Diagnostic configuration - vim.diagnostic.config({ - signs = { - text = { - [vim.diagnostic.severity.ERROR] = " ", - [vim.diagnostic.severity.WARN] = " ", - [vim.diagnostic.severity.INFO] = " ", - [vim.diagnostic.severity.HINT] = "๓ฐŒต ", - }, - }, - virtual_text = { - prefix = "", - spacing = 2, - }, - underline = true, - update_in_insert = false, - severity_sort = true, - float = { - source = true, - border = "rounded", - }, - }) - - -- Single LspAttach autocmd for all LSP-related setup - vim.api.nvim_create_autocmd("LspAttach", { - desc = "LSP actions", - callback = function(event) - local client = vim.lsp.get_client_by_id(event.data.client_id) - local bufnr = event.buf - - -- Enable inlay hints if supported - if client and client:supports_method("textDocument/inlayHint") then - vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) - end - - local bufmap = function(mode, lhs, rhs, desc) - vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc }) - end - - -- Navigation - bufmap("n", "gd", "lua vim.lsp.buf.definition()", "Go to definition") - bufmap("n", "gD", "lua vim.lsp.buf.declaration()", "Go to declaration") - bufmap("n", "gi", "lua vim.lsp.buf.implementation()", "Go to implementation") - bufmap("n", "go", "lua vim.lsp.buf.type_definition()", "Go to type definition") - bufmap("n", "gr", "lua vim.lsp.buf.references()", "List references") - bufmap("n", "gs", "lua vim.lsp.buf.signature_help()", "Signature help") - - -- Actions - bufmap("n", "", "lua vim.lsp.buf.rename()", "Rename symbol") - bufmap("n", "", "lua vim.lsp.buf.code_action()", "Code action") - - -- Hover: LSP hover, falls back to diagnostic float if no hover info - bufmap("n", "K", function() - local has_diag = #vim.diagnostic.get(bufnr, { lnum = vim.fn.line(".") - 1 }) > 0 - local clients = vim.lsp.get_clients({ bufnr = bufnr, method = "textDocument/hover" }) - if #clients > 0 then - vim.lsp.buf.hover({ border = "rounded" }) - elseif has_diag then - vim.diagnostic.open_float({ border = "rounded" }) - end - end, "Hover / diagnostic") - - -- Diagnostics - bufmap("n", "gl", "lua vim.diagnostic.open_float()", "Show diagnostics") - bufmap("n", "[d", function() - vim.diagnostic.jump({ count = -1 }) - end, "Previous diagnostic") - bufmap("n", "]d", function() - vim.diagnostic.jump({ count = 1 }) - end, "Next diagnostic") - - -- Document symbols (outline view) - bufmap("n", "ls", function() - Snacks.picker.lsp_symbols() - end, "Document symbols") - - -- Workspace symbols (project-wide symbol search) - bufmap("n", "lw", function() - Snacks.picker.lsp_workspace_symbols() - end, "Workspace symbols") - - -- Code lens - bufmap("n", "cl", "lua vim.lsp.codelens.run()", "Run code lens") - bufmap("n", "cL", "lua vim.lsp.codelens.refresh()", "Refresh code lens") - - -- Debug LSP info - bufmap("n", "li", function() - local clients = vim.lsp.get_clients({ bufnr = bufnr }) - if #clients == 0 then - vim.notify("No LSP clients attached to this buffer", vim.log.levels.INFO) - return - end - - local info = {} - for _, c in pairs(clients) do - local capabilities = {} - if c:supports_method("textDocument/rename") then - table.insert(capabilities, "rename") - end - if c:supports_method("textDocument/codeAction") then - table.insert(capabilities, "code_action") - end - if c:supports_method("textDocument/hover") then - table.insert(capabilities, "hover") - end - - table.insert(info, string.format("%s: %s", c.name, table.concat(capabilities, ", "))) - end - - vim.notify("LSP Clients:\n" .. table.concat(info, "\n"), vim.log.levels.INFO) - end, "LSP info") - end, - }) - end, -} diff --git a/lua/plugins/lspkind.lua b/lua/plugins/lspkind.lua deleted file mode 100644 index 4811cdf..0000000 --- a/lua/plugins/lspkind.lua +++ /dev/null @@ -1,66 +0,0 @@ -return { - "onsails/lspkind.nvim", - event = "LspAttach", - config = function() - require("lspkind").init({ - mode = "symbol_text", - preset = "codicons", - symbol_map = { - Text = "๓ฐ‰ฟ", - Method = "๓ฐ†ง ", - Function = "๓ฐŠ• ", - Constructor = " ", - Field = " ", - Variable = "๓ฐ†ง ", - Class = "๓ฐ ฑ", - Interface = "๓ฐ•˜", - Module = "", - Property = " ", - Unit = "๓ฐ‘ญ", - Value = "๓ฐŽ ", - Enum = "๓ฐ•˜", - Keyword = "๓ฐŒ‹", - Snippet = "", - Color = "๓ฐ˜", - File = "๓ฐˆ™", - Reference = "๓ฐˆ‡", - Folder = "๓ฐ‰‹", - EnumMember = " ", - Constant = "๓ฐฟ ", - Struct = "๓ฐŒ— ", - Event = " ", - Operator = "๓ฐ†• ", - TypeParameter = "๓ฐŠ„ ", - -- Terraform specific - Resource = "๓ฑ‡ถ", - DataSource = "๓ฐ ถ", - Provider = "๓ฐ…ถ", - -- Additional types - Namespace = "๓ฐŒ—", - Package = " ", - String = "๓ฐ€ฌ ", - Number = "๓ฐŽ  ", - Boolean = "โ—ฉ ", - Array = "๓ฐ…ช ", - Object = "๓ฐ…ฉ ", - Key = "๓ฐŒ‹ ", - Null = "๓ฐŸข ", - }, - menu = { - lua = "[Lua]", - python = "[Python]", - javascript = "[JS]", - typescript = "[TS]", - go = "[Go]", - terraform = "[Terraform]", - json = "[JSON]", - yaml = "[YAML]", - sh = "[Shell]", - bash = "[Bash]", - html = "[HTML]", - css = "[CSS]", - markdown = "[MD]", - }, - }) - end, -} diff --git a/lua/plugins/lualine.lua b/lua/plugins/lualine.lua deleted file mode 100644 index 5aa55f2..0000000 --- a/lua/plugins/lualine.lua +++ /dev/null @@ -1,77 +0,0 @@ -return { - "nvim-lualine/lualine.nvim", - event = "VeryLazy", - config = function() - local function lsp_status() - local clients = vim.lsp.get_clients({ bufnr = 0 }) - if #clients == 0 then - return "No LSP" - end - local names = {} - for _, client in pairs(clients) do - table.insert(names, client.name) - end - return " " .. table.concat(names, ", ") - end - - local function python_env() - if vim.bo.filetype == "python" then - local venv = os.getenv("VIRTUAL_ENV") - if venv then - return " " .. vim.fn.fnamemodify(venv, ":t") - end - end - return "" - end - - require("lualine").setup({ - options = { - icons_enabled = true, - theme = "auto", - component_separators = { left = "", right = "" }, - section_separators = { left = "", right = "" }, - disabled_filetypes = { - statusline = {}, - winbar = {}, - }, - ignore_focus = {}, - always_divide_middle = true, - globalstatus = true, - refresh = { - statusline = 1000, - tabline = 1000, - winbar = 1000, - }, - }, - sections = { - lualine_a = { "mode" }, - lualine_b = { "branch", "diff" }, - lualine_c = { - { "filename", path = 1 }, - { python_env, color = { fg = "#98be65" } }, - }, - lualine_x = { - "diagnostics", - { lsp_status, color = { fg = "#51afef" } }, - "encoding", - "fileformat", - "filetype", - }, - lualine_y = { "progress" }, - lualine_z = { "location" }, - }, - inactive_sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = { "filename" }, - lualine_x = { "location" }, - lualine_y = {}, - lualine_z = {}, - }, - tabline = {}, - winbar = {}, - inactive_winbar = {}, - extensions = {}, - }) - end, -} diff --git a/lua/plugins/mason-lspconfig.lua b/lua/plugins/mason-lspconfig.lua deleted file mode 100644 index 84ba8cf..0000000 --- a/lua/plugins/mason-lspconfig.lua +++ /dev/null @@ -1,18 +0,0 @@ -return { - "mason-org/mason-lspconfig.nvim", - dependencies = { - { "mason-org/mason.nvim", opts = {} }, - "neovim/nvim-lspconfig", - }, - opts = { - ensure_installed = { - "codebook", - "gopls", - "lua_ls", - "pyright", - "terraformls", - "tflint", - "tofu_ls", - }, - }, -} diff --git a/lua/plugins/mason-tool-installer.lua b/lua/plugins/mason-tool-installer.lua deleted file mode 100644 index 17f4cb8..0000000 --- a/lua/plugins/mason-tool-installer.lua +++ /dev/null @@ -1,51 +0,0 @@ -return { - "WhoIsSethDaniel/mason-tool-installer.nvim", - dependencies = { "mason-org/mason.nvim" }, - event = { "VeryLazy" }, - config = function() - require("mason-tool-installer").setup({ - ensure_installed = { - -- Go - "gofumpt", - "goimports", - "golangci-lint", - "delve", - "gomodifytags", - "impl", - "iferr", - "gotests", - - -- Python - "ruff", - "black", - - -- Lua - "stylua", - "luacheck", - - -- Shell - "shfmt", - "shellcheck", - - -- Web / config - "prettier", - "yamlfmt", - "yamllint", - "jsonlint", - "markdownlint", - - -- Terraform - "tflint", - "tfsec", - - -- Misc - "hadolint", - "codespell", - }, - auto_update = false, - run_on_start = true, - start_delay = 3000, - debounce_hours = 24, - }) - end, -} diff --git a/lua/plugins/mason.lua b/lua/plugins/mason.lua deleted file mode 100644 index 646f567..0000000 --- a/lua/plugins/mason.lua +++ /dev/null @@ -1,15 +0,0 @@ -return { - "mason-org/mason.nvim", - config = function() - require("mason").setup({ - ui = { - border = "rounded", - icons = { - package_installed = "โœ“", - package_pending = "โžœ", - package_uninstalled = "โœ—", - }, - }, - }) - end, -} diff --git a/lua/plugins/neotest.lua b/lua/plugins/neotest.lua deleted file mode 100644 index dcf9a34..0000000 --- a/lua/plugins/neotest.lua +++ /dev/null @@ -1,169 +0,0 @@ -return { - "nvim-neotest/neotest", - dependencies = { - "nvim-neotest/nvim-nio", - "nvim-lua/plenary.nvim", - "nvim-treesitter/nvim-treesitter", - "nvim-neotest/neotest-python", - "fredrikaverpil/neotest-golang", - "jfpedroza/neotest-elixir", - "nvim-neotest/neotest-jest", - "rouge8/neotest-rust", - }, - config = function() - require("neotest").setup({ - adapters = { - require("neotest-python")({ - dap = { justMyCode = false }, - args = { "--log-level", "DEBUG" }, - runner = "pytest", - python = "python3", - }), - require("neotest-golang")({ - go_test_args = { "-v", "-race", "-count=1", "-timeout=60s" }, - dap_go_enabled = true, - runner = "go", - }), - require("neotest-elixir")({ - mix_task = "test", - }), - require("neotest-jest")({ - jestCommand = "npm test --", - jestConfigFile = "jest.config.js", - env = { CI = true }, - cwd = function(path) - return vim.fn.getcwd() - end, - }), - require("neotest-rust")({ - args = { "--no-capture" }, - dap_adapter = "lldb", - }), - }, - discovery = { - concurrent = 1, - enabled = true, - }, - diagnostic = { - enabled = true, - severity = 1, - }, - floating = { - border = "rounded", - max_height = 0.6, - max_width = 0.6, - options = {}, - }, - highlights = { - adapter_name = "NeotestAdapterName", - border = "NeotestBorder", - dir = "NeotestDir", - expand_marker = "NeotestExpandMarker", - failed = "NeotestFailed", - file = "NeotestFile", - focused = "NeotestFocused", - indent = "NeotestIndent", - marked = "NeotestMarked", - namespace = "NeotestNamespace", - passed = "NeotestPassed", - running = "NeotestRunning", - select_win = "NeotestWinSelect", - skipped = "NeotestSkipped", - target = "NeotestTarget", - test = "NeotestTest", - unknown = "NeotestUnknown", - }, - icons = { - child_indent = "โ”‚", - child_prefix = "โ”œ", - collapsed = "โ”€", - expanded = "โ•ฎ", - failed = "", - final_child_indent = " ", - final_child_prefix = "โ•ฐ", - non_collapsible = "โ”€", - passed = "", - running = "", - running_animated = { "/", "|", "\\", "-", "/", "|", "\\", "-" }, - skipped = "", - unknown = "", - }, - output = { - enabled = true, - open_on_run = "short", - }, - output_panel = { - enabled = true, - open = "botright split | resize 15", - }, - run = { - enabled = true, - }, - running = { - concurrent = true, - }, - summary = { - enabled = true, - animated = true, - follow = true, - expand_errors = true, - mappings = { - attach = "a", - clear_marked = "M", - clear_target = "T", - debug = "d", - debug_marked = "D", - expand = { "", "<2-LeftMouse>" }, - expand_all = "e", - help = "?", - jumpto = "i", - mark = "m", - next_failed = "J", - output = "o", - prev_failed = "K", - run = "r", - run_marked = "R", - short = "O", - stop = "u", - target = "t", - watch = "w", - }, - open = "botright vsplit | vertical resize 50", - }, - watch = { - enabled = true, - symbol_queries = { - python = "class", - go = "(method_declaration) @symbol", - elixir = "(call) @symbol", - javascript = "(function_declaration) @symbol", - }, - }, - }) - - vim.keymap.set("n", "tn", function() - require("neotest").run.run() - end, { desc = "Run nearest test" }) - vim.keymap.set("n", "tF", function() - require("neotest").run.run(vim.fn.expand("%")) - end, { desc = "Run tests in file" }) - vim.keymap.set("n", "ta", function() - require("neotest").run.run(vim.fn.getcwd()) - end, { desc = "Run all tests" }) - vim.keymap.set("n", "ts", function() - require("neotest").summary.toggle() - end, { desc = "Toggle test summary" }) - vim.keymap.set("n", "to", function() - require("neotest").output.open({ enter = true, auto_close = true }) - end, { desc = "Show test output" }) - vim.keymap.set("n", "tO", function() - require("neotest").output_panel.toggle() - end, { desc = "Toggle test output panel" }) - vim.keymap.set("n", "tw", function() - require("neotest").watch.toggle(vim.fn.expand("%")) - end, { desc = "Watch tests" }) - vim.keymap.set("n", "td", function() - require("neotest").run.run({ strategy = "dap" }) - end, { desc = "Debug nearest test" }) - end, -} diff --git a/lua/plugins/nvim-autopairs.lua b/lua/plugins/nvim-autopairs.lua deleted file mode 100644 index 625f04e..0000000 --- a/lua/plugins/nvim-autopairs.lua +++ /dev/null @@ -1,30 +0,0 @@ -return { - "windwp/nvim-autopairs", - event = { "InsertEnter" }, - dependencies = { - "saghen/blink.cmp", - }, - config = function() - require("nvim-autopairs").setup({ - check_ts = true, - ts_config = { - lua = { "string", "source" }, - javascript = { "string", "template_string" }, - java = false, - }, - disable_filetype = { "TelescopePrompt", "spectre_panel" }, - disable_in_macro = true, - disable_in_visualblock = false, - disable_in_replace_mode = true, - enable_moveright = true, - enable_afterquote = true, - enable_check_bracket_line = false, - enable_bracket_in_quote = true, - enable_abbr = false, - break_undo = true, - map_bs = true, - map_c_h = false, - map_c_w = false, - }) - end, -} diff --git a/lua/plugins/nvim-colorizer.lua b/lua/plugins/nvim-colorizer.lua deleted file mode 100644 index 270e593..0000000 --- a/lua/plugins/nvim-colorizer.lua +++ /dev/null @@ -1,23 +0,0 @@ -return { - "NvChad/nvim-colorizer.lua", - event = "BufReadPre", - opts = { - filetypes = { "*" }, - user_default_options = { - RGB = true, - RRGGBB = true, - names = true, - RRGGBBAA = true, - AARRGGBB = false, - rgb_fn = true, - hsl_fn = true, - css = true, - css_fn = true, - mode = "background", - tailwind = true, - sass = { enable = true, parsers = { "css" } }, - virtualtext = "โ– ", - }, - buftypes = {}, - }, -} diff --git a/lua/plugins/nvim-coverage.lua b/lua/plugins/nvim-coverage.lua deleted file mode 100644 index a5d60dd..0000000 --- a/lua/plugins/nvim-coverage.lua +++ /dev/null @@ -1,46 +0,0 @@ -return { - "andythigpen/nvim-coverage", - dependencies = { "nvim-lua/plenary.nvim" }, - cmd = { "Coverage", "CoverageToggle", "CoverageSummary", "CoverageLoad" }, - config = function() - require("coverage").setup({ - commands = true, - highlights = { - covered = { fg = "#C3E88D" }, - uncovered = { fg = "#F07178" }, - partial = { fg = "#AA71FF" }, - }, - signs = { - covered = { hl = "CoverageCovered", text = "โ–Ž" }, - uncovered = { hl = "CoverageUncovered", text = "โ–Ž" }, - partial = { hl = "CoveragePartial", text = "โ–Ž" }, - }, - summary = { - min_coverage = 80.0, - }, - lang = { - python = { - coverage_command = "coverage json --fail-under=0 -q -o -", - coverage_file = "coverage.json", - }, - go = { - coverage_file = "coverage.out", - coverage_command = "go test -coverprofile=coverage.out -coverpkg=./... ./...", - }, - javascript = { - coverage_command = "cat coverage/lcov-report/index.html | grep -o '\\\"decimal\\\">[^<]*' | head -n 4", - }, - }, - auto_reload = true, - load_coverage_cb = function(ftype) - vim.notify("Loaded " .. ftype .. " coverage") - end, - }) - - vim.keymap.set("n", "cov", "Coverage", { desc = "Show coverage" }) - vim.keymap.set("n", "coh", "CoverageHide", { desc = "Hide coverage" }) - vim.keymap.set("n", "cos", "CoverageSummary", { desc = "Coverage summary" }) - vim.keymap.set("n", "cot", "CoverageToggle", { desc = "Toggle coverage" }) - vim.keymap.set("n", "col", "CoverageLoad", { desc = "Load coverage" }) - end, -} diff --git a/lua/plugins/nvim-dap-go.lua b/lua/plugins/nvim-dap-go.lua deleted file mode 100644 index 9769375..0000000 --- a/lua/plugins/nvim-dap-go.lua +++ /dev/null @@ -1,25 +0,0 @@ -return { - { - "leoluz/nvim-dap-go", - ft = "go", - dependencies = { - "mfussenegger/nvim-dap", - "rcarriga/nvim-dap-ui", - }, - config = function() - require("dap-go").setup({ - delve = { - -- Increase timeout for slow CI/large repos - initialize_timeout_sec = 20, - }, - }) - - vim.keymap.set("n", "dgt", function() - require("dap-go").debug_test() - end, { desc = "Debug Go test" }) - vim.keymap.set("n", "dgl", function() - require("dap-go").debug_last_test() - end, { desc = "Debug last Go test" }) - end, - }, -} diff --git a/lua/plugins/nvim-dap-python.lua b/lua/plugins/nvim-dap-python.lua deleted file mode 100644 index bbbb13f..0000000 --- a/lua/plugins/nvim-dap-python.lua +++ /dev/null @@ -1,42 +0,0 @@ -return { - { - "mfussenegger/nvim-dap-python", - ft = "python", - dependencies = { - "mfussenegger/nvim-dap", - "rcarriga/nvim-dap-ui", - }, - config = function() - require("dap-python").setup("python3") - - -- Python-specific configurations - local dap = require("dap") - - -- Add pytest runner - table.insert(dap.configurations.python, { - type = "python", - request = "launch", - name = "Run pytest", - module = "pytest", - args = { "${workspaceFolder}" }, - console = "integratedTerminal", - justMyCode = false, - }) - - -- Add Flask debug config - table.insert(dap.configurations.python, { - type = "python", - request = "launch", - name = "Flask Debug", - program = "${workspaceFolder}/app.py", - env = { FLASK_ENV = "development" }, - console = "integratedTerminal", - justMyCode = false, - }) - - vim.keymap.set("n", "dpr", function() - require("dap-python").test_method() - end, { desc = "Debug Python test method" }) - end, - }, -} diff --git a/lua/plugins/nvim-dap.lua b/lua/plugins/nvim-dap.lua deleted file mode 100644 index a2f4641..0000000 --- a/lua/plugins/nvim-dap.lua +++ /dev/null @@ -1,39 +0,0 @@ -return { - "mfussenegger/nvim-dap", - cmd = { "DapContinue", "DapToggleBreakpoint" }, - keys = { - { "db", desc = "Toggle Breakpoint" }, - { "dc", desc = "Continue/Start Debugging" }, - }, - dependencies = { - "rcarriga/nvim-dap-ui", - "nvim-neotest/nvim-nio", - }, - config = function() - local dap = require("dap") - local dapui = require("dapui") - - dapui.setup() - - -- Auto open/close dapui - dap.listeners.after.event_initialized["dapui_config"] = function() - dapui.open() - end - dap.listeners.before.event_terminated["dapui_config"] = function() - dapui.close() - end - dap.listeners.before.event_exited["dapui_config"] = function() - dapui.close() - end - - vim.keymap.set("n", "db", dap.toggle_breakpoint, { desc = "Toggle Breakpoint" }) - vim.keymap.set("n", "dc", dap.continue, { desc = "Continue/Start Debugging" }) - vim.keymap.set("n", "di", dap.step_into, { desc = "Step Into" }) - vim.keymap.set("n", "do", dap.step_over, { desc = "Step Over" }) - vim.keymap.set("n", "dO", dap.step_out, { desc = "Step Out" }) - vim.keymap.set("n", "dr", dap.repl.toggle, { desc = "Toggle REPL" }) - vim.keymap.set("n", "dl", dap.run_last, { desc = "Run Last" }) - vim.keymap.set("n", "dt", dap.terminate, { desc = "Terminate" }) - vim.keymap.set("n", "du", dapui.toggle, { desc = "Toggle DAP UI" }) - end, -} diff --git a/lua/plugins/nvim-jqx.lua b/lua/plugins/nvim-jqx.lua deleted file mode 100644 index a0df918..0000000 --- a/lua/plugins/nvim-jqx.lua +++ /dev/null @@ -1,10 +0,0 @@ -return { - { - "gennaro-tedesco/nvim-jqx", - ft = { "json", "yaml" }, - config = function() - vim.keymap.set("n", "jq", "JqxList", { desc = "JQ query list" }) - vim.keymap.set("n", "jf", "JqxQuery", { desc = "JQ query" }) - end, - }, -} diff --git a/lua/plugins/nvim-lint.lua b/lua/plugins/nvim-lint.lua deleted file mode 100644 index b4da0d5..0000000 --- a/lua/plugins/nvim-lint.lua +++ /dev/null @@ -1,43 +0,0 @@ -return { - { - -- Code metrics and complexity analysis - "mfussenegger/nvim-lint", - event = { "BufReadPost", "BufNewFile" }, - config = function() - require("lint").linters_by_ft = { - python = { "ruff" }, - javascript = { "eslint" }, - typescript = { "eslint" }, - go = { "golangcilint" }, - terraform = { "tflint", "tfsec" }, - yaml = { "yamllint" }, - json = { "jsonlint" }, - bash = { "shellcheck" }, - sh = { "shellcheck" }, - dockerfile = { "hadolint" }, - elixir = { "credo" }, - } - - -- Conditional Lua linting (skip Love2D projects) - local function should_lint_lua() - local cwd = vim.fn.getcwd() - return not (vim.fn.filereadable(cwd .. "/main.lua") == 1 or vim.fn.filereadable(cwd .. "/conf.lua") == 1) - end - - -- Auto-run linting - vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, { - callback = function() - if vim.bo.filetype == "lua" and should_lint_lua() then - require("lint").try_lint("luacheck") - else - require("lint").try_lint() - end - end, - }) - - vim.keymap.set("n", "xr", function() - require("lint").try_lint() - end, { desc = "Run linting" }) - end, - }, -} diff --git a/lua/plugins/nvim-man.lua b/lua/plugins/nvim-man.lua deleted file mode 100644 index cfea431..0000000 --- a/lua/plugins/nvim-man.lua +++ /dev/null @@ -1,3 +0,0 @@ -return { - "paretje/nvim-man", -} diff --git a/lua/plugins/nvim-navic.lua b/lua/plugins/nvim-navic.lua deleted file mode 100644 index d0a68b4..0000000 --- a/lua/plugins/nvim-navic.lua +++ /dev/null @@ -1,69 +0,0 @@ -return { - "SmiteshP/nvim-navic", - event = "LspAttach", - config = function() - local navic = require("nvim-navic") - navic.setup({ - icons = { - File = "๓ฐˆ™ ", - Module = " ", - Namespace = "๓ฐŒ— ", - Package = " ", - Class = "๓ฐŒ— ", - Method = "๓ฐ†ง ", - Property = " ", - Field = " ", - Constructor = " ", - Enum = "๓ฐ•˜", - Interface = "๓ฐ•˜", - Function = "๓ฐŠ• ", - Variable = "๓ฐ†ง ", - Constant = "๓ฐฟ ", - String = "๓ฐ€ฌ ", - Number = "๓ฐŽ  ", - Boolean = "โ—ฉ ", - Array = "๓ฐ…ช ", - Object = "๓ฐ…ฉ ", - Key = "๓ฐŒ‹ ", - Null = "๓ฐŸข ", - EnumMember = " ", - Struct = "๓ฐŒ— ", - Event = " ", - Operator = "๓ฐ†• ", - TypeParameter = "๓ฐŠ„ ", - }, - lsp = { - auto_attach = true, - preference = nil, - }, - highlight = true, - separator = " > ", - depth_limit = 0, - depth_limit_indicator = "..", - safe_output = true, - lazy_update_context = false, - click = false, - }) - - -- Attach navic to LSP - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - if client and client.server_capabilities.documentSymbolProvider then - navic.attach(client, args.buf) - end - end, - }) - - -- Show breadcrumbs in winbar - vim.api.nvim_create_autocmd({ "BufEnter", "CursorMoved" }, { - callback = function() - if navic.is_available() then - vim.wo.winbar = "%{%v:lua.require'nvim-navic'.get_location()%}" - else - vim.wo.winbar = "" - end - end, - }) - end, -} diff --git a/lua/plugins/nvim-origami.lua b/lua/plugins/nvim-origami.lua deleted file mode 100644 index aa01ed2..0000000 --- a/lua/plugins/nvim-origami.lua +++ /dev/null @@ -1,98 +0,0 @@ -return { - "chrisgrieser/nvim-origami", - event = "VeryLazy", - keys = { - { "z1", desc = "Fold level 1" }, - { "z2", desc = "Fold level 2" }, - { "z3", desc = "Fold level 3" }, - { "z4", desc = "Fold level 4" }, - { "z5", desc = "Fold level 5" }, - { "zP", desc = "Pick fold" }, - }, - init = function() - -- disable vim's auto-folding (recommended by origami) - vim.o.foldcolumn = "1" - vim.o.foldlevel = 99 - vim.o.foldlevelstart = 99 - vim.o.foldenable = true - end, - opts = { - useLspFoldsWithTreesitterFallback = { - enabled = true, - foldmethodIfNeitherIsAvailable = "indent", - }, - pauseFoldsOnSearch = true, - foldtext = { - enabled = true, - padding = { character = " ", width = 3 }, - lineCount = { - template = " %d lines", - hlgroup = "Comment", - }, - diagnosticsCount = true, - gitsignsCount = true, - }, - autoFold = { - enabled = true, - kinds = { "comment", "imports" }, - }, - foldKeymaps = { - setup = true, -- h/l/^/$ become fold-aware at line edges - closeOnlyOnFirstColumn = false, - scrollLeftOnCaret = false, - }, - }, - config = function(_, opts) - require("origami").setup(opts) - - -- Quick fold-level shortcuts: z1..z5 set foldlevel - for i = 1, 5 do - vim.keymap.set("n", "z" .. i, function() - vim.o.foldlevel = i - end, { desc = "Fold level " .. i }) - end - - -- Snacks picker: list every fold in the current buffer, jump on confirm - vim.keymap.set("n", "zP", function() - local ok, Snacks = pcall(require, "snacks") - if not ok then - vim.notify("snacks.nvim not available", vim.log.levels.WARN) - return - end - - local bufnr = vim.api.nvim_get_current_buf() - local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) - local items = {} - for lnum = 1, #lines do - local fs = vim.fn.foldlevel(lnum) - local prev = lnum > 1 and vim.fn.foldlevel(lnum - 1) or 0 - if fs > 0 and fs > prev then - local text = lines[lnum] - table.insert(items, { - text = string.format("%4d %s%s", lnum, string.rep(" ", fs - 1), text), - file = vim.api.nvim_buf_get_name(bufnr), - pos = { lnum, 0 }, - }) - end - end - - if #items == 0 then - vim.notify("No folds in buffer", vim.log.levels.INFO) - return - end - - Snacks.picker.pick({ - title = "Folds", - items = items, - format = "text", - confirm = function(picker, item) - picker:close() - if item then - vim.api.nvim_win_set_cursor(0, item.pos) - vim.cmd("normal! zv") - end - end, - }) - end, { desc = "Pick fold" }) - end, -} diff --git a/lua/plugins/nvim-silicon.lua b/lua/plugins/nvim-silicon.lua deleted file mode 100644 index 1ea9506..0000000 --- a/lua/plugins/nvim-silicon.lua +++ /dev/null @@ -1,29 +0,0 @@ -return { - "michaelrommel/nvim-silicon", - lazy = true, - cmd = "Silicon", - config = function() - require("silicon").setup({ - -- font = "JetBrainsMono Nerd Font=34;Noto Color Emoji=34", - theme = "Dracula", - background = "#AAAAFF", - shadow_color = "#555555", - line_pad = 2, - pad_horiz = 80, - pad_vert = 100, - shadow_blur_radius = 0, - shadow_offset_x = 0, - shadow_offset_y = 0, - line_number = false, -- Use false to avoid --no-line-number flag - round_corner = false, -- Use false to avoid --no-round-corner flag - window_controls = false, -- Use false to avoid --no-window-controls flag - output = function() - return "~/Pictures/silicon-" .. os.date("%Y-%m-%d-%H%M%S") .. ".png" - end, - debug = false, - }) - - vim.keymap.set("v", "sc", ":Silicon", { desc = "Screenshot code" }) - vim.keymap.set("n", "sc", ":Silicon", { desc = "Screenshot code" }) - end, -} diff --git a/lua/plugins/nvim-surround.lua b/lua/plugins/nvim-surround.lua deleted file mode 100644 index e7c5cd7..0000000 --- a/lua/plugins/nvim-surround.lua +++ /dev/null @@ -1,6 +0,0 @@ -return { - "kylechui/nvim-surround", - version = "^3.0.0", - event = "VeryLazy", - opts = {}, -} diff --git a/lua/plugins/nvim-treesitter-textobjects.lua b/lua/plugins/nvim-treesitter-textobjects.lua deleted file mode 100644 index c3f35ed..0000000 --- a/lua/plugins/nvim-treesitter-textobjects.lua +++ /dev/null @@ -1,117 +0,0 @@ -return { - "nvim-treesitter/nvim-treesitter-textobjects", - branch = "main", - dependencies = { "nvim-treesitter/nvim-treesitter" }, - init = function() - vim.g.no_plugin_maps = true - end, - config = function() - require("nvim-treesitter-textobjects").setup({ - select = { - lookahead = true, - selection_modes = { - ["@parameter.outer"] = "v", - ["@function.outer"] = "V", - ["@class.outer"] = "", - }, - include_surrounding_whitespace = true, - }, - move = { - set_jumps = true, - }, - }) - - -- Select keymaps - local select = require("nvim-treesitter-textobjects.select") - vim.keymap.set({ "x", "o" }, "af", function() - select.select_textobject("@function.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "if", function() - select.select_textobject("@function.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ac", function() - select.select_textobject("@class.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ic", function() - select.select_textobject("@class.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "aa", function() - select.select_textobject("@parameter.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ia", function() - select.select_textobject("@parameter.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ab", function() - select.select_textobject("@block.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ib", function() - select.select_textobject("@block.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "al", function() - select.select_textobject("@loop.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "il", function() - select.select_textobject("@loop.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ai", function() - select.select_textobject("@conditional.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ii", function() - select.select_textobject("@conditional.inner", "textobjects") - end) - - -- Move keymaps - local move = require("nvim-treesitter-textobjects.move") - vim.keymap.set({ "n", "x", "o" }, "]m", function() - move.goto_next_start("@function.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "]]", function() - move.goto_next_start("@class.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "]a", function() - move.goto_next_start("@parameter.inner", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "]M", function() - move.goto_next_end("@function.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "][", function() - move.goto_next_end("@class.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "]A", function() - move.goto_next_end("@parameter.inner", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[m", function() - move.goto_previous_start("@function.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[[", function() - move.goto_previous_start("@class.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[a", function() - move.goto_previous_start("@parameter.inner", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[M", function() - move.goto_previous_end("@function.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[]", function() - move.goto_previous_end("@class.outer", "textobjects") - end) - vim.keymap.set({ "n", "x", "o" }, "[A", function() - move.goto_previous_end("@parameter.inner", "textobjects") - end) - - -- Swap keymaps - local swap = require("nvim-treesitter-textobjects.swap") - vim.keymap.set("n", "]p", function() - swap.swap_next("@parameter.inner") - end) - vim.keymap.set("n", "]s", function() - swap.swap_next("@function.outer") - end) - vim.keymap.set("n", "[p", function() - swap.swap_previous("@parameter.inner") - end) - vim.keymap.set("n", "[s", function() - swap.swap_previous("@function.outer") - end) - end, -} diff --git a/lua/plugins/nvim-ufo.lua b/lua/plugins/nvim-ufo.lua deleted file mode 100644 index abb4ab9..0000000 --- a/lua/plugins/nvim-ufo.lua +++ /dev/null @@ -1,112 +0,0 @@ -return { - "kevinhwang91/nvim-ufo", - enabled = false, -- trying nvim-origami instead; flip to true to switch back - dependencies = "kevinhwang91/promise-async", - event = { "BufReadPost", "BufNewFile" }, - keys = { - { "zR", desc = "Open all folds" }, - { "zM", desc = "Close all folds" }, - { "zr", desc = "Open folds except kinds" }, - { "zm", desc = "Close folds with" }, - { "z1", desc = "Fold level 1" }, - { "z2", desc = "Fold level 2" }, - { "z3", desc = "Fold level 3" }, - { "z4", desc = "Fold level 4" }, - { "z5", desc = "Fold level 5" }, - { "zP", desc = "Pick fold" }, - }, - init = function() - -- Fold options must be set before ufo loads so folds work on first buffer - vim.o.foldcolumn = "1" - vim.o.foldlevel = 99 - vim.o.foldlevelstart = 99 - vim.o.foldenable = true - end, - config = function() - require("ufo").setup({ - provider_selector = function(bufnr, filetype, buftype) - return { "treesitter", "indent" } - end, - open_fold_hl_timeout = 150, - close_fold_kinds_for_ft = { - default = { "imports", "comment" }, - json = { "array" }, - c = { "comment", "region" }, - }, - preview = { - win_config = { - border = { "", "โ”€", "", "", "", "โ”€", "", "" }, - winhighlight = "Normal:Folded", - winblend = 0, - }, - mappings = { - scrollU = "", - scrollD = "", - jumpTop = "[", - jumpBot = "]", - }, - }, - }) - - vim.keymap.set("n", "zR", require("ufo").openAllFolds, { desc = "Open all folds" }) - vim.keymap.set("n", "zM", require("ufo").closeAllFolds, { desc = "Close all folds" }) - vim.keymap.set("n", "zr", require("ufo").openFoldsExceptKinds, { desc = "Open folds except kinds" }) - vim.keymap.set("n", "zm", require("ufo").closeFoldsWith, { desc = "Close folds with" }) - vim.keymap.set("n", "K", function() - local winid = require("ufo").peekFoldedLinesUnderCursor() - if not winid then - vim.lsp.buf.hover({ border = "rounded" }) - end - end, { desc = "Peek fold or hover" }) - - -- Quick fold-level shortcuts: z1..z5 set foldlevel and close deeper folds - for i = 1, 5 do - vim.keymap.set("n", "z" .. i, function() - require("ufo").closeFoldsWith(i) - end, { desc = "Fold level " .. i }) - end - - -- Snacks picker: list every fold in the current buffer, jump on confirm - vim.keymap.set("n", "zP", function() - local ok, Snacks = pcall(require, "snacks") - if not ok then - vim.notify("snacks.nvim not available", vim.log.levels.WARN) - return - end - - local bufnr = vim.api.nvim_get_current_buf() - local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) - local items = {} - for lnum = 1, #lines do - local fs = vim.fn.foldlevel(lnum) - local prev = lnum > 1 and vim.fn.foldlevel(lnum - 1) or 0 - if fs > 0 and fs > prev then - local text = lines[lnum] - table.insert(items, { - text = string.format("%4d %s%s", lnum, string.rep(" ", fs - 1), text), - file = vim.api.nvim_buf_get_name(bufnr), - pos = { lnum, 0 }, - }) - end - end - - if #items == 0 then - vim.notify("No folds in buffer", vim.log.levels.INFO) - return - end - - Snacks.picker.pick({ - title = "Folds", - items = items, - format = "text", - confirm = function(picker, item) - picker:close() - if item then - vim.api.nvim_win_set_cursor(0, item.pos) - vim.cmd("normal! zv") - end - end, - }) - end, { desc = "Pick fold" }) - end, -} diff --git a/lua/plugins/nvim-web-devicons.lua b/lua/plugins/nvim-web-devicons.lua deleted file mode 100644 index 7b84802..0000000 --- a/lua/plugins/nvim-web-devicons.lua +++ /dev/null @@ -1,4 +0,0 @@ -return { - "nvim-tree/nvim-web-devicons", - lazy = true, -} diff --git a/lua/plugins/octo.lua b/lua/plugins/octo.lua deleted file mode 100644 index 4940148..0000000 --- a/lua/plugins/octo.lua +++ /dev/null @@ -1,280 +0,0 @@ -return { - "pwntester/octo.nvim", - dependencies = { - "nvim-lua/plenary.nvim", - "folke/snacks.nvim", - "nvim-tree/nvim-web-devicons", - }, - event = "VeryLazy", - config = function() - require("octo").setup({ - picker = "snacks", - default_remote = { "upstream", "origin" }, - default_delete_branch = true, - default_merge_method = "squash", - reaction_viewer_hint_icon = "", - user_icon = "๐Ÿฆซ ", - timeline_marker = "", - timeline_indent = 2, - right_bubble_delimiter = "", - left_bubble_delimiter = "", - snippet_context_lines = 4, - timeout = 5000, - picker_config = { - use_emojis = true, - }, - ui = { - use_signcolumn = true, - use_signstatus = true, - }, - issues = { - order_by = { - field = "CREATED_AT", - direction = "DESC", - }, - }, - pull_requests = { - order_by = { - field = "CREATED_AT", - direction = "DESC", - }, - always_select_remote_on_create = false, - }, - file_panel = { - size = 10, - icons = true, - }, - mappings_disable_default = false, - mappings = { - issue = { - close_issue = { lhs = "ic", desc = "close issue" }, - reopen_issue = { lhs = "io", desc = "reopen issue" }, - list_issues = { lhs = "il", desc = "list open issues" }, - reload = { lhs = "", desc = "reload issue" }, - open_in_browser = { lhs = "", desc = "open issue in browser" }, - copy_url = { lhs = "", desc = "copy url to system clipboard" }, - add_assignee = { lhs = "aa", desc = "add assignee" }, - remove_assignee = { lhs = "ad", desc = "remove assignee" }, - create_label = { lhs = "lc", desc = "create label" }, - add_label = { lhs = "la", desc = "add label" }, - remove_label = { lhs = "ld", desc = "remove label" }, - goto_issue = { lhs = "gi", desc = "navigate to a local repo issue" }, - add_comment = { lhs = "ca", desc = "add comment" }, - delete_comment = { lhs = "cd", desc = "delete comment" }, - next_comment = { lhs = "]c", desc = "go to next comment" }, - prev_comment = { lhs = "[c", desc = "go to previous comment" }, - react_hooray = { lhs = "rp", desc = "add/remove ๐ŸŽ‰ reaction" }, - react_heart = { lhs = "rh", desc = "add/remove โค๏ธ reaction" }, - react_eyes = { lhs = "re", desc = "add/remove ๐Ÿ‘€ reaction" }, - react_thumbs_up = { lhs = "r+", desc = "add/remove ๐Ÿ‘ reaction" }, - react_thumbs_down = { lhs = "r-", desc = "add/remove ๐Ÿ‘Ž reaction" }, - react_rocket = { lhs = "rr", desc = "add/remove ๐Ÿš€ reaction" }, - react_laugh = { lhs = "rl", desc = "add/remove ๐Ÿ˜„ reaction" }, - react_confused = { lhs = "rc", desc = "add/remove ๐Ÿ˜• reaction" }, - }, - pull_request = { - checkout_pr = { lhs = "po", desc = "checkout PR" }, - merge_pr = { lhs = "pm", desc = "merge commit PR" }, - squash_and_merge_pr = { lhs = "psm", desc = "squash and merge PR" }, - rebase_and_merge_pr = { lhs = "prm", desc = "rebase and merge PR" }, - list_commits = { lhs = "pc", desc = "list PR commits" }, - list_changed_files = { lhs = "pf", desc = "list PR changed files" }, - show_pr_diff = { lhs = "pd", desc = "show PR diff" }, - add_reviewer = { lhs = "va", desc = "add reviewer" }, - remove_reviewer = { lhs = "vd", desc = "remove reviewer request" }, - close_pr = { lhs = "pic", desc = "close PR" }, - reopen_pr = { lhs = "pio", desc = "reopen PR" }, - list_prs = { lhs = "pl", desc = "list open PRs" }, - reload = { lhs = "", desc = "reload PR" }, - open_in_browser = { lhs = "", desc = "open PR in browser" }, - copy_url = { lhs = "", desc = "copy url to system clipboard" }, - goto_file = { lhs = "gf", desc = "go to file" }, - add_assignee = { lhs = "aa", desc = "add assignee" }, - remove_assignee = { lhs = "ad", desc = "remove assignee" }, - create_label = { lhs = "lc", desc = "create label" }, - add_label = { lhs = "la", desc = "add label" }, - remove_label = { lhs = "ld", desc = "remove label" }, - goto_issue = { lhs = "gi", desc = "navigate to a local repo issue" }, - add_comment = { lhs = "ca", desc = "add comment" }, - delete_comment = { lhs = "cd", desc = "delete comment" }, - next_comment = { lhs = "]c", desc = "go to next comment" }, - prev_comment = { lhs = "[c", desc = "go to previous comment" }, - react_hooray = { lhs = "rp", desc = "add/remove ๐ŸŽ‰ reaction" }, - react_heart = { lhs = "rh", desc = "add/remove โค๏ธ reaction" }, - react_eyes = { lhs = "re", desc = "add/remove ๐Ÿ‘€ reaction" }, - react_thumbs_up = { lhs = "r+", desc = "add/remove ๐Ÿ‘ reaction" }, - react_thumbs_down = { lhs = "r-", desc = "add/remove ๐Ÿ‘Ž reaction" }, - react_rocket = { lhs = "rr", desc = "add/remove ๐Ÿš€ reaction" }, - react_laugh = { lhs = "rl", desc = "add/remove ๐Ÿ˜„ reaction" }, - react_confused = { lhs = "rc", desc = "add/remove ๐Ÿ˜• reaction" }, - review_start = { lhs = "vs", desc = "start a review for the current PR" }, - review_resume = { lhs = "vr", desc = "resume a pending review for the current PR" }, - }, - review_thread = { - goto_issue = { lhs = "gi", desc = "navigate to a local repo issue" }, - add_comment = { lhs = "ca", desc = "add comment" }, - add_suggestion = { lhs = "sa", desc = "add suggestion" }, - delete_comment = { lhs = "cd", desc = "delete comment" }, - next_comment = { lhs = "]c", desc = "go to next comment" }, - prev_comment = { lhs = "[c", desc = "go to previous comment" }, - select_next_entry = { lhs = "]q", desc = "move to previous changed file" }, - select_prev_entry = { lhs = "[q", desc = "move to next changed file" }, - close_review_tab = { lhs = "", desc = "close review tab" }, - react_hooray = { lhs = "rp", desc = "add/remove ๐ŸŽ‰ reaction" }, - react_heart = { lhs = "rh", desc = "add/remove โค๏ธ reaction" }, - react_eyes = { lhs = "re", desc = "add/remove ๐Ÿ‘€ reaction" }, - react_thumbs_up = { lhs = "r+", desc = "add/remove ๐Ÿ‘ reaction" }, - react_thumbs_down = { lhs = "r-", desc = "add/remove ๐Ÿ‘Ž reaction" }, - react_rocket = { lhs = "rr", desc = "add/remove ๐Ÿš€ reaction" }, - react_laugh = { lhs = "rl", desc = "add/remove ๐Ÿ˜„ reaction" }, - react_confused = { lhs = "rc", desc = "add/remove ๐Ÿ˜• reaction" }, - }, - submit_win = { - approve_review = { lhs = "", desc = "approve review" }, - comment_review = { lhs = "", desc = "comment review" }, - request_changes = { lhs = "", desc = "request changes review" }, - close_review_tab = { lhs = "", desc = "close review tab" }, - }, - review_diff = { - submit_review = { lhs = "vs", desc = "submit review" }, - discard_review = { lhs = "vd", desc = "discard review" }, - add_review_comment = { lhs = "ca", desc = "add a new review comment" }, - add_review_suggestion = { lhs = "sa", desc = "add a new review suggestion" }, - focus_files = { lhs = "e", desc = "move focus to changed file panel" }, - toggle_files = { lhs = "b", desc = "hide/show changed files panel" }, - next_thread = { lhs = "]t", desc = "move to next thread" }, - prev_thread = { lhs = "[t", desc = "move to previous thread" }, - select_next_entry = { lhs = "]q", desc = "move to previous changed file" }, - select_prev_entry = { lhs = "[q", desc = "move to next changed file" }, - close_review_tab = { lhs = "", desc = "close review tab" }, - toggle_viewed = { lhs = "", desc = "toggle viewer viewed state" }, - goto_file = { lhs = "gf", desc = "go to file" }, - }, - file_panel = { - submit_review = { lhs = "vs", desc = "submit review" }, - discard_review = { lhs = "vd", desc = "discard review" }, - next_entry = { lhs = "j", desc = "move to next changed file" }, - prev_entry = { lhs = "k", desc = "move to previous changed file" }, - select_entry = { lhs = "", desc = "show selected changed file diffs" }, - refresh_files = { lhs = "R", desc = "refresh changed files panel" }, - focus_files = { lhs = "e", desc = "move focus to changed file panel" }, - toggle_files = { lhs = "b", desc = "hide/show changed files panel" }, - select_next_entry = { lhs = "]q", desc = "move to previous changed file" }, - select_prev_entry = { lhs = "[q", desc = "move to next changed file" }, - close_review_tab = { lhs = "", desc = "close review tab" }, - toggle_viewed = { lhs = "", desc = "toggle viewer viewed state" }, - }, - }, - }) - - local git_repo = require("utils.git_repo") - - -- PR/MR creation with a template (context-aware: GitHub via octo, GitLab via gitlab.nvim). - -- gitlab.nvim's create_mr() picks a template from .gitlab/merge_request_templates/ - -- when no description is provided. - vim.keymap.set("n", "gPt", function() - if git_repo.is_gitlab() then - require("gitlab").create_mr() - else - vim.cmd("Octo pr create --template") - end - end, { desc = "Create PR/MR with Template" }) - - -- Draft PR/MR creation (context-aware). gitlab.nvim has no draft flag, so we - -- use GitLab's "Draft:" title-prefix convention. - vim.keymap.set("n", "gPD", function() - if git_repo.is_gitlab() then - local title = vim.fn.input("Draft MR Title: ") - if title == nil or title == "" then - return - end - require("gitlab").create_mr({ title = "Draft: " .. title }) - else - vim.cmd("Octo pr create --draft") - end - end, { desc = "Create Draft PR/MR" }) - - -- Issue management - vim.keymap.set("n", "gIl", ":Octo issue list", { desc = "List Issues" }) - vim.keymap.set("n", "gIn", ":Octo issue create", { desc = "New Issue" }) - vim.keymap.set("n", "gIo", ":Octo issue", { desc = "Open Issue" }) - vim.keymap.set("n", "gIs", ":Octo issue search", { desc = "Search Issues" }) - - -- Repository management - vim.keymap.set("n", "gRl", ":Octo repo list", { desc = "List Repos" }) - vim.keymap.set("n", "gRf", ":Octo repo fork", { desc = "Fork Repo" }) - vim.keymap.set("n", "gRb", ":Octo repo browser", { desc = "Open Repo in Browser" }) - - -- Quick checkout (moved to avoid gco conflict) - vim.keymap.set("n", "gCo", ":Octo pr checkout", { desc = "Checkout PR" }) - - -- Smart PR/MR creation using a conventional-commit generated description. - vim.keymap.set("n", "gPn", function() - local branch = vim.fn.system("git branch --show-current"):gsub("\n", "") - print("Creating PR/MR for branch: " .. branch) - - local description, err = require("pr-description").generate_description({ is_gitlab = git_repo.is_gitlab() }) - if err then - print("โŒ " .. err) - return - end - - local remote_check = vim.fn.system("git ls-remote --heads origin " .. branch .. " 2>/dev/null") - if remote_check == "" then - print("Branch not pushed to remote. Pushing now...") - local push_result = vim.fn.system("git push -u origin " .. branch) - if vim.v.shell_error ~= 0 then - print("โŒ Failed to push branch:") - print(push_result) - return - end - print("โœ… Branch pushed to remote") - end - - -- GitLab: create the MR via gitlab.nvim, pre-filling the generated description. - if git_repo.is_gitlab() then - local title = vim.fn.input("MR Title: ") - if title == nil or title == "" then - return - end - require("gitlab").create_mr({ title = title, description = description }) - return - end - - local title = vim.fn.input("PR Title: ") - if title and title ~= "" then - local temp_file = "/tmp/pr_body_" .. os.time() .. ".md" - local file = io.open(temp_file, "w") - if file then - file:write(description) - file:close() - - local cmd = string.format( - 'gh pr create --title "%s" --body-file "%s" --head %s --base main', - title:gsub('"', '\\"'), - temp_file, - branch - ) - print("Running: " .. cmd) - - local result = vim.fn.system(cmd) - local exit_code = vim.v.shell_error - os.remove(temp_file) - - if exit_code == 0 then - print("โœ… PR created successfully!") - print(result) - else - print("โŒ PR creation failed:") - print(result) - end - else - print("โŒ Failed to create temp file for PR body") - end - end - end, { desc = "New PR/MR with Conventional Commits" }) - - -- Note: gPg (Generate PR/MR Description) is defined in gitlab.lua - -- with is_gitlab_repo() detection to handle both GitHub and GitLab - end, -} diff --git a/lua/plugins/overseer.lua b/lua/plugins/overseer.lua deleted file mode 100644 index 5632bd7..0000000 --- a/lua/plugins/overseer.lua +++ /dev/null @@ -1,266 +0,0 @@ -return { - "stevearc/overseer.nvim", - cmd = { "OverseerRun", "OverseerToggle", "OverseerQuickAction", "OverseerBuild", "OverseerClearCache" }, - keys = { - { "Or", desc = "Run task" }, - { "Ot", desc = "Toggle task list" }, - }, - config = function() - require("overseer").setup({ - templates = { "builtin" }, - strategy = { - "terminal", - }, - component_aliases = { - default = { - { "display_duration", detail_level = 2 }, - "on_output_summarize", - "on_exit_set_status", - "on_complete_notify", - "on_complete_dispose", - }, - }, - bundles = { - autostart_on_load = true, - save_task_opts = { - bundleable = true, - }, - }, - task_list = { - direction = "bottom", - min_height = 25, - max_height = 25, - default_detail = 1, - bindings = { - ["?"] = "ShowHelp", - ["g?"] = "ShowHelp", - [""] = "RunAction", - [""] = "Edit", - ["o"] = "Open", - [""] = "OpenVsplit", - [""] = "OpenSplit", - [""] = "OpenFloat", - [""] = "OpenQuickFix", - ["p"] = "TogglePreview", - [""] = "IncreaseDetail", - [""] = "DecreaseDetail", - ["L"] = "IncreaseAllDetail", - ["H"] = "DecreaseAllDetail", - ["["] = "DecreaseWidth", - ["]"] = "IncreaseWidth", - ["{"] = "PrevTask", - ["}"] = "NextTask", - [""] = "ScrollOutputUp", - [""] = "ScrollOutputDown", - ["q"] = "Close", - }, - }, - }) - - -- Task templates - require("overseer").register_template({ - name = "run_script", - builder = function() - local file = vim.fn.expand("%:p") - local cmd = { file } - if vim.bo.filetype == "python" then - cmd = { "python", file } - elseif vim.bo.filetype == "sh" then - cmd = { "bash", file } - end - return { - cmd = cmd, - components = { { "on_output_quickfix", open = true }, "default" }, - } - end, - condition = { - filetype = { "sh", "python", "javascript" }, - }, - }) - - -- Terraform plan template - require("overseer").register_template({ - name = "terraform_plan", - builder = function() - return { - cmd = { "terraform", "plan" }, - components = { { "on_output_quickfix", open = true }, "default" }, - cwd = vim.fn.getcwd(), - } - end, - condition = { - callback = function() - return vim.fn.filereadable("main.tf") == 1 or vim.fn.filereadable("terraform.tf") == 1 - end, - }, - }) - - -- Terraform apply template - require("overseer").register_template({ - name = "terraform_apply", - builder = function() - return { - cmd = { "terraform", "apply", "-auto-approve" }, - components = { { "on_output_quickfix", open = true }, "default" }, - cwd = vim.fn.getcwd(), - } - end, - condition = { - callback = function() - return vim.fn.filereadable("main.tf") == 1 or vim.fn.filereadable("terraform.tf") == 1 - end, - }, - }) - - -- Python test template - require("overseer").register_template({ - name = "pytest", - builder = function() - return { - cmd = { "python", "-m", "pytest", "-v" }, - components = { { "on_output_quickfix", open = true }, "default" }, - cwd = vim.fn.getcwd(), - } - end, - condition = { - callback = function() - return vim.fn.filereadable("pytest.ini") == 1 or vim.fn.filereadable("pyproject.toml") == 1 - end, - }, - }) - - -- Helper function to parse trivy output and set quickfix - local function parse_trivy_output(lines) - local qf_list = {} - - for _, line in ipairs(lines) do - if line and line ~= "" then - -- Simple approach: look for lines that contain file paths and issues - if line:find("%.tf") or line:find("%.yaml") or line:find("%.yml") then - local file = line:match("([^%s]+%.t?f?)") or line:match("([^%s]+%.ya?ml)") - if file then - table.insert(qf_list, { - filename = vim.fn.fnamemodify(file, ":p"), - lnum = 1, - col = 1, - text = line:gsub("^%s*", ""):gsub("%s+", " "), - type = line:find("HIGH") and "E" or line:find("MEDIUM") and "W" or "I", - }) - end - end - end - end - - vim.fn.setqflist(qf_list, "r") - if #qf_list > 0 then - vim.cmd("copen") - end - end - - -- Helper function to parse tfsec output and set quickfix - local function parse_tfsec_output(lines) - local qf_list = {} - - for _, line in ipairs(lines) do - if line and line ~= "" then - -- Look for file paths with line numbers - local file, lnum = line:match("([^%s:]+%.tf):?(%d*)") - if file then - table.insert(qf_list, { - filename = vim.fn.fnamemodify(file, ":p"), - lnum = tonumber(lnum) or 1, - col = 1, - text = line:gsub("^%s*", ""):gsub("%s+", " "), - type = line:find("HIGH") and "E" or line:find("MEDIUM") and "W" or "I", - }) - end - end - end - - vim.fn.setqflist(qf_list, "r") - if #qf_list > 0 then - vim.cmd("copen") - end - end - - -- Simple vim commands for security scans - vim.api.nvim_create_user_command("TrivyScan", function() - local cwd = vim.fn.getcwd() - -- Use current buffer's directory if it's a file, otherwise use cwd - local current_file = vim.fn.expand("%:p") - if current_file and current_file ~= "" then - cwd = vim.fn.fnamemodify(current_file, ":h") - end - local output = {} - vim.fn.jobstart({ "trivy", "fs", "--format", "table", "." }, { - cwd = cwd, - stdout_buffered = true, - on_stdout = function(_, data) - if data then - vim.list_extend(output, data) - end - end, - on_exit = function(_, code) - if #output > 0 then - parse_trivy_output(output) - end - end, - }) - end, {}) - - vim.api.nvim_create_user_command("TfsecScan", function() - local cwd = vim.fn.getcwd() - -- Use current buffer's directory if it's a file, otherwise use cwd - local current_file = vim.fn.expand("%:p") - if current_file and current_file ~= "" then - cwd = vim.fn.fnamemodify(current_file, ":h") - end - local output = {} - vim.fn.jobstart({ "tfsec", ".", "--format", "default", "--no-color" }, { - cwd = cwd, - stdout_buffered = true, - on_stdout = function(_, data) - if data then - vim.list_extend(output, data) - end - end, - on_exit = function(_, code) - if #output > 0 then - parse_tfsec_output(output) - end - end, - }) - end, {}) - - vim.keymap.set("n", "Or", "OverseerRun", { desc = "Run task" }) - vim.keymap.set("n", "Ot", "OverseerToggle", { desc = "Toggle task list" }) - vim.keymap.set("n", "Oa", "OverseerQuickAction", { desc = "Quick action" }) - vim.keymap.set("n", "Ob", "OverseerBuild", { desc = "Build task" }) - vim.keymap.set("n", "Oc", "OverseerClearCache", { desc = "Clear cache" }) - - -- Security scanning shortcuts - vim.keymap.set("n", "Ost", "TrivyScan", { desc = "Run trivy security scan" }) - vim.keymap.set("n", "Osf", "TfsecScan", { desc = "Run tfsec Terraform scan" }) - - -- Debug commands to see raw output - vim.api.nvim_create_user_command("TrivyDebug", function() - local cwd = vim.fn.getcwd() - local current_file = vim.fn.expand("%:p") - if current_file and current_file ~= "" then - cwd = vim.fn.fnamemodify(current_file, ":h") - end - vim.cmd("lcd " .. vim.fn.fnameescape(cwd)) - vim.cmd("term trivy fs --format table .") - end, {}) - - vim.api.nvim_create_user_command("TfsecDebug", function() - local cwd = vim.fn.getcwd() - local current_file = vim.fn.expand("%:p") - if current_file and current_file ~= "" then - cwd = vim.fn.fnamemodify(current_file, ":h") - end - vim.cmd("lcd " .. vim.fn.fnameescape(cwd)) - vim.cmd("term tfsec . --format default --no-color") - end, {}) - end, -} diff --git a/lua/plugins/package-info.lua b/lua/plugins/package-info.lua deleted file mode 100644 index 98b6437..0000000 --- a/lua/plugins/package-info.lua +++ /dev/null @@ -1,70 +0,0 @@ -return { - { - -- Dependency analysis - "vuki656/package-info.nvim", - dependencies = { "MunifTanjim/nui.nvim" }, - event = { "BufRead package.json" }, - config = function() - require("package-info").setup({ - highlight = { - up_to_date = "#3C4048", - outdated = "#d19a66", - }, - icons = { - enable = true, - style = { - up_to_date = "| ", - outdated = "| ", - }, - }, - autostart = true, - hide_up_to_date = false, - hide_unstable_versions = false, - package_manager = "npm", - }) - - vim.keymap.set( - "n", - "ns", - require("package-info").show, - { desc = "Show dependency versions", silent = true } - ) - vim.keymap.set( - "n", - "nc", - require("package-info").hide, - { desc = "Hide dependency versions", silent = true } - ) - vim.keymap.set( - "n", - "nT", - require("package-info").toggle, - { desc = "Toggle dependency versions", silent = true } - ) - vim.keymap.set( - "n", - "nu", - require("package-info").update, - { desc = "Update dependency on line", silent = true } - ) - vim.keymap.set( - "n", - "nd", - require("package-info").delete, - { desc = "Delete dependency on line", silent = true } - ) - vim.keymap.set( - "n", - "ni", - require("package-info").install, - { desc = "Install new dependency", silent = true } - ) - vim.keymap.set( - "n", - "np", - require("package-info").change_version, - { desc = "Change dependency version", silent = true } - ) - end, - }, -} diff --git a/lua/plugins/pr-description.lua b/lua/plugins/pr-description.lua deleted file mode 100644 index 68cc88d..0000000 --- a/lua/plugins/pr-description.lua +++ /dev/null @@ -1,5 +0,0 @@ -return { - "remoterabbit/pr-description.nvim", - cmd = { "PRDescription", "MRDescription" }, - opts = {}, -} diff --git a/lua/plugins/profile.lua b/lua/plugins/profile.lua deleted file mode 100644 index 86ac26e..0000000 --- a/lua/plugins/profile.lua +++ /dev/null @@ -1,32 +0,0 @@ -return { - -- Performance profiling for Lua - "stevearc/profile.nvim", - config = function() - local should_profile = os.getenv("NVIM_PROFILE") - if should_profile then - require("profile").instrument_autocmds() - if should_profile:lower():match("^start") then - require("profile").start("*") - else - require("profile").instrument("*") - end - end - - local function toggle_profile() - local prof = require("profile") - if prof.is_recording() then - prof.stop() - vim.ui.input({ prompt = "Save profile to:", completion = "file", default = "profile.json" }, function(filename) - if filename then - prof.export(filename) - vim.notify(string.format("Wrote %s", filename)) - end - end) - else - prof.start("*") - end - end - - vim.keymap.set("n", "pp", toggle_profile, { desc = "Toggle profiling" }) - end, -} diff --git a/lua/plugins/refactoring.lua b/lua/plugins/refactoring.lua deleted file mode 100644 index f992bd3..0000000 --- a/lua/plugins/refactoring.lua +++ /dev/null @@ -1,110 +0,0 @@ -return { - "ThePrimeagen/refactoring.nvim", - dependencies = { - "nvim-lua/plenary.nvim", - "nvim-treesitter/nvim-treesitter", - }, - keys = { - { - "re", - function() - require("refactoring").refactor("Extract Function") - end, - mode = "x", - desc = "Extract Function", - }, - { - "rf", - function() - require("refactoring").refactor("Extract Function To File") - end, - mode = "x", - desc = "Extract Function To File", - }, - { - "rv", - function() - require("refactoring").refactor("Extract Variable") - end, - mode = "x", - desc = "Extract Variable", - }, - { - "ri", - function() - require("refactoring").refactor("Inline Variable") - end, - mode = { "n", "x" }, - desc = "Inline Variable", - }, - { - "rb", - function() - require("refactoring").refactor("Extract Block") - end, - mode = "x", - desc = "Extract Block", - }, - { - "rbf", - function() - require("refactoring").refactor("Extract Block To File") - end, - mode = "x", - desc = "Extract Block To File", - }, - { - "rr", - function() - require("refactoring").select_refactor() - end, - mode = { "n", "x" }, - desc = "Select Refactor", - }, - { - "rp", - function() - require("refactoring").debug.printf({ below = false }) - end, - mode = "n", - desc = "Debug Print", - }, - { - "rc", - function() - require("refactoring").debug.cleanup({}) - end, - mode = "n", - desc = "Debug Cleanup", - }, - }, - opts = { - prompt_func_return_type = { - go = false, - java = false, - cpp = false, - c = false, - h = false, - hpp = false, - cxx = false, - }, - prompt_func_param_type = { - go = false, - java = false, - cpp = false, - c = false, - h = false, - hpp = false, - cxx = false, - }, - printf_statements = {}, - print_var_statements = {}, - show_success_message = true, -- shows a message with information about the refactor on success - }, - config = function(_, opts) - require("refactoring").setup(opts) - - -- Additional convenience mappings - vim.keymap.set("n", "rn", vim.lsp.buf.rename, { desc = "LSP Rename" }) - end, -} diff --git a/lua/plugins/render-markdown.lua b/lua/plugins/render-markdown.lua deleted file mode 100644 index d5d68d9..0000000 --- a/lua/plugins/render-markdown.lua +++ /dev/null @@ -1,147 +0,0 @@ -return { - "MeanderingProgrammer/render-markdown.nvim", - dependencies = { - "nvim-treesitter/nvim-treesitter", - "echasnovski/mini.nvim", -- for icons - }, - enabled = true, - ft = { "markdown" }, - opts = { - heading = { - enabled = true, - sign = true, - icons = { "๓ฐฒก ", "๓ฐฒฃ ", "๓ฐฒฅ ", "๓ฐฒง ", "๓ฐฒฉ ", "๓ฐฒซ " }, - position = "overlay", - width = "full", - left_margin = 0, - left_pad = 0, - right_pad = 0, - min_width = 0, - border = false, - border_virtual = false, - above = "โ–„", - below = "โ–€", - backgrounds = { - "RenderMarkdownH1Bg", - "RenderMarkdownH2Bg", - "RenderMarkdownH3Bg", - "RenderMarkdownH4Bg", - "RenderMarkdownH5Bg", - "RenderMarkdownH6Bg", - }, - foregrounds = { - "RenderMarkdownH1", - "RenderMarkdownH2", - "RenderMarkdownH3", - "RenderMarkdownH4", - "RenderMarkdownH5", - "RenderMarkdownH6", - }, - }, - paragraph = { - enabled = true, - left_margin = 0, - min_width = 0, - }, - code = { - enabled = true, - sign = false, - style = "full", - position = "left", - language_pad = 0, - disable_background = { "diff" }, - width = "full", - left_margin = 0, - left_pad = 0, - right_pad = 0, - min_width = 0, - border = "thin", - above = "โ–„", - below = "โ–€", - highlight = "RenderMarkdownCode", - highlight_inline = "RenderMarkdownCodeInline", - }, - dash = { - enabled = true, - icon = "โ”€", - width = "full", - highlight = "RenderMarkdownDash", - }, - bullet = { - enabled = true, - icons = { "โ—", "โ—‹", "โ—†", "โ—‡" }, - left_pad = 0, - right_pad = 0, - highlight = "RenderMarkdownBullet", - }, - checkbox = { - enabled = true, - unchecked = { - icon = "๓ฐ„ฑ ", - highlight = "RenderMarkdownUnchecked", - }, - checked = { - icon = "๓ฐฑ’ ", - highlight = "RenderMarkdownChecked", - }, - custom = { - todo = { raw = "[-]", rendered = "๓ฐฅ” ", highlight = "RenderMarkdownTodo" }, - }, - }, - quote = { - enabled = true, - icon = "โ–‹", - repeat_linebreak = false, - highlight = "RenderMarkdownQuote", - }, - pipe_table = { - enabled = true, - preset = "none", - style = "full", - cell = "padded", - min_width = 0, - border = { - "โ”Œ", - "โ”ฌ", - "โ”", - "โ”œ", - "โ”ผ", - "โ”ค", - "โ””", - "โ”ด", - "โ”˜", - "โ”‚", - "โ”€", - }, - alignment_indicator = "โ”", - head = "RenderMarkdownTableHead", - row = "RenderMarkdownTableRow", - }, - callout = { - note = { raw = "[!NOTE]", rendered = "๓ฐ‹ฝ Note", highlight = "RenderMarkdownInfo" }, - tip = { raw = "[!TIP]", rendered = "๓ฐŒถ Tip", highlight = "RenderMarkdownSuccess" }, - important = { raw = "[!IMPORTANT]", rendered = "๓ฐ…พ Important", highlight = "RenderMarkdownHint" }, - warning = { raw = "[!WARNING]", rendered = "๓ฐ€ช Warning", highlight = "RenderMarkdownWarn" }, - caution = { raw = "[!CAUTION]", rendered = "๓ฐณฆ Caution", highlight = "RenderMarkdownError" }, - }, - link = { - enabled = true, - image = "๓ฐฅถ ", - email = "๓ฐ€“ ", - hyperlink = "๓ฐŒน ", - highlight = "RenderMarkdownLink", - custom = { - web = { pattern = "^http[s]?://", icon = "๓ฐ–Ÿ ", highlight = "RenderMarkdownLink" }, - }, - }, - sign = { - enabled = true, - highlight = "RenderMarkdownSign", - }, - }, - config = function(_, opts) - require("render-markdown").setup(opts) - - vim.keymap.set("n", "mR", ":RenderMarkdown toggle", { desc = "Toggle Markdown Rendering" }) - end, -} diff --git a/lua/plugins/scissors.lua b/lua/plugins/scissors.lua deleted file mode 100644 index de22d1a..0000000 --- a/lua/plugins/scissors.lua +++ /dev/null @@ -1,43 +0,0 @@ -return { - "chrisgrieser/nvim-scissors", - dependencies = { "folke/snacks.nvim" }, - cmd = { "ScissorsAddNewSnippet", "ScissorsEditSnippet" }, - keys = { - { - "csa", - function() - require("scissors").addNewSnippet() - end, - mode = { "n", "x" }, - desc = "Add new snippet", - }, - { - "cse", - function() - require("scissors").editSnippet() - end, - desc = "Edit snippet", - }, - }, - opts = { - snippetDir = vim.fn.stdpath("config") .. "/snippets", - snippetSelection = { - picker = "snacks", - }, - editSnippetPopup = { - height = 0.4, - width = 0.6, - border = "rounded", - keymaps = { - cancel = "q", - saveChanges = "", - goBackToSearch = "", - deleteSnippet = "", - duplicateSnippet = "", - openInFile = "", - insertNextToken = "", - jumpBetweenBodyAndPrefix = "", - }, - }, - }, -} diff --git a/lua/plugins/smart-splits.lua b/lua/plugins/smart-splits.lua deleted file mode 100644 index ba83913..0000000 --- a/lua/plugins/smart-splits.lua +++ /dev/null @@ -1,56 +0,0 @@ -return { - { - "mrjones2014/smart-splits.nvim", - event = "VeryLazy", - config = function() - require("smart-splits").setup({ - ignored_buftypes = { - "nofile", - "quickfix", - "prompt", - }, - default_amount = 3, - at_edge = "wrap", - move_cursor_same_row = false, - cursor_follows_swapped_bufs = false, - resize_mode = { - quit_key = "", - resize_keys = { "h", "j", "k", "l" }, - silent = false, - hooks = { - on_enter = function() - vim.notify("Entering resize mode") - end, - on_leave = function() - vim.notify("Exiting resize mode") - end, - }, - }, - ignored_events = { - "BufEnter", - "WinEnter", - }, - multiplexer_integration = nil, - disable_multiplexer_nav_when_zoomed = true, - }) - - -- Keymaps for smart splits - vim.keymap.set("n", "", require("smart-splits").move_cursor_left) - vim.keymap.set("n", "", require("smart-splits").move_cursor_down) - vim.keymap.set("n", "", require("smart-splits").move_cursor_up) - vim.keymap.set("n", "", require("smart-splits").move_cursor_right) - - -- Resize with arrows - vim.keymap.set("n", "", require("smart-splits").resize_up) - vim.keymap.set("n", "", require("smart-splits").resize_down) - vim.keymap.set("n", "", require("smart-splits").resize_left) - vim.keymap.set("n", "", require("smart-splits").resize_right) - - -- Swapping buffers - vim.keymap.set("n", "h", require("smart-splits").swap_buf_left) - vim.keymap.set("n", "j", require("smart-splits").swap_buf_down) - vim.keymap.set("n", "k", require("smart-splits").swap_buf_up) - vim.keymap.set("n", "l", require("smart-splits").swap_buf_right) - end, - }, -} diff --git a/lua/plugins/smartcolumn-nvim.lua b/lua/plugins/smartcolumn-nvim.lua deleted file mode 100644 index 5460ddf..0000000 --- a/lua/plugins/smartcolumn-nvim.lua +++ /dev/null @@ -1,15 +0,0 @@ -return { - "m4xshen/smartcolumn.nvim", - opts = { - colorcolumn = { - "80", - "120", - }, - disabled_filetypes = { - "lazy", - "help", - "checkhealth", - "snacks_dashboard", - }, - }, -} diff --git a/lua/plugins/snacks.lua b/lua/plugins/snacks.lua deleted file mode 100644 index f0deb44..0000000 --- a/lua/plugins/snacks.lua +++ /dev/null @@ -1,392 +0,0 @@ -return { - "folke/snacks.nvim", - priority = 1000, - lazy = false, - opts = { - bigfile = { - enabled = true, - }, - bufferline = { - style = "minimal", - }, - ----- - dashboard = { - preset = { - header = [[ - -------------------------------------------------------------------------------------------------------- - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— - โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ• - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• - -------------------------------------------------------------------------------------------------------- -]], - keys = { - { icon = "๐Ÿช„", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" }, - { icon = "๐Ÿ“ฐ", key = "n", desc = "New File", action = ":ene | startinsert" }, - { icon = "๐Ÿ—„๏ธ", key = "r", desc = "Recent Files", action = ":lua Snacks.dashboard.pick('oldfiles')" }, - { icon = "๐Ÿ”Ž", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" }, - { - icon = "โš™๏ธ", - key = "c", - desc = "Config", - action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})", - }, - { icon = "๓ฐ’ฒ ", key = "l", desc = "Lazy", action = ":Lazy" }, - { icon = " ", key = "q", desc = "Quit", action = ":qa" }, - }, - }, - }, - dim = { - enabled = true, - }, - ----- - git = { - enabled = true, - }, - ----- - image = { - enabled = true, - }, - ----- - -- Auto-disable LSP/treesitter/etc. on huge files (>1.5MB by default). - bigfile = { - enabled = true, - }, - ----- - -- Render the file before plugins load for a snappier startup feel. - quickfile = { - enabled = true, - }, - ----- - -- Pretty floating prompt for vim.ui.input (rename, etc.). - input = { - enabled = true, - }, - ----- - -- Combined number + sign + fold column with git sign integration. - statuscolumn = { - enabled = true, - }, - ----- - -- Smooth scrolling (replaces neoscroll). - scroll = { - enabled = true, - }, - ----- - -- Highlight + jump between LSP references to the word under cursor - -- (replaces vim-illuminate). Keymaps `]w` / `[w` are already defined below. - words = { - enabled = true, - }, - ----- - picker = { - enabled = true, - hidden = true, - sources = { - files = { - exclude = { - ".git", - ".devenv", - ".direnv", - "node_modules", - }, - }, - }, - actions = { - trouble_open = function(...) - return require("trouble.sources.snacks").actions.trouble_open.action(...) - end, - }, - win = { - input = { - keys = { - [""] = { "trouble_open", mode = { "n", "i" } }, - }, - }, - }, - }, - ----- - explorer = { - enabled = true, - hidden = true, - ignored = true, - }, - ----- - indent = { - enabled = true, - filter = function(buf) - local ft = vim.bo[buf].filetype - return ft ~= "markdown" and ft ~= "markdown_inline" - end, - }, - scope = { - enabled = true, - filter = function(buf) - local ft = vim.bo[buf].filetype - return ft ~= "markdown" and ft ~= "markdown_inline" - end, - }, - ----- - lazygit = { - win = { - style = "float", - width = 0.95, - height = 0.95, - border = "rounded", - }, - throttle = { - ms = 50, - }, - focus = true, - enter = true, - }, - ----- - notifier = { - timeout = 3000, - }, - ----- - scratch = { - name = "Scratch", - ft = function() - local current_ft = vim.bo.filetype - return current_ft and current_ft ~= "" and current_ft or "markdown" - end, - }, - }, - keys = { - { - "ff", - function() - Snacks.picker.files({ hidden = true, ignored = true }) - end, - desc = "Find Files", - }, - { - "fg", - function() - Snacks.picker.grep() - end, - desc = "Grep", - }, - { - "fb", - function() - Snacks.picker.buffers() - end, - desc = "Buffers", - }, - { - "fr", - function() - Snacks.picker.recent() - end, - desc = "Recent Files", - }, - { - "fh", - function() - Snacks.picker.help() - end, - desc = "Help Tags", - }, - { - "fc", - function() - Snacks.picker.files({ cwd = vim.fn.stdpath("config") }) - end, - desc = "Config Files", - }, - { - ".", - function() - local filetypes = { - "markdown", - "lua", - "python", - "bash", - "text", - "json", - "yaml", - } - - local current_ft = vim.bo.filetype - if current_ft and current_ft ~= "" then - local found = false - for _, ft in ipairs(filetypes) do - if ft == current_ft then - found = true - break - end - end - if not found then - table.insert(filetypes, 1, current_ft .. " (current)") - end - end - - vim.ui.select(filetypes, { - prompt = "Select filetype: ", - format_item = function(item) - return item - end, - }, function(choice) - if choice then - local selected_ft = choice:gsub(" %(current%)", "") - Snacks.scratch({ ft = selected_ft }) - end - end) - end, - desc = "Toggle Scratch Buffer", - }, - { - "S", - function() - Snacks.scratch.select() - end, - desc = "Select scratch buffer.", - }, - { - "sd", - function() - local items = Snacks.scratch.list() - if #items == 0 then - vim.notify("No scratch buffers found", vim.log.levels.INFO) - return - end - - vim.ui.select(items, { - prompt = "Delete Scratch Buffer", - format_item = function(item) - local icon = item.icon or Snacks.util.icon(item.ft, "filetype") or "๓ฐˆ”" - return icon .. " " .. item.name .. (item.cwd and " (" .. vim.fn.fnamemodify(item.cwd, ":p:~") .. ")" or "") - end, - }, function(selected) - if selected then - -- Close any open buffers for this file - for _, buf in ipairs(vim.api.nvim_list_bufs()) do - if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == selected.file then - vim.api.nvim_buf_delete(buf, { force = true }) - end - end - -- Delete the actual file - vim.fn.delete(selected.file) - vim.notify("Deleted scratch: " .. selected.name, vim.log.levels.INFO) - end - end) - end, - desc = "Delete scratch buffer", - }, - { - "un", - function() - Snacks.notifier.hide() - end, - desc = "Dismiss All Notifications", - }, - { - "bd", - function() - Snacks.bufdelete() - end, - desc = "Delete Buffer", - }, - { - "gg", - function() - Snacks.lazygit() - end, - desc = "Lazygit", - }, - { - "gB", - function() - Snacks.git.blame_line() - end, - desc = "Git Blame Line", - }, - { - "gW", - function() - Snacks.gitbrowse() - end, - desc = "Git Browse Web", - }, - { - "gf", - function() - Snacks.lazygit.log_file() - end, - desc = "Lazygit Current File History", - }, - { - "gl", - function() - Snacks.lazygit.log() - end, - desc = "Lazygit Log (cwd)", - }, - { - "cR", - function() - Snacks.rename() - end, - desc = "Rename File", - }, - { - "]w", - function() - Snacks.words.jump(vim.v.count1) - end, - desc = "Next Reference", - }, - { - "[w", - function() - Snacks.words.jump(-vim.v.count1) - end, - desc = "Prev Reference", - }, - { - "zm", - function() - Snacks.zen() - end, - desc = "Zen Mode", - }, - { - "ee", - function() - Snacks.explorer.open() - end, - desc = "Explorer", - }, - { "", "bprevious", desc = "Prev Buffer" }, - { "", "bnext", desc = "Next Buffer" }, - { "[b", "bprevious", desc = "Prev Buffer" }, - { "]b", "bnext", desc = "Next Buffer" }, - }, - init = function() - vim.api.nvim_create_autocmd("User", { - pattern = "VeryLazy", - callback = function() - _G.dd = function(...) - Snacks.debug.inspect(...) - end - _G.bt = function() - Snacks.debug.backtrace() - end - vim.print = _G.dd - - Snacks.toggle.option("spell", { name = "Spelling" }):map("us") - Snacks.toggle.option("wrap", { name = "Wrap" }):map("uw") - Snacks.toggle.diagnostics():map("ud") - Snacks.toggle - .option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }) - :map("uc") - Snacks.toggle.inlay_hints():map("uh") - Snacks.toggle.dim({ enable = true }):map("uz") - end, - }) - end, -} diff --git a/lua/plugins/spectre.lua b/lua/plugins/spectre.lua deleted file mode 100644 index 93cc8ee..0000000 --- a/lua/plugins/spectre.lua +++ /dev/null @@ -1,9 +0,0 @@ -return { - "nvim-pack/nvim-spectre", - dependencies = { "nvim-lua/plenary.nvim" }, - cmd = "Spectre", - opts = { open_cmd = "noswapfile vnew" }, - keys = { - { "fr", "Spectre", desc = "Replace in files (Spectre)" }, - }, -} diff --git a/lua/plugins/terraform-local-modules.lua b/lua/plugins/terraform-local-modules.lua deleted file mode 100644 index 471af6b..0000000 --- a/lua/plugins/terraform-local-modules.lua +++ /dev/null @@ -1,446 +0,0 @@ -return { - "nvim-lua/plenary.nvim", - ft = "terraform", - config = function() - -- Find all variable files in a directory (including nested) - local function find_variable_files(dir) - local var_files = {} - local possible_names = { "variables.tf", "vars.tf", "variable.tf" } - - -- Check direct directory - for _, name in ipairs(possible_names) do - local file = dir .. "/" .. name - if vim.fn.filereadable(file) == 1 then - table.insert(var_files, file) - end - end - - -- Check nested modules directory - local modules_dir = dir .. "/modules" - if vim.fn.isdirectory(modules_dir) == 1 then - local nested_modules = vim.fn.glob(modules_dir .. "/*", false, true) - for _, nested_path in ipairs(nested_modules) do - if vim.fn.isdirectory(nested_path) == 1 then - for _, name in ipairs(possible_names) do - local file = nested_path .. "/" .. name - if vim.fn.filereadable(file) == 1 then - table.insert(var_files, file) - end - end - end - end - end - - return var_files - end - - -- Parse variables from a variables.tf file - local function parse_variables_from_file(variables_file) - if vim.fn.filereadable(variables_file) == 0 then - return {} - end - - local content = table.concat(vim.fn.readfile(variables_file), "\n") - local variables = {} - - -- Better regex to match variable blocks with proper brace handling - local i = 1 - while i <= #content do - local var_start, var_end, var_name = content:find('variable%s+"([^"]+)"%s*{', i) - if not var_start then - break - end - - -- Find the matching closing brace - local brace_count = 1 - local j = var_end + 1 - while j <= #content and brace_count > 0 do - local char = content:sub(j, j) - if char == "{" then - brace_count = brace_count + 1 - elseif char == "}" then - brace_count = brace_count - 1 - end - j = j + 1 - end - - if brace_count == 0 then - local var_content = content:sub(var_end + 1, j - 2) - local has_default = var_content:match("default%s*=") - local is_required = not has_default - - -- Extract description if available - local description = var_content:match('description%s*=%s*"([^"]*)"') or "" - - -- Extract type information - local type_info = var_content:match("type%s*=%s*([^\n]+)") or "any" - type_info = type_info:gsub("%s+$", "") -- trim trailing whitespace - - -- Extract default value for optional variables - local default_value = "" - if has_default then - local default_match = var_content:match("default%s*=%s*([^\n]+)") - if default_match then - default_value = default_match:gsub("%s+$", "") -- trim trailing whitespace - -- Truncate long defaults - if #default_value > 50 then - default_value = default_value:sub(1, 47) .. "..." - end - end - end - - table.insert(variables, { - name = var_name, - required = is_required, - description = description, - type = type_info, - default = default_value, - }) - end - - i = j - end - - return variables - end - - -- Parse all variables from a module directory - local function parse_variables(module_dir) - local all_variables = {} - local var_files = find_variable_files(module_dir) - - for _, file in ipairs(var_files) do - local file_vars = parse_variables_from_file(file) - for _, var in ipairs(file_vars) do - table.insert(all_variables, var) - end - end - - return all_variables - end - - -- Function to parse .terraform/modules/modules.json - local function parse_terraform_modules() - local modules_json = "./.terraform/modules/modules.json" - if vim.fn.filereadable(modules_json) == 0 then - return {} - end - - local content = table.concat(vim.fn.readfile(modules_json), "") - local ok, data = pcall(vim.json.decode, content) - if not ok then - print("Failed to parse modules.json") - return {} - end - - local modules = {} - if data.Modules then - for _, module in ipairs(data.Modules) do - if module.Key ~= "" then -- Skip root module - -- Dir field might already include .terraform/modules/ prefix - local module_dir = module.Dir - if not module_dir:match("^%.terraform/modules/") then - module_dir = "./.terraform/modules/" .. module_dir - else - module_dir = "./" .. module_dir - end - - local variables = parse_variables(module_dir) - - table.insert(modules, { - name = module.Key, - source = module.Source, - dir = module_dir, - variables = variables, - }) - end - end - end - - return modules - end - - -- Function to get unique module sources - local function get_unique_modules() - local unique_modules = {} - local seen_sources = {} - - -- First, get downloaded modules from modules.json (group by source) - local terraform_modules = parse_terraform_modules() - for _, module in ipairs(terraform_modules) do - if not seen_sources[module.source] then - seen_sources[module.source] = true - - -- Extract module name from source - local display_name = module.source - if module.source:match("^%.*/(.+)$") then - display_name = module.source:match("^%.*/(.+)$") - elseif module.source:match("([^/]+)$") then - display_name = module.source:match("([^/]+)$") - end - - table.insert(unique_modules, { - name = display_name, - source = module.source, - dir = module.dir, - variables = module.variables, - type = "downloaded", - }) - end - end - - -- Then, get local modules - local local_paths = { - "./modules", - "../modules", - "../../modules", - "./terraform-modules", - "../terraform-modules", - } - - for _, path in ipairs(local_paths) do - local result = vim.fn.glob(path .. "/*", false, true) - for _, module_path in ipairs(result) do - if vim.fn.isdirectory(module_path) == 1 then - local module_name = vim.fn.fnamemodify(module_path, ":t") - local relative_path = vim.fn.fnamemodify(module_path, ":.") - local variables = parse_variables(module_path) - - if not seen_sources[relative_path] then - seen_sources[relative_path] = true - - table.insert(unique_modules, { - name = module_name, - source = relative_path, - dir = module_path, - variables = variables, - type = "local", - }) - end - end - end - end - - return unique_modules - end - - -- Create command to show available modules - vim.api.nvim_create_user_command("TerraformShowModules", function() - get_unique_modules() - end, { - desc = "Show discovered Terraform modules", - }) - - -- Simple keymap to insert module template - vim.api.nvim_create_autocmd("FileType", { - pattern = "terraform", - callback = function() - vim.keymap.set("n", "tm", function() - local modules = get_unique_modules() - if #modules > 0 then - vim.ui.select(modules, { - prompt = "Select module source:", - format_item = function(item) - local req_count = 0 - for _, var in ipairs(item.variables) do - if var.required then - req_count = req_count + 1 - end - end - local opt_count = #item.variables - req_count - -- Truncate long source paths to keep selection readable - local source = item.source - if #source > 60 then - source = "..." .. source:sub(-57) - end - return string.format( - "[%s] %s (%d req, %d opt) - %s", - item.type, - item.name, - req_count, - opt_count, - source - ) - end, - }, function(choice) - if choice then - -- Prompt for module name first - vim.ui.input({ - prompt = "Module name: ", - }, function(module_name) - if not module_name or module_name == "" then - return - end - - -- Separate required and optional variables - local required_vars = {} - for _, var in ipairs(choice.variables) do - if var.required then - table.insert(required_vars, var) - end - end - - -- Function to format value based on type - local function format_value(value, var_type) - if not value or value == "" then - return '""' -- default to empty string - end - - -- Clean up type (remove extra whitespace, etc.) - local clean_type = var_type:gsub("%s+", ""):lower() - - -- Handle different types - if clean_type:match("^string") then - -- String type - add quotes if not already quoted - if not value:match('^".*"$') then - return '"' .. value .. '"' - end - return value - elseif clean_type:match("^number") or clean_type:match("^int") then - -- Number type - no quotes - return value - elseif clean_type:match("^bool") then - -- Boolean type - ensure it's true/false - local lower_val = value:lower() - if lower_val == "true" or lower_val == "yes" or lower_val == "1" then - return "true" - elseif lower_val == "false" or lower_val == "no" or lower_val == "0" then - return "false" - end - return value -- let user handle complex cases - elseif clean_type:match("^list") then - -- List type - add brackets if not present - if not value:match("^%[.*%]$") then - return "[" .. value .. "]" - end - return value - elseif clean_type:match("^map") or clean_type:match("^object") then - -- Map/object type - add braces if not present - if not value:match("^{.*}$") then - return "{" .. value .. "}" - end - return value - else - -- Unknown or 'any' type - return as-is - return value - end - end - - -- Collect values for required variables - local var_values = {} - local function collect_var(index) - if index > #required_vars then - -- All variables collected, generate template - local lines = {} - table.insert(lines, 'module "' .. module_name .. '" {') - table.insert(lines, ' source = "' .. choice.source .. '"') - table.insert(lines, "") - - if #required_vars > 0 then - table.insert(lines, " # Required variables:") - for i, var in ipairs(required_vars) do - local formatted_value = format_value(var_values[i], var.type) - table.insert(lines, " " .. var.name .. " = " .. formatted_value) - end - table.insert(lines, "") - end - - -- Optional variables (commented) - local optional_vars = {} - for _, var in ipairs(choice.variables) do - if not var.required then - table.insert(optional_vars, var) - end - end - - if #optional_vars > 0 then - table.insert(lines, " # Optional variables:") - for _, var in ipairs(optional_vars) do - local comment = "" - if var.default ~= "" then - comment = string.format(" # default: %s", var.default) - end - if var.description ~= "" then - local desc = var.description - -- Truncate long descriptions to prevent very long lines - if #desc > 50 then - desc = desc:sub(1, 47) .. "..." - end - comment = comment .. (comment ~= "" and " - " or " # ") .. desc - end - - local line = " # " .. var.name .. " = " .. comment - -- If line would be too long, break it up - if #line > 120 then - table.insert(lines, " # " .. var.name .. " = ") - table.insert(lines, " # " .. comment:gsub("^# ", "")) - else - table.insert(lines, line) - end - end - end - - table.insert(lines, "}") - vim.api.nvim_put(lines, "l", true, true) - return - end - - -- Prompt for current variable - local var = required_vars[index] - local prompt = var.name - if var.type ~= "any" then - -- Truncate very long types - local var_type = var.type - if #var_type > 30 then - var_type = var_type:sub(1, 27) .. "..." - end - prompt = prompt .. " (" .. var_type .. ")" - end - if var.description ~= "" then - -- Truncate long descriptions to keep prompt reasonable - local desc = var.description - if #desc > 60 then - desc = desc:sub(1, 57) .. "..." - end - prompt = prompt .. " - " .. desc - end - prompt = prompt .. ": " - - -- Provide suggestions for common variable names - local default_value = "" - if var.name:match("region") and var.type:match("string") then - default_value = "us-east-1" - elseif var.name:match("environment") and var.type:match("string") then - default_value = "dev" - elseif var.name:match("enabled") and var.type:match("bool") then - default_value = "true" - end - - vim.ui.input({ - prompt = prompt .. " (or 'back' to go back)", - default = default_value, - }, function(value) - if value == "back" and index > 1 then - collect_var(index - 1) -- go back to previous variable - elseif value and value ~= "" and value ~= "back" then - var_values[index] = value - collect_var(index + 1) - else - var_values[index] = '""' -- default empty string - collect_var(index + 1) - end - end) - end - - collect_var(1) - end) - end - end) - else - print("No modules found in current directory") - end - end, { buffer = true, desc = "Insert Module Template" }) - end, - }) - end, -} diff --git a/lua/plugins/terrareg.lua b/lua/plugins/terrareg.lua deleted file mode 100644 index 45fbe12..0000000 --- a/lua/plugins/terrareg.lua +++ /dev/null @@ -1,16 +0,0 @@ -return { - "terrareg.nvim", - dir = vim.fn.expand("~/repos/open/terrareg"), - enabled = false, - dependencies = { - "nvim-lua/plenary.nvim", - }, - config = function() - require("terrareg").setup({ - debug = true, - ensure_installed = { "aws" }, - keep_float_buffers = true, - }) - end, - -- ft = { "terraform", "hcl" }, -} diff --git a/lua/plugins/todo-comments.lua b/lua/plugins/todo-comments.lua deleted file mode 100644 index 6b50fa3..0000000 --- a/lua/plugins/todo-comments.lua +++ /dev/null @@ -1,22 +0,0 @@ -return { - "folke/todo-comments.nvim", - lazy = false, - dependencies = { "nvim-lua/plenary.nvim", "folke/snacks.nvim" }, - opts = {}, - keys = { - { - "st", - function() - Snacks.picker.todo_comments() - end, - desc = "Todo", - }, - { - "sT", - function() - Snacks.picker.todo_comments({ keywords = { "TODO", "FIX", "FIXME" } }) - end, - desc = "Todo/Fix/Fixme", - }, - }, -} diff --git a/lua/plugins/trouble.lua b/lua/plugins/trouble.lua deleted file mode 100644 index f94bb54..0000000 --- a/lua/plugins/trouble.lua +++ /dev/null @@ -1,77 +0,0 @@ -return { - { - "folke/trouble.nvim", - config = function() - require("trouble").setup({ - icons = { - indent = { - middle = "โ”‚ ", - last = "โ”” ", - top = "โ”‚ ", - ws = " ", - }, - folder_closed = "", - folder_open = "", - kinds = { - Array = "", - Boolean = "๓ฐจ™", - Class = "", - Constant = "๓ฐฟ", - Constructor = "", - Enum = "", - EnumMember = "", - Event = "", - Field = "", - File = "๓ฐˆ”", - Function = "๓ฐŠ•", - Interface = "", - Key = "", - Method = "๓ฐŠ•", - Module = "", - Namespace = "๓ฐฆฎ", - Null = "", - Number = "๓ฐŽ ", - Object = "", - Operator = "๓ฐ†•", - Package = "", - Property = "", - String = "", - Struct = "๓ฐ†ผ", - TypeParameter = "", - Variable = "๓ฐ€ซ", - }, - }, - signs = { - error = "", - warning = "", - hint = "๓ฐŒต", - information = "", - other = "", - }, - modes = { - symbols = { - win = { position = "right" }, - }, - }, - }) - - -- Keymaps for trouble - vim.keymap.set("n", "xx", "Trouble diagnostics toggle", { desc = "Diagnostics (Trouble)" }) - vim.keymap.set( - "n", - "xX", - "Trouble diagnostics toggle filter.buf=0", - { desc = "Buffer Diagnostics (Trouble)" } - ) - vim.keymap.set("n", "xs", "Trouble symbols toggle focus=false", { desc = "Symbols (Trouble)" }) - vim.keymap.set( - "n", - "xl", - "Trouble lsp toggle focus=false win.position=right", - { desc = "LSP Definitions / references / ... (Trouble)" } - ) - vim.keymap.set("n", "xL", "Trouble loclist toggle", { desc = "Location List (Trouble)" }) - vim.keymap.set("n", "xQ", "Trouble qflist toggle", { desc = "Quickfix List (Trouble)" }) - end, - }, -} diff --git a/lua/plugins/undotree.lua b/lua/plugins/undotree.lua deleted file mode 100644 index f2c30fa..0000000 --- a/lua/plugins/undotree.lua +++ /dev/null @@ -1,7 +0,0 @@ -return { - "mbbill/undotree", - cmd = "UndotreeToggle", - keys = { - { "U", vim.cmd.UndotreeToggle, desc = "Toggle Undotree" }, - }, -} diff --git a/lua/plugins/vim-dadbod-ui.lua b/lua/plugins/vim-dadbod-ui.lua deleted file mode 100644 index c302cd9..0000000 --- a/lua/plugins/vim-dadbod-ui.lua +++ /dev/null @@ -1,28 +0,0 @@ -return { - { - -- Database browser - "kristijanhusak/vim-dadbod-ui", - dependencies = { - { "tpope/vim-dadbod", lazy = true }, - { "kristijanhusak/vim-dadbod-completion", ft = { "sql", "mysql", "plsql" }, lazy = true }, - }, - cmd = { - "DBUI", - "DBUIToggle", - "DBUIAddConnection", - "DBUIFindBuffer", - }, - init = function() - vim.g.db_ui_use_nerd_fonts = 1 - vim.g.db_ui_show_database_icon = 1 - vim.g.db_ui_force_echo_messages = 1 - vim.g.db_ui_win_position = "left" - vim.g.db_ui_winwidth = 40 - - vim.keymap.set("n", "Du", "DBUIToggle", { desc = "Toggle DBUI" }) - vim.keymap.set("n", "Df", "DBUIFindBuffer", { desc = "Find DB buffer" }) - vim.keymap.set("n", "Dr", "DBUIRenameBuffer", { desc = "Rename DB buffer" }) - vim.keymap.set("n", "Dq", "DBUILastQueryInfo", { desc = "Last query info" }) - end, - }, -} diff --git a/lua/plugins/vim-table-mode.lua b/lua/plugins/vim-table-mode.lua deleted file mode 100644 index d0b3614..0000000 --- a/lua/plugins/vim-table-mode.lua +++ /dev/null @@ -1,30 +0,0 @@ -return { - "dhruvasagar/vim-table-mode", - ft = { "markdown", "text", "org" }, - config = function() - -- Use markdown-compatible corners - vim.g.table_mode_corner = "|" - vim.g.table_mode_corner_corner = "|" - vim.g.table_mode_header_fillchar = "-" - - -- Enable table mode for markdown files by default - vim.g.table_mode_map_prefix = "m" - - -- Disable default mappings to avoid conflicts - vim.g.table_mode_disable_mappings = 0 - - -- Auto format tables when typing - vim.g.table_mode_auto_align = 1 - - -- Syntax for tables - vim.g.table_mode_syntax = 1 - - -- Motion mappings for tables - vim.g.table_mode_motion_up_map = "" - vim.g.table_mode_motion_down_map = "" - vim.g.table_mode_motion_left_map = "" - vim.g.table_mode_motion_right_map = "" - - vim.keymap.set("n", "mt", ":TableModeToggle", { desc = "Toggle Table Mode" }) - end, -} diff --git a/lua/plugins/which-key.lua b/lua/plugins/which-key.lua deleted file mode 100644 index a7b5e86..0000000 --- a/lua/plugins/which-key.lua +++ /dev/null @@ -1,103 +0,0 @@ -return { - "folke/which-key.nvim", - event = "VeryLazy", - opts = { - preset = "modern", - delay = function(ctx) - return ctx.plugin and 0 or 200 - end, - filter = function(mapping) - return true - end, - spec = { - { - mode = { "n", "v" }, - -- Core groups - { "b", group = "Buffers" }, - { "c", group = "Code/LSP" }, - { "cA", group = "CodeCompanion" }, - { "co", group = "Coverage" }, - { "cs", group = "Snippets" }, - { "d", group = "Debug" }, - { "dp", group = "Debug Python" }, - { "D", group = "Database" }, - { "f", group = "File/Find" }, - - -- Git ecosystem - { "g", group = "Git" }, - { "gI", group = "GitHub Issues" }, - { "gP", group = "GitHub/GitLab PRs" }, - { "gR", group = "GitHub Repos" }, - - -- Go-specific - { "G", group = "Go" }, - { "Gs", group = "Go Struct" }, - { "Gc", group = "Go Coverage" }, - - { "h", group = "Harpoon" }, - - { "j", group = "JQ/JSON" }, - { "l", group = "LSP Info" }, - { "m", group = "Markdown/Table" }, - { "n", group = "NPM/Neovim Tips" }, - { "nt", group = "Neovim Tips" }, - { "o", group = "Outline" }, - { "p", group = "Profile/Python" }, - - -- Overseer/Tasks - { "O", group = "Overseer/Tasks" }, - { "Os", group = "Security Scans" }, - - -- Refactoring - { "r", group = "Refactor" }, - { "R", group = "REST" }, - - { "s", group = "Search/Screenshot" }, - - -- Test/Terraform - { "t", group = "Test/Terraform" }, - { "tm", group = "Terraform Modules" }, - { "tr", group = "Terraform Registry" }, - - { "u", group = "UI/Toggle" }, - { "v", group = "Virtual Env/Review" }, - { "w", group = "Windows/Workspace" }, - { "x", group = "Diagnostics/Lint" }, - { "z", group = "Zen Mode" }, - - -- Navigation - { "[", group = "Previous" }, - { "]", group = "Next" }, - { "g", group = "Goto" }, - { "gs", group = "Surround" }, - { "z", group = "Folds" }, - }, - }, - icons = { - breadcrumb = "ยป", - separator = "โžœ", - group = "+", - }, - layout = { - height = { min = 4, max = 25 }, - width = { min = 20, max = 50 }, - spacing = 3, - align = "left", - }, - show_help = true, - show_keys = true, - disable = { - buftypes = {}, - filetypes = { "TelescopePrompt" }, - }, - }, - keys = { - { - "?", - function() - require("which-key").show({ global = false }) - end, - desc = "Buffer Local Keymaps (which-key)", - }, - }, -} diff --git a/lua/utils/git_repo.lua b/lua/utils/git_repo.lua deleted file mode 100644 index 7587a69..0000000 --- a/lua/utils/git_repo.lua +++ /dev/null @@ -1,146 +0,0 @@ --- Shared helpers for detecting the forge (GitHub vs GitLab) of the current repo. -local M = {} - ---- Get the origin remote URL for the current repo. ----@return string -function M.remote_url() - return vim.fn.system("git config --get remote.origin.url 2>/dev/null"):gsub("%s+", "") -end - ---- The explicitly configured GitLab instance URL, if any ---- (`git config gitlab.url` or $GITLAB_URL). Empty string if unset. ----@return string -function M.configured_gitlab_url() - local url = vim.fn.system("git config --get gitlab.url 2>/dev/null"):gsub("%s+", "") - if url == "" then - url = os.getenv("GITLAB_URL") or "" - end - return url -end - ---- Whether the current repositories origin remote points at GitHub. ----@return boolean -function M.is_github() - return M.remote_url():match("github") ~= nil -end - ---- Whether the current repositories origin remote points at GitLab. ---- Matches the substring "gitlab", or for self-hosted instances on a ---- custom domain a host equal to the configured GitLab instance host. ----@return boolean -function M.is_gitlab() - local remote = M.remote_url() - if remote == "" or M.is_github() then - return false - end - if remote:match("gitlab") then - return true - end - local configured = M.configured_gitlab_url() - if configured ~= "" then - local configured_host = M.host_from_remote(configured) - if configured_host and M.host_from_remote(remote) == configured_host then - return true - end - end - return false -end - ---- Extract the host (e.g. "gitlab.example.com") from a git remote URL. ---- Handles HTTPS, ssh:// and git-style (git@host:group/repo.git) remotes. ----@param url string ----@return string|nil -function M.host_from_remote(url) - if not url or url == "" then - return nil - end - -- https://host/... or ssh://git@host[:port]/... - local host = url:match("^https?://([^/]+)") or url:match("^ssh://[^@]*@?([^:/]+)") - if not host then - -- git-style: git@host:group/repo.git - host = url:match("^[^@]+@([^:]+):") - end - if host then - host = host:gsub(":%d+$", "") -- strip any :port - end - return host -end - ---- Derive the GitLab instance base URL (e.g. "https://gitlab.example.com") ---- from the current repositories origin remote. Returns nil if no host can be parsed. ----@return string|nil -function M.gitlab_url_from_remote() - local host = M.host_from_remote(M.remote_url()) - if not host then - return nil - end - return "https://" .. host -end - --- Read the first set value among the given environment variable names. -local function env_first(...) - for _, name in ipairs({ ... }) do - local v = os.getenv(name) - if v and v ~= "" then - return v - end - end - return nil -end - ---- Whether `host` is excluded from proxying by the NO_PROXY / no_proxy env var. ----@param host string ----@return boolean -function M.host_in_no_proxy(host) - local no_proxy = env_first("NO_PROXY", "no_proxy") - if not no_proxy or host == "" then - return false - end - for raw in no_proxy:gmatch("[^,]+") do - local entry = raw:gsub("%s+", ""):gsub("^%*", ""):gsub("^%.", "") -- strip wildcard/leading dot - if entry ~= "" and (host == entry or host:sub(-(#entry + 1)) == "." .. entry) then - return true - end - end - return false -end - ---- Resolve the HTTP proxy to use for `host`. ---- Priority: explicit `git config http.gitlab.proxy`, then the standard ---- HTTPS_PROXY / HTTP_PROXY env vars (unless the host is in NO_PROXY). ---- gitlab.nvim's Go server uses a custom transport and does NOT honor the ---- env proxy on its own, so we must pass it explicitly. ----@param host string ----@return string -function M.proxy_for_host(host) - local configured = vim.fn.system("git config --get http.gitlab.proxy 2>/dev/null"):gsub("%s+", "") - if configured ~= "" then - return configured - end - if host and host ~= "" and M.host_in_no_proxy(host) then - return "" - end - return env_first("HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy") or "" -end - ---- Read the GitLab token that `glab` uses for `host`, if glab is installed and ---- configured for it. This keeps a single source of truth so gitlab.nvim and ---- glab never drift out of sync (e.g. one having an expired token). ----@param host string ----@return string|nil -function M.glab_token_for_host(host) - if not host or host == "" or vim.fn.executable("glab") == 0 then - return nil - end - local token = vim.fn.system({ "glab", "config", "get", "token", "--host", host }) - if vim.v.shell_error ~= 0 then - return nil - end - token = token:gsub("%s+", "") - if token == "" then - return nil - end - return token -end - -return M diff --git a/lua/utils/keymap_check.lua b/lua/utils/keymap_check.lua deleted file mode 100644 index eeadf76..0000000 --- a/lua/utils/keymap_check.lua +++ /dev/null @@ -1,330 +0,0 @@ -local M = {} - --- Known intentional overrides (plugins extending built-in behavior) --- These are not real conflicts -local IGNORED_PATTERNS = { - -- Fold mappings (nvim-ufo extends these) - "^z[mMrRaAcCoOnN]$", - -- Diagnostic navigation (multiple plugins provide this) - "^%[d$", - "^%]d$", - -- Buffer/tab navigation (bufferline, etc.) - "^%[b$", - "^%]b$", - "^%[t$", - "^%]t$", - "^gt$", - "^gT$", - -- Quickfix/location list - "^%[q$", - "^%]q$", - "^%[l$", - "^%]l$", - -- Argument list - "^%[a$", - "^%]a$", - -- Comment mappings - "^gc", - "^gco$", - "^gcO$", - "^gcA$", - -- Scroll mappings in visual mode (neoscroll) - "^$", - -- Center/top/bottom in visual mode - "^z[ztb]$", -} - --- Modes where we expect lots of intentional overrides -local RELAXED_MODES = { "v", "x", "s", "o" } - -local function get_all_keymaps() - local keymaps = {} - local modes = { "n", "i", "v", "x", "s", "o", "c", "t" } - - for _, mode in ipairs(modes) do - local mode_maps = vim.api.nvim_get_keymap(mode) - for _, map in ipairs(mode_maps) do - table.insert(keymaps, { - mode = mode, - lhs = map.lhs, - rhs = map.rhs or map.callback and "" or "", - desc = map.desc or "", - buffer = false, - }) - end - end - - return keymaps -end - -local function normalize_key(key) - -- Normalize special keys but preserve case for regular characters - return key - :gsub("<[Ll]eader>", vim.g.mapleader or "\\") - :gsub("", "\r") - :gsub("", "\027") - :gsub("", "\t") - :gsub("", " ") - :gsub("<([Cc])%-", "<%1-") -- Normalize Ctrl - :gsub("<([Ss])%-", "<%1-") -- Normalize Shift - :gsub("<([Mm])%-", "<%1-") -- Normalize Meta/Alt -end - -local function is_ignored(lhs, mode) - -- Check if mode is relaxed (we expect overrides there) - for _, m in ipairs(RELAXED_MODES) do - if mode == m and not lhs:match("^<[Ll]eader>") then - return true - end - end - - -- Check against ignored patterns - for _, pattern in ipairs(IGNORED_PATTERNS) do - if lhs:match(pattern) then - return true - end - end - - return false -end - -function M.find_conflicts(opts) - opts = opts or {} - local include_ignored = opts.include_ignored or false - local leader_only = opts.leader_only or false - - local keymaps = get_all_keymaps() - local conflicts = {} - local seen = {} - - for _, map in ipairs(keymaps) do - local should_process = true - - -- Skip if leader_only and not a leader mapping - if leader_only and not map.lhs:match("^<[Ll]eader>") then - should_process = false - end - - -- Skip ignored patterns unless explicitly requested - if should_process and not include_ignored and is_ignored(map.lhs, map.mode) then - should_process = false - end - - if should_process then - local key = map.mode .. ":" .. normalize_key(map.lhs) - - if seen[key] then - if not conflicts[key] then - conflicts[key] = { seen[key] } - end - table.insert(conflicts[key], map) - else - seen[key] = map - end - end - end - - return conflicts -end - -function M.find_leader_duplicates() - local keymaps = get_all_keymaps() - local leader_maps = {} - local duplicates = {} - - for _, map in ipairs(keymaps) do - if map.lhs:match("^<[Ll]eader>") or map.lhs:match("^ ") then - local key = map.mode .. ":" .. map.lhs - if leader_maps[key] then - if not duplicates[key] then - duplicates[key] = { leader_maps[key] } - end - table.insert(duplicates[key], map) - else - leader_maps[key] = map - end - end - end - - return duplicates -end - -function M.check_conflicts() - local conflicts = M.find_conflicts({ leader_only = true }) - local count = vim.tbl_count(conflicts) - - if count > 0 then - print("CONFLICTS_FOUND:" .. count) - else - print("NO_CONFLICTS") - end - - return conflicts -end - -function M.show_conflicts(opts) - opts = opts or {} - local show_all = opts.all or false - - local conflicts - if show_all then - conflicts = M.find_conflicts({ include_ignored = true }) - else - conflicts = M.find_conflicts() - end - - local lines = { "# Keymap Analysis", "" } - - if not show_all then - table.insert(lines, "_Filtered view (use `:CheckKeymaps!` to show all)_") - table.insert(lines, "") - end - - -- Show conflicts - local conflict_count = vim.tbl_count(conflicts) - if conflict_count > 0 then - table.insert(lines, "## โš  Conflicts Found: " .. conflict_count) - table.insert(lines, "") - - -- Sort keys for consistent output - local sorted_keys = {} - for key in pairs(conflicts) do - table.insert(sorted_keys, key) - end - table.sort(sorted_keys) - - for _, key in ipairs(sorted_keys) do - local maps = conflicts[key] - table.insert(lines, "### " .. key) - for _, map in ipairs(maps) do - local desc = map.desc ~= "" and (" - " .. map.desc) or "" - local rhs = (map.rhs or ""):sub(1, 50) - table.insert(lines, string.format(" - `%s` โ†’ `%s`%s", map.lhs, rhs, desc)) - end - table.insert(lines, "") - end - else - table.insert(lines, "## โœ“ No keymap conflicts detected") - table.insert(lines, "") - end - - -- Show leader key summary - table.insert(lines, "## Leader Key Summary") - table.insert(lines, "") - - local leader_maps = {} - local keymaps = get_all_keymaps() - for _, map in ipairs(keymaps) do - if map.lhs:match("^<[Ll]eader>") and map.mode == "n" then - table.insert(leader_maps, map) - end - end - - table.sort(leader_maps, function(a, b) - return a.lhs < b.lhs - end) - - table.insert(lines, "| Key | Description |") - table.insert(lines, "|-----|-------------|") - for _, map in ipairs(leader_maps) do - local desc = map.desc ~= "" and map.desc or (map.rhs or "") - table.insert(lines, string.format("| `%s` | %s |", map.lhs, desc)) - end - - -- Display in a floating window - local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) - vim.api.nvim_set_option_value("filetype", "markdown", { buf = buf }) - vim.api.nvim_set_option_value("modifiable", false, { buf = buf }) - - local width = math.min(100, vim.o.columns - 10) - local height = math.min(#lines + 2, vim.o.lines - 10) - - local win = vim.api.nvim_open_win(buf, true, { - relative = "editor", - width = width, - height = height, - col = (vim.o.columns - width) / 2, - row = (vim.o.lines - height) / 2, - style = "minimal", - border = "rounded", - title = " Keymap Check ", - title_pos = "center", - }) - - vim.keymap.set("n", "q", function() - vim.api.nvim_win_close(win, true) - end, { buffer = buf, nowait = true }) - - vim.keymap.set("n", "", function() - vim.api.nvim_win_close(win, true) - end, { buffer = buf, nowait = true }) -end - -function M.export_keymaps(filepath) - filepath = filepath or vim.fn.stdpath("config") .. "/keymaps_export.md" - - local keymaps = get_all_keymaps() - local lines = { "# All Keymaps", "", "Generated: " .. os.date("%Y-%m-%d %H:%M:%S"), "" } - - local by_mode = {} - for _, map in ipairs(keymaps) do - if not by_mode[map.mode] then - by_mode[map.mode] = {} - end - table.insert(by_mode[map.mode], map) - end - - local mode_names = { - n = "Normal", - i = "Insert", - v = "Visual", - x = "Visual Block", - s = "Select", - o = "Operator", - c = "Command", - t = "Terminal", - } - - for mode, maps in pairs(by_mode) do - table.insert(lines, "## " .. (mode_names[mode] or mode) .. " Mode") - table.insert(lines, "") - table.insert(lines, "| Key | Action | Description |") - table.insert(lines, "|-----|--------|-------------|") - - table.sort(maps, function(a, b) - return a.lhs < b.lhs - end) - - for _, map in ipairs(maps) do - if map.lhs:match("^<[Ll]eader>") then - local rhs = (map.rhs or ""):gsub("|", "\\|"):sub(1, 40) - local desc = (map.desc or ""):gsub("|", "\\|") - table.insert(lines, string.format("| `%s` | `%s` | %s |", map.lhs, rhs, desc)) - end - end - table.insert(lines, "") - end - - local file = io.open(filepath, "w") - if file then - file:write(table.concat(lines, "\n")) - file:close() - vim.notify("Keymaps exported to: " .. filepath, vim.log.levels.INFO) - else - vim.notify("Failed to export keymaps", vim.log.levels.ERROR) - end -end - --- Setup user commands -function M.setup() - vim.api.nvim_create_user_command("CheckKeymaps", function(opts) - M.show_conflicts({ all = opts.bang }) - end, { desc = "Check for keymap conflicts (use ! for all)", bang = true }) - - vim.api.nvim_create_user_command("ExportKeymaps", function(opts) - M.export_keymaps(opts.args ~= "" and opts.args or nil) - end, { desc = "Export all keymaps to markdown", nargs = "?" }) -end - -return M diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json new file mode 100644 index 0000000..b0b9a27 --- /dev/null +++ b/nvim-pack-lock.json @@ -0,0 +1,28 @@ +{ + "plugins": { + "conform.nvim": { + "rev": "3543d000dafbc41cc7761d860cfdb24e82154f75", + "src": "https://github.com/stevearc/conform.nvim", + "version": "'v9.1.0'" + }, + "gitsigns.nvim": { + "rev": "a462f416e2ce4744531c6256252dee99a7d34a83", + "src": "https://github.com/lewis6991/gitsigns.nvim", + "version": "'v2.1.0'" + }, + "nvim-treesitter": { + "rev": "4916d6592ede8c07973490d9322f187e07dfefac", + "src": "https://github.com/nvim-treesitter/nvim-treesitter", + "version": "'main'" + }, + "snacks.nvim": { + "rev": "e6fd58c82f2f3fcddd3fe81703d47d6d48fc7b9f", + "src": "https://github.com/folke/snacks.nvim", + "version": "'v2.31.0'" + }, + "vim-tmux-navigator": { + "rev": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432", + "src": "https://github.com/christoomey/vim-tmux-navigator" + } + } +} diff --git a/options.lua b/options.lua new file mode 100644 index 0000000..affbd2d --- /dev/null +++ b/options.lua @@ -0,0 +1,81 @@ +-- ============================================================================ +-- OPTIONS +-- ============================================================================ +vim.opt.number = true -- line number +vim.opt.relativenumber = true -- relative line numbers +vim.opt.cursorline = true -- highlight current line +vim.opt.wrap = false -- do not wrap lines by default +vim.opt.scrolloff = 10 -- keep 10 lines above/below cursor +vim.opt.sidescrolloff = 10 -- keep 10 lines to left/right of cursor + +vim.opt.tabstop = 2 -- tabwidth +vim.opt.shiftwidth = 2 -- indent width +vim.opt.softtabstop = 2 -- soft tab stop not tabs on tab/backspace +vim.opt.expandtab = true -- use spaces instead of tabs +vim.opt.smartindent = true -- smart auto-indent +vim.opt.autoindent = true -- copy indent from current line + +vim.opt.ignorecase = true -- case insensitive search +vim.opt.smartcase = true -- case sensitive if uppercase in string +vim.opt.hlsearch = true -- highlight search matches +vim.opt.incsearch = true -- show matches as you type + +vim.opt.signcolumn = "yes" -- always show a sign column +vim.opt.colorcolumn = "100" -- show a column at 100 position chars +vim.opt.showmatch = true -- highlights matching brackets +vim.opt.cmdheight = 1 -- single line command line +vim.opt.completeopt = "menuone,noinsert,noselect" -- completion options +vim.opt.showmode = false -- do not show the mode, instead have it in statusline +vim.opt.pumheight = 10 -- popup menu height +vim.opt.pumblend = 10 -- popup menu transparency +vim.opt.winblend = 0 -- floating window transparency +vim.opt.concealcursor = "" -- do not hide cursorline in markup +vim.opt.synmaxcol = 300 -- syntax highlighting limit +vim.opt.fillchars = { eob = " " } -- hide "~" on empty lines + +local undodir = vim.fn.expand("~/.vim/undodir") +if + vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent +then + vim.fn.mkdir(undodir, "p") +end + +vim.opt.backup = false -- do not create a backup file +vim.opt.writebackup = false -- do not write to a backup file +vim.opt.swapfile = false -- do not create a swapfile +vim.opt.undofile = true -- do create an undo file +vim.opt.undodir = undodir -- set the undo directory +vim.opt.updatetime = 300 -- faster completion +vim.opt.timeoutlen = 500 -- timeout duration +vim.opt.ttimeoutlen = 50 -- key code timeout +vim.opt.autoread = true -- auto-reload changes if outside of neovim +vim.opt.autowrite = false -- do not auto-save + +vim.opt.hidden = true -- allow hidden buffers +vim.opt.errorbells = false -- no error sounds +vim.opt.backspace = "indent,eol,start" -- better backspace behaviour +vim.opt.autochdir = false -- do not autochange directories +vim.opt.iskeyword:append("-") -- include - in words +vim.opt.path:append("**") -- include subdirs in search +vim.opt.selection = "inclusive" -- include last char in selection +vim.opt.mouse = "a" -- enable mouse support +vim.opt.clipboard:append("unnamedplus") -- use system clipboard +vim.opt.modifiable = true -- allow buffer modifications + +-- guicursor: configure cursor shape, blink timing, and highlight per editor mode +vim.opt.guicursor = + "n-v-c:block,i-ci-ve:block,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175" -- cursor blinking and settings + +-- Folding: requires treesitter available at runtime; safe fallback if not +vim.opt.foldmethod = "expr" -- use expression for folding +vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" -- use treesitter for folding +vim.opt.foldlevel = 99 -- start with all folds open + +vim.opt.splitbelow = true -- horizontal splits go below +vim.opt.splitright = true -- vertical splits go right + +vim.opt.wildmenu = true -- tab completion +vim.opt.wildmode = "longest:full,full" -- complete longest common match, full completion list, cycle through with Tab +vim.opt.diffopt:append("linematch:60") -- improve diff display +vim.opt.redrawtime = 10000 -- increase neovim redraw tolerance +vim.opt.maxmempattern = 20000 -- increase max memory diff --git a/lua/plugins/conform.lua b/plugins/conform.lua similarity index 84% rename from lua/plugins/conform.lua rename to plugins/conform.lua index 614c853..58c4897 100644 --- a/lua/plugins/conform.lua +++ b/plugins/conform.lua @@ -1,11 +1,8 @@ return { - "stevearc/conform.nvim", - opts = {}, - lazy = true, - event = { "BufReadPre", "BufNewFile" }, + src = "https://github.com/stevearc/conform.nvim", + version = "v9.1.0", config = function() - local conform = require("conform") - conform.setup({ + require("conform").setup({ formatters_by_ft = { lua = { "stylua" }, python = { "ruff_format", "ruff_organize_imports" }, diff --git a/plugins/gitsigns.lua b/plugins/gitsigns.lua new file mode 100644 index 0000000..eef7a2a --- /dev/null +++ b/plugins/gitsigns.lua @@ -0,0 +1,56 @@ +return { + src = "https://github.com/lewis6991/gitsigns.nvim", + version = "v2.1.0", + config = function() + require("gitsigns").setup({ + signs = { + add = { text = "โ”ƒ" }, + change = { text = "โ”ƒ" }, + delete = { text = "_" }, + topdelete = { text = "โ€พ" }, + changedelete = { text = "~" }, + untracked = { text = "โ”†" }, + }, + signs_staged = { + add = { text = "โ”ƒ" }, + change = { text = "โ”ƒ" }, + delete = { text = "_" }, + topdelete = { text = "โ€พ" }, + changedelete = { text = "~" }, + untracked = { text = "โ”†" }, + }, + signs_staged_enable = true, + signcolumn = true, -- Toggle with `:Gitsigns toggle_signs` + numhl = false, -- Toggle with `:Gitsigns toggle_numhl` + linehl = false, -- Toggle with `:Gitsigns toggle_linehl` + word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff` + watch_gitdir = { + follow_files = true, + }, + auto_attach = true, + attach_to_untracked = false, + current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame` + current_line_blame_opts = { + virt_text = true, + virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align' + delay = 1000, + ignore_whitespace = false, + virt_text_priority = 100, + use_focus = true, + }, + current_line_blame_formatter = ", - ", + blame_formatter = nil, -- Use default + sign_priority = 6, + update_debounce = 100, + status_formatter = nil, -- Use default + max_file_length = 40000, -- Disable if file is longer than this (in lines) + preview_config = { + -- Options passed to nvim_open_win + style = "minimal", + relative = "cursor", + row = 0, + col = 1, + }, + }) + end, +} diff --git a/lua/plugins/nvim-treesitter.lua b/plugins/nvim-treesitter.lua similarity index 66% rename from lua/plugins/nvim-treesitter.lua rename to plugins/nvim-treesitter.lua index 33d5197..1aea4f5 100644 --- a/lua/plugins/nvim-treesitter.lua +++ b/plugins/nvim-treesitter.lua @@ -1,46 +1,43 @@ return { - "nvim-treesitter/nvim-treesitter", - branch = "main", - version = false, - build = ":TSUpdate", - event = { "BufReadPost", "BufNewFile", "BufWritePre" }, - cmd = { "TSUpdate", "TSInstall", "TSLog", "TSUninstall" }, - opts = { - indent = { enable = true }, - highlight = { enable = true }, - ensure_installed = { - "bash", - "c", - "diff", - "go", - "gomod", - "gosum", - "gowork", - "hcl", - "html", - "javascript", - "jsdoc", - "json", - "lua", - "luadoc", - "luap", - "markdown", - "markdown_inline", - "printf", - "python", - "query", - "regex", - "terraform", - "toml", - "tsx", - "typescript", - "vim", - "vimdoc", - "xml", - "yaml", - }, - }, - config = function(_, opts) + src = "https://github.com/nvim-treesitter/nvim-treesitter", + version = "main", + config = function() + local opts = { + indent = { enable = true }, + highlight = { enable = true }, + ensure_installed = { + "bash", + "c", + "diff", + "go", + "gomod", + "gosum", + "gowork", + "hcl", + "html", + "javascript", + "jsdoc", + "json", + "lua", + "luadoc", + "luap", + "markdown", + "markdown_inline", + "printf", + "python", + "query", + "regex", + "terraform", + "toml", + "tsx", + "typescript", + "vim", + "vimdoc", + "xml", + "yaml", + }, + } + local ts = require("nvim-treesitter") if not ts.get_installed then diff --git a/plugins/snacks.lua b/plugins/snacks.lua new file mode 100644 index 0000000..b4596e9 --- /dev/null +++ b/plugins/snacks.lua @@ -0,0 +1,123 @@ +return { + src = "https://github.com/folke/snacks.nvim", + version = "v2.31.0", + config = function() + require("snacks").setup({ + bigfile = { enabled = true }, -- disables heavy features on huge files + dashboard = { + enabled = true, + width = 60, + row = nil, -- dashboard position. nil for center + col = nil, -- dashboard position. nil for center + pane_gap = 4, -- empty columns between vertical panes + preset = { + ---@type fun(cmd:string, opts:table)|nil + pick = "snacks", + -- Used by the `keys` section to show keymaps. + -- Set your custom keymaps here. + -- When using a function, the `items` argument are the default keymaps. + ---@type snacks.dashboard.Item[] + keys = { + { + icon = "๏€‚ ", + key = "f", + desc = "Find File", + action = ":lua Snacks.dashboard.pick('files')", + }, + { icon = "๏…› ", key = "n", desc = "New File", action = ":ene | startinsert" }, + { + icon = "๏€ข ", + key = "g", + desc = "Find Text", + action = ":lua Snacks.dashboard.pick('live_grep')", + }, + { + icon = "๏ƒ… ", + key = "r", + desc = "Recent Files", + action = ":lua Snacks.dashboard.pick('oldfiles')", + }, + { + icon = "๏ฃ ", + key = "c", + desc = "Config", + action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})", + }, + { icon = "๎ˆ ", key = "s", desc = "Restore Session", section = "session" }, + { + icon = "๓ฐ’ฒ ", + key = "L", + desc = "Lazy", + action = ":Lazy", + enabled = package.loaded.lazy ~= nil, + }, + { icon = "๏ฆ ", key = "q", desc = "Quit", action = ":qa" }, + }, + -- Used by the `header` section + header = [[ + -------------------------------------------------------------------------------------------------------- + โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— + โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ• + โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• + -------------------------------------------------------------------------------------------------------- +]], + }, + -- item field formatters + formats = { + icon = function(item) + if item.file and item.icon == "file" or item.icon == "directory" then + return Snacks.dashboard.icon(item.file, item.icon) + end + return { item.icon, width = 2, hl = "icon" } + end, + footer = { "%s", align = "center" }, + header = { "%s", align = "center" }, + file = function(item, ctx) + local fname = vim.fn.fnamemodify(item.file, ":~") + fname = ctx.width and #fname > ctx.width and vim.fn.pathshorten(fname) or fname + if #fname > ctx.width then + local dir = vim.fn.fnamemodify(fname, ":h") + local file = vim.fn.fnamemodify(fname, ":t") + if dir and file then + file = file:sub(-(ctx.width - #dir - 2)) + fname = dir .. "/โ€ฆ" .. file + end + end + local dir, file = fname:match("^(.*)/(.+)$") + return dir and { { dir .. "/", hl = "dir" }, { file, hl = "file" } } or { { fname, hl = "file" } } + end, + }, + sections = { + { section = "header" }, + { section = "keys", gap = 1, padding = 1 }, + }, + }, + explorer = { enabled = true, hidden = true, ignored = true }, -- file explorer (uses picker) + indent = { enabled = true }, -- indent guides + lazygit = { enabled = true }, + notifier = { enabled = true }, -- vim.notify replacement + picker = { + enabled = true, + hidden = true, + sources = { + files = { + exclude = { + ".git", + ".devenv", + ".direnv", + "node_modules", + }, + }, + }, + }, -- fuzzy finder (files, grep, buffers, ...) + quickfile = { enabled = true }, -- render files before plugins load + scroll = { enabled = true }, -- smooth scrolling + statuscolumn = { enabled = true }, -- pretty status column + terminal = { enabled = true }, -- toggleable terminal + words = { enabled = true }, -- highlight/navigate references under cursor + }) + end, +} diff --git a/plugins/vim-tmux-navigator.lua b/plugins/vim-tmux-navigator.lua new file mode 100644 index 0000000..86dfb60 --- /dev/null +++ b/plugins/vim-tmux-navigator.lua @@ -0,0 +1,3 @@ +return { + src = "https://github.com/christoomey/vim-tmux-navigator", +} diff --git a/renovate.json b/renovate.json deleted file mode 100644 index ae72961..0000000 --- a/renovate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - ":semanticCommits", - ":enablePreCommit", - "helpers:pinGitHubActionDigests" - ], - "labels": ["dependencies"], - "packageRules": [ - { - "matchManagers": ["github-actions"], - "groupName": "GitHub Actions", - "minimumReleaseAge": "7 days" - }, - { - "matchManagers": ["github-actions"], - "matchUpdateTypes": ["minor", "patch", "pin", "digest"], - "automerge": true - }, - { - "matchManagers": ["pre-commit"], - "groupName": "pre-commit hooks", - "minimumReleaseAge": "7 days" - }, - { - "matchManagers": ["pre-commit"], - "matchUpdateTypes": ["minor", "patch"], - "automerge": true - } - ] -} diff --git a/scripts/extract-keybindings.lua b/scripts/extract-keybindings.lua deleted file mode 100644 index bb30b16..0000000 --- a/scripts/extract-keybindings.lua +++ /dev/null @@ -1,78 +0,0 @@ --- extract-keybindings.lua - generate docs/KEYBINDINGS.md from the config. --- --- Run with: nvim -l scripts/extract-keybindings.lua --- --- Parses every Lua file with tree-sitter, collects `*.keymap.set` calls that --- have a string key and a `desc`, and writes a markdown reference grouped by --- mode with clickable source links. - -local script_dir = arg[0]:match("(.*[/\\])") or "./" -package.path = script_dir .. "lib/?.lua;" .. package.path -local docgen = require("docgen") - -local function escape(s) - return (s:gsub("|", "\\|")) -end - -local mode_names = { - n = "Normal Mode", - i = "Insert Mode", - v = "Visual Mode", - x = "Visual Block Mode", - s = "Select Mode", - o = "Operator-pending Mode", - t = "Terminal Mode", - c = "Command Mode", - [""] = "Normal, Visual, Operator-pending", -} - -local files = {} -vim.list_extend(files, docgen.lua_files("lua", "**/*.lua")) -vim.list_extend(files, docgen.lua_files(".", "*.lua")) -table.sort(files) - --- Collect keymaps grouped by mode. -local by_mode = {} -local total = 0 -for _, file in ipairs(files) do - local src = docgen.read(file) - if src then - local rel = file:gsub("^%./", "") - for _, km in ipairs(docgen.extract_keymaps(src)) do - by_mode[km.mode] = by_mode[km.mode] or {} - table.insert(by_mode[km.mode], { key = km.key, desc = km.desc, src = rel, line = km.line }) - total = total + 1 - end - end -end - -local modes = vim.tbl_keys(by_mode) -table.sort(modes) - -local out = {} -table.insert(out, "# Keybindings Reference") -table.insert(out, "") -table.insert(out, "_Auto-generated from configuration files. Do not edit manually._") -table.insert(out, "") - -for _, mode in ipairs(modes) do - table.insert(out, "## " .. (mode_names[mode] or ("Mode '" .. mode .. "'"))) - table.insert(out, "") - table.insert(out, "| Key | Description | Source |") - table.insert(out, "|-----|-------------|--------|") - local rows = by_mode[mode] - table.sort(rows, function(a, b) - if a.key == b.key then - return a.src < b.src - end - return a.key < b.key - end) - for _, r in ipairs(rows) do - local source = string.format("[%s#L%d](%s#L%d)", r.src, r.line, r.src, r.line) - table.insert(out, string.format("| `%s` | %s | %s |", escape(r.key), escape(r.desc), source)) - end - table.insert(out, "") -end - -docgen.write("docs/KEYBINDINGS.md", table.concat(out, "\n")) -print(string.format("Generated docs/KEYBINDINGS.md with %d keybindings", total)) diff --git a/scripts/generate-docs.lua b/scripts/generate-docs.lua deleted file mode 100644 index 0e4c84b..0000000 --- a/scripts/generate-docs.lua +++ /dev/null @@ -1,46 +0,0 @@ --- generate-docs.lua - generate docs/PLUGINS.md from lua/plugins/*.lua. --- --- Run with: nvim -l scripts/generate-docs.lua --- --- Parses each plugin spec with tree-sitter to extract the repository, --- dependencies, and whether it is configured / defines keymaps. - -local script_dir = arg[0]:match("(.*[/\\])") or "./" -package.path = script_dir .. "lib/?.lua;" .. package.path -local docgen = require("docgen") - -local out = {} -table.insert(out, "# Neovim Plugins Documentation") -table.insert(out, "") -table.insert(out, "This file is auto-generated by pre-commit hooks. Do not edit manually.") -table.insert(out, "") - -local files = docgen.lua_files("lua/plugins", "*.lua") -local count = 0 -for _, file in ipairs(files) do - local info = docgen.plugin_info(file) - if info then - count = count + 1 - table.insert(out, "## " .. info.title) - table.insert(out, "") - if info.repo then - table.insert(out, "- **Repository:** https://github.com/" .. info.repo) - else - table.insert(out, "- **Repository:** Not specified") - end - if #info.dependencies > 0 then - table.insert(out, "- **Dependencies:**") - for _, dep in ipairs(info.dependencies) do - table.insert(out, string.format(" - [%s](https://github.com/%s)", dep, dep)) - end - end - table.insert(out, "- **Configured:** " .. (info.configured and "Yes" or "Basic setup")) - if info.has_keymaps then - table.insert(out, "- **Has keybindings:** Yes") - end - table.insert(out, "") - end -end - -docgen.write("docs/PLUGINS.md", table.concat(out, "\n")) -print(string.format("Generated docs/PLUGINS.md for %d plugins", count)) diff --git a/scripts/lib/docgen.lua b/scripts/lib/docgen.lua deleted file mode 100644 index df9a6de..0000000 --- a/scripts/lib/docgen.lua +++ /dev/null @@ -1,228 +0,0 @@ --- docgen.lua - shared helpers for documentation generation scripts. --- --- These helpers parse the Lua configuration using Neovim's bundled tree-sitter --- Lua parser instead of regular expressions, so they understand the real syntax --- of keymap calls and plugin specs (multi-line calls, tables, nested fields). --- --- Intended to be used from scripts run with `nvim -l scripts/.lua`. - -local M = {} - --- Return the inner value of a tree-sitter `string` node (without quotes), --- or nil if the node is not a plain string literal. -function M.string_value(node, src) - if not node or node:type() ~= "string" then - return nil - end - for child in node:iter_children() do - if child:type() == "string_content" then - return vim.treesitter.get_node_text(child, src) - end - end - return "" -- empty string literal ("") -end - --- Parse Lua source and return the root tree-sitter node. -function M.parse(src) - local parser = vim.treesitter.get_string_parser(src, "lua") - return parser:parse()[1]:root() -end - --- Read a file and return its contents, or nil. -function M.read(path) - local fd = io.open(path, "r") - if not fd then - return nil - end - local content = fd:read("*a") - fd:close() - return content -end - --- List Lua files (sorted) matching a glob pattern. -function M.lua_files(dir, pattern) - local files = vim.fn.globpath(dir, pattern or "**/*.lua", false, true) - table.sort(files) - return files -end - --- Recursively search a node for a `field` named `key` and return its string --- value, or nil. Used to find e.g. `desc = "..."` anywhere inside a call. -local function find_field_string(node, src, key) - if node:type() == "field" then - local name = node:field("name")[1] - if name and vim.treesitter.get_node_text(name, src) == key then - return M.string_value(node:field("value")[1], src) - end - end - for child in node:iter_children() do - local found = find_field_string(child, src, key) - if found then - return found - end - end - return nil -end - --- Collect string values from a table_constructor / string node. -local function collect_strings(node, src) - if not node then - return {} - end - if node:type() == "string" then - local v = M.string_value(node, src) - return v and { v } or {} - end - local out = {} - if node:type() == "table_constructor" then - for child in node:iter_children() do - if child:type() == "field" then - local v = M.string_value(child:field("value")[1], src) - if v then - table.insert(out, v) - end - end - end - end - return out -end - --- Extract keymaps from a Lua source string. --- Returns a list of { mode, key, desc, line } for every `*.keymap.set(...)` --- call that has a string key and a `desc`. A call with multiple modes yields --- one entry per mode. -function M.extract_keymaps(src) - local root = M.parse(src) - local query = vim.treesitter.query.parse("lua", "(function_call) @call") - local results = {} - for _, node in query:iter_captures(root, src, 0, -1) do - local name = node:field("name")[1] - local fn = name and vim.treesitter.get_node_text(name, src) or "" - if fn:match("keymap%.set$") then - local args = node:field("arguments")[1] - local arg_nodes = {} - if args then - for child in args:iter_children() do - if child:named() then - table.insert(arg_nodes, child) - end - end - end - local modes = collect_strings(arg_nodes[1], src) - local key = M.string_value(arg_nodes[2], src) - local desc = find_field_string(node, src, "desc") - if key and desc and #modes > 0 then - local line = node:range() + 1 - for _, mode in ipairs(modes) do - table.insert(results, { mode = mode, key = key, desc = desc, line = line }) - end - end - end - end - return results -end - --- Extract the dependencies (owner/repo strings) declared in a plugin spec. -local function extract_dependencies(root, src) - local query = vim.treesitter.query.parse("lua", "(field) @field") - local deps = {} - local seen = {} - for _, node in query:iter_captures(root, src, 0, -1) do - local name = node:field("name")[1] - if name and vim.treesitter.get_node_text(name, src) == "dependencies" then - for _, dep in ipairs(collect_strings(node:field("value")[1], src)) do - if dep:match("^[%w%._%-]+/[%w%._%-]+$") and not seen[dep] then - seen[dep] = true - table.insert(deps, dep) - end - end - end - end - table.sort(deps) - return deps -end - --- Find the first `owner/repo` style string literal in a plugin spec. -function M.plugin_repo(root, src) - local query = vim.treesitter.query.parse("lua", "(string) @s") - for _, node in query:iter_captures(root, src, 0, -1) do - local v = M.string_value(node, src) - if v and v:match("^[%w%._%-]+/[%w%._%-]+$") then - return v - end - end - return nil -end - --- Title-case a plugin filename: "blink-cmp" -> "Blink Cmp". -local function title_case(name) - return (name:gsub("%-", " "):gsub("(%w+)", function(w) - return w:sub(1, 1):upper() .. w:sub(2) - end)) -end - --- Build a structured description of a plugin spec file. -function M.plugin_info(path) - local src = M.read(path) - if not src then - return nil - end - local root = M.parse(src) - local name = vim.fn.fnamemodify(path, ":t:r") - return { - title = title_case(name), - repo = M.plugin_repo(root, src), - dependencies = extract_dependencies(root, src), - configured = src:find("setup(", 1, true) ~= nil, - has_keymaps = src:find("keymap.set", 1, true) ~= nil, - } -end - --- Categorize a plugin file by its filename, mirroring update-readme buckets. -function M.category(name) - local rules = { - { "๐Ÿ”ง Language & LSP", { "lsp", "mason", "language" } }, - { "๐Ÿ“ Git Integration", { "git", "fugitive" } }, - { "๐Ÿ” Navigation & Search", { "telescope", "search", "tree" } }, - { "๐Ÿ› Testing & Debugging", { "test", "debug", "dap" } }, - { "๐ŸŽจ UI & Themes", { "ui", "theme", "color", "catppuccin", "bufferline", "lualine" } }, - { "๐ŸŒณ Syntax & Parsing", { "treesitter", "syntax" } }, - { "๐Ÿ’ก Completion", { "completion", "cmp", "snippet" } }, - { "โœ๏ธ Editing", { "editor", "autopair", "surround", "comment" } }, - { "๐Ÿ“‹ Productivity", { "productivity", "todo", "bookmark" } }, - { "๐Ÿ’ป Terminal", { "terminal", "tmux" } }, - } - for _, rule in ipairs(rules) do - for _, kw in ipairs(rule[2]) do - if name:find(kw, 1, true) then - return rule[1] - end - end - end - return "๐Ÿ”Œ Other Plugins" -end - --- Ordered list of categories for stable output. -M.category_order = { - "๐Ÿ”ง Language & LSP", - "๐ŸŽจ UI & Themes", - "๐Ÿ” Navigation & Search", - "๐Ÿ’ก Completion", - "โœ๏ธ Editing", - "๐Ÿ“ Git Integration", - "๐Ÿ› Testing & Debugging", - "๐Ÿ“‹ Productivity", - "๐ŸŒณ Syntax & Parsing", - "๐Ÿ’ป Terminal", - "๐Ÿ”Œ Other Plugins", -} - --- Write content to a file, creating parent dirs as needed. -function M.write(path, content) - vim.fn.mkdir(vim.fn.fnamemodify(path, ":h"), "p") - local fd = assert(io.open(path, "w")) - fd:write(content) - fd:close() -end - -return M diff --git a/scripts/update-readme.lua b/scripts/update-readme.lua deleted file mode 100644 index 20d7404..0000000 --- a/scripts/update-readme.lua +++ /dev/null @@ -1,63 +0,0 @@ --- update-readme.lua - refresh the auto-generated plugin list in README.md. --- --- Run with: nvim -l scripts/update-readme.lua --- --- Replaces the content between the AUTO-GENERATED PLUGIN LIST markers in place, --- categorizing plugins by filename. If the markers are missing the section is --- appended to the end of the file. - -local script_dir = arg[0]:match("(.*[/\\])") or "./" -package.path = script_dir .. "lib/?.lua;" .. package.path -local docgen = require("docgen") - -local START = "" -local STOP = "" -local README = "README.md" - --- Build the categorized plugin list. -local function build_section() - local files = docgen.lua_files("lua/plugins", "*.lua") - local by_cat = {} - for _, file in ipairs(files) do - local name = vim.fn.fnamemodify(file, ":t:r") - local info = docgen.plugin_info(file) - local repo = info and info.repo or name - local cat = docgen.category(name) - by_cat[cat] = by_cat[cat] or {} - table.insert(by_cat[cat], repo) - end - - local lines = { START, "", string.format("### Installed Plugins (%d total)", #files), "" } - for _, cat in ipairs(docgen.category_order) do - if by_cat[cat] then - table.sort(by_cat[cat]) - table.insert(lines, "#### " .. cat) - table.insert(lines, "") - for _, repo in ipairs(by_cat[cat]) do - table.insert(lines, string.format("- [%s](https://github.com/%s)", repo, repo)) - end - table.insert(lines, "") - end - end - table.insert(lines, STOP) - return table.concat(lines, "\n") -end - -local content = docgen.read(README) -if not content then - error("README.md not found") -end - -local section = build_section() -local start_idx = content:find(START, 1, true) -local stop_idx = content:find(STOP, 1, true) - -local updated -if start_idx and stop_idx then - updated = content:sub(1, start_idx - 1) .. section .. content:sub(stop_idx + #STOP) -else - updated = content:gsub("%s*$", "") .. "\n\n" .. section .. "\n" -end - -docgen.write(README, updated) -print("Updated plugin list in README.md") diff --git a/scripts/validate.sh b/scripts/validate.sh deleted file mode 100755 index 4cde600..0000000 --- a/scripts/validate.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Neovim Configuration Validator -# Run this after updates to check for errors - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -CONFIG_DIR="$(dirname "$SCRIPT_DIR")" -TEMP_LOG=$(mktemp) -ERRORS_FOUND=0 - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo "๐Ÿ” Neovim Configuration Validator" -echo "==================================" -echo "" - -# Check 1: Lua syntax validation -echo -n "Checking Lua syntax... " -LUA_ERRORS=0 -while IFS= read -r -d '' file; do - if ! luac -p "$file" 2>/dev/null; then - echo "" - echo -e "${RED} โœ— Syntax error in: $file${NC}" - LUA_ERRORS=$((LUA_ERRORS + 1)) - ERRORS_FOUND=1 - fi -done < <(find "$CONFIG_DIR/lua" -name "*.lua" -print0 2>/dev/null) - -if [ $LUA_ERRORS -eq 0 ]; then - echo -e "${GREEN}โœ“ All Lua files valid${NC}" -else - echo -e "${RED}โœ— Found $LUA_ERRORS Lua syntax errors${NC}" -fi - -# Check 2: Neovim startup (headless) -echo -n "Checking Neovim startup... " -STARTUP_OUTPUT=$(nvim --headless -c "lua print('STARTUP_OK')" -c "qa!" 2>&1) || true - -if echo "$STARTUP_OUTPUT" | grep -q "STARTUP_OK"; then - echo -e "${GREEN}โœ“ Neovim starts successfully${NC}" -else - echo -e "${RED}โœ— Neovim startup failed${NC}" - echo "$STARTUP_OUTPUT" | head -20 - ERRORS_FOUND=1 -fi - -# Check 3: Plugin loading -echo -n "Checking plugin loading... " -PLUGIN_CHECK=$(nvim --headless -c "lua local ok, lazy = pcall(require, 'lazy'); if ok then print('PLUGINS:' .. #lazy.plugins()) else print('LAZY_FAIL') end" -c "qa!" 2>&1) || true - -if echo "$PLUGIN_CHECK" | grep -q "PLUGINS:"; then - PLUGIN_COUNT=$(echo "$PLUGIN_CHECK" | grep -o 'PLUGINS:[0-9]*' | cut -d: -f2) - echo -e "${GREEN}โœ“ $PLUGIN_COUNT plugins loaded${NC}" -else - echo -e "${RED}โœ— Plugin loading failed${NC}" - ERRORS_FOUND=1 -fi - -# Check 4: LSP configuration -echo -n "Checking LSP configuration... " -LSP_CHECK=$(nvim --headless -c "lua local configs = vim.lsp._configs or {}; print('LSP_OK:' .. vim.tbl_count(configs))" -c "qa!" 2>&1) || true - -if echo "$LSP_CHECK" | grep -q "LSP_OK"; then - echo -e "${GREEN}โœ“ LSP configured${NC}" -else - echo -e "${YELLOW}โš  LSP check inconclusive${NC}" -fi - -# Check 5: Keymap conflicts -echo -n "Checking for keymap conflicts... " -KEYMAP_CHECK=$(nvim --headless -c "lua require('utils.keymap_check').check_conflicts()" -c "qa!" 2>&1) || true - -if echo "$KEYMAP_CHECK" | grep -q "CONFLICTS_FOUND"; then - echo -e "${YELLOW}โš  Keymap conflicts detected (run :CheckKeymaps for details)${NC}" -elif echo "$KEYMAP_CHECK" | grep -q "NO_CONFLICTS"; then - echo -e "${GREEN}โœ“ No keymap conflicts${NC}" -else - echo -e "${YELLOW}โš  Keymap check skipped (module not loaded)${NC}" -fi - -# Check 6: Health checks (quick) -echo -n "Running health checks... " -HEALTH_OUTPUT=$(nvim --headless -c "silent! checkhealth vim.lsp" -c "qa!" 2>&1) || true -echo -e "${GREEN}โœ“ Health checks passed${NC}" - -echo "" -echo "==================================" -if [ $ERRORS_FOUND -eq 0 ]; then - echo -e "${GREEN}โœ“ All checks passed!${NC}" - exit 0 -else - echo -e "${RED}โœ— Some checks failed${NC}" - exit 1 -fi diff --git a/snippets/go.json b/snippets/go.json deleted file mode 100644 index 8804355..0000000 --- a/snippets/go.json +++ /dev/null @@ -1,306 +0,0 @@ -{ - "function": { - "prefix": "func", - "body": [ - "func ${1:functionName}(${2})${3: returnType} {", - "\t${0}", - "}" - ], - "description": "Function declaration (delete placeholder for void return)" - }, - "function returning error": { - "prefix": "funce", - "body": [ - "func ${1:functionName}(${2}) error {", - "\t${0}", - "\treturn nil", - "}" - ], - "description": "Function returning error" - }, - "function returning (T, error)": { - "prefix": "functe", - "body": [ - "func ${1:functionName}(${2}) (${3:T}, error) {", - "\t${0}", - "\treturn ${4:zero}, nil", - "}" - ], - "description": "Function returning (T, error)" - }, - "method": { - "prefix": "method", - "body": [ - "func (${1:r} ${2:Receiver}) ${3:Name}(${4})${5: returnType} {", - "\t${0}", - "}" - ], - "description": "Method with receiver (delete placeholder for void return)" - }, - "struct": { - "prefix": "struct", - "body": [ - "type ${1:StructName} struct {", - "\t${0}", - "}" - ], - "description": "Struct declaration" - }, - "json-tagged struct": { - "prefix": "jstruct", - "body": [ - "type ${1:StructName} struct {", - "\t${2:FieldName} ${3:string} `json:\"${4:field_name}${5:,omitempty}\"`", - "\t$0", - "}" - ], - "description": "Struct seeded with one json-tagged field (wire type)" - }, - "interface": { - "prefix": "interface", - "body": [ - "type ${1:Name} interface {", - "\t${0}", - "}" - ], - "description": "Interface declaration" - }, - "if err != nil": { - "prefix": "iferr", - "body": [ - "if err != nil {", - "\treturn err", - "}" - ], - "description": "Standard error check" - }, - "if err != nil (wrap)": { - "prefix": "iferrf", - "body": [ - "if err != nil {", - "\treturn ${1:nil, }fmt.Errorf(\"${2:context}: %w\", err)", - "}" - ], - "description": "Error check wrapping with fmt.Errorf and %w" - }, - "if err != nil (test fatal)": { - "prefix": "iferrt", - "body": [ - "if err != nil {", - "\tt.Fatalf(\"${1:context}: %v\", err)", - "}" - ], - "description": "Error check that fails the test" - }, - "got want equal": { - "prefix": "gotwant", - "body": [ - "if got, want := ${1:expr}, ${2:expected}; !reflect.DeepEqual(got, want) {", - "\tt.Errorf(\"${3:name} = %v, want %v\", got, want)", - "}" - ], - "description": "Standard got/want equality assertion" - }, - "test function": { - "prefix": "tparallel", - "body": [ - "func Test${1:Name}(t *testing.T) {", - "\tt.Parallel()", - "", - "\t${0}", - "}" - ], - "description": "Test function with t.Parallel()" - }, - "table-driven test": { - "prefix": "ttable", - "body": [ - "func Test${1:Name}(t *testing.T) {", - "\tt.Parallel()", - "", - "\ttests := []struct {", - "\t\tname string", - "\t\t${2:in} ${3:string}", - "\t\twant ${4:string}", - "\t}{", - "\t\t{name: \"${5:case}\", $2: ${6}, want: ${7}},", - "\t}", - "", - "\tfor _, tt := range tests {", - "\t\tt.Run(tt.name, func(t *testing.T) {", - "\t\t\tt.Parallel()", - "", - "\t\t\t${0}", - "\t\t})", - "\t}", - "}" - ], - "description": "Table-driven test scaffold" - }, - "test helper": { - "prefix": "thelp", - "body": [ - "func ${1:helperName}(t *testing.T${2}) ${3:string} {", - "\tt.Helper()", - "", - "\t${0}", - "}" - ], - "description": "Test helper with t.Helper()" - }, - "benchmark": { - "prefix": "bench", - "body": [ - "func Benchmark${1:Name}(b *testing.B) {", - "\tfor i := 0; i < b.N; i++ {", - "\t\t${0}", - "\t}", - "}" - ], - "description": "Benchmark function" - }, - "MPL-2.0 header": { - "prefix": "mpl", - "body": [ - "// This Source Code Form is subject to the terms of the Mozilla Public", - "// License, v. 2.0. If a copy of the MPL was not distributed with this", - "// file, You can obtain one at https://mozilla.org/MPL/2.0/.", - "", - "package ${1:name}", - "", - "$0" - ], - "description": "MPL-2.0 file header + package line" - }, - "package doc": { - "prefix": "pkgdoc", - "body": [ - "// Package ${1:name} ${2:summary sentence.}", - "package $1", - "", - "$0" - ], - "description": "Package doc comment" - }, - "golden -update flag": { - "prefix": "goldenflag", - "body": [ - "// update regenerates the golden snapshot files when set. Run:", - "//", - "//\tgo test ./${1:pkg} -run ${2:TestName} -update", - "var update = flag.Bool(\"update\", false, \"regenerate golden snapshots\")", - "$0" - ], - "description": "Golden snapshot -update flag" - }, - "model.Diagnostic": { - "prefix": "diag", - "body": [ - "model.Diagnostic{", - "\tSeverity: model.Severity${1|Error,Warning|},", - "\tSummary: \"${2:summary}\",", - "\tDetail: \"${3:detail}\",", - "}$0" - ], - "description": "model.Diagnostic literal" - }, - "json-tagged field": { - "prefix": "jf", - "body": [ - "${1:FieldName} ${2:string} `json:\"${3:field_name}${4:,omitempty}\"`$0" - ], - "description": "Struct field with json tag (use inside a struct body)" - }, - "hcl BodySchema": { - "prefix": "hclschema", - "body": [ - "var ${1:name}Schema = &hcl.BodySchema{", - "\tAttributes: []hcl.AttributeSchema{", - "\t\t{Name: \"${2:attr}\"${3:, Required: true}},$0", - "\t},", - "\tBlocks: []hcl.BlockHeaderSchema{", - "\t\t{Type: \"${4:block}\"${5:, LabelNames: []string{\"name\"}}},", - "\t},", - "}" - ], - "description": "hcl.BodySchema with attributes and blocks" - }, - "hcl AttributeSchema entry": { - "prefix": "hclattr", - "body": [ - "{Name: \"${1:attr}\"${2:, Required: true}},$0" - ], - "description": "hcl.AttributeSchema row" - }, - "hcl BlockHeaderSchema entry": { - "prefix": "hclblock", - "body": [ - "{Type: \"${1:block}\"${2:, LabelNames: []string{\"name\"}}},$0" - ], - "description": "hcl.BlockHeaderSchema row" - }, - "hcl PartialContent decode": { - "prefix": "hcldecode", - "body": [ - "content, _, hdiag := ${1:block}.Body.PartialContent(${2:name}Schema)", - "diags := model.DiagnosticsFromHCL(hdiag)", - "$0" - ], - "description": "PartialContent + diagnostics translation" - }, - "hcl attribute lookup": { - "prefix": "hclattrlookup", - "body": [ - "if attribute, ok := content.Attributes[\"${1:name}\"]; ok {", - "\t${0}", - "}" - ], - "description": "Optional attribute lookup pattern" - }, - "hcl blocks OfType loop": { - "prefix": "hclblockloop", - "body": [ - "for _, ${1:inner} := range content.Blocks.OfType(\"${2:type}\") {", - "\t${0}", - "}" - ], - "description": "Iterate over inner blocks of a given type" - }, - "cobra subcommand": { - "prefix": "cobracmd", - "body": [ - "var ${1:name}Cmd = &cobra.Command{", - "\tUse: \"${2:$1}\",", - "\tShort: \"${3:short description}\",", - "\tLong: `${4:long description}`,", - "\tArgs: cobra.${5|NoArgs,ExactArgs(1),MaximumNArgs(1),MinimumNArgs(1),RangeArgs(1\\,2)|},", - "\tRunE: func(cmd *cobra.Command, args []string) error {", - "\t\t${0}", - "\t\treturn nil", - "\t},", - "}" - ], - "description": "Cobra subcommand definition" - }, - "cobra root command + main": { - "prefix": "cobraroot", - "body": [ - "var rootCmd = &cobra.Command{", - "\tUse: \"${1:open-inspector}\",", - "\tShort: \"${2:short description}\",", - "}", - "", - "func Execute() {", - "\tif err := rootCmd.Execute(); err != nil {", - "\t\tfmt.Fprintln(os.Stderr, err)", - "\t\tos.Exit(1)", - "\t}", - "}", - "", - "func init() {", - "\trootCmd.AddCommand(${3:childCmd})$0", - "}" - ], - "description": "Cobra root command with Execute() and init" - } -} diff --git a/snippets/package.json b/snippets/package.json deleted file mode 100644 index ddf277f..0000000 --- a/snippets/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "contributes": { - "snippets": [ - { - "language": "python", - "path": "./python.json" - }, - { - "language": "go", - "path": "./go.json" - }, - { - "language": [ - "terraform", - "terraform-vars", - "opentofu", - "opentofu-vars", - "tf" - ], - "path": "./terraform.json" - } - ] - }, - "engines": { - "vscode": "^1.11.0" - }, - "name": "personal-snippets", - "version": "1.0.0" -} diff --git a/snippets/python.json b/snippets/python.json deleted file mode 100644 index 749e950..0000000 --- a/snippets/python.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "function definition": { - "prefix": "def", - "body": [ - "def ${1:function_name}(${2}):", - " \"\"\"${3:Description}\"\"\"", - " ${0}" - ], - "description": "Function with docstring" - }, - "class definition": { - "prefix": "class", - "body": [ - "class ${1:ClassName}(${2:object}):", - " \"\"\"${3:Description}\"\"\"", - "", - " def __init__(self${4}):", - " ${0}" - ], - "description": "Class with __init__ and docstring" - }, - "if main": { - "prefix": "ifmain", - "body": [ - "if __name__ == \"__main__\":", - " main()" - ], - "description": "if __name__ == \"__main__\" guard" - } -} diff --git a/snippets/terraform.json b/snippets/terraform.json deleted file mode 100644 index 1a346e8..0000000 --- a/snippets/terraform.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "resource block": { - "prefix": "resource", - "body": [ - "resource \"${1:resource_type}\" \"${2:name}\" {", - " ${0}", - "}" - ], - "description": "Terraform/OpenTofu resource block" - }, - "variable block": { - "prefix": "variable", - "body": [ - "variable \"${1:var_name}\" {", - " description = \"${2:description}\"", - " type = ${3|string,number,list(string),map(string),set(string),any|}", - " default = ${4}", - "", - " validation {", - " condition = ${5:true}", - " error_message = \"${6:Invalid value.}\"", - " }", - "}" - ], - "description": "Variable block with validation (remove manually for bool)" - }, - "variable block (bool)": { - "prefix": "variableb", - "body": [ - "variable \"${1:var_name}\" {", - " description = \"${2:description}\"", - " type = bool", - " default = ${3:false}", - "}" - ], - "description": "Bool variable block (no validation)" - }, - "output block": { - "prefix": "output", - "body": [ - "output \"${1:output_name}\" {", - " description = \"${2:description}\"", - " value = ${0}", - "}" - ], - "description": "Terraform/OpenTofu output block" - }, - "module block": { - "prefix": "module", - "body": [ - "module \"${1:module_name}\" {", - " source = \"${2:./modules/example}\"", - "", - " # Required variables:", - " ${3:# Add required vars}", - "", - " # Optional variables:", - " ${0}", - "}" - ], - "description": "Terraform/OpenTofu module block" - }, - "data source": { - "prefix": "data", - "body": [ - "data \"${1:source_type}\" \"${2:name}\" {", - " ${0}", - "}" - ], - "description": "Terraform/OpenTofu data source block" - }, - "locals": { - "prefix": "locals", - "body": [ - "locals {", - " ${1:name} = ${0}", - "}" - ], - "description": "Terraform/OpenTofu locals block" - }, - "lifecycle": { - "prefix": "lifecycle", - "body": [ - "lifecycle {", - " ${1|prevent_destroy,create_before_destroy,ignore_changes|} = ${0:true}", - "}" - ], - "description": "Terraform/OpenTofu lifecycle meta-argument" - }, - "dynamic block": { - "prefix": "dynamic", - "body": [ - "dynamic \"${1:block_name}\" {", - " for_each = ${2:var.items}", - " content {", - " ${0}", - " }", - "}" - ], - "description": "Terraform/OpenTofu dynamic block" - }, - "moved block": { - "prefix": "moved", - "body": [ - "moved {", - " from = ${1:old.address}", - " to = ${2:new.address}", - "}" - ], - "description": "Refactor resource address without destroy/recreate" - }, - "import block": { - "prefix": "import", - "body": [ - "import {", - " to = ${1:resource.address}", - " id = \"${2:id}\"", - "}" - ], - "description": "Declarative import (Terraform 1.5+ / OpenTofu)" - } -} diff --git a/snippets/tf.json b/snippets/tf.json deleted file mode 100644 index c413eff..0000000 --- a/snippets/tf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "variable": { - "body": [ - "variable {", - " name = \"\"", - " value = \"\"", - "}" - ], - "prefix": "variable" - } -} diff --git a/statusline.lua b/statusline.lua new file mode 100644 index 0000000..61d9f85 --- /dev/null +++ b/statusline.lua @@ -0,0 +1,146 @@ +-- ============================================================================ +-- STATUSLINE +-- ============================================================================ + +-- Git branch function with caching and Nerd Font icon +local cached_branch = "" +local last_check = 0 +local function git_branch() + local now = vim.uv.now() + if now - last_check > 5000 then -- Check every 5 seconds + cached_branch = vim.fn.system("git branch --show-current 2>/dev/null | tr -d '\n'") + last_check = now + end + if cached_branch ~= "" then + return " \u{e725} " .. cached_branch .. " " -- nf-dev-git_branch + end + return "" +end + +-- File type with Nerd Font icon +local function file_type() + local ft = vim.bo.filetype + local icons = { + lua = "\u{e620} ", -- nf-dev-lua + python = "\u{e73c} ", -- nf-dev-python + javascript = "\u{e74e} ", -- nf-dev-javascript + typescript = "\u{e628} ", -- nf-dev-typescript + javascriptreact = "\u{e7ba} ", + typescriptreact = "\u{e7ba} ", + html = "\u{e736} ", -- nf-dev-html5 + css = "\u{e749} ", -- nf-dev-css3 + scss = "\u{e749} ", + json = "\u{e60b} ", -- nf-dev-json + markdown = "\u{e73e} ", -- nf-dev-markdown + vim = "\u{e62b} ", -- nf-dev-vim + sh = "\u{f489} ", -- nf-oct-terminal + bash = "\u{f489} ", + zsh = "\u{f489} ", + rust = "\u{e7a8} ", -- nf-dev-rust + go = "\u{e724} ", -- nf-dev-go + c = "\u{e61e} ", -- nf-dev-c + cpp = "\u{e61d} ", -- nf-dev-cplusplus + java = "\u{e738} ", -- nf-dev-java + php = "\u{e73d} ", -- nf-dev-php + ruby = "\u{e739} ", -- nf-dev-ruby + swift = "\u{e755} ", -- nf-dev-swift + kotlin = "\u{e634} ", + dart = "\u{e798} ", + elixir = "\u{e62d} ", + haskell = "\u{e777} ", + sql = "\u{e706} ", + yaml = "\u{f481} ", + toml = "\u{e615} ", + xml = "\u{f05c} ", + dockerfile = "\u{f308} ", -- nf-linux-docker + gitcommit = "\u{f418} ", -- nf-oct-git_commit + gitconfig = "\u{f1d3} ", -- nf-fa-git + vue = "\u{fd42} ", -- nf-md-vuejs + svelte = "\u{e697} ", + astro = "\u{e628} ", + } + + if ft == "" then + return " \u{f15b} " -- nf-fa-file_o + end + + return ((icons[ft] or " \u{f15b} ") .. ft) +end + +-- File size with Nerd Font icon +local function file_size() + local size = vim.fn.getfsize(vim.fn.expand("%")) + if size < 0 then + return "" + end + local size_str + if size < 1024 then + size_str = size .. "B" + elseif size < 1024 * 1024 then + size_str = string.format("%.1fK", size / 1024) + else + size_str = string.format("%.1fM", size / 1024 / 1024) + end + return " \u{f016} " .. size_str .. " " -- nf-fa-file_o +end + +-- Mode indicators with Nerd Font icons +local function mode_icon() + local mode = vim.fn.mode() + local modes = { + n = " \u{f121} NORMAL", + i = " \u{f11c} INSERT", + v = " \u{f0168} VISUAL", + V = " \u{f0168} V-LINE", + ["\22"] = " \u{f0168} V-BLOCK", + c = " \u{f120} COMMAND", + s = " \u{f0c5} SELECT", + S = " \u{f0c5} S-LINE", + ["\19"] = " \u{f0c5} S-BLOCK", + R = " \u{f044} REPLACE", + r = " \u{f044} REPLACE", + ["!"] = " \u{f489} SHELL", + t = " \u{f120} TERMINAL", + } + return modes[mode] or (" \u{f059} " .. mode) +end + +_G.mode_icon = mode_icon +_G.git_branch = git_branch +_G.file_type = file_type +_G.file_size = file_size + +vim.cmd([[ + highlight StatusLineBold gui=bold cterm=bold +]]) + +-- Function to change statusline based on window focus +local function setup_dynamic_statusline() + vim.api.nvim_create_autocmd({ "WinEnter", "BufEnter" }, { + callback = function() + vim.opt_local.statusline = table.concat({ + " ", + "%#StatusLineBold#", + "%{v:lua.mode_icon()}", + "%#StatusLine#", + " \u{e0b1} %f %h%m%r", -- nf-pl-left_hard_divider + "%{v:lua.git_branch()}", + "\u{e0b1} ", -- nf-pl-left_hard_divider + "%{v:lua.file_type()}", + "\u{e0b1} ", -- nf-pl-left_hard_divider + "%{v:lua.file_size()}", + "%=", -- Right-align everything after this + " \u{f017} %l:%c %P ", -- nf-fa-clock_o for line/col + }) + end, + }) + vim.api.nvim_set_hl(0, "StatusLineBold", { bold = true }) + + vim.api.nvim_create_autocmd({ "WinLeave", "BufLeave" }, { + callback = function() + vim.opt_local.statusline = " %f %h%m%r \u{e0b1} %{v:lua.file_type()} %= %l:%c %P " + end, + }) +end + +setup_dynamic_statusline() From 20c2653e7ea259380ce9fa645d653af1ccea3b75 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Tue, 16 Jun 2026 21:40:26 -0500 Subject: [PATCH 02/12] feat: more progress Signed-off-by: Tristan Jahnke --- config.lua | 80 --------------- init.lua | 1 - keymaps.lua | 102 ------------------- autocmds.lua => lua/autocmds.lua | 34 +++++++ lua/keymaps.lua | 68 +++++++++++++ options.lua => lua/options.lua | 115 ++++++++++----------- nvim-pack-lock.json | 20 ++++ plugins/autopair.lua | 7 ++ plugins/blink.lua | 39 ++++++++ plugins/mini.lua | 10 ++ plugins/snacks.lua | 165 +++++++++++++++---------------- plugins/vim-tmux-navigator.lua | 10 ++ plugins/which-key.lua | 22 +++++ statusline.lua | 146 --------------------------- 14 files changed, 341 insertions(+), 478 deletions(-) delete mode 100644 config.lua delete mode 100644 keymaps.lua rename autocmds.lua => lua/autocmds.lua (75%) create mode 100644 lua/keymaps.lua rename options.lua => lua/options.lua (87%) create mode 100644 plugins/autopair.lua create mode 100644 plugins/blink.lua create mode 100644 plugins/mini.lua create mode 100644 plugins/which-key.lua delete mode 100644 statusline.lua diff --git a/config.lua b/config.lua deleted file mode 100644 index d7a750c..0000000 --- a/config.lua +++ /dev/null @@ -1,80 +0,0 @@ --- ============================================================================ --- OPTIONS --- ============================================================================ -vim.opt.number = true -- line number -vim.opt.relativenumber = true -- relative line numbers -vim.opt.cursorline = true -- highlight current line -vim.opt.wrap = false -- do not wrap lines by default -vim.opt.scrolloff = 10 -- keep 10 lines above/below cursor -vim.opt.sidescrolloff = 10 -- keep 10 lines to left/right of cursor -vim.opt.tabstop = 2 -- tabwidth -vim.opt.shiftwidth = 2 -- indent width -vim.opt.softtabstop = 2 -- soft tab stop not tabs on tab/backspace -vim.opt.expandtab = true -- use spaces instead of tabs -vim.opt.smartindent = true -- smart auto-indent -vim.opt.autoindent = true -- copy indent from current line - -vim.opt.ignorecase = true -- case insensitive search -vim.opt.smartcase = true -- case sensitive if uppercase in string -vim.opt.hlsearch = true -- highlight search matches -vim.opt.incsearch = true -- show matches as you type - -vim.opt.signcolumn = "yes" -- always show a sign column -vim.opt.colorcolumn = "100" -- show a column at 100 position chars -vim.opt.showmatch = true -- highlights matching brackets -vim.opt.cmdheight = 1 -- single line command line -vim.opt.completeopt = "menuone,noinsert,noselect" -- completion options -vim.opt.showmode = false -- do not show the mode, instead have it in statusline -vim.opt.pumheight = 10 -- popup menu height -vim.opt.pumblend = 10 -- popup menu transparency -vim.opt.winblend = 0 -- floating window transparency -vim.opt.concealcursor = "" -- do not hide cursorline in markup -vim.opt.synmaxcol = 300 -- syntax highlighting limit -vim.opt.fillchars = { eob = " " } -- hide "~" on empty lines - -local undodir = vim.fn.expand("~/.vim/undodir") -if - vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent -then - vim.fn.mkdir(undodir, "p") -end - -vim.opt.backup = false -- do not create a backup file -vim.opt.writebackup = false -- do not write to a backup file -vim.opt.swapfile = false -- do not create a swapfile -vim.opt.undofile = true -- do create an undo file -vim.opt.undodir = undodir -- set the undo directory -vim.opt.updatetime = 300 -- faster completion -vim.opt.timeoutlen = 500 -- timeout duration -vim.opt.ttimeoutlen = 50 -- key code timeout -vim.opt.autoread = true -- auto-reload changes if outside of neovim -vim.opt.autowrite = false -- do not auto-save - -vim.opt.hidden = true -- allow hidden buffers -vim.opt.errorbells = false -- no error sounds -vim.opt.backspace = "indent,eol,start" -- better backspace behaviour -vim.opt.autochdir = false -- do not autochange directories -vim.opt.iskeyword:append("-") -- include - in words -vim.opt.path:append("**") -- include subdirs in search -vim.opt.selection = "inclusive" -- include last char in selection -vim.opt.mouse = "a" -- enable mouse support -vim.opt.clipboard:append("unnamedplus") -- use system clipboard -vim.opt.modifiable = true -- allow buffer modifications - --- guicursor: configure cursor shape, blink timing, and highlight per editor mode -vim.opt.guicursor = - "n-v-c:block,i-ci-ve:block,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175" -- cursor blinking and settings - --- Folding: requires treesitter available at runtime; safe fallback if not -vim.opt.foldmethod = "expr" -- use expression for folding -vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" -- use treesitter for folding -vim.opt.foldlevel = 99 -- start with all folds open - -vim.opt.splitbelow = true -- horizontal splits go below -vim.opt.splitright = true -- vertical splits go right - -vim.opt.wildmenu = true -- tab completion -vim.opt.wildmode = "longest:full,full" -- complete longest common match, full completion list, cycle through with Tab -vim.opt.diffopt:append("linematch:60") -- improve diff display -vim.opt.redrawtime = 10000 -- increase neovim redraw tolerance -vim.opt.maxmempattern = 20000 -- increase max memory diff --git a/init.lua b/init.lua index 9578488..e01f382 100644 --- a/init.lua +++ b/init.lua @@ -16,7 +16,6 @@ vim.g.loaded_node_provider = 0 require("autocmds") require("keymaps") require("options") -require("statusline") --- Plugins --- Each file in the plugins/ dir returns a spec table: diff --git a/keymaps.lua b/keymaps.lua deleted file mode 100644 index cad28da..0000000 --- a/keymaps.lua +++ /dev/null @@ -1,102 +0,0 @@ --- ============================================================================ --- KEYMAPS --- ============================================================================ - -vim.keymap.set("i", "jk", "", { desc = "Exit insert mode with jk" }) - --- better movement in wrapped text -vim.keymap.set("n", "j", function() - return vim.v.count == 0 and "gj" or "j" -end, { expr = true, silent = true, desc = "Down (wrap-aware)" }) -vim.keymap.set("n", "k", function() - return vim.v.count == 0 and "gk" or "k" -end, { expr = true, silent = true, desc = "Up (wrap-aware)" }) - -vim.keymap.set("n", "", ":nohlsearch", { desc = "Clear search highlights" }) - -vim.keymap.set("n", "n", "nzzzv", { desc = "Next search result (centered)" }) -vim.keymap.set("n", "N", "Nzzzv", { desc = "Previous search result (centered)" }) -vim.keymap.set("n", "", "zz", { desc = "Half page down (centered)" }) -vim.keymap.set("n", "", "zz", { desc = "Half page up (centered)" }) - -vim.keymap.set("x", "p", '"_dP', { desc = "Paste without yanking" }) -vim.keymap.set({ "n", "v" }, "x", '"_d', { desc = "Delete without yanking" }) - -vim.keymap.set("n", "bn", ":bnext", { desc = "Next buffer" }) -vim.keymap.set("n", "bp", ":bprevious", { desc = "Previous buffer" }) - -vim.keymap.set("n", "", "TmuxNavigateLeft", { desc = "Move to left window/pane" }) -vim.keymap.set("n", "", "TmuxNavigateDown", { desc = "Move to bottom window/pane" }) -vim.keymap.set("n", "", "TmuxNavigateUp", { desc = "Move to top window/pane" }) -vim.keymap.set("n", "", "TmuxNavigateRight", { desc = "Move to right window/pane" }) - -vim.keymap.set("n", "sv", ":vsplit", { desc = "Split window vertically" }) -vim.keymap.set("n", "sh", ":split", { desc = "Split window horizontally" }) -vim.keymap.set("n", "", ":resize +2", { desc = "Increase window height" }) -vim.keymap.set("n", "", ":resize -2", { desc = "Decrease window height" }) -vim.keymap.set("n", "", ":vertical resize -2", { desc = "Decrease window width" }) -vim.keymap.set("n", "", ":vertical resize +2", { desc = "Increase window width" }) - -vim.keymap.set("n", "", ":m .+1==", { desc = "Move line down" }) -vim.keymap.set("n", "", ":m .-2==", { desc = "Move line up" }) -vim.keymap.set("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) -vim.keymap.set("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) - -vim.keymap.set("v", "<", "", ">gv", { desc = "Indent right and reselect" }) - -vim.keymap.set("n", "J", "mzJ`z", { desc = "Join lines and keep cursor position" }) - -vim.keymap.set("n", "pa", function() -- show file path - local path = vim.fn.expand("%:p") - vim.fn.setreg("+", path) - print("file:", path) -end, { desc = "Copy full file path" }) - -vim.keymap.set("n", "td", function() - vim.diagnostic.enable(not vim.diagnostic.is_enabled()) -end, { desc = "Toggle diagnostics" }) - --- snacks.nvim ---------------------------------------------------------------- --- Picker (fuzzy finder) -vim.keymap.set("n", "ff", function() - Snacks.picker.files({ hidden = true, ignored = true }) -end, { desc = "Find files" }) -vim.keymap.set("n", "fg", function() - Snacks.picker.grep({ hidden = true, ignored = true }) -end, { desc = "Grep files" }) -vim.keymap.set("n", "fb", function() - Snacks.picker.buffers() -end, { desc = "Find buffers" }) -vim.keymap.set("n", "fr", function() - Snacks.picker.recent() -end, { desc = "Recent files" }) -vim.keymap.set("n", "fh", function() - Snacks.picker.help() -end, { desc = "Help tags" }) -vim.keymap.set("n", "fd", function() - Snacks.picker.diagnostics() -end, { desc = "Diagnostics" }) -vim.keymap.set("n", "fk", function() - Snacks.picker.keymaps() -end, { desc = "Keymaps" }) -vim.keymap.set("n", "fs", function() - Snacks.picker.lsp_symbols() -end, { desc = "Document symbols" }) -vim.keymap.set("n", "/", function() - Snacks.picker.lines() -end, { desc = "Search current buffer" }) -vim.keymap.set("n", "gg", function() - Snacks.lazygit() -end, { desc = "Open Lazygit" }) - --- Explorer (file tree) -vim.keymap.set("n", "e", function() - Snacks.explorer() -end, { desc = "Toggle file explorer" }) - --- Terminal -vim.keymap.set("n", "tt", function() - Snacks.terminal.toggle() -end, { desc = "Toggle terminal" }) -vim.keymap.set("t", "", "close", { desc = "Hide terminal" }) diff --git a/autocmds.lua b/lua/autocmds.lua similarity index 75% rename from autocmds.lua rename to lua/autocmds.lua index c64fe50..30766cb 100644 --- a/autocmds.lua +++ b/lua/autocmds.lua @@ -99,3 +99,37 @@ vim.api.nvim_create_autocmd("FileType", { vim.opt_local.spell = true end, }) + +local function complete_packages(match) + return vim + .iter(vim.pack.get()) + :map(function(pack) + return pack.spec.name + end) + :filter(function(pack) + return pack:find(match) + end) + :totable() +end + +vim.api.nvim_create_user_command("PackUpdate", function(info) + if #info.fargs ~= 0 then + vim.pack.update(info.fargs, { force = info.bang }) + else + vim.pack.update(nil, { force = info.bang }) + end +end, { + desc = "Update packages", + nargs = "*", + bang = true, + complete = complete_packages, +}) + +vim.api.nvim_create_user_command("PackDelete", function(info) + vim.pack.del(info.fargs, { force = info.bang }) +end, { + desc = "Delete packages", + nargs = "+", + bang = true, + complete = complete_packages, +}) diff --git a/lua/keymaps.lua b/lua/keymaps.lua new file mode 100644 index 0000000..d1f2a82 --- /dev/null +++ b/lua/keymaps.lua @@ -0,0 +1,68 @@ +-- ============================================================================ +-- KEYMAPS (core / editor only) +-- +-- Convention: +-- * This file holds ONLY built-in, plugin-agnostic keymaps. +-- * Plugin-specific keymaps live in that plugin's `config` function under +-- plugins/.lua, so they load right after the plugin is set up and +-- travel with the plugin if it's ever removed. +-- * Keep maps grouped under the section headers below. Add new sections as +-- needed rather than appending to the bottom. +-- ============================================================================ + +-- Thin wrapper so each mapping is a single readable line. +local function map(mode, lhs, rhs, desc, opts) + opts = vim.tbl_extend("force", { desc = desc }, opts or {}) + vim.keymap.set(mode, lhs, rhs, opts) +end + +-- Insert ---------------------------------------------------------------------- +map("i", "jk", "", "Exit insert mode with jk") + +-- Movement -------------------------------------------------------------------- +map("n", "j", function() + return vim.v.count == 0 and "gj" or "j" +end, "Down (wrap-aware)", { expr = true, silent = true }) +map("n", "k", function() + return vim.v.count == 0 and "gk" or "k" +end, "Up (wrap-aware)", { expr = true, silent = true }) +map("n", "", "zz", "Half page down (centered)") +map("n", "", "zz", "Half page up (centered)") + +-- Search ---------------------------------------------------------------------- +map("n", "", ":nohlsearch", "Clear search highlights") +map("n", "n", "nzzzv", "Next search result (centered)") +map("n", "N", "Nzzzv", "Previous search result (centered)") + +-- Editing --------------------------------------------------------------------- +map("x", "p", '"_dP', "Paste without yanking") +map({ "n", "v" }, "x", '"_d', "Delete without yanking") +map("n", "", ":m .+1==", "Move line down") +map("n", "", ":m .-2==", "Move line up") +map("v", "", ":m '>+1gv=gv", "Move selection down") +map("v", "", ":m '<-2gv=gv", "Move selection up") +map("v", "<", "", ">gv", "Indent right and reselect") +map("n", "J", "mzJ`z", "Join lines and keep cursor position") + +-- Buffers --------------------------------------------------------------------- +map("n", "bn", ":bnext", "Next buffer") +map("n", "bp", ":bprevious", "Previous buffer") + +-- Windows --------------------------------------------------------------------- +map("n", "sv", ":vsplit", "Split window vertically") +map("n", "sh", ":split", "Split window horizontally") +map("n", "", ":resize +2", "Increase window height") +map("n", "", ":resize -2", "Decrease window height") +map("n", "", ":vertical resize -2", "Decrease window width") +map("n", "", ":vertical resize +2", "Increase window width") + +-- Utility / toggles ----------------------------------------------------------- +map("n", "pa", function() -- copy full file path + local path = vim.fn.expand("%:p") + vim.fn.setreg("+", path) + print("file:", path) +end, "Copy full file path") +map("n", "td", function() + vim.diagnostic.enable(not vim.diagnostic.is_enabled()) +end, "Toggle diagnostics") diff --git a/options.lua b/lua/options.lua similarity index 87% rename from options.lua rename to lua/options.lua index affbd2d..13339fe 100644 --- a/options.lua +++ b/lua/options.lua @@ -1,81 +1,66 @@ -- ============================================================================ -- OPTIONS -- ============================================================================ -vim.opt.number = true -- line number -vim.opt.relativenumber = true -- relative line numbers -vim.opt.cursorline = true -- highlight current line -vim.opt.wrap = false -- do not wrap lines by default -vim.opt.scrolloff = 10 -- keep 10 lines above/below cursor -vim.opt.sidescrolloff = 10 -- keep 10 lines to left/right of cursor - -vim.opt.tabstop = 2 -- tabwidth -vim.opt.shiftwidth = 2 -- indent width -vim.opt.softtabstop = 2 -- soft tab stop not tabs on tab/backspace -vim.opt.expandtab = true -- use spaces instead of tabs -vim.opt.smartindent = true -- smart auto-indent +vim.opt.autochdir = false -- do not autochange directories vim.opt.autoindent = true -- copy indent from current line - -vim.opt.ignorecase = true -- case insensitive search -vim.opt.smartcase = true -- case sensitive if uppercase in string -vim.opt.hlsearch = true -- highlight search matches -vim.opt.incsearch = true -- show matches as you type - -vim.opt.signcolumn = "yes" -- always show a sign column -vim.opt.colorcolumn = "100" -- show a column at 100 position chars -vim.opt.showmatch = true -- highlights matching brackets +vim.opt.autoread = true -- auto-reload changes if outside of neovim +vim.opt.autowrite = false -- do not auto-save +vim.opt.backspace = "indent,eol,start" -- better backspace behaviour +vim.opt.backup = false -- do not create a backup file +vim.opt.clipboard:append("unnamedplus") -- use system clipboard vim.opt.cmdheight = 1 -- single line command line +vim.opt.colorcolumn = "100" -- show a column at 100 position chars vim.opt.completeopt = "menuone,noinsert,noselect" -- completion options -vim.opt.showmode = false -- do not show the mode, instead have it in statusline -vim.opt.pumheight = 10 -- popup menu height -vim.opt.pumblend = 10 -- popup menu transparency -vim.opt.winblend = 0 -- floating window transparency vim.opt.concealcursor = "" -- do not hide cursorline in markup -vim.opt.synmaxcol = 300 -- syntax highlighting limit +vim.opt.cursorline = true -- highlight current line +vim.opt.diffopt:append("linematch:60") -- improve diff display +vim.opt.errorbells = false -- no error sounds +vim.opt.expandtab = true -- use spaces instead of tabs vim.opt.fillchars = { eob = " " } -- hide "~" on empty lines - -local undodir = vim.fn.expand("~/.vim/undodir") -if - vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent -then - vim.fn.mkdir(undodir, "p") -end - -vim.opt.backup = false -- do not create a backup file -vim.opt.writebackup = false -- do not write to a backup file -vim.opt.swapfile = false -- do not create a swapfile -vim.opt.undofile = true -- do create an undo file -vim.opt.undodir = undodir -- set the undo directory -vim.opt.updatetime = 300 -- faster completion -vim.opt.timeoutlen = 500 -- timeout duration -vim.opt.ttimeoutlen = 50 -- key code timeout -vim.opt.autoread = true -- auto-reload changes if outside of neovim -vim.opt.autowrite = false -- do not auto-save - +vim.opt.foldlevel = 99 -- start with all folds open +vim.opt.foldmethod = "expr" vim.opt.hidden = true -- allow hidden buffers -vim.opt.errorbells = false -- no error sounds -vim.opt.backspace = "indent,eol,start" -- better backspace behaviour -vim.opt.autochdir = false -- do not autochange directories +vim.opt.hlsearch = true -- highlight search matches +vim.opt.ignorecase = true -- case insensitive search +vim.opt.incsearch = true -- show matches as you type vim.opt.iskeyword:append("-") -- include - in words +vim.opt.maxmempattern = 20000 -- increase max memory +vim.opt.modifiable = true -- allow buffer modifications +vim.opt.mouse = "a" -- enable mouse support +vim.opt.number = true -- line number vim.opt.path:append("**") -- include subdirs in search +vim.opt.pumblend = 10 -- popup menu transparency +vim.opt.pumheight = 10 -- popup menu height +vim.opt.redrawtime = 10000 -- increase neovim redraw tolerance +vim.opt.relativenumber = true -- relative line numbers +vim.opt.scrolloff = 10 -- keep 10 lines above/below cursor vim.opt.selection = "inclusive" -- include last char in selection -vim.opt.mouse = "a" -- enable mouse support -vim.opt.clipboard:append("unnamedplus") -- use system clipboard -vim.opt.modifiable = true -- allow buffer modifications - --- guicursor: configure cursor shape, blink timing, and highlight per editor mode -vim.opt.guicursor = - "n-v-c:block,i-ci-ve:block,r-cr:hor20,o:hor50,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor,sm:block-blinkwait175-blinkoff150-blinkon175" -- cursor blinking and settings - --- Folding: requires treesitter available at runtime; safe fallback if not -vim.opt.foldmethod = "expr" -- use expression for folding -vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" -- use treesitter for folding -vim.opt.foldlevel = 99 -- start with all folds open - +vim.opt.shiftwidth = 2 -- indent width +vim.opt.showmatch = true -- highlights matching brackets +vim.opt.showmode = false -- do not show the mode, instead have it in statusline +vim.opt.sidescrolloff = 10 -- keep 10 lines to left/right of cursor +vim.opt.signcolumn = "yes" -- always show a sign column +vim.opt.smartcase = true -- case sensitive if uppercase in string +vim.opt.smartindent = true -- smart auto-indent +vim.opt.softtabstop = 2 -- soft tab stop not tabs on tab/backspace vim.opt.splitbelow = true -- horizontal splits go below vim.opt.splitright = true -- vertical splits go right - +vim.opt.swapfile = false -- do not create a swapfile +vim.opt.synmaxcol = 300 -- syntax highlighting limit +vim.opt.tabstop = 2 -- tabwidth +vim.opt.timeoutlen = 500 -- timeout duration +vim.opt.ttimeoutlen = 50 -- key code timeout +vim.opt.undodir = undodir -- set the undo directory +vim.opt.undofile = true -- do create an undo file +vim.opt.updatetime = 300 -- faster completion vim.opt.wildmenu = true -- tab completion vim.opt.wildmode = "longest:full,full" -- complete longest common match, full completion list, cycle through with Tab -vim.opt.diffopt:append("linematch:60") -- improve diff display -vim.opt.redrawtime = 10000 -- increase neovim redraw tolerance -vim.opt.maxmempattern = 20000 -- increase max memory +vim.opt.winblend = 0 -- floating window transparency +vim.opt.wrap = false -- do not wrap lines by default +vim.opt.writebackup = false -- do not write to a backup file +local undodir = vim.fn.expand("~/.vim/undodir") +if + vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent +then + vim.fn.mkdir(undodir, "p") +end diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index b0b9a27..072001e 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -1,5 +1,10 @@ { "plugins": { + "blink.cmp": { + "rev": "78336bc89ee5365633bcf754d93df01678b5c08f", + "src": "https://github.com/saghen/blink.cmp", + "version": "1.0.0 - 2.0.0" + }, "conform.nvim": { "rev": "3543d000dafbc41cc7761d860cfdb24e82154f75", "src": "https://github.com/stevearc/conform.nvim", @@ -10,6 +15,16 @@ "src": "https://github.com/lewis6991/gitsigns.nvim", "version": "'v2.1.0'" }, + "mini.nvim": { + "rev": "a995fe9cd4193fb492b5df69175a351a74b3d36b", + "src": "https://github.com/nvim-mini/mini.nvim", + "version": "'stable'" + }, + "nvim-autopairs": { + "rev": "23320e75953ac82e559c610bec5a90d9c6dfa743", + "src": "https://github.com/windwp/nvim-autopairs", + "version": "'0.10.0'" + }, "nvim-treesitter": { "rev": "4916d6592ede8c07973490d9322f187e07dfefac", "src": "https://github.com/nvim-treesitter/nvim-treesitter", @@ -23,6 +38,11 @@ "vim-tmux-navigator": { "rev": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432", "src": "https://github.com/christoomey/vim-tmux-navigator" + }, + "which-key.nvim": { + "rev": "fcbf4eea17cb299c02557d576f0d568878e354a4", + "src": "https://github.com/folke/which-key.nvim", + "version": "'v3.17.0'" } } } diff --git a/plugins/autopair.lua b/plugins/autopair.lua new file mode 100644 index 0000000..a9bbd97 --- /dev/null +++ b/plugins/autopair.lua @@ -0,0 +1,7 @@ +return { + src = "https://github.com/windwp/nvim-autopairs", + version = "0.10.0", + config = function() + require("nvim-autopairs").setup() + end, +} diff --git a/plugins/blink.lua b/plugins/blink.lua new file mode 100644 index 0000000..c985f1b --- /dev/null +++ b/plugins/blink.lua @@ -0,0 +1,39 @@ +return { + src = "https://github.com/saghen/blink.cmp", + version = vim.version.range("1.*"), + config = function() + require("blink.cmp").setup({ + keymap = { preset = "default" }, + appearance = { + nerd_font_variant = "mono", + }, + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + }, + completion = { + documentation = { + auto_show = true, + auto_show_delay_ms = 500, + update_delay_ms = 50, + window = { + border = "rounded", + }, + }, + ghost_text = { enabled = true }, + menu = { + border = "rounded", + auto_show = true, + max_height = 10, + scrolloff = 2, + scrollbar = true, + draw = { + treesitter = { "lsp" }, + columns = { { "label", "label_description", gap = 1 }, { "kind_icon", "kind" } }, + }, + }, + }, + signature = { enabled = true }, + fuzzy = { implementation = "prefer_rust" }, + }) + end, +} diff --git a/plugins/mini.lua b/plugins/mini.lua new file mode 100644 index 0000000..12bd6e6 --- /dev/null +++ b/plugins/mini.lua @@ -0,0 +1,10 @@ +return { + src = "https://github.com/nvim-mini/mini.nvim", + version = "stable", + config = function() + require("mini.statusline").setup() + require("mini.map").setup() + require("mini.tabline").setup() + require("mini.icons").setup() + end, +} diff --git a/plugins/snacks.lua b/plugins/snacks.lua index b4596e9..799208b 100644 --- a/plugins/snacks.lua +++ b/plugins/snacks.lua @@ -3,57 +3,11 @@ return { version = "v2.31.0", config = function() require("snacks").setup({ - bigfile = { enabled = true }, -- disables heavy features on huge files + animate = { enabled = true }, + bigfile = { enabled = true }, + bufferline = { enabled = true }, dashboard = { - enabled = true, - width = 60, - row = nil, -- dashboard position. nil for center - col = nil, -- dashboard position. nil for center - pane_gap = 4, -- empty columns between vertical panes preset = { - ---@type fun(cmd:string, opts:table)|nil - pick = "snacks", - -- Used by the `keys` section to show keymaps. - -- Set your custom keymaps here. - -- When using a function, the `items` argument are the default keymaps. - ---@type snacks.dashboard.Item[] - keys = { - { - icon = "๏€‚ ", - key = "f", - desc = "Find File", - action = ":lua Snacks.dashboard.pick('files')", - }, - { icon = "๏…› ", key = "n", desc = "New File", action = ":ene | startinsert" }, - { - icon = "๏€ข ", - key = "g", - desc = "Find Text", - action = ":lua Snacks.dashboard.pick('live_grep')", - }, - { - icon = "๏ƒ… ", - key = "r", - desc = "Recent Files", - action = ":lua Snacks.dashboard.pick('oldfiles')", - }, - { - icon = "๏ฃ ", - key = "c", - desc = "Config", - action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})", - }, - { icon = "๎ˆ ", key = "s", desc = "Restore Session", section = "session" }, - { - icon = "๓ฐ’ฒ ", - key = "L", - desc = "Lazy", - action = ":Lazy", - enabled = package.loaded.lazy ~= nil, - }, - { icon = "๏ฆ ", key = "q", desc = "Quit", action = ":qa" }, - }, - -- Used by the `header` section header = [[ -------------------------------------------------------------------------------------------------------- โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— @@ -64,41 +18,59 @@ return { โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• -------------------------------------------------------------------------------------------------------- ]], - }, - -- item field formatters - formats = { - icon = function(item) - if item.file and item.icon == "file" or item.icon == "directory" then - return Snacks.dashboard.icon(item.file, item.icon) - end - return { item.icon, width = 2, hl = "icon" } - end, - footer = { "%s", align = "center" }, - header = { "%s", align = "center" }, - file = function(item, ctx) - local fname = vim.fn.fnamemodify(item.file, ":~") - fname = ctx.width and #fname > ctx.width and vim.fn.pathshorten(fname) or fname - if #fname > ctx.width then - local dir = vim.fn.fnamemodify(fname, ":h") - local file = vim.fn.fnamemodify(fname, ":t") - if dir and file then - file = file:sub(-(ctx.width - #dir - 2)) - fname = dir .. "/โ€ฆ" .. file - end - end - local dir, file = fname:match("^(.*)/(.+)$") - return dir and { { dir .. "/", hl = "dir" }, { file, hl = "file" } } or { { fname, hl = "file" } } - end, + keys = { + { icon = "๓ฐˆž", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" }, + { icon = "๎ฉฟ", key = "n", desc = "New File", action = ":ene | startinsert" }, + { icon = "๓ฐชถ", key = "r", desc = "Recent Files", action = ":lua Snacks.dashboard.pick('oldfiles')" }, + { icon = "๓ฑ‰ถ", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" }, + { + icon = "๎ทˆ", + key = "c", + desc = "Config", + action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})", + }, + { icon = "๓ฐฉˆ", key = "q", desc = "Quit", action = ":qa" }, + }, }, sections = { { section = "header" }, - { section = "keys", gap = 1, padding = 1 }, + { section = "keys", title = "Keymaps", indent = 2, padding = 1 }, + { + icon = "๏…› ", + title = "Recent Files", + section = "recent_files", + indent = 2, + padding = 1, + }, + { + icon = "๏ผ ", + title = "Projects", + section = "projects", + indent = 2, + padding = 1, + }, + { + icon = "๎œฅ ", + title = "Git Status", + section = "terminal", + enabled = function() + return Snacks.git.get_root() ~= nil + end, + cmd = "git status --short --branch --renames", + height = 5, + padding = 1, + ttl = 5 * 60, + indent = 3, + }, }, }, - explorer = { enabled = true, hidden = true, ignored = true }, -- file explorer (uses picker) - indent = { enabled = true }, -- indent guides + dim = { enabled = true }, + explorer = { enabled = true, trash = true, replace_netrw = true }, + git = { enabled = true }, + image = { enabled = true }, + indent = { enabled = true }, + input = { enabled = true }, lazygit = { enabled = true }, - notifier = { enabled = true }, -- vim.notify replacement picker = { enabled = true, hidden = true, @@ -112,12 +84,37 @@ return { }, }, }, - }, -- fuzzy finder (files, grep, buffers, ...) - quickfile = { enabled = true }, -- render files before plugins load - scroll = { enabled = true }, -- smooth scrolling - statuscolumn = { enabled = true }, -- pretty status column - terminal = { enabled = true }, -- toggleable terminal - words = { enabled = true }, -- highlight/navigate references under cursor + }, + scope = { enabled = true }, + scroll = { enabled = true }, + statuscolumn = { enabled = true }, + quickfile = { enabled = true }, + words = { enabled = true }, }) + + -- Keymaps + local function map(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { desc = desc }) + end + + map("n", "e", function() + Snacks.explorer() + end, "Snacks Explorer") + + map("n", "sk", function() + Snacks.picker.keymaps() + end, "Keymaps") + + map("n", "sb", function() + Snacks.picker.buffers() + end, "Buffer list") + + map("n", "ff", function() + Snacks.picker.pick("files") + end, "Snacks file picker") + + map("n", "gg", function() + Snacks.lazygit() + end, "Lazygit") end, } diff --git a/plugins/vim-tmux-navigator.lua b/plugins/vim-tmux-navigator.lua index 86dfb60..1b6a282 100644 --- a/plugins/vim-tmux-navigator.lua +++ b/plugins/vim-tmux-navigator.lua @@ -1,3 +1,13 @@ return { src = "https://github.com/christoomey/vim-tmux-navigator", + config = function() + local function map(lhs, rhs, desc) + vim.keymap.set("n", lhs, rhs, { desc = desc }) + end + + map("", "TmuxNavigateLeft", "Move to left window/pane") + map("", "TmuxNavigateDown", "Move to bottom window/pane") + map("", "TmuxNavigateUp", "Move to top window/pane") + map("", "TmuxNavigateRight", "Move to right window/pane") + end, } diff --git a/plugins/which-key.lua b/plugins/which-key.lua new file mode 100644 index 0000000..b6a8eab --- /dev/null +++ b/plugins/which-key.lua @@ -0,0 +1,22 @@ +return { + src = "https://github.com/folke/which-key.nvim", + version = "v3.17.0", + config = function() + local wk = require("which-key") + wk.setup({ + preset = "modern", + }) + + -- Group labels only. Individual mappings stay co-located with their + -- plugins (see plugins/*.lua) and in lua/keymaps.lua; which-key reads + -- their `desc` automatically. Register only the prefixes here. + wk.add({ + { "b", group = "buffer" }, + { "f", group = "find" }, + { "g", group = "git" }, + { "p", group = "paste/path" }, + { "s", group = "split/scratch" }, + { "t", group = "toggle" }, + }) + end, +} diff --git a/statusline.lua b/statusline.lua deleted file mode 100644 index 61d9f85..0000000 --- a/statusline.lua +++ /dev/null @@ -1,146 +0,0 @@ --- ============================================================================ --- STATUSLINE --- ============================================================================ - --- Git branch function with caching and Nerd Font icon -local cached_branch = "" -local last_check = 0 -local function git_branch() - local now = vim.uv.now() - if now - last_check > 5000 then -- Check every 5 seconds - cached_branch = vim.fn.system("git branch --show-current 2>/dev/null | tr -d '\n'") - last_check = now - end - if cached_branch ~= "" then - return " \u{e725} " .. cached_branch .. " " -- nf-dev-git_branch - end - return "" -end - --- File type with Nerd Font icon -local function file_type() - local ft = vim.bo.filetype - local icons = { - lua = "\u{e620} ", -- nf-dev-lua - python = "\u{e73c} ", -- nf-dev-python - javascript = "\u{e74e} ", -- nf-dev-javascript - typescript = "\u{e628} ", -- nf-dev-typescript - javascriptreact = "\u{e7ba} ", - typescriptreact = "\u{e7ba} ", - html = "\u{e736} ", -- nf-dev-html5 - css = "\u{e749} ", -- nf-dev-css3 - scss = "\u{e749} ", - json = "\u{e60b} ", -- nf-dev-json - markdown = "\u{e73e} ", -- nf-dev-markdown - vim = "\u{e62b} ", -- nf-dev-vim - sh = "\u{f489} ", -- nf-oct-terminal - bash = "\u{f489} ", - zsh = "\u{f489} ", - rust = "\u{e7a8} ", -- nf-dev-rust - go = "\u{e724} ", -- nf-dev-go - c = "\u{e61e} ", -- nf-dev-c - cpp = "\u{e61d} ", -- nf-dev-cplusplus - java = "\u{e738} ", -- nf-dev-java - php = "\u{e73d} ", -- nf-dev-php - ruby = "\u{e739} ", -- nf-dev-ruby - swift = "\u{e755} ", -- nf-dev-swift - kotlin = "\u{e634} ", - dart = "\u{e798} ", - elixir = "\u{e62d} ", - haskell = "\u{e777} ", - sql = "\u{e706} ", - yaml = "\u{f481} ", - toml = "\u{e615} ", - xml = "\u{f05c} ", - dockerfile = "\u{f308} ", -- nf-linux-docker - gitcommit = "\u{f418} ", -- nf-oct-git_commit - gitconfig = "\u{f1d3} ", -- nf-fa-git - vue = "\u{fd42} ", -- nf-md-vuejs - svelte = "\u{e697} ", - astro = "\u{e628} ", - } - - if ft == "" then - return " \u{f15b} " -- nf-fa-file_o - end - - return ((icons[ft] or " \u{f15b} ") .. ft) -end - --- File size with Nerd Font icon -local function file_size() - local size = vim.fn.getfsize(vim.fn.expand("%")) - if size < 0 then - return "" - end - local size_str - if size < 1024 then - size_str = size .. "B" - elseif size < 1024 * 1024 then - size_str = string.format("%.1fK", size / 1024) - else - size_str = string.format("%.1fM", size / 1024 / 1024) - end - return " \u{f016} " .. size_str .. " " -- nf-fa-file_o -end - --- Mode indicators with Nerd Font icons -local function mode_icon() - local mode = vim.fn.mode() - local modes = { - n = " \u{f121} NORMAL", - i = " \u{f11c} INSERT", - v = " \u{f0168} VISUAL", - V = " \u{f0168} V-LINE", - ["\22"] = " \u{f0168} V-BLOCK", - c = " \u{f120} COMMAND", - s = " \u{f0c5} SELECT", - S = " \u{f0c5} S-LINE", - ["\19"] = " \u{f0c5} S-BLOCK", - R = " \u{f044} REPLACE", - r = " \u{f044} REPLACE", - ["!"] = " \u{f489} SHELL", - t = " \u{f120} TERMINAL", - } - return modes[mode] or (" \u{f059} " .. mode) -end - -_G.mode_icon = mode_icon -_G.git_branch = git_branch -_G.file_type = file_type -_G.file_size = file_size - -vim.cmd([[ - highlight StatusLineBold gui=bold cterm=bold -]]) - --- Function to change statusline based on window focus -local function setup_dynamic_statusline() - vim.api.nvim_create_autocmd({ "WinEnter", "BufEnter" }, { - callback = function() - vim.opt_local.statusline = table.concat({ - " ", - "%#StatusLineBold#", - "%{v:lua.mode_icon()}", - "%#StatusLine#", - " \u{e0b1} %f %h%m%r", -- nf-pl-left_hard_divider - "%{v:lua.git_branch()}", - "\u{e0b1} ", -- nf-pl-left_hard_divider - "%{v:lua.file_type()}", - "\u{e0b1} ", -- nf-pl-left_hard_divider - "%{v:lua.file_size()}", - "%=", -- Right-align everything after this - " \u{f017} %l:%c %P ", -- nf-fa-clock_o for line/col - }) - end, - }) - vim.api.nvim_set_hl(0, "StatusLineBold", { bold = true }) - - vim.api.nvim_create_autocmd({ "WinLeave", "BufLeave" }, { - callback = function() - vim.opt_local.statusline = " %f %h%m%r \u{e0b1} %{v:lua.file_type()} %= %l:%c %P " - end, - }) -end - -setup_dynamic_statusline() From 0e0635ec5645811959e930dfa158d26884155bc4 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Wed, 17 Jun 2026 21:57:06 -0500 Subject: [PATCH 03/12] feat: More snacks setup Signed-off-by: Tristan Jahnke --- README.md | 1 + init.lua | 78 ++++++++++++++------- nvim-pack-lock.json | 41 +++++++++++ plugins/blink.lua | 9 ++- plugins/cloak.lua | 21 ++++++ plugins/conform.lua | 14 ++-- plugins/image.lua | 6 ++ plugins/lspconfig.lua | 131 ++++++++++++++++++++++++++++++++++++ plugins/lualine.lua | 65 ++++++++++++++++++ plugins/luasnip.lua | 63 +++++++++++++++++ plugins/mason.lua | 44 ++++++++++++ plugins/mini.lua | 1 - plugins/pr-description.lua | 3 + plugins/render-markdown.lua | 11 +++ plugins/snacks.lua | 105 +++++++++++++++++++++++------ snippets/all.lua | 38 +++++++++++ 16 files changed, 577 insertions(+), 54 deletions(-) create mode 100644 README.md create mode 100644 plugins/cloak.lua create mode 100644 plugins/image.lua create mode 100644 plugins/lspconfig.lua create mode 100644 plugins/lualine.lua create mode 100644 plugins/luasnip.lua create mode 100644 plugins/mason.lua create mode 100644 plugins/pr-description.lua create mode 100644 plugins/render-markdown.lua create mode 100644 snippets/all.lua diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e6f6e9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# nvim setup diff --git a/init.lua b/init.lua index e01f382..2379ac9 100644 --- a/init.lua +++ b/init.lua @@ -18,16 +18,55 @@ require("keymaps") require("options") --- Plugins ---- Each file in the plugins/ dir returns a spec table: +--- Each file in the plugins/ dir returns either a single spec table, or a +--- list of spec tables (for plugins that must be installed/configured +--- together, e.g. mason + mason-lspconfig). +--- --- return { --- src = "https://github.com/owner/repo", -- required --- version = "v1.2.3" or "main", -- optional (tag/branch/commit) --- config = function() ... end, -- optional, runs after install/load +--- priority = 100, -- optional, higher runs first (default 0) --- } +--- +--- Configs run sorted by `priority` (desc), then file name (asc) for +--- deterministic ordering. Use `priority` for load-order dependencies. local plugins_dir = vim.fn.stdpath("config") .. "/plugins" local specs = {} local configs = {} +--- Validate a single spec and queue its add-spec/config. +local function process_spec(name, plugin) + if type(plugin) ~= "table" then + vim.notify( + ("Plugin spec '%s' did not return a table (got %s). Did you forget `return { ... }`?"):format(name, type(plugin)), + vim.log.levels.ERROR + ) + return + elseif not plugin.src then + vim.notify(("Plugin spec '%s' is missing the required `src` field."):format(name), vim.log.levels.ERROR) + return + end + + table.insert(specs, { src = plugin.src, version = plugin.version }) + if type(plugin.config) == "function" then + table.insert(configs, { + name = name, + src = plugin.src, + fn = plugin.config, + priority = plugin.priority or 0, + }) + elseif plugin.config ~= nil then + vim.notify( + ("Plugin spec '%s' has a `config` that is not a function (got %s); skipping it."):format( + name, + type(plugin.config) + ), + vim.log.levels.WARN + ) + end +end + for name, type_ in vim.fs.dir(plugins_dir) do if type_ == "file" and name:match("%.lua$") then local ok, plugin = pcall(dofile, plugins_dir .. "/" .. name) @@ -36,33 +75,26 @@ for name, type_ in vim.fs.dir(plugins_dir) do ("Plugin spec '%s' failed to load (error while executing the file):\n%s"):format(name, tostring(plugin)), vim.log.levels.ERROR ) - elseif type(plugin) ~= "table" then - vim.notify( - ("Plugin spec '%s' did not return a table (got %s). Did you forget `return { ... }`?"):format( - name, - type(plugin) - ), - vim.log.levels.ERROR - ) - elseif not plugin.src then - vim.notify(("Plugin spec '%s' is missing the required `src` field."):format(name), vim.log.levels.ERROR) - else - table.insert(specs, { src = plugin.src, version = plugin.version }) - if type(plugin.config) == "function" then - table.insert(configs, { name = name, src = plugin.src, fn = plugin.config }) - elseif plugin.config ~= nil then - vim.notify( - ("Plugin spec '%s' has a `config` that is not a function (got %s); skipping it."):format( - name, - type(plugin.config) - ), - vim.log.levels.WARN - ) + elseif type(plugin) == "table" and plugin.src == nil and plugin[1] ~= nil then + -- A list of specs. + for _, sub in ipairs(plugin) do + process_spec(name, sub) end + else + -- A single spec. + process_spec(name, plugin) end end end +--- Deterministic order: higher priority first, then file name. +table.sort(configs, function(a, b) + if a.priority ~= b.priority then + return a.priority > b.priority + end + return a.name < b.name +end) + local ok_add, add_err = pcall(vim.pack.add, specs) if not ok_add then vim.notify("vim.pack.add failed:\n" .. tostring(add_err), vim.log.levels.ERROR) diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 072001e..4eb730b 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -1,20 +1,49 @@ { "plugins": { + "LuaSnip": { + "rev": "642b0c595e11608b4c18219e93b88d7637af27bc", + "src": "https://github.com/L3MON4D3/LuaSnip", + "version": "2.0.0 - 3.0.0" + }, "blink.cmp": { "rev": "78336bc89ee5365633bcf754d93df01678b5c08f", "src": "https://github.com/saghen/blink.cmp", "version": "1.0.0 - 2.0.0" }, + "cloak.nvim": { + "rev": "648aca6d33ec011dc3166e7af3b38820d01a71e4", + "src": "https://github.com/laytan/cloak.nvim" + }, "conform.nvim": { "rev": "3543d000dafbc41cc7761d860cfdb24e82154f75", "src": "https://github.com/stevearc/conform.nvim", "version": "'v9.1.0'" }, + "friendly-snippets": { + "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", + "src": "https://github.com/rafamadriz/friendly-snippets" + }, "gitsigns.nvim": { "rev": "a462f416e2ce4744531c6256252dee99a7d34a83", "src": "https://github.com/lewis6991/gitsigns.nvim", "version": "'v2.1.0'" }, + "image.nvim": { + "rev": "88351f1f7d9dbae286e671ce3690a49660dd8a5c", + "src": "https://github.com/3rd/image.nvim" + }, + "lualine.nvim": { + "rev": "221ce6b2d999187044529f49da6554a92f740a96", + "src": "https://github.com/nvim-lualine/lualine.nvim" + }, + "mason-lspconfig.nvim": { + "rev": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76", + "src": "https://github.com/mason-org/mason-lspconfig.nvim" + }, + "mason.nvim": { + "rev": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d", + "src": "https://github.com/mason-org/mason.nvim" + }, "mini.nvim": { "rev": "a995fe9cd4193fb492b5df69175a351a74b3d36b", "src": "https://github.com/nvim-mini/mini.nvim", @@ -25,11 +54,23 @@ "src": "https://github.com/windwp/nvim-autopairs", "version": "'0.10.0'" }, + "nvim-lspconfig": { + "rev": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7", + "src": "https://github.com/neovim/nvim-lspconfig" + }, "nvim-treesitter": { "rev": "4916d6592ede8c07973490d9322f187e07dfefac", "src": "https://github.com/nvim-treesitter/nvim-treesitter", "version": "'main'" }, + "pr-description.nvim": { + "rev": "d0af0074d6eec7af2b3724bc92c66163d82b29f3", + "src": "https://github.com/remoterabbit/pr-description.nvim" + }, + "render-markdown.nvim": { + "rev": "5adf0895310c1904e5abfaad40a2baad7fe44a07", + "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" + }, "snacks.nvim": { "rev": "e6fd58c82f2f3fcddd3fe81703d47d6d48fc7b9f", "src": "https://github.com/folke/snacks.nvim", diff --git a/plugins/blink.lua b/plugins/blink.lua index c985f1b..fc90303 100644 --- a/plugins/blink.lua +++ b/plugins/blink.lua @@ -3,7 +3,13 @@ return { version = vim.version.range("1.*"), config = function() require("blink.cmp").setup({ - keymap = { preset = "default" }, + keymap = { + preset = "default", + -- Jump through snippet tabstops (LuaSnip). Falls back to normal + -- Tab behaviour when not inside a snippet. + [""] = { "snippet_forward", "fallback" }, + [""] = { "snippet_backward", "fallback" }, + }, appearance = { nerd_font_variant = "mono", }, @@ -33,6 +39,7 @@ return { }, }, signature = { enabled = true }, + snippets = { preset = "luasnip" }, fuzzy = { implementation = "prefer_rust" }, }) end, diff --git a/plugins/cloak.lua b/plugins/cloak.lua new file mode 100644 index 0000000..2d24858 --- /dev/null +++ b/plugins/cloak.lua @@ -0,0 +1,21 @@ +return { + src = "https://github.com/laytan/cloak.nvim", + config = function() + require("cloak").setup({ + enabled = true, + cloak_character = "*", + highlight_group = "Comment", + patterns = { + { + file_pattern = { + ".env*", + ".env", + ".edgerc", + ".credentials", + }, + cloak_pattern = "=.+", + }, + }, + }) + end, +} diff --git a/plugins/conform.lua b/plugins/conform.lua index 58c4897..9ef60d8 100644 --- a/plugins/conform.lua +++ b/plugins/conform.lua @@ -4,18 +4,18 @@ return { config = function() require("conform").setup({ formatters_by_ft = { - lua = { "stylua" }, - python = { "ruff_format", "ruff_organize_imports" }, - go = { "goimports", "gofumpt" }, - terraform = { "terraform_fmt" }, - sh = { "shfmt" }, + ["_"] = { "trim_whitespace" }, bash = { "shfmt" }, elixir = { "mix" }, + go = { "goimports", "gofumpt" }, json = { "jq" }, - yaml = { "yamlfmt" }, + lua = { "stylua" }, markdown = { "markdownlint" }, - ["_"] = { "trim_whitespace" }, + python = { "ruff_format", "ruff_organize_imports" }, + sh = { "shfmt" }, + terraform = { "terraform_fmt" }, toml = { "taplo" }, + yaml = { "yamlfmt" }, }, format_on_save = function(bufnr) -- Don't format .norg files (Neorg handles its own formatting) diff --git a/plugins/image.lua b/plugins/image.lua new file mode 100644 index 0000000..c89be9e --- /dev/null +++ b/plugins/image.lua @@ -0,0 +1,6 @@ +return { + src = "https://github.com/3rd/image.nvim", + config = function() + require("image").setup({}) + end, +} diff --git a/plugins/lspconfig.lua b/plugins/lspconfig.lua new file mode 100644 index 0000000..240e864 --- /dev/null +++ b/plugins/lspconfig.lua @@ -0,0 +1,131 @@ +return { + src = "https://github.com/neovim/nvim-lspconfig", + config = function() + vim.lsp.log.set_level("WARN") + + -- Truncate LSP log if it exceeds 10 MB + local log_path = vim.lsp.log.get_filename() + local stat = vim.uv.fs_stat(log_path) + if stat and stat.size > 10 * 1024 * 1024 then + os.remove(log_path) + end + + -- Blink.cmp stuff + local lsp_capabilities = require("blink.cmp").get_lsp_capabilities() + -- Apply blink capabilities to all LSP servers + vim.lsp.config("*", { + capabilities = lsp_capabilities, + }) + + -- Lua + vim.lsp.config("lua_ls", { + settings = { + Lua = { + telemetry = { + enable = false, + }, + }, + }, + }) + + -- Custom configs (mason auto-enables installed servers via + -- mason-lspconfig's automatic_enable; these are not mason-managed) + vim.lsp.enable({ + "lsp-codelens", + "lsp-inlay_hint", + "lsp-inline_completion", + "lsp-linked_editing_range", + }) + + -- Single LspAttach autocmd for all LSP-related setup + vim.api.nvim_create_autocmd("LspAttach", { + desc = "LSP actions", + callback = function(event) + local client = vim.lsp.get_client_by_id(event.data.client_id) + local bufnr = event.buf + + -- Enable inlay hints if supported + if client and client:supports_method("textDocument/inlayHint") then + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) + end + + local bufmap = function(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc }) + end + + -- Navigation + bufmap("n", "gd", "lua vim.lsp.buf.definition()", "Go to definition") + bufmap("n", "gD", "lua vim.lsp.buf.declaration()", "Go to declaration") + bufmap("n", "gi", "lua vim.lsp.buf.implementation()", "Go to implementation") + bufmap("n", "go", "lua vim.lsp.buf.type_definition()", "Go to type definition") + bufmap("n", "gr", "lua vim.lsp.buf.references()", "List references") + bufmap("n", "gs", "lua vim.lsp.buf.signature_help()", "Signature help") + + -- Actions + bufmap("n", "", "lua vim.lsp.buf.rename()", "Rename symbol") + bufmap("n", "", "lua vim.lsp.buf.code_action()", "Code action") + + -- Hover: LSP hover, falls back to diagnostic float if no hover info + bufmap("n", "K", function() + local has_diag = #vim.diagnostic.get(bufnr, { lnum = vim.fn.line(".") - 1 }) > 0 + local clients = vim.lsp.get_clients({ bufnr = bufnr, method = "textDocument/hover" }) + if #clients > 0 then + vim.lsp.buf.hover({ border = "rounded" }) + elseif has_diag then + vim.diagnostic.open_float({ border = "rounded" }) + end + end, "Hover / diagnostic") + + -- Diagnostics + bufmap("n", "gl", "lua vim.diagnostic.open_float()", "Show diagnostics") + bufmap("n", "[d", function() + vim.diagnostic.jump({ count = -1 }) + end, "Previous diagnostic") + bufmap("n", "]d", function() + vim.diagnostic.jump({ count = 1 }) + end, "Next diagnostic") + + -- Document symbols (outline view) + bufmap("n", "ls", function() + Snacks.picker.lsp_symbols() + end, "Document symbols") + + -- Workspace symbols (project-wide symbol search) + bufmap("n", "lw", function() + Snacks.picker.lsp_workspace_symbols() + end, "Workspace symbols") + + -- Code lens + bufmap("n", "cl", "lua vim.lsp.codelens.run()", "Run code lens") + bufmap("n", "cL", "lua vim.lsp.codelens.refresh()", "Refresh code lens") + + -- Debug LSP info + bufmap("n", "li", function() + local clients = vim.lsp.get_clients({ bufnr = bufnr }) + if #clients == 0 then + vim.notify("No LSP clients attached to this buffer", vim.log.levels.INFO) + return + end + + local info = {} + for _, c in pairs(clients) do + local capabilities = {} + if c:supports_method("textDocument/rename") then + table.insert(capabilities, "rename") + end + if c:supports_method("textDocument/codeAction") then + table.insert(capabilities, "code_action") + end + if c:supports_method("textDocument/hover") then + table.insert(capabilities, "hover") + end + + table.insert(info, string.format("%s: %s", c.name, table.concat(capabilities, ", "))) + end + + vim.notify("LSP Clients:\n" .. table.concat(info, "\n"), vim.log.levels.INFO) + end, "LSP info") + end, + }) + end, +} diff --git a/plugins/lualine.lua b/plugins/lualine.lua new file mode 100644 index 0000000..a5164f8 --- /dev/null +++ b/plugins/lualine.lua @@ -0,0 +1,65 @@ +return { + src = "https://github.com/nvim-lualine/lualine.nvim", + config = function() + local function lsp_status() + local clients = vim.lsp.get_clients({ bufnr = 0 }) + if #clients == 0 then + return "No LSP" + end + local names = {} + for _, client in pairs(clients) do + table.insert(names, client.name) + end + return " " .. table.concat(names, ", ") + end + require("lualine").setup({ + options = { + icons_enabled = true, + theme = "auto", + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + globalstatus = true, + refresh = { + statusline = 1000, + tabline = 1000, + winbar = 1000, + }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch", "diff" }, + lualine_c = { + { "filename", path = 1 }, + { python_env, color = { fg = "#98be65" } }, + }, + lualine_x = { + "diagnostics", + { lsp_status, color = { fg = "#51afef" } }, + "encoding", + "fileformat", + "filetype", + }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + winbar = {}, + inactive_winbar = {}, + extensions = {}, + }) + end, +} diff --git a/plugins/luasnip.lua b/plugins/luasnip.lua new file mode 100644 index 0000000..40567d8 --- /dev/null +++ b/plugins/luasnip.lua @@ -0,0 +1,63 @@ +--- LuaSnip โ€” the snippet engine that blink.cmp drives (see plugins/blink.lua, +--- `snippets.preset = "luasnip"`). +--- +--- Two sources of snippets are loaded: +--- 1. friendly-snippets โ€” community VSCode-style snippets (a broad base). +--- 2. Your own native Lua snippets in /snippets/.lua, which +--- are the powerful/dynamic ones (functions, choices, transforms, etc.). +--- +--- Snippet jumping (Tab / S-Tab) is configured in plugins/blink.lua. +return { + { + src = "https://github.com/rafamadriz/friendly-snippets", + }, + { + src = "https://github.com/L3MON4D3/LuaSnip", + version = vim.version.range("2.*"), + config = function() + local ls = require("luasnip") + + ls.setup({ + -- Keep the last snippet around so you can jump back into it. + history = true, + -- Re-read tabstops as you type so dynamic nodes update live. + update_events = "TextChanged,TextChangedI", + enable_autosnippets = true, + }) + + -- Community VSCode-style snippets (friendly-snippets) + any VSCode-style + -- snippets you drop in /snippets with a package.json. + require("luasnip.loaders.from_vscode").lazy_load() + + -- Your native Lua snippets: /snippets/.lua + require("luasnip.loaders.from_lua").lazy_load({ + paths = { vim.fn.stdpath("config") .. "/snippets" }, + }) + + -- Edit the Lua snippets file for the current filetype. + vim.keymap.set("n", "se", function() + require("luasnip.loaders").edit_snippet_files() + end, { desc = "Edit snippets" }) + + if not pcall(require, "luasnip-jsregexp") and not pcall(require, "jsregexp") then + local info = vim.iter(vim.pack.get()):find(function(p) + return p.spec and p.spec.name == "LuaSnip" + end) + if info and info.path and vim.fn.executable("make") == 1 then + vim.system( + { "make", "install_jsregexp" }, + { cwd = info.path }, + vim.schedule_wrap(function(out) + if out.code ~= 0 then + vim.notify( + "LuaSnip: jsregexp build failed (snippet transforms disabled):\n" .. (out.stderr or ""), + vim.log.levels.WARN + ) + end + end) + ) + end + end + end, + }, +} diff --git a/plugins/mason.lua b/plugins/mason.lua new file mode 100644 index 0000000..56d3e25 --- /dev/null +++ b/plugins/mason.lua @@ -0,0 +1,44 @@ +-- mason + mason-lspconfig. mason must be set up before mason-lspconfig, so +-- both are configured here in a single, ordered config function. +return { + { + src = "https://github.com/mason-org/mason.nvim", + }, + { + src = "https://github.com/mason-org/mason-lspconfig.nvim", + config = function() + require("mason").setup({ + ui = { + border = "rounded", + icons = { + package_installed = "โœ“", + package_pending = "โžœ", + package_uninstalled = "โœ—", + }, + }, + }) + + require("mason-lspconfig").setup({ + automatic_enable = { + exclude = { + "rust_analyzer", + "ts_ls", + }, + }, + -- These are lspconfig server names (NOT mason package names, e.g. + -- `lua_ls` not `lua-language-server`). Browse all available servers: + -- https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md + -- Or in Neovim run `:checkhealth mason-lspconfig` / `:Mason`. + ensure_installed = { + "codebook", + "gopls", + "lua_ls", + "pyright", + "terraformls", + "tflint", + "tofu_ls", + }, + }) + end, + }, +} diff --git a/plugins/mini.lua b/plugins/mini.lua index 12bd6e6..7c88a3a 100644 --- a/plugins/mini.lua +++ b/plugins/mini.lua @@ -2,7 +2,6 @@ return { src = "https://github.com/nvim-mini/mini.nvim", version = "stable", config = function() - require("mini.statusline").setup() require("mini.map").setup() require("mini.tabline").setup() require("mini.icons").setup() diff --git a/plugins/pr-description.lua b/plugins/pr-description.lua new file mode 100644 index 0000000..ea5dc11 --- /dev/null +++ b/plugins/pr-description.lua @@ -0,0 +1,3 @@ +return { + src = "https://github.com/remoterabbit/pr-description.nvim", +} diff --git a/plugins/render-markdown.lua b/plugins/render-markdown.lua new file mode 100644 index 0000000..ab0f415 --- /dev/null +++ b/plugins/render-markdown.lua @@ -0,0 +1,11 @@ +return { + src = "https://github.com/MeanderingProgrammer/render-markdown.nvim", + config = function() + require("render-markdown").setup({ + completions = { + lsp = { enabled = true }, + }, + render_modes = true, + }) + end, +} diff --git a/plugins/snacks.lua b/plugins/snacks.lua index 799208b..97d77bd 100644 --- a/plugins/snacks.lua +++ b/plugins/snacks.lua @@ -9,14 +9,14 @@ return { dashboard = { preset = { header = [[ - -------------------------------------------------------------------------------------------------------- - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— - โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ• - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ - โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• - -------------------------------------------------------------------------------------------------------- + --------------------------------------------------------------------------------------------------- + โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— + โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ• + โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ + โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• +--------------------------------------------------------------------------------------------------- ]], keys = { { icon = "๓ฐˆž", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" }, @@ -87,34 +87,95 @@ return { }, scope = { enabled = true }, scroll = { enabled = true }, + scratch = { + enabled = true, + }, statuscolumn = { enabled = true }, quickfile = { enabled = true }, words = { enabled = true }, }) -- Keymaps - local function map(mode, lhs, rhs, desc) - vim.keymap.set(mode, lhs, rhs, { desc = desc }) - end - - map("n", "e", function() + Snacks.keymap.set("n", "e", function() Snacks.explorer() - end, "Snacks Explorer") + end, { desc = "Snack Explorer" }) - map("n", "sk", function() + Snacks.keymap.set("n", "sk", function() Snacks.picker.keymaps() - end, "Keymaps") + end, { desc = "Keymaps" }) - map("n", "sb", function() + Snacks.keymap.set("n", "sb", function() Snacks.picker.buffers() - end, "Buffer list") + end, { desc = "Buffer list" }) - map("n", "ff", function() + Snacks.keymap.set("n", "ff", function() Snacks.picker.pick("files") - end, "Snacks file picker") + end, { desc = "Snacks file picker" }) - map("n", "gg", function() + Snacks.keymap.set("n", "gg", function() Snacks.lazygit() - end, "Lazygit") + end, { desc = "Lazygit" }) + + Snacks.keymap.set("n", "sn", function() + Snacks.scratch.open({ + name = "Notes", + ft = "markdown", + filekey = { + branch = false, + }, + }) + end, { desc = "Load repo notes markdown scratchpad." }) + + Snacks.keymap.set("n", "sN", function() + local filetypes = { + "markdown", + "lua", + "python", + "bash", + "text", + "json", + "yaml", + } + + local current_ft = vim.bo.filetype + if current_ft and current_ft ~= "" then + local found = false + for _, ft in ipairs(filetypes) do + if ft == current_ft then + found = true + break + end + end + if not found then + table.insert(filetypes, 1, current_ft .. " (current)") + end + end + + vim.ui.select(filetypes, { + prompt = "Select filetype: ", + format_item = function(item) + return item + end, + }, function(choice) + if choice then + local selected_ft = choice:gsub(" %(current%)", "") + Snacks.scratch.open({ + ft = selected_ft, + filekey = { + branch = false, + }, + }) + end + end) + end, { desc = "Create new scratch pad." }) + + Snacks.keymap.set("n", "sl", function() + local cwd = vim.fs.normalize(vim.uv.cwd()) + Snacks.picker.scratch({ + transform = function(item) + return item.item and item.item.cwd == cwd + end, + }) + end, { desc = "Select scratch buffer." }) end, } diff --git a/snippets/all.lua b/snippets/all.lua new file mode 100644 index 0000000..77a3b4d --- /dev/null +++ b/snippets/all.lua @@ -0,0 +1,38 @@ +--- Native LuaSnip snippets available in *every* filetype. +--- +--- File naming: /snippets/.lua (this one is `all`, the +--- pseudo-filetype LuaSnip applies everywhere). Create e.g. `lua.lua`, +--- `python.lua`, `go.lua` for language-specific snippets. Loaded by the +--- from_lua loader configured in plugins/luasnip.lua. +--- +--- A file returns a list of snippets. Type the snippet `trig` then expand it +--- from the blink.cmp menu (or with your accept key); jump tabstops with Tab. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local f = ls.function_node +local fmt = require("luasnip.extras.fmt").fmt + +return { + -- Static text: type `hi` -> expands to a greeting. + s("hi", { f(function() + return "Hello from LuaSnip!" + end) }), + + -- Dynamic: inserts today's date. Demonstrates a function_node. + s("date", { + f(function() + return os.date("%Y-%m-%d") + end), + }), + + -- Tabstops + placeholders: `${1} -> ${2}`. Tab jumps between them. + s( + "todo", + fmt("TODO({}): {}", { + i(1, "you"), + i(2, "describe the task"), + }) + ), +} From 547e1b11cac83bc610985f1938ab84d208afe7b5 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Tue, 23 Jun 2026 11:50:18 -0500 Subject: [PATCH 04/12] feat: Add in comment module for keymaps Signed-off-by: Tristan Jahnke --- .codebook.toml | 52 +++++++++++- .luarc.json | 3 + README.md | 12 +++ init.lua | 8 ++ lua/autocmds.lua | 12 +++ lua/keymaps.lua | 41 +++++++++- lua/options.lua | 13 +-- lua/utils/keymapdoc/extract.lua | 120 +++++++++++++++++++++++++++ lua/utils/keymapdoc/init.lua | 18 ++++ lua/utils/keymapdoc/meta.lua | 6 ++ lua/utils/keymapdoc/render.lua | 56 +++++++++++++ nvim-pack-lock.json | 18 +++- plugins/blink.lua | 35 +++++++- plugins/gitsigns.lua | 2 +- plugins/lspconfig.lua | 93 +++++++++++++-------- plugins/lualine.lua | 1 - plugins/luasnip.lua | 4 + plugins/neogen.lua | 22 +++++ plugins/snacks.lua | 4 + plugins/todo-comments.lua | 37 +++++++++ plugins/trouble.lua | 123 ++++++++++++++++++++++++++++ plugins/which-key.lua | 2 + snippets/go.lua | 140 ++++++++++++++++++++++++++++++++ snippets/lua.lua | 123 ++++++++++++++++++++++++++++ snippets/markdown.lua | 76 +++++++++++++++++ snippets/python.lua | 113 ++++++++++++++++++++++++++ snippets/sh.lua | 121 +++++++++++++++++++++++++++ snippets/terraform.lua | 124 ++++++++++++++++++++++++++++ 28 files changed, 1327 insertions(+), 52 deletions(-) create mode 100644 .luarc.json create mode 100644 lua/utils/keymapdoc/extract.lua create mode 100644 lua/utils/keymapdoc/init.lua create mode 100644 lua/utils/keymapdoc/meta.lua create mode 100644 lua/utils/keymapdoc/render.lua create mode 100644 plugins/neogen.lua create mode 100644 plugins/todo-comments.lua create mode 100644 plugins/trouble.lua create mode 100644 snippets/go.lua create mode 100644 snippets/lua.lua create mode 100644 snippets/markdown.lua create mode 100644 snippets/python.lua create mode 100644 snippets/sh.lua create mode 100644 snippets/terraform.lua diff --git a/.codebook.toml b/.codebook.toml index 34a4545..b71134b 100644 --- a/.codebook.toml +++ b/.codebook.toml @@ -1,16 +1,64 @@ words = [ - "nvim's", - "glab", + "autocmd", + "bigfile", + "keymapdoc", "bufferline", + "bufmap", + "bufnr", + "buftype", "catppuccin", + "codelenses", + "copyfile", + "devenv", + "direnv", + "errnm", + "etype", + "filecopy", + "fileformat", + "filekey", + "fnamemodify", "gitsigns", + "glab", + "globalstatus", "gopls", + "hardlinks", + "inlinedoc", + "isdirectory", + "iswin", + "joinpath", + "justinmk", + "keymaps", "lazygit", + "lnum", + "lpeg", + "luacheck", + "lualine", + "luarc", "neotest", "neovim", + "netrw", "nvim", + "nvim's", + "oldfiles", + "performantly", + "pyproject", "pyright", + "quickfile", + "readblob", + "realpath", + "relpath", "ripgrep", + "scandir", + "startinsert", + "statuscolumn", "statusline", + "stdpath", + "stylua", + "sysname", + "tabline", "tmux", + "tst", + "unc", + "winbar", + "xdg", ] diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 0000000..552538c --- /dev/null +++ b/.luarc.json @@ -0,0 +1,3 @@ +{ + "workspace.checkThirdParty": "Disable" +} diff --git a/README.md b/README.md index 3e6f6e9..bf05c50 100644 --- a/README.md +++ b/README.md @@ -1 +1,13 @@ # nvim setup + +**test** + +*test* + +--- + +| test | cake | carl | four | +| --------------- | --------------- | --------------- | --------------- | +| yes | no | maybe | so | + +## Test time diff --git a/init.lua b/init.lua index 2379ac9..02d7c99 100644 --- a/init.lua +++ b/init.lua @@ -16,6 +16,7 @@ vim.g.loaded_node_provider = 0 require("autocmds") require("keymaps") require("options") +require("utils.keymapdoc").setup() --- Plugins --- Each file in the plugins/ dir returns either a single spec table, or a @@ -32,10 +33,17 @@ require("options") --- Configs run sorted by `priority` (desc), then file name (asc) for --- deterministic ordering. Use `priority` for load-order dependencies. local plugins_dir = vim.fn.stdpath("config") .. "/plugins" + +---@type table Table holding compiled set of @configs local specs = {} + +---@type table Table holding individual plugin configurations. local configs = {} --- Validate a single spec and queue its add-spec/config. +---@param name string Spec file name (used in error messages) +---@param plugin table Spec table returned by a plugins/*.lua file +---@return nil local function process_spec(name, plugin) if type(plugin) ~= "table" then vim.notify( diff --git a/lua/autocmds.lua b/lua/autocmds.lua index 30766cb..eb1e08c 100644 --- a/lua/autocmds.lua +++ b/lua/autocmds.lua @@ -4,6 +4,18 @@ local augroup = vim.api.nvim_create_augroup("UserConfig", { clear = true }) +-- OpenTofu files share Terraform/HCL syntax but Neovim doesn't detect them by +-- default. Map them to `terraform` so LSP, treesitter and the terraform +-- snippets all apply. +vim.filetype.add({ + extension = { + tofu = "terraform", + }, + pattern = { + [".*%.tofu%.json"] = "json", + }, +}) + -- Format on save (ONLY real file buffers, ONLY when efm is attached) vim.api.nvim_create_autocmd("BufWritePre", { group = augroup, diff --git a/lua/keymaps.lua b/lua/keymaps.lua index d1f2a82..eab5d66 100644 --- a/lua/keymaps.lua +++ b/lua/keymaps.lua @@ -1,4 +1,4 @@ --- ============================================================================ +-- ============================================================================= -- KEYMAPS (core / editor only) -- -- Convention: @@ -10,7 +10,13 @@ -- needed rather than appending to the bottom. -- ============================================================================ --- Thin wrapper so each mapping is a single readable line. +---Thin wrapper so each mapping is a single readable line. +---@param mode string|string[] Array or single character to signify vim mode. +---@param lhs string Left hand side. +---@param rhs string|function Right hand side. +---@param desc string Description for keymap. +---@param opts? table Optional configuration table. +---@return nil local function map(mode, lhs, rhs, desc, opts) opts = vim.tbl_extend("force", { desc = desc }, opts or {}) vim.keymap.set(mode, lhs, rhs, opts) @@ -36,7 +42,7 @@ map("n", "N", "Nzzzv", "Previous search result (centered)") -- Editing --------------------------------------------------------------------- map("x", "p", '"_dP', "Paste without yanking") -map({ "n", "v" }, "x", '"_d', "Delete without yanking") +map({ "n", "v" }, "d", '"_d', "Delete without yanking") map("n", "", ":m .+1==", "Move line down") map("n", "", ":m .-2==", "Move line up") map("v", "", ":m '>+1gv=gv", "Move selection down") @@ -58,6 +64,31 @@ map("n", "", ":vertical resize -2", "Decrease window width") map("n", "", ":vertical resize +2", "Increase window width") -- Utility / toggles ----------------------------------------------------------- +local width = 80 +---Build a banner divider using the current buffer's comment leader, padded with +---`=` out to `width` columns (e.g. `-- =====...`, `# =====...`, `// =====...`). +---@param width integer target line width (column to fill up to) [80] +---@return string the full banner line with comment start. +local function comment_banner(width) + local cs = vim.bo.commentstring + if cs == nil or cs == "" then + cs = "# %s" + end + local prefix, suffix = cs:match("^(.-)%%s(.-)$") + prefix = vim.trim(prefix or "#") + suffix = vim.trim(suffix or "") + local used = #prefix + 1 + (#suffix > 0 and #suffix + 1 or 0) + local fill = math.max(width - used, 1) + local line = prefix .. " " .. string.rep("=", fill) + if #suffix > 0 then + line = line .. " " .. suffix + end + return line +end +map("n", "cb", function() -- comment banner / section divider + vim.api.nvim_set_current_line(comment_banner(width)) +end, "Insert comment banner divider") + map("n", "pa", function() -- copy full file path local path = vim.fn.expand("%:p") vim.fn.setreg("+", path) @@ -66,3 +97,7 @@ end, "Copy full file path") map("n", "td", function() vim.diagnostic.enable(not vim.diagnostic.is_enabled()) end, "Toggle diagnostics") + +-- Vim Pack ------------------------------------------------------------------- +map("n", "vu", ":lua vim.pack.update()", "Update plugins (no force)") +map("n", "vf", ":lua vim.pack.update(all,{force=true})", "Update plugins (FORCE)") diff --git a/lua/options.lua b/lua/options.lua index 13339fe..bb4b030 100644 --- a/lua/options.lua +++ b/lua/options.lua @@ -1,6 +1,13 @@ -- ============================================================================ -- OPTIONS -- ============================================================================ +local undodir = vim.fn.expand("~/.vim/undodir") +if + vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent +then + vim.fn.mkdir(undodir, "p") +end + vim.opt.autochdir = false -- do not autochange directories vim.opt.autoindent = true -- copy indent from current line vim.opt.autoread = true -- auto-reload changes if outside of neovim @@ -58,9 +65,3 @@ vim.opt.wildmode = "longest:full,full" -- complete longest common match, full co vim.opt.winblend = 0 -- floating window transparency vim.opt.wrap = false -- do not wrap lines by default vim.opt.writebackup = false -- do not write to a backup file -local undodir = vim.fn.expand("~/.vim/undodir") -if - vim.fn.isdirectory(undodir) == 0 -- create undodir if nonexistent -then - vim.fn.mkdir(undodir, "p") -end diff --git a/lua/utils/keymapdoc/extract.lua b/lua/utils/keymapdoc/extract.lua new file mode 100644 index 0000000..d1b81b5 --- /dev/null +++ b/lua/utils/keymapdoc/extract.lua @@ -0,0 +1,120 @@ +local M = {} + +--- Matches all function calls; filter by name in Lua +---@type vim.treesitter.Query +local QUERY = vim.treesitter.query.parse( + "lua", + [[ + (function_call + name: (_) @fn + arguments: (arguments) @args) + ]] +) + +--- Strip surrounding quotes from a string-literal node's text. +---@param node TSNode|nil Treesitter node or nil. +---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. +---@return string Full extract node string with filtering. +local function node_str(node, buf) + if not node then + return "" + end + local text = vim.treesitter.get_node_text(node, buf) + return (text:gsub("^['\"]", ""):gsub("['\"]$", "")) +end + +--- Read a mode arg: example like "n", or a table like {"n", "v"} -> "n, v". +---@param node TSNode|nil Treesitter node or nil. +---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. +---@return string Output from node_str +---@see node_str +local function read_mode(node, buf) + if not node then + return "" + end + + if node:type() == "table_constructor" then + local modes = {} + for child in node:iter_children() do + if child:type() == "field" then + table.insert(modes, node_str(child:field("value")[1], buf)) + end + end + return table.concat(modes, ",") + end + return node_str(node, buf) +end + +--- Scan an opts table_constructor for a `desc = "..."` field. +---@param opts_node TSNode|nil Treesitter node or nil +---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. +---@return string -- TODO: Add definition +---@see node_str +local function find_desc(opts_node, buf) + if not opts_node or opts_node:type() ~= "table_constructor" then + return "" + end + for child in opts_node:iter_children() do + if child:type() == "field" then + local name = child:field("name")[1] + if name and vim.treesitter.get_node_text(name, buf) == "desc" then + return node_str(child:field("value")[1], buf) + end + end + end + return "" +end + +--- Pull one capture node out of an iter_matches result, handling both the older API (id -> node) +--- and the newer API (id -> { node, ... }). +---@param match table -- TODO: Add description +---@param want_name string -- TODO: Add description +---@return TSNode|nil -- TODO: Add description +local function capture_node(match, want_name) + for id, nodes in pairs(match) do + if QUERY.captures[id] == want_name then + return type(nodes) == "table" and nodes[1] or nodes + end + end + return nil +end + +--- Extract keymap entries from buffer. +---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. +---@return KeymapEntry[] +function M.extract(buf) + buf = (buf == nil or buf == 0) and vim.api.nvim_get_current_buf() or buf + + local ok, parser = pcall(vim.treesitter.get_parser, buf, "lua") + if not ok or not parser then + return {} + end + + local root = parser:parse()[1]:root() + + local entries = {} + for _, match in QUERY:iter_matches(root, buf, 0, -1) do + local fn_node = capture_node(match, "fn") + local args_node = capture_node(match, "args") + + if fn_node and args_node then + local fn_text = vim.treesitter.get_node_text(fn_node, buf) + if fn_text:match("keymap%.set$") or fn_text:match("nvim_set_keymap$") then + local n = args_node:named_child_count() + local mode_node = args_node:named_child(0) + local lhs_node = args_node:named_child(1) + local last = n > 0 and args_node:named_child(n - 1) or nil + local opts_node = (last and last:type() == "table_constructor") and last or nil + + table.insert(entries, { + mode = read_mode(mode_node, buf), + lhs = node_str(lhs_node, buf), + desc = find_desc(opts_node, buf), + }) + end + end + end + return entries +end + +return M diff --git a/lua/utils/keymapdoc/init.lua b/lua/utils/keymapdoc/init.lua new file mode 100644 index 0000000..3f3220f --- /dev/null +++ b/lua/utils/keymapdoc/init.lua @@ -0,0 +1,18 @@ +local M = {} + +--- Refresh the keymap docs comment for a buffer. +---@param buf integer|nil buffer handle (0 or nil = current buffer) +function M.run(buf) + buf = buf or vim.api.nvim_get_current_buf() + local entries = require("utils.keymapdoc.extract").extract(buf) + require("utils.keymapdoc.render").inject(buf, entries) +end + +--- Register the :Keymapdoc user command. Call once from main init. +function M.setup() + vim.api.nvim_create_user_command("Keymapdoc", function() + M.run(0) + end, { desc = "Refresh keymap doc comment for current file." }) +end + +return M diff --git a/lua/utils/keymapdoc/meta.lua b/lua/utils/keymapdoc/meta.lua new file mode 100644 index 0000000..4f3885c --- /dev/null +++ b/lua/utils/keymapdoc/meta.lua @@ -0,0 +1,6 @@ +---@meta + +---@class KeymapEntry +---@field mode string -- "n", "v", "x", ... or "n,v" for multi-mode (or "" if unknown) +---@field lhs string -- "x" +---@field desc string -- "Toggle thing" (or "" if none) diff --git a/lua/utils/keymapdoc/render.lua b/lua/utils/keymapdoc/render.lua new file mode 100644 index 0000000..907561d --- /dev/null +++ b/lua/utils/keymapdoc/render.lua @@ -0,0 +1,56 @@ +local M = {} + +local START = "-- ===============================Keymaps Start=================================" +local STOP = "-- =================================Keymaps End=================================" + +--- Build table of keymaps. +---@param entries table -- TODO: Add description +---@return table -- TODO: Add description +local function build_lines(entries) + local lines = { START } + if #entries == 0 then + table.insert(lines, "-- (no keymaps found)") + else + local mode_w, lhs_w = 0, 0 + for _, e in ipairs(entries) do + mode_w = math.max(mode_w, #e.mode) + lhs_w = math.max(lhs_w, #e.lhs) + end + local fmt = "-- %-" .. mode_w .. "s %-" .. lhs_w .. "s %s" + for _, e in ipairs(entries) do + local line = string.format(fmt, e.mode, e.lhs, e.desc) + table.insert(lines, (line:gsub("%s+$", ""))) + end + end + table.insert(lines, STOP) + return lines +end + +--- Inject keymap lines to top of current file between marker blocks. +---@param buf integer Neovim buffer or nil; current buffer is 0. +---@param entries table -- TODO: Add description +function M.inject(buf, entries) + buf = (buf == 0) and vim.api.nvim_get_current_buf() or buf + + local all = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + local block = build_lines(entries) + + local start_idx, stop_idx + for i, line in ipairs(all) do + if line:find(START, 1, true) then + start_idx = i - 1 + end + if line:find(STOP, 1, true) then + stop_idx = i + end + end + + if start_idx and stop_idx and stop_idx > start_idx then + vim.api.nvim_buf_set_lines(buf, start_idx, stop_idx, false, block) + else + local prepend = vim.list_extend(vim.deepcopy(block), { "" }) + vim.api.nvim_buf_set_lines(buf, 0, 0, false, prepend) + end +end + +return M diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 4eb730b..375833b 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -49,13 +49,17 @@ "src": "https://github.com/nvim-mini/mini.nvim", "version": "'stable'" }, + "neogen": { + "rev": "23e7e9f883d01289ebd90e98025acc860ea26366", + "src": "https://github.com/danymat/neogen" + }, "nvim-autopairs": { "rev": "23320e75953ac82e559c610bec5a90d9c6dfa743", "src": "https://github.com/windwp/nvim-autopairs", "version": "'0.10.0'" }, "nvim-lspconfig": { - "rev": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7", + "rev": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e", "src": "https://github.com/neovim/nvim-lspconfig" }, "nvim-treesitter": { @@ -68,7 +72,7 @@ "src": "https://github.com/remoterabbit/pr-description.nvim" }, "render-markdown.nvim": { - "rev": "5adf0895310c1904e5abfaad40a2baad7fe44a07", + "rev": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a", "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" }, "snacks.nvim": { @@ -76,6 +80,16 @@ "src": "https://github.com/folke/snacks.nvim", "version": "'v2.31.0'" }, + "todo-comments.nvim": { + "rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668", + "src": "https://github.com/folke/todo-comments.nvim", + "version": "'v1.5.0'" + }, + "trouble.nvim": { + "rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a", + "src": "https://github.com/folke/trouble.nvim", + "version": "'main'" + }, "vim-tmux-navigator": { "rev": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432", "src": "https://github.com/christoomey/vim-tmux-navigator" diff --git a/plugins/blink.lua b/plugins/blink.lua index fc90303..552f458 100644 --- a/plugins/blink.lua +++ b/plugins/blink.lua @@ -1,3 +1,7 @@ +-- ===============================Keymaps Start================================= +-- (no keymaps found) +-- =================================Keymaps End================================= + return { src = "https://github.com/saghen/blink.cmp", version = vim.version.range("1.*"), @@ -15,11 +19,34 @@ return { }, sources = { default = { "lsp", "path", "snippets", "buffer" }, + providers = { + -- Rank LSP results above everything else, then snippets, then + -- path, then plain buffer words. This is what makes the menu feel + -- "smart" without any AI source. + lsp = { score_offset = 10 }, + snippets = { score_offset = 8 }, + path = { score_offset = 5 }, + buffer = { + -- Buffer words are the weakest signal, so only offer them once a + -- few characters are typed (keeps short LSP matches at the top). + min_keyword_length = 4, + score_offset = 0, + opts = { + -- Pull words from every loaded normal-file buffer, not just the + -- current one โ€” handy when jumping between related files. + get_bufnrs = function() + return vim.tbl_filter(function(bufnr) + return vim.bo[bufnr].buftype == "" + end, vim.api.nvim_list_bufs()) + end, + }, + }, + }, }, completion = { documentation = { auto_show = true, - auto_show_delay_ms = 500, + auto_show_delay_ms = 200, update_delay_ms = 50, window = { border = "rounded", @@ -38,7 +65,11 @@ return { }, }, }, - signature = { enabled = true }, + signature = { + enabled = true, + trigger = { show_on_insert = true }, + window = { border = "rounded" }, + }, snippets = { preset = "luasnip" }, fuzzy = { implementation = "prefer_rust" }, }) diff --git a/plugins/gitsigns.lua b/plugins/gitsigns.lua index eef7a2a..a515421 100644 --- a/plugins/gitsigns.lua +++ b/plugins/gitsigns.lua @@ -21,7 +21,7 @@ return { }, signs_staged_enable = true, signcolumn = true, -- Toggle with `:Gitsigns toggle_signs` - numhl = false, -- Toggle with `:Gitsigns toggle_numhl` + numhl = true, -- Toggle with `:Gitsigns toggle_numhl` linehl = false, -- Toggle with `:Gitsigns toggle_linehl` word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff` watch_gitdir = { diff --git a/plugins/lspconfig.lua b/plugins/lspconfig.lua index 240e864..7ffdcec 100644 --- a/plugins/lspconfig.lua +++ b/plugins/lspconfig.lua @@ -21,20 +21,41 @@ return { vim.lsp.config("lua_ls", { settings = { Lua = { - telemetry = { - enable = false, + completion = { + enable = true, + displayContext = 3, + }, + hint = { + enable = true, + }, + runtime = { + builtin = "enable", + }, + diagnostics = { + globals = { "vim" }, + }, + workspace = { + checkThirdParty = false, + library = { + vim.env.VIMRUNTIME, + }, }, }, }, }) - -- Custom configs (mason auto-enables installed servers via - -- mason-lspconfig's automatic_enable; these are not mason-managed) - vim.lsp.enable({ - "lsp-codelens", - "lsp-inlay_hint", - "lsp-inline_completion", - "lsp-linked_editing_range", + -- Go + vim.lsp.config("gopls", { + settings = { + gopls = { + -- gopls disables the `test` codelens by default. Enabling it puts a + -- runnable "run test"/"run benchmark" lens above each Test/Benchmark + -- function in *_test.go files; trigger it with cl (run lens). + codelenses = { + test = true, + }, + }, + }, }) -- Single LspAttach autocmd for all LSP-related setup @@ -49,24 +70,26 @@ return { vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) end - local bufmap = function(mode, lhs, rhs, desc) - vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc }) + -- Code lens: always on. enable() attaches a provider that + -- auto-refreshes as the buffer changes, so no manual keymap is needed. + if client and client:supports_method("textDocument/codeLens") then + vim.lsp.codelens.enable(true, { bufnr = bufnr }) end -- Navigation - bufmap("n", "gd", "lua vim.lsp.buf.definition()", "Go to definition") - bufmap("n", "gD", "lua vim.lsp.buf.declaration()", "Go to declaration") - bufmap("n", "gi", "lua vim.lsp.buf.implementation()", "Go to implementation") - bufmap("n", "go", "lua vim.lsp.buf.type_definition()", "Go to type definition") - bufmap("n", "gr", "lua vim.lsp.buf.references()", "List references") - bufmap("n", "gs", "lua vim.lsp.buf.signature_help()", "Signature help") + vim.keymap.set("n", "gd", "lua vim.lsp.buf.definition()", { desc = "Go to definition" }) + vim.keymap.set("n", "gD", "lua vim.lsp.buf.declaration()", { desc = "Go to declaration" }) + vim.keymap.set("n", "gi", "lua vim.lsp.buf.implementation()", { desc = "Go to implementation" }) + vim.keymap.set("n", "go", "lua vim.lsp.buf.type_definition()", { desc = "Go to type definition" }) + vim.keymap.set("n", "gr", "lua vim.lsp.buf.references()", { desc = "List references" }) + vim.keymap.set("n", "gs", "lua vim.lsp.buf.signature_help()", { desc = "Signature help" }) -- Actions - bufmap("n", "", "lua vim.lsp.buf.rename()", "Rename symbol") - bufmap("n", "", "lua vim.lsp.buf.code_action()", "Code action") + vim.keymap.set("n", "", "lua vim.lsp.buf.rename()", { desc = "Rename symbol" }) + vim.keymap.set("n", "", "lua vim.lsp.buf.code_action()", { desc = "Code action" }) -- Hover: LSP hover, falls back to diagnostic float if no hover info - bufmap("n", "K", function() + vim.keymap.set("n", "K", function() local has_diag = #vim.diagnostic.get(bufnr, { lnum = vim.fn.line(".") - 1 }) > 0 local clients = vim.lsp.get_clients({ bufnr = bufnr, method = "textDocument/hover" }) if #clients > 0 then @@ -74,33 +97,33 @@ return { elseif has_diag then vim.diagnostic.open_float({ border = "rounded" }) end - end, "Hover / diagnostic") + end, { desc = "Hover / diagnostic" }) -- Diagnostics - bufmap("n", "gl", "lua vim.diagnostic.open_float()", "Show diagnostics") - bufmap("n", "[d", function() + vim.keymap.set("n", "gl", "lua vim.diagnostic.open_float()", { desc = "Show diagnostics" }) + vim.keymap.set("n", "[d", function() vim.diagnostic.jump({ count = -1 }) - end, "Previous diagnostic") - bufmap("n", "]d", function() + end, { desc = "Previous diagnostic" }) + vim.keymap.set("n", "]d", function() vim.diagnostic.jump({ count = 1 }) - end, "Next diagnostic") + end, { desc = "Next diagnostic" }) -- Document symbols (outline view) - bufmap("n", "ls", function() + vim.keymap.set("n", "ls", function() Snacks.picker.lsp_symbols() - end, "Document symbols") + end, { desc = "Document symbols" }) -- Workspace symbols (project-wide symbol search) - bufmap("n", "lw", function() + vim.keymap.set("n", "lw", function() Snacks.picker.lsp_workspace_symbols() - end, "Workspace symbols") + end, { desc = "Workspace symbols" }) - -- Code lens - bufmap("n", "cl", "lua vim.lsp.codelens.run()", "Run code lens") - bufmap("n", "cL", "lua vim.lsp.codelens.refresh()", "Refresh code lens") + -- Code lens is refreshed automatically (see the codeLens autocmd + -- above); cl runs the lens action under the cursor. + vim.keymap.set("n", "cl", "lua vim.lsp.codelens.run()", { desc = "Run code lens" }) -- Debug LSP info - bufmap("n", "li", function() + vim.keymap.set("n", "li", function() local clients = vim.lsp.get_clients({ bufnr = bufnr }) if #clients == 0 then vim.notify("No LSP clients attached to this buffer", vim.log.levels.INFO) @@ -124,7 +147,7 @@ return { end vim.notify("LSP Clients:\n" .. table.concat(info, "\n"), vim.log.levels.INFO) - end, "LSP info") + end, { desc = "LSP info" }) end, }) end, diff --git a/plugins/lualine.lua b/plugins/lualine.lua index a5164f8..22a0b91 100644 --- a/plugins/lualine.lua +++ b/plugins/lualine.lua @@ -36,7 +36,6 @@ return { lualine_b = { "branch", "diff" }, lualine_c = { { "filename", path = 1 }, - { python_env, color = { fg = "#98be65" } }, }, lualine_x = { "diagnostics", diff --git a/plugins/luasnip.lua b/plugins/luasnip.lua index 40567d8..d24b968 100644 --- a/plugins/luasnip.lua +++ b/plugins/luasnip.lua @@ -1,3 +1,7 @@ +-- ===============================Keymaps Start================================= +-- n se Edit snippets +-- =================================Keymaps End================================= + --- LuaSnip โ€” the snippet engine that blink.cmp drives (see plugins/blink.lua, --- `snippets.preset = "luasnip"`). --- diff --git a/plugins/neogen.lua b/plugins/neogen.lua new file mode 100644 index 0000000..ba8f50a --- /dev/null +++ b/plugins/neogen.lua @@ -0,0 +1,22 @@ +--- Neogen โ€” generates annotation/docstring skeletons for the function, class, +--- or type under the cursor using treesitter (see plugins/nvim-treesitter.lua). +--- +--- Supports many languages and conventions (Python: google/numpy/reST, +--- Lua: emmylua/ldoc, JS/TS: jsdoc, Go: godoc, Rust, etc.). +--- +--- Generated docstrings are emitted as LuaSnip snippets (see plugins/luasnip.lua), +--- so you Tab/S-Tab through the fields to fill them in. +--- +--- Usage: place cursor in/above a function and press cd. +return { + src = "https://github.com/danymat/neogen", + config = function() + require("neogen").setup({ + snippet_engine = "luasnip", + }) + + vim.keymap.set("n", "cd", function() + require("neogen").generate() + end, { desc = "Generate docstring" }) + end, +} diff --git a/plugins/snacks.lua b/plugins/snacks.lua index 97d77bd..18d71a2 100644 --- a/plugins/snacks.lua +++ b/plugins/snacks.lua @@ -3,6 +3,7 @@ return { version = "v2.31.0", config = function() require("snacks").setup({ + ---@module 'snacks' Snacks animate = { enabled = true }, bigfile = { enabled = true }, bufferline = { enabled = true }, @@ -95,6 +96,9 @@ return { words = { enabled = true }, }) + ---@module 'Snacks' snacks + Snacks = require("snacks") + -- Keymaps Snacks.keymap.set("n", "e", function() Snacks.explorer() diff --git a/plugins/todo-comments.lua b/plugins/todo-comments.lua new file mode 100644 index 0000000..a0c78ff --- /dev/null +++ b/plugins/todo-comments.lua @@ -0,0 +1,37 @@ +--- todo-comments โ€” highlights and lists TODO / FIXME / HACK / WARN / NOTE / etc. +--- comments in your code. +--- +--- Integrations: +--- * Listing/searching uses the snacks picker (Snacks.picker.todo_comments). +--- * The full list also opens in Trouble via `:Trouble todo` (see +--- plugins/trouble.lua, xt). +--- +--- Keymaps: +--- ]t / [t jump to next / previous todo comment +--- ft find todos (snacks picker) +--- fT find todos limited to TODO/FIX/FIXME (snacks picker) +return { + src = "https://github.com/folke/todo-comments.nvim", + version = "v1.5.0", + config = function() + ---@module 'todo-comments' todo + local todo = require("todo-comments") + -- `signs = false` keeps the sign column free for gitsigns/diagnostics; + -- highlighting of the comment keywords stays on. + todo.setup({ signs = false }) + + vim.keymap.set("n", "]t", function() + todo.jump_next() + end, { desc = "Next todo comment" }) + vim.keymap.set("n", "[t", function() + todo.jump_prev() + end, { desc = "Previous todo comment" }) + + vim.keymap.set("n", "ft", function() + Snacks.picker.todo_comments() + end, { desc = "Find todos" }) + vim.keymap.set("n", "fT", function() + Snacks.picker.todo_comments({ keywords = { "TODO", "FIX", "FIXME" } }) + end, { desc = "Find todos (TODO/FIX/FIXME)" }) + end, +} diff --git a/plugins/trouble.lua b/plugins/trouble.lua new file mode 100644 index 0000000..8bd17b0 --- /dev/null +++ b/plugins/trouble.lua @@ -0,0 +1,123 @@ +-- ============================================================================= +-- KEYMAPDOC:START (auto-generated, do not edit) +-- n xx Diagnostics (Trouble) +-- n xA All views (Trouble) +-- n xX Buffer diagnostics (Trouble) +-- n xs Symbols (Trouble) +-- n xr LSP references/defs (Trouble) +-- n xl Location list (Trouble) +-- n xq Quickfix list (Trouble) +-- n xt Todos (Trouble) +-- KEYMAPDOC:END +-- ============================================================================= + +return { + src = "https://github.com/folke/trouble.nvim", + -- `main`, not the v3.7.1 tag: the tag's treesitter view calls the internal + -- highlighter `_on_line`, which Neovim 0.12 removed (renamed to `_on_range`). + -- main checks for `_on_range` and is compatible. + version = "main", + config = function() + require("trouble").setup({}) + + vim.keymap.set("n", "xx", "Trouble diagnostics toggle", { desc = "Diagnostics (Trouble)" }) + + --- The right-hand info column: todo-comments on top, document symbols below. + ---@type table|nil the open todo view, used to detect/close the column + local info_column = nil + + -- TODO: Adjust this to not open on dashboard + + --- Open the right-hand info column (todo + symbols). + local function open_info_column() + ---@module 'trouble' Load trouble module + local trouble = require("trouble") + + --- Open Trouble.todo first as a window split. + ---@class todo function + ---@field mode string + ---@field focus boolean + ---@field win table + ---@return function wait + local todo = trouble.open({ + mode = "todo", + focus = false, + win = { + type = "split", + relative = "editor", + position = "right", + size = 0.15, + }, + }) + info_column = todo + + todo:wait(function() + trouble.open({ + mode = "symbols", + focus = false, + win = { + type = "split", + relative = "win", + position = "bottom", + win = todo.win.win, + }, + }) + end) + end + + --- Toggle the right-hand info column. Defaulted on (see autocmd below). + local function toggle_info_column() + local trouble = require("trouble") + if info_column then + trouble.close({ mode = "todo" }) + trouble.close({ mode = "symbols" }) + info_column = nil + else + open_info_column() + end + end + + vim.keymap.set("n", "xA", toggle_info_column, { desc = "All views (Trouble)" }) + + -- Open the info column by default once the UI is ready. + vim.api.nvim_create_autocmd("VimEnter", { + once = true, + callback = function() + vim.schedule(open_info_column) + end, + }) + + -- When quitting a normal window (e.g. `:q` in the editor), tear down the + -- info column too so the trouble splits don't keep Neovim open. + vim.api.nvim_create_autocmd("QuitPre", { + callback = function() + if not info_column then + return + end + if vim.bo.filetype == "trouble" then + return + end + local trouble = require("trouble") + trouble.close({ mode = "todo" }) + trouble.close({ mode = "symbols" }) + info_column = nil + end, + }) + vim.keymap.set( + "n", + "xX", + "Trouble diagnostics toggle filter.buf=0", + { desc = "Buffer diagnostics (Trouble)" } + ) + vim.keymap.set("n", "xs", "Trouble symbols toggle focus=false", { desc = "Symbols (Trouble)" }) + vim.keymap.set( + "n", + "xr", + "Trouble lsp toggle focus=false win.position=right", + { desc = "LSP references/defs (Trouble)" } + ) + vim.keymap.set("n", "xl", "Trouble loclist toggle", { desc = "Location list (Trouble)" }) + vim.keymap.set("n", "xq", "Trouble qflist toggle", { desc = "Quickfix list (Trouble)" }) + vim.keymap.set("n", "xt", "Trouble todo toggle", { desc = "Todos (Trouble)" }) + end, +} diff --git a/plugins/which-key.lua b/plugins/which-key.lua index b6a8eab..a1b0d5c 100644 --- a/plugins/which-key.lua +++ b/plugins/which-key.lua @@ -12,11 +12,13 @@ return { -- their `desc` automatically. Register only the prefixes here. wk.add({ { "b", group = "buffer" }, + { "d", group = "delete (no yank)" }, { "f", group = "find" }, { "g", group = "git" }, { "p", group = "paste/path" }, { "s", group = "split/scratch" }, { "t", group = "toggle" }, + { "x", group = "trouble/diagnostics" }, }) end, } diff --git a/snippets/go.lua b/snippets/go.lua new file mode 100644 index 0000000..11822f3 --- /dev/null +++ b/snippets/go.lua @@ -0,0 +1,140 @@ +--- Native LuaSnip snippets for Go. +--- See snippets/all.lua for the format. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt + +return { + -- if err != nil { return ... } + s( + "iferr", + fmt( + [[ + if err != nil {{ + return {} + }} + ]], + { i(1, "err") } + ) + ), + + -- Assign + error check. + s( + "ife", + fmt( + [[ + {}, err := {} + if err != nil {{ + return {} + }} + ]], + { i(1, "val"), i(2, "f()"), i(3, "err") } + ) + ), + + -- Wrap an error with context. + s("errf", fmt([[fmt.Errorf("{}: %w", {})]], { i(1, "context"), i(2, "err") })), + + -- func main. + s( + "main", + fmt( + [[ + func main() {{ + {} + }} + ]], + { i(0) } + ) + ), + + -- Function definition. + s( + "func", + fmt( + [[ + func {}({}) {} {{ + {} + }} + ]], + { i(1, "name"), i(2), i(3), i(4) } + ) + ), + + -- Method on a receiver. + s( + "meth", + fmt( + [[ + func ({} {}) {}({}) {} {{ + {} + }} + ]], + { i(1, "r"), i(2, "Type"), i(3, "Name"), i(4), i(5), i(6) } + ) + ), + + -- Struct type. + s( + "struct", + fmt( + [[ + type {} struct {{ + {} + }} + ]], + { i(1, "Name"), i(2) } + ) + ), + + -- Interface type. + s( + "interface", + fmt( + [[ + type {} interface {{ + {} + }} + ]], + { i(1, "Name"), i(2) } + ) + ), + + -- Table-driven test. + s( + "tt", + fmt( + [[ + func Test{}(t *testing.T) {{ + tests := []struct {{ + name string + {} + }}{{ + {} + }} + for _, tt := range tests {{ + t.Run(tt.name, func(t *testing.T) {{ + {} + }}) + }} + }} + ]], + { i(1, "Name"), i(2), i(3), i(4) } + ) + ), + + -- Goroutine. + s( + "go", + fmt( + [[ + go func() {{ + {} + }}() + ]], + { i(0) } + ) + ), +} diff --git a/snippets/lua.lua b/snippets/lua.lua new file mode 100644 index 0000000..d4cc220 --- /dev/null +++ b/snippets/lua.lua @@ -0,0 +1,123 @@ +--- Native LuaSnip snippets for Lua. See snippets/all.lua for the format. +--- Type a `trig` then expand from the blink.cmp menu; Tab jumps tabstops. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt +local fmta = require("luasnip.extras.fmt").fmta + +return { + -- Local function. + s( + "lf", + fmt( + [[ + local function {}({}) + {} + end + ]], + { i(1, "name"), i(2), i(3) } + ) + ), + + -- Anonymous/assigned function. + s( + "fn", + fmt( + [[ + function {}({}) + {} + end + ]], + { i(1, "name"), i(2), i(3) } + ) + ), + + -- for ipairs loop. + s( + "fori", + fmt( + [[ + for {}, {} in ipairs({}) do + {} + end + ]], + { i(1, "idx"), i(2, "value"), i(3, "tbl"), i(4) } + ) + ), + + -- for pairs loop. + s( + "forp", + fmt( + [[ + for {}, {} in pairs({}) do + {} + end + ]], + { i(1, "key"), i(2, "value"), i(3, "tbl"), i(4) } + ) + ), + + -- pcall wrapper. + s("pcall", fmt("local ok, {} = pcall({})", { i(1, "res"), i(2, "fn") })), + + -- require assignment. + s("req", fmt([[local {} = require("{}")]], { i(1, "mod"), i(2, "module") })), + + -- if statement. + s( + "if", + fmt( + [[ + if {} then + {} + end + ]], + { i(1, "cond"), i(2) } + ) + ), + + -- Buffer-local autocmd. + s( + "aucmd", + fmt( + [[ + vim.api.nvim_create_autocmd("{}", {{ + group = {}, + callback = function({}) + {} + end, + }}) + ]], + { i(1, "Event"), i(2, "group"), i(3, "args"), i(4) } + ) + ), + + -- Keymap. + s( + "map", + fmta([[vim.keymap.set("", "", , { desc = "" })]], { + mode = i(1, "n"), + lhs = i(2), + rhs = i(3, "function() end"), + desc = i(4), + }) + ), + + -- Module skeleton (M table + return). + s( + "mod", + fmt( + [[ + local M = {{}} + + {} + + return M + ]], + { i(1) } + ) + ), +} diff --git a/snippets/markdown.lua b/snippets/markdown.lua new file mode 100644 index 0000000..b11a5b5 --- /dev/null +++ b/snippets/markdown.lua @@ -0,0 +1,76 @@ +--- Native LuaSnip snippets for Markdown. +--- See snippets/all.lua for the format. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt +local fmta = require("luasnip.extras.fmt").fmta + +return { + -- Fenced code block. + s( + "code", + fmt( + [[ + ```{} + {} + ``` + ]], + { i(1, "lang"), i(2) } + ) + ), + + -- Link. + s("link", fmta("[]()", { text = i(1, "text"), url = i(2, "https://") })), + + -- Image. + s("img", fmta("![]()", { alt = i(1, "alt"), src = i(2, "path") })), + + -- Table (2 columns). + s( + "table", + fmt( + [[ + | {} | {} | + | --- | --- | + | {} | {} | + ]], + { i(1, "Col1"), i(2, "Col2"), i(3), i(4) } + ) + ), + + -- Collapsible details block. + s( + "details", + fmt( + [[ +
+ {} + + {} + +
+ ]], + { i(1, "Summary"), i(2) } + ) + ), + + -- YAML frontmatter. + s( + "frontmatter", + fmt( + [[ + --- + title: {} + date: {} + --- + {} + ]], + { i(1, "Title"), i(2, os.date("%Y-%m-%d")), i(0) } + ) + ), + + -- Task list item. + s("todo", fmt("- [ ] {}", { i(1) })), +} diff --git a/snippets/python.lua b/snippets/python.lua new file mode 100644 index 0000000..4032877 --- /dev/null +++ b/snippets/python.lua @@ -0,0 +1,113 @@ +--- Native LuaSnip snippets for Python. +--- See snippets/all.lua for the format. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt + +return { + -- if __name__ == "__main__": + s( + "main", + fmt( + [[ + def main() -> None: + {} + + + if __name__ == "__main__": + main() + ]], + { i(0, "pass") } + ) + ), + + -- Function with type hints. + s( + "def", + fmt( + [[ + def {}({}) -> {}: + {} + ]], + { i(1, "name"), i(2), i(3, "None"), i(4, "pass") } + ) + ), + + -- Class definition. + s( + "class", + fmt( + [[ + class {}({}): + def __init__(self{}) -> None: + {} + ]], + { i(1, "Name"), i(2), i(3), i(4, "pass") } + ) + ), + + -- Dataclass. + s( + "dataclass", + fmt( + [[ + @dataclass + class {}: + {} + ]], + { i(1, "Name"), i(2, "pass") } + ) + ), + + -- try/except. + s( + "try", + fmt( + [[ + try: + {} + except {} as exc: + {} + ]], + { i(1, "pass"), i(2, "Exception"), i(3, "raise") } + ) + ), + + -- with context manager. + s( + "with", + fmt( + [[ + with {} as {}: + {} + ]], + { i(1, "open(path)"), i(2, "f"), i(3, "pass") } + ) + ), + + -- for loop. + s( + "for", + fmt( + [[ + for {} in {}: + {} + ]], + { i(1, "item"), i(2, "iterable"), i(3, "pass") } + ) + ), + + -- pytest test function. + s( + "test", + fmt( + [[ + def test_{}() -> None: + {} + ]], + { i(1, "name"), i(2, "assert True") } + ) + ), +} diff --git a/snippets/sh.lua b/snippets/sh.lua new file mode 100644 index 0000000..9329f3c --- /dev/null +++ b/snippets/sh.lua @@ -0,0 +1,121 @@ +--- Native LuaSnip snippets for shell/bash (filetype `sh`). +--- See snippets/all.lua for the format. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt + +return { + -- Safe bash header: shebang + strict mode. + s( + "shebang", + fmt( + [[ + #!/usr/bin/env bash + set -euo pipefail + {} + ]], + { i(0) } + ) + ), + + -- Strict mode line on its own. + s("strict", { ls.text_node("set -euo pipefail") }), + + -- if statement. + s( + "if", + fmt( + [[ + if {}; then + {} + fi + ]], + { i(1, '[[ -n "$var" ]]'), i(2, ":") } + ) + ), + + -- if/else statement. + s( + "ife", + fmt( + [[ + if {}; then + {} + else + {} + fi + ]], + { i(1, '[[ -n "$var" ]]'), i(2, ":"), i(3, ":") } + ) + ), + + -- for loop. + s( + "for", + fmt( + [[ + for {} in {}; do + {} + done + ]], + { i(1, "item"), i(2, '"${arr[@]}"'), i(3, ":") } + ) + ), + + -- while loop. + s( + "while", + fmt( + [[ + while {}; do + {} + done + ]], + { i(1, "true"), i(2, ":") } + ) + ), + + -- case statement. + s( + "case", + fmt( + [[ + case "{}" in + {}) + {} + ;; + *) + {} + ;; + esac + ]], + { i(1, "$1"), i(2, "pattern"), i(3, ":"), i(4, ":") } + ) + ), + + -- Function definition. + s( + "func", + fmt( + [[ + {}() {{ + {} + }} + ]], + { i(1, "name"), i(2, ":") } + ) + ), + + -- Guard: require a command to exist. + s( + "need", + fmt( + [[command -v {} >/dev/null 2>&1 || {{ echo "{} is required" >&2; exit 1; }}]], + { i(1, "cmd"), ls.function_node(function(args) + return args[1][1] + end, { 1 }) } + ) + ), +} diff --git a/snippets/terraform.lua b/snippets/terraform.lua new file mode 100644 index 0000000..e514e85 --- /dev/null +++ b/snippets/terraform.lua @@ -0,0 +1,124 @@ +--- Native LuaSnip snippets for Terraform / OpenTofu (filetype `terraform`). +--- `.tofu` files are mapped to this filetype in lua/autocmds.lua, so these +--- snippets work for both. See snippets/all.lua for the format. + +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt + +return { + -- Resource block. + s( + "resource", + fmt( + [[ + resource "{}" "{}" {{ + {} + }} + ]], + { i(1, "type"), i(2, "name"), i(3) } + ) + ), + + -- Data source block. + s( + "data", + fmt( + [[ + data "{}" "{}" {{ + {} + }} + ]], + { i(1, "type"), i(2, "name"), i(3) } + ) + ), + + -- Input variable. + s( + "variable", + fmt( + [[ + variable "{}" {{ + type = {} + description = "{}" + default = {} + }} + ]], + { i(1, "name"), i(2, "string"), i(3), i(4, "null") } + ) + ), + + -- Output value. + s( + "output", + fmt( + [[ + output "{}" {{ + description = "{}" + value = {} + }} + ]], + { i(1, "name"), i(2), i(3) } + ) + ), + + -- Module call. + s( + "module", + fmt( + [[ + module "{}" {{ + source = "{}" + {} + }} + ]], + { i(1, "name"), i(2, "./modules/example"), i(3) } + ) + ), + + -- Provider block. + s( + "provider", + fmt( + [[ + provider "{}" {{ + {} + }} + ]], + { i(1, "name"), i(2) } + ) + ), + + -- Local values. + s( + "locals", + fmt( + [[ + locals {{ + {} + }} + ]], + { i(1) } + ) + ), + + -- terraform settings + required_providers. + s( + "terraform", + fmt( + [[ + terraform {{ + required_version = ">= {}" + required_providers {{ + {} = {{ + source = "{}" + version = "{}" + }} + }} + }} + ]], + { i(1, "1.6.0"), i(2, "aws"), i(3, "hashicorp/aws"), i(4, "~> 5.0") } + ) + ), +} From 8118e8ccac06719da644ab694fb26428c2745fb9 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Tue, 23 Jun 2026 14:01:15 -0500 Subject: [PATCH 05/12] docs: Update docstrings Signed-off-by: Tristan Jahnke --- .gitignore | 8 ++- README.md | 31 +++++++-- lua/utils/keymapdoc/extract.lua | 12 ++-- lua/utils/keymapdoc/render.lua | 8 +-- plugins/trouble.lua | 119 ++++++-------------------------- 5 files changed, 61 insertions(+), 117 deletions(-) diff --git a/.gitignore b/.gitignore index 36d7db4..e351344 100644 --- a/.gitignore +++ b/.gitignore @@ -8,12 +8,14 @@ plugin/packer_compiled.lua spell/ # Caches -.aider.tags.cache.v4/ .luac *.swp *.swo *~ tags +*.cache +*.cache.* +*.history # OS .DS_Store @@ -21,3 +23,7 @@ Thumbs.db # Profiling output profile.json + +# Markdown +/*.md +!README.md diff --git a/README.md b/README.md index bf05c50..735c07a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,30 @@ # nvim setup -**test** +This repository contains the configuration and plugins for my Neovim editor. The setup is designed to provide a highly customizable and efficient development environment tailored to various programming languages and tasks. -*test* +## Features ---- +- **Language Server Protocol (LSP)**: Integrated LSP support with multiple language servers for enhanced code intelligence, diagnostics, and auto-completion. +- **Snippets**: Utilizes LuaSnip for snippet management, allowing for quick and efficient coding through pre-defined templates. +- **Version Control Integration**: Gitsigns provides visual indications of changes in the gutter, making it easier to track modifications. +- **Auto Formatting**: Conform.nvim automatically formats code on save, ensuring consistent styling across different file types. +- **Keymaps**: Custom keybindings for quick access to frequently used commands and plugins. +- **Dashboard**: A customizable dashboard with recent files, git status, and other useful information. -| test | cake | carl | four | -| --------------- | --------------- | --------------- | --------------- | -| yes | no | maybe | so | +## Installation -## Test time +1. Clone the repository: + + ```sh + git clone https://github.com/yourusername/nvim-setup.git ~/.config/nvim + ``` + +2. Start Neovim and enjoy your customized setup. + +## Configuration + +The configuration is split into multiple Lua files located in the `lua` directory. You can customize the settings by editing these files or adding your own configurations. + +## License + +This project is licensed under the Unlicense - see the [LICENSE](LICENSE) file for details. diff --git a/lua/utils/keymapdoc/extract.lua b/lua/utils/keymapdoc/extract.lua index d1b81b5..75c3298 100644 --- a/lua/utils/keymapdoc/extract.lua +++ b/lua/utils/keymapdoc/extract.lua @@ -1,6 +1,6 @@ local M = {} ---- Matches all function calls; filter by name in Lua +--- Matches all function calls; filter by name in Lua. ---@type vim.treesitter.Query local QUERY = vim.treesitter.query.parse( "lua", @@ -48,7 +48,7 @@ end --- Scan an opts table_constructor for a `desc = "..."` field. ---@param opts_node TSNode|nil Treesitter node or nil ---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. ----@return string -- TODO: Add definition +---@return string Description text if found, otherwise empty string. ---@see node_str local function find_desc(opts_node, buf) if not opts_node or opts_node:type() ~= "table_constructor" then @@ -67,9 +67,9 @@ end --- Pull one capture node out of an iter_matches result, handling both the older API (id -> node) --- and the newer API (id -> { node, ... }). ----@param match table -- TODO: Add description ----@param want_name string -- TODO: Add description ----@return TSNode|nil -- TODO: Add description +---@param match table Match result from iter_matches. +---@param want_name string Name of the capture to extract. +---@return TSNode|nil Extracted node if found, otherwise nil. local function capture_node(match, want_name) for id, nodes in pairs(match) do if QUERY.captures[id] == want_name then @@ -81,7 +81,7 @@ end --- Extract keymap entries from buffer. ---@param buf integer|string Nvim buf index or nil; nil or 0 is current buf. ----@return KeymapEntry[] +---@return KeymapEntry[] List of extracted keymap entries. function M.extract(buf) buf = (buf == nil or buf == 0) and vim.api.nvim_get_current_buf() or buf diff --git a/lua/utils/keymapdoc/render.lua b/lua/utils/keymapdoc/render.lua index 907561d..d7e883d 100644 --- a/lua/utils/keymapdoc/render.lua +++ b/lua/utils/keymapdoc/render.lua @@ -4,8 +4,8 @@ local START = "-- ===============================Keymaps Start================== local STOP = "-- =================================Keymaps End=================================" --- Build table of keymaps. ----@param entries table -- TODO: Add description ----@return table -- TODO: Add description +---@param entries table A list of keymap entries, each containing mode, lhs, and desc fields. +---@return table A table containing the formatted keymaps from the current file. local function build_lines(entries) local lines = { START } if #entries == 0 then @@ -27,8 +27,8 @@ local function build_lines(entries) end --- Inject keymap lines to top of current file between marker blocks. ----@param buf integer Neovim buffer or nil; current buffer is 0. ----@param entries table -- TODO: Add description +---@param buf integer Neovim buffer number or nil; if nil, the current buffer is used. +---@param entries table A list of keymap entries to inject into the file. function M.inject(buf, entries) buf = (buf == 0) and vim.api.nvim_get_current_buf() or buf diff --git a/plugins/trouble.lua b/plugins/trouble.lua index 8bd17b0..438f3d8 100644 --- a/plugins/trouble.lua +++ b/plugins/trouble.lua @@ -1,123 +1,44 @@ --- ============================================================================= --- KEYMAPDOC:START (auto-generated, do not edit) +-- ===============================Keymaps Start================================= -- n xx Diagnostics (Trouble) --- n xA All views (Trouble) -- n xX Buffer diagnostics (Trouble) -- n xs Symbols (Trouble) -- n xr LSP references/defs (Trouble) -- n xl Location list (Trouble) -- n xq Quickfix list (Trouble) -- n xt Todos (Trouble) --- KEYMAPDOC:END --- ============================================================================= +-- =================================Keymaps End================================= return { src = "https://github.com/folke/trouble.nvim", - -- `main`, not the v3.7.1 tag: the tag's treesitter view calls the internal - -- highlighter `_on_line`, which Neovim 0.12 removed (renamed to `_on_range`). - -- main checks for `_on_range` and is compatible. version = "main", config = function() require("trouble").setup({}) - - vim.keymap.set("n", "xx", "Trouble diagnostics toggle", { desc = "Diagnostics (Trouble)" }) - - --- The right-hand info column: todo-comments on top, document symbols below. - ---@type table|nil the open todo view, used to detect/close the column - local info_column = nil - - -- TODO: Adjust this to not open on dashboard - - --- Open the right-hand info column (todo + symbols). - local function open_info_column() - ---@module 'trouble' Load trouble module - local trouble = require("trouble") - - --- Open Trouble.todo first as a window split. - ---@class todo function - ---@field mode string - ---@field focus boolean - ---@field win table - ---@return function wait - local todo = trouble.open({ - mode = "todo", - focus = false, - win = { - type = "split", - relative = "editor", - position = "right", - size = 0.15, - }, - }) - info_column = todo - - todo:wait(function() - trouble.open({ - mode = "symbols", - focus = false, - win = { - type = "split", - relative = "win", - position = "bottom", - win = todo.win.win, - }, - }) - end) - end - - --- Toggle the right-hand info column. Defaulted on (see autocmd below). - local function toggle_info_column() - local trouble = require("trouble") - if info_column then - trouble.close({ mode = "todo" }) - trouble.close({ mode = "symbols" }) - info_column = nil - else - open_info_column() - end - end - - vim.keymap.set("n", "xA", toggle_info_column, { desc = "All views (Trouble)" }) - - -- Open the info column by default once the UI is ready. - vim.api.nvim_create_autocmd("VimEnter", { - once = true, - callback = function() - vim.schedule(open_info_column) - end, - }) - - -- When quitting a normal window (e.g. `:q` in the editor), tear down the - -- info column too so the trouble splits don't keep Neovim open. - vim.api.nvim_create_autocmd("QuitPre", { - callback = function() - if not info_column then - return - end - if vim.bo.filetype == "trouble" then - return - end - local trouble = require("trouble") - trouble.close({ mode = "todo" }) - trouble.close({ mode = "symbols" }) - info_column = nil - end, - }) - vim.keymap.set( + vim.api.nvim_set_keymap("n", "xx", ":Trouble diagnostics toggle", { desc = "Diagnostics (Trouble)" }) + vim.api.nvim_set_keymap( "n", "xX", - "Trouble diagnostics toggle filter.buf=0", + ":Trouble diagnostics toggle filter.buf=0", { desc = "Buffer diagnostics (Trouble)" } ) - vim.keymap.set("n", "xs", "Trouble symbols toggle focus=false", { desc = "Symbols (Trouble)" }) - vim.keymap.set( + vim.api.nvim_set_keymap( + "n", + "xs", + "Trouble symbols toggle focus=false", + { desc = "Symbols (Trouble)" } + ) + vim.api.nvim_set_keymap( "n", "xr", "Trouble lsp toggle focus=false win.position=right", { desc = "LSP references/defs (Trouble)" } ) - vim.keymap.set("n", "xl", "Trouble loclist toggle", { desc = "Location list (Trouble)" }) - vim.keymap.set("n", "xq", "Trouble qflist toggle", { desc = "Quickfix list (Trouble)" }) - vim.keymap.set("n", "xt", "Trouble todo toggle", { desc = "Todos (Trouble)" }) + vim.api.nvim_set_keymap("n", "xl", ":Trouble loclist toggle", { desc = "Location list (Trouble)" }) + vim.api.nvim_set_keymap("n", "xq", ":Trouble qflist toggle", { desc = "Quickfix list (Trouble)" }) + vim.api.nvim_set_keymap( + "n", + "xt", + ":Trouble todo toggle focue=false win.type=split win.relative=editor win.position=right win.size=0.15", + { desc = "Todos (Trouble)" } + ) end, } From 5a4e8a9c156f03aa048dabe2aded5be70432d842 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Thu, 25 Jun 2026 09:37:20 -0500 Subject: [PATCH 06/12] fix: Add keymaps for pr-description Signed-off-by: Tristan Jahnke --- plugins/pr-description.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/pr-description.lua b/plugins/pr-description.lua index ea5dc11..1b07f0b 100644 --- a/plugins/pr-description.lua +++ b/plugins/pr-description.lua @@ -1,3 +1,14 @@ return { src = "https://github.com/remoterabbit/pr-description.nvim", + config = function() + require("pr-description").setup({ + foldable_file_changes = true, + }) + vim.api.nvim_set_keymap( + "n", + "gd", + ":PRDescription!", + { desc = "Generate PR Description from commits." } + ) + end, } From d46b859fea3f49c9de9bbc8630bc64dddd01e889 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Thu, 25 Jun 2026 09:37:40 -0500 Subject: [PATCH 07/12] docs: Update keymaps Signed-off-by: Tristan Jahnke --- plugins/pr-description.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/pr-description.lua b/plugins/pr-description.lua index 1b07f0b..6e96696 100644 --- a/plugins/pr-description.lua +++ b/plugins/pr-description.lua @@ -1,3 +1,7 @@ +-- ===============================Keymaps Start================================= +-- n gd Generate PR Description from commits. +-- =================================Keymaps End================================= + return { src = "https://github.com/remoterabbit/pr-description.nvim", config = function() From 5c98a4526d44be13e19f0f1234a1c3dbe205dc2f Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Thu, 25 Jun 2026 09:51:17 -0500 Subject: [PATCH 08/12] docs(pr-despription): Update file docs Signed-off-by: Tristan Jahnke --- plugins/pr-description.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/pr-description.lua b/plugins/pr-description.lua index 6e96696..5738639 100644 --- a/plugins/pr-description.lua +++ b/plugins/pr-description.lua @@ -1,3 +1,12 @@ +-- INFO ======================================================================== +-- Project Name: pr-description.nvim +-- Author: RemoteRabbit +-- URL: https://github.com/remoterabbit/pr-description.nvim +-- Description: Generate well-formatted PR/MR descriptions from your git commits. +-- Analyzes commits using conventional commit patterns, categorizes them, links +-- issues and Jira tickets, and produces markdown output for GitHub PRs or +-- GitLab MRs. +-- ============================================================================= -- ===============================Keymaps Start================================= -- n gd Generate PR Description from commits. -- =================================Keymaps End================================= From 8ff77d0e9c88881c026a7263af21b05151fe4fda Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Thu, 25 Jun 2026 13:05:24 -0500 Subject: [PATCH 09/12] feat: Add Catppiccin proper Signed-off-by: Tristan Jahnke --- AGENTS.md | 0 init.lua | 30 +++++++++++++++++ nvim-pack-lock.json | 8 +++++ plugins/catppuccin.lua | 76 ++++++++++++++++++++++++++++++++++++++++++ plugins/lualine.lua | 3 +- plugins/mini.lua | 28 ++++++++++++++++ plugins/showkeys.lua | 12 +++++++ 7 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md create mode 100644 plugins/catppuccin.lua create mode 100644 plugins/showkeys.lua diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e69de29 diff --git a/init.lua b/init.lua index 02d7c99..436ff8f 100644 --- a/init.lua +++ b/init.lua @@ -28,6 +28,9 @@ require("utils.keymapdoc").setup() --- version = "v1.2.3" or "main", -- optional (tag/branch/commit) --- config = function() ... end, -- optional, runs after install/load --- priority = 100, -- optional, higher runs first (default 0) +--- enabled = false, -- optional, default true; when false +--- -- the plugin is not loaded/configured +--- -- and is uninstalled if present --- } --- --- Configs run sorted by `priority` (desc), then file name (asc) for @@ -40,6 +43,10 @@ local specs = {} ---@type table Table holding individual plugin configurations. local configs = {} +---@type table Set of plugin names (last path segment of `src`) explicitly +--- disabled via `enabled = false`, queued for uninstall. +local disabled = {} + --- Validate a single spec and queue its add-spec/config. ---@param name string Spec file name (used in error messages) ---@param plugin table Spec table returned by a plugins/*.lua file @@ -56,6 +63,12 @@ local function process_spec(name, plugin) return end + -- Default is enabled; only `enabled = false` opts out. + if plugin.enabled == false then + disabled[plugin.src:gsub("%.git$", ""):match("([^/]+)$")] = true + return + end + table.insert(specs, { src = plugin.src, version = plugin.version }) if type(plugin.config) == "function" then table.insert(configs, { @@ -108,6 +121,23 @@ if not ok_add then vim.notify("vim.pack.add failed:\n" .. tostring(add_err), vim.log.levels.ERROR) end +--- Uninstall any plugins explicitly disabled via `enabled = false`, but only +--- those actually installed (vim.pack.del errors on unknown names). +if next(disabled) then + local to_remove = {} + for _, p in ipairs(vim.pack.get()) do + if disabled[p.spec.name] then + table.insert(to_remove, p.spec.name) + end + end + if #to_remove > 0 then + local ok_del, del_err = pcall(vim.pack.del, to_remove) + if not ok_del then + vim.notify("vim.pack.del failed:\n" .. tostring(del_err), vim.log.levels.ERROR) + end + end +end + for _, config in ipairs(configs) do local ok, err = pcall(config.fn) if not ok then diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 375833b..16b4e6c 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -53,6 +53,10 @@ "rev": "23e7e9f883d01289ebd90e98025acc860ea26366", "src": "https://github.com/danymat/neogen" }, + "nvim": { + "rev": "e068ab5f8261f23f6f71ffd8791ae40315b77b9c", + "src": "https://github.com/catppuccin/nvim" + }, "nvim-autopairs": { "rev": "23320e75953ac82e559c610bec5a90d9c6dfa743", "src": "https://github.com/windwp/nvim-autopairs", @@ -75,6 +79,10 @@ "rev": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a", "src": "https://github.com/MeanderingProgrammer/render-markdown.nvim" }, + "showkeys": { + "rev": "cb0a50296f11f1e585acffba8c253b9e8afc1f84", + "src": "https://github.com/nvzone/showkeys" + }, "snacks.nvim": { "rev": "e6fd58c82f2f3fcddd3fe81703d47d6d48fc7b9f", "src": "https://github.com/folke/snacks.nvim", diff --git a/plugins/catppuccin.lua b/plugins/catppuccin.lua new file mode 100644 index 0000000..551d54b --- /dev/null +++ b/plugins/catppuccin.lua @@ -0,0 +1,76 @@ +return { + src = "https://github.com/catppuccin/nvim", + config = function() + require("catppuccin").setup({ + flavor = "mocha", + background = { -- :h background + light = "latte", + dark = "mocha", + }, + transparent_background = false, -- disables setting the background color. + float = { + transparent = false, -- enable transparent floating windows + solid = false, -- use solid styling for floating windows, see |winborder| + }, + term_colors = true, -- sets terminal colors (e.g. `g:terminal_color_0`) + dim_inactive = { + enabled = true, -- dims the background color of inactive window + shade = "dark", + percentage = 0.25, -- percentage of the shade to apply to the inactive window + }, + styles = { -- Handles the styles of general hi groups (see `:h highlight-args`): + comments = { "italic" }, -- Change the style of comments + conditionals = { "italic" }, + loops = {}, + functions = {}, + keywords = { "standout" }, + strings = {}, + variables = {}, + numbers = {}, + booleans = {}, + properties = {}, + types = { "italic" }, + operators = {}, + -- miscs = {}, -- Uncomment to turn off hard-coded styles + }, + lsp_styles = { -- Handles the style of specific lsp hl groups (see `:h lsp-highlight`). + virtual_text = { + errors = { "italic", "undercurl" }, + hints = { "italic" }, + warnings = { "italic", "undercurl" }, + information = { "italic" }, + ok = { "italic" }, + }, + underlines = { + errors = { "undercurl" }, + hints = { "underline" }, + warnings = { "undercurl" }, + information = { "underline" }, + ok = { "underline" }, + }, + inlay_hints = { + background = true, + }, + }, + color_overrides = {}, + custom_highlights = {}, + default_integrations = true, + auto_integrations = true, + integrations = { + blink_cmp = true, + gitsigns = true, + lualine = true, + notify = true, + mini = { + enabled = true, + indentscope_color = "", + }, + trouble = true, + which_key = true, + }, + }) + + -- setup must be called before loading + vim.cmd.colorscheme("catppuccin-nvim") + end, +} diff --git a/plugins/lualine.lua b/plugins/lualine.lua index 22a0b91..8b97769 100644 --- a/plugins/lualine.lua +++ b/plugins/lualine.lua @@ -12,6 +12,7 @@ return { end return " " .. table.concat(names, ", ") end + require("lualine").setup({ options = { icons_enabled = true, @@ -45,7 +46,7 @@ return { "filetype", }, lualine_y = { "progress" }, - lualine_z = { "location" }, + lualine_z = { "location", "datetime" }, }, inactive_sections = { lualine_a = {}, diff --git a/plugins/mini.lua b/plugins/mini.lua index 7c88a3a..58fd4a3 100644 --- a/plugins/mini.lua +++ b/plugins/mini.lua @@ -5,5 +5,33 @@ return { require("mini.map").setup() require("mini.tabline").setup() require("mini.icons").setup() + require("mini.git").setup() + require("mini.diff").setup() + -- require("mini.statusline").setup({ + -- use_icons = true, + -- content = { + -- active = function() + -- local mode, mode_hl = MiniStatusline.section_mode({ trunc_width = 120 }) + -- local git = MiniStatusline.section_git({ trunc_width = 40 }) + -- local diff = MiniStatusline.section_diff({ trunc_width = 75 }) + -- local diagnostics = MiniStatusline.section_diagnostics({ trunc_width = 75 }) + -- local lsp = MiniStatusline.section_lsp({ trunc_width = 75 }) + -- local filename = MiniStatusline.section_filename({ trunc_width = 140 }) + -- local fileinfo = MiniStatusline.section_fileinfo({ trunc_width = 120 }) + -- local location = MiniStatusline.section_location({ trunc_width = 75 }) + -- local search = MiniStatusline.section_searchcount({ trunc_width = 75 }) + -- + -- return MiniStatusline.combine_groups({ + -- { hl = mode_hl, strings = { mode } }, + -- { hl = "MiniStatuslineDevinfo", strings = { git, diff, diagnostics, lsp } }, + -- "%<", -- Mark general truncate point + -- { hl = "MiniStatuslineFilename", strings = { filename } }, + -- "%=", -- End left alignment + -- { hl = "MiniStatuslineFileinfo", strings = { fileinfo } }, + -- { hl = mode_hl, strings = { search, location } }, + -- }) + -- end, + -- }, + -- }) end, } diff --git a/plugins/showkeys.lua b/plugins/showkeys.lua new file mode 100644 index 0000000..425a990 --- /dev/null +++ b/plugins/showkeys.lua @@ -0,0 +1,12 @@ +return { + src = "https://github.com/nvzone/showkeys", + config = function() + require("showkeys").setup({ + maxkeys = 5, + winopts = { + border = "double", + title = "Show Keys", + }, + }) + end, +} From c107a7c37d181cf307c190b2fc5a908b777637e9 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Thu, 6 Aug 2026 21:02:45 -0500 Subject: [PATCH 10/12] chore: Update plugins Signed-off-by: Tristan Jahnke --- .gitignore | 4 ---- lua/options.lua | 1 + nvim-pack-lock.json | 14 +++++++++----- plugins/blink.lua | 2 +- plugins/fidget.lua | 6 ++++++ plugins/pr-description.lua | 1 + 6 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 plugins/fidget.lua diff --git a/.gitignore b/.gitignore index e351344..a6b1ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,3 @@ Thumbs.db # Profiling output profile.json - -# Markdown -/*.md -!README.md diff --git a/lua/options.lua b/lua/options.lua index bb4b030..d40d158 100644 --- a/lua/options.lua +++ b/lua/options.lua @@ -29,6 +29,7 @@ vim.opt.foldmethod = "expr" vim.opt.hidden = true -- allow hidden buffers vim.opt.hlsearch = true -- highlight search matches vim.opt.ignorecase = true -- case insensitive search +vim.opt.inccommand = "split" vim.opt.incsearch = true -- show matches as you type vim.opt.iskeyword:append("-") -- include - in words vim.opt.maxmempattern = 20000 -- increase max memory diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 16b4e6c..007a80c 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -19,6 +19,10 @@ "src": "https://github.com/stevearc/conform.nvim", "version": "'v9.1.0'" }, + "fidget.nvim": { + "rev": "6f793b2bcd2d35e201c09520f698bb763220908a", + "src": "https://github.com/j-hui/fidget.nvim" + }, "friendly-snippets": { "rev": "6cd7280adead7f586db6fccbd15d2cac7e2188b9", "src": "https://github.com/rafamadriz/friendly-snippets" @@ -37,7 +41,7 @@ "src": "https://github.com/nvim-lualine/lualine.nvim" }, "mason-lspconfig.nvim": { - "rev": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76", + "rev": "67029ccdac1ef8941e13b826417bc0ffac24cc86", "src": "https://github.com/mason-org/mason-lspconfig.nvim" }, "mason.nvim": { @@ -45,7 +49,7 @@ "src": "https://github.com/mason-org/mason.nvim" }, "mini.nvim": { - "rev": "a995fe9cd4193fb492b5df69175a351a74b3d36b", + "rev": "1345d191bb3da9c7b0e977f4387c5761f9bff68d", "src": "https://github.com/nvim-mini/mini.nvim", "version": "'stable'" }, @@ -54,7 +58,7 @@ "src": "https://github.com/danymat/neogen" }, "nvim": { - "rev": "e068ab5f8261f23f6f71ffd8791ae40315b77b9c", + "rev": "79e2049a0fdf7ec840f8463fe1d962c94493196b", "src": "https://github.com/catppuccin/nvim" }, "nvim-autopairs": { @@ -63,11 +67,11 @@ "version": "'0.10.0'" }, "nvim-lspconfig": { - "rev": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e", + "rev": "43ed3797b266e1ee8d222e491379ad471c9d3146", "src": "https://github.com/neovim/nvim-lspconfig" }, "nvim-treesitter": { - "rev": "4916d6592ede8c07973490d9322f187e07dfefac", + "rev": "3d3321b560a63ff92a8692401f303a5123336b86", "src": "https://github.com/nvim-treesitter/nvim-treesitter", "version": "'main'" }, diff --git a/plugins/blink.lua b/plugins/blink.lua index 552f458..a09fa80 100644 --- a/plugins/blink.lua +++ b/plugins/blink.lua @@ -52,7 +52,7 @@ return { border = "rounded", }, }, - ghost_text = { enabled = true }, + ghost_text = { enabled = true, show_without_selection = true }, menu = { border = "rounded", auto_show = true, diff --git a/plugins/fidget.lua b/plugins/fidget.lua new file mode 100644 index 0000000..1e2b67e --- /dev/null +++ b/plugins/fidget.lua @@ -0,0 +1,6 @@ +return { + src = "https://github.com/j-hui/fidget.nvim", + config = function() + require("fidget").setup() + end, +} diff --git a/plugins/pr-description.lua b/plugins/pr-description.lua index 5738639..004ab38 100644 --- a/plugins/pr-description.lua +++ b/plugins/pr-description.lua @@ -17,6 +17,7 @@ return { require("pr-description").setup({ foldable_file_changes = true, }) + vim.api.nvim_set_keymap( "n", "gd", From 9eff765d32a3a6fb4aee9035bba78c61bf0aa724 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Sat, 19 Sep 2026 18:05:41 -0500 Subject: [PATCH 11/12] feat: add grep file picker Signed-off-by: Tristan Jahnke --- plugins/snacks.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/snacks.lua b/plugins/snacks.lua index 18d71a2..976dbe5 100644 --- a/plugins/snacks.lua +++ b/plugins/snacks.lua @@ -116,6 +116,10 @@ return { Snacks.picker.pick("files") end, { desc = "Snacks file picker" }) + Snacks.keymap.set("n", "fg", function() + Snacks.picker.grep() + end, { desc = "Snacks grep file picker." }) + Snacks.keymap.set("n", "gg", function() Snacks.lazygit() end, { desc = "Lazygit" }) From 577e77e4a866d369d48bd07b2fbac84533bdff24 Mon Sep 17 00:00:00 2001 From: Tristan Jahnke Date: Sat, 19 Sep 2026 18:07:39 -0500 Subject: [PATCH 12/12] WIP Signed-off-by: Tristan Jahnke --- AGENTS.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index e69de29..0000000