init.lua (14974B)
1 -- Neovim init.lua 2 3 -- Disable unused providers 4 vim.g.loaded_perl_provider = 0 5 vim.g.loaded_ruby_provider = 0 6 vim.g.loaded_node_provider = 0 7 vim.g.loaded_python3_provider = 0 8 9 -- Basic options 10 vim.opt.number = true -- enable absolute line numbers 11 vim.opt.relativenumber = true -- enable relative line numbers 12 vim.opt.clipboard = "unnamedplus" -- use system clipboard 13 vim.opt.mouse = "a" -- enable mouse 14 vim.opt.termguicolors = true -- true color support 15 vim.opt.signcolumn = "yes" -- always show signcolumn 16 vim.opt.showmode = false -- don't show mode (we use statusline) 17 vim.opt.cursorline = true -- highlight current line 18 vim.opt.hidden = true -- allow buffer switching without saving 19 20 -- Indentation 21 vim.opt.expandtab = true -- spaces instead of tabs 22 vim.opt.shiftwidth = 2 -- size of an indent 23 vim.opt.tabstop = 2 -- number of spaces tabs count for 24 vim.opt.softtabstop = 2 -- spaces when hitting <Tab> 25 26 -- Searching 27 vim.opt.ignorecase = true -- ignore case 28 vim.opt.smartcase = true -- unless uppercase present 29 vim.opt.incsearch = true -- incremental search 30 vim.opt.hlsearch = false -- no persistent highlight 31 32 -- Splits & Windows 33 vim.opt.splitbelow = true -- horizontal splits go below 34 vim.opt.splitright = true -- vertical splits go right 35 vim.opt.equalalways = true -- auto-resize splits 36 37 -- Backups & Undo 38 vim.opt.backup = false 39 vim.opt.writebackup = false 40 vim.opt.swapfile = false 41 vim.opt.undofile = true -- enable persistent undo 42 vim.opt.undodir = vim.fn.stdpath('state') .. '/undo' 43 44 -- Timing 45 vim.opt.updatetime = 300 -- faster CursorHold 46 vim.opt.timeoutlen = 500 -- faster mapped sequences 47 48 -- Leader Key 49 vim.g.mapleader = ' ' 50 vim.g.maplocalleader = ' ' 51 52 -- Bootstrap lazy.nvim 53 local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' 54 if not vim.loop.fs_stat(lazypath) then 55 vim.fn.system({ 56 'git', 'clone', '--filter=blob:none', 57 'https://github.com/folke/lazy.nvim.git', 58 '--branch=stable', lazypath, 59 }) 60 end 61 vim.opt.rtp:prepend(lazypath) 62 63 -- Plugin setup 64 require('lazy').setup({ 65 -- lazy.nvim manager 66 { 'folke/lazy.nvim', version = '*' }, 67 68 -- Lualine statusline 69 { 70 'nvim-lualine/lualine.nvim', 71 event = 'VeryLazy', 72 dependencies = { 'kyazdani42/nvim-web-devicons', opt = true }, 73 config = function() 74 require('lualine').setup { 75 options = { 76 icons_enabled = true, 77 theme = 'auto', 78 component_separators = { left = '', right = '' }, 79 section_separators = { left = '', right = '' }, 80 }, 81 sections = { 82 lualine_a = {'mode'}, 83 lualine_b = {'branch', 'diff', 'diagnostics'}, 84 lualine_c = {'filename'}, 85 lualine_x = {'encoding', 'fileformat', 'filetype'}, 86 lualine_y = {'progress'}, 87 lualine_z = {'location'}, 88 }, 89 } 90 end, 91 }, 92 { 93 "zbirenbaum/copilot.lua", 94 event = "VeryLazy", 95 config = function() 96 require("copilot").setup({ 97 suggestion = { 98 enabled = true, 99 auto_trigger = true, 100 accept = false, 101 }, 102 panel = { 103 enabled = false 104 }, 105 filetypes = { 106 markdown = true, 107 help = true, 108 html = true, 109 javascript = true, 110 typescript = true, 111 ["*"] = true 112 }, 113 }) 114 115 vim.keymap.set("i", '<Tab>', function() 116 if require("copilot.suggestion").is_visible() then 117 require("copilot.suggestion").accept() 118 else 119 vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Tab>", true, false, true), "n", false) 120 end 121 end, { 122 silent = true, 123 }) 124 end, 125 }, 126 -- Telescope fuzzy finder 127 { 128 'nvim-telescope/telescope.nvim', 129 cmd = 'Telescope', 130 dependencies = { 'nvim-lua/plenary.nvim' }, 131 config = function() 132 require('telescope').setup { 133 defaults = { 134 layout_strategy = 'flex', 135 file_ignore_patterns = {'node_modules'} 136 } 137 } 138 end, 139 }, 140 141 -- File explorer 142 { 143 'nvim-tree/nvim-tree.lua', 144 cmd = { 'NvimTreeToggle', 'NvimTreeFocus' }, 145 dependencies = { 'kyazdani42/nvim-web-devicons' }, 146 config = function() 147 require('nvim-tree').setup { 148 view = { width = 30 }, 149 update_focused_file = { enable = true }, 150 } 151 end, 152 }, 153 154 -- Treesitter for syntax 155 { 156 'nvim-treesitter/nvim-treesitter', 157 build = ':TSUpdate', 158 event = { 'BufReadPost', 'BufNewFile' }, 159 config = function() 160 require('nvim-treesitter.configs').setup { 161 ensure_installed = { 'lua', 'python', 'javascript', 'go', 'rust', 'regex', 'bash' }, 162 highlight = { enable = true }, 163 indent = { enable = true }, 164 } 165 end, 166 }, 167 168 -- Mason LSP installer 169 { 'williamboman/mason.nvim', cmd = 'Mason', config = true }, 170 { 171 'williamboman/mason-lspconfig.nvim', 172 dependencies = 'neovim/nvim-lspconfig', 173 config = function() 174 require('mason-lspconfig').setup { 175 ensure_installed = { 'pyright', 'ts_ls', 'lua_ls' }, 176 automatic_enable = false, 177 } 178 vim.lsp.config('lua_ls', { 179 settings = { 180 Lua = { 181 runtime = { version = 'LuaJIT' }, 182 diagnostics = { globals = {'vim'} }, 183 workspace = { library = vim.api.nvim_get_runtime_file('', true) }, 184 telemetry = { enable = false }, 185 }, 186 }, 187 }) 188 vim.lsp.enable({ 'pyright', 'ts_ls', 'lua_ls' }) 189 end, 190 }, 191 192 -- Completion 193 { 194 'hrsh7th/nvim-cmp', 195 event = 'InsertEnter', 196 dependencies = { 197 'hrsh7th/cmp-nvim-lsp', 'hrsh7th/cmp-path', 198 'L3MON4D3/LuaSnip', 'saadparwaiz1/cmp_luasnip', 199 }, 200 config = function() 201 local cmp = require('cmp') 202 cmp.setup { 203 snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end }, 204 sources = cmp.config.sources({{ name = 'nvim_lsp' },{ name = 'path' },{ name = 'luasnip' }}), 205 } 206 end, 207 }, 208 209 -- Git signs 210 { 211 'lewis6991/gitsigns.nvim', 212 event = 'BufReadPre', 213 config = function() require('gitsigns').setup {} end, 214 }, 215 216 -- Autopairs 217 { 218 'windwp/nvim-autopairs', 219 event = 'InsertEnter', 220 config = function() require('nvim-autopairs').setup {} end, 221 }, 222 223 -- Commenting 224 { 225 'numToStr/Comment.nvim', 226 keys = { 227 { '<Leader>/', function() require('Comment.api').toggle.linewise.current() end, desc = 'Toggle comment (line)' }, 228 { '<Leader>/', '<Esc><cmd>lua require("Comment.api").toggle.blockwise(vim.fn.visualmode())<CR>', mode = 'v', desc = 'Toggle comment (block)' }, 229 }, 230 config = function() 231 require('Comment').setup({ 232 -- Add any custom config here; these are the defaults: 233 padding = true, -- add a space b/w comment and line 234 sticky = true, -- cursor stays put 235 mappings = { 236 basic = false, -- disable builtin mappings because we're using our own 237 extra = false, 238 }, 239 toggler = { 240 line = '<Leader>/', -- won't be set by default since basic=false 241 block = '<Leader>/', -- same here 242 }, 243 }) 244 end, 245 }, 246 247 248 -- Which-key 249 { 250 'folke/which-key.nvim', 251 event = 'VeryLazy', 252 config = function() require('which-key').setup {} end, 253 }, 254 255 -- Bufferline 256 { 257 'akinsho/bufferline.nvim', 258 event = 'BufWinEnter', 259 dependencies = 'kyazdani42/nvim-web-devicons', 260 config = function() 261 require('bufferline').setup { options = { separator_style = 'thick' } } 262 end, 263 }, 264 265 -- Hop 266 { 267 'phaazon/hop.nvim', 268 branch = 'v2', 269 keys = { 'f', 'F', 't', 'T' }, 270 config = function() require('hop').setup {} end, 271 }, 272 273 { 274 'akinsho/toggleterm.nvim', -- terminal toggling plugin 275 version = '*', 276 keys = { { '<Leader>t', '<cmd>ToggleTerm<CR>', desc = 'Toggle floating terminal' } }, 277 opts = { 278 size = 20, -- height of split if not floating 279 open_mapping = [[<Leader>t]], -- map <Leader>t to toggle 280 direction = 'float', -- open as floating window 281 float_opts = { 282 border = 'curved', -- single, double, rounded, curved, or none 283 winblend = 0, 284 width = function() return math.floor(vim.o.columns * 0.8) end, 285 height = function() return math.floor(vim.o.lines * 0.8) end, 286 -- row and col will center the float 287 row = 0.5, 288 col = 0.5, 289 }, 290 -- hide line numbers and start in insert mode 291 hide_numbers = true, 292 start_in_insert= true, 293 persist_size = true, 294 }, 295 config = function(_, opts) 296 require('toggleterm').setup(opts) -- apply settings 297 end, 298 }, 299 300 -- Notifications 301 { 302 'rcarriga/nvim-notify', 303 event = 'VeryLazy', 304 config = function() 305 local notify = require('notify') 306 notify.setup({ 307 background_colour = '#000000', 308 stages = 'fade', 309 timeout = 3000, 310 }) 311 vim.notify = notify 312 end, 313 }, 314 315 -- Todo comments 316 { 317 'folke/todo-comments.nvim', 318 event = 'VeryLazy', 319 dependencies = { 'nvim-lua/plenary.nvim' }, 320 config = function() 321 require('todo-comments').setup({ 322 signs = true, 323 sign_priority = 8, 324 keywords = { 325 FIX = { icon = ' ', color = 'error' }, 326 TODO = { icon = ' ', color = 'info' }, 327 HACK = { icon = ' ', color = 'warning' }, 328 WARN = { icon = ' ', color = 'warning', alt = { 'WARNING', 'XXX' } }, 329 PERF = { icon = ' ', alt = { 'OPTIM', 'PERFORMANCE', 'OPTIMIZE' } }, 330 NOTE = { icon = ' ', color = 'hint', alt = { 'INFO' } }, 331 }, 332 highlight = { 333 pattern = [[.*<(KEYWORDS)\s*:]], 334 keyword = 'wide', 335 }, 336 }) 337 end, 338 }, 339 340 -- Neogit 341 { 342 "NeogitOrg/neogit", 343 dependencies = { 344 "nvim-lua/plenary.nvim", 345 "sindrets/diffview.nvim", 346 "nvim-telescope/telescope.nvim", 347 }, 348 opts = { 349 kind = "tab", -- or "split", "vsplit", "floating" 350 integrations = { diffview = true, telescope = true }, 351 }, 352 keys = { 353 { "<leader>gg", function() require("neogit").open() end, desc = "Neogit" }, 354 }, 355 }, 356 357 -- Noice UI 358 { 359 'folke/noice.nvim', 360 event = 'VeryLazy', 361 dependencies = { 362 'MunifTanjim/nui.nvim', 363 'rcarriga/nvim-notify', 364 }, 365 config = function() 366 require('noice').setup({ 367 lsp = { 368 override = { 369 ['vim.lsp.util.convert_input_to_markdown_lines'] = true, 370 ['vim.lsp.util.stylize_markdown'] = true, 371 ['cmp.entry.get_documentation'] = true, 372 }, 373 }, 374 presets = { 375 bottom_search = true, 376 command_palette = true, 377 long_message_to_split = true, 378 inc_rename = false, 379 lsp_doc_border = false, 380 }, 381 }) 382 end, 383 }, 384 }, { 385 rocks = { enabled = false }, -- Disable luarocks since no plugins need it 386 }) 387 388 local map = vim.keymap.set 389 local opts = { silent = true, noremap = true } 390 391 -- Better window navigation 392 map('n', '<Leader>h', '<C-w>h', { desc = 'Move to left split', unpack(opts) }) 393 map('n', '<Leader>j', '<C-w>j', { desc = 'Move to below split', unpack(opts) }) 394 map('n', '<Leader>k', '<C-w>k', { desc = 'Move to above split', unpack(opts) }) 395 map('n', '<Leader>l', '<C-w>l', { desc = 'Move to right split', unpack(opts) }) 396 397 -- Resize splits with arrows 398 map('n', '<Leader><Up>', ':resize -2<CR>', { desc = 'Decrease split height', unpack(opts) }) 399 map('n', '<Leader><Down>', ':resize +2<CR>', { desc = 'Increase split height', unpack(opts) }) 400 map('n', '<Leader><Left>', ':vertical resize -2<CR>', { desc = 'Decrease split width', unpack(opts) }) 401 map('n', '<Leader><Right>', ':vertical resize +2<CR>', { desc = 'Increase split width', unpack(opts) }) 402 403 -- Buffer navigation 404 map('n', '<Leader>bn', ':bnext<CR>', { desc = 'Next buffer', unpack(opts) }) 405 map('n', '<Leader>bp', ':bprevious<CR>', { desc = 'Previous buffer', unpack(opts) }) 406 map('n', '<Leader>bc', ':bdelete<CR>', { desc = 'Close buffer', unpack(opts) }) 407 408 -- Quick save & quit 409 map('n', '<Leader>w', ':write<CR>', { desc = 'Save current file', unpack(opts) }) 410 map('n', '<Leader>q', ':quit<CR>', { desc = 'Quit current window', unpack(opts) }) 411 map('n', '<Leader>WQ', ':wqall<CR>', { desc = 'Save all and quit', unpack(opts) }) 412 413 -- Move lines up/down in visual mode 414 map('v', '<Leader>j', ":m '>+1<CR>gv=gv", { desc = 'Move selection down', unpack(opts) }) 415 map('v', '<Leader>k', ":m '<-2<CR>gv=gv", { desc = 'Move selection up', unpack(opts) }) 416 417 -- Yank to system clipboard 418 map('n', '<Leader>y', '"+y', { desc = 'Yank to system clipboard', unpack(opts) }) 419 map('v', '<Leader>y', '"+y', { desc = 'Yank selection to system clipboard', unpack(opts) }) 420 map('n', '<Leader>Y', '"+Y', { desc = 'Yank entire line to clipboard', unpack(opts) }) 421 422 -- Paste over visual selection without losing register 423 map('v', '<Leader>p', '"_dP', { desc = 'Paste over selection', unpack(opts) }) 424 425 -- Clear search highlights 426 map('n', '<Leader>c', ':nohlsearch<CR>', { desc = 'Clear search highlights',unpack(opts) }) 427 428 -- Quick Telescope pickers 429 map('n', '<Leader>ff', '<cmd>Telescope find_files<CR>', { desc = 'Find files', unpack(opts) }) 430 map('n', '<Leader>fg', '<cmd>Telescope live_grep<CR>', { desc = 'Live grep', unpack(opts) }) 431 map('n', '<Leader>fb', '<cmd>Telescope buffers<CR>', { desc = 'List open buffers', unpack(opts) }) 432 map('n', '<Leader>fh', '<cmd>Telescope help_tags<CR>', { desc = 'Find help tags', unpack(opts) }) 433 434 -- Toggle NvimTree 435 map('n', '<Leader>e', ':NvimTreeToggle<CR>', { desc = 'Toggle file explorer', unpack(opts) }) 436 437 -- Make ESC faster (jk/ kj in insert mode) 438 map('i', 'jk', '<Esc>', { desc = 'Exit insert mode', unpack(opts) }) 439 map('i', 'kj', '<Esc>', { desc = 'Exit insert mode', unpack(opts) }) 440 441 -- Quick comment toggling (using Comment.nvim) 442 -- map('n', '<Leader>/', '<cmd>CommentToggle<CR>', opts) 443 -- map('v', '<Leader>/', '<esc><cmd>CommentToggle<CR>', opts) 444 445 446 -- End of init.lua