init.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. --[[
  2. =====================================================================
  3. ==================== READ THIS BEFORE CONTINUING ====================
  4. =====================================================================
  5. Kickstart.nvim is *not* a distribution.
  6. Kickstart.nvim is a template for your own configuration.
  7. The goal is that you can read every line of code, top-to-bottom, understand
  8. what your configuration is doing, and modify it to suit your needs.
  9. Once you've done that, you should start exploring, configuring and tinkering to
  10. explore Neovim!
  11. If you don't know anything about Lua, I recommend taking some time to read through
  12. a guide. One possible example:
  13. - https://learnxinyminutes.com/docs/lua/
  14. And then you can explore or search through `:help lua-guide`
  15. - https://neovim.io/doc/user/lua-guide.html
  16. Kickstart Guide:
  17. I have left several `:help X` comments throughout the init.lua
  18. You should run that command and read that help section for more information.
  19. In addition, I have some `NOTE:` items throughout the file.
  20. These are for you, the reader to help understand what is happening. Feel free to delete
  21. them once you know what you're doing, but they should serve as a guide for when you
  22. are first encountering a few different constructs in your nvim config.
  23. I hope you enjoy your Neovim journey,
  24. - TJ
  25. P.S. You can delete this when you're done too. It's your config now :)
  26. --]]
  27. -- Set <space> as the leader key
  28. -- See `:help mapleader`
  29. -- NOTE: Must happen before plugins are required (otherwise wrong leader will be used)
  30. vim.g.mapleader = ' '
  31. vim.g.maplocalleader = ' '
  32. -- Install package manager
  33. -- https://github.com/folke/lazy.nvim
  34. -- `:help lazy.nvim.txt` for more info
  35. local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
  36. if not vim.loop.fs_stat(lazypath) then
  37. vim.fn.system {
  38. 'git',
  39. 'clone',
  40. '--filter=blob:none',
  41. 'https://github.com/folke/lazy.nvim.git',
  42. '--branch=stable', -- latest stable release
  43. lazypath,
  44. }
  45. end
  46. vim.opt.rtp:prepend(lazypath)
  47. -- NOTE: Here is where you install your plugins.
  48. -- You can configure plugins using the `config` key.
  49. --
  50. -- You can also configure plugins after the setup call,
  51. -- as they will be available in your neovim runtime.
  52. require('lazy').setup({
  53. -- NOTE: First, some plugins that don't require any configuration
  54. -- Git related plugins
  55. 'tpope/vim-fugitive',
  56. 'tpope/vim-rhubarb',
  57. -- Detect tabstop and shiftwidth automatically
  58. 'tpope/vim-sleuth',
  59. -- NOTE: This is where your plugins related to LSP can be installed.
  60. -- The configuration is done below. Search for lspconfig to find it below.
  61. {
  62. -- LSP Configuration & Plugins
  63. 'neovim/nvim-lspconfig',
  64. dependencies = {
  65. -- Automatically install LSPs to stdpath for neovim
  66. { 'williamboman/mason.nvim', config = true },
  67. 'williamboman/mason-lspconfig.nvim',
  68. -- Useful status updates for LSP
  69. -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})`
  70. { 'j-hui/fidget.nvim', tag = 'legacy', opts = {} },
  71. -- Additional lua configuration, makes nvim stuff amazing!
  72. 'folke/neodev.nvim',
  73. },
  74. },
  75. {
  76. -- Autocompletion
  77. 'hrsh7th/nvim-cmp',
  78. dependencies = {
  79. -- Snippet Engine & its associated nvim-cmp source
  80. 'L3MON4D3/LuaSnip',
  81. 'saadparwaiz1/cmp_luasnip',
  82. -- Adds LSP completion capabilities
  83. 'hrsh7th/cmp-nvim-lsp',
  84. -- Adds a number of user-friendly snippets
  85. 'rafamadriz/friendly-snippets',
  86. },
  87. },
  88. -- Useful plugin to show you pending keybinds.
  89. { 'folke/which-key.nvim', opts = {} },
  90. {
  91. -- Adds git related signs to the gutter, as well as utilities for managing changes
  92. 'lewis6991/gitsigns.nvim',
  93. opts = {
  94. -- See `:help gitsigns.txt`
  95. signs = {
  96. add = { text = '+' },
  97. change = { text = '~' },
  98. delete = { text = '_' },
  99. topdelete = { text = '‾' },
  100. changedelete = { text = '~' },
  101. },
  102. on_attach = function(bufnr)
  103. vim.keymap.set('n', '<leader>gp', require('gitsigns').prev_hunk,
  104. { buffer = bufnr, desc = '[G]o to [P]revious Hunk' })
  105. vim.keymap.set('n', '<leader>gn', require('gitsigns').next_hunk, { buffer = bufnr, desc = '[G]o to [N]ext Hunk' })
  106. vim.keymap.set('n', '<leader>ph', require('gitsigns').preview_hunk, { buffer = bufnr, desc = '[P]review [H]unk' })
  107. end,
  108. },
  109. },
  110. {
  111. -- Theme inspired by Atom
  112. 'navarasu/onedark.nvim',
  113. priority = 1000,
  114. config = function()
  115. vim.cmd.colorscheme 'onedark'
  116. end,
  117. },
  118. {
  119. -- Set lualine as statusline
  120. 'nvim-lualine/lualine.nvim',
  121. -- See `:help lualine.txt`
  122. opts = {
  123. options = {
  124. icons_enabled = false,
  125. theme = 'onedark',
  126. component_separators = '|',
  127. section_separators = '',
  128. },
  129. },
  130. },
  131. {
  132. -- Add indentation guides even on blank lines
  133. 'lukas-reineke/indent-blankline.nvim',
  134. -- Enable `lukas-reineke/indent-blankline.nvim`
  135. -- See `:help indent_blankline.txt`
  136. opts = {
  137. char = '┊',
  138. show_trailing_blankline_indent = false,
  139. },
  140. },
  141. -- "gc" to comment visual regions/lines
  142. { 'numToStr/Comment.nvim', opts = {} },
  143. -- Fuzzy Finder (files, lsp, etc)
  144. {
  145. 'nvim-telescope/telescope.nvim',
  146. branch = '0.1.x',
  147. dependencies = {
  148. 'nvim-lua/plenary.nvim',
  149. -- Fuzzy Finder Algorithm which requires local dependencies to be built.
  150. -- Only load if `make` is available. Make sure you have the system
  151. -- requirements installed.
  152. {
  153. 'nvim-telescope/telescope-fzf-native.nvim',
  154. -- NOTE: If you are having trouble with this installation,
  155. -- refer to the README for telescope-fzf-native for more instructions.
  156. build = 'make',
  157. cond = function()
  158. return vim.fn.executable 'make' == 1
  159. end,
  160. },
  161. },
  162. },
  163. {
  164. -- Highlight, edit, and navigate code
  165. 'nvim-treesitter/nvim-treesitter',
  166. dependencies = {
  167. 'nvim-treesitter/nvim-treesitter-textobjects',
  168. },
  169. build = ':TSUpdate',
  170. },
  171. -- NOTE: Next Step on Your Neovim Journey: Add/Configure additional "plugins" for kickstart
  172. -- These are some example plugins that I've included in the kickstart repository.
  173. -- Uncomment any of the lines below to enable them.
  174. -- require 'kickstart.plugins.autoformat',
  175. -- require 'kickstart.plugins.debug',
  176. -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua`
  177. -- You can use this folder to prevent any conflicts with this init.lua if you're interested in keeping
  178. -- up-to-date with whatever is in the kickstart repo.
  179. -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going.
  180. --
  181. -- For additional information see: https://github.com/folke/lazy.nvim#-structuring-your-plugins
  182. -- { import = 'custom.plugins' },
  183. }, {})
  184. -- [[ Setting options ]]
  185. -- See `:help vim.o`
  186. -- NOTE: You can change these options as you wish!
  187. -- Set highlight on search
  188. vim.o.hlsearch = false
  189. -- Make line numbers default
  190. vim.wo.number = true
  191. -- Enable mouse mode
  192. vim.o.mouse = 'a'
  193. -- Sync clipboard between OS and Neovim.
  194. -- Remove this option if you want your OS clipboard to remain independent.
  195. -- See `:help 'clipboard'`
  196. vim.o.clipboard = 'unnamedplus'
  197. -- Enable break indent
  198. vim.o.breakindent = true
  199. -- Save undo history
  200. vim.o.undofile = true
  201. -- Case-insensitive searching UNLESS \C or capital in search
  202. vim.o.ignorecase = true
  203. vim.o.smartcase = true
  204. -- Keep signcolumn on by default
  205. vim.wo.signcolumn = 'yes'
  206. -- Decrease update time
  207. vim.o.updatetime = 250
  208. vim.o.timeoutlen = 300
  209. -- Set completeopt to have a better completion experience
  210. vim.o.completeopt = 'menuone,noselect'
  211. -- NOTE: You should make sure your terminal supports this
  212. vim.o.termguicolors = true
  213. -- [[ Basic Keymaps ]]
  214. -- Keymaps for better default experience
  215. -- See `:help vim.keymap.set()`
  216. vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
  217. -- Remap for dealing with word wrap
  218. vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
  219. vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
  220. -- [[ Highlight on yank ]]
  221. -- See `:help vim.highlight.on_yank()`
  222. local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
  223. vim.api.nvim_create_autocmd('TextYankPost', {
  224. callback = function()
  225. vim.highlight.on_yank()
  226. end,
  227. group = highlight_group,
  228. pattern = '*',
  229. })
  230. -- [[ Configure Telescope ]]
  231. -- See `:help telescope` and `:help telescope.setup()`
  232. require('telescope').setup {
  233. defaults = {
  234. mappings = {
  235. i = {
  236. ['<C-u>'] = false,
  237. ['<C-d>'] = false,
  238. },
  239. },
  240. },
  241. }
  242. -- Enable telescope fzf native, if installed
  243. pcall(require('telescope').load_extension, 'fzf')
  244. -- See `:help telescope.builtin`
  245. vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
  246. vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
  247. vim.keymap.set('n', '<leader>/', function()
  248. -- You can pass additional configuration to telescope to change theme, layout, etc.
  249. require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
  250. winblend = 10,
  251. previewer = false,
  252. })
  253. end, { desc = '[/] Fuzzily search in current buffer' })
  254. vim.keymap.set('n', '<leader>ff', require('telescope.builtin').git_files, { desc = 'Search [G]it [F]iles' })
  255. vim.keymap.set('n', '<leader>sf', require('telescope.builtin').find_files, { desc = '[S]earch [F]iles' })
  256. vim.keymap.set('n', '<leader>sh', require('telescope.builtin').help_tags, { desc = '[S]earch [H]elp' })
  257. vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
  258. vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
  259. vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
  260. -- [[ Configure Treesitter ]]
  261. -- See `:help nvim-treesitter`
  262. require('nvim-treesitter.configs').setup {
  263. -- Add languages to be installed here that you want installed for treesitter
  264. ensure_installed = { 'c', 'cpp', 'go', 'lua', 'python', 'rust', 'tsx', 'typescript', 'vimdoc', 'vim' },
  265. -- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
  266. auto_install = false,
  267. highlight = { enable = true },
  268. indent = { enable = true },
  269. incremental_selection = {
  270. enable = true,
  271. keymaps = {
  272. init_selection = '<c-space>',
  273. node_incremental = '<c-space>',
  274. scope_incremental = '<c-s>',
  275. node_decremental = '<M-space>',
  276. },
  277. },
  278. textobjects = {
  279. select = {
  280. enable = true,
  281. lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
  282. keymaps = {
  283. -- You can use the capture groups defined in textobjects.scm
  284. ['aa'] = '@parameter.outer',
  285. ['ia'] = '@parameter.inner',
  286. ['af'] = '@function.outer',
  287. ['if'] = '@function.inner',
  288. ['ac'] = '@class.outer',
  289. ['ic'] = '@class.inner',
  290. },
  291. },
  292. move = {
  293. enable = true,
  294. set_jumps = true, -- whether to set jumps in the jumplist
  295. goto_next_start = {
  296. [']m'] = '@function.outer',
  297. [']]'] = '@class.outer',
  298. },
  299. goto_next_end = {
  300. [']M'] = '@function.outer',
  301. [']['] = '@class.outer',
  302. },
  303. goto_previous_start = {
  304. ['[m'] = '@function.outer',
  305. ['[['] = '@class.outer',
  306. },
  307. goto_previous_end = {
  308. ['[M'] = '@function.outer',
  309. ['[]'] = '@class.outer',
  310. },
  311. },
  312. swap = {
  313. enable = true,
  314. swap_next = {
  315. ['<leader>a'] = '@parameter.inner',
  316. },
  317. swap_previous = {
  318. ['<leader>A'] = '@parameter.inner',
  319. },
  320. },
  321. },
  322. }
  323. -- Diagnostic keymaps
  324. vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' })
  325. vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' })
  326. vim.keymap.set('n', '<leader>e', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' })
  327. vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostics list' })
  328. -- [[ Configure LSP ]]
  329. -- This function gets run when an LSP connects to a particular buffer.
  330. local on_attach = function(_, bufnr)
  331. -- NOTE: Remember that lua is a real programming language, and as such it is possible
  332. -- to define small helper and utility functions so you don't have to repeat yourself
  333. -- many times.
  334. --
  335. -- In this case, we create a function that lets us more easily define mappings specific
  336. -- for LSP related items. It sets the mode, buffer and description for us each time.
  337. local nmap = function(keys, func, desc)
  338. if desc then
  339. desc = 'LSP: ' .. desc
  340. end
  341. vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
  342. end
  343. nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
  344. nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
  345. nmap('<leader>cf', vim.lsp.buf.format, '[C]ode [F]ormat')
  346. nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition')
  347. nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
  348. nmap('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation')
  349. nmap('<leader>D', vim.lsp.buf.type_definition, 'Type [D]efinition')
  350. nmap('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
  351. nmap('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
  352. -- See `:help K` for why this keymap
  353. nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
  354. nmap('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
  355. -- Lesser used LSP functionality
  356. nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
  357. nmap('<leader>wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder')
  358. nmap('<leader>wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder')
  359. nmap('<leader>wl', function()
  360. print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
  361. end, '[W]orkspace [L]ist Folders')
  362. -- Create a command `:Format` local to the LSP buffer
  363. vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
  364. vim.lsp.buf.format()
  365. end, { desc = 'Format current buffer with LSP' })
  366. end
  367. -- Enable the following language servers
  368. -- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
  369. --
  370. -- Add any additional override configuration in the following tables. They will be passed to
  371. -- the `settings` field of the server config. You must look up that documentation yourself.
  372. --
  373. -- If you want to override the default filetypes that your language server will attach to you can
  374. -- define the property 'filetypes' to the map in question.
  375. local servers = {
  376. clangd = {},
  377. gopls = {},
  378. -- pyright = {},
  379. rust_analyzer = {},
  380. tsserver = {},
  381. html = { filetypes = { 'html', 'twig', 'hbs' } },
  382. lua_ls = {
  383. Lua = {
  384. workspace = { checkThirdParty = false },
  385. telemetry = { enable = false },
  386. },
  387. },
  388. }
  389. -- Setup neovim lua configuration
  390. require('neodev').setup()
  391. -- nvim-cmp supports additional completion capabilities, so broadcast that to servers
  392. local capabilities = vim.lsp.protocol.make_client_capabilities()
  393. capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
  394. -- Ensure the servers above are installed
  395. local mason_lspconfig = require 'mason-lspconfig'
  396. mason_lspconfig.setup {
  397. ensure_installed = vim.tbl_keys(servers),
  398. }
  399. mason_lspconfig.setup_handlers {
  400. function(server_name)
  401. require('lspconfig')[server_name].setup {
  402. capabilities = capabilities,
  403. on_attach = on_attach,
  404. settings = servers[server_name],
  405. filetypes = (servers[server_name] or {}).filetypes,
  406. }
  407. end
  408. }
  409. -- [[ Configure nvim-cmp ]]
  410. -- See `:help cmp`
  411. local cmp = require 'cmp'
  412. local luasnip = require 'luasnip'
  413. require('luasnip.loaders.from_vscode').lazy_load()
  414. luasnip.config.setup {}
  415. cmp.setup {
  416. snippet = {
  417. expand = function(args)
  418. luasnip.lsp_expand(args.body)
  419. end,
  420. },
  421. mapping = cmp.mapping.preset.insert {
  422. ['<C-n>'] = cmp.mapping.select_next_item(),
  423. ['<C-p>'] = cmp.mapping.select_prev_item(),
  424. ['<C-d>'] = cmp.mapping.scroll_docs(-4),
  425. ['<C-f>'] = cmp.mapping.scroll_docs(4),
  426. ['<C-Space>'] = cmp.mapping.complete {},
  427. ['<CR>'] = cmp.mapping.confirm {
  428. behavior = cmp.ConfirmBehavior.Replace,
  429. select = true,
  430. },
  431. ['<Tab>'] = cmp.mapping(function(fallback)
  432. if cmp.visible() then
  433. cmp.select_next_item()
  434. elseif luasnip.expand_or_locally_jumpable() then
  435. luasnip.expand_or_jump()
  436. else
  437. fallback()
  438. end
  439. end, { 'i', 's' }),
  440. ['<S-Tab>'] = cmp.mapping(function(fallback)
  441. if cmp.visible() then
  442. cmp.select_prev_item()
  443. elseif luasnip.locally_jumpable(-1) then
  444. luasnip.jump(-1)
  445. else
  446. fallback()
  447. end
  448. end, { 'i', 's' }),
  449. },
  450. sources = {
  451. { name = 'nvim_lsp' },
  452. { name = 'luasnip' },
  453. },
  454. }
  455. -- The line beneath this is called `modeline`. See `:help modeline`
  456. -- vim: ts=2 sts=2 sw=2 et