diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000000..e90bf150c51 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changelog + +## 2026-07-07 — Full Decoupling Refactor + +### Architecture: Monolith → Modular + +Extracted all plugin configurations from `init.lua` into individual files under `lua/kickstart/plugins/`. init.lua shrank from **949 → 334 lines** and now serves as a spine: options, keymaps, build hooks, and a clean `require` table in Section 10. + +Each plugin is now a self-contained file — to enable or disable, comment or uncomment a single `require` line. + +### New Files Created + +| File | Purpose | +|---|---| +| `lua/kickstart/util.lua` | Shared `gh()` helper for GitHub URL shorthand | +| `lua/kickstart/plugins/guess-indent.lua` | Auto-detect indentation | +| `lua/kickstart/plugins/gitsigns.lua` | Git signs + hunk keymaps (consolidated) | +| `lua/kickstart/plugins/which-key.lua` | Pending keybind display | +| `lua/kickstart/plugins/tokyonight.lua` | Colorscheme (tokyonight-night) | +| `lua/kickstart/plugins/todo-comments.lua` | Highlight TODO/FIXME in comments | +| `lua/kickstart/plugins/mini.lua` | mini.ai + mini.surround + mini.statusline | +| `lua/kickstart/plugins/telescope.lua` | Fuzzy finder + LSP pickers + keymaps | +| `lua/kickstart/plugins/lsp.lua` | LSP servers + Mason + LspAttach keymaps | +| `lua/kickstart/plugins/conform.lua` | Formatting (go, hcl, ps1, lua) + hclfmt | +| `lua/kickstart/plugins/blink.lua` | blink.cmp + LuaSnip autocomplete | +| `lua/kickstart/plugins/treesitter.lua` | Syntax parsing + auto-install | + +### Existing Files Modified + +| File | Change | +|---|---| +| `init.lua` | Sections 4-9 extracted into plugin files; Section 10 rewritten as clean require table | +| `lua/kickstart/plugins/lint.lua` | Expanded from markdown-only to shell/bash/zsh + Go linting | +| `lua/kickstart/plugins/gitsigns.lua` | Consolidated signs config + on_attach keymaps (was duplicated) | +| `README.md` | Rewritten with full stack docs, keymap table, modular architecture guide | + +### Files Removed + +- `lazy-lock.json` — leftover from lazy.nvim era (migrated to vim.pack) +- `lua/kickstart/plugins/neo-tree.lua` — removed (user prefers Telescope for file navigation) +- `lua/custom/plugins/init.lua` — removed in prior cleanup +- `containerfix` branch — deprecated, deleted + +### New Features + +- **Linting enabled**: shellcheck for bash/sh/zsh, golangci-lint for Go +- **Gitsigns keymaps**: hunk navigation (`]c`/`[c`), staging (`hs`), blame (`tb`), word diff (`tw`) +- **System deps documented**: `Makefile` for one-command dependency installation + +### How to Use + +```bash +# Install system dependencies +make install + +# Enable/disable plugins: edit init.lua Section 10 +# Add a plugin: create lua/kickstart/plugins/.lua, add require in Section 10 +``` diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..5f4453c04d9 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# Neovim Config — Dependency Installation +# Run: make install + +.PHONY: install check clean help + +# Core dependencies (required) +CORE_DEPS := neovim gcc make git ripgrep fd tree-sitter-cli unzip xclip + +# Linting (recommended) +LINT_DEPS := shellcheck golangci-lint + +# All deps combined +ALL_DEPS := $(CORE_DEPS) $(LINT_DEPS) + +install: + @echo "==> Installing core dependencies..." + sudo pacman -S --needed --noconfirm $(CORE_DEPS) + @echo "==> Installing linting dependencies..." + sudo pacman -S --needed --noconfirm $(LINT_DEPS) 2>/dev/null || true + @echo "==> Done. Launch nvim to auto-install plugins." + +check: + @echo "==> Checking dependencies..." + @missing=0; \ + for dep in $(ALL_DEPS); do \ + if command -v $$dep >/dev/null 2>&1; then \ + echo " [OK] $$dep"; \ + else \ + echo " [MISSING] $$dep"; \ + missing=1; \ + fi; \ + done; \ + if [ $$missing -eq 0 ]; then echo "==> All dependencies installed."; \ + else echo "==> Run 'make install' to install missing deps."; fi + +clean: + @echo "==> This removes Neovim's local data (plugins, cache). Use with caution." + @echo " Run: rm -rf ~/.local/share/nvim ~/.local/state/nvim ~/.cache/nvim" + +help: + @echo "Targets:" + @echo " make install Install all system dependencies via pacman" + @echo " make check Check which dependencies are installed" + @echo " make clean Instructions for wiping Neovim data" diff --git a/README.md b/README.md index 7c62e907134..05403371eeb 100644 --- a/README.md +++ b/README.md @@ -1,345 +1,72 @@ -# kickstart.nvim +# Neovim Development Environment -## Introduction +A single-file Neovim configuration forked from Kickstart.nvim, tuned for infrastructure and backend development. -A starting point for Neovim that is: +## Philosophy -* Small -* Single-file -* Completely Documented +- **Built for DevOps:** Deep integrations for Go, Terraform/HCL, Bicep, PowerShell, Ansible, Jinja, and Bash. +- **vim.pack native:** Uses Neovim 0.12+'s built-in `vim.pack` plugin manager — no external plugin manager needed. +- **Terminal-native:** Keyboard-driven. No GUI fluff. +- **Modular:** Each plugin lives in its own file under `lua/kickstart/plugins/`. Enable or disable by commenting a single `require` in Section 10 of `init.lua`. -**NOT** a Neovim distribution, but instead a starting point for your configuration. - -## Installation - -### Install Neovim - -Kickstart.nvim targets *only* the latest -['stable'](https://github.com/neovim/neovim/releases/tag/stable) and latest -['nightly'](https://github.com/neovim/neovim/releases/tag/nightly) of Neovim. -If you are experiencing issues, please make sure you have at least the latest -stable version. Most likely, you want to install neovim via a [package -manager](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package). -To check your neovim version, run `nvim --version` and make sure it is not -below the latest -['stable'](https://github.com/neovim/neovim/releases/tag/stable) version. If -your chosen install method only gives you an outdated version of neovim, find -alternative [installation methods below](#alternative-neovim-installation-methods). - -### Install External Dependencies - -External Requirements: -- Basic utils: `git`, `make`, `unzip`, C Compiler (`gcc`) -- [ripgrep](https://github.com/BurntSushi/ripgrep#installation), - [fd-find](https://github.com/sharkdp/fd#installation) -- [tree-sitter CLI](https://github.com/tree-sitter/tree-sitter/blob/master/crates/cli/README.md#installation) -- Clipboard tool (xclip/xsel/win32yank or other depending on the platform) -- A [Nerd Font](https://www.nerdfonts.com/): optional, provides various icons - - if you have it set `vim.g.have_nerd_font` in `init.lua` to true -- Emoji fonts (Ubuntu only, and only if you want emoji!) `sudo apt install fonts-noto-color-emoji` -- Language Setup: - - If you want to write Typescript, you need `npm` - - If you want to write Golang, you will need `go` - - etc. - -> [!NOTE] -> See [Install Recipes](#Install-Recipes) for additional Windows and Linux specific notes -> and quick install snippets - -### Install Kickstart - -> [!NOTE] -> [Backup](#FAQ) your previous configuration (if any exists) - -Neovim's configurations are located under the following paths, depending on your OS: - -| OS | PATH | -| :- | :--- | -| Linux, MacOS | `$XDG_CONFIG_HOME/nvim`, `~/.config/nvim` | -| Windows (cmd)| `%localappdata%\nvim\` | -| Windows (powershell)| `$env:LOCALAPPDATA\nvim\` | - -#### Recommended Step - -[Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) this repo -so that you have your own copy that you can modify, then install by cloning the -fork to your machine using one of the commands below, depending on your OS. - -> [!NOTE] -> Your fork's URL will be something like this: -> `https://github.com//kickstart.nvim.git` - -You likely want to remove `nvim-pack-lock.json` from your fork's `.gitignore` -file too - it's ignored in the kickstart repo to make maintenance easier, but -it's recommended to track it in version control (see `:help vim.pack-lockfile`). - -#### Clone kickstart.nvim - -> [!NOTE] -> If following the recommended step above (i.e., forking the repo), replace -> `nvim-lua` with `` in the commands below - -
Linux and Mac - -```sh -git clone https://github.com/nvim-lua/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim -``` - -
- -
Windows - -If you're using `cmd.exe`: - -``` -git clone https://github.com/nvim-lua/kickstart.nvim.git "%localappdata%\nvim" -``` - -If you're using `powershell.exe` - -``` -git clone https://github.com/nvim-lua/kickstart.nvim.git "${env:LOCALAPPDATA}\nvim" -``` - -
- -### Post Installation - -Start Neovim - -```sh -nvim -``` - -That's it! `vim.pack` will install all the plugins from your config. Use -`:lua vim.pack.update(nil, { offline = true })` to inspect plugin state and -`:lua vim.pack.update()` to fetch updates (`:write` applies updates, `:quit` -cancels them). - -#### Read The Friendly Documentation - -Read through the `init.lua` file in your configuration folder for more -information about extending and exploring Neovim. That also includes -examples of adding popularly requested plugins. - -> [!NOTE] -> For more information about a particular plugin check its repository's documentation. - - -### Getting Started - -[The Only Video You Need to Get Started with Neovim](https://youtu.be/m8C0Cq9Uv9o) - -### FAQ - -* What should I do if I already have a pre-existing Neovim configuration? - * You should back it up and then delete all associated files. - * This includes your existing init.lua and the Neovim files in `~/.local` - which can be deleted with `rm -rf ~/.local/share/nvim/` -* Can I keep my existing configuration in parallel to kickstart? - * Yes! You can use [NVIM_APPNAME](https://neovim.io/doc/user/starting.html#%24NVIM_APPNAME)`=nvim-NAME` - to maintain multiple configurations. For example, you can install the kickstart - configuration in `~/.config/nvim-kickstart` and create an alias: - ``` - alias nvim-kickstart='NVIM_APPNAME="nvim-kickstart" nvim' - ``` - When you run Neovim using `nvim-kickstart` alias it will use the alternative - config directory and the matching local directory - `~/.local/share/nvim-kickstart`. You can apply this approach to any Neovim - distribution that you would like to try out. -* What if I want to "uninstall" this configuration: - * Remove your config directory and local data directory (for example, - `~/.config/nvim` and `~/.local/share/nvim`). -* Why is the kickstart `init.lua` a single file? Wouldn't it make sense to split it into multiple files? - * The main purpose of kickstart is to serve as a teaching tool and a reference - configuration that someone can easily use to `git clone` as a basis for their own. - As you progress in learning Neovim and Lua, you might consider splitting `init.lua` - into smaller parts. A fork of kickstart that does this while maintaining the - same functionality is available here: - * [kickstart-modular.nvim](https://github.com/dam9000/kickstart-modular.nvim) - * Discussions on this topic can be found here: - * [Restructure the configuration](https://github.com/nvim-lua/kickstart.nvim/issues/218) - * [Reorganize init.lua into a multi-file setup](https://github.com/nvim-lua/kickstart.nvim/pull/473) - -### Install Recipes - -Below you can find OS specific install instructions for Neovim and dependencies. - -After installing all the dependencies continue with the [Install Kickstart](#install-kickstart) step. - -#### Windows Installation - -
Windows with Microsoft C++ Build Tools and CMake -Kickstart's default config is make-only for `telescope-fzf-native.nvim`. -If `make` is unavailable, the plugin is skipped. - -Recommended: install `make` (see the chocolatey section below). - -If you want a CMake-only setup, customize `init.lua` in two places: - -1. Include `telescope-fzf-native.nvim` when `cmake` is available: - -```lua -if vim.fn.executable 'make' == 1 or vim.fn.executable 'cmake' == 1 then - table.insert(plugins, gh 'nvim-telescope/telescope-fzf-native.nvim') -end -``` - -2. In the `PackChanged` hook, use CMake when `make` is unavailable: - -```lua -if name == 'telescope-fzf-native.nvim' then - if vim.fn.executable 'make' == 1 then - run_build(name, { 'make' }, ev.data.path) - elseif vim.fn.executable 'cmake' == 1 then - run_build(name, { 'cmake', '-S.', '-Bbuild', '-DCMAKE_BUILD_TYPE=Release' }, ev.data.path) - run_build(name, { 'cmake', '--build', 'build', '--config', 'Release', '--target', 'install' }, ev.data.path) - end - return -end -``` - -See `telescope-fzf-native` documentation for [build details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation). -
-
Windows with gcc/make using chocolatey -Alternatively, one can install gcc and make which don't require changing the config, -the easiest way is to use choco: - -1. install [chocolatey](https://chocolatey.org/install) -either follow the instructions on the page or use winget, -run in cmd as **admin**: -``` -winget install --accept-source-agreements chocolatey.chocolatey -``` - -2. install all requirements using choco, exit the previous cmd and -open a new one so that choco path is set, and run in cmd as **admin**: -``` -choco install -y neovim git ripgrep wget fd unzip gzip mingw make tree-sitter -``` -
-
WSL (Windows Subsystem for Linux) - -``` -wsl --install -wsl -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep fd-find tree-sitter-cli unzip git xclip neovim -``` -
- -#### Linux Install -
Ubuntu Install Steps - -``` -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep fd-find tree-sitter-cli unzip git xclip neovim -``` -
-
Debian Install Steps - -``` -sudo apt update -sudo apt install make gcc ripgrep fd-find tree-sitter-cli unzip git xclip curl - -# Now we install nvim -curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz -sudo rm -rf /opt/nvim-linux-x86_64 -sudo mkdir -p /opt/nvim-linux-x86_64 -sudo chmod a+rX /opt/nvim-linux-x86_64 -sudo tar -C /opt -xzf nvim-linux-x86_64.tar.gz - -# make it available in /usr/local/bin, distro installs to /usr/bin -sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/ -``` -
-
Fedora Install Steps - -``` -sudo dnf install -y gcc make git ripgrep fd-find tree-sitter-cli unzip neovim -``` -
- -
Arch Install Steps - -``` -sudo pacman -S --noconfirm --needed gcc make git ripgrep fd tree-sitter-cli unzip neovim -``` -
- -### Alternative neovim installation methods - -For some systems it is not unexpected that the [package manager installation -method](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package) -recommended by neovim is significantly behind. If that is the case for you, -pick one of the following methods that are known to deliver fresh neovim versions very quickly. -They have been picked for their popularity and because they make installing and updating -neovim to the latest versions easy. You can also find more detail about the -available methods being discussed -[here](https://github.com/nvim-lua/kickstart.nvim/issues/1583). - - -
Bob - -[Bob](https://github.com/MordechaiHadad/bob) is a Neovim version manager for -all platforms. Simply install -[rustup](https://rust-lang.github.io/rustup/installation/other.html), -and run the following commands: +## Prerequisites +Arch Linux: ```bash -rustup default stable -rustup update stable -cargo install bob-nvim -bob use stable +sudo pacman -S --needed neovim gcc make git ripgrep fd tree-sitter-cli unzip xclip ``` -
- -
Homebrew - -[Homebrew](https://brew.sh) is a package manager popular on Mac and Linux. -Simply install using [`brew install`](https://formulae.brew.sh/formula/neovim). - -
- -
Flatpak - -Flatpak is a package manager for applications that allows developers to package their applications -just once to make it available on all Linux systems. Simply [install flatpak](https://flatpak.org/setup/) -and setup [flathub](https://flathub.org/setup) to [install neovim](https://flathub.org/apps/io.neovim.nvim). - -
- -
asdf and mise-en-place - -[asdf](https://asdf-vm.com/) and [mise](https://mise.jdx.dev/) are tool version managers, -mostly aimed towards project-specific tool versioning. However both support managing tools -globally in the user-space as well: - -
mise - -[Install mise](https://mise.jdx.dev/getting-started.html), then run: - +Optional but recommended: ```bash -mise plugins install neovim -mise use neovim@stable +sudo pacman -S --needed shellcheck golangci-lint # for linting ``` -
- -
asdf - -[Install asdf](https://asdf-vm.com/guide/getting-started.html), then run: +## Installation ```bash -asdf plugin add neovim -asdf install neovim stable -asdf set neovim stable --home -asdf reshim neovim -``` - -
- -
+# Backup existing config +mv ~/.config/nvim ~/.config/nvim.bak +rm -rf ~/.local/share/nvim + +# Clone and bootstrap +git clone https://github.com//nvim.git ~/.config/nvim +nvim # Plugins auto-install on first run +``` + +## Core Stack + +| Category | Tooling | +|---|---| +| **LSP** | gopls, terraformls, ansiblels, jinja_lsp, powershell_es, pyright, bicep-lsp, lua_ls | +| **Autocomplete** | blink.cmp + LuaSnip | +| **Fuzzy Finder** | Telescope.nvim (ripgrep + fd + fzf-native) | +| **Parsing** | Treesitter (auto-installs parsers on demand) | +| **Formatting** | conform.nvim — autoformat on save for go, hcl, ps1, lua; external hclfmt for HCL | +| **Linting** | nvim-lint — shellcheck (bash/sh/zsh), golangci-lint (Go), markdownlint (markdown) | +| **Git** | gitsigns.nvim — hunk staging, blame, diff, text objects | +| **File Tree** | neo-tree.nvim — toggle with `ff` | +| **Debug** | nvim-dap + dap-ui + dap-go (commented out by default) | + +## Custom Keymaps + +| Key | Action | +|---|---| +| `` | Save file (insert + normal mode) | +| `` / `` | Scroll up/down | +| `` | Navigate splits | +| `ff` | Toggle neo-tree file explorer | +| `fb` | Toggle neo-tree buffer explorer | +| `sf` | Telescope find files | +| `sg` | Telescope live grep | +| `f` | Format buffer | +| `hs` | Stage git hunk | +| `hr` | Reset git hunk | +| `tb` | Toggle git blame | + +## Management + +- **Check plugin status:** `:lua vim.pack.update(nil, { offline = true })` +- **Update plugins:** `:lua vim.pack.update()` (`:write` to apply, `:quit` to cancel) +- **Health check:** `:checkhealth kickstart` +- **Add a plugin:** Create `lua/kickstart/plugins/.lua`, add `require 'kickstart.plugins.'` in init.lua Section 10 +- **Disable a plugin:** Comment its `require` in init.lua Section 10 diff --git a/init.lua b/init.lua index aff5250e921..caffe8683f8 100644 --- a/init.lua +++ b/init.lua @@ -1,89 +1,3 @@ ---[[ - -===================================================================== -==================== READ THIS BEFORE CONTINUING ==================== -===================================================================== -======== .-----. ======== -======== .----------------------. | === | ======== -======== |.-""""""""""""""""""-.| |-----| ======== -======== || || | === | ======== -======== || KICKSTART.NVIM || |-----| ======== -======== || || | === | ======== -======== || || |-----| ======== -======== ||:Tutor || |:::::| ======== -======== |'-..................-'| |____o| ======== -======== `"")----------------(""` ___________ ======== -======== /::::::::::| |::::::::::\ \ no mouse \ ======== -======== /:::========| |==hjkl==:::\ \ required \ ======== -======== '""""""""""""' '""""""""""""' '""""""""""' ======== -======== ======== -===================================================================== -===================================================================== - -What is Kickstart? - - Kickstart.nvim is *not* a distribution. - - Kickstart.nvim is a starting point for your own configuration. - The goal is that you can read every line of code, top-to-bottom, understand - what your configuration is doing, and modify it to suit your needs. - - Once you've done that, you can start exploring, configuring and tinkering to - make Neovim your own! That might mean leaving Kickstart just the way it is for a while - or immediately breaking it into modular pieces. It's up to you! - - If you don't know anything about Lua, I recommend taking some time to read through - a guide. One possible example which will only take 10-15 minutes: - - https://learnxinyminutes.com/docs/lua/ - - After understanding a bit more about Lua, you can use `:help lua-guide` as a - reference for how Neovim integrates Lua. - - :help lua-guide - - (or HTML version): https://neovim.io/doc/user/lua-guide.html - -Kickstart Guide: - - TODO: The very first thing you should do is to run the command `:Tutor` in Neovim. - - If you don't know what this means, type the following: - - - - : - - Tutor - - - - (If you already know the Neovim basics, you can skip this step.) - - Once you've completed that, you can continue working through **AND READING** the rest - of the kickstart init.lua. - - Next, run AND READ `:help`. - This will open up a help window with some basic information - about reading, navigating and searching the builtin help documentation. - - This should be the first place you go to look when you're stuck or confused - with something. It's one of my favorite Neovim features. - - MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, - which is very useful when you're not exactly sure of what you're looking for. - - I have left several `:help X` comments throughout the init.lua - These are hints about where to find more information about the relevant settings, - plugins or Neovim features used in Kickstart. - - NOTE: Look for lines like this - - Throughout the file. These are for you, the reader, to help you understand what is happening. - Feel free to delete them once you know what you're doing, but they should serve as a guide - for when you are first encountering a few different constructs in your Neovim config. - -If you experience any errors while trying to install kickstart, run `:checkhealth` for more info. - -I hope you enjoy your Neovim journey, -- TJ - -P.S. You can delete this when you're done too. It's your config now! :) ---]] - -- ============================================================ -- SECTION 1: OPTIONS -- Core Neovim settings, leaders, options, basic keymaps, basic autocmds @@ -327,657 +241,94 @@ local function gh(repo) return 'https://github.com/' .. repo end -- ============================================================ -- SECTION 4: UI / CORE UX PLUGINS --- guess-indent, gitsigns, which-key, colorscheme, todo-comments, mini modules +-- Extracted to lua/kickstart/plugins/{guess-indent,gitsigns,which-key,tokyonight,todo-comments,mini}.lua -- ============================================================ -do - -- [[ Installing and Configuring Plugins ]] - -- - -- To install a plugin simply call `vim.pack.add` with its git url. - -- This will download the default branch of the plugin, which will usually be `main` or `master` - -- You can also have more advanced specs, which we will talk about later. - -- - -- For most plugins its not enough to install them, you also need to call their `.setup()` to start them. - -- - -- For example, lets say we want to install `guess-indent.nvim` - a plugin for - -- automatically detecting and setting the indentation. - -- - -- We first install it from https://github.com/NMAC427/guess-indent.nvim - -- and then call its `setup()` function to start it with default settings. - vim.pack.add { gh 'NMAC427/guess-indent.nvim' } - require('guess-indent').setup {} - - -- Here is a more advanced configuration example that passes options to `gitsigns.nvim` - -- - -- See `:help gitsigns` to understand what each configuration key does. - -- Adds git related signs to the gutter, as well as utilities for managing changes - vim.pack.add { gh 'lewis6991/gitsigns.nvim' } - require('gitsigns').setup { - signs = { - add = { text = '+' }, ---@diagnostic disable-line: missing-fields - change = { text = '~' }, ---@diagnostic disable-line: missing-fields - delete = { text = '_' }, ---@diagnostic disable-line: missing-fields - topdelete = { text = '‾' }, ---@diagnostic disable-line: missing-fields - changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields - }, - } - - -- Useful plugin to show you pending keybinds. - vim.pack.add { gh 'folke/which-key.nvim' } - require('which-key').setup { - -- Delay between pressing a key and opening which-key (milliseconds) - delay = 0, - icons = { mappings = vim.g.have_nerd_font }, - -- Document existing key chains - spec = { - { 's', group = '[S]earch', mode = { 'n', 'v' } }, - { 't', group = '[T]oggle' }, - { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first - { 'gr', group = 'LSP Actions', mode = { 'n' } }, - }, - } - - -- [[ Colorscheme ]] - -- You can easily change to a different colorscheme. - -- Change the name of the colorscheme plugin below, and then - -- change the command under that to load whatever the name of that colorscheme is. - -- - -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`. - vim.pack.add { gh 'folke/tokyonight.nvim' } - ---@diagnostic disable-next-line: missing-fields - require('tokyonight').setup { - styles = { - comments = { italic = false }, -- Disable italics in comments - }, - } - - -- Load the colorscheme here. - -- Like many other themes, this one has different styles, and you could load - -- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'. - vim.cmd.colorscheme 'tokyonight-night' - - -- Highlight todo, notes, etc in comments - vim.pack.add { gh 'folke/todo-comments.nvim' } - require('todo-comments').setup { signs = false } - - -- [[ mini.nvim ]] - -- A collection of various small independent plugins/modules - vim.pack.add { gh 'nvim-mini/mini.nvim' } - - -- If a nerd font is available, load the icons module for pretty icons in various plugins. - if vim.g.have_nerd_font then - require('mini.icons').setup() - -- Used for backwards compatibility with plugins that require `nvim-web-devicons` (e.g. telescope.nvim) - MiniIcons.mock_nvim_web_devicons() - end - - -- Better Around/Inside textobjects - -- - -- Examples: - -- - va) - [V]isually select [A]round [)]paren - -- - yiiq - [Y]ank [I]nside [I]+1 [Q]uote - -- - ci' - [C]hange [I]nside [']quote - require('mini.ai').setup { - -- NOTE: Avoid conflicts with the built-in incremental selection mappings on Neovim>=0.12 (see `:help treesitter-incremental-selection`) - mappings = { - around_next = 'aa', - inside_next = 'ii', - }, - n_lines = 500, - } - - -- Add/delete/replace surroundings (brackets, quotes, etc.) - -- - -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren - -- - sd' - [S]urround [D]elete [']quotes - -- - sr)' - [S]urround [R]eplace [)] ['] - require('mini.surround').setup() - - -- Simple and easy statusline. - -- You could remove this setup call if you don't like it, - -- and try some other statusline plugin - local statusline = require 'mini.statusline' - -- Set `use_icons` to true if you have a Nerd Font - statusline.setup { use_icons = vim.g.have_nerd_font } - - -- You can configure sections in the statusline by overriding their - -- default behavior. For example, here we set the section for - -- cursor location to LINE:COLUMN - ---@diagnostic disable-next-line: duplicate-set-field - statusline.section_location = function() return '%2l:%-2v' end - - -- ... and there is more! - -- Check out: https://github.com/nvim-mini/mini.nvim -end -- ============================================================ -- SECTION 5: SEARCH & NAVIGATION --- Telescope setup, keymaps, LSP picker mappings +-- Extracted to lua/kickstart/plugins/telescope.lua -- ============================================================ -do - -- [[ Fuzzy Finder (files, lsp, etc) ]] - -- - -- Telescope is a fuzzy finder that comes with a lot of different things that - -- it can fuzzy find! It's more than just a "file finder", it can search - -- many different aspects of Neovim, your workspace, LSP, and more! - -- - -- There are lots of other alternative pickers (like snacks.picker, or fzf-lua) - -- so feel free to experiment and see what you like! - -- - -- The easiest way to use Telescope, is to start by doing something like: - -- :Telescope help_tags - -- - -- After running this command, a window will open up and you're able to - -- type in the prompt window. You'll see a list of `help_tags` options and - -- a corresponding preview of the help. - -- - -- Two important keymaps to use while in Telescope are: - -- - Insert mode: - -- - Normal mode: ? - -- - -- This opens a window that shows you all of the keymaps for the current - -- Telescope picker. This is really useful to discover what Telescope can - -- do as well as how to actually do it! - - ---@type (string|vim.pack.Spec)[] - local telescope_plugins = { - gh 'nvim-lua/plenary.nvim', - gh 'nvim-telescope/telescope.nvim', - gh 'nvim-telescope/telescope-ui-select.nvim', - } - if vim.fn.executable 'make' == 1 then table.insert(telescope_plugins, gh 'nvim-telescope/telescope-fzf-native.nvim') end - - -- NOTE: You can install multiple plugins at once - vim.pack.add(telescope_plugins) - - -- See `:help telescope` and `:help telescope.setup()` - require('telescope').setup { - -- You can put your default mappings / updates / etc. in here - -- All the info you're looking for is in `:help telescope.setup()` - -- - -- defaults = { - -- mappings = { - -- i = { [''] = 'to_fuzzy_refine' }, - -- }, - -- }, - -- pickers = {} - extensions = { - ['ui-select'] = { require('telescope.themes').get_dropdown() }, - }, - } - -- Enable Telescope extensions if they are installed - pcall(require('telescope').load_extension, 'fzf') - pcall(require('telescope').load_extension, 'ui-select') - - -- See `:help telescope.builtin` - local builtin = require 'telescope.builtin' - vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) - vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) - vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) - vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) - vim.keymap.set({ 'n', 'v' }, 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) - vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) - vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) - vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) - vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) - vim.keymap.set('n', 'sc', builtin.commands, { desc = '[S]earch [C]ommands' }) - vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) - - -- Add Telescope-based LSP pickers when an LSP attaches to a buffer. - -- If you later switch picker plugins, this is where to update these mappings. - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }), - callback = function(event) - local buf = event.buf - - -- Find references for the word under your cursor. - vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' }) - - -- Jump to the implementation of the word under your cursor. - -- Useful when your language has ways of declaring types without an actual implementation. - vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' }) - - -- Jump to the definition of the word under your cursor. - -- This is where a variable was first declared, or where a function is defined, etc. - -- To jump back, press . - vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' }) - - -- Fuzzy find all the symbols in your current document. - -- Symbols are things like variables, functions, types, etc. - vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' }) - - -- Fuzzy find all the symbols in your current workspace. - -- Similar to document symbols, except searches over your entire project. - vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' }) - - -- Jump to the type of the word under your cursor. - -- Useful when you're not sure what type a variable is and you want to see - -- the definition of its *type*, not where it was *defined*. - vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' }) - end, - }) - - -- Override default behavior and theme when searching - vim.keymap.set('n', '/', function() - -- You can pass additional configuration to Telescope to change the theme, layout, etc. - builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { - winblend = 10, - previewer = false, - }) - end, { desc = '[/] Fuzzily search in current buffer' }) - - -- It's also possible to pass additional configuration options. - -- See `:help telescope.builtin.live_grep()` for information about particular keys - vim.keymap.set( - 'n', - 's/', - function() - builtin.live_grep { - grep_open_files = true, - prompt_title = 'Live Grep in Open Files', - } - end, - { desc = '[S]earch [/] in Open Files' } - ) - - -- Shortcut for searching your Neovim configuration files - vim.keymap.set('n', 'sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config', follow = true } end, { desc = '[S]earch [N]eovim files' }) -end - --- ============================================================ --- SECTION 6: LSP --- LSP keymaps, server configuration, Mason tools installations -- ============================================================ -do - -- [[ LSP Configuration ]] - -- Brief aside: **What is LSP?** - -- - -- LSP is an initialism you've probably heard, but might not understand what it is. - -- - -- LSP stands for Language Server Protocol. It's a protocol that helps editors - -- and language tooling communicate in a standardized fashion. - -- - -- In general, you have a "server" which is some tool built to understand a particular - -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers - -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone - -- processes that communicate with some "client" - in this case, Neovim! - -- - -- LSP provides Neovim with features like: - -- - Go to definition - -- - Find references - -- - Autocompletion - -- - Symbol Search - -- - and more! - -- - -- Thus, Language Servers are external tools that must be installed separately from - -- Neovim. This is where `mason` and related plugins come into play. - -- - -- If you're wondering about lsp vs treesitter, you can check out the wonderfully - -- and elegantly composed help section, `:help lsp-vs-treesitter` - - -- Useful status updates for LSP. - vim.pack.add { gh 'j-hui/fidget.nvim' } - require('fidget').setup {} - - -- This function gets run when an LSP attaches to a particular buffer. - -- That is to say, every time a new file is opened that is associated with - -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this - -- function will be executed to configure the current buffer - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), - callback = function(event) - -- NOTE: Remember that Lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local map = function(keys, func, desc, mode) - mode = mode or 'n' - vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) - end - - -- Rename the variable under your cursor. - -- Most Language Servers support renaming across files, etc. - map('grn', vim.lsp.buf.rename, '[R]e[n]ame') - - -- Execute a code action, usually your cursor needs to be on top of an error - -- or a suggestion from your LSP for this to activate. - map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) - - -- WARN: This is not Goto Definition, this is Goto Declaration. - -- For example, in C this would take you to the header. - map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - - -- The following two autocommands are used to highlight references of the - -- word under your cursor when your cursor rests there for a little while. - -- See `:help CursorHold` for information about when this is executed - -- - -- When you move your cursor, the highlights will be cleared (the second autocommand). - local client = vim.lsp.get_client_by_id(event.data.client_id) - if client and client:supports_method('textDocument/documentHighlight', event.buf) then - local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) - vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { - buffer = event.buf, - group = highlight_augroup, - callback = vim.lsp.buf.document_highlight, - }) - - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - buffer = event.buf, - group = highlight_augroup, - callback = vim.lsp.buf.clear_references, - }) - - vim.api.nvim_create_autocmd('LspDetach', { - group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), - callback = function(event2) - vim.lsp.buf.clear_references() - vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } - end, - }) - end - - -- The following code creates a keymap to toggle inlay hints in your - -- code, if the language server you are using supports them - -- - -- This may be unwanted, since they displace some of your code - if client and client:supports_method('textDocument/inlayHint', event.buf) then - map('th', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) end, '[T]oggle Inlay [H]ints') - end - end, - }) - - -- Enable the following language servers - -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. - -- See `:help lsp-config` for information about keys and how to configure - ---@type table - local servers = { - -- clangd = {}, - -- gopls = {}, - -- pyright = {}, - -- rust_analyzer = {}, - -- - -- Some languages (like typescript) have entire language plugins that can be useful: - -- https://github.com/pmizio/typescript-tools.nvim - -- - -- But for many setups, the LSP (`ts_ls`) will work just fine - -- ts_ls = {}, - - stylua = {}, -- Used to format Lua code - - -- Special Lua Config, as recommended by neovim help docs - lua_ls = { - on_init = function(client) - client.server_capabilities.documentFormattingProvider = false -- Disable formatting (formatting is done by stylua) - - if client.workspace_folders then - local path = client.workspace_folders[1].name - if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end - end - - client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { - runtime = { - version = 'LuaJIT', - path = { 'lua/?.lua', 'lua/?/init.lua' }, - }, - workspace = { - checkThirdParty = false, - -- NOTE: this is a lot slower and will cause issues when working on your own configuration. - -- See https://github.com/neovim/nvim-lspconfig/issues/3189 - library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { - '${3rd}/luv/library', - '${3rd}/busted/library', - }), - }, - }) - end, - ---@type lspconfig.settings.lua_ls - settings = { - Lua = { - format = { enable = false }, -- Disable formatting (formatting is done by stylua) - }, - }, - }, - } - - vim.pack.add { - gh 'neovim/nvim-lspconfig', - gh 'mason-org/mason.nvim', - gh 'mason-org/mason-lspconfig.nvim', - gh 'WhoIsSethDaniel/mason-tool-installer.nvim', - } - - -- Automatically install LSPs and related tools to stdpath for Neovim - require('mason').setup {} - - -- Ensure the servers and tools above are installed - -- - -- To check the current status of installed tools and/or manually install - -- other tools, you can run - -- :Mason - -- - -- You can press `g?` for help in this menu. - local ensure_installed = vim.tbl_keys(servers or {}) - vim.list_extend(ensure_installed, { - -- You can add other tools here that you want Mason to install - }) - - require('mason-tool-installer').setup { ensure_installed = ensure_installed } - - for name, server in pairs(servers) do - vim.lsp.config(name, server) - vim.lsp.enable(name) - end -end - -- ============================================================ --- SECTION 7: FORMATTING --- conform.nvim setup and keymap +-- SECTIONS 6-9: LSP, FORMATTING, COMPLETION, TREESITTER +-- Extracted to lua/kickstart/plugins/{lsp,conform,blink,treesitter}.lua -- ============================================================ -do - -- [[ Formatting ]] - vim.pack.add { gh 'stevearc/conform.nvim' } - require('conform').setup { - notify_on_error = false, - format_on_save = function(bufnr) - -- You can specify filetypes to autoformat on save here: - local enabled_filetypes = { - -- lua = true, - -- python = true, - } - if enabled_filetypes[vim.bo[bufnr].filetype] then - return { timeout_ms = 500 } - else - return nil - end - end, - default_format_opts = { - lsp_format = 'fallback', -- Use external formatters if configured below, otherwise use LSP formatting. Set to `false` to disable LSP formatting entirely. - }, - -- You can also specify external formatters in here. - formatters_by_ft = { - -- rust = { 'rustfmt' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use 'stop_after_first' to run the first available formatter from the list - -- javascript = { "prettierd", "prettier", stop_after_first = true }, - }, - } - - vim.keymap.set({ 'n', 'v' }, 'f', function() require('conform').format { async = true } end, { desc = '[F]ormat buffer' }) -end -- ============================================================ --- SECTION 8: AUTOCOMPLETE & SNIPPETS --- blink.cmp and luasnip setup +-- SECTION 10: PLUGIN REQUIRES +-- Each plugin lives in lua/kickstart/plugins/.lua +-- Comment/uncomment to enable/disable -- ============================================================ do - -- [[ Snippet Engine ]] - - -- NOTE: You can also specify plugin using a version range for its git tag. - -- See `:help vim.version.range()` for more info - vim.pack.add { { src = gh 'L3MON4D3/LuaSnip', version = vim.version.range '2.*' } } - require('luasnip').setup {} - - -- `friendly-snippets` contains a variety of premade snippets. - -- See the README about individual language/framework/plugin snippets: - -- https://github.com/rafamadriz/friendly-snippets - -- - -- vim.pack.add { gh 'rafamadriz/friendly-snippets' } - -- require('luasnip.loaders.from_vscode').lazy_load() - - -- [[ Autocomplete Engine ]] - vim.pack.add { { src = gh 'saghen/blink.cmp', version = vim.version.range '1.*' } } - require('blink.cmp').setup { - keymap = { - -- 'default' (recommended) for mappings similar to built-in completions - -- to accept ([y]es) the completion. - -- This will auto-import if your LSP supports it. - -- This will expand snippets if the LSP sent a snippet. - -- 'super-tab' for tab to accept - -- 'enter' for enter to accept - -- 'none' for no mappings - -- - -- For an understanding of why the 'default' preset is recommended, - -- you will need to read `:help ins-completion` - -- - -- No, but seriously. Please read `:help ins-completion`, it is really good! - -- - -- All presets have the following mappings: - -- /: move to right/left of your snippet expansion - -- : Open menu or open docs if already open - -- / or /: Select next/previous item - -- : Hide menu - -- : Toggle signature help - -- - -- See `:help blink-cmp-config-keymap` for defining your own keymap - preset = 'default', - - -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: - -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps - }, - - appearance = { - -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' - -- Adjusts spacing to ensure icons are aligned - nerd_font_variant = 'mono', - }, - - completion = { - -- By default, you may press `` to show the documentation. - -- Optionally, set `auto_show = true` to show the documentation after a delay. - documentation = { auto_show = false, auto_show_delay_ms = 500 }, - }, + -- UI & Core + require 'kickstart.plugins.guess-indent' + require 'kickstart.plugins.gitsigns' + require 'kickstart.plugins.which-key' + require 'kickstart.plugins.tokyonight' + require 'kickstart.plugins.todo-comments' + require 'kickstart.plugins.mini' - sources = { - default = { 'lsp', 'path', 'snippets' }, - }, + -- Search & Navigation + require 'kickstart.plugins.telescope' - snippets = { preset = 'luasnip' }, + -- LSP + require 'kickstart.plugins.lsp' - -- Blink.cmp includes an optional, recommended rust fuzzy matcher, - -- which automatically downloads a prebuilt binary when enabled. - -- - -- By default, we use the Lua implementation instead, but you may enable - -- the rust implementation via `'prefer_rust_with_warning'` - -- - -- See `:help blink-cmp-config-fuzzy` for more information - fuzzy = { implementation = 'lua' }, + -- Formatting + require 'kickstart.plugins.conform' - -- Shows a signature help window while you type arguments for a function - signature = { enabled = true }, - } -end + -- Autocomplete & Snippets + require 'kickstart.plugins.blink' --- ============================================================ --- SECTION 9: TREESITTER --- Parser installation, syntax highlighting, folds, indentation --- ============================================================ -do - -- [[ Configure Treesitter ]] - -- Used to highlight, edit, and navigate code - -- - -- See `:help nvim-treesitter-intro` - - -- NOTE: You can also specify a branch or a specific commit - vim.pack.add { { src = gh 'nvim-treesitter/nvim-treesitter', version = 'main' } } - - -- Ensure basic parsers are installed - local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } - require('nvim-treesitter').install(parsers) - - ---@param buf integer - ---@param language string - local function treesitter_try_attach(buf, language) - -- Check if a parser exists and load it - if not vim.treesitter.language.add(language) then return end - -- Enable syntax highlighting and other treesitter features - vim.treesitter.start(buf, language) - - -- Enable treesitter based folds - -- For more info on folds see `:help folds` - -- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' - -- vim.wo.foldmethod = 'expr' - - -- Check if treesitter indentation is available for this language, and if so enable it - -- in case there is no indent query, the indentexpr will fallback to the vim's built in one - local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil - - -- Enable treesitter based indentation - if has_indent_query then vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" end - end + -- Treesitter + require 'kickstart.plugins.treesitter' - local available_parsers = require('nvim-treesitter').get_available() - vim.api.nvim_create_autocmd('FileType', { - callback = function(args) - local buf, filetype = args.buf, args.match - - local language = vim.treesitter.language.get_lang(filetype) - if not language then return end - - local installed_parsers = require('nvim-treesitter').get_installed 'parsers' - - if vim.tbl_contains(installed_parsers, language) then - -- Enable the parser if it is already installed - treesitter_try_attach(buf, language) - elseif vim.tbl_contains(available_parsers, language) then - -- If a parser is available in `nvim-treesitter`, auto-install it and enable it after the installation is done - require('nvim-treesitter').install(language):await(function() treesitter_try_attach(buf, language) end) - else - -- Try to enable treesitter features in case the parser exists but is not available from `nvim-treesitter` - treesitter_try_attach(buf, language) - end - end, - }) -end - --- ============================================================ --- SECTION 10: OPTIONAL EXAMPLES / NEXT STEPS --- kickstart.plugins.* examples --- ============================================================ -do - -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the - -- init.lua. If you want these files, they are in the repository, so you can just download them and - -- place them in the correct locations. - - -- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart - -- - -- Here are some example plugins that I've included in the Kickstart repository. - -- Uncomment any of the lines below to enable them (you will need to restart nvim). - -- + -- Optional plugins (uncomment to enable) + -- require 'kickstart.plugins.neo-tree' + require 'kickstart.plugins.lint' -- require 'kickstart.plugins.debug' - -- require 'kickstart.plugins.indent_line' - -- require 'kickstart.plugins.lint' -- require 'kickstart.plugins.autopairs' - -- require 'kickstart.plugins.neo-tree' - -- require 'kickstart.plugins.gitsigns' -- adds gitsigns recommended keymaps - - -- NOTE: You can add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` - -- - -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- require 'custom.plugins' + -- require 'kickstart.plugins.indent_line' end -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et + +-- [[ Custom Keymaps ]] +-- Page up/down scrolling +vim.keymap.set( + 'n', + '', + function() vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('', true, true, true), 'n', true) end, + { desc = 'Page Up' } +) + +vim.keymap.set( + 'n', + '', + function() vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('', true, true, true), 'n', true) end, + { desc = 'Page Down' } +) + +-- Save current file with Ctrl+S in insert and normal mode +vim.api.nvim_set_keymap('i', '', ':wa', { noremap = true, silent = true }) +vim.api.nvim_set_keymap('n', '', ':w', { noremap = true, silent = true }) + +-- Custom highlight groups for better syntax highlighting +vim.api.nvim_set_hl(0, '@function', { fg = '#EBCB8B', bold = true }) +vim.api.nvim_set_hl(0, '@function.builtin', { fg = '#EBCB8B' }) +vim.api.nvim_set_hl(0, '@method', { fg = '#EBCB8B' }) +vim.api.nvim_set_hl(0, '@type', { fg = '#82AAFF', italic = true }) + +-- Enable bicep LSP with specific configuration +vim.filetype.add { extension = { bicep = 'bicep', bicepparam = 'bicepparam' } } + +pcall(vim.treesitter.language.register, 'bicep', 'bicepparam') + +vim.lsp.config('bicep', { + cmd = { vim.fn.expand '~/.local/share/nvim/mason/bin/bicep-lsp' }, + filetypes = { 'bicep', 'bicep-params' }, + root_markers = { '.git', 'bicepconfig.json' }, + workspace_required = false, +}) diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua deleted file mode 100644 index 01e91722fb0..00000000000 --- a/lua/custom/plugins/init.lua +++ /dev/null @@ -1,13 +0,0 @@ --- You can add your own plugins here or in other files in this directory! --- I promise not to create any merge conflicts in this directory :) --- --- See the kickstart.nvim README for more information - --- Iterate over all Lua files in the plugins directory and load them -local plugins_dir = vim.fs.joinpath(vim.fn.stdpath 'config', 'lua', 'custom', 'plugins') -for file_name, type in vim.fs.dir(plugins_dir, { follow = true }) do - if (type == 'file' or type == 'link') and file_name:match '%.lua$' and file_name ~= 'init.lua' then - local module = file_name:gsub('%.lua$', '') - require('custom.plugins.' .. module) - end -end diff --git a/lua/kickstart/plugins/blink.lua b/lua/kickstart/plugins/blink.lua new file mode 100644 index 00000000000..ad793b83787 --- /dev/null +++ b/lua/kickstart/plugins/blink.lua @@ -0,0 +1,21 @@ +local gh = require('kickstart.util').gh + +-- Snippet engine +vim.pack.add { { src = gh 'L3MON4D3/LuaSnip', version = vim.version.range '2.*' } } +require('luasnip').setup {} + +-- Autocomplete engine +vim.pack.add { { src = gh 'saghen/blink.cmp', version = vim.version.range '1.*' } } +require('blink.cmp').setup { + keymap = { preset = 'default' }, + appearance = { nerd_font_variant = 'mono' }, + completion = { + documentation = { auto_show = false, auto_show_delay_ms = 500 }, + }, + sources = { + default = { 'lsp', 'path', 'snippets' }, + }, + snippets = { preset = 'luasnip' }, + fuzzy = { implementation = 'lua' }, + signature = { enabled = true }, +} diff --git a/lua/kickstart/plugins/conform.lua b/lua/kickstart/plugins/conform.lua new file mode 100644 index 00000000000..79981c4a9cf --- /dev/null +++ b/lua/kickstart/plugins/conform.lua @@ -0,0 +1,34 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'stevearc/conform.nvim' } +require('conform').setup { + notify_on_error = true, + format_on_save = function(bufnr) + local enabled_filetypes = { + go = true, + hcl = true, + ps1 = true, + lua = true, + } + if enabled_filetypes[vim.bo[bufnr].filetype] then + return { timeout_ms = 500 } + else + return nil + end + end, + default_format_opts = { + lsp_format = 'fallback', + }, + formatters_by_ft = { + hcl = { 'hclfmt' }, + }, + formatters = { + hclfmt = { + command = 'hclfmt', + }, + }, +} + +vim.keymap.set({ 'n', 'v' }, 'f', function() + require('conform').format { async = true } +end, { desc = '[F]ormat buffer' }) diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/kickstart/plugins/gitsigns.lua index b7e40a87cfc..aac8e88de09 100644 --- a/lua/kickstart/plugins/gitsigns.lua +++ b/lua/kickstart/plugins/gitsigns.lua @@ -1,12 +1,19 @@ --- Adds git related signs to the gutter, as well as utilities for managing changes --- NOTE: gitsigns is already included in init.lua but contains only the base --- config. This will add also the recommended keymaps. +-- gitsigns: git signs in the gutter + hunk navigation/actions +local gh = require('kickstart.util').gh -vim.pack.add { 'https://github.com/lewis6991/gitsigns.nvim' } +vim.pack.add { gh 'lewis6991/gitsigns.nvim' } require('gitsigns').setup { + signs = { + add = { text = '+' }, + change = { text = '~' }, + delete = { text = '_' }, + topdelete = { text = '‾' }, + changedelete = { text = '~' }, + }, on_attach = function(bufnr) - local gitsigns = require 'gitsigns' + local gs = package.loaded.gitsigns + if not gs then return end local function map(mode, l, r, opts) opts = opts or {} @@ -16,42 +23,32 @@ require('gitsigns').setup { -- Navigation map('n', ']c', function() - if vim.wo.diff then - vim.cmd.normal { ']c', bang = true } - else - gitsigns.nav_hunk 'next' - end + if vim.wo.diff then vim.cmd.normal { ']c', bang = true } else gs.nav_hunk 'next' end end, { desc = 'Jump to next git [c]hange' }) - map('n', '[c', function() - if vim.wo.diff then - vim.cmd.normal { '[c', bang = true } - else - gitsigns.nav_hunk 'prev' - end + if vim.wo.diff then vim.cmd.normal { '[c', bang = true } else gs.nav_hunk 'prev' end end, { desc = 'Jump to previous git [c]hange' }) -- Actions - -- visual mode - map('v', 'hs', function() gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [s]tage hunk' }) - map('v', 'hr', function() gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [r]eset hunk' }) - -- normal mode - map('n', 'hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' }) - map('n', 'hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' }) - map('n', 'hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' }) - map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) - map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) - map('n', 'hi', gitsigns.preview_hunk_inline, { desc = 'git preview hunk [i]nline' }) - map('n', 'hb', function() gitsigns.blame_line { full = true } end, { desc = 'git [b]lame line' }) - map('n', 'hd', gitsigns.diffthis, { desc = 'git [d]iff against index' }) - map('n', 'hD', function() gitsigns.diffthis '@' end, { desc = 'git [D]iff against last commit' }) - map('n', 'hQ', function() gitsigns.setqflist 'all' end, { desc = 'git hunk [Q]uickfix list (all files in repo)' }) - map('n', 'hq', gitsigns.setqflist, { desc = 'git hunk [q]uickfix list (all changes in this file)' }) + map('v', 'hs', function() gs.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [s]tage hunk' }) + map('v', 'hr', function() gs.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'git [r]eset hunk' }) + map('n', 'hs', gs.stage_hunk, { desc = 'git [s]tage hunk' }) + map('n', 'hr', gs.reset_hunk, { desc = 'git [r]eset hunk' }) + map('n', 'hS', gs.stage_buffer, { desc = 'git [S]tage buffer' }) + map('n', 'hR', gs.reset_buffer, { desc = 'git [R]eset buffer' }) + map('n', 'hp', gs.preview_hunk, { desc = 'git [p]review hunk' }) + map('n', 'hi', gs.preview_hunk_inline, { desc = 'git preview hunk [i]nline' }) + map('n', 'hb', function() gs.blame_line { full = true } end, { desc = 'git [b]lame line' }) + map('n', 'hd', gs.diffthis, { desc = 'git [d]iff against index' }) + map('n', 'hD', function() gs.diffthis '@' end, { desc = 'git [D]iff against last commit' }) + map('n', 'hQ', function() gs.setqflist 'all' end, { desc = 'git hunk [Q]uickfix list (all files)' }) + map('n', 'hq', gs.setqflist, { desc = 'git hunk [q]uickfix list (this file)' }) + -- Toggles - map('n', 'tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) - map('n', 'tw', gitsigns.toggle_word_diff, { desc = '[T]oggle git intra-line [w]ord diff' }) + map('n', 'tb', gs.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) + map('n', 'tw', gs.toggle_word_diff, { desc = '[T]oggle git intra-line [w]ord diff' }) -- Text object - map({ 'o', 'x' }, 'ih', gitsigns.select_hunk) + map({ 'o', 'x' }, 'ih', gs.select_hunk) end, } diff --git a/lua/kickstart/plugins/guess-indent.lua b/lua/kickstart/plugins/guess-indent.lua new file mode 100644 index 00000000000..b3344a4c167 --- /dev/null +++ b/lua/kickstart/plugins/guess-indent.lua @@ -0,0 +1,4 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'NMAC427/guess-indent.nvim' } +require('guess-indent').setup {} diff --git a/lua/kickstart/plugins/lint.lua b/lua/kickstart/plugins/lint.lua index d63054452fd..f016ff80a88 100644 --- a/lua/kickstart/plugins/lint.lua +++ b/lua/kickstart/plugins/lint.lua @@ -1,53 +1,25 @@ --- Linting +-- Linting: static analysis that catches logic bugs, unused vars, security issues. +-- Different from formatting: linting finds problems; formatting fixes appearance. +-- Runs on BufEnter, BufWritePost, and InsertLeave for modifiable buffers. +local gh = require('kickstart.util').gh -vim.pack.add { 'https://github.com/mfussenegger/nvim-lint' } +vim.pack.add { gh 'mfussenegger/nvim-lint' } local lint = require 'lint' + lint.linters_by_ft = { - markdown = { 'markdownlint' }, -- Make sure to install `markdownlint` via mason / npm + sh = { 'shellcheck' }, + bash = { 'shellcheck' }, + zsh = { 'shellcheck' }, + go = { 'golangcilint' }, } --- To allow other plugins to add linters to require('lint').linters_by_ft, --- instead set linters_by_ft like this: --- lint.linters_by_ft = lint.linters_by_ft or {} --- lint.linters_by_ft['markdown'] = { 'markdownlint' } --- --- However, note that this will enable a set of default linters, --- which will cause errors unless these tools are available: --- { --- clojure = { "clj-kondo" }, --- dockerfile = { "hadolint" }, --- inko = { "inko" }, --- janet = { "janet" }, --- json = { "jsonlint" }, --- markdown = { "vale" }, --- rst = { "vale" }, --- ruby = { "ruby" }, --- terraform = { "tflint" }, --- text = { "vale" } --- } --- --- You can disable the default linters by setting their filetypes to nil: --- lint.linters_by_ft['clojure'] = nil --- lint.linters_by_ft['dockerfile'] = nil --- lint.linters_by_ft['inko'] = nil --- lint.linters_by_ft['janet'] = nil --- lint.linters_by_ft['json'] = nil --- lint.linters_by_ft['markdown'] = nil --- lint.linters_by_ft['rst'] = nil --- lint.linters_by_ft['ruby'] = nil --- lint.linters_by_ft['terraform'] = nil --- lint.linters_by_ft['text'] = nil - --- Create autocommand which carries out the actual linting --- on the specified events. local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, { group = lint_augroup, callback = function() - -- Only run the linter in buffers that you can modify in order to - -- avoid superfluous noise, notably within the handy LSP pop-ups that - -- describe the hovered symbol using Markdown. - if vim.bo.modifiable then lint.try_lint() end + if vim.bo.modifiable then + lint.try_lint() + end end, }) diff --git a/lua/kickstart/plugins/lsp.lua b/lua/kickstart/plugins/lsp.lua new file mode 100644 index 00000000000..8c62cf8cf57 --- /dev/null +++ b/lua/kickstart/plugins/lsp.lua @@ -0,0 +1,110 @@ +local gh = require('kickstart.util').gh + +-- Status updates for LSP +vim.pack.add { gh 'j-hui/fidget.nvim' } +require('fidget').setup {} + +-- LspAttach: per-buffer LSP keymaps and inlay hints +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), + callback = function(event) + local map = function(keys, func, desc, mode) + mode = mode or 'n' + vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) + end + + map('grn', vim.lsp.buf.rename, '[R]e[n]ame') + map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) + map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + + -- Highlight references on cursor hold + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client:supports_method('textDocument/documentHighlight', event.buf) then + local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) + vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.clear_references, + }) + vim.api.nvim_create_autocmd('LspDetach', { + group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), + callback = function(event2) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } + end, + }) + end + + -- Inlay hints toggle + if client and client:supports_method('textDocument/inlayHint', event.buf) then + map('th', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) + end, '[T]oggle Inlay [H]ints') + end + end, +}) + +-- Language servers +---@type table +local servers = { + gopls = {}, + pyright = {}, + terraformls = {}, + ansiblels = {}, + jinja_lsp = {}, + powershell_es = { + bundle_path = vim.fn.stdpath('data') .. '/mason/packages/powershell-editor-services', + }, + stylua = {}, + lua_ls = { + on_init = function(client) + client.server_capabilities.documentFormattingProvider = false + if client.workspace_folders then + local path = client.workspace_folders[1].name + if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then + return + end + end + client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { + runtime = { + version = 'LuaJIT', + path = { 'lua/?.lua', 'lua/?/init.lua' }, + }, + workspace = { + checkThirdParty = false, + library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { + '${3rd}/luv/library', + '${3rd}/busted/library', + }), + }, + }) + end, + settings = { + Lua = { + format = { enable = true }, + }, + }, + }, +} + +-- Mason: LSP installer and manager +vim.pack.add { + gh 'neovim/nvim-lspconfig', + gh 'mason-org/mason.nvim', + gh 'mason-org/mason-lspconfig.nvim', + gh 'WhoIsSethDaniel/mason-tool-installer.nvim', +} +require('mason').setup {} +local ensure_installed = vim.tbl_keys(servers or {}) +require('mason-tool-installer').setup { ensure_installed = ensure_installed } + +-- Enable all configured servers +for name, server in pairs(servers) do + vim.lsp.config(name, server) + vim.lsp.enable(name) +end diff --git a/lua/kickstart/plugins/mini.lua b/lua/kickstart/plugins/mini.lua new file mode 100644 index 00000000000..30f59ba319e --- /dev/null +++ b/lua/kickstart/plugins/mini.lua @@ -0,0 +1,26 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'nvim-mini/mini.nvim' } + +-- Icons (only if Nerd Font available) +if vim.g.have_nerd_font then + require('mini.icons').setup() + MiniIcons.mock_nvim_web_devicons() +end + +-- Better Around/Inside textobjects (vag, cia, etc.) +require('mini.ai').setup { + mappings = { + around_next = 'aa', + inside_next = 'ii', + }, + n_lines = 500, +} + +-- Surround (add/delete/replace brackets, quotes, etc.) +require('mini.surround').setup() + +-- Statusline +local statusline = require 'mini.statusline' +statusline.setup { use_icons = vim.g.have_nerd_font } +statusline.section_location = function() return '%2l:%-2v' end diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/kickstart/plugins/neo-tree.lua deleted file mode 100644 index 549629ae020..00000000000 --- a/lua/kickstart/plugins/neo-tree.lua +++ /dev/null @@ -1,20 +0,0 @@ --- Neo-tree is a Neovim plugin to browse the file system --- https://github.com/nvim-neo-tree/neo-tree.nvim - -vim.pack.add { - { src = 'https://github.com/nvim-neo-tree/neo-tree.nvim', version = vim.version.range '*' }, - 'https://github.com/nvim-lua/plenary.nvim', - 'https://github.com/MunifTanjim/nui.nvim', -} - -vim.keymap.set('n', '\\', 'Neotree reveal', { desc = 'NeoTree reveal', silent = true }) - -require('neo-tree').setup { - filesystem = { - window = { - mappings = { - ['\\'] = 'close_window', - }, - }, - }, -} diff --git a/lua/kickstart/plugins/telescope.lua b/lua/kickstart/plugins/telescope.lua new file mode 100644 index 00000000000..bec973ae56c --- /dev/null +++ b/lua/kickstart/plugins/telescope.lua @@ -0,0 +1,70 @@ +local gh = require('kickstart.util').gh + +---@type (string|vim.pack.Spec)[] +local telescope_plugins = { + gh 'nvim-lua/plenary.nvim', + gh 'nvim-telescope/telescope.nvim', + gh 'nvim-telescope/telescope-ui-select.nvim', +} +if vim.fn.executable 'make' == 1 then + table.insert(telescope_plugins, gh 'nvim-telescope/telescope-fzf-native.nvim') +end + +vim.pack.add(telescope_plugins) + +require('telescope').setup { + extensions = { + ['ui-select'] = { require('telescope.themes').get_dropdown() }, + }, +} + +pcall(require('telescope').load_extension, 'fzf') +pcall(require('telescope').load_extension, 'ui-select') + +local builtin = require 'telescope.builtin' +vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) +vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) +vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) +vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) +vim.keymap.set({ 'n', 'v' }, 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) +vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) +vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) +vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) +vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files (\".\" for repeat)' }) +vim.keymap.set('n', 'sc', builtin.commands, { desc = '[S]earch [C]ommands' }) +vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) + +-- LSP pickers per-buffer +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }), + callback = function(event) + local buf = event.buf + vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' }) + vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' }) + vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' }) + vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' }) + vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' }) + vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' }) + end, +}) + +-- Buffer fuzzy find +vim.keymap.set('n', '/', function() + builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) +end, { desc = '[/] Fuzzily search in current buffer' }) + +-- Live grep in open files +vim.keymap.set('n', 's/', function() + builtin.live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } +end, { desc = '[S]earch [/] in Open Files' }) + +-- Search Neovim config files +vim.keymap.set('n', 'sn', function() + builtin.find_files { cwd = vim.fn.stdpath 'config', follow = true } +end, { desc = '[S]earch [N]eovim files' }) diff --git a/lua/kickstart/plugins/todo-comments.lua b/lua/kickstart/plugins/todo-comments.lua new file mode 100644 index 00000000000..a92596ad7d4 --- /dev/null +++ b/lua/kickstart/plugins/todo-comments.lua @@ -0,0 +1,4 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'folke/todo-comments.nvim' } +require('todo-comments').setup { signs = false } diff --git a/lua/kickstart/plugins/tokyonight.lua b/lua/kickstart/plugins/tokyonight.lua new file mode 100644 index 00000000000..69b6983f2f3 --- /dev/null +++ b/lua/kickstart/plugins/tokyonight.lua @@ -0,0 +1,10 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'folke/tokyonight.nvim' } +require('tokyonight').setup { + styles = { + comments = { italic = false }, + }, +} + +vim.cmd.colorscheme 'tokyonight-night' diff --git a/lua/kickstart/plugins/treesitter.lua b/lua/kickstart/plugins/treesitter.lua new file mode 100644 index 00000000000..e4b3db251e6 --- /dev/null +++ b/lua/kickstart/plugins/treesitter.lua @@ -0,0 +1,38 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { { src = gh 'nvim-treesitter/nvim-treesitter', version = 'main' } } + +-- Install basic parsers +local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } +require('nvim-treesitter').install(parsers) + +---@param buf integer +---@param language string +local function treesitter_try_attach(buf, language) + if not vim.treesitter.language.add(language) then return end + vim.treesitter.start(buf, language) + local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil + if has_indent_query then + vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end +end + +local available_parsers = require('nvim-treesitter').get_available() +vim.api.nvim_create_autocmd('FileType', { + callback = function(args) + local buf, filetype = args.buf, args.match + local language = vim.treesitter.language.get_lang(filetype) + if not language then return end + + local installed_parsers = require('nvim-treesitter').get_installed 'parsers' + if vim.tbl_contains(installed_parsers, language) then + treesitter_try_attach(buf, language) + elseif vim.tbl_contains(available_parsers, language) then + require('nvim-treesitter').install(language):await(function() + treesitter_try_attach(buf, language) + end) + else + treesitter_try_attach(buf, language) + end + end, +}) diff --git a/lua/kickstart/plugins/which-key.lua b/lua/kickstart/plugins/which-key.lua new file mode 100644 index 00000000000..3c9615b91c3 --- /dev/null +++ b/lua/kickstart/plugins/which-key.lua @@ -0,0 +1,13 @@ +local gh = require('kickstart.util').gh + +vim.pack.add { gh 'folke/which-key.nvim' } +require('which-key').setup { + delay = 0, + icons = { mappings = vim.g.have_nerd_font }, + spec = { + { 's', group = '[S]earch', mode = { 'n', 'v' } }, + { 't', group = '[T]oggle' }, + { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + { 'gr', group = 'LSP Actions', mode = { 'n' } }, + }, +} diff --git a/lua/kickstart/util.lua b/lua/kickstart/util.lua new file mode 100644 index 00000000000..fffacd52d57 --- /dev/null +++ b/lua/kickstart/util.lua @@ -0,0 +1,11 @@ +-- Shared utilities for kickstart plugin files +local M = {} + +--- GitHub URL shorthand: gh('user/repo') -> 'https://github.com/user/repo' +---@param repo string +---@return string +function M.gh(repo) + return 'https://github.com/' .. repo +end + +return M