init.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. -- disable netrw for nvim-tree plugin
  2. vim.g.loaded_netrw = 1
  3. vim.g.loaded_netrwPlugin = 1
  4. -- package manager
  5. local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
  6. if not (vim.uv or vim.loop).fs_stat(lazypath) then
  7. local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  8. local out = vim.fn.system({
  9. "git",
  10. "clone",
  11. "--filter=blob:none",
  12. "--branch=stable", -- latest stable release
  13. lazyrepo,
  14. lazypath,
  15. })
  16. if vim.v.shell_error ~= 0 then
  17. vim.api.nvim_echo({
  18. { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
  19. { out, "WarningMsg" },
  20. { "\nPress any key to exit..." },
  21. }, true, {})
  22. vim.fn.getchar()
  23. os.exit(1)
  24. end
  25. end
  26. vim.opt.rtp:prepend(lazypath)
  27. -- set space key as a leader key,
  28. -- this has to be done before loading lazy.nvim
  29. vim.g.mapleader = ' '
  30. vim.g.maplocalleader = ' '
  31. require("lazy").setup({
  32. spec = {
  33. "nvim-tree/nvim-tree.lua",
  34. "nvim-tree/nvim-web-devicons",
  35. "nvim-lualine/lualine.nvim",
  36. -- color theme
  37. {
  38. "catppuccin/nvim",
  39. name = "catppuccin",
  40. -- make sure to load this during startup
  41. lazy = false,
  42. -- make sure to load this beofre all other plugins
  43. priority = 1000,
  44. config = function()
  45. vim.cmd.colorscheme("catppuccin-macchiato")
  46. end,
  47. },
  48. -- LSP
  49. {
  50. "mason-org/mason-lspconfig.nvim",
  51. opts = {
  52. ensure_installed = {
  53. "lua_ls",
  54. "rust_analyzer",
  55. "pyright",
  56. "clangd",
  57. },
  58. },
  59. dependencies = {
  60. { "mason-org/mason.nvim", opts = {} },
  61. "neovim/nvim-lspconfig",
  62. }
  63. },
  64. -- configure lua language server for nvim config file
  65. {
  66. "folke/lazydev.nvim",
  67. ft = "lua", -- only load for lua files
  68. opts = {},
  69. },
  70. -- venv selector for python
  71. {
  72. "linux-cultist/venv-selector.nvim",
  73. dependencies = {
  74. "neovim/nvim-lspconfig",
  75. {
  76. "nvim-telescope/telescope.nvim",
  77. branch = "0.1.x",
  78. dependencies = { "nvim-lua/plenary.nvim" }
  79. }, -- optional: you can also use fzf-lua, snacks, mini-pick instead.
  80. },
  81. ft = "python", -- Load when opening Python files
  82. keys = {
  83. { ",v", "<cmd>VenvSelect<cr>" }, -- Open picker on keymap
  84. },
  85. opts = { -- this can be an empty lua table - just showing below for clarity.
  86. search = {}, -- if you add your own searches, they go here.
  87. options = {} -- if you add plugin options, they go here.
  88. },
  89. },
  90. -- Autocompletion
  91. -- TODO: look into github.com/ms-jpq/coq_nvim
  92. {
  93. 'hrsh7th/nvim-cmp',
  94. dependencies = {
  95. -- Snippet Engine & its associated nvim-cmp source
  96. 'L3MON4D3/LuaSnip',
  97. 'saadparwaiz1/cmp_luasnip',
  98. -- Adds LSP completion capabilities
  99. 'hrsh7th/cmp-nvim-lsp',
  100. -- Adds a number of user-friendly snippets
  101. 'rafamadriz/friendly-snippets',
  102. },
  103. },
  104. -- Useful plugin to show you pending keybinds.
  105. "folke/which-key.nvim",
  106. -- "gc" to comment visual regions/lines
  107. "numToStr/Comment.nvim",
  108. -- Fuzzy Finder (files, lsp, etc)
  109. {
  110. 'nvim-telescope/telescope.nvim',
  111. branch = '0.1.x',
  112. dependencies = {
  113. 'nvim-lua/plenary.nvim',
  114. -- Fuzzy Finder Algorithm which requires local dependencies to be built.
  115. -- Only load if `make` is available. Make sure you have the system
  116. -- requirements installed.
  117. {
  118. 'nvim-telescope/telescope-fzf-native.nvim',
  119. -- NOTE: If you are having trouble with this installation,
  120. -- refer to the README for telescope-fzf-native for more instructions.
  121. build = 'make',
  122. cond = function()
  123. return vim.fn.executable 'make' == 1
  124. end,
  125. },
  126. },
  127. },
  128. -- Highlight, edit, and navigate code
  129. {
  130. 'nvim-treesitter/nvim-treesitter',
  131. dependencies = {
  132. 'nvim-treesitter/nvim-treesitter-textobjects',
  133. },
  134. build = ':TSUpdate',
  135. },
  136. -- Cut text without populating unnamed register
  137. {
  138. "gbprod/cutlass.nvim",
  139. opts = {
  140. cut_key = "<Leader>x",
  141. }
  142. },
  143. },
  144. -- automatically check for plugin updates
  145. checker = { enabled = true },
  146. })
  147. -- copy to system clipboard by default
  148. vim.o.clipboard = "unnamedplus"
  149. vim.o.termguicolors = true
  150. vim.o.completeopt = "menuone,noselect"
  151. vim.opt.guifont = "Hack Nerd Font Mono:h12"
  152. vim.opt.number = true
  153. vim.opt.mouse = ""
  154. vim.opt.hlsearch = true
  155. vim.opt.tabstop = 2
  156. vim.opt.shiftwidth = 2
  157. require("lualine").setup({})
  158. require("nvim-tree").setup({
  159. view = {
  160. width = 30,
  161. },
  162. on_attach = function (bufnr)
  163. local api = require "nvim-tree.api"
  164. api.config.mappings.default_on_attach(bufnr)
  165. vim.keymap.set("n", ".", api.tree.change_root_to_node,
  166. {noremap=true, silent=true, buffer=bufnr, nowait=true})
  167. end,
  168. })
  169. -- unmap space
  170. vim.api.nvim_set_keymap('n', '<Space>', '', {noremap=true, silent=true})
  171. -- window operations with leader key
  172. vim.api.nvim_set_keymap("n", "<Leader>w", "<C-w>", {noremap=true, silent=true})
  173. -- custom nvim tree mappings
  174. vim.api.nvim_set_keymap("n", "<Leader>ft", ":NvimTreeToggle<CR>", {noremap=true, silent=true})
  175. vim.api.nvim_set_keymap("n", "<BS>", ":NvimTreeFocus<CR>", {noremap=true, silent=true})
  176. -- configure telescope
  177. -- See `:help telescope` and `:help telescope.setup()`
  178. require('telescope').setup {
  179. defaults = {
  180. mappings = {
  181. i = {
  182. ['<C-u>'] = false,
  183. ['<C-d>'] = false,
  184. },
  185. },
  186. },
  187. }
  188. -- Enable telescope fzf native, if installed
  189. pcall(require('telescope').load_extension, 'fzf')
  190. -- See `:help telescope.builtin`
  191. vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
  192. vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
  193. vim.keymap.set('n', '<leader>/', function()
  194. -- You can pass additional configuration to telescope to change theme, layout, etc.
  195. require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
  196. winblend = 10,
  197. previewer = false,
  198. })
  199. end, { desc = '[/] Fuzzily search in current buffer' })
  200. -- vim.keymap.set('n', '<leader>gf', require('telescope.builtin').git_files, { desc = 'Search [G]it [F]iles' })
  201. vim.keymap.set('n', '<leader>ff', require('telescope.builtin').find_files, { desc = '[S]earch [F]iles' })
  202. -- vim.keymap.set('n', '<leader>sh', require('telescope.builtin').help_tags, { desc = '[S]earch [H]elp' })
  203. -- vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
  204. -- vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
  205. -- vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
  206. -- Configure Treesitter
  207. -- See `:help nvim-treesitter`
  208. require('nvim-treesitter.configs').setup {
  209. modules = {},
  210. -- Add languages to be installed here that you want installed for treesitter
  211. ensure_installed = {'haskell', 'c', 'cpp', 'go', 'glsl', 'lua', 'python', 'rust', 'tsx', 'typescript', 'vimdoc', 'vim' },
  212. -- Install parsers synchronously (only applied to `ensure_installed`)
  213. sync_install = false,
  214. -- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
  215. auto_install = true,
  216. -- List of parsers to ignore installing (or "all")
  217. ignore_install = {},
  218. highlight = { enable = true },
  219. indent = { enable = true },
  220. incremental_selection = {
  221. enable = true,
  222. keymaps = {
  223. init_selection = '<c-space>',
  224. node_incremental = '<c-space>',
  225. scope_incremental = '<c-s>',
  226. node_decremental = '<M-space>',
  227. },
  228. },
  229. textobjects = {
  230. select = {
  231. enable = true,
  232. lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
  233. keymaps = {
  234. -- You can use the capture groups defined in textobjects.scm
  235. ['aa'] = '@parameter.outer',
  236. ['ia'] = '@parameter.inner',
  237. ['af'] = '@function.outer',
  238. ['if'] = '@function.inner',
  239. ['ac'] = '@class.outer',
  240. ['ic'] = '@class.inner',
  241. },
  242. },
  243. move = {
  244. enable = true,
  245. set_jumps = true, -- whether to set jumps in the jumplist
  246. goto_next_start = {
  247. [']m'] = '@function.outer',
  248. [']]'] = '@class.outer',
  249. },
  250. goto_next_end = {
  251. [']M'] = '@function.outer',
  252. [']['] = '@class.outer',
  253. },
  254. goto_previous_start = {
  255. ['[m'] = '@function.outer',
  256. ['[['] = '@class.outer',
  257. },
  258. goto_previous_end = {
  259. ['[M'] = '@function.outer',
  260. ['[]'] = '@class.outer',
  261. },
  262. },
  263. swap = {
  264. enable = true,
  265. swap_next = {
  266. ['<leader>a'] = '@parameter.inner',
  267. },
  268. swap_previous = {
  269. ['<leader>A'] = '@parameter.inner',
  270. },
  271. },
  272. },
  273. }
  274. -- Diagnostic keymaps
  275. vim.keymap.set('n', '<Leader>dp',
  276. function() vim.diagnostic.jump({count=-1, float=true}) end,
  277. { desc = 'Go to previous diagnostic message' })
  278. vim.keymap.set('n', '<Leader>dn',
  279. function() vim.diagnostic.jump({count=1, float=true}) end,
  280. { desc = 'Go to next diagnostic message' })
  281. vim.keymap.set('n', '<Leader>de', vim.diagnostic.open_float,
  282. { desc = 'Open floating diagnostic message' })
  283. vim.keymap.set('n', '<Leader>dl', vim.diagnostic.setloclist,
  284. { desc = 'Open diagnostics list' })
  285. -- nvim-cmp supports additional completion capabilities, so broadcast that to servers
  286. local capabilities = vim.lsp.protocol.make_client_capabilities()
  287. capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
  288. -- Configure autocompletion nvim-cmp
  289. -- See `:help cmp`
  290. local cmp = require 'cmp'
  291. local luasnip = require 'luasnip'
  292. require('luasnip.loaders.from_vscode').lazy_load()
  293. luasnip.config.setup {}
  294. cmp.setup {
  295. snippet = {
  296. expand = function(args)
  297. luasnip.lsp_expand(args.body)
  298. end,
  299. },
  300. mapping = cmp.mapping.preset.insert {
  301. ['<C-n>'] = cmp.mapping.select_next_item(),
  302. ['<C-p>'] = cmp.mapping.select_prev_item(),
  303. ['<C-d>'] = cmp.mapping.scroll_docs(-4),
  304. ['<C-f>'] = cmp.mapping.scroll_docs(4),
  305. ['<C-Space>'] = cmp.mapping.complete {},
  306. ['<CR>'] = cmp.mapping.confirm {
  307. behavior = cmp.ConfirmBehavior.Replace,
  308. select = true,
  309. },
  310. ['<Tab>'] = cmp.mapping(function(fallback)
  311. if cmp.visible() then
  312. cmp.select_next_item()
  313. elseif luasnip.expand_or_locally_jumpable() then
  314. luasnip.expand_or_jump()
  315. else
  316. fallback()
  317. end
  318. end, { 'i', 's' }),
  319. ['<S-Tab>'] = cmp.mapping(function(fallback)
  320. if cmp.visible() then
  321. cmp.select_prev_item()
  322. elseif luasnip.locally_jumpable(-1) then
  323. luasnip.jump(-1)
  324. else
  325. fallback()
  326. end
  327. end, { 'i', 's' }),
  328. },
  329. sources = {
  330. { name = 'nvim_lsp' },
  331. { name = 'luasnip' },
  332. },
  333. }
  334. -- Do not yank when pasting over selected text
  335. -- "x" - visual mode
  336. vim.keymap.set("x", "p", "P", { silent = true })
  337. -- Auto format selected code
  338. vim.keymap.set("v", "<leader>f", function()
  339. local start_pos = vim.api.nvim_buf_get_mark(0, "<")
  340. local end_pos = vim.api.nvim_buf_get_mark(0, ">")
  341. vim.lsp.buf.format({
  342. range = {
  343. ["start"] = { start_pos[1] - 1, start_pos[2] },
  344. ["end"] = { end_pos[1] - 1, end_pos[2] },
  345. },
  346. })
  347. end)