neovim conf based on kickstart.nvim
at main 992 lines 40 kB view raw
1-- Set <space> as the leader key 2-- See `:help mapleader` 3-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) 4vim.g.mapleader = ' ' 5vim.g.maplocalleader = ' ' 6 7-- Set to true if you have a Nerd Font installed and selected in the terminal 8vim.g.have_nerd_font = true 9 10-- [[ Setting options ]] 11-- See `:help vim.o` 12-- NOTE: You can change these options as you wish! 13-- For more options, you can see `:help option-list` 14 15-- Make line numbers default 16vim.o.number = true 17-- You can also add relative line numbers, to help with jumping. 18-- Experiment for yourself to see if you like it! 19vim.o.relativenumber = true 20 21-- Enable mouse mode, can be useful for resizing splits for example! 22vim.o.mouse = 'a' 23 24-- Don't show the mode, since it's already in the status line 25vim.o.showmode = false 26 27-- Sync clipboard between OS and Neovim. 28-- Schedule the setting after `UiEnter` because it can increase startup-time. 29-- Remove this option if you want your OS clipboard to remain independent. 30-- See `:help 'clipboard'` 31vim.schedule(function() vim.o.clipboard = 'unnamedplus' end) 32 33-- Enable break indent 34vim.o.breakindent = true 35 36-- Enable undo/redo changes even after closing and reopening a file 37vim.o.undofile = true 38 39-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term 40vim.o.ignorecase = true 41vim.o.smartcase = true 42 43-- Keep signcolumn on by default 44vim.o.signcolumn = 'yes' 45 46-- Decrease update time 47vim.o.updatetime = 250 48 49-- Decrease mapped sequence wait time 50vim.o.timeoutlen = 300 51 52-- Configure how new splits should be opened 53vim.o.splitright = true 54vim.o.splitbelow = true 55 56-- Sets how neovim will display certain whitespace characters in the editor. 57-- See `:help 'list'` 58-- and `:help 'listchars'` 59-- 60-- Notice listchars is set using `vim.opt` instead of `vim.o`. 61-- It is very similar to `vim.o` but offers an interface for conveniently interacting with tables. 62-- See `:help lua-options` 63-- and `:help lua-guide-options` 64vim.o.list = true 65vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '' } 66 67-- Preview substitutions live, as you type! 68vim.o.inccommand = 'split' 69 70-- Show which line your cursor is on 71vim.o.cursorline = true 72 73-- Minimal number of screen lines to keep above and below the cursor. 74vim.o.scrolloff = 10 75 76-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`), 77-- instead raise a dialog asking if you wish to save the current file(s) 78-- See `:help 'confirm'` 79vim.o.confirm = true 80 81-- [[ Basic Keymaps ]] 82-- See `:help vim.keymap.set()` 83 84-- Clear highlights on search when pressing <Esc> in normal mode 85-- See `:help hlsearch` 86vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>') 87 88-- Diagnostic Config & Keymaps 89-- -- See :help vim.diagnostic.Opts 90-- vim.diagnostic.config { 91-- update_in_insert = false, 92-- severity_sort = true, 93-- float = { border = 'rounded', max_width = 120, max_height = 20, focusable = true }, 94-- underline = { severity = { min = vim.diagnostic.severity.WARN } }, 95-- 96-- -- Can switch between these as you prefer 97-- virtual_text = true, -- Text shows up at the end of the line 98-- virtual_lines = { only_current_line = true }, -- Text shows up underneath the line, with virtual lines 99-- 100-- -- Auto open the float, so you can easily read the errors when jumping with `[d` and `]d` 101-- jump = { float = true }, 102-- } 103-- 104-- vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) 105 106-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier 107-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which 108-- is not what someone will guess without a bit more experience. 109-- 110-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping 111-- or just use <C-\><C-n> to exit terminal mode 112vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' }) 113 114-- TIP: Disable arrow keys in normal mode 115-- vim.keymap.set('n', '<left>', '<cmd>echo "Use h to move!!"<CR>') 116-- vim.keymap.set('n', '<right>', '<cmd>echo "Use l to move!!"<CR>') 117-- vim.keymap.set('n', '<up>', '<cmd>echo "Use k to move!!"<CR>') 118-- vim.keymap.set('n', '<down>', '<cmd>echo "Use j to move!!"<CR>') 119 120-- Keybinds to make split navigation easier. 121-- Use CTRL+<hjkl> to switch between windows 122-- 123-- See `:help wincmd` for a list of all window commands 124vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' }) 125vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' }) 126vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' }) 127vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' }) 128 129-- NOTE: Some terminals have colliding keymaps or are not able to send distinct keycodes 130-- vim.keymap.set("n", "<C-S-h>", "<C-w>H", { desc = "Move window to the left" }) 131-- vim.keymap.set("n", "<C-S-l>", "<C-w>L", { desc = "Move window to the right" }) 132-- vim.keymap.set("n", "<C-S-j>", "<C-w>J", { desc = "Move window to the lower" }) 133-- vim.keymap.set("n", "<C-S-k>", "<C-w>K", { desc = "Move window to the upper" }) 134 135-- [[ Quality of life ]] 136vim.o.winborder = 'rounded' 137 138-- [[ Basic Autocommands ]] 139-- See `:help lua-guide-autocommands` 140 141-- Highlight when yanking (copying) text 142-- Try it with `yap` in normal mode 143-- See `:help vim.hl.on_yank()` 144vim.api.nvim_create_autocmd('TextYankPost', { 145 desc = 'Highlight when yanking (copying) text', 146 group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }), 147 callback = function() vim.hl.on_yank() end, 148}) 149 150-- [[ Install `lazy.nvim` plugin manager ]] 151-- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info 152local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' 153if not (vim.uv or vim.loop).fs_stat(lazypath) then 154 local lazyrepo = 'https://github.com/folke/lazy.nvim.git' 155 local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath } 156 if vim.v.shell_error ~= 0 then error('Error cloning lazy.nvim:\n' .. out) end 157end 158 159---@type vim.Option 160local rtp = vim.opt.rtp 161rtp:prepend(lazypath) 162 163-- [[ Configure and install plugins ]] 164-- 165-- To check the current status of your plugins, run 166-- :Lazy 167-- 168-- You can press `?` in this menu for help. Use `:q` to close the window 169-- 170-- To update plugins you can run 171-- :Lazy update 172-- 173-- NOTE: Here is where you install your plugins. 174require('lazy').setup({ 175 -- NOTE: Plugins can be added via a link or github org/name. To run setup automatically, use `opts = {}` 176 { 'NMAC427/guess-indent.nvim', opts = {} }, 177 178 -- Alternatively, use `config = function() ... end` for full control over the configuration. 179 -- If you prefer to call `setup` explicitly, use: 180 -- { 181 -- 'lewis6991/gitsigns.nvim', 182 -- config = function() 183 -- require('gitsigns').setup({ 184 -- -- Your gitsigns configuration here 185 -- }) 186 -- end, 187 -- } 188 -- 189 -- Here is a more advanced example where we pass configuration 190 -- options to `gitsigns.nvim`. 191 -- 192 -- See `:help gitsigns` to understand what the configuration keys do 193 { -- Adds git related signs to the gutter, as well as utilities for managing changes 194 'lewis6991/gitsigns.nvim', 195 ---@module 'gitsigns' 196 ---@type Gitsigns.Config 197 ---@diagnostic disable-next-line: missing-fields 198 opts = { 199 signs = { 200 add = { text = '+' }, ---@diagnostic disable-line: missing-fields 201 change = { text = '~' }, ---@diagnostic disable-line: missing-fields 202 delete = { text = '_' }, ---@diagnostic disable-line: missing-fields 203 topdelete = { text = '' }, ---@diagnostic disable-line: missing-fields 204 changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields 205 }, 206 }, 207 }, 208 209 -- NOTE: Plugins can also be configured to run Lua code when they are loaded. 210 -- 211 -- This is often very useful to both group configuration, as well as handle 212 -- lazy loading plugins that don't need to be loaded immediately at startup. 213 -- 214 -- For example, in the following configuration, we use: 215 -- event = 'VimEnter' 216 -- 217 -- which loads which-key before all the UI elements are loaded. Events can be 218 -- normal autocommands events (`:help autocmd-events`). 219 -- 220 -- Then, because we use the `opts` key (recommended), the configuration runs 221 -- after the plugin has been loaded as `require(MODULE).setup(opts)`. 222 223 { -- Useful plugin to show you pending keybinds. 224 'folke/which-key.nvim', 225 event = 'VimEnter', 226 ---@module 'which-key' 227 ---@type wk.Opts 228 ---@diagnostic disable-next-line: missing-fields 229 opts = { 230 -- delay between pressing a key and opening which-key (milliseconds) 231 delay = 0, 232 icons = { mappings = vim.g.have_nerd_font }, 233 234 preset = 'helix', 235 236 -- Document existing key chains 237 spec = { 238 { '<leader>s', group = '[S]earch', mode = { 'n', 'v' } }, 239 { '<leader>t', group = '[T]oggle' }, 240 { '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first 241 { 'gr', group = 'LSP Actions', mode = { 'n' } }, 242 }, 243 }, 244 }, 245 246 -- NOTE: Plugins can specify dependencies. 247 -- 248 -- The dependencies are proper plugin specifications as well - anything 249 -- you do for a plugin at the top level, you can do for a dependency. 250 -- 251 -- Use the `dependencies` key to specify the dependencies of a particular plugin 252 253 { 254 'folke/snacks.nvim', 255 priority = 1000, 256 lazy = false, 257 ---@type snacks.Config 258 opts = { 259 bufdelete = { enabled = true }, 260 debug = { enabled = true }, 261 zen = { enabled = true }, 262 bigfile = { enabled = true }, 263 dashboard = { enabled = true }, 264 explorer = { enabled = true }, 265 image = { enabled = true }, 266 indent = { enabled = true }, 267 input = { enabled = true }, 268 keyboard = { enabled = true }, 269 lazygit = { enabled = true }, 270 notifier = { enabled = true }, 271 picker = { enabled = true }, 272 quickfile = { enabled = true }, 273 scope = { enabled = true }, 274 scroll = { enabled = true }, 275 statuscolumn = { enabled = true }, 276 terminal = { enabled = true }, 277 words = { enabled = true }, 278 }, 279 keys = { 280 { '\\', function() Snacks.explorer() end, desc = 'snacks explorer reveal', silent = true }, 281 { '<leader><space>', function() Snacks.picker.smart() end, desc = 'Smart Find Files' }, 282 { '<leader>,', function() Snacks.picker.buffers() end, desc = 'Buffers' }, 283 { '<leader>/', function() Snacks.picker.grep() end, desc = 'Grep' }, 284 { '<leader>:', function() Snacks.picker.command_history() end, desc = 'Command History' }, 285 { '<leader>n', function() Snacks.picker.notifications() end, desc = 'Notification History' }, 286 { '<leader>e', function() Snacks.explorer() end, desc = 'File Explorer' }, 287 -- find 288 { '<leader>fb', function() Snacks.picker.buffers() end, desc = 'Buffers' }, 289 { '<leader>fc', function() Snacks.picker.files { cwd = vim.fn.stdpath 'config' } end, desc = 'Find Config File' }, 290 { '<leader>ff', function() Snacks.picker.files() end, desc = 'Find Files' }, 291 { '<leader>fg', function() Snacks.picker.git_files() end, desc = 'Find Git Files' }, 292 { '<leader>fp', function() Snacks.picker.projects() end, desc = 'Projects' }, 293 { '<leader>fr', function() Snacks.picker.recent() end, desc = 'Recent' }, 294 -- git 295 { '<leader>gb', function() Snacks.picker.git_branches() end, desc = 'Git Branches' }, 296 { '<leader>gl', function() Snacks.picker.git_log() end, desc = 'Git Log' }, 297 { '<leader>gL', function() Snacks.picker.git_log_line() end, desc = 'Git Log Line' }, 298 { '<leader>gs', function() Snacks.picker.git_status() end, desc = 'Git Status' }, 299 { '<leader>gS', function() Snacks.picker.git_stash() end, desc = 'Git Stash' }, 300 { '<leader>gd', function() Snacks.picker.git_diff() end, desc = 'Git Diff (Hunks)' }, 301 { '<leader>gf', function() Snacks.picker.git_log_file() end, desc = 'Git Log File' }, 302 -- gh 303 { '<leader>gi', function() Snacks.picker.gh_issue() end, desc = 'GitHub Issues (open)' }, 304 { '<leader>gI', function() Snacks.picker.gh_issue { state = 'all' } end, desc = 'GitHub Issues (all)' }, 305 { '<leader>gp', function() Snacks.picker.gh_pr() end, desc = 'GitHub Pull Requests (open)' }, 306 { '<leader>gP', function() Snacks.picker.gh_pr { state = 'all' } end, desc = 'GitHub Pull Requests (all)' }, 307 -- Grep 308 { '<leader>sb', function() Snacks.picker.lines() end, desc = 'Buffer Lines' }, 309 { '<leader>sB', function() Snacks.picker.grep_buffers() end, desc = 'Grep Open Buffers' }, 310 { '<leader>sg', function() Snacks.picker.grep() end, desc = 'Grep' }, 311 { '<leader>sw', function() Snacks.picker.grep_word() end, desc = 'Visual selection or word', mode = { 'n', 'x' } }, 312 -- search 313 { '<leader>s"', function() Snacks.picker.registers() end, desc = 'Registers' }, 314 { '<leader>s/', function() Snacks.picker.search_history() end, desc = 'Search History' }, 315 { '<leader>sa', function() Snacks.picker.autocmds() end, desc = 'Autocmds' }, 316 { '<leader>sb', function() Snacks.picker.lines() end, desc = 'Buffer Lines' }, 317 { '<leader>sc', function() Snacks.picker.command_history() end, desc = 'Command History' }, 318 { '<leader>sC', function() Snacks.picker.commands() end, desc = 'Commands' }, 319 { '<leader>sd', function() Snacks.picker.diagnostics() end, desc = 'Diagnostics' }, 320 { '<leader>sD', function() Snacks.picker.diagnostics_buffer() end, desc = 'Buffer Diagnostics' }, 321 { '<leader>sh', function() Snacks.picker.help() end, desc = 'Help Pages' }, 322 { '<leader>sH', function() Snacks.picker.highlights() end, desc = 'Highlights' }, 323 { '<leader>si', function() Snacks.picker.icons() end, desc = 'Icons' }, 324 { '<leader>sj', function() Snacks.picker.jumps() end, desc = 'Jumps' }, 325 { '<leader>sk', function() Snacks.picker.keymaps() end, desc = 'Keymaps' }, 326 { '<leader>sl', function() Snacks.picker.loclist() end, desc = 'Location List' }, 327 { '<leader>sm', function() Snacks.picker.marks() end, desc = 'Marks' }, 328 { '<leader>sM', function() Snacks.picker.man() end, desc = 'Man Pages' }, 329 { '<leader>sp', function() Snacks.picker.lazy() end, desc = 'Search for Plugin Spec' }, 330 { '<leader>sq', function() Snacks.picker.qflist() end, desc = 'Quickfix List' }, 331 { '<leader>sR', function() Snacks.picker.resume() end, desc = 'Resume' }, 332 { '<leader>su', function() Snacks.picker.undo() end, desc = 'Undo History' }, 333 { '<leader>uC', function() Snacks.picker.colorschemes() end, desc = 'Colorschemes' }, 334 -- LSP 335 { 'gd', function() Snacks.picker.lsp_definitions() end, desc = 'Goto Definition' }, 336 { 'gD', function() Snacks.picker.lsp_declarations() end, desc = 'Goto Declaration' }, 337 { 'gr', function() Snacks.picker.lsp_references() end, nowait = true, desc = 'References' }, 338 { 'gI', function() Snacks.picker.lsp_implementations() end, desc = 'Goto Implementation' }, 339 { 'gy', function() Snacks.picker.lsp_type_definitions() end, desc = 'Goto T[y]pe Definition' }, 340 { 'gai', function() Snacks.picker.lsp_incoming_calls() end, desc = 'C[a]lls Incoming' }, 341 { 'gao', function() Snacks.picker.lsp_outgoing_calls() end, desc = 'C[a]lls Outgoing' }, 342 { '<leader>ss', function() Snacks.picker.lsp_symbols() end, desc = 'LSP Symbols' }, 343 { '<leader>sS', function() Snacks.picker.lsp_workspace_symbols() end, desc = 'LSP Workspace Symbols' }, 344 -- Other 345 { '<leader>z', function() Snacks.zen() end, desc = 'Toggle Zen Mode' }, 346 { '<leader>Z', function() Snacks.zen.zoom() end, desc = 'Toggle Zoom' }, 347 { '<leader>n', function() Snacks.notifier.show_history() end, desc = 'Notification History' }, 348 { '<leader>bd', function() Snacks.bufdelete() end, desc = 'Delete Buffer' }, 349 { '<leader>cR', function() Snacks.rename.rename_file() end, desc = 'Rename File' }, 350 { '<leader>gB', function() Snacks.gitbrowse() end, desc = 'Git Browse', mode = { 'n', 'v' } }, 351 { '<leader>gg', function() Snacks.lazygit() end, desc = 'Lazygit' }, 352 { '<leader>un', function() Snacks.notifier.hide() end, desc = 'Dismiss All Notifications' }, 353 { '<c-/>', function() Snacks.terminal() end, desc = 'Toggle Terminal' }, 354 { '<c-_>', function() Snacks.terminal() end, desc = 'which_key_ignore' }, 355 { ']]', function() Snacks.words.jump(vim.v.count1) end, desc = 'Next Reference', mode = { 'n', 't' } }, 356 { '[[', function() Snacks.words.jump(-vim.v.count1) end, desc = 'Prev Reference', mode = { 'n', 't' } }, 357 { 358 '<leader>N', 359 desc = 'Neovim News', 360 function() 361 Snacks.win { 362 file = vim.api.nvim_get_runtime_file('doc/news.txt', false)[1], 363 width = 0.6, 364 height = 0.6, 365 wo = { 366 spell = false, 367 wrap = false, 368 signcolumn = 'yes', 369 statuscolumn = ' ', 370 conceallevel = 3, 371 }, 372 } 373 end, 374 }, 375 }, 376 }, 377 378 -- LSP Plugins 379 { 380 -- Main LSP Configuration 381 'neovim/nvim-lspconfig', 382 dependencies = { 383 -- Automatically install LSPs and related tools to stdpath for Neovim 384 -- Mason must be loaded before its dependents so we need to set it up here. 385 -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` 386 { 387 'mason-org/mason.nvim', 388 ---@module 'mason.settings' 389 ---@type MasonSettings 390 ---@diagnostic disable-next-line: missing-fields 391 opts = {}, 392 }, 393 'smjonas/inc-rename.nvim', 394 395 -- Maps LSP server names between nvim-lspconfig and Mason package names. 396 'mason-org/mason-lspconfig.nvim', 397 'WhoIsSethDaniel/mason-tool-installer.nvim', 398 399 -- Useful status updates for LSP. 400 { 'j-hui/fidget.nvim', opts = {} }, 401 }, 402 config = function() 403 -- Brief aside: **What is LSP?** 404 -- 405 -- LSP is an initialism you've probably heard, but might not understand what it is. 406 -- 407 -- LSP stands for Language Server Protocol. It's a protocol that helps editors 408 -- and language tooling communicate in a standardized fashion. 409 -- 410 -- In general, you have a "server" which is some tool built to understand a particular 411 -- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers 412 -- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone 413 -- processes that communicate with some "client" - in this case, Neovim! 414 -- 415 -- LSP provides Neovim with features like: 416 -- - Go to definition 417 -- - Find references 418 -- - Autocompletion 419 -- - Symbol Search 420 -- - and more! 421 -- 422 -- Thus, Language Servers are external tools that must be installed separately from 423 -- Neovim. This is where `mason` and related plugins come into play. 424 -- 425 -- If you're wondering about lsp vs treesitter, you can check out the wonderfully 426 -- and elegantly composed help section, `:help lsp-vs-treesitter` 427 428 -- This function gets run when an LSP attaches to a particular buffer. 429 -- That is to say, every time a new file is opened that is associated with 430 -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this 431 -- function will be executed to configure the current buffer 432 vim.api.nvim_create_autocmd('LspAttach', { 433 group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), 434 callback = function(event) 435 -- NOTE: Remember that Lua is a real programming language, and as such it is possible 436 -- to define small helper and utility functions so you don't have to repeat yourself. 437 -- 438 -- In this case, we create a function that lets us more easily define mappings specific 439 -- for LSP related items. It sets the mode, buffer and description for us each time. 440 local map = function(keys, func, desc, mode) 441 mode = mode or 'n' 442 vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) 443 end 444 445 -- Rename the variable under your cursor. 446 -- Most Language Servers support renaming across files, etc. 447 map('grn', vim.lsp.buf.rename, '[R]e[n]ame') 448 449 -- Execute a code action, usually your cursor needs to be on top of an error 450 -- or a suggestion from your LSP for this to activate. 451 map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) 452 453 -- WARN: This is not Goto Definition, this is Goto Declaration. 454 -- For example, in C this would take you to the header. 455 map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') 456 457 -- The following two autocommands are used to highlight references of the 458 -- word under your cursor when your cursor rests there for a little while. 459 -- See `:help CursorHold` for information about when this is executed 460 -- 461 -- When you move your cursor, the highlights will be cleared (the second autocommand). 462 local client = vim.lsp.get_client_by_id(event.data.client_id) 463 if client and client:supports_method('textDocument/documentHighlight', event.buf) then 464 local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) 465 vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { 466 buffer = event.buf, 467 group = highlight_augroup, 468 callback = vim.lsp.buf.document_highlight, 469 }) 470 471 vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { 472 buffer = event.buf, 473 group = highlight_augroup, 474 callback = vim.lsp.buf.clear_references, 475 }) 476 477 vim.api.nvim_create_autocmd('LspDetach', { 478 group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), 479 callback = function(event2) 480 vim.lsp.buf.clear_references() 481 vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } 482 end, 483 }) 484 end 485 486 -- The following code creates a keymap to toggle inlay hints in your 487 -- code, if the language server you are using supports them 488 -- 489 -- This may be unwanted, since they displace some of your code 490 if client and client:supports_method('textDocument/inlayHint', event.buf) then 491 map('<leader>th', function() vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) end, '[T]oggle Inlay [H]ints') 492 end 493 end, 494 }) 495 496 -- Enable the following language servers 497 -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. 498 -- See `:help lsp-config` for information about keys and how to configure 499 ---@type table<string, vim.lsp.Config> 500 local servers = { 501 clangd = {}, 502 gopls = {}, 503 ty = {}, 504 bashls = {}, 505 -- vtsls = {}, 506 astro = {}, 507 508 tailwindcss = { 509 -- exclude a filetype from the default_config 510 filetypes_exclude = { 'markdown' }, 511 -- add additional filetypes to the default_config 512 filetypes_include = {}, 513 -- to fully override the default_config, change the below 514 -- filetypes = {} 515 516 -- additional settings for the server, e.g: 517 -- tailwindCSS = { includeLanguages = { someLang = "html" } } 518 -- can be addeded to the settings table and will be merged with 519 -- this defaults for Phoenix projects 520 settings = { 521 tailwindCSS = { 522 includeLanguages = { 523 elixir = 'html-eex', 524 eelixir = 'html-eex', 525 heex = 'html-eex', 526 }, 527 }, 528 }, 529 }, 530 jsonls = { 531 -- lazy-load schemastore when needed 532 before_init = function(_, new_config) 533 new_config.settings.json.schemas = new_config.settings.json.schemas or {} 534 vim.list_extend(new_config.settings.json.schemas, require('schemastore').json.schemas()) 535 end, 536 settings = { 537 json = { 538 format = { 539 enable = true, 540 }, 541 validate = { enable = true }, 542 }, 543 }, 544 }, 545 546 bacon_ls = { 547 enabled = diagnostics == 'bacon-ls', 548 }, 549 rust_analyzer = { enabled = false }, 550 stylua = {}, -- Used to format Lua code 551 552 -- Special Lua Config, as recommended by neovim help docs 553 lua_ls = { 554 on_init = function(client) 555 if client.workspace_folders then 556 local path = client.workspace_folders[1].name 557 if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end 558 end 559 560 client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { 561 runtime = { 562 version = 'LuaJIT', 563 path = { 'lua/?.lua', 'lua/?/init.lua' }, 564 }, 565 workspace = { 566 checkThirdParty = false, 567 -- NOTE: this is a lot slower and will cause issues when working on your own configuration. 568 -- See https://github.com/neovim/nvim-lspconfig/issues/3189 569 library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { 570 '${3rd}/luv/library', 571 '${3rd}/busted/library', 572 }), 573 }, 574 }) 575 end, 576 settings = { 577 Lua = {}, 578 }, 579 }, 580 } 581 582 -- Ensure the servers and tools above are installed 583 -- 584 -- To check the current status of installed tools and/or manually install 585 -- other tools, you can run 586 -- :Mason 587 -- 588 -- You can press `g?` for help in this menu. 589 local ensure_installed = vim.tbl_keys(servers or {}) 590 vim.list_extend(ensure_installed, { 591 -- You can add other tools here that you want Mason to install 592 }) 593 594 require('mason-tool-installer').setup { ensure_installed = ensure_installed } 595 596 for name, server in pairs(servers) do 597 vim.lsp.config(name, server) 598 vim.lsp.enable(name) 599 end 600 end, 601 setup = { 602 tailwindcss = function(_, opts) 603 opts.filetypes = opts.filetypes or {} 604 605 -- Add default filetypes 606 vim.list_extend(opts.filetypes, vim.lsp.config.tailwindcss.filetypes) 607 608 -- Remove excluded filetypes 609 --- @param ft string 610 opts.filetypes = vim.tbl_filter(function(ft) return not vim.tbl_contains(opts.filetypes_exclude or {}, ft) end, opts.filetypes) 611 612 -- Add additional filetypes 613 vim.list_extend(opts.filetypes, opts.filetypes_include or {}) 614 end, 615 }, 616 keys = { 617 { 618 '<leader>cr', 619 function() 620 local inc_rename = require 'inc_rename' 621 return ':' .. inc_rename.config.cmd_name .. ' ' .. vim.fn.expand '<cword>' 622 end, 623 expr = true, 624 desc = 'Rename (inc-rename.nvim)', 625 }, 626 }, 627 }, 628 629 { -- Autoformat 630 'stevearc/conform.nvim', 631 event = { 'BufWritePre' }, 632 cmd = { 'ConformInfo' }, 633 keys = { 634 { 635 '<leader>f', 636 function() require('conform').format { async = true, lsp_format = 'fallback' } end, 637 mode = '', 638 desc = '[F]ormat buffer', 639 }, 640 }, 641 ---@module 'conform' 642 ---@type conform.setupOpts 643 opts = { 644 notify_on_error = false, 645 format_on_save = function(bufnr) 646 -- Disable "format_on_save lsp_fallback" for languages that don't 647 -- have a well standardized coding style. You can add additional 648 -- languages here or re-enable it for the disabled ones. 649 local disable_filetypes = { c = true, cpp = true } 650 if disable_filetypes[vim.bo[bufnr].filetype] then 651 return nil 652 else 653 return { 654 timeout_ms = 500, 655 lsp_format = 'fallback', 656 } 657 end 658 end, 659 formatters_by_ft = { 660 lua = { 'stylua' }, 661 -- Conform can also run multiple formatters sequentially 662 -- python = { "isort", "black" }, 663 typescript = { 'biome-check' }, 664 -- You can use 'stop_after_first' to run the first available formatter from the list 665 -- javascript = { "prettierd", "prettier", stop_after_first = true }, 666 }, 667 }, 668 }, 669 670 { -- Autocompletion 671 'saghen/blink.cmp', 672 event = 'VimEnter', 673 version = '1.*', 674 dependencies = { 675 { 676 'rafamadriz/friendly-snippets', 677 }, 678 { 679 'onsails/lspkind.nvim', 680 }, 681 }, 682 ---@module 'blink.cmp' 683 ---@type blink.cmp.Config 684 opts = { 685 keymap = { 686 -- 'default' (recommended) for mappings similar to built-in completions 687 -- <c-y> to accept ([y]es) the completion. 688 -- This will auto-import if your LSP supports it. 689 -- This will expand snippets if the LSP sent a snippet. 690 -- 'super-tab' for tab to accept 691 -- 'enter' for enter to accept 692 -- 'none' for no mappings 693 -- 694 -- For an understanding of why the 'default' preset is recommended, 695 -- you will need to read `:help ins-completion` 696 -- 697 -- No, but seriously. Please read `:help ins-completion`, it is really good! 698 -- 699 -- All presets have the following mappings: 700 -- <tab>/<s-tab>: move to right/left of your snippet expansion 701 -- <c-space>: Open menu or open docs if already open 702 -- <c-n>/<c-p> or <up>/<down>: Select next/previous item 703 -- <c-e>: Hide menu 704 -- <c-k>: Toggle signature help 705 -- 706 -- See :h blink-cmp-config-keymap for defining your own keymap 707 preset = 'super-tab', 708 709 -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: 710 -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps 711 }, 712 713 appearance = { 714 -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' 715 -- Adjusts spacing to ensure icons are aligned 716 nerd_font_variant = 'mono', 717 }, 718 719 completion = { 720 -- By default, you may press `<c-space>` to show the documentation. 721 -- Optionally, set `auto_show = true` to show the documentation after a delay. 722 documentation = { auto_show = false, auto_show_delay_ms = 500 }, 723 724 menu = { 725 draw = { 726 components = { 727 kind_icon = { 728 text = function(ctx) return require('lspkind').symbol_map[ctx.kind] or '' end, 729 }, 730 }, 731 }, 732 }, 733 }, 734 sources = { 735 default = { 'lsp', 'path', 'snippets' }, 736 per_filetype = { 737 sql = { 'snippets', 'dadbod', 'buffer' }, 738 }, 739 providers = { 740 dadbod = { name = 'Dadbod', module = 'vim_dadbod_completion.blink' }, 741 }, 742 }, 743 744 snippets = { preset = 'mini_snippets' }, 745 746 -- Blink.cmp includes an optional, recommended rust fuzzy matcher, 747 -- which automatically downloads a prebuilt binary when enabled. 748 -- 749 -- By default, we use the Lua implementation instead, but you may enable 750 -- the rust implementation via `'prefer_rust_with_warning'` 751 -- 752 -- See :h blink-cmp-config-fuzzy for more information 753 fuzzy = { implementation = 'prefer_rust_with_warning' }, 754 755 -- Shows a signature help window while you type arguments for a function 756 -- signature = { enabled = true }, 757 }, 758 }, 759 -- Highlight todo, notes, etc in comments 760 { 761 'folke/todo-comments.nvim', 762 event = 'VimEnter', 763 dependencies = { 'nvim-lua/plenary.nvim' }, 764 ---@module 'todo-comments' 765 ---@type TodoOptions 766 ---@diagnostic disable-next-line: missing-fields 767 opts = { signs = false }, 768 }, 769 770 { -- Collection of various small independent plugins/modules 771 'nvim-mini/mini.nvim', 772 config = function() 773 -- Better Around/Inside textobjects 774 -- 775 -- Examples: 776 -- - va) - [V]isually select [A]round [)]paren 777 -- - yinq - [Y]ank [I]nside [N]ext [Q]uote 778 -- - ci' - [C]hange [I]nside [']quote 779 require('mini.ai').setup { n_lines = 500 } 780 781 -- Add/delete/replace surroundings (brackets, quotes, etc.) 782 -- 783 -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren 784 -- - sd' - [S]urround [D]elete [']quotes 785 -- - sr)' - [S]urround [R]eplace [)] ['] 786 require('mini.surround').setup() 787 788 require('mini.icons').setup() 789 790 require('mini.cursorword').setup() 791 require('mini.snippets').setup() 792 require('mini.indentscope').setup() 793 require('mini.tabline').setup() 794 require('mini.extra').setup() 795 require('mini.sessions').setup() 796 require('mini.git').setup() 797 require('mini.cmdline').setup() 798 require('mini.files').setup() 799 require('mini.visits').setup() 800 require('mini.move').setup() 801 require('mini.pairs').setup() 802 require('mini.diff').setup() 803 end, 804 }, 805 806 { 807 'nvim-lualine/lualine.nvim', 808 event = 'VeryLazy', 809 init = function() 810 vim.g.lualine_laststatus = vim.o.laststatus 811 if vim.fn.argc(-1) > 0 then 812 -- set an empty statusline till lualine loads 813 vim.o.statusline = ' ' 814 else 815 -- hide the statusline on the starter page 816 vim.o.laststatus = 0 817 end 818 end, 819 opts = function() 820 local colors = { 821 blue = '#80a0ff', 822 cyan = '#79dac8', 823 black = '#080808', 824 white = '#c6c6c6', 825 red = '#ff5189', 826 violet = '#d183e8', 827 grey = '#303030', 828 } 829 830 local bubbles_theme = { 831 normal = { 832 a = { fg = colors.black, bg = colors.violet }, 833 b = { fg = colors.white, bg = colors.grey }, 834 c = { fg = colors.white }, 835 }, 836 837 insert = { a = { fg = colors.black, bg = colors.blue } }, 838 visual = { a = { fg = colors.black, bg = colors.cyan } }, 839 replace = { a = { fg = colors.black, bg = colors.red } }, 840 841 inactive = { 842 a = { fg = colors.white, bg = colors.black }, 843 b = { fg = colors.white, bg = colors.black }, 844 c = { fg = colors.white }, 845 }, 846 } 847 848 require('lualine').setup { 849 options = { 850 theme = bubbles_theme, 851 component_separators = '', 852 section_separators = { left = '', right = '' }, 853 }, 854 sections = { 855 lualine_a = { { 'mode', separator = { left = '' }, right_padding = 2 } }, 856 lualine_b = { 'filename', 'branch' }, 857 lualine_c = { 858 '%=', --[[ add your center components here in place of this comment ]] 859 }, 860 lualine_x = {}, 861 lualine_y = { 'filetype', 'progress' }, 862 lualine_z = { 863 { 'location', separator = { right = '' }, left_padding = 2 }, 864 }, 865 }, 866 inactive_sections = { 867 lualine_a = { 'filename' }, 868 lualine_b = {}, 869 lualine_c = {}, 870 lualine_x = {}, 871 lualine_y = {}, 872 lualine_z = { 'location' }, 873 }, 874 tabline = {}, 875 extensions = {}, 876 } 877 end, 878 }, 879 880 { -- Highlight, edit, and navigate code 881 'nvim-treesitter/nvim-treesitter', 882 lazy = false, 883 build = ':TSUpdate', 884 branch = 'main', 885 -- [[ Configure Treesitter ]] See `:help nvim-treesitter-intro` 886 opts = { 887 -- LazyVim config for treesitter 888 indent = { enable = true }, ---@type lazyvim.TSFeat 889 highlight = { enable = true }, ---@type lazyvim.TSFeat 890 folds = { enable = true }, ---@type lazyvim.TSFeat 891 ensure_installed = { 892 'bash', 893 'c', 894 'diff', 895 'html', 896 'javascript', 897 'jsdoc', 898 'json', 899 'lua', 900 'luadoc', 901 'luap', 902 'markdown', 903 'markdown_inline', 904 'printf', 905 'python', 906 'query', 907 'regex', 908 'toml', 909 'tsx', 910 'typescript', 911 'vim', 912 'vimdoc', 913 'xml', 914 'yaml', 915 }, 916 }, 917 config = function() 918 local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } 919 require('nvim-treesitter').install(parsers) 920 vim.api.nvim_create_autocmd('FileType', { 921 callback = function(args) 922 local buf, filetype = args.buf, args.match 923 924 local language = vim.treesitter.language.get_lang(filetype) 925 if not language then return end 926 927 -- check if parser exists and load it 928 if not vim.treesitter.language.add(language) then return end 929 -- enables syntax highlighting and other treesitter features 930 vim.treesitter.start(buf, language) 931 932 -- enables treesitter based folds 933 -- for more info on folds see `:help folds` 934 -- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' 935 -- vim.wo.foldmethod = 'expr' 936 937 -- enables treesitter based indentation 938 vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" 939 end, 940 }) 941 end, 942 }, 943 944 -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the 945 -- init.lua. If you want these files, they are in the repository, so you can just download them and 946 -- place them in the correct locations. 947 948 -- NOTE: Next step on your Neovim journey: Add/Configure additional plugins for Kickstart 949 -- 950 -- Here are some example plugins that I've included in the Kickstart repository. 951 -- Uncomment any of the lines below to enable them (you will need to restart nvim). 952 -- 953 require 'kickstart.plugins.debug', 954 require 'kickstart.plugins.lint', 955 require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps 956 957 -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` 958 -- This is the easiest way to modularize your config. 959 -- 960 -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. 961 { import = 'custom.plugins' }, 962 -- 963 -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` 964 -- Or use telescope! 965 -- In normal mode type `<space>sh` then write `lazy.nvim-plugin` 966 -- you can continue same window with `<space>sr` which resumes last telescope search 967}, { ---@diagnostic disable-line: missing-fields 968 ui = { 969 -- If you are using a Nerd Font: set icons to an empty table which will use the 970 -- default lazy.nvim defined Nerd Font icons, otherwise define a unicode icons table 971 icons = vim.g.have_nerd_font and {} or { 972 cmd = '', 973 config = '🛠', 974 event = '📅', 975 ft = '📂', 976 init = '', 977 keys = '🗝', 978 plugin = '🔌', 979 runtime = '💻', 980 require = '🌙', 981 source = '📄', 982 start = '🚀', 983 task = '📌', 984 lazy = '💤 ', 985 }, 986 }, 987}) 988 989require('matugen').setup() 990 991-- The line beneath this is called `modeline`. See `:help modeline` 992-- vim: ts=2 sts=2 sw=2 et