diff options
Diffstat (limited to 'nvim/init.lua')
| -rw-r--r-- | nvim/init.lua | 498 |
1 files changed, 460 insertions, 38 deletions
diff --git a/nvim/init.lua b/nvim/init.lua index 864b997..9c61926 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -1,48 +1,470 @@ -vim.g.base46_cache = vim.fn.stdpath "data" .. "/base46/" -vim.g.mapleader = " " +vim.loader.enable() +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' +vim.g.have_nerd_font = true +vim.opt.wrap = false +vim.opt.colorcolumn = "80" +vim.o.number = true +vim.o.relativenumber = true +vim.o.mouse = 'a' +vim.o.showmode = false +vim.schedule(function() vim.o.clipboard = 'unnamedplus' end) +vim.o.breakindent = true +vim.o.undofile = true +vim.o.ignorecase = true +vim.o.smartcase = true +vim.o.signcolumn = 'yes' +vim.o.updatetime = 250 +vim.o.timeoutlen = 300 +vim.o.splitright = true +vim.o.splitbelow = true +vim.o.list = true +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } +vim.o.inccommand = 'split' +vim.o.cursorline = true +vim.o.scrolloff = 5 +vim.o.confirm = true --- bootstrap lazy and all plugins -local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" +vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>') +vim.diagnostic.config { + update_in_insert = false, + severity_sort = true, + float = { border = 'rounded', source = 'if_many' }, + underline = { severity = { min = vim.diagnostic.severity.WARN } }, -if not vim.uv.fs_stat(lazypath) then - local repo = "https://github.com/folke/lazy.nvim.git" - vim.fn.system { "git", "clone", "--filter=blob:none", repo, "--branch=stable", lazypath } -end + virtual_text = true, + virtual_lines = false, -vim.opt.rtp:prepend(lazypath) - -local lazy_config = require "configs.lazy" - --- load plugins -require("lazy").setup({ - { - "NvChad/NvChad", - lazy = false, - branch = "v2.5", - import = "nvchad.plugins", - config = function() - require "options" - local nvim_tree_options = require "nvchad.configs.nvimtree" - nvim_tree_options.filters.dotfiles = false -- To show dotfiles as well - nvim_tree_options.filters.git_ignored = false -- Set this to false to show git ignored files - nvim_tree_options.git = { - enable = true, - ignore = false, -- Set this to false to show git ignored files - timeout = 500, + jump = { + on_jump = function(_, bufnr) + vim.diagnostic.open_float { + bufnr = bufnr, + scope = 'cursor', + focus = false, } end, }, +} + +vim.keymap.set("n", "<leader>mh", "<cmd>:wincmd h<CR>", { desc = "Move between windows (h)" }) +vim.keymap.set("n", "<leader>mj", "<cmd>:wincmd j<CR>", { desc = "Move between windows (j)" }) +vim.keymap.set("n", "<leader>mk", "<cmd>:wincmd k<CR>", { desc = "Move between windows (k)" }) +vim.keymap.set("n", "<leader>ml", "<cmd>:wincmd l<CR>", { desc = "Move between windows (l)" }) + +vim.keymap.set("n", "<leader>sv", "<cmd>:vsplit<CR>", { desc = "Split vertically" }) +vim.keymap.set("n", "<leader>sh", "<cmd>:split<CR>", { desc = "Split horizontally" }) + +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, +}) + +local function run_build(name, cmd, cwd) + local result = vim.system(cmd, { cwd = cwd }):wait() + if result.code ~= 0 then + local stderr = result.stderr or '' + local stdout = result.stdout or '' + local output = stderr ~= '' and stderr or stdout + if output == '' then output = 'No output from build command.' end + vim.notify(('Build failed for %s:\n%s'):format(name, output), vim.log.levels.ERROR) + end +end + +vim.api.nvim_create_autocmd('PackChanged', { + callback = function(ev) + local name = ev.data.spec.name + local kind = ev.data.kind + if kind ~= 'install' and kind ~= 'update' then return end + + if name == 'telescope-fzf-native.nvim' and vim.fn.executable 'make' == 1 then + run_build(name, { 'make' }, ev.data.path) + return + end + + if name == 'LuaSnip' then + if vim.fn.has 'win32' ~= 1 and vim.fn.executable 'make' == 1 then run_build(name, { 'make', 'install_jsregexp' }, ev.data.path) end + return + end + + if name == 'nvim-treesitter' then + if not ev.data.active then vim.cmd.packadd 'nvim-treesitter' end + vim.cmd 'TSUpdate' + return + end + end, +}) + +---@param repo string +---@return string +local function gh(repo) return 'https://github.com/' .. repo end + +vim.pack.add { gh 'NMAC427/guess-indent.nvim' } +require('guess-indent').setup {} + +-- Here is a more advanced configuration example that passes options to `gitsigns.nvim` +-- +-- See `:help gitsigns` to understand what each configuration key does. +-- Adds git related signs to the gutter, as well as utilities for managing changes +vim.pack.add { gh 'lewis6991/gitsigns.nvim' } +require('gitsigns').setup { + signs = { + add = { text = '+' }, ---@diagnostic disable-line: missing-fields + change = { text = '~' }, ---@diagnostic disable-line: missing-fields + delete = { text = '_' }, ---@diagnostic disable-line: missing-fields + topdelete = { text = '‾' }, ---@diagnostic disable-line: missing-fields + changedelete = { text = '~' }, ---@diagnostic disable-line: missing-fields + }, +} + +vim.pack.add { gh 'folke/which-key.nvim' } +require('which-key').setup { + delay = 0, + icons = { mappings = vim.g.have_nerd_font }, + spec = { + { '<leader>s', group = '[S]plit', mode = { 'n' } }, + { '<leader>f', group = '[F]ind', mode = { 'n', 'v' } }, + { '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + { 'gr', group = 'LSP Actions', mode = { 'n' } }, + }, +} + +vim.pack.add { gh 'MunifTanjim/nui.nvim' } +vim.pack.add { gh 'X3eRo0/dired.nvim' } +require('dired').setup { } + +vim.pack.add { gh 'ellisonleao/gruvbox.nvim' } +vim.cmd.colorscheme 'gruvbox' + +vim.pack.add { gh 'folke/todo-comments.nvim' } +require('todo-comments').setup { signs = false } + +vim.pack.add { gh 'nvim-mini/mini.nvim' } + +if vim.g.have_nerd_font then + require('mini.icons').setup() + MiniIcons.mock_nvim_web_devicons() +end + +require('mini.ai').setup { + -- NOTE: Avoid conflicts with the built-in incremental selection mappings on Neovim>=0.12 (see `:help treesitter-incremental-selection`) + mappings = { + around_next = 'aa', + inside_next = 'ii', + }, + n_lines = 500, +} + +require('mini.surround').setup() +local statusline = require 'mini.statusline' +statusline.setup { use_icons = vim.g.have_nerd_font } +---@diagnostic disable-next-line: duplicate-set-field +statusline.section_location = function() return '%2l:%-2v' end + +---@type (string|vim.pack.Spec)[] +local telescope_plugins = { + gh 'nvim-lua/plenary.nvim', + gh 'nvim-telescope/telescope.nvim', + gh 'nvim-telescope/telescope-ui-select.nvim', +} +if vim.fn.executable 'make' == 1 then table.insert(telescope_plugins, gh 'nvim-telescope/telescope-fzf-native.nvim') end + +vim.pack.add(telescope_plugins) + +require('telescope').setup { + extensions = { + ['ui-select'] = { require('telescope.themes').get_dropdown() }, + }, +} + +pcall(require('telescope').load_extension, 'fzf') +pcall(require('telescope').load_extension, 'ui-select') + +local builtin = require 'telescope.builtin' +vim.keymap.set('n', '<leader>fk', builtin.keymaps, { desc = '[F]ind [K]eymaps' }) +vim.keymap.set('n', '<leader>ff', builtin.find_files, { desc = '[F]ind [F]iles' }) +vim.keymap.set({ 'n', 'v' }, '<leader>fw', builtin.grep_string, { desc = '[F]ind current [W]ord' }) +vim.keymap.set('n', '<leader>fg', builtin.live_grep, { desc = '[F]ind by [G]rep' }) +vim.keymap.set('n', '<leader>fd', builtin.diagnostics, { desc = '[F]ind [D]iagnostics' }) +vim.keymap.set('n', '<leader>fc', builtin.commands, { desc = '[F]ind [C]ommands' }) +vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' }) + +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }), + callback = function(event) + local buf = event.buf + vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' }) + vim.keymap.set('n', 'gri', builtin.lsp_implementations, { buffer = buf, desc = '[G]oto [I]mplementation' }) + vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' }) + vim.keymap.set('n', 'gO', builtin.lsp_document_symbols, { buffer = buf, desc = 'Open Document Symbols' }) + vim.keymap.set('n', 'gW', builtin.lsp_dynamic_workspace_symbols, { buffer = buf, desc = 'Open Workspace Symbols' }) + vim.keymap.set('n', 'grt', builtin.lsp_type_definitions, { buffer = buf, desc = '[G]oto [T]ype Definition' }) + end, +}) + +vim.keymap.set('n', '<leader>fc', function() + builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) +end, { desc = '[F]uzzily search in [c]urrent buffer' }) + +vim.keymap.set( + 'n', + '<leader>f/', + function() + builtin.live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, + { desc = '[F]ind in Open Files' } +) + +vim.pack.add { gh 'j-hui/fidget.nvim' } +require('fidget').setup {} + +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('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client:supports_method('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 + if client and client:supports_method('textDocument/inlayHint', event.buf) then + 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') + end + end, +}) + +local servers = { + -- clangd = {}, + -- gopls = {}, + -- pyright = {}, + -- rust_analyzer = {}, + -- + -- 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 = {}, + + stylua = {}, -- Used to format Lua code + + lua_ls = { + on_init = function(client) + client.server_capabilities.documentFormattingProvider = false + + if client.workspace_folders then + local path = client.workspace_folders[1].name + 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 + end + + client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { + runtime = { + version = 'LuaJIT', + path = { 'lua/?.lua', 'lua/?/init.lua' }, + }, + workspace = { + checkThirdParty = false, + -- NOTE: this is a lot slower and will cause issues when working on your own configuration. + -- See https://github.com/neovim/nvim-lspconfig/issues/3189 + library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { + '${3rd}/luv/library', + '${3rd}/busted/library', + }), + }, + }) + end, + ---@type lspconfig.settings.lua_ls + settings = { + Lua = { + format = { enable = false }, + }, + }, + }, +} + +vim.pack.add { + -- gh 'neovim/nvim-lspconfig', + -- gh 'mason-org/mason.nvim', + -- gh 'mason-org/mason-lspconfig.nvim', + -- gh 'WhoIsSethDaniel/mason-tool-installer.nvim', +} + +-- Automatically install LSPs and related tools to stdpath for Neovim +-- require('mason').setup {} + +local ensure_installed = vim.tbl_keys(servers or {}) +vim.list_extend(ensure_installed, { + -- You can add other tools here that you want Mason to install +}) + +-- require('mason-tool-installer').setup { ensure_installed = ensure_installed } + +for name, server in pairs(servers) do + vim.lsp.config(name, server) + vim.lsp.enable(name) +end + +vim.pack.add { gh 'stevearc/conform.nvim' } +require('conform').setup { + notify_on_error = false, + format_on_save = function(bufnr) + local enabled_filetypes = { +c = true, + lua = true, + python = true, + } + if enabled_filetypes[vim.bo[bufnr].filetype] then + return { timeout_ms = 500 } + else + return nil + end + end, + default_format_opts = { + lsp_format = 'fallback', -- Use external formatters if configured below, otherwise use LSP formatting. Set to `false` to disable LSP formatting entirely. + }, + -- You can also specify external formatters in here. + formatters_by_ft = { + -- rust = { 'rustfmt' }, + -- 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 }, + }, +} + +vim.keymap.set({ 'n', 'v' }, '<leader>f', function() require('conform').format { async = true } end, { desc = '[F]ormat buffer' }) + +-- vim.pack.add { { src = gh 'L3MON4D3/LuaSnip', version = vim.version.range '2.*' } } +-- require('luasnip').setup {} + +-- `friendly-snippets` contains a variety of premade snippets. +-- See the README about individual language/framework/plugin snippets: +-- https://github.com/rafamadriz/friendly-snippets +-- +-- vim.pack.add { gh 'rafamadriz/friendly-snippets' } +-- require('luasnip.loaders.from_vscode').lazy_load() + +-- [[ Autocomplete Engine ]] +-- vim.pack.add { { src = gh 'saghen/blink.cmp', version = vim.version.range '1.*' } } +-- require('blink.cmp').setup { + -- keymap = { + -- 'default' (recommended) for mappings similar to built-in completions + -- <c-y> 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: + -- <tab>/<s-tab>: move to right/left of your snippet expansion + -- <c-space>: Open menu or open docs if already open + -- <c-n>/<c-p> or <up>/<down>: Select next/previous item + -- <c-e>: Hide menu + -- <c-k>: Toggle signature help + -- + -- See `:help 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 `<c-space>` 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' }, + -- }, + + -- 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 `:help 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 }, +-- } + +vim.pack.add { { src = gh 'nvim-treesitter/nvim-treesitter', version = 'main' } } + +local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } +require('nvim-treesitter').install(parsers) + +local function treesitter_try_attach(buf, language) + if not vim.treesitter.language.add(language) then return end + vim.treesitter.start(buf, language) + local has_indent_query = vim.treesitter.query.get(language, 'indents') ~= nil + if has_indent_query then vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" end +end - { import = "plugins" }, -}, lazy_config) +local available_parsers = require('nvim-treesitter').get_available() +vim.api.nvim_create_autocmd('FileType', { + callback = function(args) + local buf, filetype = args.buf, args.match --- load theme -dofile(vim.g.base46_cache .. "defaults") -dofile(vim.g.base46_cache .. "statusline") + local language = vim.treesitter.language.get_lang(filetype) + if not language then return end -require "options" -require "autocmds" + local installed_parsers = require('nvim-treesitter').get_installed 'parsers' -vim.schedule(function() - require "mappings" -end) + if vim.tbl_contains(installed_parsers, language) then + treesitter_try_attach(buf, language) + elseif vim.tbl_contains(available_parsers, language) then + require('nvim-treesitter').install(language):await(function() treesitter_try_attach(buf, language) end) + else + treesitter_try_attach(buf, language) + end + end, +}) |
