diff --git a/.gitignore b/.gitignore index 005b535b606..8a192cab54d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ test.sh nvim spell/ -lazy-lock.json diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000000..3f350df2928 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,11 @@ +{ + "MD013": false, + "MD012": false, + "MD028": false, + "MD033": false, + "MD034": false, + "MD036": false, + "MD024": false, + "MD041": false, + "MD060": false +} diff --git a/README.md b/README.md index 4113950550d..6f88813b171 100644 --- a/README.md +++ b/README.md @@ -1,241 +1,240 @@ -# kickstart.nvim +# Neovim Configuration -## Introduction +This is my personal Neovim configuration, originally forked from [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim) and expanded into a Windows-first setup. It uses [lazy.nvim](https://github.com/folke/lazy.nvim) for plugin management and is aimed at Unreal Engine and game-development workflows, especially C++ and Python. It also supports general-purpose development in Lua, TypeScript, CSS, and HTML. -A starting point for Neovim that is: +## Managing Plugins -* Small -* Single-file -* Completely Documented +### Adding a plugin -**NOT** a Neovim distribution, but instead a starting point for your configuration. +Create a new file in `lua/plugins/` that returns a lazy.nvim plugin spec table. Those plugin specs are loaded through `lua/setup/lazy.lua`, so keeping each plugin in its own file is the intended workflow. -## Installation +### Removing a plugin -### Install Neovim +Delete the plugin file in `lua/plugins/`, empty it, or remove the plugin spec you no longer want. If you want to keep the file around, you can also disable the plugin in place. -Kickstart.nvim targets *only* the latest -['stable'](https://github.com/neovim/neovim/releases/tag/stable) and latest -['nightly'](https://github.com/neovim/neovim/releases/tag/nightly) of Neovim. -If you are experiencing issues, please make sure you have the latest versions. +### Disabling a plugin temporarily -### Install External Dependencies +Add `enabled = false` to the plugin spec table. -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) -- 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 `lazy-lock.json` from your fork's `.gitignore` file -too - it's ignored in the kickstart repo to make maintenance easier, but it's -[recommended to track it in version control](https://lazy.folke.io/usage/lockfile). - -#### Clone kickstart.nvim - -> [!NOTE] -> If following the recommended step above (i.e., forking the repo), replace -> `nvim-lua` with `` in the commands below - -
Linux and Mac - -```sh -git clone https://github.com/nvim-lua/kickstart.nvim.git "${XDG_CONFIG_HOME:-$HOME/.config}"/nvim -``` - -
- -
Windows - -If you're using `cmd.exe`: - -``` -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! Lazy will install all the plugins you have. Use `:Lazy` to view -the current plugin status. Hit `q` to close the window. - -#### Read The Friendly Documentation - -Read through the `init.lua` file in your configuration folder for more -information about extending and exploring Neovim. That also includes -examples of adding popularly requested plugins. - -> [!NOTE] -> For more information about a particular plugin check its repository's documentation. - - -### Getting Started - -[The Only Video You Need to Get Started with Neovim](https://youtu.be/m8C0Cq9Uv9o) - -### FAQ - -* What should I do if I already have a pre-existing Neovim configuration? - * You should back it up and then delete all associated files. - * This includes your existing init.lua and the Neovim files in `~/.local` - which can be deleted with `rm -rf ~/.local/share/nvim/` -* Can I keep my existing configuration in parallel to kickstart? - * Yes! You can use [NVIM_APPNAME](https://neovim.io/doc/user/starting.html#%24NVIM_APPNAME)`=nvim-NAME` - to maintain multiple configurations. For example, you can install the kickstart - configuration in `~/.config/nvim-kickstart` and create an alias: - ``` - alias nvim-kickstart='NVIM_APPNAME="nvim-kickstart" nvim' - ``` - When you run Neovim using `nvim-kickstart` alias it will use the alternative - config directory and the matching local directory - `~/.local/share/nvim-kickstart`. You can apply this approach to any Neovim - distribution that you would like to try out. -* What if I want to "uninstall" this configuration: - * See [lazy.nvim uninstall](https://lazy.folke.io/usage#-uninstalling) information -* Why is the kickstart `init.lua` a single file? Wouldn't it make sense to split it into multiple files? - * The main purpose of kickstart is to serve as a teaching tool and a reference - configuration that someone can easily use to `git clone` as a basis for their own. - As you progress in learning Neovim and Lua, you might consider splitting `init.lua` - into smaller parts. A fork of kickstart that does this while maintaining the - same functionality is available here: - * [kickstart-modular.nvim](https://github.com/dam9000/kickstart-modular.nvim) - * Discussions on this topic can be found here: - * [Restructure the configuration](https://github.com/nvim-lua/kickstart.nvim/issues/218) - * [Reorganize init.lua into a multi-file setup](https://github.com/nvim-lua/kickstart.nvim/pull/473) - -### Install Recipes +```lua +return { + 'plugin/name', + enabled = false, + -- other options... +} +``` + +### Machine-specific paths + +Copy `machine.json.template` to `machine.json` (it is gitignored), then fill in the machine-specific paths for `basedpyright`, `clangd`, and optionally `ue_python`. + +## Keybinds + +Leader key: `` + +### Navigation + +| Key | Mode | Action | +| ------------- | ---- | ---------------------------------------- | +| `\` | n | Open file tree (Neo-tree) | +| `` | n | Move to left split | +| `` | n | Move to lower split | +| `` | n | Move to upper split | +| `` | n | Move to right split | +| `` | n | Resize split left | +| `` | n | Resize split down | +| `` | n | Resize split up | +| `` | n | Resize split right | +| `` | n | Scroll half-page down (centered) | +| `` | n | Scroll half-page up (centered) | +| `n` / `N` | n | Next/prev search result (centered) | +| `]b` / `[b` | n | Next/prev buffer | +| `]d` / `[d` | n | Next/prev diagnostic | +| `]c` / `[c` | n | Next/prev git hunk (in git buffers) | +| `]q` / `[q` | n | Next/prev quickfix item | +| `j` / `k` | n | Move by visual lines when no count given | +| `` | i | Move cursor in insert mode | +| `J` / `K` | v | Move selected lines down/up | + +### Search (Telescope) + +| Key | Action | +| ------------------ | ------------------------------ | +| `sf` | Find files | +| `sg` | Live grep | +| `sw` | Search current word | +| `sd` | Search diagnostics | +| `sh` | Search help tags | +| `sk` | Search keymaps | +| `ss` | Select Telescope picker | +| `sr` | Resume last search | +| `s.` | Recent files | +| `` | Find open buffers | +| `/` | Fuzzy search in current buffer | +| `s/` | Grep in open files | +| `sn` | Search Neovim config files | + +### LSP + +| Key | Action | +| ------------ | ------------------------------------------------------ | +| `grd` | Go to definition (Telescope) | +| `grD` | Go to declaration | +| `grr` | Go to references (Telescope) | +| `gri` | Go to implementation (Telescope) | +| `grt` | Go to type definition (Telescope) | +| `gd` | Go to definition (native) | +| `gO` | Document symbols | +| `gW` | Workspace symbols | +| `K` | Hover documentation | +| `grn` | Rename symbol | +| `n` | Rename symbol | +| `gra` | Code action (n/x) | +| `lh` | Toggle inlay hints (per buffer) | +| `ld` | Toggle diagnostic mode (all lines ↔ current line only) | +| `li` | Toggle inlay hints (global) | +| `q` | Send diagnostics to quickfix list | +| `pi` | Organize imports (Python/basedpyright) | + +### Git + +| Key | Action | +| ------------ | ------------------------- | +| `gs` | Git status (fugitive) | +| `gd` | Git diff split | +| `gb` | Git blame (fugitive) | +| `gl` | Git log | +| `gp` | Git push | +| `hs` | Stage hunk (n/v) | +| `hr` | Reset hunk (n/v) | +| `hS` | Stage buffer | +| `hu` | Undo stage hunk | +| `hR` | Reset buffer | +| `hp` | Preview hunk (popup) | +| `hP` | Preview hunk inline | +| `hb` | Blame line | +| `hd` | Diff against index | +| `hD` | Diff against last commit | +| `tb` | Toggle line blame | +| `tD` | Toggle show deleted lines | +| `tw` | Toggle word diff | + +### Debug (DAP) + +| Key | Action | +| ----------- | -------------------------- | +| `` | Start / Continue | +| `` | Step into | +| `` | Step over | +| `` | Step out | +| `` | Toggle DAP UI | +| `b` | Toggle breakpoint | +| `B` | Set conditional breakpoint | + +### Build (CMake) + +| Key | Action | +| ------------- | -------------- | +| `cmg` | CMake Generate | +| `cmb` | CMake Build | +| `cmr` | CMake Run | +| `cmd` | CMake Debug | +| `cms` | CMake Stop | + +### AI + +| Key | Action | +| ------------ | --------------------------- | +| `cc` | CodeCompanion Chat toggle | +| `ca` | CodeCompanion Actions (n/v) | +| `cd` | Generate docstring (visual) | + +### Toggles & Utilities + +| Key | Action | +| ---------------- | -------------------------------------- | +| `` | Toggle terminal (float) | +| `tf` | Toggle floating terminal | +| `th` | Toggle horizontal terminal | +| `` | Clear search highlight | +| `` | Clear search highlight | +| `jk` | Escape (n/v/i/t) | +| `p` | Paste over selection (v, no overwrite) | +| `d` | Delete to black hole (n/v) | + +### Commands (no keybind, but worth knowing) + +| Command | Action | +| --------------------------------- | ---------------------------------- | +| `:LspRestart ` | Restart a named LSP server | +| `:LspInfo` | Show comprehensive LSP info | +| `:LspStatus` | Show LSP clients on current buffer | +| `:LspCapabilities` | Show LSP capabilities | +| `:LspDiagnostics` | Show diagnostic counts | +| `:Unreal` | Manually initialize Unreal-Nvim | +| `:LspPyrightOrganizeImports` | Organize Python imports | +| `:LspPyrightSetPythonPath ` | Set Python interpreter path | + +## Unreal Engine + +### Auto-initialization + +Unreal-Nvim auto-initializes when opening: + +- `*.uproject`, `*.uplugin`, `*.Build.cs`, `*.Target.cs` +- C/C++ files (`*.cpp`, `*.h`, `*.hpp`, `*.c`) when the cwd contains a `.uproject` +- New C/C++ files created inside a UE project cwd + +If auto-init does not trigger, run `:Unreal` manually. + +### C++ Workflow + +- Open Neovim from the Unreal project root so `clangd` picks up `compile_commands.json` or `compile_flags.txt` +- Use `CMakeGenerate` / `CMakeBuild` (`cmg`, `cmb`) or UBT directly +- Debugging uses the `codelldb` adapter via DAP (`` to start, `b` for breakpoints) +- `clangd` provides completion, hover, and go-to-definition for UE C++ headers +- You can set a machine-specific `clangd` binary path in `machine.json` under the `clangd` key + +### Python (Editor Scripting) + +- Open Neovim from the Unreal project root so Python stub detection works correctly +- `basedpyright` picks up `Intermediate/PythonStub` automatically when Unreal-Nvim is initialized +- Plugin Python paths (`Plugins/*/Content/Python`) are added to `extraPaths` automatically +- Set the UE Python interpreter in `machine.json` under the `ue_python` key +- Use `pi` to organize imports +- Python debugging uses `debugpy` via DAP (``) + +## Troubleshooting + +### LSP not starting -Below you can find OS specific install instructions for Neovim and dependencies. +- Run `:LspInfo` to check whether a client is attached +- Ensure the language server binary is on `PATH` or configured in `machine.json` +- Run `:LspRestart ` to force-restart a specific server -After installing all the dependencies continue with the [Install Kickstart](#Install-Kickstart) step. +### Plugins not loading -#### Windows Installation +- Run `:Lazy` to open the plugin manager UI +- Check `:Lazy log` for errors +- Run `:Lazy sync` to update all plugins -
Windows with Microsoft C++ Build Tools and CMake -Installation may require installing build tools and updating the run command for `telescope-fzf-native` +### machine.json missing -See `telescope-fzf-native` documentation for [more details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation) +- Copy `machine.json.template` to `machine.json` and fill in the required paths +- Without it, LSP servers fall back to binaries on `PATH`, which may or may not work on your system -This requires: +### Python debugging fails on first launch -- Install CMake and the Microsoft C++ Build Tools on Windows +- On first run, Mason installs `debugpy` in the background; Python DAP is wired automatically once installation completes +- If it still fails, restart Neovim and try again -```lua -{'nvim-telescope/telescope-fzf-native.nvim', build = 'cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release && cmake --install build --prefix build' } -``` -
-
Windows with gcc/make using chocolatey -Alternatively, one can install gcc and make which don't require changing the config, -the easiest way is to use choco: - -1. install [chocolatey](https://chocolatey.org/install) -either follow the instructions on the page or use winget, -run in cmd as **admin**: -``` -winget install --accept-source-agreements chocolatey.chocolatey -``` +### Unreal LSP/Python not working -2. install all requirements using choco, exit the previous cmd and -open a new one so that choco path is set, and run in cmd as **admin**: -``` -choco install -y neovim git ripgrep wget fd unzip gzip mingw make -``` -
-
WSL (Windows Subsystem for Linux) +- Ensure Neovim is opened from the Unreal project root (the directory containing the `.uproject`) +- Run `:Unreal` to manually trigger Unreal-Nvim initialization +- Check that `ue_python` is set in `machine.json` for the correct UE Python interpreter -``` -wsl --install -wsl -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip neovim -``` -
- -#### Linux Install -
Ubuntu Install Steps - -``` -sudo add-apt-repository ppa:neovim-ppa/unstable -y -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip neovim -``` -
-
Debian Install Steps - -``` -sudo apt update -sudo apt install make gcc ripgrep unzip git xclip curl - -# Now we install nvim -curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-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 unzip neovim -``` -
- -
Arch Install Steps - -``` -sudo pacman -S --noconfirm --needed gcc make git ripgrep fd unzip neovim -``` -
+### Clangd not finding headers +- Ensure a `compile_commands.json` or `compile_flags.txt` exists in the project root (generated by CMake or UBT) +- Set the `clangd` path in `machine.json` if you use a custom LLVM build diff --git a/doc/kickstart.txt b/doc/kickstart.txt deleted file mode 100644 index cb87ac3f1de..00000000000 --- a/doc/kickstart.txt +++ /dev/null @@ -1,24 +0,0 @@ -================================================================================ -INTRODUCTION *kickstart.nvim* - -Kickstart.nvim is a project to help you get started on your neovim journey. - - *kickstart-is-not* -It is not: -- Complete framework for every plugin under the sun -- Place to add every plugin that could ever be useful - - *kickstart-is* -It is: -- Somewhere that has a good start for the most common "IDE" type features: - - autocompletion - - goto-definition - - find references - - fuzzy finding - - and hinting at what more can be done :) -- A place to _kickstart_ your journey. - - You should fork this project and use/modify it so that it matches your - style and preferences. If you don't want to do that, there are probably - other projects that would fit much better for you (and that's great!)! - - vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/tags b/doc/tags deleted file mode 100644 index 687ae7721d9..00000000000 --- a/doc/tags +++ /dev/null @@ -1,3 +0,0 @@ -kickstart-is kickstart.txt /*kickstart-is* -kickstart-is-not kickstart.txt /*kickstart-is-not* -kickstart.nvim kickstart.txt /*kickstart.nvim* diff --git a/init.lua b/init.lua index b98ffc6198a..68e2ea24fb4 100644 --- a/init.lua +++ b/init.lua @@ -1,1016 +1,5 @@ ---[[ - -===================================================================== -==================== READ THIS BEFORE CONTINUING ==================== -===================================================================== -======== .-----. ======== -======== .----------------------. | === | ======== -======== |.-""""""""""""""""""-.| |-----| ======== -======== || || | === | ======== -======== || KICKSTART.NVIM || |-----| ======== -======== || || | === | ======== -======== || || |-----| ======== -======== ||:Tutor || |:::::| ======== -======== |'-..................-'| |____o| ======== -======== `"")----------------(""` ___________ ======== -======== /::::::::::| |::::::::::\ \ no mouse \ ======== -======== /:::========| |==hjkl==:::\ \ required \ ======== -======== '""""""""""""' '""""""""""""' '""""""""""' ======== -======== ======== -===================================================================== -===================================================================== - -What is Kickstart? - - Kickstart.nvim is *not* a distribution. - - Kickstart.nvim is a starting point for your own configuration. - The goal is that you can read every line of code, top-to-bottom, understand - what your configuration is doing, and modify it to suit your needs. - - Once you've done that, you can start exploring, configuring and tinkering to - make Neovim your own! That might mean leaving Kickstart just the way it is for a while - or immediately breaking it into modular pieces. It's up to you! - - If you don't know anything about Lua, I recommend taking some time to read through - a guide. One possible example which will only take 10-15 minutes: - - https://learnxinyminutes.com/docs/lua/ - - After understanding a bit more about Lua, you can use `:help lua-guide` as a - reference for how Neovim integrates Lua. - - :help lua-guide - - (or HTML version): https://neovim.io/doc/user/lua-guide.html - -Kickstart Guide: - - TODO: The very first thing you should do is to run the command `:Tutor` in Neovim. - - If you don't know what this means, type the following: - - - - : - - Tutor - - - - (If you already know the Neovim basics, you can skip this step.) - - Once you've completed that, you can continue working through **AND READING** the rest - of the kickstart init.lua. - - Next, run AND READ `:help`. - This will open up a help window with some basic information - about reading, navigating and searching the builtin help documentation. - - This should be the first place you go to look when you're stuck or confused - with something. It's one of my favorite Neovim features. - - MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, - which is very useful when you're not exactly sure of what you're looking for. - - I have left several `:help X` comments throughout the init.lua - These are hints about where to find more information about the relevant settings, - plugins or Neovim features used in Kickstart. - - NOTE: Look for lines like this - - Throughout the file. These are for you, the reader, to help you understand what is happening. - Feel free to delete them once you know what you're doing, but they should serve as a guide - for when you are first encountering a few different constructs in your Neovim config. - -If you experience any errors while trying to install kickstart, run `:checkhealth` for more info. - -I hope you enjoy your Neovim journey, -- TJ - -P.S. You can delete this when you're done too. It's your config now! :) ---]] - --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) -vim.g.mapleader = ' ' -vim.g.maplocalleader = ' ' - --- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false - --- [[ Setting options ]] --- See `:help vim.o` --- NOTE: You can change these options as you wish! --- For more options, you can see `:help option-list` - --- Make line numbers default -vim.o.number = true --- You can also add relative line numbers, to help with jumping. --- Experiment for yourself to see if you like it! --- vim.o.relativenumber = true - --- Enable mouse mode, can be useful for resizing splits for example! -vim.o.mouse = 'a' - --- Don't show the mode, since it's already in the status line -vim.o.showmode = false - --- Sync clipboard between OS and Neovim. --- Schedule the setting after `UiEnter` because it can increase startup-time. --- Remove this option if you want your OS clipboard to remain independent. --- See `:help 'clipboard'` -vim.schedule(function() - vim.o.clipboard = 'unnamedplus' -end) - --- Enable break indent -vim.o.breakindent = true - --- Save undo history -vim.o.undofile = true - --- Case-insensitive searching UNLESS \C or one or more capital letters in the search term -vim.o.ignorecase = true -vim.o.smartcase = true - --- Keep signcolumn on by default -vim.o.signcolumn = 'yes' - --- Decrease update time -vim.o.updatetime = 250 - --- Decrease mapped sequence wait time -vim.o.timeoutlen = 300 - --- Configure how new splits should be opened -vim.o.splitright = true -vim.o.splitbelow = true - --- Sets how neovim will display certain whitespace characters in the editor. --- See `:help 'list'` --- and `:help 'listchars'` --- --- Notice listchars is set using `vim.opt` instead of `vim.o`. --- It is very similar to `vim.o` but offers an interface for conveniently interacting with tables. --- See `:help lua-options` --- and `:help lua-options-guide` -vim.o.list = true -vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } - --- Preview substitutions live, as you type! -vim.o.inccommand = 'split' - --- Show which line your cursor is on -vim.o.cursorline = true - --- Minimal number of screen lines to keep above and below the cursor. -vim.o.scrolloff = 10 - --- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`), --- instead raise a dialog asking if you wish to save the current file(s) --- See `:help 'confirm'` -vim.o.confirm = true - --- [[ Basic Keymaps ]] --- See `:help vim.keymap.set()` - --- Clear highlights on search when pressing in normal mode --- See `:help hlsearch` -vim.keymap.set('n', '', 'nohlsearch') - --- Diagnostic keymaps -vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) - --- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier --- for people to discover. Otherwise, you normally need to press , which --- is not what someone will guess without a bit more experience. --- --- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping --- or just use to exit terminal mode -vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) - --- TIP: Disable arrow keys in normal mode --- vim.keymap.set('n', '', 'echo "Use h to move!!"') --- vim.keymap.set('n', '', 'echo "Use l to move!!"') --- vim.keymap.set('n', '', 'echo "Use k to move!!"') --- vim.keymap.set('n', '', 'echo "Use j to move!!"') - --- Keybinds to make split navigation easier. --- Use CTRL+ to switch between windows --- --- See `:help wincmd` for a list of all window commands -vim.keymap.set('n', '', '', { desc = 'Move focus to the left window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the right window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the lower window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the upper window' }) - --- NOTE: Some terminals have colliding keymaps or are not able to send distinct keycodes --- vim.keymap.set("n", "", "H", { desc = "Move window to the left" }) --- vim.keymap.set("n", "", "L", { desc = "Move window to the right" }) --- vim.keymap.set("n", "", "J", { desc = "Move window to the lower" }) --- vim.keymap.set("n", "", "K", { desc = "Move window to the upper" }) - --- [[ Basic Autocommands ]] --- See `:help lua-guide-autocommands` - --- Highlight when yanking (copying) text --- Try it with `yap` in normal mode --- See `:help vim.hl.on_yank()` -vim.api.nvim_create_autocmd('TextYankPost', { - desc = 'Highlight when yanking (copying) text', - group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }), - callback = function() - vim.hl.on_yank() - end, -}) - --- [[ Install `lazy.nvim` plugin manager ]] --- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info -local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' -if not (vim.uv or vim.loop).fs_stat(lazypath) then - local lazyrepo = 'https://github.com/folke/lazy.nvim.git' - local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath } - if vim.v.shell_error ~= 0 then - error('Error cloning lazy.nvim:\n' .. out) - end -end - ----@type vim.Option -local rtp = vim.opt.rtp -rtp:prepend(lazypath) - --- [[ Configure and install plugins ]] --- --- To check the current status of your plugins, run --- :Lazy --- --- You can press `?` in this menu for help. Use `:q` to close the window --- --- To update plugins you can run --- :Lazy update --- --- NOTE: Here is where you install your plugins. -require('lazy').setup({ - -- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). - 'NMAC427/guess-indent.nvim', -- Detect tabstop and shiftwidth automatically - - -- NOTE: Plugins can also be added by using a table, - -- with the first argument being the link and the following - -- keys can be used to configure plugin behavior/loading/etc. - -- - -- Use `opts = {}` to automatically pass options to a plugin's `setup()` function, forcing the plugin to be loaded. - -- - - -- Alternatively, use `config = function() ... end` for full control over the configuration. - -- If you prefer to call `setup` explicitly, use: - -- { - -- 'lewis6991/gitsigns.nvim', - -- config = function() - -- require('gitsigns').setup({ - -- -- Your gitsigns configuration here - -- }) - -- end, - -- } - -- - -- Here is a more advanced example where we pass configuration - -- options to `gitsigns.nvim`. - -- - -- See `:help gitsigns` to understand what the configuration keys do - { -- Adds git related signs to the gutter, as well as utilities for managing changes - 'lewis6991/gitsigns.nvim', - opts = { - signs = { - add = { text = '+' }, - change = { text = '~' }, - delete = { text = '_' }, - topdelete = { text = '‾' }, - changedelete = { text = '~' }, - }, - }, - }, - - -- NOTE: Plugins can also be configured to run Lua code when they are loaded. - -- - -- This is often very useful to both group configuration, as well as handle - -- lazy loading plugins that don't need to be loaded immediately at startup. - -- - -- For example, in the following configuration, we use: - -- event = 'VimEnter' - -- - -- which loads which-key before all the UI elements are loaded. Events can be - -- normal autocommands events (`:help autocmd-events`). - -- - -- Then, because we use the `opts` key (recommended), the configuration runs - -- after the plugin has been loaded as `require(MODULE).setup(opts)`. - - { -- Useful plugin to show you pending keybinds. - 'folke/which-key.nvim', - event = 'VimEnter', -- Sets the loading event to 'VimEnter' - opts = { - -- delay between pressing a key and opening which-key (milliseconds) - -- this setting is independent of vim.o.timeoutlen - delay = 0, - icons = { - -- set icon mappings to true if you have a Nerd Font - mappings = vim.g.have_nerd_font, - -- If you are using a Nerd Font: set icons.keys to an empty table which will use the - -- default which-key.nvim defined Nerd Font icons, otherwise define a string table - keys = vim.g.have_nerd_font and {} or { - Up = ' ', - Down = ' ', - Left = ' ', - Right = ' ', - C = ' ', - M = ' ', - D = ' ', - S = ' ', - CR = ' ', - Esc = ' ', - ScrollWheelDown = ' ', - ScrollWheelUp = ' ', - NL = ' ', - BS = ' ', - Space = ' ', - Tab = ' ', - F1 = '', - F2 = '', - F3 = '', - F4 = '', - F5 = '', - F6 = '', - F7 = '', - F8 = '', - F9 = '', - F10 = '', - F11 = '', - F12 = '', - }, - }, - - -- Document existing key chains - spec = { - { 's', group = '[S]earch' }, - { 't', group = '[T]oggle' }, - { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, - }, - }, - }, - - -- NOTE: Plugins can specify dependencies. - -- - -- The dependencies are proper plugin specifications as well - anything - -- you do for a plugin at the top level, you can do for a dependency. - -- - -- Use the `dependencies` key to specify the dependencies of a particular plugin - - { -- Fuzzy Finder (files, lsp, etc) - 'nvim-telescope/telescope.nvim', - event = 'VimEnter', - dependencies = { - 'nvim-lua/plenary.nvim', - { -- If encountering errors, see telescope-fzf-native README for installation instructions - 'nvim-telescope/telescope-fzf-native.nvim', - - -- `build` is used to run some command when the plugin is installed/updated. - -- This is only run then, not every time Neovim starts up. - build = 'make', - - -- `cond` is a condition used to determine whether this plugin should be - -- installed and loaded. - cond = function() - return vim.fn.executable 'make' == 1 - end, - }, - { 'nvim-telescope/telescope-ui-select.nvim' }, - - -- Useful for getting pretty icons, but requires a Nerd Font. - { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font }, - }, - config = function() - -- Telescope is a fuzzy finder that comes with a lot of different things that - -- it can fuzzy find! It's more than just a "file finder", it can search - -- many different aspects of Neovim, your workspace, LSP, and more! - -- - -- The easiest way to use Telescope, is to start by doing something like: - -- :Telescope help_tags - -- - -- After running this command, a window will open up and you're able to - -- type in the prompt window. You'll see a list of `help_tags` options and - -- a corresponding preview of the help. - -- - -- Two important keymaps to use while in Telescope are: - -- - Insert mode: - -- - Normal mode: ? - -- - -- This opens a window that shows you all of the keymaps for the current - -- Telescope picker. This is really useful to discover what Telescope can - -- do as well as how to actually do it! - - -- [[ Configure Telescope ]] - -- See `:help telescope` and `:help telescope.setup()` - require('telescope').setup { - -- You can put your default mappings / updates / etc. in here - -- All the info you're looking for is in `:help telescope.setup()` - -- - -- defaults = { - -- mappings = { - -- i = { [''] = 'to_fuzzy_refine' }, - -- }, - -- }, - -- pickers = {} - extensions = { - ['ui-select'] = { - require('telescope.themes').get_dropdown(), - }, - }, - } - - -- Enable Telescope extensions if they are installed - pcall(require('telescope').load_extension, 'fzf') - pcall(require('telescope').load_extension, 'ui-select') - - -- See `:help telescope.builtin` - local builtin = require 'telescope.builtin' - vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) - vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) - vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) - vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) - vim.keymap.set('n', 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) - vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) - vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) - vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) - vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) - vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) - - -- Slightly advanced example of overriding default behavior and theme - vim.keymap.set('n', '/', function() - -- You can pass additional configuration to Telescope to change the theme, layout, etc. - builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { - winblend = 10, - previewer = false, - }) - end, { desc = '[/] Fuzzily search in current buffer' }) - - -- It's also possible to pass additional configuration options. - -- See `:help telescope.builtin.live_grep()` for information about particular keys - vim.keymap.set('n', 's/', function() - builtin.live_grep { - grep_open_files = true, - prompt_title = 'Live Grep in Open Files', - } - end, { desc = '[S]earch [/] in Open Files' }) - - -- Shortcut for searching your Neovim configuration files - vim.keymap.set('n', 'sn', function() - builtin.find_files { cwd = vim.fn.stdpath 'config' } - end, { desc = '[S]earch [N]eovim files' }) - end, - }, - - -- LSP Plugins - { - -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins - -- used for completion, annotations and signatures of Neovim apis - 'folke/lazydev.nvim', - ft = 'lua', - opts = { - library = { - -- Load luvit types when the `vim.uv` word is found - { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, - }, - }, - }, - { - -- Main LSP Configuration - 'neovim/nvim-lspconfig', - dependencies = { - -- Automatically install LSPs and related tools to stdpath for Neovim - -- Mason must be loaded before its dependents so we need to set it up here. - -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` - { 'mason-org/mason.nvim', opts = {} }, - 'mason-org/mason-lspconfig.nvim', - 'WhoIsSethDaniel/mason-tool-installer.nvim', - - -- Useful status updates for LSP. - { 'j-hui/fidget.nvim', opts = {} }, - - -- Allows extra capabilities provided by blink.cmp - 'saghen/blink.cmp', - }, - config = function() - -- Brief aside: **What is LSP?** - -- - -- LSP is an initialism you've probably heard, but might not understand what it is. - -- - -- LSP stands for Language Server Protocol. It's a protocol that helps editors - -- and language tooling communicate in a standardized fashion. - -- - -- In general, you have a "server" which is some tool built to understand a particular - -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers - -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone - -- processes that communicate with some "client" - in this case, Neovim! - -- - -- LSP provides Neovim with features like: - -- - Go to definition - -- - Find references - -- - Autocompletion - -- - Symbol Search - -- - and more! - -- - -- Thus, Language Servers are external tools that must be installed separately from - -- Neovim. This is where `mason` and related plugins come into play. - -- - -- If you're wondering about lsp vs treesitter, you can check out the wonderfully - -- and elegantly composed help section, `:help lsp-vs-treesitter` - - -- This function gets run when an LSP attaches to a particular buffer. - -- That is to say, every time a new file is opened that is associated with - -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this - -- function will be executed to configure the current buffer - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), - callback = function(event) - -- NOTE: Remember that Lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local map = function(keys, func, desc, mode) - mode = mode or 'n' - vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) - end - - -- 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' }) - - -- Find references for the word under your cursor. - map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') - - -- Jump to the implementation of the word under your cursor. - -- Useful when your language has ways of declaring types without an actual implementation. - map('gri', require('telescope.builtin').lsp_implementations, '[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 . - map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') - - -- 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') - - -- Fuzzy find all the symbols in your current document. - -- Symbols are things like variables, functions, types, etc. - map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols') - - -- Fuzzy find all the symbols in your current workspace. - -- Similar to document symbols, except searches over your entire project. - map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, '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*. - map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition') - - -- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10) - ---@param client vim.lsp.Client - ---@param method vim.lsp.protocol.Method - ---@param bufnr? integer some lsp support methods only in specific files - ---@return boolean - local function client_supports_method(client, method, bufnr) - if vim.fn.has 'nvim-0.11' == 1 then - return client:supports_method(method, bufnr) - else - return client.supports_method(method, { bufnr = bufnr }) - end - end - - -- 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(client, vim.lsp.protocol.Methods.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(client, vim.lsp.protocol.Methods.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, - }) - - -- Diagnostic Config - -- See :help vim.diagnostic.Opts - vim.diagnostic.config { - severity_sort = true, - float = { border = 'rounded', source = 'if_many' }, - underline = { severity = vim.diagnostic.severity.ERROR }, - signs = vim.g.have_nerd_font and { - text = { - [vim.diagnostic.severity.ERROR] = '󰅚 ', - [vim.diagnostic.severity.WARN] = '󰀪 ', - [vim.diagnostic.severity.INFO] = '󰋽 ', - [vim.diagnostic.severity.HINT] = '󰌶 ', - }, - } or {}, - virtual_text = { - source = 'if_many', - spacing = 2, - format = function(diagnostic) - local diagnostic_message = { - [vim.diagnostic.severity.ERROR] = diagnostic.message, - [vim.diagnostic.severity.WARN] = diagnostic.message, - [vim.diagnostic.severity.INFO] = diagnostic.message, - [vim.diagnostic.severity.HINT] = diagnostic.message, - } - return diagnostic_message[diagnostic.severity] - end, - }, - } - - -- LSP servers and clients are able to communicate to each other what features they support. - -- By default, Neovim doesn't support everything that is in the LSP specification. - -- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities. - -- So, we create new capabilities with blink.cmp, and then broadcast that to the servers. - local capabilities = require('blink.cmp').get_lsp_capabilities() - - -- Enable the following language servers - -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. - -- - -- Add any additional override configuration in the following tables. Available keys are: - -- - cmd (table): Override the default command used to start the server - -- - filetypes (table): Override the default list of associated filetypes for the server - -- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features. - -- - settings (table): Override the default settings passed when initializing the server. - -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ - local servers = { - -- clangd = {}, - -- gopls = {}, - -- pyright = {}, - -- rust_analyzer = {}, - -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs - -- - -- Some languages (like typescript) have entire language plugins that can be useful: - -- https://github.com/pmizio/typescript-tools.nvim - -- - -- But for many setups, the LSP (`ts_ls`) will work just fine - -- ts_ls = {}, - -- - - lua_ls = { - -- cmd = { ... }, - -- filetypes = { ... }, - -- capabilities = {}, - settings = { - Lua = { - completion = { - callSnippet = 'Replace', - }, - -- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings - -- diagnostics = { disable = { 'missing-fields' } }, - }, - }, - }, - } - - -- Ensure the servers and tools above are installed - -- - -- To check the current status of installed tools and/or manually install - -- other tools, you can run - -- :Mason - -- - -- You can press `g?` for help in this menu. - -- - -- `mason` had to be setup earlier: to configure its options see the - -- `dependencies` table for `nvim-lspconfig` above. - -- - -- You can add other tools here that you want Mason to install - -- for you, so that they are available from within Neovim. - local ensure_installed = vim.tbl_keys(servers or {}) - vim.list_extend(ensure_installed, { - 'stylua', -- Used to format Lua code - }) - require('mason-tool-installer').setup { ensure_installed = ensure_installed } - - require('mason-lspconfig').setup { - ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer) - automatic_installation = false, - handlers = { - function(server_name) - local server = servers[server_name] or {} - -- This handles overriding only values explicitly passed - -- by the server configuration above. Useful when disabling - -- certain features of an LSP (for example, turning off formatting for ts_ls) - server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - require('lspconfig')[server_name].setup(server) - end, - }, - } - end, - }, - - { -- Autoformat - 'stevearc/conform.nvim', - event = { 'BufWritePre' }, - cmd = { 'ConformInfo' }, - keys = { - { - 'f', - function() - require('conform').format { async = true, lsp_format = 'fallback' } - end, - mode = '', - desc = '[F]ormat buffer', - }, - }, - opts = { - notify_on_error = false, - format_on_save = function(bufnr) - -- Disable "format_on_save lsp_fallback" for languages that don't - -- have a well standardized coding style. You can add additional - -- languages here or re-enable it for the disabled ones. - local disable_filetypes = { c = true, cpp = true } - if disable_filetypes[vim.bo[bufnr].filetype] then - return nil - else - return { - timeout_ms = 500, - lsp_format = 'fallback', - } - end - end, - formatters_by_ft = { - lua = { 'stylua' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use 'stop_after_first' to run the first available formatter from the list - -- javascript = { "prettierd", "prettier", stop_after_first = true }, - }, - }, - }, - - { -- Autocompletion - 'saghen/blink.cmp', - event = 'VimEnter', - version = '1.*', - dependencies = { - -- Snippet Engine - { - 'L3MON4D3/LuaSnip', - version = '2.*', - build = (function() - -- Build Step is needed for regex support in snippets. - -- This step is not supported in many windows environments. - -- Remove the below condition to re-enable on windows. - if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then - return - end - return 'make install_jsregexp' - end)(), - dependencies = { - -- `friendly-snippets` contains a variety of premade snippets. - -- See the README about individual language/framework/plugin snippets: - -- https://github.com/rafamadriz/friendly-snippets - -- { - -- 'rafamadriz/friendly-snippets', - -- config = function() - -- require('luasnip.loaders.from_vscode').lazy_load() - -- end, - -- }, - }, - opts = {}, - }, - 'folke/lazydev.nvim', - }, - --- @module 'blink.cmp' - --- @type blink.cmp.Config - opts = { - 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 :h 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 }, - }, - - sources = { - default = { 'lsp', 'path', 'snippets', 'lazydev' }, - providers = { - lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 }, - }, - }, - - snippets = { preset = 'luasnip' }, - - -- 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 :h blink-cmp-config-fuzzy for more information - fuzzy = { implementation = 'lua' }, - - -- Shows a signature help window while you type arguments for a function - signature = { enabled = true }, - }, - }, - - { -- You can easily change to a different colorscheme. - -- Change the name of the colorscheme plugin below, and then - -- change the command in the config to whatever the name of that colorscheme is. - -- - -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`. - 'folke/tokyonight.nvim', - priority = 1000, -- Make sure to load this before all the other start plugins. - config = function() - ---@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' - end, - }, - - -- Highlight todo, notes, etc in comments - { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, - - { -- Collection of various small independent plugins/modules - 'echasnovski/mini.nvim', - config = function() - -- Better Around/Inside textobjects - -- - -- Examples: - -- - va) - [V]isually select [A]round [)]paren - -- - yinq - [Y]ank [I]nside [N]ext [Q]uote - -- - ci' - [C]hange [I]nside [']quote - require('mini.ai').setup { n_lines = 500 } - - -- Add/delete/replace surroundings (brackets, quotes, etc.) - -- - -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren - -- - sd' - [S]urround [D]elete [']quotes - -- - sr)' - [S]urround [R]eplace [)] ['] - require('mini.surround').setup() - - -- Simple and easy statusline. - -- You could remove this setup call if you don't like it, - -- and try some other statusline plugin - local statusline = require 'mini.statusline' - -- set use_icons to true if you have a Nerd Font - statusline.setup { use_icons = vim.g.have_nerd_font } - - -- You can configure sections in the statusline by overriding their - -- default behavior. For example, here we set the section for - -- cursor location to LINE:COLUMN - ---@diagnostic disable-next-line: duplicate-set-field - statusline.section_location = function() - return '%2l:%-2v' - end - - -- ... and there is more! - -- Check out: https://github.com/echasnovski/mini.nvim - end, - }, - { -- Highlight, edit, and navigate code - 'nvim-treesitter/nvim-treesitter', - build = ':TSUpdate', - main = 'nvim-treesitter.configs', -- Sets main module to use for opts - -- [[ Configure Treesitter ]] See `:help nvim-treesitter` - opts = { - ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }, - -- Autoinstall languages that are not installed - auto_install = true, - highlight = { - enable = true, - -- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. - -- If you are experiencing weird indenting issues, add the language to - -- the list of additional_vim_regex_highlighting and disabled languages for indent. - additional_vim_regex_highlighting = { 'ruby' }, - }, - indent = { enable = true, disable = { 'ruby' } }, - }, - -- There are additional nvim-treesitter modules that you can use to interact - -- with nvim-treesitter. You should go explore a few and see what interests you: - -- - -- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod` - -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context - -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects - }, - - -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the - -- init.lua. If you want these files, they are in the repository, so you can just download them and - -- place them in the correct locations. - - -- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart - -- - -- Here are some example plugins that I've included in the Kickstart repository. - -- Uncomment any of the lines below to enable them (you will need to restart nvim). - -- - -- require 'kickstart.plugins.debug', - -- require 'kickstart.plugins.indent_line', - -- require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', - -- require 'kickstart.plugins.neo-tree', - -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommend keymaps - - -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` - -- This is the easiest way to modularize your config. - -- - -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- { import = 'custom.plugins' }, - -- - -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` - -- Or use telescope! - -- In normal mode type `sh` then write `lazy.nvim-plugin` - -- you can continue same window with `sr` which resumes last telescope search -}, { - ui = { - -- If you are using a Nerd Font: set icons to an empty table which will use the - -- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table - icons = vim.g.have_nerd_font and {} or { - cmd = '⌘', - config = '🛠', - event = '📅', - ft = '📂', - init = '⚙', - keys = '🗝', - plugin = '🔌', - runtime = '💻', - require = '🌙', - source = '📄', - start = '🚀', - task = '📌', - lazy = '💤 ', - }, - }, -}) - --- The line beneath this is called `modeline`. See `:help modeline` --- vim: ts=2 sts=2 sw=2 et +require 'setup.keymap' +require 'setup.autocmds' +require 'setup.set' +require 'setup.lazy' +require 'setup.lsp' diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 00000000000..df7df4e461c --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,57 @@ +{ + "CopilotChat.nvim": { "branch": "main", "commit": "9fec6c3c2a4069b1f649e116c10e6fbcf1463764" }, + "LuaSnip": { "branch": "master", "commit": "5a1e39223db9a0498024a77b8441169d260c8c25" }, + "Unreal-Nvim": { "branch": "main", "commit": "b0991bbd83645717cc0b3c98dd1fbf6ee7684c25" }, + "blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" }, + "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, + "cmake-tools.nvim": { "branch": "master", "commit": "906fd4816bf4d588162d5ec78830456f0d969c5f" }, + "codecompanion.nvim": { "branch": "main", "commit": "78203ccaa36469b4a212123c7d532e2367ad9dd4" }, + "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, + "copilot.lua": { "branch": "master", "commit": "e8b9be2e51c393bedc893cef3bd1c5555a4d45f5" }, + "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, + "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "50c205548d8b037b7ff6378fca6d21146f0b6161" }, + "gruvbox.nvim": { "branch": "main", "commit": "334d5fd49fc8033f26408425366c66c6390c57bb" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "log-highlight.nvim": { "branch": "main", "commit": "ca88628f6dd3b9bb46f9a7401669e24cf7de47a4" }, + "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "38499e0bda64bc0f3ec6e7f03f8e13dd11c0fa00" }, + "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, + "mini.ai": { "branch": "main", "commit": "4b0a6207341d895b6cfe9bcb1e4d3e8607bfe4f4" }, + "neo-tree.nvim": { "branch": "main", "commit": "84c75e7a7e443586f60508d12fc50f90d9aee14e" }, + "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, + "nvim-dap": { "branch": "master", "commit": "2a8799ad91a1495c6bdf753f9b2179b3ff0f5bba" }, + "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, + "nvim-dap-ui": { "branch": "master", "commit": "f5b6673f374626515401c5bc51b005f784a4f252" }, + "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, + "nvim-highlight-colors": { "branch": "main", "commit": "e2cb22089cc2358b2b995c09578224f142de6039" }, + "nvim-lint": { "branch": "master", "commit": "4b03656c09c1561f89b6aa0665c15d292ba9499d" }, + "nvim-lspconfig": { "branch": "master", "commit": "16812abf0e8d8175155f26143a8504e8253e92b0" }, + "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, + "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" }, + "nvim-surround": { "branch": "main", "commit": "61319d4bd1c5e336e197defa15bd104c51f0fb29" }, + "nvim-treesitter": { "branch": "main", "commit": "7caec274fd19c12b55902a5b795100d21531391f" }, + "nvim-treesitter-context": { "branch": "master", "commit": "adf4b6b0420b7be6c717ef0ac7993183d6c201b1" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "93d60a475f0b08a8eceb99255863977d3a25f310" }, + "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "render-markdown.nvim": { "branch": "main", "commit": "e3c18ddd27a853f85a6f513a864cf4f2982b9f26" }, + "smart-splits.nvim": { "branch": "master", "commit": "12426763591f06b865c20990d8423345ea96d44f" }, + "snacks.nvim": { "branch": "main", "commit": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, + "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, + "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, + "treesj": { "branch": "main", "commit": "26bc2a8432ba3ea79ed6aa346fba780a3d372570" }, + "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, + "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/lsp/basedpyright.lua b/lsp/basedpyright.lua new file mode 100644 index 00000000000..578c163f1d4 --- /dev/null +++ b/lsp/basedpyright.lua @@ -0,0 +1,137 @@ +local machine = require('machine') + +local function set_python_path(path) + local clients = vim.lsp.get_clients { + bufnr = vim.api.nvim_get_current_buf(), + name = 'basedpyright', + } + for _, client in ipairs(clients) do + client.config.settings = vim.tbl_deep_extend('force', client.config.settings or {}, { python = { pythonPath = path } }) + if client.settings then + client.settings.python = vim.tbl_deep_extend('force', client.settings.python or {}, { pythonPath = path }) + end + client.notify('workspace/didChangeConfiguration', { settings = client.config.settings }) + end +end + +local function is_ue_project() + local ok, unreal_nvim = pcall(require, 'unreal-nvim') + if ok and unreal_nvim.find_uproject and unreal_nvim.find_uproject() then + return true + end + return vim.fn.glob(vim.fn.getcwd() .. '/*.uproject') ~= '' +end + +local function get_python_path() + local venv_path = os.getenv 'VIRTUAL_ENV' + if venv_path then + return venv_path .. '/scripts/python.exe' + end + if is_ue_project() then + local ue_python = machine.get('ue_python', nil) + if ue_python then return ue_python end + end + local python_on_path = vim.fn.exepath('python') + return python_on_path ~= '' and python_on_path or 'python' +end + +local function get_current_ue_python_stub() + local ok, unreal_nvim = pcall(require, 'unreal-nvim') + if not ok then return '' end + local ue_project = unreal_nvim.find_uproject() + if ue_project then + local ue_folder = ue_project:match '^(.*[\\/])' + return ue_folder .. 'Intermediate\\PythonStub' + end + return '' +end + +local function get_ue_python_plugins() + local ok, unreal_nvim = pcall(require, 'unreal-nvim') + if not ok then return {} end + local folders = {} + local ue_project = unreal_nvim.find_uproject() + if ue_project then + local ue_folder = ue_project:match '^(.*[\\/])' + local ue_plugins = ue_folder .. 'Plugins\\' + local handle = vim.uv.fs_scandir(ue_plugins) + if not handle then return folders end + while true do + local name, t = vim.uv.fs_scandir_next(handle) + if not name then break end + if t == 'directory' then + local plugin_folder = ue_plugins .. name .. '\\Content\\Python' + local stat = vim.uv.fs_stat(plugin_folder) + if stat ~= nil and stat.type == 'directory' then + table.insert(folders, plugin_folder) + end + end + end + end + return folders +end + +-- Called lazily at server start, not at file load time +local function get_extra_paths() + local paths = { + get_current_ue_python_stub(), + 'C:/venvs/python_extras/Lib/site-packages', + } + vim.list_extend(paths, get_ue_python_plugins()) + return paths +end + +return { + cmd = { machine.get('basedpyright', vim.fn.exepath('basedpyright-langserver')), '--stdio' }, + filetypes = { 'python' }, + root_markers = { + 'pyproject.toml', + 'setup.py', + 'setup.cfg', + 'requirements.txt', + 'Pipfile', + 'pyrightconfig.json', + '.git', + }, + before_init = function(_, config) + -- Settings are computed here, after plugins are loaded + config.settings = vim.tbl_deep_extend('force', config.settings or {}, { + python = { + pythonPath = get_python_path(), + }, + basedpyright = { + disableOrganizeImports = true, + analysis = { + diagnosticSeverityOverrides = { + reportUnannotatedClassAttribute = false, + reportUnusedCallResult = false, + reportAny = false, + }, + autoImportCompletions = true, + autoSearchPaths = true, + useLibraryCodeForTypes = true, + diagnosticMode = 'openFilesOnly', + extraPaths = get_extra_paths(), + }, + }, + }) + end, + on_attach = function(client, bufnr) + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightOrganizeImports', function() + client:exec_cmd { + command = 'basedpyright.organizeimports', + arguments = { vim.uri_from_bufnr(bufnr) }, + } + end, { desc = 'Organize Imports' }) + + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightSetPythonPath', function(opts) + set_python_path(opts.args) + end, { + desc = 'Reconfigure basedpyright with the provided python path', + nargs = 1, + complete = 'file', + }) + + vim.keymap.set('n', 'pi', 'LspPyrightOrganizeImports', { buffer = bufnr, desc = '[P]ython Organize [I]mports' }) + end, +} diff --git a/lsp/clangd.lua b/lsp/clangd.lua new file mode 100644 index 00000000000..e38bc9556b2 --- /dev/null +++ b/lsp/clangd.lua @@ -0,0 +1,92 @@ +local machine = require('machine') + +local function switch_source_header(bufnr) + local method_name = 'textDocument/switchSourceHeader' + local client = vim.lsp.get_clients({ bufnr = bufnr, name = 'clangd' })[1] + if not client then + return vim.notify(('method %s is not supported by any servers active on the current buffer'):format(method_name)) + end + local params = vim.lsp.util.make_text_document_params(bufnr) + client.request(method_name, params, function(err, result) + if err then + vim.notify(tostring(err), vim.log.levels.ERROR) + return + end + if not result then + vim.notify 'corresponding file cannot be determined' + return + end + vim.cmd.edit(vim.uri_to_fname(result)) + end, bufnr) +end + +local function symbol_info() + local bufnr = vim.api.nvim_get_current_buf() + local clangd_client = vim.lsp.get_clients({ bufnr = bufnr, name = 'clangd' })[1] + if not clangd_client or not clangd_client.supports_method 'textDocument/symbolInfo' then + return vim.notify('Clangd client not found', vim.log.levels.ERROR) + end + local win = vim.api.nvim_get_current_win() + local params = vim.lsp.util.make_position_params(win, clangd_client.offset_encoding) + clangd_client.request('textDocument/symbolInfo', params, function(err, res) + if err or not res or #res == 0 then + -- Clangd always returns an error, there is not reason to parse it + return + end + local container = string.format('container: %s', res[1].containerName) ---@type string + local name = string.format('name: %s', res[1].name) ---@type string + vim.lsp.util.open_floating_preview({ name, container }, '', { + height = 2, + width = math.max(string.len(name), string.len(container)), + focusable = false, + focus = false, + border = 'single', + title = 'Symbol Info', + }) + end, bufnr) +end + +---@class ClangdInitializeResult: lsp.InitializeResult +---@field offsetEncoding? string + +return { + cmd = { machine.get('clangd', vim.fn.exepath('clangd')) }, + filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' }, + root_markers = { + '.clangd', + '.clang-tidy', + '.clang-format', + 'compile_commands.json', + 'compile_flags.txt', + 'configure.ac', -- AutoTools + '.git', + }, + capabilities = { + textDocument = { + completion = { + editsNearCursor = true, + }, + }, + offsetEncoding = { 'utf-8', 'utf-16' }, + }, + ---@param client vim.lsp.Client + ---@param init_result ClangdInitializeResult + on_init = function(client, init_result) + if init_result.offsetEncoding then + client.offset_encoding = init_result.offsetEncoding + end + end, + on_attach = function(_, bufnr) + vim.api.nvim_buf_create_user_command(bufnr, 'LspClangdSwitchSourceHeader', function() + switch_source_header(bufnr) + end, { desc = 'Switch between source/header' }) + + vim.api.nvim_buf_create_user_command(bufnr, 'LspClangdShowSymbolInfo', function() + symbol_info() + end, { desc = 'Show symbol info' }) + + vim.keymap.set('n', 'ch', function() + switch_source_header(bufnr) + end, { buffer = bufnr, desc = '[C]langd Switch [H]eader/Source' }) + end, +} diff --git a/lsp/lua_ls.lua b/lsp/lua_ls.lua new file mode 100644 index 00000000000..947e6419a1e --- /dev/null +++ b/lsp/lua_ls.lua @@ -0,0 +1,14 @@ +return { + cmd = { 'lua-language-server' }, + filetypes = { 'lua' }, + root_markers = { + '.luarc.json', + '.luarc.jsonc', + '.luacheckrc', + '.stylua.toml', + 'stylua.toml', + 'selene.toml', + 'selene.yml', + '.git', + }, +} diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua deleted file mode 100644 index be0eb9d8d7a..00000000000 --- a/lua/custom/plugins/init.lua +++ /dev/null @@ -1,5 +0,0 @@ --- You can add your own plugins here or in other files in this directory! --- I promise not to create any merge conflicts in this directory :) --- --- See the kickstart.nvim README for more information -return {} diff --git a/lua/kickstart/health.lua b/lua/kickstart/health.lua deleted file mode 100644 index b59d08649af..00000000000 --- a/lua/kickstart/health.lua +++ /dev/null @@ -1,52 +0,0 @@ ---[[ --- --- This file is not required for your own configuration, --- but helps people determine if their system is setup correctly. --- ---]] - -local check_version = function() - local verstr = tostring(vim.version()) - if not vim.version.ge then - vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr)) - return - end - - if vim.version.ge(vim.version(), '0.10-dev') then - vim.health.ok(string.format("Neovim version is: '%s'", verstr)) - else - vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr)) - end -end - -local check_external_reqs = function() - -- Basic utils: `git`, `make`, `unzip` - for _, exe in ipairs { 'git', 'make', 'unzip', 'rg' } do - local is_executable = vim.fn.executable(exe) == 1 - if is_executable then - vim.health.ok(string.format("Found executable: '%s'", exe)) - else - vim.health.warn(string.format("Could not find executable: '%s'", exe)) - end - end - - return true -end - -return { - check = function() - vim.health.start 'kickstart.nvim' - - vim.health.info [[NOTE: Not every warning is a 'must-fix' in `:checkhealth` - - Fix only warnings for plugins and languages you intend to use. - Mason will give warnings for languages that are not installed. - You do not need to install, unless you want to use those languages!]] - - local uv = vim.uv or vim.loop - vim.health.info('System Information: ' .. vim.inspect(uv.os_uname())) - - check_version() - check_external_reqs() - end, -} diff --git a/lua/machine.lua b/lua/machine.lua new file mode 100644 index 00000000000..e224a8b6067 --- /dev/null +++ b/lua/machine.lua @@ -0,0 +1,30 @@ +-- machine.lua +-- Loads machine-specific paths from machine.json in the config directory. +-- Copy machine.json.template to machine.json and fill in your paths. +local M = {} + +local _cache = nil + +local function load() + local path = vim.fn.stdpath('config') .. '/machine.json' + local f = io.open(path, 'r') + if not f then return {} end + local content = f:read('*a') + f:close() + local ok, data = pcall(vim.fn.json_decode, content) + return (ok and type(data) == 'table') and data or {} +end + +--- Get a machine-specific path by key. +--- Falls back to `fallback` if the key is missing or empty. +---@param key string +---@param fallback string|nil +---@return string|nil +function M.get(key, fallback) + if not _cache then _cache = load() end + local val = _cache[key] + if val and val ~= '' then return val end + return fallback +end + +return M diff --git a/lua/kickstart/plugins/autopairs.lua b/lua/plugins/autopairs.lua similarity index 100% rename from lua/kickstart/plugins/autopairs.lua rename to lua/plugins/autopairs.lua diff --git a/lua/plugins/blink.lua b/lua/plugins/blink.lua new file mode 100644 index 00000000000..d11466b9999 --- /dev/null +++ b/lua/plugins/blink.lua @@ -0,0 +1,56 @@ +return { + 'saghen/blink.cmp', + event = 'InsertEnter', + version = '1.*', + dependencies = { + { + 'L3MON4D3/LuaSnip', + version = '2.*', + build = (function() + if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then + return + end + return 'make install_jsregexp' + end)(), + dependencies = { + { + 'rafamadriz/friendly-snippets', + config = function() + require('luasnip.loaders.from_vscode').lazy_load() + end, + }, + }, + opts = {}, + }, + 'folke/lazydev.nvim', + 'zbirenbaum/copilot.lua', + 'giuxtaposition/blink-cmp-copilot', + }, + opts = { + -- 'default' (recommended) for mappings similar to built-in completions (C-y to accept) + -- 'super-tab' for mappings similar to vscode (tab to accept) + -- 'enter' for enter to accept + -- 'none' for no mappings + keymap = { preset = 'default' }, + + -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' + -- Adjusts spacing to ensure icons are aligned + appearance = { nerd_font_variant = 'mono' }, + completion = { + documentation = { auto_show = false, auto_show_delay_ms = 200 }, + }, + sources = { + default = { 'lsp', 'path', 'snippets', 'lazydev', 'buffer', 'copilot' }, + providers = { + lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 }, + copilot = { module = 'blink-cmp-copilot', score_offset = 100, async = true }, + }, + }, + snippets = { preset = 'luasnip' }, + -- (Default) Rust fuzzy matcher for typo resistance and significantly better performance + -- You may use a lua implementation instead by using `implementation = "lua"` or fallback to the lua implementation, + -- when the Rust fuzzy matcher is not available, by using `implementation = "prefer_rust"` + fuzzy = { implementation = 'prefer_rust_with_warning' }, + signature = { enabled = true }, + }, +} diff --git a/lua/plugins/cmake-tools.lua b/lua/plugins/cmake-tools.lua new file mode 100644 index 00000000000..650d3050ca1 --- /dev/null +++ b/lua/plugins/cmake-tools.lua @@ -0,0 +1,13 @@ +return { + 'Civitasv/cmake-tools.nvim', + dependencies = { 'nvim-lua/plenary.nvim' }, + ft = { 'c', 'cpp' }, + keys = { + { 'cmg', 'CMakeGenerate', desc = '[C]Make [G]enerate' }, + { 'cmb', 'CMakeBuild', desc = '[C]Make [B]uild' }, + { 'cmr', 'CMakeRun', desc = '[C]Make [R]un' }, + { 'cmd', 'CMakeDebug', desc = '[C]Make [D]ebug' }, + { 'cms', 'CMakeStop', desc = '[C]Make [S]top' }, + }, + opts = {}, +} diff --git a/lua/plugins/codecompanion.lua b/lua/plugins/codecompanion.lua new file mode 100644 index 00000000000..88a75c79c85 --- /dev/null +++ b/lua/plugins/codecompanion.lua @@ -0,0 +1,51 @@ +return { + 'olimorris/codecompanion.nvim', + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-treesitter/nvim-treesitter', + }, + config = function() + require('codecompanion').setup { + adapters = { + ollama = function() + return require('codecompanion.adapters').extend('ollama', { + schema = { + model = { + default = 'deepseek-coder-v2:16b', + }, + }, + }) + end, + }, + strategies = { + chat = { adapter = 'ollama' }, + inline = { adapter = 'ollama' }, + }, + prompt_library = { + ['Generate Docstring'] = { + interaction = 'inline', + description = 'Generate a docstring for the selected code', + opts = { + alias = 'doc', + placement = 'before', + modes = { 'v' }, + }, + prompts = { + { + role = 'user', + content = function(context) + return 'Write only the docstring comment for the following code, no explanation, no markdown, just the comment:\n\n' .. context.code + end, + }, + }, + }, + }, + } + end, + keys = { + { 'cc', 'CodeCompanionChat Toggle', desc = '[C]ode [C]ompanion Chat' }, + { 'ca', 'CodeCompanionActions', mode = { 'n', 'v' }, desc = '[C]ode [A]ctions' }, + { 'cd', 'CodeCompanion /doc', mode = 'v', desc = '[C]ode [D]ocstring' }, + }, +} + diff --git a/lua/plugins/colorscheme.lua b/lua/plugins/colorscheme.lua new file mode 100644 index 00000000000..d2a5f96fdc8 --- /dev/null +++ b/lua/plugins/colorscheme.lua @@ -0,0 +1,11 @@ +-- Colorscheme +return { + 'ellisonleao/gruvbox.nvim', + priority = 1000, + config = function() + require('gruvbox').setup { + contrast = 'hard', + } + vim.cmd.colorscheme 'gruvbox' + end, +} diff --git a/lua/plugins/conform.lua b/lua/plugins/conform.lua new file mode 100644 index 00000000000..275f3a19fe7 --- /dev/null +++ b/lua/plugins/conform.lua @@ -0,0 +1,43 @@ +return { + 'stevearc/conform.nvim', + event = { 'BufWritePre' }, + cmd = { 'ConformInfo' }, + keys = { + { + 'f', + function() + require('conform').format { async = true, lsp_format = 'fallback' } + end, + mode = '', + desc = '[F]ormat buffer', + }, + }, + opts = { + notify_on_error = false, + format_on_save = function(bufnr) + local disable_filetypes = {} + if disable_filetypes[vim.bo[bufnr].filetype] then + return nil + else + return { + timeout_ms = 500, + lsp_format = 'fallback', + } + end + end, + formatters_by_ft = { + lua = { 'stylua' }, + c = { 'clang_format' }, + cpp = { 'clang_format' }, + python = { 'ruff_format', 'ruff_organize_imports' }, + javascript = { 'prettier' }, + typescript = { 'prettier' }, + javascriptreact = { 'prettier' }, + typescriptreact = { 'prettier' }, + json = { 'prettier' }, + html = { 'prettier' }, + css = { 'prettier' }, + markdown = { 'prettier' }, + }, + }, +} diff --git a/lua/plugins/copilot-chat.lua b/lua/plugins/copilot-chat.lua new file mode 100644 index 00000000000..0be736bf870 --- /dev/null +++ b/lua/plugins/copilot-chat.lua @@ -0,0 +1,13 @@ +return { + 'CopilotC-Nvim/CopilotChat.nvim', + cmd = { 'CopilotChat', 'CopilotChatToggle', 'CopilotChatOpen' }, + dependencies = { + 'zbirenbaum/copilot.lua', + 'nvim-lua/plenary.nvim', + }, + opts = { + window = { + layout = 'vertical', + }, + }, +} diff --git a/lua/plugins/copilot.lua b/lua/plugins/copilot.lua new file mode 100644 index 00000000000..ce6cd95488e --- /dev/null +++ b/lua/plugins/copilot.lua @@ -0,0 +1,10 @@ +return { + { + 'zbirenbaum/copilot.lua', + event = 'InsertEnter', + opts = { + suggestion = { enabled = false }, -- handled by blink.cmp + panel = { enabled = false }, + }, + }, +} diff --git a/lua/kickstart/plugins/debug.lua b/lua/plugins/debug.lua similarity index 76% rename from lua/kickstart/plugins/debug.lua rename to lua/plugins/debug.lua index 8e332bf2ff9..af802d77359 100644 --- a/lua/kickstart/plugins/debug.lua +++ b/lua/plugins/debug.lua @@ -22,7 +22,8 @@ return { 'jay-babu/mason-nvim-dap.nvim', -- Add your own debuggers here - 'leoluz/nvim-dap-go', + 'theHamsta/nvim-dap-virtual-text', + 'mfussenegger/nvim-dap-python', }, keys = { -- Basic debugging keymaps, feel free to change to your liking! @@ -94,10 +95,41 @@ return { -- online, please don't ask me how to install them :) ensure_installed = { -- Update this to ensure that you have the debuggers for the langs you want - 'delve', + 'codelldb', -- C/C++/Unreal Engine debugging + 'debugpy', -- Python debugging }, } + -- Configure Python debugger using Mason-installed debugpy + local function setup_dap_python() + local ok2, reg = pcall(require, 'mason-registry') + if not ok2 then return end + if not reg.is_installed('debugpy') then return end + local debugpy_path = reg.get_package('debugpy'):get_install_path() + -- Windows uses Scripts/, Unix uses bin/ + local python_exec = debugpy_path .. '/venv/Scripts/python.exe' + if vim.fn.filereadable(python_exec) == 0 then + python_exec = debugpy_path .. '/venv/bin/python' + end + require('dap-python').setup(python_exec) + end + + -- Configure immediately if already installed + setup_dap_python() + + -- Also configure when debugpy finishes installing on first run + local ok_reg, reg2 = pcall(require, 'mason-registry') + if ok_reg then + reg2:on('package:install:success', function(pkg) + if pkg.name == 'debugpy' then + vim.schedule(setup_dap_python) + end + end) + end + + -- Configure virtual text for DAP + require('nvim-dap-virtual-text').setup() + -- Dap UI setup -- For more information, see |:help nvim-dap-ui| dapui.setup { @@ -136,13 +168,5 @@ return { dap.listeners.before.event_terminated['dapui_config'] = dapui.close dap.listeners.before.event_exited['dapui_config'] = dapui.close - -- Install golang specific config - require('dap-go').setup { - delve = { - -- On Windows delve must be run attached or it crashes. - -- See https://github.com/leoluz/nvim-dap-go/blob/main/README.md#configuring - detached = vim.fn.has 'win32' == 0, - }, - } end, } diff --git a/lua/plugins/fugitive.lua b/lua/plugins/fugitive.lua new file mode 100644 index 00000000000..8083b81e9fc --- /dev/null +++ b/lua/plugins/fugitive.lua @@ -0,0 +1,11 @@ +return { + 'tpope/vim-fugitive', + cmd = { 'Git', 'G' }, + keys = { + { 'gs', 'Git', desc = '[G]it [S]tatus' }, + { 'gd', 'Gdiffsplit', desc = '[G]it [D]iff' }, + { 'gb', 'Git blame', desc = '[G]it [B]lame' }, + { 'gl', 'Git log', desc = '[G]it [L]og' }, + { 'gp', 'Git push', desc = '[G]it [P]ush' }, + }, +} diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/plugins/gitsigns.lua similarity index 85% rename from lua/kickstart/plugins/gitsigns.lua rename to lua/plugins/gitsigns.lua index cbbd22d24fc..ca9b055cee4 100644 --- a/lua/kickstart/plugins/gitsigns.lua +++ b/lua/plugins/gitsigns.lua @@ -44,9 +44,10 @@ return { 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', 'hu', gitsigns.stage_hunk, { desc = 'git [u]ndo stage hunk' }) + map('n', 'hu', gitsigns.undo_stage_hunk, { desc = 'git [u]ndo stage hunk' }) map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) + map('n', 'hP', gitsigns.preview_hunk_inline, { desc = 'git [P]review hunk inline' }) map('n', 'hb', gitsigns.blame_line, { desc = 'git [b]lame line' }) map('n', 'hd', gitsigns.diffthis, { desc = 'git [d]iff against index' }) map('n', 'hD', function() @@ -54,7 +55,8 @@ return { end, { desc = 'git [D]iff against last commit' }) -- Toggles map('n', 'tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) - map('n', 'tD', gitsigns.preview_hunk_inline, { desc = '[T]oggle git show [D]eleted' }) + map('n', 'tD', gitsigns.toggle_deleted, { desc = '[T]oggle git show [D]eleted' }) + map('n', 'tw', gitsigns.toggle_word_diff, { desc = '[T]oggle git [W]ord diff' }) end, }, }, diff --git a/lua/plugins/highlight-colors.lua b/lua/plugins/highlight-colors.lua new file mode 100644 index 00000000000..6217484a599 --- /dev/null +++ b/lua/plugins/highlight-colors.lua @@ -0,0 +1,9 @@ +return { + 'brenoprata10/nvim-highlight-colors', + event = 'BufReadPre', + opts = { + render = 'background', -- or 'foreground' or 'first_column' + enable_named_colors = true, + enable_tailwind = false, -- set true if you ever use Tailwind + }, +} diff --git a/lua/kickstart/plugins/indent_line.lua b/lua/plugins/indent_line.lua similarity index 78% rename from lua/kickstart/plugins/indent_line.lua rename to lua/plugins/indent_line.lua index ed7f269399f..240f3d0864d 100644 --- a/lua/kickstart/plugins/indent_line.lua +++ b/lua/plugins/indent_line.lua @@ -4,6 +4,8 @@ return { -- Enable `lukas-reineke/indent-blankline.nvim` -- See `:help ibl` main = 'ibl', - opts = {}, + opts = { + scope = { enabled = false }, + }, }, } diff --git a/lua/plugins/lazy-dev.lua b/lua/plugins/lazy-dev.lua new file mode 100644 index 00000000000..b4ae793c350 --- /dev/null +++ b/lua/plugins/lazy-dev.lua @@ -0,0 +1,9 @@ +return { + 'folke/lazydev.nvim', + ft = 'lua', + opts = { + library = { + { path = '${3rd}/luv/library', words = { 'vim%.uv' } }, + }, + }, +} diff --git a/lua/kickstart/plugins/lint.lua b/lua/plugins/lint.lua similarity index 98% rename from lua/kickstart/plugins/lint.lua rename to lua/plugins/lint.lua index dec42f097c6..ecdf36f4078 100644 --- a/lua/kickstart/plugins/lint.lua +++ b/lua/plugins/lint.lua @@ -7,6 +7,7 @@ return { local lint = require 'lint' lint.linters_by_ft = { markdown = { 'markdownlint' }, + python = { 'ruff' }, } -- To allow other plugins to add linters to require('lint').linters_by_ft, diff --git a/lua/plugins/log-highlight.lua b/lua/plugins/log-highlight.lua new file mode 100644 index 00000000000..eb7030c9285 --- /dev/null +++ b/lua/plugins/log-highlight.lua @@ -0,0 +1,4 @@ +return { + 'fei6409/log-highlight.nvim', + opts = {}, +} diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua new file mode 100644 index 00000000000..e2c8e9bfde7 --- /dev/null +++ b/lua/plugins/lsp.lua @@ -0,0 +1,78 @@ +return { + 'neovim/nvim-lspconfig', -- still needed for default server configs + dependencies = { + 'saghen/blink.cmp', + { 'j-hui/fidget.nvim', opts = {} }, + }, + config = function() + -- Inject blink.cmp capabilities into ALL servers globally. + -- This replaces what the old mason-lspconfig handler was doing per-server. + vim.lsp.config('*', { + capabilities = require('blink.cmp').get_lsp_capabilities(), + }) + + local detach_augroup = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }) + + -- LspAttach: keymaps only. Server setup is handled by vim.lsp.enable in setup/lsp.lua + 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('grr', function() require('telescope.builtin').lsp_references() end, '[G]oto [R]eferences') + map('gri', function() require('telescope.builtin').lsp_implementations() end, '[G]oto [I]mplementation') + map('grd', function() require('telescope.builtin').lsp_definitions() end, '[G]oto [D]efinition') + map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + map('gO', function() require('telescope.builtin').lsp_document_symbols() end, 'Open Document Symbols') + map('gW', function() require('telescope.builtin').lsp_dynamic_workspace_symbols() end, 'Open Workspace Symbols') + map('grt', function() require('telescope.builtin').lsp_type_definitions() end, '[G]oto [T]ype Definition') + map('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') + map('K', vim.lsp.buf.hover, 'Hover Documentation') + map('n', vim.lsp.buf.rename, '[R]e[n]ame') + + local function client_supports_method(client, method, bufnr) + if vim.fn.has 'nvim-0.11' == 1 then + return client:supports_method(method, bufnr) + else + return client.supports_method(method, { bufnr = bufnr }) + end + end + + local client = vim.lsp.get_client_by_id(event.data.client_id) + + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then + local hl_group = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) + vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { + buffer = event.buf, + group = hl_group, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { + buffer = event.buf, + group = hl_group, + callback = vim.lsp.buf.clear_references, + }) + vim.api.nvim_create_autocmd('LspDetach', { + group = detach_augroup, + buffer = event.buf, + callback = function(event2) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } + end, + }) + end + + if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then + map('lh', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) + end, '[L]SP Toggle Inlay [H]ints') + end + end, + }) + end, +} diff --git a/lua/plugins/lualine.lua b/lua/plugins/lualine.lua new file mode 100644 index 00000000000..5b3e4acd41a --- /dev/null +++ b/lua/plugins/lualine.lua @@ -0,0 +1,13 @@ +-- Set lualine as statusline +return { + 'nvim-lualine/lualine.nvim', + -- See `:help lualine.txt` + opts = { + options = { + icons_enabled = true, + theme = 'gruvbox', + component_separators = '|', + section_separators = '', + }, + }, +} diff --git a/lua/plugins/mason.lua b/lua/plugins/mason.lua new file mode 100644 index 00000000000..54768c9bfda --- /dev/null +++ b/lua/plugins/mason.lua @@ -0,0 +1,38 @@ +return { + { + 'mason-org/mason.nvim', + opts = {}, + }, + { + 'WhoIsSethDaniel/mason-tool-installer.nvim', + dependencies = { + 'mason-org/mason.nvim', + 'mason-org/mason-lspconfig.nvim', + }, + config = function() + -- mason-lspconfig only for name-mapping / install bridging, NOT for server setup + require('mason-lspconfig').setup { + ensure_installed = {}, + automatic_installation = false, + } + + require('mason-tool-installer').setup { + ensure_installed = { + -- LSP servers (mason package names) + 'lua-language-server', + 'basedpyright', + 'clangd', + 'typescript-language-server', + 'css-lsp', + 'html-lsp', + -- Formatters / linters + 'stylua', + 'prettier', + 'ruff', + 'clang-format', + 'markdownlint', + }, + } + end, + }, +} diff --git a/lua/plugins/mini-ai.lua b/lua/plugins/mini-ai.lua new file mode 100644 index 00000000000..ec5af933ad8 --- /dev/null +++ b/lua/plugins/mini-ai.lua @@ -0,0 +1,5 @@ +return { + 'echasnovski/mini.ai', + event = 'VeryLazy', + opts = { n_lines = 500 }, +} diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/plugins/neo-tree.lua similarity index 97% rename from lua/kickstart/plugins/neo-tree.lua rename to lua/plugins/neo-tree.lua index c7067891df0..2a271eb7387 100644 --- a/lua/kickstart/plugins/neo-tree.lua +++ b/lua/plugins/neo-tree.lua @@ -9,7 +9,7 @@ return { 'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended 'MunifTanjim/nui.nvim', }, - lazy = false, + lazy = true, keys = { { '\\', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, }, diff --git a/lua/plugins/noice.lua b/lua/plugins/noice.lua new file mode 100644 index 00000000000..abaa47457b3 --- /dev/null +++ b/lua/plugins/noice.lua @@ -0,0 +1,33 @@ +return { + 'folke/noice.nvim', + event = 'VeryLazy', + dependencies = { + 'MunifTanjim/nui.nvim', + 'rcarriga/nvim-notify', + }, + opts = { + lsp = { + override = { + ['vim.lsp.util.convert_input_to_markdown_lines'] = true, + ['vim.lsp.util.stylize_markdown'] = true, + ['cmp.entry.get_documentation'] = true, + }, + signature = { + enabled = false, + }, + }, + presets = { + -- bottom_search = true, -- classic search bar at bottom + -- command_palette = true, -- command line + popupmenu together + long_message_to_split = true, + lsp_doc_border = true, + }, + routes = { + -- suppress annoying "written" message on save + { + filter = { event = 'msg_show', kind = '', find = 'written' }, + opts = { skip = true }, + }, + }, + }, +} diff --git a/lua/plugins/render-markdown.lua b/lua/plugins/render-markdown.lua new file mode 100644 index 00000000000..fd460976c0e --- /dev/null +++ b/lua/plugins/render-markdown.lua @@ -0,0 +1,6 @@ +-- Beautiful markdown +return { + 'MeanderingProgrammer/render-markdown.nvim', + ft = { 'markdown', 'md' }, + opts = {}, +} diff --git a/lua/plugins/smart-splits.lua b/lua/plugins/smart-splits.lua new file mode 100644 index 00000000000..37b40ea6a83 --- /dev/null +++ b/lua/plugins/smart-splits.lua @@ -0,0 +1,28 @@ +return { + 'mrjones2014/smart-splits.nvim', + keys = { + { '', mode = 'n', desc = 'Move focus to the left window' }, + { '', mode = 'n', desc = 'Move focus to the lower window' }, + { '', mode = 'n', desc = 'Move focus to the upper window' }, + { '', mode = 'n', desc = 'Move focus to the right window' }, + { '', mode = 'n', desc = 'Resize split left' }, + { '', mode = 'n', desc = 'Resize split down' }, + { '', mode = 'n', desc = 'Resize split up' }, + { '', mode = 'n', desc = 'Resize split right' }, + }, + config = function() + local ss = require 'smart-splits' + + -- Moving between splits + vim.keymap.set('n', '', ss.move_cursor_left, { desc = 'Move focus to the left window' }) + vim.keymap.set('n', '', ss.move_cursor_down, { desc = 'Move focus to the lower window' }) + vim.keymap.set('n', '', ss.move_cursor_up, { desc = 'Move focus to the upper window' }) + vim.keymap.set('n', '', ss.move_cursor_right, { desc = 'Move focus to the right window' }) + + -- Resizing splits + vim.keymap.set('n', '', ss.resize_left, { desc = 'Resize split left' }) + vim.keymap.set('n', '', ss.resize_down, { desc = 'Resize split down' }) + vim.keymap.set('n', '', ss.resize_up, { desc = 'Resize split up' }) + vim.keymap.set('n', '', ss.resize_right, { desc = 'Resize split right' }) + end, +} diff --git a/lua/plugins/snacks.lua b/lua/plugins/snacks.lua new file mode 100644 index 00000000000..3885db58ae6 --- /dev/null +++ b/lua/plugins/snacks.lua @@ -0,0 +1,32 @@ +-- Folk Snacks +return { + 'folke/snacks.nvim', + priority = 1000, + lazy = false, + opts = { + bigfile = { enabled = true }, + dashboard = { enabled = true }, + indent = { enabled = true }, + input = { enabled = true }, + styles = { + input = { + relative = 'editor', + row = 20, + }, + }, + picker = { enabled = true }, + quickfile = { enabled = true }, + scope = { enabled = true }, + scroll = { enabled = false }, + words = { enabled = true }, + -- image = { + -- enabled = true, + -- resolve = function(path, src) + -- local api = require 'obsidian.api' + -- if api.path_is_note(path) then + -- return api.resolve_attachment_path(src) + -- end + -- end, + -- }, + }, +} diff --git a/lua/plugins/surround.lua b/lua/plugins/surround.lua new file mode 100644 index 00000000000..387dc9d4b53 --- /dev/null +++ b/lua/plugins/surround.lua @@ -0,0 +1,9 @@ +-- Surround +return { + 'kylechui/nvim-surround', + -- version = '*', -- Use for stability; omit to use `main` branch for the latest features + event = 'VeryLazy', + config = function() + require('nvim-surround').setup {} + end, +} diff --git a/lua/plugins/telescope-fuzzy-finder.lua b/lua/plugins/telescope-fuzzy-finder.lua new file mode 100644 index 00000000000..2137f740430 --- /dev/null +++ b/lua/plugins/telescope-fuzzy-finder.lua @@ -0,0 +1,67 @@ +return { + 'nvim-telescope/telescope.nvim', + cmd = { 'Telescope' }, + dependencies = { + 'nvim-lua/plenary.nvim', + { + 'nvim-telescope/telescope-fzf-native.nvim', + build = 'make', + cond = function() + return vim.fn.executable 'make' == 1 + end, + }, + { 'nvim-telescope/telescope-ui-select.nvim' }, + { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font }, + }, + keys = { + { 'sh', function() require('telescope.builtin').help_tags() end, desc = '[S]earch [H]elp' }, + { 'sk', function() require('telescope.builtin').keymaps() end, desc = '[S]earch [K]eymaps' }, + { 'sf', function() require('telescope.builtin').find_files() end, desc = '[S]earch [F]iles' }, + { 'ss', function() require('telescope.builtin').builtin() end, desc = '[S]earch [S]elect Telescope' }, + { 'sw', function() require('telescope.builtin').grep_string() end, desc = '[S]earch current [W]ord' }, + { 'sg', function() require('telescope.builtin').live_grep() end, desc = '[S]earch by [G]rep' }, + { 'sd', function() require('telescope.builtin').diagnostics() end, desc = '[S]earch [D]iagnostics' }, + { 'sr', function() require('telescope.builtin').resume() end, desc = '[S]earch [R]esume' }, + { 's.', function() require('telescope.builtin').oldfiles() end, desc = '[S]earch Recent Files' }, + { '', function() require('telescope.builtin').buffers() end, desc = '[ ] Find buffers' }, + { + '/', + function() + require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) + end, + desc = '[/] Search in current buffer', + }, + { + 's/', + function() + require('telescope.builtin').live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, + desc = '[S]earch [/] in Open Files', + }, + { + 'sn', + function() + require('telescope.builtin').find_files { cwd = vim.fn.stdpath 'config' } + end, + desc = '[S]earch [N]eovim files', + }, + }, + config = function() + require('telescope').setup { + extensions = { + ['ui-select'] = { + require('telescope.themes').get_dropdown(), + }, + }, + } + + pcall(require('telescope').load_extension, 'fzf') + pcall(require('telescope').load_extension, 'ui-select') + end, +} diff --git a/lua/plugins/todo-comments.lua b/lua/plugins/todo-comments.lua new file mode 100644 index 00000000000..15bc4f1ed00 --- /dev/null +++ b/lua/plugins/todo-comments.lua @@ -0,0 +1,6 @@ +return { + 'folke/todo-comments.nvim', + event = 'VimEnter', + dependencies = { 'nvim-lua/plenary.nvim' }, + opts = { signs = false }, +} diff --git a/lua/plugins/toggleterm.lua b/lua/plugins/toggleterm.lua new file mode 100644 index 00000000000..2626f8e36c0 --- /dev/null +++ b/lua/plugins/toggleterm.lua @@ -0,0 +1,41 @@ +return { + 'akinsho/toggleterm.nvim', + version = '*', + keys = { + { '', desc = 'Toggle terminal' }, + { 'tf', desc = 'Toggle floating terminal' }, + { 'th', desc = 'Toggle horizontal terminal' }, + }, + opts = { + size = function(term) + if term.direction == 'horizontal' then + return 15 + elseif term.direction == 'vertical' then + return vim.o.columns * 0.4 + end + end, + open_mapping = [[]], + direction = 'float', + float_opts = { + border = 'curved', + }, + shade_terminals = true, + }, + config = function(_, opts) + require('toggleterm').setup(opts) + + local Terminal = require('toggleterm.terminal').Terminal + + -- Floating terminal shortcut + local float_term = Terminal:new { direction = 'float' } + vim.keymap.set('n', 'tf', function() + float_term:toggle() + end, { desc = '[T]oggle [F]loating terminal' }) + + -- Horizontal terminal shortcut + local h_term = Terminal:new { direction = 'horizontal' } + vim.keymap.set('n', 'th', function() + h_term:toggle() + end, { desc = '[T]oggle [H]orizontal terminal' }) + end, +} diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 00000000000..a7879b26574 --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,48 @@ +return { + { + 'nvim-treesitter/nvim-treesitter', + build = ':TSUpdate', + dependencies = { + 'nvim-treesitter/nvim-treesitter-textobjects', + }, + opts = { + ensure_installed = { + 'bash', + 'c', + 'cpp', + 'diff', + 'html', + 'lua', + 'luadoc', + 'markdown', + 'markdown_inline', + 'query', + 'vim', + 'vimdoc', + 'python', + 'javascript', + 'typescript', + 'tsx', + 'json', + 'css', + 'glsl', + 'cmake', + 'hlsl', + 'ini', + }, + auto_install = true, + highlight = { + enable = true, + additional_vim_regex_highlighting = { 'ruby' }, + }, + indent = { enable = true, disable = { 'ruby' } }, + fold = { + enable = false, + }, + }, + }, + { + 'nvim-treesitter/nvim-treesitter-context', + opts = { max_lines = 2 }, + }, +} diff --git a/lua/plugins/treesj.lua b/lua/plugins/treesj.lua new file mode 100644 index 00000000000..457e177c9d7 --- /dev/null +++ b/lua/plugins/treesj.lua @@ -0,0 +1,8 @@ +return { + 'Wansmer/treesj', + keys = { 'm', 'j', 's' }, + dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` + config = function() + require('treesj').setup() + end, +} diff --git a/lua/plugins/unreal.lua b/lua/plugins/unreal.lua new file mode 100644 index 00000000000..122ecf4fcc2 --- /dev/null +++ b/lua/plugins/unreal.lua @@ -0,0 +1,42 @@ +-- Unreal +return { + 'PlayKigai/Unreal-Nvim', + cmd = { 'Unreal' }, + init = function() + local group = vim.api.nvim_create_augroup('UnrealAutoInit', { clear = true }) + local initialized = false + + local function try_init() + if initialized then return end + initialized = true + vim.api.nvim_del_augroup_by_id(group) + require('lazy').load { plugins = { 'Unreal-Nvim' } } + require('unreal-nvim').setup({}) + end + + -- Auto-init on explicit UE project/plugin/build files + vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + group = group, + pattern = { '*.uproject', '*.uplugin', '*.Build.cs', '*.Target.cs' }, + callback = try_init, + }) + + -- Auto-init on C++ files when a .uproject exists in cwd (UE source code) + vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufNewFile' }, { + group = group, + pattern = { '*.cpp', '*.h', '*.hpp', '*.c' }, + callback = function() + if vim.fn.glob(vim.fn.getcwd() .. '/*.uproject') ~= '' then + try_init() + end + end, + }) + end, + config = function() + -- Plugin is set up by try_init() above; this is only reached when + -- loaded manually via :Unreal or by the auto-init path. + vim.api.nvim_create_user_command('Unreal', function() + require('unreal-nvim').setup({}) + end, { desc = 'Manually initialize Unreal-Nvim' }) + end, +} diff --git a/lua/plugins/which-key.lua b/lua/plugins/which-key.lua new file mode 100644 index 00000000000..18fcf1e8701 --- /dev/null +++ b/lua/plugins/which-key.lua @@ -0,0 +1,53 @@ +return { + 'folke/which-key.nvim', + event = 'VeryLazy', + opts = { + delay = 0, + icons = { + mappings = vim.g.have_nerd_font, + keys = vim.g.have_nerd_font and {} or { + Up = ' ', + Down = ' ', + Left = ' ', + Right = ' ', + C = ' ', + M = ' ', + D = ' ', + S = ' ', + CR = ' ', + Esc = ' ', + ScrollWheelDown = ' ', + ScrollWheelUp = ' ', + NL = ' ', + BS = ' ', + Space = ' ', + Tab = ' ', + F1 = '', + F2 = '', + F3 = '', + F4 = '', + F5 = '', + F6 = '', + F7 = '', + F8 = '', + F9 = '', + F10 = '', + F11 = '', + F12 = '', + }, + }, + spec = { + { 's', group = '[S]earch' }, + { 't', group = '[T]oggle' }, + { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + { 'b', group = '[B]reakpoint' }, + { 'l', group = '[L]SP' }, + { 'g', group = '[G]it' }, + { 'c', group = '[C]ode / C++' }, + { 'd', group = '[D]ebug' }, + { 'r', group = '[R]un' }, + { 'u', group = '[U]nreal' }, + { 'a', group = '[A]I' }, + }, + }, +} diff --git a/lua/setup/autocmds.lua b/lua/setup/autocmds.lua new file mode 100644 index 00000000000..c7b1822c408 --- /dev/null +++ b/lua/setup/autocmds.lua @@ -0,0 +1,96 @@ +-- Shader file associations +vim.filetype.add { + extension = { + vert = 'glsl', + frag = 'glsl', + geom = 'glsl', + comp = 'glsl', + tesc = 'glsl', + tese = 'glsl', + }, +} + +-- Highlight on yank +vim.api.nvim_create_autocmd('TextYankPost', { + desc = 'Highlight when yanking text', + group = vim.api.nvim_create_augroup('highlight-yank', { clear = true }), + callback = function() + vim.hl.on_yank() + end, +}) + +-- Load project-local config +local uv = vim.uv or vim.loop + +local function load_project_config() + local config_file = vim.fn.getcwd() .. '/.nvim.lua' + if vim.fn.filereadable(config_file) ~= 1 then + return + end + + local stat = uv.fs_lstat(config_file) + if not (stat and stat.type == 'file') then + return + end + + local ok, err = pcall(dofile, config_file) + if not ok then + vim.notify('Error loading project config: ' .. err, vim.log.levels.WARN) + end +end + +vim.api.nvim_create_autocmd('VimEnter', { + desc = 'Load project-local .nvim.lua', + group = vim.api.nvim_create_augroup('project-local-config', { clear = true }), + callback = load_project_config, +}) + +-- Restore cursor to file position in previous editing session +vim.api.nvim_create_autocmd('BufReadPost', { + callback = function(args) + local mark = vim.api.nvim_buf_get_mark(args.buf, '"') + local line_count = vim.api.nvim_buf_line_count(args.buf) + if mark[1] > 0 and mark[1] <= line_count then + vim.api.nvim_win_set_cursor(0, mark) + vim.schedule(function() + vim.cmd 'normal! zz' + end) + end + end, +}) + +-- Open help in vertical split +vim.api.nvim_create_autocmd('FileType', { + pattern = 'help', + command = 'wincmd L', +}) + +-- Auto resize splits when the terminal's window is resized +vim.api.nvim_create_autocmd('VimResized', { + command = 'wincmd =', +}) + +-- No auto continue comments on new line +vim.api.nvim_create_autocmd('FileType', { + group = vim.api.nvim_create_augroup('no_auto_comment', { clear = true }), + callback = function() + vim.opt_local.formatoptions:remove { 'c', 'r', 'o' } + end, +}) + +-- Show cursorline only in active window (enable) +local cursorline_group = vim.api.nvim_create_augroup('active_cursorline', { clear = true }) +vim.api.nvim_create_autocmd({ 'WinEnter', 'BufEnter' }, { + group = cursorline_group, + callback = function() + vim.opt_local.cursorline = true + end, +}) + +-- Show cursorline only in active window (disable) +vim.api.nvim_create_autocmd({ 'WinLeave', 'BufLeave' }, { + group = cursorline_group, + callback = function() + vim.opt_local.cursorline = false + end, +}) diff --git a/lua/setup/keymap.lua b/lua/setup/keymap.lua new file mode 100644 index 00000000000..61d51259572 --- /dev/null +++ b/lua/setup/keymap.lua @@ -0,0 +1,60 @@ +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' +vim.g.have_nerd_font = true + +vim.keymap.set('n', '', 'nohlsearch') +vim.keymap.set('n', 'q', vim.diagnostic.setqflist, { desc = 'Open diagnostic [Q]uickfix list' }) +vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) + +-- Disables as a normal/visual key, so it only works as leader +vim.keymap.set({ 'n', 'v' }, '', '', { silent = true }) + +-- Remap jk to esc +vim.keymap.set({ 'n', 'v', 'i' }, 'jk', '') +vim.keymap.set('t', 'jk', '') + +-- Quickly remove search highlight with (now ) +vim.keymap.set('n', '', ':noh', { desc = 'Remove search highlight' }) + +-- Makes 'j'/'k' move by visual lines when no count is given +vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) + +-- Move cursor right/left in insert mode with Ctrl+l/h. +vim.keymap.set('i', '', '', { desc = 'Move to right on insert mode' }) +vim.keymap.set('i', '', '', { desc = 'Move to left on insert mode' }) +vim.keymap.set('i', '', '', { desc = 'Move to down on insert mode' }) +vim.keymap.set('i', '', '', { desc = 'Move to Up on insert mode' }) + +-- Move selected lines up/down in visual mode with J/K. +vim.keymap.set('v', 'J', ":m '>+1gv=gv") +vim.keymap.set('v', 'K', ":m '<-2gv=gv") + +-- Scroll half-page down/up and center cursor. +vim.keymap.set('n', '', 'zz') +vim.keymap.set('n', '', 'zz') + +-- Next/previous search result and center cursor. +vim.keymap.set('n', 'n', 'nzzzv') +vim.keymap.set('n', 'N', 'Nzzzv') + +-- Paste over selection without overwriting the default register. +vim.keymap.set('x', 'p', [["_dP]]) + +-- Delete to black hole register (doesn't overwrite yank buffer). +vim.keymap.set({ 'n', 'v' }, 'd', [["_d]]) + +-- In insert mode, Ctrl+c acts as . +vim.keymap.set('i', '', '') + +-- Diagnostic navigation +vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Next [D]iagnostic' }) +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Previous [D]iagnostic' }) + +-- Buffer navigation +vim.keymap.set('n', ']b', 'bnext', { desc = 'Next [B]uffer' }) +vim.keymap.set('n', '[b', 'bprev', { desc = 'Previous [B]uffer' }) + +-- Quickfix navigation +vim.keymap.set('n', ']q', 'cnext', { desc = 'Next [Q]uickfix' }) +vim.keymap.set('n', '[q', 'cprev', { desc = 'Previous [Q]uickfix' }) diff --git a/lua/setup/lazy.lua b/lua/setup/lazy.lua new file mode 100644 index 00000000000..38388d1c384 --- /dev/null +++ b/lua/setup/lazy.lua @@ -0,0 +1,103 @@ +-- [[ Install lazy.nvim ]] +local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = 'https://github.com/folke/lazy.nvim.git' + local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath } + if vim.v.shell_error ~= 0 then + error('Error cloning lazy.nvim:\n' .. out) + end +end +vim.opt.rtp:prepend(lazypath) + +require('lazy').setup({ + -- Git related plugins + { + 'sindrets/diffview.nvim', + cmd = { 'DiffviewOpen', 'DiffviewFileHistory', 'DiffviewClose' }, + keys = { + { 'gv', 'DiffviewOpen', desc = '[G]it Diff[V]iew' }, + { 'gh', 'DiffviewFileHistory %', desc = '[G]it File [H]istory' }, + }, + }, + + -- Detect tabstop and shiftwidth automatically + 'tpope/vim-sleuth', + + -- Completion + { import = 'plugins.blink' }, + { import = 'plugins.autopairs' }, + + -- LSP + { import = 'plugins.lsp' }, + { import = 'plugins.mason' }, + + -- Treesitter + { import = 'plugins.treesitter' }, + + -- Formatting & Linting + { import = 'plugins.conform' }, + { import = 'plugins.lint' }, + + -- UI + { import = 'plugins.colorscheme' }, + { import = 'plugins.lualine' }, + { import = 'plugins.snacks' }, + { import = 'plugins.noice' }, + { import = 'plugins.neo-tree' }, + { import = 'plugins.which-key' }, + { import = 'plugins.indent_line' }, + { import = 'plugins.render-markdown' }, + { import = 'plugins.highlight-colors' }, + { import = 'plugins.todo-comments' }, + { import = 'plugins.log-highlight' }, + + -- Navigation + { import = 'plugins.telescope-fuzzy-finder' }, + { import = 'plugins.smart-splits' }, + { import = 'plugins.treesj' }, + + -- Git + { import = 'plugins.fugitive' }, + { import = 'plugins.gitsigns' }, + + -- Editing + { import = 'plugins.surround' }, + -- { import = 'plugins.mini-nvim' }, -- replaced by individual mini.ai below + { import = 'plugins.mini-ai' }, + + -- Terminal + { import = 'plugins.toggleterm' }, + + -- AI + { import = 'plugins.copilot' }, + { import = 'plugins.copilot-chat' }, + { import = 'plugins.codecompanion' }, + + -- Debugging + { import = 'plugins.debug' }, + + -- Language specific + { import = 'plugins.cmake-tools' }, + { import = 'plugins.unreal' }, + + -- Misc + { import = 'plugins.lazy-dev' }, +}, { + ui = { + icons = vim.g.have_nerd_font and {} or { + cmd = '⌘', + config = '🛠', + event = '📅', + ft = '📂', + init = '⚙', + keys = '🗝', + plugin = '🔌', + runtime = '💻', + require = '🌙', + source = '📄', + start = '🚀', + task = '📌', + lazy = '💤 ', + }, + }, +}) diff --git a/lua/setup/lsp.lua b/lua/setup/lsp.lua new file mode 100644 index 00000000000..6b0ee43d3a5 --- /dev/null +++ b/lua/setup/lsp.lua @@ -0,0 +1,353 @@ +vim.lsp.enable { + 'lua_ls', + 'basedpyright', + 'clangd', + -- 'typos_lsp', + -- 'ty', -- removed: redundant with basedpyright, adds diagnostic noise + 'ts_ls', + 'cssls', + 'html', +} + +vim.lsp.inlay_hint.enable(true) + +local virtual_text_mode = nil +local base_virtual_text = { + source = 'if_many', + spacing = 2, + format = function(diagnostic) + return diagnostic.message + end, +} +local diagnostic_underline = { severity = vim.diagnostic.severity.ERROR } + +vim.diagnostic.config { + virtual_text = base_virtual_text, + underline = diagnostic_underline, + update_in_insert = false, + severity_sort = true, + float = { + border = 'rounded', + source = 'if_many', + }, + signs = vim.g.have_nerd_font and { + text = { + [vim.diagnostic.severity.ERROR] = '󰅚 ', + [vim.diagnostic.severity.WARN] = '󰀪 ', + [vim.diagnostic.severity.INFO] = '󰋽 ', + [vim.diagnostic.severity.HINT] = '󰌶 ', + }, + numhl = { + [vim.diagnostic.severity.ERROR] = 'ErrorMsg', + [vim.diagnostic.severity.WARN] = 'WarningMsg', + } or {}, + }, +} + +vim.api.nvim_create_user_command('LspToggleDiagnostic', function() + if virtual_text_mode == nil then + virtual_text_mode = true + vim.diagnostic.config { + virtual_text = { + current_line = virtual_text_mode, + }, + underline = false, + } + else + virtual_text_mode = nil + vim.diagnostic.config { + virtual_text = base_virtual_text, + underline = diagnostic_underline, + } + end +end, {}) + +vim.api.nvim_create_user_command('LspToggleInlayHints', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) +end, {}) + +vim.keymap.set('n', 'ld', 'LspToggleDiagnostic', { desc = 'Toggle Lsp Diagnostic Mode' }) +vim.keymap.set('n', 'li', 'LspToggleInlayHints', { desc = 'Toggle Lsp Inlay Hints' }) + +-- Extras +local function restart_lsp(client_name) + if not client_name or client_name == '' then + vim.notify('restart_lsp: missing client_name', vim.log.levels.WARN) + return + end + + -- 1) Collect buffers that had this client and the client configs to reuse + local target = {} -- [bufnr] = client.config + local to_stop = {} -- [client_id] = client + + for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_is_loaded(bufnr) then + for _, c in ipairs(vim.lsp.get_clients { bufnr = bufnr }) do + if c.name == client_name then + target[bufnr] = c.config + to_stop[c.id] = c + end + end + end + end + + if vim.tbl_isempty(target) then + vim.notify(("restart_lsp: no buffers with client '%s'"):format(client_name), vim.log.levels.INFO) + return + end + + -- 2) Stop all those clients (force=true) + for _, client in pairs(to_stop) do + client:stop(true) + end + + -- 3) For each buffer, (re)start using the original config. + -- vim.lsp.start() will *reuse* a running client with same name+root_dir + -- and will attach this buffer; otherwise it spawns a new one. + vim.defer_fn(function() + for bufnr, cfg in pairs(target) do + if vim.api.nvim_buf_is_valid(bufnr) and vim.api.nvim_buf_is_loaded(bufnr) then + local conf = vim.deepcopy(cfg) -- don’t mutate the old config + vim.api.nvim_buf_call(bufnr, function() + vim.lsp.start(conf) + end) + end + end + end, 100) +end + +vim.api.nvim_create_user_command('LspRestart', function(opts) + restart_lsp(unpack(opts.fargs)) +end, { + nargs = '?', +}) + +local function lsp_status() + local bufnr = vim.api.nvim_get_current_buf() + local clients = vim.lsp.get_clients { bufnr = bufnr } + + if #clients == 0 then + print '󰅚 No LSP clients attached' + return + end + + print('󰒋 LSP Status for buffer ' .. bufnr .. ':') + print '─────────────────────────────────' + + for i, client in ipairs(clients) do + print(string.format('󰌘 Client %d: %s (ID: %d)', i, client.name, client.id)) + print(' Root: ' .. (client.config.root_dir or 'N/A')) + -- print(' Filetypes: ' .. table.concat(client.config.filetypes or {}, ', ')) + + -- Check capabilities + local caps = client.server_capabilities + local features = {} + if caps ~= nil then + if caps.completionProvider then + table.insert(features, 'completion') + end + if caps.hoverProvider then + table.insert(features, 'hover') + end + if caps.definitionProvider then + table.insert(features, 'definition') + end + if caps.referencesProvider then + table.insert(features, 'references') + end + if caps.renameProvider then + table.insert(features, 'rename') + end + if caps.codeActionProvider then + table.insert(features, 'code_action') + end + if caps.documentFormattingProvider then + table.insert(features, 'formatting') + end + end + + print(' Features: ' .. table.concat(features, ', ')) + print '' + end +end + +vim.api.nvim_create_user_command('LspStatus', lsp_status, { desc = 'Show detailed LSP status' }) + +local function check_lsp_capabilities() + local bufnr = vim.api.nvim_get_current_buf() + local clients = vim.lsp.get_clients { bufnr = bufnr } + + if #clients == 0 then + print 'No LSP clients attached' + return + end + + for _, client in ipairs(clients) do + print('Capabilities for ' .. client.name .. ':') + local caps = client.server_capabilities + if caps ~= nil then + local capability_list = { + { 'Completion', caps.completionProvider }, + { 'Hover', caps.hoverProvider }, + { 'Signature Help', caps.signatureHelpProvider }, + { 'Go to Definition', caps.definitionProvider }, + { 'Go to Declaration', caps.declarationProvider }, + { 'Go to Implementation', caps.implementationProvider }, + { 'Go to Type Definition', caps.typeDefinitionProvider }, + { 'Find References', caps.referencesProvider }, + { 'Document Highlight', caps.documentHighlightProvider }, + { 'Document Symbol', caps.documentSymbolProvider }, + { 'Workspace Symbol', caps.workspaceSymbolProvider }, + { 'Code Action', caps.codeActionProvider }, + { 'Code Lens', caps.codeLensProvider }, + { 'Document Formatting', caps.documentFormattingProvider }, + { 'Document Range Formatting', caps.documentRangeFormattingProvider }, + { 'Rename', caps.renameProvider }, + { 'Folding Range', caps.foldingRangeProvider }, + { 'Selection Range', caps.selectionRangeProvider }, + } + for _, cap in ipairs(capability_list) do + local status = cap[2] and '✓' or '✗' + print(string.format(' %s %s', status, cap[1])) + end + end + print '' + end +end + +vim.api.nvim_create_user_command('LspCapabilities', check_lsp_capabilities, { desc = 'Show LSP capabilities' }) + +local function lsp_diagnostics_info() + local bufnr = vim.api.nvim_get_current_buf() + local diagnostics = vim.diagnostic.get(bufnr) + + local counts = { ERROR = 0, WARN = 0, INFO = 0, HINT = 0 } + + for _, diagnostic in ipairs(diagnostics) do + local severity = vim.diagnostic.severity[diagnostic.severity] + counts[severity] = counts[severity] + 1 + end + + print '󰒡 Diagnostics for current buffer:' + print(' Errors: ' .. counts.ERROR) + print(' Warnings: ' .. counts.WARN) + print(' Info: ' .. counts.INFO) + print(' Hints: ' .. counts.HINT) + print(' Total: ' .. #diagnostics) +end + +vim.api.nvim_create_user_command('LspDiagnostics', lsp_diagnostics_info, { desc = 'Show LSP diagnostics count' }) + +local function lsp_info() + local bufnr = vim.api.nvim_get_current_buf() + local clients = vim.lsp.get_clients { bufnr = bufnr } + + print '═══════════════════════════════════' + print ' LSP INFORMATION ' + print '═══════════════════════════════════' + print '' + + -- Basic info + print('󰈙 Language client log: ' .. vim.lsp.get_log_path()) + print('󰈔 Detected filetype: ' .. vim.bo.filetype) + print('󰈮 Buffer: ' .. bufnr) + print('󰈔 Root directory: ' .. (vim.fn.getcwd() or 'N/A')) + print '' + + if #clients == 0 then + print('󰅚 No LSP clients attached to buffer ' .. bufnr) + print '' + print 'Possible reasons:' + print(' • No language server installed for ' .. vim.bo.filetype) + print ' • Language server not configured' + print ' • Not in a project root directory' + print ' • File type not recognized' + return + end + + print('󰒋 LSP clients attached to buffer ' .. bufnr .. ':') + print '─────────────────────────────────' + + for i, client in ipairs(clients) do + print(string.format('󰌘 Client %d: %s', i, client.name)) + print(' ID: ' .. client.id) + print(' Root dir: ' .. (client.config.root_dir or 'Not set')) + -- print(' Command: ' .. table.concat(client.config.cmd or {}, ' ')) + -- print(' Filetypes: ' .. table.concat(client.config.filetypes or {}, ', ')) + + -- Server status + if client:is_stopped() then + print ' Status: 󰅚 Stopped' + else + print ' Status: 󰄬 Running' + end + + -- Workspace folders + if client.workspace_folders and #client.workspace_folders > 0 then + print ' Workspace folders:' + for _, folder in ipairs(client.workspace_folders) do + print(' • ' .. folder.name) + end + end + + -- Attached buffers count + local attached_buffers = {} + for buf, _ in pairs(client.attached_buffers or {}) do + table.insert(attached_buffers, buf) + end + print(' Attached buffers: ' .. #attached_buffers) + + -- Key capabilities + local caps = client.server_capabilities + local key_features = {} + if caps ~= nil then + if caps.completionProvider then + table.insert(key_features, 'completion') + end + if caps.hoverProvider then + table.insert(key_features, 'hover') + end + if caps.definitionProvider then + table.insert(key_features, 'definition') + end + if caps.documentFormattingProvider then + table.insert(key_features, 'formatting') + end + if caps.codeActionProvider then + table.insert(key_features, 'code_action') + end + end + + if #key_features > 0 then + print(' Key features: ' .. table.concat(key_features, ', ')) + end + + print '' + end + -- Diagnostics summary + local diagnostics = vim.diagnostic.get(bufnr) + if #diagnostics > 0 then + print '󰒡 Diagnostics Summary:' + local counts = { ERROR = 0, WARN = 0, INFO = 0, HINT = 0 } + + for _, diagnostic in ipairs(diagnostics) do + local severity = vim.diagnostic.severity[diagnostic.severity] + counts[severity] = counts[severity] + 1 + end + + print(' 󰅚 Errors: ' .. counts.ERROR) + print(' 󰀪 Warnings: ' .. counts.WARN) + print(' 󰋽 Info: ' .. counts.INFO) + print(' 󰌶 Hints: ' .. counts.HINT) + print(' Total: ' .. #diagnostics) + else + print '󰄬 No diagnostics' + end + + print '' + print 'Use :LspLog to view detailed logs' + print 'Use :LspCapabilities for full capability list' +end + +-- Create command +vim.api.nvim_create_user_command('LspInfo', lsp_info, { desc = 'Show comprehensive LSP information' }) diff --git a/lua/setup/set.lua b/lua/setup/set.lua new file mode 100644 index 00000000000..93a873d3138 --- /dev/null +++ b/lua/setup/set.lua @@ -0,0 +1,91 @@ +vim.opt.fsync = false + +-- System Clipboard Integration +vim.schedule(function() + vim.o.clipboard = 'unnamedplus' +end) + +-- Make line numbers default +vim.opt.nu = true +vim.opt.relativenumber = true + +-- Default terminal to pwsh +vim.opt.shell = vim.fn.executable('pwsh') == 1 and 'pwsh' or 'powershell' +vim.opt.shellcmdflag = + '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;' +vim.opt.shellredir = '-RedirectStandardOutput %s -NoNewWindow -Wait' +vim.opt.shellpipe = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode' +vim.opt.shellquote = '' +vim.opt.shellxquote = '' + +-- Enable break indent +vim.o.breakindent = true + +-- Quality of life bindings for common/essential operations +vim.cmd 'command! W w' +vim.cmd 'command! Qw wq' +vim.cmd 'command! Q q' + +-- Save undo history +vim.fn.mkdir(vim.fn.stdpath('data') .. '/undodir', 'p') +vim.opt.undodir = vim.fn.stdpath 'data' .. '/undodir' +vim.opt.undofile = true + +-- Case-insensitive searching UNLESS \C or capital in search +vim.o.ignorecase = true +vim.o.smartcase = true + +-- Keep signcolumn on by default +vim.opt.scrolloff = 10 +vim.opt.signcolumn = 'yes' +vim.opt.isfname:append '@-@' +vim.opt.colorcolumn = '80' + +-- Decrease update time +vim.o.timeoutlen = 300 +vim.opt.updatetime = 250 + +-- Set completeopt to have a better completion experience +vim.o.completeopt = 'menuone,noselect' + +-- NOTE: You should make sure your terminal supports this +vim.o.termguicolors = true +vim.opt.guicursor = '' + +-- Setup tab +vim.opt.tabstop = 4 +vim.opt.softtabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = true + +vim.opt.smartindent = true +vim.o.autoindent = true +vim.opt.wrap = false + +-- Disable swap and backup files +vim.opt.swapfile = false +vim.opt.backup = false + +-- Search Highlighting +vim.opt.hlsearch = true +vim.opt.incsearch = true + +-- Cursos and window appearance +vim.opt.cursorline = true + +-- Window splitting behavior +vim.opt.splitright = true + +-- Disable netrw(built-in file explorer) +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 + +-- Window border style +vim.o.winborder = 'rounded' + +-- Show invisible characters +vim.o.list = true +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } + +-- Live substitution preview +vim.o.inccommand = 'split' diff --git a/machine.json b/machine.json new file mode 100644 index 00000000000..9e08be5ab4f --- /dev/null +++ b/machine.json @@ -0,0 +1,6 @@ +{ + "_comment": "Machine-specific paths — DO NOT COMMIT. See machine.json.template for the template.", + "basedpyright": "D:\\language-servers\\basedpyright\\Scripts\\basedpyright-langserver.exe", + "clangd": "D:\\language-servers\\clangd\\bin\\clangd.exe", + "ue_python": "C:\\Program Files\\Epic Games\\UE_5.7\\Engine\\Binaries\\ThirdParty\\Python3\\Win64\\python.exe" +} diff --git a/machine.json.template b/machine.json.template new file mode 100644 index 00000000000..d4c2de0bf9c --- /dev/null +++ b/machine.json.template @@ -0,0 +1,6 @@ +{ + "_comment": "Copy this file to machine.json and fill in the paths for this machine. machine.json is gitignored.", + "basedpyright": "D:\\language-servers\\basedpyright\\Scripts\\basedpyright-langserver.exe", + "clangd": "D:\\language-servers\\clangd\\bin\\clangd.exe", + "ue_python": "C:\\Program Files\\Epic Games\\UE_5.7\\Engine\\Binaries\\ThirdParty\\Python3\\Win64\\python.exe" +} diff --git a/requirements.md b/requirements.md new file mode 100644 index 00000000000..cf707bb09c1 --- /dev/null +++ b/requirements.md @@ -0,0 +1,387 @@ +# Neovim Configuration Requirements + +## Plugin Manager + +| Plugin | GitHub | +|--------|--------| +| lazy.nvim | https://github.com/folke/lazy.nvim | + +--- + +## Completion + +| Plugin | GitHub | +|--------|--------| +| blink.cmp | https://github.com/saghen/blink.cmp | +| LuaSnip | https://github.com/L3MON4D3/LuaSnip | +| friendly-snippets | https://github.com/rafamadriz/friendly-snippets | +| nvim-autopairs | https://github.com/windwp/nvim-autopairs | + +--- + +## LSP + +| Plugin | GitHub | +|--------|--------| +| nvim-lspconfig | https://github.com/neovim/nvim-lspconfig | +| mason.nvim | https://github.com/mason-org/mason.nvim | +| mason-lspconfig.nvim | https://github.com/mason-org/mason-lspconfig.nvim | +| mason-tool-installer.nvim | https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim | +| lazydev.nvim | https://github.com/folke/lazydev.nvim | +| fidget.nvim | https://github.com/j-hui/fidget.nvim | +| lua-language-server | https://github.com/LuaLS/lua-language-server | +| basedpyright | https://github.com/DetachHead/basedpyright | +| clangd | https://github.com/clangd/clangd | +| typescript-language-server | https://github.com/typescript-language-server/typescript-language-server | +| vscode-langservers-extracted (css-lsp + html-lsp) | https://github.com/hrsh7th/vscode-langservers-extracted | + +--- + +## Formatting & Linting + +| Plugin | GitHub | +|--------|--------| +| conform.nvim | https://github.com/stevearc/conform.nvim | +| nvim-lint | https://github.com/mfussenegger/nvim-lint | +| stylua | https://github.com/JohnnyMorganz/StyLua | +| prettier | https://github.com/prettier/prettier | +| ruff | https://github.com/astral-sh/ruff | +| clang-format | https://github.com/llvm/llvm-project | +| markdownlint | https://github.com/DavidAnson/markdownlint-cli | + +--- + +## Treesitter + +| Plugin | GitHub | +|--------|--------| +| nvim-treesitter | https://github.com/nvim-treesitter/nvim-treesitter | +| nvim-treesitter-context | https://github.com/nvim-treesitter/nvim-treesitter-context | +| nvim-treesitter-textobjects | https://github.com/nvim-treesitter/nvim-treesitter-textobjects | + +--- + +## UI + +| Plugin | GitHub | +|--------|--------| +| gruvbox.nvim | https://github.com/ellisonleao/gruvbox.nvim | +| lualine.nvim | https://github.com/nvim-lualine/lualine.nvim | +| snacks.nvim | https://github.com/folke/snacks.nvim | +| noice.nvim | https://github.com/folke/noice.nvim | +| nvim-notify | https://github.com/rcarriga/nvim-notify | +| nui.nvim | https://github.com/MunifTanjim/nui.nvim | +| neo-tree.nvim | https://github.com/nvim-neo-tree/neo-tree.nvim | +| which-key.nvim | https://github.com/folke/which-key.nvim | +| indent-blankline.nvim | https://github.com/lukas-reineke/indent-blankline.nvim | +| render-markdown.nvim | https://github.com/MeanderingProgrammer/render-markdown.nvim | +| nvim-highlight-colors | https://github.com/brenoprata10/nvim-highlight-colors | +| todo-comments.nvim | https://github.com/folke/todo-comments.nvim | +| log-highlight.nvim | https://github.com/fei6409/log-highlight.nvim | +| nvim-web-devicons | https://github.com/nvim-tree/nvim-web-devicons | + +--- + +## Navigation + +| Plugin | GitHub | +|--------|--------| +| telescope.nvim | https://github.com/nvim-telescope/telescope.nvim | +| telescope-fzf-native.nvim | https://github.com/nvim-telescope/telescope-fzf-native.nvim | +| telescope-ui-select.nvim | https://github.com/nvim-telescope/telescope-ui-select.nvim | +| smart-splits.nvim | https://github.com/mrjones2014/smart-splits.nvim | +| treesj | https://github.com/Wansmer/treesj | + +--- + +## Git + +| Plugin | GitHub | +|--------|--------| +| vim-fugitive | https://github.com/tpope/vim-fugitive | +| gitsigns.nvim | https://github.com/lewis6991/gitsigns.nvim | +| diffview.nvim | https://github.com/sindrets/diffview.nvim | + +--- + +## Editing + +| Plugin | GitHub | +|--------|--------| +| nvim-surround | https://github.com/kylechui/nvim-surround | +| mini.ai | https://github.com/echasnovski/mini.ai | +| vim-sleuth | https://github.com/tpope/vim-sleuth | + +--- + +## Terminal + +| Plugin | GitHub | +|--------|--------| +| toggleterm.nvim | https://github.com/akinsho/toggleterm.nvim | + +--- + +## AI + +| Plugin | GitHub | +|--------|--------| +| copilot.lua | https://github.com/zbirenbaum/copilot.lua | +| blink-cmp-copilot | https://github.com/giuxtaposition/blink-cmp-copilot | +| CopilotChat.nvim | https://github.com/CopilotC-Nvim/CopilotChat.nvim | +| codecompanion.nvim | https://github.com/olimorris/codecompanion.nvim | + +--- + +## Debugging (DAP) + +| Plugin | GitHub | +|--------|--------| +| nvim-dap | https://github.com/mfussenegger/nvim-dap | +| nvim-dap-ui | https://github.com/rcarriga/nvim-dap-ui | +| nvim-nio | https://github.com/nvim-neotest/nvim-nio | +| mason-nvim-dap.nvim | https://github.com/jay-babu/mason-nvim-dap.nvim | +| nvim-dap-python | https://github.com/mfussenegger/nvim-dap-python | +| nvim-dap-virtual-text | https://github.com/theHamsta/nvim-dap-virtual-text | +| codelldb | https://github.com/vadimcn/codelldb | +| debugpy | https://github.com/microsoft/debugpy | + +--- + +## Language Specific + +| Plugin | GitHub | +|--------|--------| +| cmake-tools.nvim | https://github.com/Civitasv/cmake-tools.nvim | +| Unreal-Nvim | https://github.com/PlayKigai/Unreal-Nvim | + +--- + +## Shared Dependencies + +| Plugin | GitHub | +|--------|--------| +| plenary.nvim | https://github.com/nvim-lua/plenary.nvim | + + +## Completion + +| Plugin | GitHub | +|--------|--------| +| blink.cmp | https://github.com/saghen/blink.cmp | +| LuaSnip | https://github.com/L3MON4D3/LuaSnip | +| friendly-snippets | https://github.com/rafamadriz/friendly-snippets | +| nvim-autopairs | https://github.com/windwp/nvim-autopairs | + +--- + +## LSP + +| Plugin | GitHub | +|--------|--------| +| nvim-lspconfig | https://github.com/neovim/nvim-lspconfig | +| mason.nvim | https://github.com/mason-org/mason.nvim | +| mason-lspconfig.nvim | https://github.com/mason-org/mason-lspconfig.nvim | +| mason-tool-installer.nvim | https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim | +| lazydev.nvim | https://github.com/folke/lazydev.nvim | +| fidget.nvim | https://github.com/j-hui/fidget.nvim | + +### LSP Servers (installed via Mason) + +| Server | Language | +|--------|----------| +| lua-language-server | Lua | +| basedpyright | Python | +| clangd | C / C++ | +| typescript-language-server (ts_ls) | TypeScript / JavaScript | +| css-lsp | CSS | +| html-lsp | HTML | + +### LSP Servers — Manual Install (No Mason) + +> Clone or download releases directly from GitHub, build/install per each repo's README, then either put the binary on your `PATH` or set the machine-specific path in `machine.json` for servers that use `lua/machine.lua` (`basedpyright` and `clangd` in the current config). + +| Server | GitHub | Notes | +|--------|--------|-------| +| lua-language-server | https://github.com/LuaLS/lua-language-server | Pre-built releases available; add `bin/` to PATH | +| basedpyright | https://github.com/DetachHead/basedpyright | Install via `pip install basedpyright`; `lsp/basedpyright.lua` can also read the binary path from `machine.json` key `basedpyright` | +| clangd | https://github.com/clangd/clangd | Pre-built releases available; part of LLVM toolchain; `lsp/clangd.lua` can also read the binary path from `machine.json` key `clangd` | +| typescript-language-server | https://github.com/typescript-language-server/typescript-language-server | Requires Node.js; build from source with `npm install` | +| css-lsp + html-lsp | https://github.com/hrsh7th/vscode-langservers-extracted | Both servers come from this single repo; requires Node.js | + +> `:LspRestart` currently does a stop-then-deferred-start cycle and may hit timing issues on some buffers or roots. If a restart looks incomplete, use `:LspStop` and then `:LspStart` separately. + +> `:LspToggleDiagnostic` switches `virtual_text.current_line` and underline state, but custom `virtual_text` settings may need to be re-applied manually after toggling. + +### Formatters & Linters (installed via Mason) + +| Tool | Purpose | +|------|---------| +| stylua | Lua formatter | +| prettier | JS / TS / CSS / HTML formatter | +| ruff | Python formatter / import sorter | +| clang-format | C / C++ formatter | + +### Formatters & Linters — Manual Install (No Mason) + +> Same rule: build from source or grab a release binary, put it on `PATH`. `conform.nvim` and `nvim-lint` will pick it up automatically. + +| Tool | GitHub | Notes | +|------|--------|-------| +| stylua | https://github.com/JohnnyMorganz/StyLua | Pre-built releases available for all platforms | +| prettier | https://github.com/prettier/prettier | Requires Node.js; build from source with `npm install` | +| ruff | https://github.com/astral-sh/ruff | Requires Python; install with `pip install ruff` from source or release | +| clang-format | https://github.com/llvm/llvm-project | Pre-built releases available; part of LLVM toolchain | +| markdownlint | https://github.com/DavidAnson/markdownlint-cli | Requires Node.js; install with `npm install` so `nvim-lint` can lint Markdown | + +### DAP Adapters (installed via Mason) + +| Adapter | GitHub | +|---------|--------| +| codelldb | https://github.com/vadimcn/codelldb | +| debugpy | https://github.com/microsoft/debugpy | + +### DAP Adapters — Manual Install (No Mason) + +> `lua/plugins/debug.lua` configures `mason-nvim-dap.nvim` to install both `codelldb` and `debugpy`. Without Mason, install from GitHub and point `nvim-dap`'s adapter config at the binary. + +| Adapter | GitHub | Notes | +|---------|--------|-------| +| codelldb | https://github.com/vadimcn/codelldb | Pre-built releases available; point `nvim-dap` at the adapter executable if needed | +| debugpy (Python) | https://github.com/microsoft/debugpy | Install with `pip install debugpy`; with Mason, `nvim-dap-python` uses the Mason `debugpy` virtualenv first and falls back to the system Python if the Mason package is missing | + +> Verify that the Python interpreter selected for debugging matches the current workspace, especially when Mason is installed but the project expects a different virtualenv. + +--- + +## Treesitter + +| Plugin | GitHub | +|--------|--------| +| nvim-treesitter | https://github.com/nvim-treesitter/nvim-treesitter | +| nvim-treesitter-context | https://github.com/nvim-treesitter/nvim-treesitter-context | +| nvim-treesitter-textobjects | https://github.com/nvim-treesitter/nvim-treesitter-textobjects | + +--- + +## Formatting & Linting + +| Plugin | GitHub | +|--------|--------| +| conform.nvim | https://github.com/stevearc/conform.nvim | +| nvim-lint | https://github.com/mfussenegger/nvim-lint | + +### Formatters / Linters (installed via Mason) + +| Tool | Purpose | +|------|---------| +| stylua | Lua formatter | +| prettier | JS / TS / CSS / HTML formatter | +| ruff | Python formatter / import sorter | +| clang-format | C / C++ formatter | + +--- + +## UI + +| Plugin | GitHub | +|--------|--------| +| gruvbox.nvim | https://github.com/ellisonleao/gruvbox.nvim | +| lualine.nvim | https://github.com/nvim-lualine/lualine.nvim | +| snacks.nvim | https://github.com/folke/snacks.nvim | +| noice.nvim | https://github.com/folke/noice.nvim | +| nvim-notify | https://github.com/rcarriga/nvim-notify | +| nui.nvim | https://github.com/MunifTanjim/nui.nvim | +| neo-tree.nvim | https://github.com/nvim-neo-tree/neo-tree.nvim | +| which-key.nvim | https://github.com/folke/which-key.nvim | +| indent-blankline.nvim | https://github.com/lukas-reineke/indent-blankline.nvim | +| render-markdown.nvim | https://github.com/MeanderingProgrammer/render-markdown.nvim | +| nvim-highlight-colors | https://github.com/brenoprata10/nvim-highlight-colors | +| todo-comments.nvim | https://github.com/folke/todo-comments.nvim | +| log-highlight.nvim | https://github.com/fei6409/log-highlight.nvim | +| nvim-web-devicons | https://github.com/nvim-tree/nvim-web-devicons | + +--- + +## Navigation + +| Plugin | GitHub | +|--------|--------| +| telescope.nvim | https://github.com/nvim-telescope/telescope.nvim | +| telescope-fzf-native.nvim | https://github.com/nvim-telescope/telescope-fzf-native.nvim | +| telescope-ui-select.nvim | https://github.com/nvim-telescope/telescope-ui-select.nvim | +| smart-splits.nvim | https://github.com/mrjones2014/smart-splits.nvim | +| treesj | https://github.com/Wansmer/treesj | + +--- + +## Git + +| Plugin | GitHub | +|--------|--------| +| vim-fugitive | https://github.com/tpope/vim-fugitive | +| gitsigns.nvim | https://github.com/lewis6991/gitsigns.nvim | +| diffview.nvim | https://github.com/sindrets/diffview.nvim | + +--- + +## Editing + +| Plugin | GitHub | +|--------|--------| +| nvim-surround | https://github.com/kylechui/nvim-surround | +| mini.ai | https://github.com/echasnovski/mini.ai | +| vim-sleuth | https://github.com/tpope/vim-sleuth | + +--- + +## Terminal + +| Plugin | GitHub | +|--------|--------| +| toggleterm.nvim | https://github.com/akinsho/toggleterm.nvim | + +--- + +## AI + +| Plugin | GitHub | +|--------|--------| +| copilot.lua | https://github.com/zbirenbaum/copilot.lua | +| blink-cmp-copilot | https://github.com/giuxtaposition/blink-cmp-copilot | +| CopilotChat.nvim | https://github.com/CopilotC-Nvim/CopilotChat.nvim | +| codecompanion.nvim | https://github.com/olimorris/codecompanion.nvim | + +--- + +## Debugging (DAP) + +| Plugin | GitHub | +|--------|--------| +| nvim-dap | https://github.com/mfussenegger/nvim-dap | +| nvim-dap-ui | https://github.com/rcarriga/nvim-dap-ui | +| nvim-nio | https://github.com/nvim-neotest/nvim-nio | +| mason-nvim-dap.nvim | https://github.com/jay-babu/mason-nvim-dap.nvim | +| nvim-dap-python | https://github.com/mfussenegger/nvim-dap-python | +| nvim-dap-virtual-text | https://github.com/theHamsta/nvim-dap-virtual-text | + +> Current DAP setup auto-installs `codelldb` and `debugpy` through Mason; Python debugging is wired through `nvim-dap-python`, which prefers Mason's `debugpy` environment and falls back to the system Python when the Mason package is unavailable. + +--- + +## Language Specific + +| Plugin | GitHub | +|--------|--------| +| cmake-tools.nvim | https://github.com/Civitasv/cmake-tools.nvim | +| Unreal-Nvim | https://github.com/PlayKigai/Unreal-Nvim | + +> `lua/plugins/unreal.lua` now auto-initializes `Unreal-Nvim` when opening `*.uproject`, `*.uplugin`, `*.Build.cs`, or `*.Target.cs` files, and also when opening C/C++ files inside a working directory that contains a `.uproject`. This covers the common Unreal entry points, but edge cases may still need a manual `:Unreal` command. + +--- + +## Shared Dependencies + +| Plugin | GitHub | +|--------|--------| +| plenary.nvim | https://github.com/nvim-lua/plenary.nvim | diff --git a/tmp/diag_test.lua b/tmp/diag_test.lua new file mode 100644 index 00000000000..589387e4a06 --- /dev/null +++ b/tmp/diag_test.lua @@ -0,0 +1,9 @@ +vim.diagnostic.config({ + virtual_text = { source = 'if_many', spacing = 2, format = function(d) return d.message end, current_line = nil }, + underline = { severity = vim.diagnostic.severity.ERROR }, +}) +vim.diagnostic.config({ virtual_text = { current_line = true }, underline = false }) +local cfg = vim.diagnostic.config() +print(vim.inspect(cfg.virtual_text)) +print(vim.inspect(cfg.underline)) +vim.cmd('qa!') diff --git a/tmp/nvim-profile.log b/tmp/nvim-profile.log new file mode 100644 index 00000000000..fb3fc887a77 --- /dev/null +++ b/tmp/nvim-profile.log @@ -0,0 +1,3494 @@ +SCRIPT C:/Users/User/AppData/Local/nvim-data/lazy/neo-tree.nvim/plugin/neo-tree.lua +Sourced 1 time +Total time: 0.000427 + Self time: 0.000427 + +count total (s) self (s) + if vim.g.loaded_neo_tree == 1 or vim.g.loaded_neo_tree == true then + return + end + + -- Possibly convert this to lua using customlist instead of custom in the future? + vim.api.nvim_create_user_command("Neotree", function(ctx) + require("neo-tree.command")._command(unpack(ctx.fargs)) + end, { + nargs = "*", + complete = "custom,v:lua.require'neo-tree.command'.complete_args", + }) + + ---@param path string? The path to check + ---@return boolean hijacked Whether we hijacked a buffer + local function try_netrw_hijack(path) + if not path or #path == 0 then + return false + end + + local stats = (vim.uv or vim.loop).fs_stat(path) + if not stats or stats.type ~= "directory" then + return false + end + + return require("neo-tree.setup.netrw").hijack() + end + + local augroup = vim.api.nvim_create_augroup("NeoTree", { clear = true }) + + -- lazy load until bufenter/netrw hijack + vim.api.nvim_create_autocmd({ "BufEnter" }, { + group = augroup, + desc = "Lazy-load until bufenter/opened dir", + callback = function(args) + return vim.g.neotree_watching_bufenter == 1 or try_netrw_hijack(args.file) + end, + }) + + -- track window order + vim.api.nvim_create_autocmd({ "WinEnter" }, { + group = augroup, + desc = "Track prior windows for opening intuitiveness", + callback = function(ev) + local win = vim.api.nvim_get_current_win() + local utils = require("neo-tree.utils") + if utils.is_floating(win) then + return + end + + if vim.bo[ev.buf].filetype == "neo-tree" then + return + end + + local tabid = vim.api.nvim_get_current_tabpage() + utils.prior_windows[tabid] = utils.prior_windows[tabid] or {} + local tab_windows = utils.prior_windows[tabid] + table.insert(tab_windows, win) + + -- prune history + local win_count = #tab_windows + if win_count > 100 then + ---@diagnostic disable-next-line: deprecated + if table.move then + utils.prior_windows[tabid] = + require("neo-tree.utils._compat").luajit.table_move(tab_windows, 80, win_count, 1, {}) + return + end + + local new_array = {} + for i = 80, win_count do + table.insert(new_array, tab_windows[i]) + end + utils.prior_windows[tabid] = new_array + end + end, + }) + + -- setup session loading + vim.api.nvim_create_autocmd("SessionLoadPost", { + group = augroup, + desc = "Session loading", + callback = function() + if require("neo-tree").ensure_config().auto_clean_after_session_restore then + require("neo-tree.ui.renderer").clean_invalid_neotree_buffers(true) + end + end, + }) + + vim.api.nvim_create_autocmd("WinClosed", { + group = augroup, + desc = "close_if_last_window autocmd", + callback = function(args) + local closing_win = tonumber(args.match) + local visible_winids = vim.api.nvim_tabpage_list_wins(0) + local other_panes = {} + local utils = require("neo-tree.utils") + for _, winid in ipairs(visible_winids) do + if not utils.is_floating(winid) and winid ~= closing_win then + other_panes[#other_panes + 1] = winid + end + end + + if #other_panes ~= 1 then + return + end + + local remaining_pane = other_panes[1] + local remaining_buf = vim.api.nvim_win_get_buf(remaining_pane) + + if vim.bo[remaining_buf].filetype ~= "neo-tree" then + return + end + + local position = vim.b[remaining_buf].neo_tree_position + local source = vim.b[remaining_buf].neo_tree_source + -- close_if_last_window just doesn't make sense for a split style + if position == "current" then + return + end + + local log = require("neo-tree.log") + log.trace("last window, closing") + local state = require("neo-tree.sources.manager").get_state(source) + if not state then + return + end + if not require("neo-tree").ensure_config().close_if_last_window then + return + end + local mod = utils.get_opened_buffers() + log.debug("close_if_last_window, modified files found:", vim.inspect(mod)) + for filename, buf_info in pairs(mod) do + if buf_info.modified then + local buf_name, message + if vim.startswith(filename, "[No Name]#") then + buf_name = string.sub(filename, 11) + message = + "Cannot close because an unnamed buffer is modified. Please save or discard this file." + else + buf_name = filename + message = + "Cannot close because one of the files is modified. Please save or discard changes." + end + log.trace("close_if_last_window, showing unnamed modified buffer:", filename) + vim.schedule(function() + log.warn(message) + vim.cmd("rightbelow vertical split") + vim.api.nvim_win_set_width(remaining_pane, state.window.width or 40) + vim.cmd("b " .. buf_name) + end) + return + end + end + -- this needs to be scheduled, otherwise VimLeavePre autocmds won't trigger + vim.schedule(function() + vim.cmd("q!") + end) + end, + }) + + vim.g.loaded_neo_tree = 1 + +SCRIPT C:\Program Files\Neovim\share\nvim\runtime\ftplugin\lua.vim +Sourced 1 time +Total time: 0.000139 + Self time: 0.000139 + +count total (s) self (s) + " Vim filetype plugin file. + " Language: Lua + " Maintainer: Doug Kearns + " Previous Maintainer: Max Ischenko + " Contributor: Dorai Sitaram + " C.D. MacEachern + " Phạm Bình An + " @konfekt + " Last Change: 2025 Apr 04 + " 2025 May 06 by Vim Project update 'path' setting #17267 + + 1 0.000005 if exists("b:did_ftplugin") + finish + 1 0.000001 endif + 1 0.000003 let b:did_ftplugin = 1 + + " keep in sync with syntax/lua.vim + 1 0.000002 if !exists("lua_version") + " Default is lua 5.3 + 1 0.000001 let lua_version = 5 + 1 0.000001 let lua_subversion = 3 + elseif !exists("lua_subversion") + " lua_version exists, but lua_subversion doesn't. In this case set it to 0 + let lua_subversion = 0 + 1 0.000000 endif + + 1 0.000002 let s:cpo_save = &cpo + 1 0.000005 set cpo&vim + + 1 0.000003 setlocal comments=:---,:-- + 1 0.000003 setlocal commentstring=--\ %s + 1 0.000004 setlocal formatoptions-=t formatoptions+=croql + 1 0.000002 setlocal path-=. " Lua doesn't support importing module in path related to current file like JS + + 1 0.000003 let &l:define = '\:' .. + \ '\<\%(return\|else\|elseif\)\>:' .. + \ '\,' .. + \ '\:\,' .. + \ '\%(--\)\=\[\(=*\)\[:]\1]' + 1 0.000002 let b:undo_ftplugin ..= " | unlet! b:match_words b:match_ignorecase" + 1 0.000000 endif + + 1 0.000015 if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" + if has("win32") + let b:browsefilter ..= "All Files (*.*)\t*\n" + else + let b:browsefilter ..= "All Files (*)\t*\n" + endif + let b:undo_ftplugin ..= " | unlet! b:browsefilter" + 1 0.000000 endif + + " The rest of the file needs to be :sourced only once per Vim session + 1 0.000002 if exists("s:loaded_lua") || &cp + let &cpo = s:cpo_save + unlet s:cpo_save + finish + 1 0.000000 endif + 1 0.000001 let s:loaded_lua = 1 + + 1 0.000002 function s:LuaInclude(fname) abort + let lua_ver = str2float(printf("%d.%02d", g:lua_version, g:lua_subversion)) + let fname = tr(a:fname, '.', '/') + let paths = lua_ver >= 5.03 ? [fname .. ".lua", fname .. "/init.lua"] : [fname .. ".lua"] + for path in paths + if filereadable(path) + return path + endif + endfor + return fname + endfunction + + 1 0.000002 let &cpo = s:cpo_save + 1 0.000001 unlet s:cpo_save + + " vim: nowrap sw=2 sts=2 ts=8 noet: + +SCRIPT C:\Program Files\Neovim\share\nvim\runtime\ftplugin\lua.lua +Sourced 1 time +Total time: 0.013671 + Self time: 0.013565 + +count total (s) self (s) + -- use treesitter over syntax + vim.treesitter.start() + + vim.bo.includeexpr = [[v:lua.require'vim._ftplugin.lua'.includeexpr(v:fname)]] + vim.bo.omnifunc = 'v:lua.vim.lua_omnifunc' + vim.wo[0][0].foldexpr = 'v:lua.vim.treesitter.foldexpr()' + + vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') + .. '\n call v:lua.vim.treesitter.stop()' + .. '\n setl omnifunc< foldexpr< includeexpr<' + +SCRIPT C:\Program Files\Neovim\share\nvim\runtime\indent\lua.vim +Sourced 1 time +Total time: 0.000082 + Self time: 0.000082 + +count total (s) self (s) + " Vim indent file + " Language: Lua script + " Maintainer: Marcus Aurelius Farias + " First Author: Max Ischenko + " Last Change: 2017 Jun 13 + " 2022 Sep 07: b:undo_indent added by Doug Kearns + " 2024 Jul 27: by Vim project: match '(', ')' in function GetLuaIndentIntern() + + " Only load this indent file when no other was loaded. + 1 0.000004 if exists("b:did_indent") + finish + 1 0.000000 endif + 1 0.000002 let b:did_indent = 1 + + 1 0.000005 setlocal indentexpr=GetLuaIndent() + + " To make Vim call GetLuaIndent() when it finds '\s*end' or '\s*until' + " on the current line ('else' is default and includes 'elseif'). + 1 0.000003 setlocal indentkeys+=0=end,0=until + + 1 0.000002 setlocal autoindent + + 1 0.000001 let b:undo_indent = "setlocal autoindent< indentexpr< indentkeys<" + + " Only define the function once. + 1 0.000003 if exists("*GetLuaIndent") + finish + 1 0.000000 endif + + 1 0.000001 function! GetLuaIndent() + let ignorecase_save = &ignorecase + try + let &ignorecase = 0 + return GetLuaIndentIntern() + finally + let &ignorecase = ignorecase_save + endtry + endfunction + + 1 0.000001 function! GetLuaIndentIntern() + " Find a non-blank line above the current line. + let prevlnum = prevnonblank(v:lnum - 1) + + " Hit the start of the file, use zero indent. + if prevlnum == 0 + return 0 + endif + + " Add a 'shiftwidth' after lines that start a block: + " 'function', 'if', 'for', 'while', 'repeat', 'else', 'elseif', '{', '(' + let ind = indent(prevlnum) + let prevline = getline(prevlnum) + let midx = match(prevline, '^\s*\%(if\>\|for\>\|while\>\|repeat\>\|else\>\|elseif\>\|do\>\|then\>\)') + if midx == -1 + let midx = match(prevline, '\%({\|(\)\s*\%(--\%([^[].*\)\?\)\?$') + if midx == -1 + let midx = match(prevline, '\\s*\%(\k\|[.:]\)\{-}\s*(') + endif + endif + + if midx != -1 + " Add 'shiftwidth' if what we found previously is not in a comment and + " an "end" or "until" is not present on the same line. + if synIDattr(synID(prevlnum, midx + 1, 1), "name") != "luaComment" && prevline !~ '\\|\' + let ind = ind + shiftwidth() + endif + endif + + " Subtract a 'shiftwidth' on end, else, elseif, until, '}' and ')' + " This is the part that requires 'indentkeys'. + let midx = match(getline(v:lnum), '^\s*\%(end\>\|else\>\|elseif\>\|until\>\|}\|)\)') + if midx != -1 && synIDattr(synID(v:lnum, midx + 1, 1), "name") != "luaComment" + let ind = ind - shiftwidth() + endif + + return ind + endfunction + +SCRIPT C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim +Sourced 1 time +Total time: 0.000453 + Self time: 0.000407 + +count total (s) self (s) + " matchit.vim: (global plugin) Extended "%" matching + " autload script of matchit plugin, see ../plugin/matchit.vim + " Last Change: May 20, 2024 + + " Neovim does not support scriptversion + 1 0.000014 if has("vimscript-4") + scriptversion 4 + 1 0.000001 endif + + 1 0.000003 let s:last_mps = "" + 1 0.000001 let s:last_words = ":" + 1 0.000001 let s:patBR = "" + + 1 0.000002 let s:save_cpo = &cpo + 1 0.000033 0.000006 set cpo&vim + + " Auto-complete mappings: (not yet "ready for prime time") + " TODO Read :help write-plugin for the "right" way to let the user + " specify a key binding. + " let g:match_auto = '' + " let g:match_autoCR = '' + " if exists("g:match_auto") + " execute "inoremap " . g:match_auto . ' x"=Autocomplete()Pls' + " endif + " if exists("g:match_autoCR") + " execute "inoremap " . g:match_autoCR . ' =Autocomplete()' + " endif + " if exists("g:match_gthhoh") + " execute "inoremap " . g:match_gthhoh . ' :call Gthhoh()' + " endif " gthhoh = "Get the heck out of here!" + + 1 0.000001 let s:notslash = '\\\@1" + let startpos = [line("."), col(".")] + endif + + " First step: if not already done, set the script variables + " s:do_BR flag for whether there are backrefs + " s:pat parsed version of b:match_words + " s:all regexp based on s:pat and the default groups + if !exists("b:match_words") || b:match_words == "" + let match_words = "" + elseif b:match_words =~ ":" + let match_words = b:match_words + else + " Allow b:match_words = "GetVimMatchWords()" . + execute "let match_words =" b:match_words + endif + " Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! + if (match_words != s:last_words) || (&mps != s:last_mps) + \ || exists("b:match_debug") + let s:last_mps = &mps + " quote the special chars in 'matchpairs', replace [,:] with \| and then + " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif, + " #elifdef, #elifndef, #endif) + let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. + \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\%(n\=def\)\=\>:#\s*endif\>' + " s:all = pattern with all the keywords + let match_words = match_words .. (strlen(match_words) ? "," : "") .. default + let s:last_words = match_words + if match_words !~ s:notslash .. '\\\d' + let s:do_BR = 0 + let s:pat = match_words + else + let s:do_BR = 1 + let s:pat = s:ParseWords(match_words) + endif + let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g') + " un-escape \, to , + let s:all = substitute(s:all, '\\,', ',', 'g') + " Just in case there are too many '\(...)' groups inside the pattern, make + " sure to use \%(...) groups, so that error E872 can be avoided + let s:all = substitute(s:all, '\\(', '\\%(', 'g') + let s:all = '\%(' .. s:all .. '\)' + if exists("b:match_debug") + let b:match_pat = s:pat + endif + " Reconstruct the version with unresolved backrefs. + let s:patBR = substitute(match_words .. ',', + \ s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') + " un-escape \, to , + let s:patBR = substitute(s:patBR, '\\,', ',', 'g') + endif + + " Second step: set the following local variables: + " matchline = line on which the cursor started + " curcol = number of characters before match + " prefix = regexp for start of line to start of match + " suffix = regexp for end of match to end of line + " Require match to end on or after the cursor and prefer it to + " start on or before the cursor. + let matchline = getline(startpos[0]) + if a:word != '' + " word given + if a:word !~ s:all + echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE + return s:CleanUp(restore_options, a:mode, startpos) + endif + let matchline = a:word + let curcol = 0 + let prefix = '^\%(' + let suffix = '\)$' + " Now the case when "word" is not given + else " Find the match that ends on or after the cursor and set curcol. + let regexp = s:Wholematch(matchline, s:all, startpos[1]-1) + let curcol = match(matchline, regexp) + " If there is no match, give up. + if curcol == -1 + return s:CleanUp(restore_options, a:mode, startpos) + endif + let endcol = matchend(matchline, regexp) + let suf = strlen(matchline) - endcol + let prefix = (curcol ? '^.*\%' .. (curcol + 1) .. 'c\%(' : '^\%(') + let suffix = (suf ? '\)\%' .. (endcol + 1) .. 'c.*$' : '\)$') + endif + if exists("b:match_debug") + let b:match_match = matchstr(matchline, regexp) + let b:match_col = curcol+1 + endif + + " Third step: Find the group and single word that match, and the original + " (backref) versions of these. Then, resolve the backrefs. + " Set the following local variable: + " group = colon-separated list of patterns, one of which matches + " = ini:mid:fin or ini:fin + " + " Now, set group and groupBR to the matching group: 'if:endif' or + " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns + " group . "," . groupBR, and we pick it apart. + let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, s:patBR) + let i = matchend(group, s:notslash .. ",") + let groupBR = strpart(group, i) + let group = strpart(group, 0, i-1) + " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix + if s:do_BR " Do the hard part: resolve those backrefs! + let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) + endif + if exists("b:match_debug") + let b:match_wholeBR = groupBR + let i = matchend(groupBR, s:notslash .. ":") + let b:match_iniBR = strpart(groupBR, 0, i-1) + endif + + " Fourth step: Set the arguments for searchpair(). + let i = matchend(group, s:notslash .. ":") + let j = matchend(group, '.*' .. s:notslash .. ":") + let ini = strpart(group, 0, i-1) + let mid = substitute(strpart(group, i,j-i-1), s:notslash .. '\zs:', '\\|', 'g') + let fin = strpart(group, j) + "Un-escape the remaining , and : characters. + let ini = substitute(ini, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + let mid = substitute(mid, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + let fin = substitute(fin, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + " searchpair() requires that these patterns avoid \(\) groups. + let ini = substitute(ini, s:notslash .. '\zs\\(', '\\%(', 'g') + let mid = substitute(mid, s:notslash .. '\zs\\(', '\\%(', 'g') + let fin = substitute(fin, s:notslash .. '\zs\\(', '\\%(', 'g') + " Set mid. This is optimized for readability, not micro-efficiency! + if a:forward && matchline =~ prefix .. fin .. suffix + \ || !a:forward && matchline =~ prefix .. ini .. suffix + let mid = "" + endif + " Set flag. This is optimized for readability, not micro-efficiency! + if a:forward && matchline =~ prefix .. fin .. suffix + \ || !a:forward && matchline !~ prefix .. ini .. suffix + let flag = "bW" + else + let flag = "W" + endif + " Set skip. + if exists("b:match_skip") + let skip = b:match_skip + elseif exists("b:match_comment") " backwards compatibility and testing! + let skip = "r:" .. b:match_comment + else + let skip = 's:comment\|string' + endif + let skip = s:ParseSkip(skip) + if exists("b:match_debug") + let b:match_ini = ini + let b:match_tail = (strlen(mid) ? mid .. '\|' : '') .. fin + endif + + " Fifth step: actually start moving the cursor and call searchpair(). + " Later, :execute restore_cursor to get to the original screen. + let view = winsaveview() + call cursor(0, curcol + 1) + if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) + \ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight') + let skip = "0" + else + execute "if " .. skip .. "| let skip = '0' | endif" + endif + let sp_return = searchpair(ini, mid, fin, flag, skip) + if &selection isnot# 'inclusive' && a:mode == 'v' + " move cursor one pos to the right, because selection is not inclusive + " add virtualedit=onemore, to make it work even when the match ends the + " line + if !(col('.') < col('$')-1) + let eolmark=1 " flag to set a mark on eol (since we cannot move there) + endif + norm! l + endif + let final_position = "call cursor(" .. line(".") .. "," .. col(".") .. ")" + " Restore cursor position and original screen. + call winrestview(view) + normal! m' + if sp_return > 0 + execute final_position + endif + if exists('eolmark') && eolmark + call setpos("''", [0, line('.'), col('$'), 0]) " set mark on the eol + endif + return s:CleanUp(restore_options, a:mode, startpos, mid .. '\|' .. fin) + endfun + + " Restore options and do some special handling for Operator-pending mode. + " The optional argument is the tail of the matching group. + 1 0.000002 fun! s:CleanUp(options, mode, startpos, ...) + if strlen(a:options) + execute "set" a:options + endif + " Open folds, if appropriate. + if a:mode != "o" + if &foldopen =~ "percent" + normal! zv + endif + " In Operator-pending mode, we want to include the whole match + " (for example, d%). + " This is only a problem if we end up moving in the forward direction. + elseif (a:startpos[0] < line(".")) || + \ (a:startpos[0] == line(".") && a:startpos[1] < col(".")) + if a:0 + " Check whether the match is a single character. If not, move to the + " end of the match. + let matchline = getline(".") + let currcol = col(".") + let regexp = s:Wholematch(matchline, a:1, currcol-1) + let endcol = matchend(matchline, regexp) + if endcol > currcol " This is NOT off by one! + call cursor(0, endcol) + endif + endif " a:0 + endif " a:mode != "o" && etc. + return 0 + endfun + + " Example (simplified HTML patterns): if + " a:groupBR = '<\(\k\+\)>:' + " a:prefix = '^.\{3}\(' + " a:group = '<\(\k\+\)>:' + " a:suffix = '\).\{2}$' + " a:matchline = "12312" or "12312" + " then extract "tag" from a:matchline and return ":" . + 1 0.000002 fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) + if a:matchline !~ a:prefix .. + \ substitute(a:group, s:notslash .. '\zs:', '\\|', 'g') .. a:suffix + return a:group + endif + let i = matchend(a:groupBR, s:notslash .. ':') + let ini = strpart(a:groupBR, 0, i-1) + let tailBR = strpart(a:groupBR, i) + let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix, + \ a:groupBR) + let i = matchend(word, s:notslash .. ":") + let wordBR = strpart(word, i) + let word = strpart(word, 0, i-1) + " Now, a:matchline =~ a:prefix . word . a:suffix + if wordBR != ini + let table = s:Resolve(ini, wordBR, "table") + else + let table = "" + let d = 0 + while d < 10 + if tailBR =~ s:notslash .. '\\' .. d + let table = table .. d + else + let table = table .. "-" + endif + let d = d + 1 + endwhile + endif + let d = 9 + while d + if table[d] != "-" + let backref = substitute(a:matchline, a:prefix .. word .. a:suffix, + \ '\' .. table[d], "") + " Are there any other characters that should be escaped? + let backref = escape(backref, '*,:') + execute s:Ref(ini, d, "start", "len") + let ini = strpart(ini, 0, start) .. backref .. strpart(ini, start+len) + let tailBR = substitute(tailBR, s:notslash .. '\zs\\' .. d, + \ escape(backref, '\\&'), 'g') + endif + let d = d-1 + endwhile + if exists("b:match_debug") + if s:do_BR + let b:match_table = table + let b:match_word = word + else + let b:match_table = "" + let b:match_word = "" + endif + endif + return ini .. ":" .. tailBR + endfun + + " Input a comma-separated list of groups with backrefs, such as + " a:groups = '\(foo\):end\1,\(bar\):end\1' + " and return a comma-separated list of groups with backrefs replaced: + " return '\(foo\):end\(foo\),\(bar\):end\(bar\)' + 1 0.000001 fun! s:ParseWords(groups) + let groups = substitute(a:groups .. ",", s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let groups = substitute(groups, s:notslash .. '\zs:\{2,}', ':', 'g') + let parsed = "" + while groups =~ '[^,:]' + let i = matchend(groups, s:notslash .. ':') + let j = matchend(groups, s:notslash .. ',') + let ini = strpart(groups, 0, i-1) + let tail = strpart(groups, i, j-i-1) .. ":" + let groups = strpart(groups, j) + let parsed = parsed .. ini + let i = matchend(tail, s:notslash .. ':') + while i != -1 + " In 'if:else:endif', ini='if' and word='else' and then word='endif'. + let word = strpart(tail, 0, i-1) + let tail = strpart(tail, i) + let i = matchend(tail, s:notslash .. ':') + let parsed = parsed .. ":" .. s:Resolve(ini, word, "word") + endwhile " Now, tail has been used up. + let parsed = parsed .. "," + endwhile " groups =~ '[^,:]' + let parsed = substitute(parsed, ',$', '', '') + return parsed + endfun + + " TODO I think this can be simplified and/or made more efficient. + " TODO What should I do if a:start is out of range? + " Return a regexp that matches all of a:string, such that + " matchstr(a:string, regexp) represents the match for a:pat that starts + " as close to a:start as possible, before being preferred to after, and + " ends after a:start . + " Usage: + " let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1) + " let i = match(getline("."), regexp) + " let j = matchend(getline("."), regexp) + " let match = matchstr(getline("."), regexp) + 1 0.000001 fun! s:Wholematch(string, pat, start) + let group = '\%(' .. a:pat .. '\)' + let prefix = (a:start ? '\(^.*\%<' .. (a:start + 2) .. 'c\)\zs' : '^') + let len = strlen(a:string) + let suffix = (a:start+1 < len ? '\(\%>' .. (a:start+1) .. 'c.*$\)\@=' : '$') + if a:string !~ prefix .. group .. suffix + let prefix = '' + endif + return prefix .. group .. suffix + endfun + + " No extra arguments: s:Ref(string, d) will + " find the d'th occurrence of '\(' and return it, along with everything up + " to and including the matching '\)'. + " One argument: s:Ref(string, d, "start") returns the index of the start + " of the d'th '\(' and any other argument returns the length of the group. + " Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be + " executed, having the effect of + " :let foo = s:Ref(string, d, "start") + " :let bar = s:Ref(string, d, "len") + 1 0.000001 fun! s:Ref(string, d, ...) + let len = strlen(a:string) + if a:d == 0 + let start = 0 + else + let cnt = a:d + let match = a:string + while cnt + let cnt = cnt - 1 + let index = matchend(match, s:notslash .. '\\(') + if index == -1 + return "" + endif + let match = strpart(match, index) + endwhile + let start = len - strlen(match) + if a:0 == 1 && a:1 == "start" + return start - 2 + endif + let cnt = 1 + while cnt + let index = matchend(match, s:notslash .. '\\(\|\\)') - 1 + if index == -2 + return "" + endif + " Increment if an open, decrement if a ')': + let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')' + let match = strpart(match, index+1) + endwhile + let start = start - 2 + let len = len - start - strlen(match) + endif + if a:0 == 1 + return len + elseif a:0 == 2 + return "let " .. a:1 .. "=" .. start .. "| let " .. a:2 .. "=" .. len + else + return strpart(a:string, start, len) + endif + endfun + + " Count the number of disjoint copies of pattern in string. + " If the pattern is a literal string and contains no '0' or '1' characters + " then s:Count(string, pattern, '0', '1') should be faster than + " s:Count(string, pattern). + 1 0.000001 fun! s:Count(string, pattern, ...) + let pat = escape(a:pattern, '\\') + if a:0 > 1 + let foo = substitute(a:string, '[^' .. a:pattern .. ']', "a:1", "g") + let foo = substitute(a:string, pat, a:2, "g") + let foo = substitute(foo, '[^' .. a:2 .. ']', "", "g") + return strlen(foo) + endif + let result = 0 + let foo = a:string + let index = matchend(foo, pat) + while index != -1 + let result = result + 1 + let foo = strpart(foo, index) + let index = matchend(foo, pat) + endwhile + return result + endfun + + " s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where + " word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first + " '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this + " indicates that all other instances of '\1' in target are to be replaced + " by '\3'. The hard part is dealing with nesting... + " Note that ":" is an illegal character for source and target, + " unless it is preceded by "\". + 1 0.000001 fun! s:Resolve(source, target, output) + let word = a:target + let i = matchend(word, s:notslash .. '\\\d') - 1 + let table = "----------" + while i != -2 " There are back references to be replaced. + let d = word[i] + let backref = s:Ref(a:source, d) + " The idea is to replace '\d' with backref. Before we do this, + " replace any \(\) groups in backref with :1, :2, ... if they + " correspond to the first, second, ... group already inserted + " into backref. Later, replace :1 with \1 and so on. The group + " number w+b within backref corresponds to the group number + " s within a:source. + " w = number of '\(' in word before the current one + let w = s:Count( + \ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1') + let b = 1 " number of the current '\(' in backref + let s = d " number of the current '\(' in a:source + while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1') + \ && s < 10 + if table[s] == "-" + if w + b < 10 + " let table[s] = w + b + let table = strpart(table, 0, s) .. (w+b) .. strpart(table, s+1) + endif + let b = b + 1 + let s = s + 1 + else + execute s:Ref(backref, b, "start", "len") + let ref = strpart(backref, start, len) + let backref = strpart(backref, 0, start) .. ":" .. table[s] + \ .. strpart(backref, start+len) + let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1') + endif + endwhile + let word = strpart(word, 0, i-1) .. backref .. strpart(word, i+1) + let i = matchend(word, s:notslash .. '\\\d') - 1 + endwhile + let word = substitute(word, s:notslash .. '\zs:', '\\', 'g') + if a:output == "table" + return table + elseif a:output == "word" + return word + else + return table .. word + endif + endfun + + " Assume a:comma = ",". Then the format for a:patterns and a:1 is + " a:patterns = ",,..." + " a:1 = ",,..." + " If is the first pattern that matches a:string then return + " if no optional arguments are given; return , if a:1 is given. + 1 0.000002 fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) + let tail = (a:patterns =~ a:comma .. "$" ? a:patterns : a:patterns .. a:comma) + let i = matchend(tail, s:notslash .. a:comma) + if a:0 + let alttail = (a:1 =~ a:comma .. "$" ? a:1 : a:1 .. a:comma) + let j = matchend(alttail, s:notslash .. a:comma) + endif + let current = strpart(tail, 0, i-1) + if a:branch == "" + let currpat = current + else + let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') + endif + " un-escape \, to , + let currpat = substitute(currpat, '\\,', ',', 'g') + while a:string !~ a:prefix .. currpat .. a:suffix + let tail = strpart(tail, i) + let i = matchend(tail, s:notslash .. a:comma) + if i == -1 + return -1 + endif + let current = strpart(tail, 0, i-1) + if a:branch == "" + let currpat = current + else + let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') + endif + if a:0 + let alttail = strpart(alttail, j) + let j = matchend(alttail, s:notslash .. a:comma) + endif + endwhile + if a:0 + let current = current .. a:comma .. strpart(alttail, 0, j-1) + endif + return current + endfun + + 1 0.000001 fun! matchit#Match_debug() + let b:match_debug = 1 " Save debugging information. + " pat = all of b:match_words with backrefs parsed + amenu &Matchit.&pat :echo b:match_pat + " match = bit of text that is recognized as a match + amenu &Matchit.&match :echo b:match_match + " curcol = cursor column of the start of the matching text + amenu &Matchit.&curcol :echo b:match_col + " wholeBR = matching group, original version + amenu &Matchit.wh&oleBR :echo b:match_wholeBR + " iniBR = 'if' piece, original version + amenu &Matchit.ini&BR :echo b:match_iniBR + " ini = 'if' piece, with all backrefs resolved from match + amenu &Matchit.&ini :echo b:match_ini + " tail = 'else\|endif' piece, with all backrefs resolved from match + amenu &Matchit.&tail :echo b:match_tail + " fin = 'endif' piece, with all backrefs resolved from match + amenu &Matchit.&word :echo b:match_word + " '\'.d in ini refers to the same thing as '\'.table[d] in word. + amenu &Matchit.t&able :echo '0:' .. b:match_table .. ':9' + endfun + + " Jump to the nearest unmatched "(" or "if" or "" if a:spflag == "bW" + " or the nearest unmatched "" or "endif" or ")" if a:spflag == "W". + " Return a "mark" for the original position, so that + " let m = MultiMatch("bW", "n") ... call winrestview(m) + " will return to the original position. If there is a problem, do not + " move the cursor and return {}, unless a count is given, in which case + " go up or down as many levels as possible and again return {}. + " TODO This relies on the same patterns as % matching. It might be a good + " idea to give it its own matching patterns. + 1 0.000001 fun! matchit#MultiMatch(spflag, mode) + let restore_options = s:RestoreOptions() + let startpos = [line("."), col(".")] + " save v:count1 variable, might be reset from the restore_cursor command + let level = v:count1 + if a:mode == "o" && mode(1) !~# '[vV]' + exe "norm! v" + endif + + " First step: if not already done, set the script variables + " s:do_BR flag for whether there are backrefs + " s:pat parsed version of b:match_words + " s:all regexp based on s:pat and the default groups + " This part is copied and slightly modified from matchit#Match_wrapper(). + if !exists("b:match_words") || b:match_words == "" + let match_words = "" + " Allow b:match_words = "GetVimMatchWords()" . + elseif b:match_words =~ ":" + let match_words = b:match_words + else + execute "let match_words =" b:match_words + endif + if (match_words != s:last_words) || (&mps != s:last_mps) || + \ exists("b:match_debug") + let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. + \ '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\>:#\s*endif\>' + let s:last_mps = &mps + let match_words = match_words .. (strlen(match_words) ? "," : "") .. default + let s:last_words = match_words + if match_words !~ s:notslash .. '\\\d' + let s:do_BR = 0 + let s:pat = match_words + else + let s:do_BR = 1 + let s:pat = s:ParseWords(match_words) + endif + let s:all = '\%(' .. substitute(s:pat, '[,:]\+', '\\|', 'g') .. '\)' + if exists("b:match_debug") + let b:match_pat = s:pat + endif + " Reconstruct the version with unresolved backrefs. + let s:patBR = substitute(match_words .. ',', + \ s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') + endif + + " Second step: figure out the patterns for searchpair() + " and save the screen, cursor position, and 'ignorecase'. + " - TODO: A lot of this is copied from matchit#Match_wrapper(). + " - maybe even more functionality should be split off + " - into separate functions! + let openlist = split(s:pat .. ',', s:notslash .. '\zs:.\{-}' .. s:notslash .. ',') + let midclolist = split(',' .. s:pat, s:notslash .. '\zs,.\{-}' .. s:notslash .. ':') + call map(midclolist, {-> split(v:val, s:notslash .. ':')}) + let closelist = [] + let middlelist = [] + call map(midclolist, {i,v -> [extend(closelist, v[-1 : -1]), + \ extend(middlelist, v[0 : -2])]}) + call map(openlist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) + call map(middlelist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) + call map(closelist, {i,v -> v =~# s:notslash .. '\\|' ? '\%(' .. v .. '\)' : v}) + let open = join(openlist, ',') + let middle = join(middlelist, ',') + let close = join(closelist, ',') + if exists("b:match_skip") + let skip = b:match_skip + elseif exists("b:match_comment") " backwards compatibility and testing! + let skip = "r:" .. b:match_comment + else + let skip = 's:comment\|string' + endif + let skip = s:ParseSkip(skip) + let view = winsaveview() + + " Third step: call searchpair(). + " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'. + let openpat = substitute(open, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') + let openpat = substitute(openpat, ',', '\\|', 'g') + let closepat = substitute(close, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') + let closepat = substitute(closepat, ',', '\\|', 'g') + let middlepat = substitute(middle, '\%(' .. s:notslash .. '\)\@<=\\(', '\\%(', 'g') + let middlepat = substitute(middlepat, ',', '\\|', 'g') + + if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) + \ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight') + let skip = '0' + else + try + execute "if " .. skip .. "| let skip = '0' | endif" + catch /^Vim\%((\a\+)\)\=:E363/ + " We won't find anything, so skip searching, should keep Vim responsive. + return {} + endtry + endif + mark ' + while level + if searchpair(openpat, middlepat, closepat, a:spflag, skip) < 1 + call s:CleanUp(restore_options, a:mode, startpos) + return {} + endif + let level = level - 1 + endwhile + + " Restore options and return a string to restore the original position. + call s:CleanUp(restore_options, a:mode, startpos) + return view + endfun + + " Search backwards for "if" or "while" or "" or ... + " and return "endif" or "endwhile" or "" or ... . + " For now, this uses b:match_words and the same script variables + " as matchit#Match_wrapper() . Later, it may get its own patterns, + " either from a buffer variable or passed as arguments. + " fun! s:Autocomplete() + " echo "autocomplete not yet implemented :-(" + " if !exists("b:match_words") || b:match_words == "" + " return "" + " end + " let startpos = matchit#MultiMatch("bW") + " + " if startpos == "" + " return "" + " endif + " " - TODO: figure out whether 'if' or '' matched, and construct + " " - the appropriate closing. + " let matchline = getline(".") + " let curcol = col(".") - 1 + " " - TODO: Change the s:all argument if there is a new set of match pats. + " let regexp = s:Wholematch(matchline, s:all, curcol) + " let suf = strlen(matchline) - matchend(matchline, regexp) + " let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(') + " let suffix = (suf ? '\).\{' . suf . '}$' : '\)$') + " " Reconstruct the version with unresolved backrefs. + " let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g') + " let patBR = substitute(patBR, ':\{2,}', ':', "g") + " " Now, set group and groupBR to the matching group: 'if:endif' or + " " 'while:endwhile' or whatever. + " let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR) + " let i = matchend(group, s:notslash . ",") + " let groupBR = strpart(group, i) + " let group = strpart(group, 0, i-1) + " " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix + " if s:do_BR + " let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) + " endif + " " let g:group = group + " + " " - TODO: Construct the closing from group. + " let fake = "end" . expand("") + " execute startpos + " return fake + " endfun + + " Close all open structures. "Get the heck out of here!" + " fun! s:Gthhoh() + " let close = s:Autocomplete() + " while strlen(close) + " put=close + " let close = s:Autocomplete() + " endwhile + " endfun + + " Parse special strings as typical skip arguments for searchpair(): + " s:foo becomes (current syntax item) =~ foo + " S:foo becomes (current syntax item) !~ foo + " r:foo becomes (line before cursor) =~ foo + " R:foo becomes (line before cursor) !~ foo + " t:foo becomes (current treesitter captures) =~ foo + " T:foo becomes (current treesitter captures) !~ foo + 1 0.000001 fun! s:ParseSkip(str) + let skip = a:str + if skip[1] == ":" + if skip[0] ==# "t" || skip[0] ==# "s" && &syntax != 'on' && exists("b:ts_highlight") + let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') != -1" + elseif skip[0] ==# "T" || skip[0] ==# "S" && &syntax != 'on' && exists("b:ts_highlight") + let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') == -1" + elseif skip[0] ==# "s" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .. + \ strpart(skip,2) .. "'" + elseif skip[0] ==# "S" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .. + \ strpart(skip,2) .. "'" + elseif skip[0] ==# "r" + let skip = "strpart(getline('.'),0,col('.'))=~'" .. strpart(skip,2) .. "'" + elseif skip[0] ==# "R" + let skip = "strpart(getline('.'),0,col('.'))!~'" .. strpart(skip,2) .. "'" + endif + endif + return skip + endfun + + 1 0.000024 0.000004 let &cpo = s:save_cpo + 1 0.000002 unlet s:save_cpo + + " vim:sts=2:sw=2:et: + +SCRIPT C:\Users\User\AppData\Local\nvim-data\lazy\telescope.nvim\ftplugin\TelescopePrompt.lua +Sourced 1 time +Total time: 0.000373 + Self time: 0.000373 + +count total (s) self (s) + -- Don't wrap textwidth things + vim.opt_local.formatoptions:remove "t" + vim.opt_local.formatoptions:remove "c" + + -- Don't include `showbreak` when calculating strdisplaywidth + vim.opt_local.wrap = false + + -- There's also no reason to enable textwidth here anyway + vim.opt_local.textwidth = 0 + vim.opt_local.scrollbind = false + + vim.opt_local.signcolumn = "no" + +SCRIPT C:\Users\User\AppData\Local\nvim-data\lazy\telescope.nvim\ftplugin\TelescopeResults.lua +Sourced 1 time +Total time: 0.000325 + Self time: 0.000325 + +count total (s) self (s) + -- Don't have scrolloff, it makes things weird. + vim.opt_local.scrolloff = 0 + vim.opt_local.scrollbind = false + + vim.opt_local.signcolumn = "no" + +SCRIPT C:/Users/User/AppData/Local/nvim-data/lazy/conform.nvim/plugin/conform.lua +Sourced 1 time +Total time: 0.000309 + Self time: 0.000309 + +count total (s) self (s) + vim.api.nvim_create_user_command("ConformInfo", function() + require("conform.health").show_window() + end, { desc = "Show information about Conform formatters" }) + +FUNCTION 23_Slash() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:29 +Called 3 times +Total time: 0.000011 + Self time: 0.000011 + +count total (s) self (s) + 3 0.000009 return tr(a:path, '\', '/') + +FUNCTION 57_InsertRefs() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:291 +Called 8 times +Total time: 0.002126 + Self time: 0.001618 + +count total (s) self (s) + 8 0.000071 if a:matchline !~ a:prefix .. substitute(a:group, s:notslash .. '\zs:', '\\|', 'g') .. a:suffix + return a:group + 8 0.000003 endif + 8 0.000029 let i = matchend(a:groupBR, s:notslash .. ':') + 8 0.000012 let ini = strpart(a:groupBR, 0, i-1) + 8 0.000011 let tailBR = strpart(a:groupBR, i) + 8 0.000444 0.000044 let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix, a:groupBR) + 8 0.000028 let i = matchend(word, s:notslash .. ":") + 8 0.000011 let wordBR = strpart(word, i) + 8 0.000011 let word = strpart(word, 0, i-1) + " Now, a:matchline =~ a:prefix . word . a:suffix + 8 0.000007 if wordBR != ini + 3 0.000119 0.000011 let table = s:Resolve(ini, wordBR, "table") + 5 0.000002 else + 5 0.000003 let table = "" + 5 0.000003 let d = 0 + 55 0.000049 while d < 10 + 50 0.000151 if tailBR =~ s:notslash .. '\\' .. d + let table = table .. d + 50 0.000015 else + 50 0.000047 let table = table .. "-" + 50 0.000015 endif + 50 0.000032 let d = d + 1 + 55 0.000019 endwhile + 8 0.000002 endif + 8 0.000005 let d = 9 + 80 0.000035 while d + 72 0.000183 if table[d] != "-" + let backref = substitute(a:matchline, a:prefix .. word .. a:suffix, '\' .. table[d], "") + " Are there any other characters that should be escaped? + let backref = escape(backref, '*,:') + execute s:Ref(ini, d, "start", "len") + let ini = strpart(ini, 0, start) .. backref .. strpart(ini, start+len) + let tailBR = substitute(tailBR, s:notslash .. '\zs\\' .. d, escape(backref, '\\&'), 'g') + 72 0.000020 endif + 72 0.000045 let d = d-1 + 80 0.000031 endwhile + 8 0.000013 if exists("b:match_debug") + if s:do_BR + let b:match_table = table + let b:match_word = word + else + let b:match_table = "" + let b:match_word = "" + endif + 8 0.000002 endif + 8 0.000010 return ini .. ":" .. tailBR + +FUNCTION provider#clipboard#Call() + Defined: C:\Program Files\Neovim\share\nvim\runtime\autoload\provider\clipboard.vim:344 +Called 1 time +Total time: 0.029152 + Self time: 0.000044 + +count total (s) self (s) + 1 0.000010 if get(s:, 'here', v:false) " Clipboard provider must not recurse. #7184 + return 0 + 1 0.000002 endif + 1 0.000004 let s:here = v:true + 1 0.000001 try + 1 0.029125 0.000017 return call(s:clipboard[a:method],a:args,s:clipboard) + 1 0.000002 finally + 1 0.000002 let s:here = v:false + 1 0.000001 endtry + +FUNCTION 47_AlreadyInitialized() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:76 +Called 28 times +Total time: 0.000456 + Self time: 0.000216 + +count total (s) self (s) + 28 0.000440 0.000200 return copilot#util#Defer(function(a:fn, [self] + a:000)) + +FUNCTION 47_NvimIsAttached() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:447 +Called 8 times +Total time: 0.000135 + Self time: 0.000135 + +count total (s) self (s) + 8 0.000131 return bufloaded(a:bufnr) ? luaeval('vim.lsp.buf_is_attached(_A[1], _A[2])', [a:bufnr, self.id]) : v:false + +FUNCTION 47_NvimDoNotify() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:487 +Called 3 times +Total time: 0.000088 + Self time: 0.000088 + +count total (s) self (s) + 3 0.000086 return eval("v:lua.require'_copilot'.rpc_notify(a:client.id, a:method, a:params)") + +FUNCTION copilot#logger#Debug() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\logger.vim:42 +Called 25 times +Total time: 0.000081 + Self time: 0.000081 + +count total (s) self (s) + 25 0.000048 if empty(get(g:, 'copilot_debug')) + 25 0.000012 return + endif + call copilot#logger#Raw(4, a:000) + +FUNCTION 47_NvimNotify() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:483 +Called 3 times +Total time: 0.000063 + Self time: 0.000023 + +count total (s) self (s) + 3 0.000062 0.000021 call self.AfterInitialized(function('s:NvimDoNotify'), a:method, a:params) + +FUNCTION 42_Attach() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:423 +Called 1 time +Total time: 0.002378 + Self time: 0.000015 + +count total (s) self (s) + 1 0.000001 try + 1 0.002372 0.000010 return copilot#Client().Attach(a:bufnr) + catch + call copilot#logger#Exception() + 1 0.000001 endtry + +FUNCTION 47_Cancel() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:289 +Called 25 times +Total time: 0.000229 + Self time: 0.000229 + +count total (s) self (s) + 25 0.000077 if has_key(self.requests, get(a:request, 'id', '')) + call self.Notify('$/cancelRequest', {'id': a:request.id}) + call s:RejectRequest(remove(self.requests, a:request.id), s:error_canceled) + 25 0.000010 endif + +FUNCTION 57_ParseSkip() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:767 +Called 8 times +Total time: 0.000170 + Self time: 0.000170 + +count total (s) self (s) + 8 0.000007 let skip = a:str + 8 0.000008 if skip[1] == ":" + 8 0.000031 if skip[0] ==# "t" || skip[0] ==# "s" && &syntax != 'on' && exists("b:ts_highlight") + 8 0.000020 let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') != -1" + elseif skip[0] ==# "T" || skip[0] ==# "S" && &syntax != 'on' && exists("b:ts_highlight") + let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') == -1" + elseif skip[0] ==# "s" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .. strpart(skip,2) .. "'" + elseif skip[0] ==# "S" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .. strpart(skip,2) .. "'" + elseif skip[0] ==# "r" + let skip = "strpart(getline('.'),0,col('.'))=~'" .. strpart(skip,2) .. "'" + elseif skip[0] ==# "R" + let skip = "strpart(getline('.'),0,col('.'))!~'" .. strpart(skip,2) .. "'" + 8 0.000003 endif + 8 0.000002 endif + 8 0.000005 return skip + +FUNCTION 47_Callback() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:807 +Called 25 times +Total time: 0.004243 + Self time: 0.000267 + +count total (s) self (s) + 25 0.000064 call remove(a:request.waiting, a:timer) + 25 0.000037 if has_key(a:request, a:type) + 25 0.004105 0.000130 call a:callback(a:request[a:type]) + 25 0.000006 endif + +FUNCTION 57_ParseWords() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:349 +Called 8 times +Total time: 0.008212 + Self time: 0.003673 + +count total (s) self (s) + 8 0.000357 let groups = substitute(a:groups .. ",", s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + 8 0.000192 let groups = substitute(groups, s:notslash .. '\zs:\{2,}', ':', 'g') + 8 0.000006 let parsed = "" + 72 0.000168 while groups =~ '[^,:]' + 64 0.000305 let i = matchend(groups, s:notslash .. ':') + 64 0.000341 let j = matchend(groups, s:notslash .. ',') + 64 0.000110 let ini = strpart(groups, 0, i-1) + 64 0.000112 let tail = strpart(groups, i, j-i-1) .. ":" + 64 0.000085 let groups = strpart(groups, j) + 64 0.000072 let parsed = parsed .. ini + 64 0.000247 let i = matchend(tail, s:notslash .. ':') + 152 0.000090 while i != -1 + " In 'if:else:endif', ini='if' and word='else' and then word='endif'. + 88 0.000130 let word = strpart(tail, 0, i-1) + 88 0.000103 let tail = strpart(tail, i) + 88 0.000283 let i = matchend(tail, s:notslash .. ':') + 88 0.004972 0.000433 let parsed = parsed .. ":" .. s:Resolve(ini, word, "word") + 152 0.000058 endwhile " Now, tail has been used up. + 64 0.000068 let parsed = parsed .. "," + 72 0.000026 endwhile " groups =~ '[^,:]' + 8 0.000034 let parsed = substitute(parsed, ',$', '', '') + 8 0.000006 return parsed + +FUNCTION 43_RunDeferred() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\util.vim:12 +Called 74 times +Total time: 0.009910 + Self time: 0.000797 + +count total (s) self (s) + 74 0.000192 if empty(s:deferred) + 37 0.000027 return + 37 0.000013 endif + 37 0.000115 let Fn = remove(s:deferred, 0) + 37 0.000154 call timer_start(0, function('s:RunDeferred')) + 37 0.009303 0.000190 call call(Fn, []) + +FUNCTION copilot#Client() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:48 +Called 40 times +Total time: 0.000576 + Self time: 0.000196 + +count total (s) self (s) + 40 0.000526 0.000145 call s:Start() + 40 0.000029 return s:client + +FUNCTION copilot#OnInsertEnter() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:453 +Called 4 times +Total time: 0.000980 + Self time: 0.000021 + +count total (s) self (s) + 4 0.000978 0.000018 return copilot#Schedule() + +FUNCTION 47_StatusNotification() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:649 +Called 25 times +Total time: 0.000088 + Self time: 0.000088 + +count total (s) self (s) + 25 0.000069 let a:instance.status = a:params + +FUNCTION copilot#Suggest() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:391 +Called 25 times +Total time: 0.013665 + Self time: 0.000687 + +count total (s) self (s) + 25 0.000345 0.000173 if !s:Running() + return '' + 25 0.000010 endif + 25 0.000021 try + 25 0.013112 0.000306 call copilot#Complete(function('s:HandleTriggerResult'), function('s:HandleTriggerError')) + catch + call copilot#logger#Exception() + 25 0.000028 endtry + 25 0.000015 return '' + +FUNCTION 47_NvimAttach() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:439 +Called 29 times +Total time: 0.004214 + Self time: 0.002121 + +count total (s) self (s) + 29 0.000049 if !bufloaded(a:bufnr) + return {'uri': '', 'version': 0} + 29 0.000010 endif + 29 0.003053 0.000960 call luaeval('pcall(vim.lsp.buf_attach_client, _A[1], _A[2])', [a:bufnr, self.id]) + 29 0.001026 return luaeval('{uri = vim.uri_from_bufnr(_A), version = vim.lsp.util.buf_versions[_A]}', a:bufnr) + +FUNCTION 23_AutoInit() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:632 +Called 2 times +Total time: 0.007378 + Self time: 0.000014 + +count total (s) self (s) + 2 0.007377 0.000012 return s:Init(1, 1, 1, 1) + +FUNCTION 57_RestoreOptions() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:34 +Called 8 times +Total time: 0.000617 + Self time: 0.000249 + +count total (s) self (s) + " In s:CleanUp(), :execute "set" restore_options . + 8 0.000015 let restore_options = "" + 8 0.000043 if get(b:, 'match_ignorecase', &ic) != &ic + 8 0.000025 let restore_options ..= (&ic ? " " : " no") .. "ignorecase" + 8 0.000257 0.000036 let &ignorecase = b:match_ignorecase + 8 0.000007 endif + 8 0.000012 if &ve != '' + let restore_options = " ve=" .. &ve .. restore_options + set ve= + 8 0.000003 endif + 8 0.000008 if &smartcase + 8 0.000013 let restore_options = " smartcase " .. restore_options + 8 0.000169 0.000022 set nosmartcase + 8 0.000003 endif + 8 0.000012 return restore_options + +FUNCTION 57_Count() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:450 +Called 24 times +Total time: 0.000443 + Self time: 0.000443 + +count total (s) self (s) + 24 0.000038 let pat = escape(a:pattern, '\\') + 24 0.000015 if a:0 > 1 + let foo = substitute(a:string, '[^' .. a:pattern .. ']', "a:1", "g") + let foo = substitute(a:string, pat, a:2, "g") + let foo = substitute(foo, '[^' .. a:2 .. ']', "", "g") + return strlen(foo) + 24 0.000007 endif + 24 0.000016 let result = 0 + 24 0.000017 let foo = a:string + 24 0.000047 let index = matchend(foo, pat) + 40 0.000028 while index != -1 + 16 0.000013 let result = result + 1 + 16 0.000020 let foo = strpart(foo, index) + 16 0.000029 let index = matchend(foo, pat) + 40 0.000016 endwhile + 24 0.000014 return result + +FUNCTION 47_RegisterWorkspaceFolderForBuffer() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:207 +Called 25 times +Total time: 0.001107 + Self time: 0.000465 + +count total (s) self (s) + 25 0.000060 let root = getbufvar(a:buf, 'workspace_folder') + 25 0.000036 if type(root) != v:t_string + return + 25 0.000009 endif + 25 0.000873 0.000231 let root = s:UriFromPath(substitute(root, '[\/]$', '', '')) + 25 0.000055 if empty(root) || has_key(a:instance.workspaceFolders, root) + 25 0.000013 return + endif + let a:instance.workspaceFolders[root] = v:true + call a:instance.Notify('workspace/didChangeWorkspaceFolders', {'event': {'added': [{'uri': root, 'name': fnamemodify(root, ':t')}], 'removed': []}}) + +FUNCTION 23_Warn() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:19 +Called 1 time +Total time: 0.000004 + Self time: 0.000004 + +count total (s) self (s) + 1 0.000001 if !get(a:000, 0, 0) + echohl WarningMsg + echo a:msg + echohl NONE + 1 0.000000 endif + 1 0.000000 return '' + +FUNCTION copilot#OnFileType() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:431 +Called 17 times +Total time: 0.001034 + Self time: 0.000179 + +count total (s) self (s) + 17 0.000962 0.000117 if empty(s:BufferDisabled()) && &l:modifiable && &l:buflisted + 1 0.000017 0.000007 call copilot#util#Defer(function('s:Attach'), bufnr('')) + 17 0.000006 endif + +FUNCTION 47_DispatchMessage() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:306 +Called 25 times +Total time: 0.000731 + Self time: 0.000643 + +count total (s) self (s) + 25 0.000021 try + 25 0.000289 0.000201 let response = {'result': call(a:handler, [a:params, a:instance])} + 25 0.000037 if response.result is# 0 + 25 0.000027 let response.result = v:null + 25 0.000010 endif + catch + call copilot#logger#Exception('lsp.request.' . a:method) + let response = {'error': {'code': -32000, 'message': v:exception}} + 25 0.000015 endtry + 25 0.000031 if a:id isnot# v:null + call s:Send(a:instance, extend({'id': a:id}, response)) + 25 0.000009 endif + 25 0.000052 if !has_key(s:notifications, a:method) + return response + 25 0.000007 endif + +FUNCTION 47_NvimRequest() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:451 +Called 25 times +Total time: 0.007738 + Self time: 0.000815 + +count total (s) self (s) + 25 0.000125 let params = deepcopy(a:params) + 25 0.005830 0.000170 let [bufnr, progress] = s:PreprocessParams(self, params) + 25 0.001120 0.000272 let request = call('s:SetUpRequest', [self, v:null, a:method, params, progress] + a:000) + 25 0.000605 0.000190 call self.AfterInitialized(function('s:NvimDoRequest'), request, bufnr) + 25 0.000017 return request + +FUNCTION 23_Guess() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:38 +Called 2 times +Total time: 0.005088 + Self time: 0.005088 + +count total (s) self (s) + 2 0.000012 let has_heredocs = a:detected.filetype =~# '^\%(perl\|php\|ruby\|[cz]\=sh\|bash\)$' + 2 0.000002 let options = {} + 2 0.000005 let heuristics = {'spaces': 0, 'hard': 0, 'soft': 0, 'checked': 0, 'indents': {}} + 2 0.000006 let tabstop = get(a:detected.options, 'tabstop', get(a:detected.defaults, 'tabstop', [8]))[0] + 2 0.000004 let softtab = repeat(' ', tabstop) + 2 0.000001 let waiting_on = '' + 2 0.000001 let prev_indent = -1 + 2 0.000001 let prev_line = '' + + 133 0.000060 for line in a:lines + 132 0.000098 if len(waiting_on) + if line =~# waiting_on + let waiting_on = '' + let prev_indent = -1 + let prev_line = '' + endif + continue + 132 0.000213 elseif line =~# '^\s*$' + 16 0.000005 continue + 116 0.000115 elseif a:detected.filetype ==# 'python' && prev_line[-1:-1] =~# '[[\({]' + let prev_indent = -1 + let prev_line = '' + continue + 116 0.000149 elseif line =~# '^=\w' && line !~# '^=\%(end\|cut\)\>' + let waiting_on = '^=\%(end\|cut\)\>' + 116 0.000169 elseif line =~# '^@@\+ -\d\+,\d\+ ' + let waiting_on = '^$' + 116 0.000246 elseif line !~# '[/<"`]' + " No need to do other checks + 3 0.000008 elseif line =~# '^\s*/\*' && line !~# '\*/' + let waiting_on = '\*/' + 3 0.000006 elseif line =~# '^\s*<\!--' && line !~# '-->' + let waiting_on = '-->' + 3 0.000014 elseif line =~# '^[^"]*"""' + let waiting_on = '^[^"]*"""' + 3 0.000003 elseif a:detected.filetype ==# 'go' && line =~# '^[^`]*`[^`]*$' + let waiting_on = '^[^`]*`[^`]*$' + 3 0.000001 elseif has_heredocs + let waiting_on = matchstr(line, '<<\s*\([''"]\=\)\zs\w\+\ze\1[^''"`<>]*$') + if len(waiting_on) + let waiting_on = '^' . waiting_on . '$' + endif + 116 0.000023 endif + + 116 0.000385 let indent = len(matchstr(substitute(line, '\t', softtab, 'g'), '^ *')) + 116 0.000111 if line =~# '^\t' + let heuristics.hard += 1 + 116 0.000221 elseif line =~# '^' . softtab + 10 0.000007 let heuristics.soft += 1 + 116 0.000025 endif + 116 0.000136 if line =~# '^ ' + 97 0.000066 let heuristics.spaces += 1 + 116 0.000026 endif + 116 0.000125 let increment = prev_indent < 0 ? 0 : indent - prev_indent + 116 0.000072 let prev_indent = indent + 116 0.000071 let prev_line = line + 116 0.000098 if increment > 1 && (increment < 4 || increment % 4 == 0) + 32 0.000037 if has_key(heuristics.indents, increment) + 31 0.000031 let heuristics.indents[increment] += 1 + 1 0.000000 else + 1 0.000001 let heuristics.indents[increment] = 1 + 32 0.000007 endif + 32 0.000020 let heuristics.checked += 1 + 116 0.000024 endif + 116 0.000190 if heuristics.checked >= 32 && (heuristics.hard > 3 || heuristics.soft > 3) && get(heuristics.indents, increment) * 2 > heuristics.checked + 1 0.000001 if heuristics.spaces + 1 0.000000 break + elseif !exists('no_space_indent') + let no_space_indent = stridx("\n" . join(a:lines, "\n"), "\n ") < 0 + if no_space_indent + break + endif + endif + break + 115 0.000022 endif + 117 0.000040 endfor + + 2 0.000004 let a:detected.heuristics[a:source] = heuristics + + 2 0.000002 let max_frequency = 0 + 3 0.000005 for [shiftwidth, frequency] in items(heuristics.indents) + 1 0.000002 if frequency > max_frequency || frequency == max_frequency && +shiftwidth < get(options, 'shiftwidth') + 1 0.000001 let options.shiftwidth = +shiftwidth + 1 0.000001 let max_frequency = frequency + 1 0.000000 endif + 3 0.000001 endfor + + 2 0.000003 if heuristics.hard && !heuristics.spaces && !has_key(a:detected.options, 'tabstop') + let options = {'expandtab': 0, 'shiftwidth': 0} + 2 0.000002 elseif heuristics.hard > heuristics.soft + let options.expandtab = 0 + let options.tabstop = tabstop + 2 0.000000 else + 2 0.000001 if heuristics.soft + 1 0.000001 let options.expandtab = 1 + 2 0.000001 endif + 2 0.000047 if heuristics.hard || has_key(a:detected.options, 'tabstop') || stridx(join(a:lines, "\n"), "\t") >= 0 + let options.tabstop = tabstop + 2 0.000004 elseif !&g:shiftwidth && has_key(options, 'shiftwidth') && !has_key(a:detected.options, 'shiftwidth') + let options.tabstop = options.shiftwidth + let options.shiftwidth = 0 + 2 0.000000 endif + 2 0.000001 endif + + 2 0.000005 call map(options, '[v:val, a:source]') + 2 0.000034 call extend(a:detected.options, options, 'keep') + +FUNCTION 42_HideDuringCompletion() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:189 +Called 87 times +Total time: 0.000229 + Self time: 0.000229 + +count total (s) self (s) + 87 0.000188 return get(g:, 'copilot_hide_during_completion', 1) + +FUNCTION 42_Trigger() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:403 +Called 25 times +Total time: 0.014642 + Self time: 0.000977 + +count total (s) self (s) + 25 0.000434 let timer = get(g:, '_copilot_timer', -1) + 25 0.000177 if a:bufnr !=# bufnr('') || a:timer isnot# timer || mode() !=# 'i' + return + 25 0.000024 endif + 25 0.000054 unlet! g:_copilot_timer + 25 0.013807 0.000142 return copilot#Suggest() + +FUNCTION copilot#client#LspHandle() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:491 +Called 25 times +Total time: 0.001770 + Self time: 0.000413 + +count total (s) self (s) + 25 0.000155 if !has_key(s:instances, a:id) + return + 25 0.000015 endif + 25 0.001537 0.000180 return s:OnMessage(s:instances[a:id], a:request) + +FUNCTION 42_Start() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:34 +Called 40 times +Total time: 0.000381 + Self time: 0.000222 + +count total (s) self (s) + 40 0.000323 0.000164 if s:Running() || exists('s:client.startup_error') + 40 0.000022 return + endif + let s:client = copilot#client#New() + +FUNCTION 47_OnMessage() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:324 +Called 25 times +Total time: 0.001357 + Self time: 0.000626 + +count total (s) self (s) + 25 0.000049 if !has_key(a:body, 'method') + return s:OnResponse(a:instance, a:body) + 25 0.000010 endif + 25 0.000044 let request = a:body + 25 0.000054 let id = get(request, 'id', v:null) + 25 0.000043 let params = get(request, 'params', v:null) + 25 0.000061 if has_key(a:instance.methods, request.method) + 25 0.000995 0.000264 return s:DispatchMessage(a:instance, request.method, a:instance.methods[request.method], id, params) + elseif id isnot# v:null + call s:Send(a:instance, {"id": id, "error": {"code": -32700, "message": "Method not found: " . request.method}}) + call copilot#logger#Debug('Unexpected request ' . request.method . ' called with ' . json_encode(params)) + elseif request.method !~# '^\$/' + call copilot#logger#Debug('Unexpected notification ' . request.method . ' called with ' . json_encode(params)) + endif + +FUNCTION 42_BufferDisabled() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:121 +Called 78 times +Total time: 0.003640 + Self time: 0.003640 + +count total (s) self (s) + 78 0.001084 if &buftype =~# '^\%(help\|prompt\|quickfix\|terminal\)$' + 13 0.000010 return 5 + 65 0.000040 endif + 65 0.000135 if exists('b:copilot_disabled') + return empty(b:copilot_disabled) ? 0 : 3 + 65 0.000022 endif + 65 0.000085 if exists('b:copilot_enabled') + return empty(b:copilot_enabled) ? 4 : 0 + 65 0.000020 endif + 65 0.000593 let short = empty(&l:filetype) ? '.' : split(&l:filetype, '\.', 1)[0] + 65 0.000123 let config = {} + 65 0.000241 if type(get(g:, 'copilot_filetypes')) == v:t_dict + let config = g:copilot_filetypes + 65 0.000019 endif + 65 0.000103 if has_key(config, &l:filetype) + return empty(config[&l:filetype]) + 65 0.000095 elseif has_key(config, short) + return empty(config[short]) + 65 0.000064 elseif has_key(config, '*') + return empty(config['*']) + 65 0.000022 else + 65 0.000163 return get(s:filetype_defaults, short, 1) == 0 ? 2 : 0 + endif + +FUNCTION 47_PreprocessParams() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:220 +Called 25 times +Total time: 0.005660 + Self time: 0.002776 + +count total (s) self (s) + 25 0.000030 let bufnr = v:null + 50 0.000242 for doc in filter([get(a:params, 'textDocument', {})], 'type(get(v:val, "uri", "")) == v:t_number') + 25 0.000029 let bufnr = doc.uri + 25 0.001288 0.000180 call s:RegisterWorkspaceFolderForBuffer(a:instance, bufnr) + 25 0.002707 0.000930 call extend(doc, a:instance.Attach(bufnr)) + 50 0.000043 endfor + 25 0.000033 let progress_tokens = [] + 125 0.000143 for key in keys(a:params) + 100 0.000310 if key =~# 'Token$' && type(a:params[key]) == v:t_func + let s:progress_token_id += 1 + let a:instance.progress[s:progress_token_id] = a:params[key] + call add(progress_tokens, s:progress_token_id) + let a:params[key] = s:progress_token_id + 100 0.000033 endif + 125 0.000049 endfor + 25 0.000038 return [bufnr, progress_tokens] + +FUNCTION 23_ModelineOptions() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:182 +Called 2 times +Total time: 0.000253 + Self time: 0.000158 + +count total (s) self (s) + 2 0.000002 let options = {} + 2 0.000005 if !&l:modeline && (&g:modeline || s:Capture('setlocal') =~# '\\\@' && s:Capture('verbose setglobal modeline?') !=# s:Capture('verbose setlocal modeline?')) + 1 0.000001 return options + 1 0.000000 endif + 1 0.000002 let modelines = get(b:, 'sleuth_modelines', get(g:, 'sleuth_modelines', 5)) + 1 0.000002 if line('$') > 2 * modelines + 1 0.000005 let lnums = range(1, modelines) + range(line('$') - modelines + 1, line('$')) + else + let lnums = range(1, line('$')) + 1 0.000000 endif + 11 0.000005 for lnum in lnums + 10 0.000210 0.000115 if s:ParseOptions(split(matchstr(getline(lnum), '\%(\S\@47_RequestCancel() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:296 +Called 25 times +Total time: 0.000803 + Self time: 0.000453 + +count total (s) self (s) + 25 0.000278 0.000157 let instance = self.Client() + 25 0.000036 if !empty(instance) + 25 0.000345 0.000116 call instance.Cancel(self) + elseif get(self, 'status', '') ==# 'running' + call s:RejectRequest(self, s:error_canceled) + 25 0.000009 endif + 25 0.000018 return self + +FUNCTION 23_DetectDeclared() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:488 +Called 2 times +Total time: 0.001585 + Self time: 0.000314 + +count total (s) self (s) + 2 0.000024 0.000017 let detected = {'bufname': s:Slash(@%), 'declared': {}} + 2 0.000016 let absolute_or_empty = detected.bufname =~# '^$\|^\a\+:\|^/' + 2 0.000009 if &l:buftype =~# '^\%(nowrite\)\=$' && !absolute_or_empty + let detected.bufname = substitute(s:Slash(getcwd()), '/\=$', '/', '') . detected.bufname + let absolute_or_empty = 1 + 2 0.000001 endif + 2 0.000005 let detected.path = absolute_or_empty ? detected.bufname : '' + 2 0.000018 let pre = substitute(matchstr(detected.path, '^\a\a\+\ze:'), '^\a', '\u&', 'g') + 2 0.000004 if len(pre) && exists('*' . pre . 'Real') + let detected.path = s:Slash(call(pre . 'Real', [detected.path])) + 2 0.000001 endif + + 2 0.000001 try + 2 0.000007 if len(detected.path) && exists('*ExcludeBufferFromDiscovery') && !empty(ExcludeBufferFromDiscovery(detected.path, 'sleuth')) + let detected.path = '' + 2 0.000001 endif + catch + 2 0.000001 endtry + 2 0.001000 0.000117 let [detected.editorconfig, detected.root] = s:DetectEditorConfig(detected.path) + 2 0.000175 0.000047 call extend(detected.declared, s:EditorConfigToOptions(detected.editorconfig)) + 2 0.000300 0.000047 call extend(detected.declared, s:ModelineOptions()) + 2 0.000001 return detected + +FUNCTION 47_NvimDoRequest() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:459 +Called 25 times +Total time: 0.006022 + Self time: 0.005065 + +count total (s) self (s) + 25 0.000029 let request = a:request + 25 0.000061 if has_key(a:client, 'client_id') && !has_key(a:client, 'kill') + 25 0.005489 0.004531 let request.id = eval("v:lua.require'_copilot'.lsp_request(a:client.id, a:request.method, a:request.params, a:bufnr)") + 25 0.000028 endif + 25 0.000052 if request.id isnot# v:null + 25 0.000081 let a:client.requests[request.id] = request + else + if has_key(a:client, 'client_id') + call copilot#client#LspExit(a:client.client_id, -1, -1) + endif + call copilot#util#Defer(function('s:RejectRequest'), request, s:error_connection_inactive) + 25 0.000010 endif + 25 0.000022 return request + +FUNCTION copilot#client#Error() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:822 +Called 25 times +Total time: 0.000163 + Self time: 0.000163 + +count total (s) self (s) + 25 0.000035 if has_key(a:request, 'reject') + 25 0.000038 call add(a:request.reject, a:callback) + elseif has_key(a:request, 'error') + let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', a:callback]))] = 1 + 25 0.000008 endif + +FUNCTION copilot#OnCursorMovedI() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:465 +Called 57 times +Total time: 0.014478 + Self time: 0.000363 + +count total (s) self (s) + 57 0.014437 0.000322 return copilot#Schedule() + +FUNCTION 23_DetectHeuristics() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:513 +Called 2 times +Total time: 0.005403 + Self time: 0.000282 + +count total (s) self (s) + 2 0.000002 let detected = a:into + 2 0.000007 let filetype = split(&l:filetype, '\.', 1)[0] + 2 0.000003 if get(detected, 'filetype', '*') ==# filetype + return detected + 2 0.000000 endif + 2 0.000002 let detected.filetype = filetype + 2 0.000003 let options = copy(detected.declared) + 2 0.000002 let detected.options = options + 2 0.000002 let detected.heuristics = {} + 2 0.000002 if has_key(detected, 'patterns') + call remove(detected, 'patterns') + 2 0.000001 endif + 2 0.000027 0.000008 let detected.defaults = s:UserOptions(filetype, 'defaults') + 2 0.000009 if empty(filetype) || !get(b:, 'sleuth_automatic', 1) || empty(get(b:, 'sleuth_heuristics', get(g:, 'sleuth_' . filetype . '_heuristics', get(g:, 'sleuth_heuristics', 1)))) + return detected + 2 0.000000 endif + 2 0.000011 0.000005 if s:Ready(detected) + return detected + 2 0.000000 endif + + 2 0.000043 let lines = getline(1, 1024) + 2 0.005097 0.000009 call s:Guess(detected.bufname, detected, lines) + 2 0.000011 0.000007 if s:Ready(detected) + 1 0.000001 return detected + 1 0.000003 elseif get(options, 'shiftwidth', [4])[0] < 4 && stridx(join(lines, "\n"), "\t") == -1 + let options.expandtab = [1, detected.bufname] + return detected + 1 0.000000 endif + 1 0.000002 let dir = len(detected.path) ? fnamemodify(detected.path, ':h') : '' + 1 0.000111 0.000107 let root = len(detected.root) ? fnamemodify(detected.root, ':h') : dir ==# s:Slash(expand('~')) ? dir : fnamemodify(dir, ':h') + 1 0.000006 if detected.bufname =~# '^\a\a\+:' || root ==# '.' || !isdirectory(root) + 1 0.000001 let dir = '' + 1 0.000000 endif + 1 0.000003 let c = get(b:, 'sleuth_neighbor_limit', get(g:, 'sleuth_neighbor_limit', 8)) + 1 0.000001 if c <= 0 || empty(dir) + 1 0.000001 let detected.patterns = [] + elseif type(get(b:, 'sleuth_globs')) == type([]) + let detected.patterns = b:sleuth_globs + elseif type(get(g:, 'sleuth_' . detected.filetype . '_globs')) == type([]) + let detected.patterns = get(g:, 'sleuth_' . detected.filetype . '_globs') + else + let detected.patterns = ['*' . matchstr(detected.bufname, '/\@ 0 && dir !~# '^$\|^//[^/]*$' && dir !=# fnamemodify(dir, ':h') + for pattern in detected.patterns + for neighbor in split(glob(dir.'/'.pattern), "\n")[0:7] + if neighbor !=# detected.path && filereadable(neighbor) + call s:Guess(neighbor, detected, readfile(neighbor, '', 256)) + let c -= 1 + endif + if s:Ready(detected) + return detected + endif + if c <= 0 + break + endif + endfor + if c <= 0 + break + endif + endfor + if len(dir) <= len(root) + break + endif + let dir = fnamemodify(dir, ':h') + 1 0.000001 endwhile + 1 0.000001 if !has_key(options, 'shiftwidth') + 1 0.000002 let detected.options = copy(detected.declared) + 1 0.000000 endif + 1 0.000001 return detected + +FUNCTION 41_SynSet() + Defined: C:\Program Files\Neovim\share\nvim\runtime\syntax\synload.vim:27 +Called 17 times +Total time: 0.100190 + Self time: 0.100190 + +count total (s) self (s) + " clear syntax for :set syntax=OFF and any syntax name that doesn't exist + 17 0.000054 syn clear + 17 0.000032 if exists("b:current_syntax") + unlet b:current_syntax + 17 0.000007 endif + + 17 0.000042 0verbose let s = expand("") + 17 0.000019 if s == "ON" + " :set syntax=ON + if &filetype == "" + echohl ErrorMsg + echo "filetype unknown" + echohl None + endif + let s = &filetype + 17 0.000015 elseif s == "OFF" + let s = "" + 17 0.000005 endif + + 17 0.000011 if s != "" + " Load the syntax file(s). When there are several, separated by dots, + " load each in sequence. Skip empty entries. + 32 0.000082 for name in split(s, '\.') + 16 0.000018 if !empty(name) + " XXX: "[.]" in the first pattern makes it a wildcard on Windows + 16 0.089675 exe $'runtime! syntax/{name}[.]{{vim,lua}} syntax/{name}/*.{{vim,lua}}' + 16 0.000027 endif + 32 0.009908 endfor + 17 0.000009 endif + +FUNCTION 23_EditorConfigToOptions() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:329 +Called 2 times +Total time: 0.000128 + Self time: 0.000128 + +count total (s) self (s) + 2 0.000002 let options = {} + 2 0.000007 let pairs = map(copy(a:pairs), 'v:val[0]') + 2 0.000003 let sources = map(copy(a:pairs), 'v:val[1:-1]') + 2 0.000003 call filter(pairs, 'v:val !=? "unset"') + + 2 0.000003 if get(pairs, 'indent_style', '') ==? 'tab' + let options.expandtab = [0] + sources.indent_style + 2 0.000003 elseif get(pairs, 'indent_style', '') ==? 'space' + let options.expandtab = [1] + sources.indent_style + 2 0.000001 endif + + 2 0.000011 if get(pairs, 'indent_size', '') =~? '^[1-9]\d*$\|^tab$' + let options.shiftwidth = [str2nr(pairs.indent_size)] + sources.indent_size + if &g:shiftwidth == 0 && !has_key(pairs, 'tab_width') && pairs.indent_size !=? 'tab' + let options.tabstop = options.shiftwidth + let options.shiftwidth = [0] + sources.indent_size + endif + 2 0.000000 endif + + 2 0.000008 if get(pairs, 'tab_width', '') =~? '^[1-9]\d*$' + let options.tabstop = [str2nr(pairs.tab_width)] + sources.tab_width + if !has_key(pairs, 'indent_size') && get(pairs, 'indent_style', '') ==? 'tab' + let options.shiftwidth = [0] + options.tabstop[1:-1] + endif + 2 0.000000 endif + + 2 0.000006 if get(pairs, 'max_line_length', '') =~? '^[1-9]\d*$\|^off$' + let options.textwidth = [str2nr(pairs.max_line_length)] + sources.max_line_length + 2 0.000000 endif + + 2 0.000007 if get(pairs, 'insert_final_newline', '') =~? '^true$\|^false$' + let options.endofline = [pairs.insert_final_newline ==? 'true'] + sources.insert_final_newline + let options.fixendofline = copy(options.endofline) + 2 0.000000 endif + + 2 0.000004 let eol = tolower(get(pairs, 'end_of_line', '')) + 2 0.000003 if has_key(s:editorconfig_fileformat, eol) + let options.fileformat = [s:editorconfig_fileformat[eol]] + sources.end_of_line + 2 0.000000 endif + + 2 0.000003 let charset = tolower(get(pairs, 'charset', '')) + 2 0.000003 if has_key(s:editorconfig_bomb, charset) + let options.bomb = [s:editorconfig_bomb[charset]] + sources.charset + let options.fileencoding = [substitute(charset, '\C-bom$', '', '')] + sources.charset + 2 0.000000 endif + + 2 0.000003 let filetype = tolower(get(pairs, 'vim_filetype', 'unset')) + 2 0.000002 if filetype !=# 'unset' && filetype =~# '^[.a-z0-9_-]*$' + let options.filetype = [substitute(filetype, '^\.\+\|\.\+$', '', 'g')] + sources.vim_filetype + 2 0.000000 endif + + 2 0.000001 return options + +FUNCTION 42_Focus() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:437 +Called 8 times +Total time: 0.000625 + Self time: 0.000147 + +count total (s) self (s) + 8 0.000339 0.000081 if s:Running() && copilot#Client().IsAttached(a:bufnr) + 3 0.000259 0.000039 call copilot#Client().Notify('textDocument/didFocus', {'textDocument': {'uri': copilot#Client().Attach(a:bufnr).uri}}) + 8 0.000003 endif + +FUNCTION copilot#OnBufUnload() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:469 +Called 21 times +Total time: 0.000007 + Self time: 0.000007 + +count total (s) self (s) + +FUNCTION 47_RejectRequest() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:49 +Called 25 times +Total time: 0.001265 + Self time: 0.001185 + +count total (s) self (s) + 25 0.000030 if a:request.status !=# 'running' + return + 25 0.000007 endif + 25 0.000039 let a:request.waiting = {} + 25 0.000068 call remove(a:request, 'resolve') + 25 0.000044 let reject = remove(a:request, 'reject') + 25 0.000024 let a:request.status = 'error' + 25 0.000063 let a:request.error = deepcopy(a:error) + 50 0.000093 for Cb in reject + 25 0.000209 let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', Cb]))] = 1 + 50 0.000025 endfor + 25 0.000092 if index([s:error_canceled.code, s:error_connection_inactive.code], a:error.code) != -1 + return + 25 0.000007 endif + 25 0.000159 let msg = 'Method ' . a:request.method . ' errored with E' . a:error.code . ': ' . json_encode(a:error.message) + 25 0.000027 if empty(reject) + call copilot#logger#Error(msg) + 25 0.000008 else + 25 0.000184 0.000103 call copilot#logger#Debug(msg) + 25 0.000009 endif + +FUNCTION 23_Apply() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:396 +Called 2 times +Total time: 0.000238 + Self time: 0.000234 + +count total (s) self (s) + 2 0.000036 let options = extend(copy(a:detected.defaults), a:detected.options) + 2 0.000006 if get(a:detected.defaults, 'shiftwidth', [1])[0] == 0 && get(options, 'shiftwidth', [0])[0] != 0 && !has_key(a:detected.declared, 'tabstop') + let options.tabstop = options.shiftwidth + let options.shiftwidth = a:detected.defaults.shiftwidth + 2 0.000001 endif + 2 0.000003 if has_key(options, 'shiftwidth') && !has_key(options, 'expandtab') + let options.expandtab = [stridx(join(getline(1, 256), "\n"), "\t") == -1, a:detected.bufname] + 2 0.000000 endif + 2 0.000004 if !exists('*shiftwidth') && !get(options, 'shiftwidth', [1])[0] + let options.shiftwidth = [get(options, 'tabstop', [&tabstop])[0]] + options.shiftwidth[1:-1] + 2 0.000000 endif + 2 0.000001 let msg = '' + 2 0.000001 let cmd = 'setlocal' + 22 0.000011 for option in a:permitted_options + 20 0.000046 if !exists('&' . option) || !has_key(options, option) || !&l:modifiable && index(s:safe_options, option) == -1 + 18 0.000005 continue + 2 0.000000 endif + 2 0.000002 let value = options[option] + 2 0.000002 if has_key(s:booleans, option) + 1 0.000001 let setting = (value[0] ? '' : 'no') . option + 1 0.000000 else + 1 0.000001 let setting = option . '=' . value[0] + 2 0.000000 endif + 2 0.000006 if getbufvar('', '&' . option) !=# value[0] || index(s:safe_options, option) >= 0 + 2 0.000003 let cmd .= ' ' . setting + 2 0.000000 endif + 2 0.000001 if !&verbose || a:silent + 2 0.000002 if has_key(s:booleans, option) + 1 0.000003 let msg .= ' ' . (value[0] ? '' : 'no') . get(s:short_options, option, option) + 1 0.000000 else + 1 0.000002 let msg .= ' ' . get(s:short_options, option, option) . '=' . value[0] + 2 0.000000 endif + 2 0.000000 continue + endif + if len(value) > 1 + if value[1] ==# a:detected.bufname + let file = '%' + else + let file = value[1] =~# '/' ? fnamemodify(value[1], ':~:.') : value[1] + if file !=# value[1] && file[0:0] !=# '~' + let file = './' . file + endif + endif + if len(value) > 2 + let file .= ' line ' . value[2] + endif + echo printf(':setlocal %-21s " from %s', setting, file) + else + echo ':setlocal ' . setting + endif + 2 0.000002 endfor + 2 0.000003 if !&verbose && !empty(msg) && !a:silent + echo ':setlocal' . msg + 2 0.000000 endif + 2 0.000002 if has_key(options, 'shiftwidth') + 1 0.000003 let cmd .= ' softtabstop=' . (exists('*shiftwidth') ? -1 : options.shiftwidth[0]) + 1 0.000000 else + 1 0.000008 0.000004 call s:Warn(':Sleuth failed to detect indent settings', a:silent) + 2 0.000001 endif + 2 0.000002 return cmd ==# 'setlocal' ? '' : cmd + +FUNCTION 42_Running() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:30 +Called 134 times +Total time: 0.000740 + Self time: 0.000740 + +count total (s) self (s) + 134 0.000634 return exists('s:client.job') || exists('s:client.client_id') + +FUNCTION copilot#Clear() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:94 +Called 16 times +Total time: 0.002891 + Self time: 0.000304 + +count total (s) self (s) + 16 0.000032 if exists('g:_copilot_timer') + 1 0.000004 call timer_stop(remove(g:, '_copilot_timer')) + 16 0.000010 endif + 16 0.000024 if exists('b:_copilot') + 2 0.000133 0.000014 call copilot#client#Cancel(get(b:_copilot, 'first', {})) + 2 0.000018 0.000010 call copilot#client#Cancel(get(b:_copilot, 'cycling', {})) + 16 0.000005 endif + 16 0.002528 0.000068 call s:UpdatePreview() + 16 0.000020 unlet! b:_copilot + 16 0.000009 return '' + +FUNCTION 23_UserOptions() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:460 +Called 2 times +Total time: 0.000020 + Self time: 0.000020 + +count total (s) self (s) + 2 0.000004 if exists('b:sleuth_' . a:name) + let source = 'b:sleuth_' . a:name + 2 0.000004 elseif exists('g:sleuth_' . a:ft . '_' . a:name) + let source = 'g:sleuth_' . a:ft . '_' . a:name + 2 0.000000 endif + 2 0.000004 if !exists('l:source') || type(eval(source)) == type(function('tr')) + 2 0.000001 return {} + endif + let val = eval(source) + let options = {} + if type(val) == type('') + call s:ParseOptions(split(substitute(val, '\S\@= 0') + return options + +FUNCTION 57_CleanUp() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:255 +Called 8 times +Total time: 0.000802 + Self time: 0.000399 + +count total (s) self (s) + 8 0.000011 if strlen(a:options) + 8 0.000460 0.000057 execute "set" a:options + 8 0.000004 endif + " Open folds, if appropriate. + 8 0.000009 if a:mode != "o" + 8 0.000029 if &foldopen =~ "percent" + 8 0.000159 normal! zv + 8 0.000004 endif + " In Operator-pending mode, we want to include the whole match + " (for example, d%). + " This is only a problem if we end up moving in the forward direction. + elseif (a:startpos[0] < line(".")) || (a:startpos[0] == line(".") && a:startpos[1] < col(".")) + if a:0 + " Check whether the match is a single character. If not, move to the + " end of the match. + let matchline = getline(".") + let currcol = col(".") + let regexp = s:Wholematch(matchline, a:1, currcol-1) + let endcol = matchend(matchline, regexp) + if endcol > currcol " This is NOT off by one! + call cursor(0, endcol) + endif + endif " a:0 + 8 0.000003 endif " a:mode != "o" && etc. + 8 0.000005 return 0 + +FUNCTION copilot#Complete() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:155 +Called 25 times +Total time: 0.012806 + Self time: 0.001992 + +count total (s) self (s) + 25 0.000043 if exists('g:_copilot_timer') + call timer_stop(remove(g:, '_copilot_timer')) + 25 0.000009 endif + 25 0.000141 let target = [bufnr(''), getbufvar('', 'changedtick'), line('.'), col('.')] + 25 0.000087 if !exists('b:_copilot.target') || b:_copilot.target !=# target + 25 0.000041 if exists('b:_copilot.first') + 23 0.001119 0.000116 call copilot#client#Cancel(b:_copilot.first) + 25 0.000009 endif + 25 0.000038 if exists('b:_copilot.cycling') + call copilot#client#Cancel(b:_copilot.cycling) + 25 0.000009 endif + 25 0.001295 0.000334 let params = { 'textDocument': {'uri': bufnr('')}, 'position': copilot#util#AppendPosition(), 'formattingOptions': {'insertSpaces': &expandtab ? v:true : v:false, 'tabSize': shiftwidth()}, 'context': {'triggerKind': s:inline_automatic}} + 25 0.008660 0.000177 let b:_copilot = { 'target': target, 'params': params, 'first': copilot#Request('textDocument/inlineCompletion', params)} + 25 0.000239 let g:_copilot_last = b:_copilot + 25 0.000010 endif + 25 0.000034 let completion = b:_copilot.first + 25 0.000018 if !a:0 + return completion.Await() + 25 0.000012 else + 25 0.000420 0.000216 call copilot#client#Result(completion, function(a:1, [b:_copilot])) + 25 0.000020 if a:0 > 1 + 25 0.000302 0.000138 call copilot#client#Error(completion, function(a:2, [b:_copilot])) + 25 0.000009 endif + 25 0.000008 endif + +FUNCTION 10_Event() + Defined: ~/AppData/Local/nvim-data/lazy/copilot.vim/plugin/copilot.vim:45 +Called 111 times +Total time: 0.019055 + Self time: 0.001479 + +count total (s) self (s) + 111 0.000150 try + 111 0.018451 0.000875 call call('copilot#On' . a:type, []) + catch + call copilot#logger#Exception('autocmd.' . a:type) + 111 0.000063 endtry + +FUNCTION copilot#util#AppendPosition() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\util.vim:56 +Called 25 times +Total time: 0.000961 + Self time: 0.000654 + +count total (s) self (s) + 25 0.000053 let line = getline('.') + 25 0.000312 let col_byte = col('.') - (mode() =~# '^[iR]' || empty(line)) + 25 0.000491 0.000183 let col_utf16 = copilot#util#UTF16Width(strpart(line, 0, col_byte)) + 25 0.000069 return {'line': line('.') - 1, 'character': col_utf16} + +FUNCTION 1_LoadFTPlugin() + Defined: C:\Program Files\Neovim\share\nvim\runtime\ftplugin.vim:15 +Called 17 times +Total time: 0.169061 + Self time: 0.154527 + +count total (s) self (s) + 17 0.000087 if exists("b:undo_ftplugin") + exe b:undo_ftplugin + unlet! b:undo_ftplugin b:did_ftplugin + 17 0.000010 endif + + 17 0.000074 let s = expand("") + 17 0.000025 if s != "" + 17 0.000090 if &cpo =~# "S" && exists("b:did_ftplugin") + " In compatible mode options are reset to the global values, need to + " set the local values also when a plugin was already used. + unlet b:did_ftplugin + 17 0.000006 endif + + " When there is a dot it is used to separate filetype names. Thus for + " "aaa.bbb" load "aaa" and then "bbb". + 34 0.000118 for name in split(s, '\.') + " Load Lua ftplugins after Vim ftplugins _per directory_ + " TODO(clason): use nvim__get_runtime when supports globs and modeline + " XXX: "[.]" in the first pattern makes it a wildcard on Windows + 17 0.168324 0.153790 exe $'runtime! ftplugin/{name}[.]{{vim,lua}} ftplugin/{name}_*.{{vim,lua}} ftplugin/{name}/*.{{vim,lua}}' + 34 0.000056 endfor + 17 0.000014 endif + +FUNCTION 47_OnResponse() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:341 +Called 25 times +Total time: 0.002094 + Self time: 0.000829 + +count total (s) self (s) + 25 0.000035 let response = a:response + 25 0.000048 let id = get(a:response, 'id', v:null) + 25 0.000041 if !has_key(a:instance.requests, id) + return + 25 0.000007 endif + 25 0.000055 let request = remove(a:instance.requests, id) + 25 0.000046 for progress_token in request.progress + if has_key(a:instance.progress, progress_token) + call remove(a:instance.progress, progress_token) + endif + 25 0.000015 endfor + 25 0.000030 if request.status !=# 'running' + return + 25 0.000008 endif + 25 0.000030 if has_key(response, 'result') + let request.waiting = {} + let resolve = remove(request, 'resolve') + call remove(request, 'reject') + let request.status = 'success' + let request.result = response.result + for Cb in resolve + let request.waiting[timer_start(0, function('s:Callback', [request, 'result', Cb]))] = 1 + endfor + 25 0.000011 else + 25 0.001397 0.000132 call s:RejectRequest(request, response.error) + 25 0.000007 endif + +FUNCTION copilot#Enabled() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:147 +Called 61 times +Total time: 0.003328 + Self time: 0.000534 + +count total (s) self (s) + 61 0.003289 0.000494 return get(g:, 'copilot_enabled', 1) && empty(s:BufferDisabled()) + +FUNCTION GetLuaIndentIntern() + Defined: C:\Program Files\Neovim\share\nvim\runtime\indent\lua.vim:40 +Called 1 time +Total time: 0.000074 + Self time: 0.000074 + +count total (s) self (s) + " Find a non-blank line above the current line. + 1 0.000004 let prevlnum = prevnonblank(v:lnum - 1) + + " Hit the start of the file, use zero indent. + 1 0.000002 if prevlnum == 0 + return 0 + 1 0.000001 endif + + " Add a 'shiftwidth' after lines that start a block: + " 'function', 'if', 'for', 'while', 'repeat', 'else', 'elseif', '{', '(' + 1 0.000002 let ind = indent(prevlnum) + 1 0.000002 let prevline = getline(prevlnum) + 1 0.000018 let midx = match(prevline, '^\s*\%(if\>\|for\>\|while\>\|repeat\>\|else\>\|elseif\>\|do\>\|then\>\)') + 1 0.000001 if midx == -1 + 1 0.000011 let midx = match(prevline, '\%({\|(\)\s*\%(--\%([^[].*\)\?\)\?$') + 1 0.000001 if midx == -1 + 1 0.000005 let midx = match(prevline, '\\s*\%(\k\|[.:]\)\{-}\s*(') + 1 0.000000 endif + 1 0.000000 endif + + 1 0.000000 if midx != -1 + " Add 'shiftwidth' if what we found previously is not in a comment and + " an "end" or "until" is not present on the same line. + if synIDattr(synID(prevlnum, midx + 1, 1), "name") != "luaComment" && prevline !~ '\\|\' + let ind = ind + shiftwidth() + endif + 1 0.000000 endif + + " Subtract a 'shiftwidth' on end, else, elseif, until, '}' and ')' + " This is the part that requires 'indentkeys'. + 1 0.000007 let midx = match(getline(v:lnum), '^\s*\%(end\>\|else\>\|elseif\>\|until\>\|}\|)\)') + 1 0.000002 if midx != -1 && synIDattr(synID(v:lnum, midx + 1, 1), "name") != "luaComment" + let ind = ind - shiftwidth() + 1 0.000000 endif + + 1 0.000001 return ind + +FUNCTION 42_UpdatePreview() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:306 +Called 90 times +Total time: 0.013811 + Self time: 0.007488 + +count total (s) self (s) + 90 0.000057 try + 90 0.005469 0.000616 let [text, outdent, delete_chars, item] = s:SuggestionTextWithAdjustments() + 90 0.000203 let delete = strchars(delete_chars) + 90 0.000411 let text = split(text, "\r\n\\=\\|\n", 1) + 90 0.000142 if empty(text[-1]) + 90 0.000186 call remove(text, -1) + 90 0.000035 endif + 90 0.000103 if empty(text) || !s:has_ghost_text + 90 0.001817 0.000346 return s:ClearPreview() + endif + if exists('b:_copilot.cycling_callbacks') + let annot = '(1/…)' + elseif exists('b:_copilot.cycling') + let annot = '(' . (b:_copilot.choice + 1) . '/' . len(b:_copilot.suggestions) . ')' + else + let annot = '' + endif + call s:ClearPreview() + if s:has_nvim_ghost_text + let data = {'id': 1} + let data.virt_text_pos = 'overlay' + let append = strpart(getline('.'), col('.') - 1 + delete) + let data.virt_text = [[text[0] . append . repeat(' ', delete - len(text[0])), s:hlgroup]] + if len(text) > 1 + let data.virt_lines = map(text[1:-1], { _, l -> [[l, s:hlgroup]] }) + if !empty(annot) + let data.virt_lines[-1] += [[' '], [annot, s:annot_hlgroup]] + endif + elseif len(annot) + let data.virt_text += [[' '], [annot, s:annot_hlgroup]] + endif + let data.hl_mode = 'combine' + call nvim_buf_set_extmark(0, copilot#NvimNs(), line('.')-1, col('.')-1, data) + elseif s:has_vim_ghost_text + let new_suffix = text[0] + let current_suffix = getline('.')[col('.') - 1 :] + let inset = '' + while delete > 0 && !empty(new_suffix) + let last_char = matchstr(new_suffix, '.$') + let new_suffix = matchstr(new_suffix, '^.\{-\}\ze.$') + if last_char ==# matchstr(current_suffix, '.$') + if !empty(inset) + call prop_add(line('.'), col('.') + len(current_suffix), {'type': s:hlgroup, 'text': inset}) + let inset = '' + endif + let current_suffix = matchstr(current_suffix, '^.\{-\}\ze.$') + let delete -= 1 + else + let inset = last_char . inset + endif + endwhile + if !empty(new_suffix . inset) + call prop_add(line('.'), col('.'), {'type': s:hlgroup, 'text': new_suffix . inset}) + endif + for line in text[1:] + call prop_add(line('.'), 0, {'type': s:hlgroup, 'text_align': 'below', 'text': line}) + endfor + if !empty(annot) + call prop_add(line('.'), col('$'), {'type': s:annot_hlgroup, 'text': ' ' . annot}) + endif + endif + call copilot#Notify('textDocument/didShowCompletion', {'item': item}) + catch + return copilot#logger#Exception() + 90 0.000051 endtry + +FUNCTION 42_SuggestionTextWithAdjustments() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:193 +Called 90 times +Total time: 0.004852 + Self time: 0.004623 + +count total (s) self (s) + 90 0.000178 let empty = ['', 0, '', {}] + 90 0.000033 try + 90 0.001407 0.001177 if mode() !~# '^[iR]' || (s:HideDuringCompletion() && pumvisible()) || !exists('b:_copilot.suggestions') + 20 0.000018 return empty + 70 0.000025 endif + 70 0.000163 let choice = get(b:_copilot.suggestions, b:_copilot.choice, {}) + 70 0.000214 if !has_key(choice, 'range') || choice.range.start.line != line('.') - 1 || type(choice.insertText) !=# v:t_string + 70 0.000062 return empty + endif + let line = getline('.') + let offset = col('.') - 1 + let byte_offset = copilot#util#UTF16ToByteIdx(line, choice.range.start.character) + let choice_text = strpart(line, 0, byte_offset) . substitute(substitute(choice.insertText, '\r\n\=', '\n', 'g'), '\n*$', '', '') + let typed = strpart(line, 0, offset) + let end_offset = copilot#util#UTF16ToByteIdx(line, choice.range.end.character) + if end_offset < 0 + let end_offset = len(line) + endif + let delete = strpart(line, offset, end_offset - offset) + if typed =~# '^\s*$' + let leading = strpart(matchstr(choice_text, '^\s\+'), 0, len(typed)) + let unindented = strpart(choice_text, len(leading)) + if strpart(typed, 0, len(leading)) ==# leading && unindented !=# delete + return [unindented, len(typed) - len(leading), delete, choice] + endif + elseif typed ==# strpart(choice_text, 0, offset) + return [strpart(choice_text, offset), 0, delete, choice] + endif + catch + call copilot#logger#Exception() + 90 0.000066 endtry + return empty + +FUNCTION 23_Init() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:593 +Called 2 times +Total time: 0.007364 + Self time: 0.000137 + +count total (s) self (s) + 2 0.000004 if !a:redetect && exists('b:sleuth.defaults') + let detected = b:sleuth + 2 0.000001 endif + 2 0.000004 unlet! b:sleuth + 2 0.000015 if &l:buftype !~# '^\%(nowrite\|nofile\|acwrite\)\=$' + return s:Warn(':Sleuth disabled for buftype=' . &l:buftype, a:silent) + 2 0.000001 endif + 2 0.000002 if &l:filetype ==# 'netrw' + return s:Warn(':Sleuth disabled for filetype=' . &l:filetype, a:silent) + 2 0.000001 endif + 2 0.000002 if &l:binary + return s:Warn(':Sleuth disabled for binary files', a:silent) + 2 0.000001 endif + 2 0.000004 if !exists('detected') + 2 0.001595 0.000010 let detected = s:DetectDeclared() + 2 0.000001 endif + 2 0.000001 let setfiletype = '' + 2 0.000003 if a:do_filetype && has_key(detected.declared, 'filetype') + let filetype = detected.declared.filetype[0] + if filetype !=# &l:filetype || empty(filetype) + let setfiletype = 'setlocal filetype=' . filetype + else + let setfiletype = 'setfiletype ' . filetype + endif + 2 0.000000 endif + 2 0.000003 exe setfiletype + 2 0.005428 0.000024 call s:DetectHeuristics(detected) + 2 0.000254 0.000016 let cmd = s:Apply(detected, (a:do_filetype ? ['filetype'] : []) + (a:unsafe ? s:all_options : s:safe_options), a:silent) + 2 0.000002 let b:sleuth = detected + 2 0.000003 if exists('s:polyglot') && !a:silent + call s:Warn('Charlatan :Sleuth implementation in vim-polyglot has been found and disabled.') + call s:Warn('To get rid of this message, uninstall vim-polyglot, or disable the') + call s:Warn('corresponding feature in your vimrc:') + call s:Warn(' let g:polyglot_disabled = ["autoindent"]') + 2 0.000001 endif + 2 0.000001 return cmd + +FUNCTION 42_HandleTriggerError() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:382 +Called 25 times +Total time: 0.003975 + Self time: 0.000282 + +count total (s) self (s) + 25 0.000040 let a:state.suggestions = [] + 25 0.000025 let a:state.choice = 0 + 25 0.000025 let a:state.error = a:result + 25 0.000047 if get(b:, '_copilot') is# a:state + 25 0.003795 0.000102 call s:UpdatePreview() + 25 0.000008 endif + +FUNCTION 23_DetectEditorConfig() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:270 +Called 2 times +Total time: 0.000883 + Self time: 0.000883 + +count total (s) self (s) + 2 0.000004 if empty(a:absolute_path) + 1 0.000001 return [{}, ''] + 1 0.000000 endif + 1 0.000001 let root = '' + 1 0.000001 let tail = a:0 ? a:1 : '.editorconfig' + 1 0.000003 let dir = fnamemodify(a:absolute_path, ':h') + 1 0.000001 let previous_dir = '' + 1 0.000001 let sections = [] + 1 0.000002 let overrides = get(g:, 'sleuth_editorconfig_overrides', {}) + 9 0.000040 while dir !=# previous_dir && dir !~# '^//\%([^/]\+/\=\)\=$' + 8 0.000037 let head = substitute(dir, '/\=$', '/', '') + 8 0.000024 let read_from = get(overrides, head . tail, get(overrides, head, head . tail)) + 8 0.000006 if read_from is# '' + break + 8 0.000018 elseif type(read_from) == type('') && read_from !=# head . tail && read_from !~# '^/\|^\a\+:' + let read_from = simplify(head . read_from) + 8 0.000002 endif + 8 0.000552 let ftime = type(read_from) == type('') ? getftime(read_from) : -1 + 8 0.000038 let [cachetime; econfig] = get(s:editorconfig_cache, read_from, [-1, {}, []]) + 8 0.000007 if ftime != cachetime + let econfig = s:ReadEditorConfig(read_from) + let s:editorconfig_cache[read_from] = [ftime] + econfig + lockvar! s:editorconfig_cache[read_from] + unlockvar s:editorconfig_cache[read_from] + 8 0.000003 endif + 8 0.000018 call extend(sections, econfig[1], 'keep') + 8 0.000014 if get(econfig[0], 'root', [''])[0] ==? 'true' + let root = head + break + 8 0.000002 endif + 8 0.000006 let previous_dir = dir + 8 0.000013 let dir = fnamemodify(dir, ':h') + 9 0.000004 endwhile + + 1 0.000001 let config = {} + 1 0.000001 for [pattern, pairs] in sections + if a:absolute_path =~# pattern + call extend(config, pairs) + endif + 1 0.000000 endfor + + 1 0.000001 return [config, root] + +FUNCTION matchit#Match_wrapper() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:52 +Called 8 times +Total time: 0.022294 + Self time: 0.008448 + +count total (s) self (s) + 8 0.000673 0.000056 let restore_options = s:RestoreOptions() + " In s:CleanUp(), we may need to check whether the cursor moved forward. + 8 0.000027 let startpos = [line("."), col(".")] + " if a count has been applied, use the default [count]% mode (see :h N%) + 8 0.000007 if v:count + exe "normal! " .. v:count .. "%" + return s:CleanUp(restore_options, a:mode, startpos) + 8 0.000003 end + 8 0.000052 if a:mode =~# "v" && mode(1) =~# 'ni' + exe "norm! gv" + 8 0.000012 elseif a:mode == "o" && mode(1) !~# '[vV]' + exe "norm! v" + " If this function was called from Visual mode, make sure that the cursor + " is at the correct end of the Visual range: + 8 0.000005 elseif a:mode == "v" + execute "normal! gv\" + let startpos = [line("."), col(".")] + 8 0.000003 endif + + " First step: if not already done, set the script variables + " s:do_BR flag for whether there are backrefs + " s:pat parsed version of b:match_words + " s:all regexp based on s:pat and the default groups + 8 0.000025 if !exists("b:match_words") || b:match_words == "" + let match_words = "" + 8 0.000025 elseif b:match_words =~ ":" + 8 0.000010 let match_words = b:match_words + else + " Allow b:match_words = "GetVimMatchWords()" . + execute "let match_words =" b:match_words + 8 0.000003 endif + " Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! + 8 0.000025 if (match_words != s:last_words) || (&mps != s:last_mps) || exists("b:match_debug") + 8 0.000012 let s:last_mps = &mps + " quote the special chars in 'matchpairs', replace [,:] with \| and then + " append the builtin pairs (/*, */, #if, #ifdef, #ifndef, #else, #elif, + " #elifdef, #elifndef, #endif) + 8 0.000037 let default = escape(&mps, '[$^.*~\\/?]') .. (strlen(&mps) ? "," : "") .. '\/\*:\*\/,#\s*if\%(n\=def\)\=:#\s*else\>:#\s*elif\%(n\=def\)\=\>:#\s*endif\>' + " s:all = pattern with all the keywords + 8 0.000023 let match_words = match_words .. (strlen(match_words) ? "," : "") .. default + 8 0.000009 let s:last_words = match_words + 8 0.000142 if match_words !~ s:notslash .. '\\\d' + let s:do_BR = 0 + let s:pat = match_words + 8 0.000003 else + 8 0.000006 let s:do_BR = 1 + 8 0.008296 0.000083 let s:pat = s:ParseWords(match_words) + 8 0.000003 endif + 8 0.000282 let s:all = substitute(s:pat, s:notslash .. '\zs[,:]\+', '\\|', 'g') + " un-escape \, to , + 8 0.000027 let s:all = substitute(s:all, '\\,', ',', 'g') + " Just in case there are too many '\(...)' groups inside the pattern, make + " sure to use \%(...) groups, so that error E872 can be avoided + 8 0.000032 let s:all = substitute(s:all, '\\(', '\\%(', 'g') + 8 0.000014 let s:all = '\%(' .. s:all .. '\)' + 8 0.000016 if exists("b:match_debug") + let b:match_pat = s:pat + 8 0.000003 endif + " Reconstruct the version with unresolved backrefs. + 8 0.000291 let s:patBR = substitute(match_words .. ',', s:notslash .. '\zs[,:]*,[,:]*', ',', 'g') + 8 0.000180 let s:patBR = substitute(s:patBR, s:notslash .. '\zs:\{2,}', ':', 'g') + " un-escape \, to , + 8 0.000023 let s:patBR = substitute(s:patBR, '\\,', ',', 'g') + 8 0.000003 endif + + " Second step: set the following local variables: + " matchline = line on which the cursor started + " curcol = number of characters before match + " prefix = regexp for start of line to start of match + " suffix = regexp for end of match to end of line + " Require match to end on or after the cursor and prefer it to + " start on or before the cursor. + 8 0.000023 let matchline = getline(startpos[0]) + 8 0.000008 if a:word != '' + " word given + if a:word !~ s:all + echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE + return s:CleanUp(restore_options, a:mode, startpos) + endif + let matchline = a:word + let curcol = 0 + let prefix = '^\%(' + let suffix = '\)$' + " Now the case when "word" is not given + 8 0.000003 else " Find the match that ends on or after the cursor and set curcol. + 8 0.000581 0.000050 let regexp = s:Wholematch(matchline, s:all, startpos[1]-1) + 8 0.000308 let curcol = match(matchline, regexp) + " If there is no match, give up. + 8 0.000006 if curcol == -1 + return s:CleanUp(restore_options, a:mode, startpos) + 8 0.000003 endif + 8 0.000279 let endcol = matchend(matchline, regexp) + 8 0.000013 let suf = strlen(matchline) - endcol + 8 0.000014 let prefix = (curcol ? '^.*\%' .. (curcol + 1) .. 'c\%(' : '^\%(') + 8 0.000011 let suffix = (suf ? '\)\%' .. (endcol + 1) .. 'c.*$' : '\)$') + 8 0.000003 endif + 8 0.000011 if exists("b:match_debug") + let b:match_match = matchstr(matchline, regexp) + let b:match_col = curcol+1 + 8 0.000002 endif + + " Third step: Find the group and single word that match, and the original + " (backref) versions of these. Then, resolve the backrefs. + " Set the following local variable: + " group = colon-separated list of patterns, one of which matches + " = ini:mid:fin or ini:fin + " + " Now, set group and groupBR to the matching group: 'if:endif' or + " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns + " group . "," . groupBR, and we pick it apart. + 8 0.001441 0.000052 let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, s:patBR) + 8 0.000030 let i = matchend(group, s:notslash .. ",") + 8 0.000012 let groupBR = strpart(group, i) + 8 0.000011 let group = strpart(group, 0, i-1) + " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix + 8 0.000005 if s:do_BR " Do the hard part: resolve those backrefs! + 8 0.002170 0.000045 let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) + 8 0.000003 endif + 8 0.000009 if exists("b:match_debug") + let b:match_wholeBR = groupBR + let i = matchend(groupBR, s:notslash .. ":") + let b:match_iniBR = strpart(groupBR, 0, i-1) + 8 0.000003 endif + + " Fourth step: Set the arguments for searchpair(). + 8 0.000035 let i = matchend(group, s:notslash .. ":") + 8 0.000052 let j = matchend(group, '.*' .. s:notslash .. ":") + 8 0.000013 let ini = strpart(group, 0, i-1) + 8 0.000037 let mid = substitute(strpart(group, i,j-i-1), s:notslash .. '\zs:', '\\|', 'g') + 8 0.000011 let fin = strpart(group, j) + "Un-escape the remaining , and : characters. + 8 0.000041 let ini = substitute(ini, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + 8 0.000030 let mid = substitute(mid, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + 8 0.000029 let fin = substitute(fin, s:notslash .. '\zs\\\(:\|,\)', '\1', 'g') + " searchpair() requires that these patterns avoid \(\) groups. + 8 0.000029 let ini = substitute(ini, s:notslash .. '\zs\\(', '\\%(', 'g') + 8 0.000026 let mid = substitute(mid, s:notslash .. '\zs\\(', '\\%(', 'g') + 8 0.000026 let fin = substitute(fin, s:notslash .. '\zs\\(', '\\%(', 'g') + " Set mid. This is optimized for readability, not micro-efficiency! + 8 0.000046 if a:forward && matchline =~ prefix .. fin .. suffix || !a:forward && matchline =~ prefix .. ini .. suffix + 3 0.000002 let mid = "" + 8 0.000003 endif + " Set flag. This is optimized for readability, not micro-efficiency! + 8 0.000036 if a:forward && matchline =~ prefix .. fin .. suffix || !a:forward && matchline !~ prefix .. ini .. suffix + 3 0.000002 let flag = "bW" + 5 0.000002 else + 5 0.000004 let flag = "W" + 8 0.000002 endif + " Set skip. + 8 0.000010 if exists("b:match_skip") + let skip = b:match_skip + 8 0.000011 elseif exists("b:match_comment") " backwards compatibility and testing! + let skip = "r:" .. b:match_comment + 8 0.000002 else + 8 0.000006 let skip = 's:comment\|string' + 8 0.000003 endif + 8 0.000203 0.000033 let skip = s:ParseSkip(skip) + 8 0.000009 if exists("b:match_debug") + let b:match_ini = ini + let b:match_tail = (strlen(mid) ? mid .. '\|' : '') .. fin + 8 0.000002 endif + + " Fifth step: actually start moving the cursor and call searchpair(). + " Later, :execute restore_cursor to get to the original screen. + 8 0.000024 let view = winsaveview() + 8 0.000025 call cursor(0, curcol + 1) + 8 0.000072 if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight') + let skip = "0" + 8 0.000003 else + 8 0.002479 execute "if " .. skip .. "| let skip = '0' | endif" + 8 0.000004 endif + 8 0.001635 let sp_return = searchpair(ini, mid, fin, flag, skip) + 8 0.000025 if &selection isnot# 'inclusive' && a:mode == 'v' + " move cursor one pos to the right, because selection is not inclusive + " add virtualedit=onemore, to make it work even when the match ends the + " line + if !(col('.') < col('$')-1) + let eolmark=1 " flag to set a mark on eol (since we cannot move there) + endif + norm! l + 8 0.000003 endif + 8 0.000034 let final_position = "call cursor(" .. line(".") .. "," .. col(".") .. ")" + " Restore cursor position and original screen. + 8 0.000029 call winrestview(view) + 8 0.000592 normal! m' + 8 0.000010 if sp_return > 0 + 8 0.000026 execute final_position + 8 0.000003 endif + 8 0.000012 if exists('eolmark') && eolmark + call setpos("''", [0, line('.'), col('$'), 0]) " set mark on the eol + 8 0.000003 endif + 8 0.000861 0.000059 return s:CleanUp(restore_options, a:mode, startpos, mid .. '\|' .. fin) + +FUNCTION GetLuaIndent() + Defined: C:\Program Files\Neovim\share\nvim\runtime\indent\lua.vim:30 +Called 1 time +Total time: 0.000172 + Self time: 0.000035 + +count total (s) self (s) + 1 0.000011 let ignorecase_save = &ignorecase + 1 0.000001 try + 1 0.000047 0.000007 let &ignorecase = 0 + 1 0.000081 0.000007 return GetLuaIndentIntern() + 1 0.000001 finally + 1 0.000026 0.000003 let &ignorecase = ignorecase_save + 1 0.000001 endtry + +FUNCTION copilot#NvimNs() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:90 +Called 94 times +Total time: 0.000402 + Self time: 0.000402 + +count total (s) self (s) + 94 0.000360 return nvim_create_namespace('github-copilot') + +FUNCTION copilot#Request() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:75 +Called 25 times +Total time: 0.008483 + Self time: 0.000341 + +count total (s) self (s) + 25 0.000499 0.000095 let client = copilot#Client() + 25 0.007964 0.000226 return call(client.Request, [a:method, a:params] + a:000) + +FUNCTION 57_Choose() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:529 +Called 16 times +Total time: 0.001788 + Self time: 0.001788 + +count total (s) self (s) + 16 0.000063 let tail = (a:patterns =~ a:comma .. "$" ? a:patterns : a:patterns .. a:comma) + 16 0.000104 let i = matchend(tail, s:notslash .. a:comma) + 16 0.000009 if a:0 + 16 0.000051 let alttail = (a:1 =~ a:comma .. "$" ? a:1 : a:1 .. a:comma) + 16 0.000095 let j = matchend(alttail, s:notslash .. a:comma) + 16 0.000005 endif + 16 0.000027 let current = strpart(tail, 0, i-1) + 16 0.000013 if a:branch == "" + 8 0.000006 let currpat = current + 8 0.000002 else + 8 0.000086 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') + 16 0.000005 endif + " un-escape \, to , + 16 0.000038 let currpat = substitute(currpat, '\\,', ',', 'g') + 46 0.000278 while a:string !~ a:prefix .. currpat .. a:suffix + 30 0.000044 let tail = strpart(tail, i) + 30 0.000141 let i = matchend(tail, s:notslash .. a:comma) + 30 0.000019 if i == -1 + return -1 + 30 0.000008 endif + 30 0.000046 let current = strpart(tail, 0, i-1) + 30 0.000021 if a:branch == "" + 3 0.000002 let currpat = current + 27 0.000007 else + 27 0.000153 let currpat = substitute(current, s:notslash .. a:branch, '\\|', 'g') + 30 0.000010 endif + 30 0.000013 if a:0 + 30 0.000041 let alttail = strpart(alttail, j) + 30 0.000133 let j = matchend(alttail, s:notslash .. a:comma) + 30 0.000010 endif + 46 0.000026 endwhile + 16 0.000008 if a:0 + 16 0.000033 let current = current .. a:comma .. strpart(alttail, 0, j-1) + 16 0.000005 endif + 16 0.000010 return current + +FUNCTION copilot#client#LspResponse() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:432 +Called 25 times +Total time: 0.002348 + Self time: 0.000254 + +count total (s) self (s) + 25 0.000064 if !has_key(s:instances, a:id) + return + 25 0.000009 endif + 25 0.002231 0.000137 call s:OnResponse(s:instances[a:id], a:opts) + +FUNCTION 57_Resolve() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:476 +Called 91 times +Total time: 0.004647 + Self time: 0.003776 + +count total (s) self (s) + 91 0.000080 let word = a:target + 91 0.000378 let i = matchend(word, s:notslash .. '\\\d') - 1 + 91 0.000068 let table = "----------" + 99 0.000076 while i != -2 " There are back references to be replaced. + 8 0.000011 let d = word[i] + 8 0.000459 0.000031 let backref = s:Ref(a:source, d) + " The idea is to replace '\d' with backref. Before we do this, + " replace any \(\) groups in backref with :1, :2, ... if they + " correspond to the first, second, ... group already inserted + " into backref. Later, replace :1 with \1 and so on. The group + " number w+b within backref corresponds to the group number + " s within a:source. + " w = number of '\(' in word before the current one + 8 0.000189 0.000056 let w = s:Count( substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1') + 8 0.000005 let b = 1 " number of the current '\(' in backref + 8 0.000006 let s = d " number of the current '\(' in a:source + 16 0.000394 0.000084 while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1') && s < 10 + 8 0.000010 if table[s] == "-" + 8 0.000006 if w + b < 10 + " let table[s] = w + b + 8 0.000026 let table = strpart(table, 0, s) .. (w+b) .. strpart(table, s+1) + 8 0.000003 endif + 8 0.000005 let b = b + 1 + 8 0.000008 let s = s + 1 + else + execute s:Ref(backref, b, "start", "len") + let ref = strpart(backref, start, len) + let backref = strpart(backref, 0, start) .. ":" .. table[s] .. strpart(backref, start+len) + let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1') + 8 0.000002 endif + 16 0.000005 endwhile + 8 0.000021 let word = strpart(word, 0, i-1) .. backref .. strpart(word, i+1) + 8 0.000035 let i = matchend(word, s:notslash .. '\\\d') - 1 + 99 0.000098 endwhile + 91 0.000390 let word = substitute(word, s:notslash .. '\zs:', '\\', 'g') + 91 0.000077 if a:output == "table" + 3 0.000002 return table + 88 0.000063 elseif a:output == "word" + 88 0.000050 return word + else + return table .. word + endif + +FUNCTION copilot#OnBufEnter() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:443 +Called 8 times +Total time: 0.000186 + Self time: 0.000101 + +count total (s) self (s) + 8 0.000025 let bufnr = bufnr('') + 8 0.000155 0.000069 call copilot#util#Defer(function('s:Focus'), bufnr) + +FUNCTION 13() + Defined: C:\Program Files\Neovim\share\nvim\runtime\autoload\provider\clipboard.vim:22 +Called 1 time +Total time: 0.000023 + Self time: 0.000023 + +count total (s) self (s) + " At this point this nvim instance might already have launched + " a new provider instance. Don't drop ownership in this case. + 1 0.000007 if self.owner == a:jobid + 1 0.000004 let self.owner = 0 + 1 0.000001 endif + " Don't print if exit code is >= 128 ( exit is 128+SIGNUM if by signal (e.g. 143 on SIGTERM)) + 1 0.000002 if a:data > 0 && a:data < 128 + echohl WarningMsg + echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(self.stderr) + echohl None + 1 0.000000 endif + +FUNCTION 15() + Defined: C:\Program Files\Neovim\share\nvim\runtime\autoload\provider\clipboard.vim:286 +Called 1 time +Total time: 0.029108 + Self time: 0.029108 + +count total (s) self (s) + 1 0.000002 if a:reg == '"' + call s:clipboard.set(a:lines,a:regtype,'+') + if s:copy['*'] != s:copy['+'] + call s:clipboard.set(a:lines,a:regtype,'*') + end + return 0 + 1 0.000000 end + + 1 0.000004 if s:cache_enabled == 0 || type(s:copy[a:reg]) == v:t_func + if type(s:copy[a:reg]) == v:t_func + call s:copy[a:reg](a:lines, a:regtype) + else + call s:try_cmd(s:copy[a:reg], a:lines) + endif + "Cache it anyway we can compare it later to get regtype of the yank + let s:selections[a:reg] = copy(s:selection) + let s:selections[a:reg].data = [a:lines, a:regtype] + return 0 + 1 0.000000 end + + 1 0.000002 if s:selections[a:reg].owner > 0 + let prev_job = s:selections[a:reg].owner + 1 0.000000 end + 1 0.000009 let s:selections[a:reg] = copy(s:selection) + 1 0.000002 let selection = s:selections[a:reg] + 1 0.000002 let selection.data = [a:lines, a:regtype] + 1 0.000002 let selection.argv = s:copy[a:reg] + 1 0.000002 let selection.detach = s:cache_enabled + 1 0.000001 let selection.cwd = "/" + 1 0.028941 let jobid = jobstart(selection.argv, selection) + 1 0.000009 if jobid > 0 + 1 0.000014 call jobsend(jobid, a:lines) + 1 0.000053 call jobclose(jobid, 'stdin') + " xclip does not close stdout when receiving input via stdin + 1 0.000006 if selection.argv[0] ==# 'xclip' + call jobclose(jobid, 'stdout') + 1 0.000001 endif + 1 0.000003 let selection.owner = jobid + 1 0.000001 let ret = 1 + else + echohl WarningMsg + echomsg 'clipboard: failed to execute: '.(s:copy[a:reg]) + echohl None + let ret = 1 + 1 0.000000 endif + + " The previous provider instance should exit when the new one takes + " ownership, but kill it to be sure we don't fill up the job table. + 1 0.000002 if exists('prev_job') + call timer_start(1000, {... -> jobwait([prev_job], 0)[0] == -1 && jobstop(prev_job)}) + 1 0.000000 endif + + 1 0.000002 return ret + +FUNCTION copilot#client#Cancel() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:801 +Called 27 times +Total time: 0.001130 + Self time: 0.000326 + +count total (s) self (s) + 27 0.000132 if type(a:request) == type({}) && has_key(a:request, 'Cancel') + 25 0.000956 0.000153 call a:request.Cancel() + 27 0.000010 endif + +FUNCTION 47_SetUpRequest() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:133 +Called 25 times +Total time: 0.000847 + Self time: 0.000847 + +count total (s) self (s) + 25 0.000347 let request = { 'client_id': a:instance.id, 'id': a:id, 'method': a:method, 'params': a:params, 'Client': function('s:RequestClient'), 'Wait': function('s:RequestWait'), 'Await': function('s:RequestAwait'), 'Cancel': function('s:RequestCancel'), 'resolve': [], 'reject': [], 'progress': a:progress, 'status': 'running'} + 25 0.000042 let args = a:000[2:-1] + 25 0.000033 if len(args) + if !empty(a:1) + call add(request.resolve, { v -> call(a:1, [v] + args)}) + endif + if !empty(a:2) + call add(request.reject, { v -> call(a:2, [v] + args)}) + endif + return request + 25 0.000009 endif + 25 0.000028 if a:0 && !empty(a:1) + call add(request.resolve, a:1) + 25 0.000008 endif + 25 0.000029 if a:0 > 1 && !empty(a:2) + call add(request.reject, a:2) + 25 0.000007 endif + 25 0.000017 return request + +FUNCTION 23_ParseOptions() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:166 +Called 10 times +Total time: 0.000096 + Self time: 0.000096 + +count total (s) self (s) + 10 0.000008 for option in a:declarations + if has_key(s:modeline_booleans, matchstr(option, '^\%(no\)\=\zs\w\+$')) + let a:into[s:modeline_booleans[matchstr(option, '^\%(no\)\=\zs\w\+')]] = [option !~# '^no'] + a:000 + elseif has_key(s:modeline_numbers, matchstr(option, '^\w\+\ze=[1-9]\d*$')) + let a:into[s:modeline_numbers[matchstr(option, '^\w\+')]] = [str2nr(matchstr(option, '\d\+$'))] + a:000 + elseif option =~# '^\%(ft\|filetype\)=[[:alnum:]._-]*$' + let a:into.filetype = [matchstr(option, '=\zs.*')] + a:000 + endif + if option ==# 'nomodeline' || option ==# 'noml' + return 1 + endif + 10 0.000004 endfor + 10 0.000004 return 0 + +FUNCTION 57_Ref() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:405 +Called 8 times +Total time: 0.000428 + Self time: 0.000428 + +count total (s) self (s) + 8 0.000014 let len = strlen(a:string) + 8 0.000007 if a:d == 0 + let start = 0 + 8 0.000003 else + 8 0.000006 let cnt = a:d + 8 0.000006 let match = a:string + 16 0.000010 while cnt + 8 0.000007 let cnt = cnt - 1 + 8 0.000045 let index = matchend(match, s:notslash .. '\\(') + 8 0.000006 if index == -1 + return "" + 8 0.000002 endif + 8 0.000011 let match = strpart(match, index) + 16 0.000007 endwhile + 8 0.000011 let start = len - strlen(match) + 8 0.000008 if a:0 == 1 && a:1 == "start" + return start - 2 + 8 0.000003 endif + 8 0.000005 let cnt = 1 + 16 0.000008 while cnt + 8 0.000050 let index = matchend(match, s:notslash .. '\\(\|\\)') - 1 + 8 0.000005 if index == -2 + return "" + 8 0.000002 endif + " Increment if an open, decrement if a ')': + 8 0.000015 let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')' + 8 0.000012 let match = strpart(match, index+1) + 16 0.000006 endwhile + 8 0.000006 let start = start - 2 + 8 0.000011 let len = len - start - strlen(match) + 8 0.000003 endif + 8 0.000005 if a:0 == 1 + return len + 8 0.000005 elseif a:0 == 2 + return "let " .. a:1 .. "=" .. start .. "| let " .. a:2 .. "=" .. len + 8 0.000002 else + 8 0.000011 return strpart(a:string, start, len) + endif + +FUNCTION 47_RequestClient() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:122 +Called 25 times +Total time: 0.000121 + Self time: 0.000121 + +count total (s) self (s) + 25 0.000104 return get(s:instances, self.client_id, v:null) + +FUNCTION copilot#client#Result() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:814 +Called 25 times +Total time: 0.000204 + Self time: 0.000204 + +count total (s) self (s) + 25 0.000046 if has_key(a:request, 'resolve') + 25 0.000045 call add(a:request.resolve, a:callback) + elseif has_key(a:request, 'result') + let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'result', a:callback]))] = 1 + 25 0.000008 endif + +FUNCTION 2_LoadIndent() + Defined: C:\Program Files\Neovim\share\nvim\runtime\indent.vim:14 +Called 17 times +Total time: 0.054138 + Self time: 0.054050 + +count total (s) self (s) + 17 0.000052 if exists("b:undo_indent") + exe b:undo_indent + unlet! b:undo_indent b:did_indent + 17 0.000006 endif + 17 0.000061 let s = expand("") + 17 0.000023 if s != "" + 17 0.000023 if exists("b:did_indent") + unlet b:did_indent + 17 0.000005 endif + + " When there is a dot it is used to separate filetype names. Thus for + " "aaa.bbb" load "indent/aaa.vim" and then "indent/bbb.vim". + 34 0.000089 for name in split(s, '\.') + " XXX: "[.]" in the pattern makes it a wildcard on Windows + 17 0.053645 0.053557 exe $'runtime! indent/{name}[.]{{vim,lua}}' + 34 0.000059 endfor + 17 0.000010 endif + +FUNCTION copilot#OnInsertLeavePre() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:448 +Called 4 times +Total time: 0.000890 + Self time: 0.000035 + +count total (s) self (s) + 4 0.000832 0.000014 call copilot#Clear() + 4 0.000054 0.000017 call s:ClearPreview() + +FUNCTION 47_UriFromPath() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\client.vim:179 +Called 25 times +Total time: 0.000642 + Self time: 0.000642 + +count total (s) self (s) + 25 0.000035 let absolute = a:absolute + 25 0.000188 if has('win32') && absolute =~# '^\a://\@!' + return 'file:///' . strpart(absolute, 0, 2) . s:UrlEncode(strpart(absolute, 2)) + 25 0.000074 elseif absolute =~# '^/' + return 'file://' . s:UrlEncode(absolute) + 25 0.000171 elseif absolute =~# '^\a[[:alnum:].+-]*:\|^$' + 25 0.000022 return absolute + else + return '' + endif + +FUNCTION 42_ClearPreview() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:297 +Called 94 times +Total time: 0.001508 + Self time: 0.001105 + +count total (s) self (s) + 94 0.000096 if s:has_nvim_ghost_text + 94 0.000931 0.000528 call nvim_buf_del_extmark(0, copilot#NvimNs(), 1) + elseif s:has_vim_ghost_text + call prop_remove({'type': s:hlgroup, 'all': v:true}) + call prop_remove({'type': s:annot_hlgroup, 'all': v:true}) + 94 0.000032 endif + +FUNCTION copilot#util#Defer() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot\util.vim:7 +Called 37 times +Total time: 0.000335 + Self time: 0.000335 + +count total (s) self (s) + 37 0.000137 call add(s:deferred, function(a:fn, a:000)) + 37 0.000171 return timer_start(0, function('s:RunDeferred')) + +FUNCTION copilot#Schedule() + Defined: ~\AppData\Local\nvim-data\lazy\copilot.vim\autoload\copilot.vim:412 +Called 61 times +Total time: 0.015075 + Self time: 0.001642 + +count total (s) self (s) + 61 0.004244 0.000542 if !s:has_ghost_text || !s:Running() || !copilot#Enabled() + 12 0.002114 0.000041 call copilot#Clear() + 12 0.000005 return + 49 0.000016 endif + 49 0.007903 0.000245 call s:UpdatePreview() + 49 0.000105 let delay = get(g:, 'copilot_idle_delay', 45) + 49 0.000141 call timer_stop(get(g:, '_copilot_timer', -1)) + 49 0.000351 let g:_copilot_timer = timer_start(delay, function('s:Trigger', [bufnr('')])) + +FUNCTION 23_Ready() + Defined: ~/AppData/Local/nvim-data/lazy/vim-sleuth/plugin/sleuth.vim:384 +Called 4 times +Total time: 0.000010 + Self time: 0.000010 + +count total (s) self (s) + 4 0.000008 return has_key(a:detected.options, 'expandtab') && has_key(a:detected.options, 'shiftwidth') + +FUNCTION 57_Wholematch() + Defined: C:\Program Files\Neovim\share\nvim\runtime\pack\dist\opt\matchit\autoload\matchit.vim:385 +Called 8 times +Total time: 0.000531 + Self time: 0.000531 + +count total (s) self (s) + 8 0.000017 let group = '\%(' .. a:pat .. '\)' + 8 0.000016 let prefix = (a:start ? '\(^.*\%<' .. (a:start + 2) .. 'c\)\zs' : '^') + 8 0.000011 let len = strlen(a:string) + 8 0.000015 let suffix = (a:start+1 < len ? '\(\%>' .. (a:start+1) .. 'c.*$\)\@=' : '$') + 8 0.000438 if a:string !~ prefix .. group .. suffix + 2 0.000002 let prefix = '' + 8 0.000002 endif + 8 0.000014 return prefix .. group .. suffix + +FUNCTIONS SORTED ON TOTAL TIME +count total (s) self (s) function + 17 0.169061 0.154527 1_LoadFTPlugin() + 17 0.100190 41_SynSet() + 17 0.054138 0.054050 2_LoadIndent() + 1 0.029152 0.000044 provider#clipboard#Call() + 1 0.029108 15() + 8 0.022294 0.008448 matchit#Match_wrapper() + 111 0.019055 0.001479 10_Event() + 61 0.015075 0.001642 copilot#Schedule() + 25 0.014642 0.000977 42_Trigger() + 57 0.014478 0.000363 copilot#OnCursorMovedI() + 90 0.013811 0.007488 42_UpdatePreview() + 25 0.013665 0.000687 copilot#Suggest() + 25 0.012806 0.001992 copilot#Complete() + 74 0.009910 0.000797 43_RunDeferred() + 25 0.008483 0.000341 copilot#Request() + 8 0.008212 0.003673 57_ParseWords() + 25 0.007738 0.000815 47_NvimRequest() + 2 0.007378 0.000014 23_AutoInit() + 2 0.007364 0.000137 23_Init() + 25 0.006022 0.005065 47_NvimDoRequest() + +FUNCTIONS SORTED ON SELF TIME +count total (s) self (s) function + 17 0.169061 0.154527 1_LoadFTPlugin() + 17 0.100190 41_SynSet() + 17 0.054138 0.054050 2_LoadIndent() + 1 0.029108 15() + 8 0.022294 0.008448 matchit#Match_wrapper() + 90 0.013811 0.007488 42_UpdatePreview() + 2 0.005088 23_Guess() + 25 0.006022 0.005065 47_NvimDoRequest() + 90 0.004852 0.004623 42_SuggestionTextWithAdjustments() + 91 0.004647 0.003776 57_Resolve() + 8 0.008212 0.003673 57_ParseWords() + 78 0.003640 42_BufferDisabled() + 25 0.005660 0.002776 47_PreprocessParams() + 29 0.004214 0.002121 47_NvimAttach() + 25 0.012806 0.001992 copilot#Complete() + 16 0.001788 57_Choose() + 61 0.015075 0.001642 copilot#Schedule() + 8 0.002126 0.001618 57_InsertRefs() + 111 0.019055 0.001479 10_Event() + 25 0.001265 0.001185 47_RejectRequest() +