├── .github └── README.md ├── .gitignore ├── .stylua.toml ├── .vscode ├── keybindings.json └── settings.json ├── after └── ftplugin │ ├── eruby.lua │ ├── gitcommit.lua │ ├── go.lua │ ├── markdown.lua │ └── ruby.lua ├── init.lua └── lua ├── code ├── init.lua ├── keybindings.lua └── lazy.lua ├── core ├── init.lua ├── keybindings.lua ├── lazy.lua ├── options.lua └── utils.lua ├── lsp └── init.lua ├── plugins ├── after │ ├── aerial.lua │ ├── git-blame.lua │ └── oil.lua ├── alpha.lua ├── arrow.lua ├── blink-cmp.lua ├── bufferline.lua ├── comment.lua ├── conform.lua ├── faster.lua ├── fidget.lua ├── fzf.lua ├── git-conflict.lua ├── gitsigns.lua ├── highlight-colors.lua ├── hop.lua ├── indent-blankline.lua ├── lsp.lua ├── lualine.lua ├── mini-bufremove.lua ├── mini-icons.lua ├── mini-indentscope.lua ├── mini-pairs.lua ├── mini-trailspace.lua ├── nightfox.lua ├── nvim-lint.lua ├── obsidian.lua ├── overseer.lua ├── plenary.lua ├── render-markdown.lua ├── scope.lua ├── scrollbar.lua ├── telescope.lua ├── todo-comments.lua ├── toggleterm.lua ├── treesitter.lua ├── trouble.lua ├── ufo.lua ├── vgit.lua ├── vimtex.lua └── virt-column.lua └── ui └── utils.lua /.github/README.md: -------------------------------------------------------------------------------- 1 |

Hybrid NeoVim/VSCode Config

2 | 3 |
4 | This project hosts a versatile and easy-to-use NeoVim config 5 | written in Lua, designed to deliver a comfortable and consistent 6 | developer experience in both NeoVim and VSCode. 7 |
8 | 9 | ## 💡 Rationale 10 | 11 | Transitioning from a GUI-based text editor such as VSCode to a highly 12 | customizable terminal-based editor like NeoVim can feel like a daunting task. 13 | This config aims to smooth out this learning curve, allowing developers 14 | to switch between these two at their own pace and comfort level. 15 | The keybinds were deliberatly chosen to offer a consistent developer 16 | experience across both editors. 17 | 18 | ## 📦 Dependencies 19 | 20 | Before you proceed, make sure you have the following installed: 21 | 22 | - [NeoVim 0.10+](https://github.com/neovim/neovim) 23 | - [make](https://www.gnu.org/software/make/) 24 | - [fzf](https://github.com/junegunn/fzf) - a general-purpose command-line fuzzy finder 25 | - [ripgrep](https://github.com/BurntSushi/ripgrep) - a line-oriented search tool 26 | - [Nerd Fonts](https://www.nerdfonts.com/font-downloads) - for icon and glyph support 27 | - [vscode-neovim](https://github.com/vscode-neovim/vscode-neovim/) - a NeoVim integration extension for VSCode 28 | - A system clipboard integration tool (`:help clipboard-tool`) 29 | - C++ Compiler 30 | - **For Linux**: G++ 31 | - **For Windows**: MinGW 32 | 33 | ## ⚙️ Installation 34 | 35 | To use this config, follow these steps: 36 | 37 | 1. Clone this repository into your nvim config folder, which is typically: 38 | - **Linux/Mac**: `$HOME/.config/` 39 | - **Windows**: `$ENV:LocalAppData` 40 | 2. Specify the path to your `init.lua` in the `vscode-neovim` extension settings in VSCode. 41 | 3. Open NeoVim, which will automatically install the plugins on the first start. 42 | 43 | > **Note**: VSCode config files can be found in the `.vscode/` directory. 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lazy-lock.json 2 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = 'Unix' 3 | indent_type = 'Spaces' 4 | indent_width = 2 5 | quote_style = 'AutoPreferSingle' 6 | call_parentheses = 'Always' 7 | -------------------------------------------------------------------------------- /.vscode/keybindings.json: -------------------------------------------------------------------------------- 1 | [ 2 | // Navigations towards the editor 3 | { 4 | "key": "ctrl+l", 5 | "command": "workbench.action.focusActiveEditorGroup", 6 | "when": "sideBarFocus" 7 | }, 8 | { 9 | "key": "ctrl+k", 10 | "command": "workbench.action.focusActiveEditorGroup", 11 | "when": "terminalFocus" 12 | }, 13 | { 14 | "key": "ctrl+t", 15 | "command": "workbench.action.togglePanel" 16 | }, 17 | 18 | // Lists 19 | { 20 | "key": "j", 21 | "command": "list.focusDown", 22 | "when": "listFocus && !inputFocus" 23 | }, 24 | { 25 | "key": "k", 26 | "command": "list.focusUp", 27 | "when": "listFocus && !inputFocus" 28 | }, 29 | { 30 | "key": "l", 31 | "command": "list.select", 32 | "when": "listFocus && !inputFocus" 33 | }, 34 | { 35 | "key": "o", 36 | "command": "list.toggleExpand", 37 | "when": "listFocus && !inputFocus" 38 | }, 39 | { 40 | "key": "h", 41 | "command": "list.collapse", 42 | "when": "listFocus && !inputFocus" 43 | }, 44 | 45 | // Quick Open 46 | { 47 | "key": "ctrl+j", 48 | "command": "workbench.action.quickOpenNavigateNext", 49 | "when": "inQuickOpen" 50 | }, 51 | { 52 | "key": "ctrl+k", 53 | "command": "workbench.action.quickOpenNavigatePrevious", 54 | "when": "inQuickOpen" 55 | }, 56 | 57 | // File Explorer 58 | { 59 | "key": "enter", 60 | "command": "list.select", 61 | "when": "filesExplorerFocus" 62 | }, 63 | { 64 | "key": "r", 65 | "command": "renameFile", 66 | "when": "filesExplorerFocus && !inputFocus" 67 | }, 68 | { 69 | "key": "d", 70 | "command": "deleteFile", 71 | "when": "filesExplorerFocus && !inputFocus" 72 | }, 73 | { 74 | "key": "y", 75 | "command": "filesExplorer.copy", 76 | "when": "filesExplorerFocus && !inputFocus" 77 | }, 78 | { 79 | "key": "x", 80 | "command": "filesExplorer.cut", 81 | "when": "filesExplorerFocus && !inputFocus" 82 | }, 83 | { 84 | "key": "p", 85 | "command": "filesExplorer.paste", 86 | "when": "filesExplorerFocus && !inputFocus" 87 | }, 88 | { 89 | "key": "v", 90 | "command": "explorer.openToSide", 91 | "when": "filesExplorerFocus && !inputFocus" 92 | }, 93 | { 94 | "key": "a", 95 | "command": "explorer.newFile", 96 | "when": "filesExplorerFocus && !inputFocus" 97 | }, 98 | { 99 | "key": "shift+a", 100 | "command": "explorer.newFolder", 101 | "when": "filesExplorerFocus && !inputFocus" 102 | }, 103 | 104 | // Suggestions 105 | { 106 | "key": "ctrl+j", 107 | "command": "selectNextSuggestion", 108 | "when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible" 109 | }, 110 | { 111 | "key": "ctrl+k", 112 | "command": "selectPrevSuggestion", 113 | "when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible" 114 | }, 115 | { 116 | "key": "tab", 117 | "command": "selectNextSuggestion", 118 | "when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible" 119 | }, 120 | { 121 | "key": "shift+tab", 122 | "command": "selectPrevSuggestion", 123 | "when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible" 124 | }, 125 | 126 | // Unbind default keybindings 127 | { 128 | "key": "ctrl+h", 129 | "command": "-editor.action.startFindReplaceAction", 130 | "when": "editorFocus || editorIsOpen" 131 | } 132 | ] 133 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "vscode-neovim.compositeKeys": { 3 | "jk": { 4 | "command": "vscode-neovim.lua", 5 | "args": [ 6 | [ 7 | "local code = require('vscode')", 8 | "code.action('vscode-neovim.escape')" 9 | ] 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /after/ftplugin/eruby.lua: -------------------------------------------------------------------------------- 1 | -- Set 'indentexpr' to an empty string 2 | -- Disables automatic indentation in eruby files for custom indentation control 3 | vim.opt_local.indentexpr = '' 4 | -------------------------------------------------------------------------------- /after/ftplugin/gitcommit.lua: -------------------------------------------------------------------------------- 1 | vim.opt_local.colorcolumn = { '50', '72' } 2 | vim.opt_local.spell = true 3 | -------------------------------------------------------------------------------- /after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | vim.opt.expandtab = false 2 | vim.opt.shiftwidth = 4 3 | vim.opt.tabstop = 4 4 | -------------------------------------------------------------------------------- /after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | vim.opt.conceallevel = 2 2 | vim.opt.shiftwidth = 2 3 | vim.opt.tabstop = 2 4 | -------------------------------------------------------------------------------- /after/ftplugin/ruby.lua: -------------------------------------------------------------------------------- 1 | if not vim.g.vscode then 2 | vim.opt_local.colorcolumn = '80' 3 | end 4 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | -- _ _ _ _ 2 | -- (_)_ __ (_) |_ | |_ _ __ _ 3 | -- | | '_ \| | __| | | | | |/ _` | 4 | -- | | | | | | |_ _| | |_| | (_| | 5 | -- |_|_| |_|_|\__(_)_|\__,_|\__,_| 6 | 7 | require('core') 8 | require('lsp') 9 | 10 | -- VSCode only settings 11 | if vim.g.vscode then 12 | require('code') 13 | end 14 | -------------------------------------------------------------------------------- /lua/code/init.lua: -------------------------------------------------------------------------------- 1 | require('code.keybindings') 2 | -------------------------------------------------------------------------------- /lua/code/keybindings.lua: -------------------------------------------------------------------------------- 1 | local bind = vim.keymap.set 2 | 3 | vim.g.mapleader = ' ' 4 | 5 | -- Search 6 | bind('n', 'ff', 'call VSCodeNotify("workbench.action.quickOpen")') 7 | bind('n', 'fw', 'call VSCodeNotify("workbench.action.findInFiles")') 8 | 9 | -- Navigation 10 | bind('n', '', 'call VSCodeNotify("workbench.action.navigateDown")') 11 | bind('x', '', 'call VSCodeNotify("workbench.action.navigateDown")') 12 | bind('n', '', 'call VSCodeNotify("workbench.action.navigateUp")') 13 | bind('x', '', 'call VSCodeNotify("workbench.action.navigateUp")') 14 | bind('n', '', 'call VSCodeNotify("workbench.action.navigateLeft")') 15 | bind('x', '', 'call VSCodeNotify("workbench.action.navigateLeft")') 16 | bind('n', '', 'call VSCodeNotify("workbench.action.navigateRight")') 17 | bind('x', '', 'call VSCodeNotify("workbench.action.navigateRight")') 18 | 19 | -- Active editor 20 | bind('n', '', 'call VSCodeNotify("workbench.action.closeActiveEditor")') 21 | bind('n', '', 'call VSCodeNotify("workbench.action.nextEditor")') 22 | bind('n', '', 'call VSCodeNotify("workbench.action.previousEditor")') 23 | bind('n', '', 'call VSCodeNotify("workbench.action.moveEditorLeftInGroup")') 24 | bind('n', '', 'call VSCodeNotify("workbench.action.moveEditorRightInGroup")') 25 | 26 | -- Toggles 27 | bind('n', 'e', 'call VSCodeNotify("workbench.action.toggleSidebarVisibility")') 28 | 29 | -- Hover 30 | bind('n', 'K', 'call VSCodeNotify("editor.action.showHover")') 31 | bind('n', 'k', 'call VSCodeNotify("editor.action.showHover")') 32 | 33 | -- VSCode definitions/references 34 | bind('n', 'gd', 'call VSCodeNotify("editor.action.revealDefinition")') 35 | bind('n', 'gr', 'call VSCodeNotify("editor.action.goToReferences")') 36 | -------------------------------------------------------------------------------- /lua/code/lazy.lua: -------------------------------------------------------------------------------- 1 | -- Load plugins only when in VSCode by setting the `vscode` plugin field to `true`. 2 | -- When a plugin declares its own `cond` field, it will overwrite the default, 3 | -- which means VSCode needs to be explicitly excluded. 4 | local defaults = require('lazy.core.config').defaults 5 | 6 | defaults.defaults = { 7 | cond = function(plugin) 8 | return plugin.vscode 9 | end, 10 | } 11 | -------------------------------------------------------------------------------- /lua/core/init.lua: -------------------------------------------------------------------------------- 1 | -- Detect OS and set nvim home as global variable 2 | if vim.fn.has('unix') == 1 then 3 | vim.g['nvim_home'] = '~/.config/nvim' 4 | elseif vim.fn.has('win32') == 1 then 5 | vim.g['nvim_home'] = '~/AppData/Local/nvim' 6 | end 7 | 8 | require('core.keybindings') 9 | require('core.options') 10 | require('core.lazy') 11 | -------------------------------------------------------------------------------- /lua/core/keybindings.lua: -------------------------------------------------------------------------------- 1 | local bind = vim.keymap.set 2 | 3 | vim.g.mapleader = ' ' 4 | 5 | vim.opt.langmap = 'ΑA,ΒB,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ΝN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,' 6 | .. 'ΘU,ΩV,WW,ΧX,ΥY,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,πp,qq,ρr,' 7 | .. 'σs,τt,θu,ωv,ςw,χx,υy,ζz' 8 | 9 | -- Unbind Space 10 | bind({ 'n', 'v' }, '', '') 11 | 12 | -- Unbind 'K' 13 | bind('n', 'K', '') 14 | 15 | -- Exit insert mode 16 | bind('i', 'jk', '') 17 | bind('i', 'ξκ', '') 18 | 19 | -- Stay in indent mode after indenting text 20 | bind('v', '<', '', '>gv') 22 | 23 | -- Move text up and down 24 | bind('x', 'J', ":move '>+1gv") 25 | bind('x', 'K', ":move '<-2gv") 26 | 27 | -- Clear highlights and prints 28 | bind('n', 'n', 'nohecho ""') 29 | 30 | -- Copy path to clipboard 31 | bind('n', 'yf', 'lua vim.fn.setreg("+", vim.fn.expand("%:."))') 32 | bind('n', 'yl', 'lua vim.fn.setreg("+", vim.fn.expand("%:.") .. ":" .. vim.fn.line("."))') 33 | 34 | -- Base64 decode and format JSON 35 | bind('n', 'b64', '.!base64 -d | jq .') 36 | 37 | -- TUI/GUI NeoVim only settings 38 | if not vim.g.vscode then 39 | -- Resize with arrows 40 | bind('n', '', 'resize +2') 41 | bind('n', '', 'resize -2') 42 | bind('n', '', 'vertical resize -2') 43 | bind('n', '', 'vertical resize +2') 44 | 45 | -- Improve window navigation 46 | bind('n', '', 'h') 47 | bind('n', '', 'j') 48 | bind('n', '', 'k') 49 | bind('n', '', 'l') 50 | bind('t', '', '') 51 | bind('t', '', 'wincmd h') 52 | bind('t', '', 'wincmd j') 53 | bind('t', '', 'wincmd k') 54 | bind('t', '', 'wincmd l') 55 | 56 | -- Tab navigation 57 | bind('n', 'tt', '$tabnew') 58 | bind('n', 'tq', 'tabclose') 59 | bind('n', 'tn', 'tabnext') 60 | bind('n', 'tp', 'tabprev') 61 | 62 | -- Delete selection into void register before pasting 63 | bind('x', 'p', '"_dP') 64 | 65 | -- LSP 66 | bind('n', 'k', vim.diagnostic.open_float) 67 | bind('n', '[d', vim.diagnostic.goto_prev) 68 | bind('n', ']d', vim.diagnostic.goto_next) 69 | end 70 | -------------------------------------------------------------------------------- /lua/core/lazy.lua: -------------------------------------------------------------------------------- 1 | local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' 2 | 3 | if not vim.loop.fs_stat(lazypath) then 4 | vim.fn.system({ 5 | 'git', 6 | 'clone', 7 | '--filter=blob:none', 8 | 'https://github.com/folke/lazy.nvim.git', 9 | '--branch=stable', 10 | lazypath, 11 | }) 12 | end 13 | 14 | vim.opt.rtp:prepend(lazypath) 15 | 16 | if vim.g.vscode then 17 | require('code.lazy') 18 | end 19 | 20 | require('lazy').setup({ spec = { 21 | { import = 'plugins' }, 22 | { import = 'plugins.after' }, 23 | } }) 24 | 25 | vim.keymap.set('n', 'l', 'Lazy') 26 | -------------------------------------------------------------------------------- /lua/core/options.lua: -------------------------------------------------------------------------------- 1 | -- Make line numbers default 2 | vim.opt.number = true 3 | 4 | -- Enable mouse mode 5 | vim.opt.mouse = 'a' 6 | 7 | -- Don't show the mode, since it's already in status line 8 | vim.opt.showmode = false 9 | 10 | -- Sync clipboard between OS and Neovim 11 | vim.opt.clipboard = 'unnamedplus' 12 | 13 | -- Enable break indent 14 | vim.opt.breakindent = true 15 | 16 | -- Save undo history 17 | vim.opt.undofile = true 18 | 19 | -- Case-insensitive searching UNLESS \C or capital in search 20 | vim.opt.ignorecase = true 21 | vim.opt.smartcase = true 22 | 23 | -- Keep signcolumn on by default 24 | vim.opt.signcolumn = 'yes' 25 | 26 | -- Decrease update time 27 | vim.opt.updatetime = 250 28 | vim.opt.timeoutlen = 300 29 | 30 | -- Configure how new splits should be opened 31 | vim.opt.splitright = true 32 | vim.opt.splitbelow = true 33 | 34 | -- Sets how neovim will display certain whitespace in the editor 35 | vim.opt.list = true 36 | vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } 37 | 38 | -- Preview substitutions live 39 | vim.opt.inccommand = 'split' 40 | 41 | -- Show which line your cursor is on 42 | vim.opt.cursorline = true 43 | 44 | -- Minimal number of screen lines to keep above, below, left and right of the cursor 45 | vim.opt.scrolloff = 8 46 | vim.opt.sidescrolloff = 8 47 | 48 | -- Set highlight on search, but clear on pressing in normal mode 49 | vim.opt.hlsearch = true 50 | 51 | -- Allow cursor movement keys to wrap around lines and between lines 52 | -- Enhances navigation with arrow keys, h, l, backspace, and space 53 | vim.opt.whichwrap:append('<,>,[,],h,l') 54 | 55 | -- Treat hyphenated words as a single word for editing and navigation 56 | vim.opt.iskeyword:append({ '-' }) 57 | 58 | -- Convert tabs to spaces 59 | vim.opt.expandtab = true 60 | 61 | -- Set number of spaces for indentations and tabs 62 | vim.opt.shiftwidth = 2 63 | vim.opt.tabstop = 2 64 | 65 | -- Do not insert any text for a match until the user selects a match from the menu 66 | vim.opt.completeopt = { 'menuone', 'noselect', 'noinsert' } 67 | 68 | -- Disable line wrap 69 | vim.opt.wrap = false 70 | 71 | -- Enable true color support 72 | vim.opt.termguicolors = true 73 | 74 | -- Disable foldcolumn 75 | vim.opt.foldcolumn = '0' 76 | 77 | -- Start with all folds open 78 | vim.opt.foldlevel = 99 79 | vim.opt.foldlevelstart = 99 80 | 81 | -- Enable folding 82 | vim.opt.foldenable = true 83 | 84 | -- Use 'g' by default with :s/foo/bar 85 | vim.opt.gdefault = true 86 | 87 | -- Ignore swap file messages 88 | vim.opt.shortmess:append('A') 89 | 90 | -- Disable providers 91 | vim.g.loaded_ruby_provider = 0 92 | vim.g.loaded_node_provider = 0 93 | vim.g.loaded_perl_provider = 0 94 | vim.g.loaded_python3_provider = 0 95 | 96 | -- Clear highlighting for ColorColumn 97 | vim.cmd('highlight clear ColorColumn') 98 | 99 | -- Remove 'c', 'r', 'o' from 'formatoptions' for all file types 100 | -- Prevents automatic comment formatting in new lines 101 | vim.api.nvim_create_autocmd('FileType', { 102 | pattern = '*', 103 | callback = function() 104 | vim.opt.formatoptions:remove({ 'c', 'r', 'o' }) 105 | end, 106 | }) 107 | 108 | -- Highlight when yanking text 109 | vim.api.nvim_create_autocmd('TextYankPost', { 110 | desc = 'Highlight when yanking text', 111 | group = vim.api.nvim_create_augroup('highlight-yank', { clear = true }), 112 | callback = function() 113 | vim.highlight.on_yank({ timeout = 200 }) 114 | end, 115 | }) 116 | 117 | local general_group = vim.api.nvim_create_augroup('general', {}) 118 | 119 | vim.api.nvim_create_autocmd('FocusGained', { 120 | desc = 'Reload files from disk when we focus neovim', 121 | pattern = '*', 122 | command = 'silent! checktime', 123 | group = general_group, 124 | }) 125 | 126 | vim.api.nvim_create_autocmd('BufEnter', { 127 | desc = 'Every time we enter an unmodified buffer, check if it changed on disk', 128 | pattern = '*', 129 | command = "if &buftype == '' && !&modified | exec 'checktime ' . expand('') | endif", 130 | group = general_group, 131 | }) 132 | 133 | if vim.fn.executable('rg') == 1 then 134 | vim.o.grepprg = 'rg --vimgrep --no-heading --smart-case' 135 | vim.o.grepformat = '%f:%l:%c:%m,%f:%l:%m' 136 | end 137 | -------------------------------------------------------------------------------- /lua/core/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | ---@param on_attach fun(client:table, buffer:number) 4 | function M.on_attach(on_attach) 5 | vim.api.nvim_create_autocmd('LspAttach', { 6 | callback = function(args) 7 | local buffer = args.buf 8 | local client = vim.lsp.get_client_by_id(args.data.client_id) 9 | on_attach(client, buffer) 10 | end, 11 | }) 12 | end 13 | 14 | ---@param name string 15 | ---@param fn fun(name:string) 16 | function M.on_load(name, fn) 17 | local config = require('lazy.core.config') 18 | if config.plugins[name] and config.plugins[name]._.loaded then 19 | fn(name) 20 | else 21 | vim.api.nvim_create_autocmd('User', { 22 | pattern = 'LazyLoad', 23 | callback = function(event) 24 | if event.data == name then 25 | fn(name) 26 | return true 27 | end 28 | end, 29 | }) 30 | end 31 | end 32 | 33 | --- Merge extended options with a default table of options 34 | ---@param default? table The default table that you want to merge into 35 | ---@param opts? table The new options that should be merged with the default table 36 | ---@return table # The merged table 37 | function M.extend_tbl(default, opts) 38 | opts = opts or {} 39 | return default and vim.tbl_deep_extend('force', default, opts) or opts 40 | end 41 | 42 | return M 43 | -------------------------------------------------------------------------------- /lua/lsp/init.lua: -------------------------------------------------------------------------------- 1 | vim.diagnostic.config({ 2 | severity_sort = true, 3 | underline = { severity = vim.diagnostic.severity.ERROR }, 4 | float = { border = 'single', source = 'if_many' }, 5 | signs = vim.g.have_nerd_font and { 6 | text = { 7 | [vim.diagnostic.severity.ERROR] = '󰅚 ', 8 | [vim.diagnostic.severity.WARN] = '󰀪 ', 9 | [vim.diagnostic.severity.INFO] = '󰋽 ', 10 | [vim.diagnostic.severity.HINT] = '󰌶 ', 11 | }, 12 | } or {}, 13 | virtual_text = { 14 | source = 'if_many', 15 | spacing = 2, 16 | format = function(diagnostic) 17 | local diagnostic_message = { 18 | [vim.diagnostic.severity.ERROR] = diagnostic.message, 19 | [vim.diagnostic.severity.WARN] = diagnostic.message, 20 | [vim.diagnostic.severity.INFO] = diagnostic.message, 21 | [vim.diagnostic.severity.HINT] = diagnostic.message, 22 | } 23 | return diagnostic_message[diagnostic.severity] 24 | end, 25 | }, 26 | }) 27 | 28 | local open_floating_preview = vim.lsp.util.open_floating_preview 29 | function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) 30 | opts = opts or {} 31 | opts.border = opts.border or 'single' 32 | 33 | return open_floating_preview(contents, syntax, opts, ...) 34 | end 35 | 36 | vim.api.nvim_create_autocmd('LspAttach', { 37 | group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }), 38 | callback = function(event) 39 | local bind = function(keys, func, mode) 40 | mode = mode or 'n' 41 | vim.keymap.set(mode, keys, func, { buffer = event.buf }) 42 | end 43 | 44 | bind('gn', vim.lsp.buf.rename) 45 | bind('gca', vim.lsp.buf.code_action, { 'n', 'x' }) 46 | bind('gr', require('telescope.builtin').lsp_references) 47 | bind('gi', require('telescope.builtin').lsp_implementations) 48 | bind('gd', require('telescope.builtin').lsp_definitions) 49 | bind('gD', vim.lsp.buf.declaration) 50 | bind('gs', require('telescope.builtin').lsp_document_symbols) 51 | bind('gw', require('telescope.builtin').lsp_dynamic_workspace_symbols) 52 | bind('gt', require('telescope.builtin').lsp_type_definitions) 53 | bind('K', vim.lsp.buf.hover) 54 | bind('', vim.lsp.buf.signature_help, 'i') 55 | 56 | local function client_supports_method(client, method, bufnr) 57 | if vim.fn.has('nvim-0.11') == 1 then 58 | return client:supports_method(method, bufnr) 59 | else 60 | return client.supports_method(method, { bufnr = bufnr }) 61 | end 62 | end 63 | 64 | local client = vim.lsp.get_client_by_id(event.data.client_id) 65 | if 66 | client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) 67 | then 68 | local highlight_augroup = vim.api.nvim_create_augroup('lsp-highlight', { clear = false }) 69 | vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { 70 | buffer = event.buf, 71 | group = highlight_augroup, 72 | callback = vim.lsp.buf.document_highlight, 73 | }) 74 | 75 | vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { 76 | buffer = event.buf, 77 | group = highlight_augroup, 78 | callback = vim.lsp.buf.clear_references, 79 | }) 80 | 81 | vim.api.nvim_create_autocmd('LspDetach', { 82 | group = vim.api.nvim_create_augroup('lsp-detach', { clear = true }), 83 | callback = function(event2) 84 | vim.lsp.buf.clear_references() 85 | vim.api.nvim_clear_autocmds({ buffer = event2.buf }) 86 | end, 87 | }) 88 | end 89 | 90 | if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then 91 | bind('th', function() 92 | vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = event.buf })) 93 | end) 94 | end 95 | end, 96 | }) 97 | -------------------------------------------------------------------------------- /lua/plugins/after/aerial.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'stevearc/aerial.nvim', 4 | lazy = false, 5 | dependencies = { 6 | 'nvim-treesitter/nvim-treesitter', 7 | 'echasnovski/mini.icons', 8 | }, 9 | keys = { 10 | { '}', 'AerialPrev', mode = 'n' }, 11 | { '{', 'AerialNext', mode = 'n' }, 12 | { 'at', 'AerialToggle', mode = 'n' }, 13 | }, 14 | opts = { 15 | layout = { 16 | max_width = { 90, 0.5 }, 17 | default_direction = 'prefer_left', 18 | }, 19 | }, 20 | }, 21 | { 22 | 'nvim-telescope/telescope.nvim', 23 | optional = true, 24 | keys = { 25 | { 'fc', 'Telescope aerial', mode = 'n' }, 26 | opts = function() 27 | require('core.utils').on_load('telescope.nvim', function() 28 | require('telescope').load_extension('aerial') 29 | end) 30 | end, 31 | }, 32 | }, 33 | { 34 | 'nvim-lualine/lualine.nvim', 35 | optional = true, 36 | dependencies = 'stevearc/aerial.nvim', 37 | opts = function(_, opts) 38 | table.insert(opts.winbar.lualine_c, { 39 | 'aerial', 40 | sep = '  ', 41 | depth = 3, 42 | colored = true, 43 | color = { bg = require('ui.utils').colors.bg }, 44 | }) 45 | end, 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /lua/plugins/after/git-blame.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'f-person/git-blame.nvim', 4 | keys = { 5 | { 'gu', 'GitBlameOpenCommitURL', mode = 'n' }, 6 | }, 7 | config = function() 8 | vim.g.gitblame_display_virtual_text = 0 9 | vim.g.gitblame_date_format = '%r' 10 | vim.g.gitblame_schedule_event = 'CursorHold' 11 | end, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /lua/plugins/after/oil.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'stevearc/oil.nvim', 4 | lazy = false, 5 | dependencies = { 'echasnovski/mini.icons' }, 6 | keys = { 7 | { 'e', 'Oil' }, 8 | }, 9 | opts = { 10 | keymaps = { 11 | [''] = 'actions.parent', 12 | }, 13 | }, 14 | }, 15 | { 16 | 'nvim-lualine/lualine.nvim', 17 | optional = true, 18 | dependencies = 'stevearc/oil.nvim', 19 | opts = function(_, opts) 20 | table.insert(opts.winbar.lualine_c, { 21 | function() 22 | local filepath = require('oil').get_current_dir() 23 | local home = os.getenv('HOME') 24 | 25 | filepath = filepath:gsub('^' .. home, '~') 26 | filepath = filepath:gsub('/$', '') 27 | 28 | return filepath 29 | end, 30 | cond = function() 31 | return require('oil').get_current_dir() ~= nil 32 | end, 33 | color = { fg = require('ui.utils').colors.info }, 34 | }) 35 | end, 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /lua/plugins/alpha.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'goolord/alpha-nvim', 3 | dependencies = 'ibhagwan/fzf-lua', 4 | opts = function() 5 | local ascii = { 6 | ' ', 7 | ' ⢀⣀⣤⣤⣤⠤⢤⣤⣤⣤⣤⣄⣀⡀ ⢀⣠⣤⣄⡀ ⣀⣀⣀⣤⣤⣤⣤⣤⣤⣤⣤⣀⡀ ', 8 | ' ⢀⣤⠚⠩⠁⡄ ⠠⣤⠒⠒⣂ ⢈⣨⣭⣿⠛⠶⣦⣤⣄⡀ ⢠⣾⡟⠉⠉⠝⠿⠇ ⢀⣠⡤⠔⠒⣻⠟⠋⠩⠉⢁⣀⡀ ⣶ ⠙⡛⠷ ', 9 | ' ⠸⢟⡠⠒⢊⡤ ⠋⣠ ⠈⣉⣉⣉⣉⣀⣛⣿⡒⠭⡿⢿⣷⣤⣤⣀⣽⣇⣴⠆⣴⡃⢀⣠⣤⠴⣚⣫⡥ ⠒⠛⠁⣀⣉⣉⣙⢏⡉ ⢀⣼⣤⣜⠳⡦⠂ ', 10 | ' ⠐⠚⠫⣤⠖⢣⣤⡕ ⠉⣩⣤⠔ ⠂⣋⣭⣥⣤⠴⠛⣛⠈⢩⣿⠿⠛⢉ ⡐⠞⠫⢍⠙⣓⠢⠴⣥⣍⣙⠛⢓⡢⢤⣬⠉⠅ ⣤⡜⢛⠻⠛⠉⠁ ', 11 | ' ⠘⢔⢎⣡⡔⠂⣠⡿⠁⠒⢛⡻⢛⣩⠅ ⠉ ⠚⣯⣄⢠⣿⢀⣾⠇ ⠓ ⠁⠂⠈⠍⠐⠈⡉⣿⠛⣛⠛⠉⣤⣰⣿⣿⡟⠛⠁ ', 12 | ' ⠙⠛⠐⠚⠋ ⠒⣲⡿⠇⣋ ⢺⡏⠈⣀ ⠉⠈ ⠙⢿⠟⢰⣖⡢ ⠂⠒⠚⠉ ', 13 | ' ⣴⠛⠅⢀⣾⠟⢃ ⢹⠃⠠⠁⠈⠩ ⢠⣿ ⣀⢹⣿⡷ ', 14 | ' ⢿⣤⢚⣫⠅ ⢸⠇ ⢚ ⢀ ⣸⡇ ⠉⣿⣿⠇ ', 15 | ' ⠈⠛⢻⣥⡚⠔⣠⢣⣄⡀ ⢸⡇ ⢘ ⠈ ⠠⠈ ⣀⣰⡿⣧⣄⠾⠋⠁ ', 16 | ' ⠈⠑⠁ ⠘⣿⡀⣈⣀ ⠈ ⠈⠙⠁ ', 17 | ' ⠘⣷⠁ ', 18 | ' ⠙⣤ ', 19 | ' ⠛⠂ ', 20 | ' ', 21 | } 22 | 23 | local dashboard = require('alpha.themes.dashboard') 24 | 25 | local header = { 26 | type = 'text', 27 | val = ascii, 28 | opts = { position = 'center' }, 29 | } 30 | 31 | local buttons = { 32 | type = 'group', 33 | val = { 34 | dashboard.button('f', ' Find File', 'FzfLua files'), 35 | dashboard.button('w', '󰺯 Find Word', 'FzfLua live_grep'), 36 | dashboard.button('r', '󰔠 Recent File', 'FzfLua oldfiles'), 37 | dashboard.button('u', ' Update Plugins', 'Lazy sync'), 38 | }, 39 | opts = { spacing = 1 }, 40 | } 41 | 42 | local dynamic_header_padding = vim.fn.max({ 1, vim.fn.floor(vim.fn.winheight(0) * 0.2) }) 43 | 44 | return { 45 | layout = { 46 | { type = 'padding', val = dynamic_header_padding }, 47 | header, 48 | { type = 'padding', val = 2 }, 49 | buttons, 50 | }, 51 | opts = {}, 52 | } 53 | end, 54 | config = function(_, opts) 55 | require('alpha').setup(opts) 56 | 57 | vim.api.nvim_create_autocmd('TabNewEntered', { 58 | desc = 'Open Alpha when creating a new tab', 59 | callback = function() 60 | vim.cmd('Alpha') 61 | end, 62 | }) 63 | end, 64 | } 65 | -------------------------------------------------------------------------------- /lua/plugins/arrow.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'otavioschwanck/arrow.nvim', 3 | opts = { 4 | mappings = { 5 | clear_all_items = 'c', 6 | }, 7 | show_icons = true, 8 | separate_save_and_remove = true, 9 | leader_key = ';', 10 | buffer_leader_key = 'm', 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /lua/plugins/blink-cmp.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'saghen/blink.cmp', 4 | lazy = false, 5 | version = 'v0.*', 6 | opts = { 7 | keymap = { preset = 'enter' }, 8 | fuzzy = { implementation = "lua" }, 9 | }, 10 | }, 11 | { 12 | 'EdenEast/nightfox.nvim', 13 | optional = true, 14 | opts = function(_, opts) 15 | return require('core.utils').extend_tbl(opts, { 16 | groups = { 17 | nightfox = { 18 | BlinkCmpMenu = { bg = 'palette.bg1' }, 19 | Pmenu = { bg = 'palette.bg1' }, 20 | BlinkCmpDoc = { bg = 'palette.bg1' }, 21 | NormalFloat = { bg = 'palette.bg1' }, 22 | }, 23 | }, 24 | }) 25 | end, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /lua/plugins/bufferline.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'akinsho/bufferline.nvim', 4 | lazy = false, 5 | dependencies = { 6 | 'echasnovski/mini.icons', 7 | }, 8 | keys = { 9 | { '', 'BufferLineTogglePin', mode = 'n' }, 10 | { 'go', 'BufferLinePick', mode = 'n' }, 11 | { '', 'BufferLineCyclePrev', mode = 'n' }, 12 | { '', 'BufferLineCycleNext', mode = 'n' }, 13 | { '', 'BufferLineMovePrev', mode = 'n' }, 14 | { '', 'BufferLineMoveNext', mode = 'n' }, 15 | }, 16 | opts = function(_, opts) 17 | local bufferline = require('bufferline') 18 | 19 | opts.options = { 20 | show_close_icon = false, 21 | show_buffer_close_icons = false, 22 | style_preset = { 23 | bufferline.style_preset.no_italic, 24 | }, 25 | indicator = { style = 'none' }, 26 | custom_filter = function(buf_number, _) 27 | if vim.fn.bufname(buf_number) ~= '' then 28 | return true 29 | end 30 | end, 31 | } 32 | end, 33 | }, 34 | { 35 | 'EdenEast/nightfox.nvim', 36 | optional = true, 37 | opts = function(_, opts) 38 | return require('core.utils').extend_tbl( 39 | opts, 40 | { groups = { nightfox = { BufferLineFill = { bg = 'palette.bg0' } } } } 41 | ) 42 | end, 43 | }, 44 | } 45 | -------------------------------------------------------------------------------- /lua/plugins/comment.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'numToStr/Comment.nvim', 3 | keys = { 4 | { '', 'gcc', mode = 'n', remap = true }, 5 | { '', 'gcc', mode = 'n', remap = true }, 6 | { '', 'gcgv', mode = 'v', remap = true }, 7 | { '', 'gcgv', mode = 'v', remap = true }, 8 | }, 9 | opts = {}, 10 | } 11 | -------------------------------------------------------------------------------- /lua/plugins/conform.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'stevearc/conform.nvim', 3 | lazy = true, 4 | cmd = 'ConformInfo', 5 | dependencies = 'mason.nvim', 6 | keys = { 7 | { 8 | "'f", 9 | function() 10 | require('conform').format({ async = true, lsp_fallback = true }) 11 | end, 12 | mode = 'n', 13 | }, 14 | }, 15 | opts = { 16 | formatters_by_ft = { 17 | lua = { 'stylua' }, 18 | javascript = { 'prettierd', 'prettier', stop_after_first = true }, 19 | javascriptreact = { 'prettierd', 'prettier', stop_after_first = true }, 20 | css = { 'prettierd', 'prettier', stop_after_first = true }, 21 | scss = { 'prettierd', 'prettier', stop_after_first = true }, 22 | markdown = { 'prettierd', 'prettier', stop_after_first = true }, 23 | ruby = { 'rubocop' }, 24 | typst = { 'typstfmt' }, 25 | }, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /lua/plugins/faster.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'pteroctopus/faster.nvim', 3 | keys = { 4 | { 'fd', 'FasterDisableAllFeatures', mode = 'n' }, 5 | { 'fe', 'FasterEnableAllFeatures', mode = 'n' }, 6 | }, 7 | opts = {}, 8 | } 9 | -------------------------------------------------------------------------------- /lua/plugins/fidget.lua: -------------------------------------------------------------------------------- 1 | return { 'j-hui/fidget.nvim', opts = {} } 2 | -------------------------------------------------------------------------------- /lua/plugins/fzf.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'ibhagwan/fzf-lua', 4 | keys = { 5 | { 'ff', 'FzfLua files', mode = 'n' }, 6 | { 'fr', 'FzfLua resume', mode = 'n' }, 7 | { 'fz', 'FzfLua', mode = 'n' }, 8 | }, 9 | opts = { 10 | winopts = { backdrop = 100 }, 11 | files = { previewer = false }, 12 | fzf_colors = true, 13 | fzf_opts = { ['--border'] = false }, 14 | }, 15 | }, 16 | { 17 | 'EdenEast/nightfox.nvim', 18 | optional = true, 19 | opts = function(_, opts) 20 | return require('core.utils').extend_tbl(opts, { 21 | groups = { 22 | nightfox = { 23 | FzfLuaBorder = { fg = 'palette.bg3' }, 24 | }, 25 | }, 26 | }) 27 | end, 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /lua/plugins/git-conflict.lua: -------------------------------------------------------------------------------- 1 | return { 'akinsho/git-conflict.nvim', opts = {} } 2 | -------------------------------------------------------------------------------- /lua/plugins/gitsigns.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'lewis6991/gitsigns.nvim', 3 | lazy = false, 4 | keys = { 5 | { 6 | 'gg', 7 | function() 8 | require('gitsigns').blame_line({ full = true }) 9 | end, 10 | mode = 'n', 11 | }, 12 | }, 13 | opts = {}, 14 | } 15 | -------------------------------------------------------------------------------- /lua/plugins/highlight-colors.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'brenoprata10/nvim-highlight-colors', 3 | opts = { 4 | render = 'virtual', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/hop.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'smoka7/hop.nvim', 3 | vscode = true, 4 | version = '*', 5 | keys = { 6 | { 7 | 's', 8 | function() 9 | require('hop').hint_char2() 10 | end, 11 | mode = { 'n', 'v' }, 12 | }, 13 | }, 14 | opts = {}, 15 | } 16 | -------------------------------------------------------------------------------- /lua/plugins/indent-blankline.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'lukas-reineke/indent-blankline.nvim', 3 | main = 'ibl', 4 | event = { 'BufReadPre', 'BufNewFile' }, 5 | opts = { scope = { enabled = false } }, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/lsp.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'neovim/nvim-lspconfig', 3 | dependencies = { 4 | 'saghen/blink.cmp', 5 | }, 6 | config = function() 7 | local capabilities = require('blink.cmp').get_lsp_capabilities() 8 | local server_configurations = { 9 | lua_ls = { 10 | settings = { 11 | Lua = { 12 | diagnostics = { 13 | globals = { 'vim' }, 14 | }, 15 | }, 16 | }, 17 | }, 18 | } 19 | 20 | local servers = vim.tbl_keys(server_configurations or {}) 21 | vim.list_extend(servers, { 'stylua' }) 22 | 23 | for _, server in ipairs(servers) do 24 | local server_configuration = server_configurations[server] or {} 25 | server_configuration.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) 26 | 27 | vim.lsp.enable(server) 28 | vim.lsp.config(server, server_configuration) 29 | end 30 | end, 31 | } 32 | -------------------------------------------------------------------------------- /lua/plugins/lualine.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvim-lualine/lualine.nvim', 3 | opts = function() 4 | local utils = require('ui.utils') 5 | 6 | return { 7 | options = { 8 | globalstatus = true, 9 | }, 10 | winbar = { 11 | lualine_a = {}, 12 | lualine_b = {}, 13 | lualine_c = {}, 14 | lualine_x = {}, 15 | lualine_y = {}, 16 | lualine_z = {}, 17 | }, 18 | sections = { 19 | lualine_a = { 20 | { 21 | function() 22 | return '%z{}' 23 | end, 24 | separator = { right = utils.separators.right }, 25 | color = { bg = utils.colors.success }, 26 | padding = { right = 0 }, 27 | }, 28 | { 29 | function() 30 | return '%z{}' 31 | end, 32 | separator = { right = utils.separators.right }, 33 | color = { bg = utils.colors.warning }, 34 | padding = { right = 0 }, 35 | }, 36 | { 37 | function() 38 | return '%z{}' 39 | end, 40 | separator = { right = utils.separators.right }, 41 | color = { bg = utils.colors.error }, 42 | padding = { right = 0 }, 43 | }, 44 | }, 45 | lualine_b = { 46 | { 47 | 'filetype', 48 | icon_only = true, 49 | separator = '', 50 | cond = utils.conditions.buffer_not_empty, 51 | color = { bg = utils.colors.bg }, 52 | padding = { left = 1, right = 0 }, 53 | }, 54 | { 55 | 'filename', 56 | path = 1, 57 | separator = { right = utils.separators.right }, 58 | cond = utils.conditions.buffer_not_empty, 59 | color = { bg = utils.colors.bg, fg = utils.colors.fg }, 60 | }, 61 | }, 62 | lualine_c = { 63 | { 64 | 'diagnostics', 65 | sources = { 'nvim_diagnostic' }, 66 | symbols = { error = ' ', warn = ' ', info = ' ' }, 67 | diagnostics_color = { 68 | color_error = { fg = utils.colors.error }, 69 | color_warn = { fg = utils.colors.warning }, 70 | color_info = { fg = utils.colors.info }, 71 | }, 72 | separator = { right = utils.separators.bar_small }, 73 | }, 74 | }, 75 | lualine_x = { 76 | { 77 | 'diff', 78 | symbols = { added = '+', modified = '~', removed = '-' }, 79 | diff_color = { 80 | added = { fg = utils.colors.success, gui = 'bold' }, 81 | modified = { fg = utils.colors.warning, gui = 'bold' }, 82 | removed = { fg = utils.colors.error, gui = 'bold' }, 83 | }, 84 | separator = { left = utils.separators.left }, 85 | color = { bg = utils.colors.bg }, 86 | }, 87 | }, 88 | lualine_y = { 89 | { 90 | function() 91 | return '%z{}' 92 | end, 93 | separator = { left = utils.separators.left }, 94 | color = { bg = utils.colors.error }, 95 | padding = { left = 0 }, 96 | }, 97 | { 98 | function() 99 | return '%z{}' 100 | end, 101 | separator = { left = utils.separators.left }, 102 | color = { bg = utils.colors.warning }, 103 | padding = { left = 0 }, 104 | }, 105 | { 106 | function() 107 | return '%z{}' 108 | end, 109 | separator = { left = utils.separators.left }, 110 | color = { bg = utils.colors.success }, 111 | padding = { left = 0 }, 112 | }, 113 | }, 114 | lualine_z = {}, 115 | }, 116 | } 117 | end, 118 | } 119 | -------------------------------------------------------------------------------- /lua/plugins/mini-bufremove.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'echasnovski/mini.bufremove', 3 | lazy = false, 4 | keys = { 5 | { 6 | '', 7 | function() 8 | local bd = require('mini.bufremove').delete 9 | 10 | if not vim.bo.modified then 11 | bd(0) 12 | return 13 | end 14 | 15 | local choice = vim.fn.confirm(('Save changes to %q?'):format(vim.fn.bufname()), '&Yes\n&No\n&Cancel') 16 | 17 | if choice == 1 then 18 | vim.cmd.write() 19 | bd(0) 20 | elseif choice == 2 then 21 | bd(0, true) 22 | end 23 | end, 24 | }, 25 | { 26 | '', 27 | function() 28 | require('mini.bufremove').delete(0, true) 29 | end, 30 | }, 31 | }, 32 | config = function() 33 | vim.keymap.del('n', 'd') 34 | vim.keymap.del('n', '') 35 | end, 36 | } 37 | -------------------------------------------------------------------------------- /lua/plugins/mini-icons.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'echasnovski/mini.icons', 3 | version = false, 4 | init = function() 5 | package.preload['nvim-web-devicons'] = function() 6 | require('mini.icons').mock_nvim_web_devicons() 7 | return package.loaded['nvim-web-devicons'] 8 | end 9 | end, 10 | opts = {}, 11 | } 12 | -------------------------------------------------------------------------------- /lua/plugins/mini-indentscope.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'echasnovski/mini.indentscope', 3 | event = { 'BufReadPre', 'BufNewFile' }, 4 | init = function() 5 | vim.api.nvim_create_autocmd('FileType', { 6 | pattern = { 'help', 'alpha', 'dashboard', 'terminal', 'lazy', 'mason' }, 7 | callback = function() 8 | vim.b.miniindentscope_disable = true 9 | end, 10 | }) 11 | end, 12 | opts = function() 13 | return { 14 | draw = { animation = require('mini.indentscope').gen_animation.none() }, 15 | options = { try_as_border = true }, 16 | symbol = '▏', 17 | } 18 | end, 19 | } 20 | -------------------------------------------------------------------------------- /lua/plugins/mini-pairs.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'echasnovski/mini.pairs', 3 | version = '*', 4 | opts = {}, 5 | } 6 | -------------------------------------------------------------------------------- /lua/plugins/mini-trailspace.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'echasnovski/mini.trailspace', 3 | lazy = false, 4 | version = '*', 5 | keys = { 6 | { 7 | 'tl', 8 | function() 9 | local MiniTrailspace = require('mini.trailspace') 10 | MiniTrailspace.trim() 11 | MiniTrailspace.trim_last_lines() 12 | end, 13 | mode = 'n', 14 | }, 15 | }, 16 | init = function() 17 | vim.api.nvim_create_autocmd('BufWritePost', { 18 | pattern = '*', 19 | callback = function() 20 | if vim.bo.filetype == 'oil' then 21 | return 22 | end 23 | 24 | local MiniTrailspace = require('mini.trailspace') 25 | MiniTrailspace.trim() 26 | MiniTrailspace.trim_last_lines() 27 | end, 28 | }) 29 | end, 30 | opts = {}, 31 | } 32 | -------------------------------------------------------------------------------- /lua/plugins/nightfox.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'EdenEast/nightfox.nvim', 3 | priority = 1000, 4 | opts = { 5 | options = { 6 | styles = { 7 | keywordds = 'bold', 8 | types = 'bold', 9 | }, 10 | }, 11 | palettes = { 12 | nightfox = { 13 | bg0 = '#1e2030', 14 | bg1 = '#24273a', 15 | bg2 = '#363a4f', 16 | bg3 = '#3e445e', 17 | bg4 = '#4c5373', 18 | sel0 = '#3e445e', 19 | }, 20 | }, 21 | groups = { 22 | nightfox = { 23 | ['@variable.member'] = { fg = 'palette.orange.bright' }, 24 | ['@module'] = { fg = 'palette.yellow.base' }, 25 | ['@property'] = { fg = 'palette.orange.bright' }, 26 | CursorLine = { bg = 'palette.bg2' }, 27 | StatusLine = { bg = 'palette.bg2' }, 28 | }, 29 | }, 30 | }, 31 | config = function(_, opts) 32 | require('nightfox').setup(opts) 33 | vim.cmd('colorscheme nightfox') 34 | end, 35 | } 36 | -------------------------------------------------------------------------------- /lua/plugins/nvim-lint.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'mfussenegger/nvim-lint', 3 | event = { 'BufReadPost', 'BufNewFile', 'BufWritePre' }, 4 | opts = { 5 | events = { 'BufWritePost', 'BufReadPost', 'InsertLeave' }, 6 | linters_by_ft = { 7 | css = { 'stylelint' }, 8 | scss = { 'stylelint' }, 9 | }, 10 | }, 11 | config = function(_, opts) 12 | require('lint').linters_by_ft = opts.linters_by_ft 13 | 14 | vim.api.nvim_create_autocmd(opts.events, { 15 | callback = function() 16 | require('lint').try_lint() 17 | end, 18 | }) 19 | end, 20 | } 21 | -------------------------------------------------------------------------------- /lua/plugins/obsidian.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'epwalsh/obsidian.nvim', 3 | lazy = false, 4 | cond = function() 5 | local obsidian_path = vim.fn.expand('~/Obsidian/nvim') 6 | local stat = vim.loop.fs_stat(obsidian_path) 7 | 8 | return stat and stat.type == 'directory' and not vim.g.vscode 9 | end, 10 | version = '*', 11 | event = { 12 | 'BufReadPre ~/Obsidian/**.md', 13 | 'BufNewFile ~/Obsidian/**.md', 14 | }, 15 | dependencies = { 16 | 'nvim-lua/plenary.nvim', 17 | }, 18 | init = function() 19 | vim.api.nvim_create_autocmd('BufNewFile', { 20 | pattern = vim.fn.expand('~') .. '/Obsidian/**.md', 21 | callback = function() 22 | local bufname = vim.api.nvim_buf_get_name(0) 23 | local dirname = vim.fn.fnamemodify(bufname, ':h') 24 | 25 | vim.fn.mkdir(dirname, 'p') 26 | vim.api.nvim_command('write') 27 | end, 28 | }) 29 | end, 30 | keys = { 31 | { 'oo', 'ObsidianToday', mode = 'n' }, 32 | { 'oy', 'ObsidianYesterday', mode = 'n' }, 33 | { 'os', 'ObsidianSearch', mode = 'n' }, 34 | { 'oq', 'ObsidianQuickSwitch', mode = 'n' }, 35 | { 'of', 'ObsidianFollowLink', mode = 'n' }, 36 | { 'ob', 'ObsidianBacklinks', mode = 'n' }, 37 | { 'od', 'ObsidianDailies', mode = 'n' }, 38 | { 'on', 'ObsidianNew', mode = 'n' }, 39 | }, 40 | opts = { 41 | workspaces = { 42 | { 43 | name = 'nvim', 44 | path = '~/Obsidian/nvim', 45 | }, 46 | }, 47 | daily_notes = { 48 | folder = 'Dailies', 49 | date_format = '%d-%m-%Y', 50 | }, 51 | ui = { 52 | enable = false, 53 | checkboxes = { 54 | [' '] = { char = '󰄰', hl_group = 'ObsidianTodo' }, 55 | ['x'] = { char = '󰄴', hl_group = 'ObsidianDone' }, 56 | }, 57 | }, 58 | note_id_func = function(title) 59 | return title 60 | end, 61 | follow_url_func = function(url) 62 | vim.fn.jobstart({ 'xdg-open', url }) 63 | end, 64 | disable_frontmatter = true, 65 | }, 66 | } 67 | -------------------------------------------------------------------------------- /lua/plugins/overseer.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'stevearc/overseer.nvim', 3 | keys = { 4 | { 'ot', 'OverseerToggle', mode = 'n' }, 5 | { 'or', 'OverseerRun', mode = 'n' }, 6 | { 'ok', 'OverseerQuickAction', mode = 'n' }, 7 | { 'oa', 'OverseerTaskAction', mode = 'n' }, 8 | }, 9 | opts = { 10 | templates = { 'builtin', 'bazel' }, 11 | default_neotest = { 12 | { 'on_complete_notify', on_change = true }, 13 | 'default', 14 | }, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /lua/plugins/plenary.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvim-lua/plenary.nvim', 3 | lazy = true, 4 | } 5 | -------------------------------------------------------------------------------- /lua/plugins/render-markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'MeanderingProgrammer/render-markdown.nvim', 3 | dependencies = { 4 | 'nvim-treesitter/nvim-treesitter', 5 | 'echasnovski/mini.icons', 6 | }, 7 | opts = { 8 | render_modes = { 'n', 'c', 'i', 'v', 'V', 't', 'no' }, 9 | heading = { 10 | sign = false, 11 | icons = {}, 12 | }, 13 | code = { language_border = '' }, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /lua/plugins/scope.lua: -------------------------------------------------------------------------------- 1 | return { 'tiagovla/scope.nvim', opts = {} } 2 | -------------------------------------------------------------------------------- /lua/plugins/scrollbar.lua: -------------------------------------------------------------------------------- 1 | return { 'petertriho/nvim-scrollbar', opts = {} } 2 | -------------------------------------------------------------------------------- /lua/plugins/telescope.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvim-telescope/telescope.nvim', 3 | cmd = 'Telescope', 4 | dependencies = { 5 | { 6 | 'nvim-telescope/telescope-live-grep-args.nvim', 7 | keys = { 8 | { 'fw', 'Telescope live_grep_args', mode = 'n' }, 9 | }, 10 | config = function() 11 | require('core.utils').on_load('telescope.nvim', function() 12 | local telescope = require('telescope') 13 | local lga_actions = require('telescope-live-grep-args.actions') 14 | local actions = require('telescope.actions') 15 | 16 | telescope.setup({ 17 | extensions = { 18 | live_grep_args = { 19 | auto_quoting = true, 20 | mappings = { 21 | i = { 22 | [''] = actions.close, 23 | [''] = actions.move_selection_previous, 24 | [''] = actions.move_selection_next, 25 | [''] = actions.cycle_history_next, 26 | [''] = actions.cycle_history_prev, 27 | [''] = lga_actions.quote_prompt({ postfix = ' --iglob ' }), 28 | [''] = lga_actions.quote_prompt({ postfix = " --iglob '!spec' --iglob " }), 29 | [''] = actions.to_fuzzy_refine, 30 | [''] = actions.send_to_qflist, 31 | }, 32 | }, 33 | }, 34 | }, 35 | }) 36 | 37 | telescope.load_extension('live_grep_args') 38 | end) 39 | end, 40 | }, 41 | { 42 | 'nvim-telescope/telescope-fzf-native.nvim', 43 | cond = vim.fn.executable('make') == 1 and not vim.g.vscode, 44 | build = 'make', 45 | config = function() 46 | require('core.utils').on_load('telescope.nvim', function() 47 | local telescope = require('telescope') 48 | telescope.setup({ 49 | extensions = { 50 | fzf = { 51 | fuzzy = true, 52 | override_generic_sorter = true, 53 | override_file_sorter = true, 54 | case_mode = 'smart_case', 55 | }, 56 | }, 57 | }) 58 | 59 | telescope.load_extension('fzf') 60 | end) 61 | end, 62 | }, 63 | 'echasnovski/mini.icons', 64 | }, 65 | keys = { 66 | { '?', 'Telescope keymaps', mode = 'n' }, 67 | { 'fp', 'Telescope pickers', mode = 'n' }, 68 | { 'fh', 'Telescope help_tags', mode = 'n' }, 69 | { 'fb', 'Telescope buffers', mode = 'n' }, 70 | { 71 | 'f/', 72 | function() 73 | require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown({ 74 | winblend = 10, 75 | previewer = false, 76 | })) 77 | end, 78 | mode = 'n', 79 | }, 80 | }, 81 | opts = function() 82 | local default = function(title) 83 | return { 84 | prompt_title = title, 85 | results_title = false, 86 | } 87 | end 88 | 89 | local dropdown = function(title, previewer) 90 | return { 91 | prompt_title = title, 92 | previewer = previewer or false, 93 | theme = 'dropdown', 94 | } 95 | end 96 | 97 | local actions = require('telescope.actions') 98 | 99 | return { 100 | defaults = { 101 | mappings = { 102 | i = { 103 | [''] = actions.close, 104 | [''] = actions.move_selection_previous, 105 | [''] = actions.move_selection_next, 106 | [''] = actions.cycle_history_next, 107 | [''] = actions.cycle_history_prev, 108 | }, 109 | }, 110 | prompt_prefix = '', 111 | selection_caret = '❯ ', 112 | layout_strategy = 'vertical', 113 | sorting_strategy = 'ascending', 114 | layout_config = { 115 | preview_cutoff = 25, 116 | mirror = true, 117 | prompt_position = 'top', 118 | }, 119 | cache_picker = { 120 | num_pickers = 10, 121 | }, 122 | }, 123 | pickers = { 124 | buffers = dropdown('Buffers'), 125 | find_files = dropdown('Files'), 126 | grep_string = default('Search'), 127 | live_grep = default('Grep'), 128 | commands = default('Commands'), 129 | help_tags = default('Help Tags'), 130 | keymaps = default('Keymaps'), 131 | pickers = default('Pickers'), 132 | }, 133 | } 134 | end, 135 | } 136 | -------------------------------------------------------------------------------- /lua/plugins/todo-comments.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'folke/todo-comments.nvim', 3 | event = 'BufEnter', 4 | opts = {}, 5 | } 6 | -------------------------------------------------------------------------------- /lua/plugins/toggleterm.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'akinsho/toggleterm.nvim', 3 | version = 'v2.*', 4 | opts = { 5 | open_mapping = [[]], 6 | size = 20, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /lua/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'nvim-treesitter/nvim-treesitter', 3 | vscode = true, 4 | build = ':TSUpdate', 5 | dependencies = { 6 | 'nvim-treesitter/playground', 7 | 'nvim-treesitter/nvim-treesitter-textobjects', 8 | { 9 | 'RRethy/nvim-treesitter-endwise', 10 | opts = { endwise = { enable = true } }, 11 | config = function(_, opts) 12 | require('nvim-treesitter.configs').setup(opts) 13 | end, 14 | }, 15 | { 16 | 'windwp/nvim-ts-autotag', 17 | event = 'InsertEnter', 18 | opts = {}, 19 | }, 20 | }, 21 | opts = { 22 | ensure_installed = { 23 | 'ruby', 24 | 'go', 25 | 'javascript', 26 | 'lua', 27 | 'vim', 28 | 'vimdoc', 29 | 'html', 30 | 'css', 31 | 'scss', 32 | 'markdown', 33 | 'markdown_inline', 34 | 'java', 35 | 'typescript', 36 | 'tsx', 37 | 'xml', 38 | 'sql', 39 | 'terraform', 40 | }, 41 | highlight = { 42 | enable = true, 43 | }, 44 | playground = { 45 | enable = false, 46 | }, 47 | incremental_selection = { 48 | enable = true, 49 | keymaps = { 50 | init_selection = '', 51 | node_incremental = '', 52 | }, 53 | }, 54 | textobjects = { 55 | select = { 56 | enable = true, 57 | lookahead = true, 58 | keymaps = { 59 | ['aa'] = '@parameter.outer', 60 | ['ia'] = '@parameter.inner', 61 | ['af'] = '@function.outer', 62 | ['if'] = '@function.inner', 63 | ['ab'] = '@block.outer', 64 | ['ib'] = '@block.inner', 65 | ['ac'] = '@class.outer', 66 | ['ic'] = '@class.inner', 67 | }, 68 | }, 69 | move = { 70 | enable = true, 71 | set_jumps = true, 72 | goto_next_start = { 73 | [']f'] = '@function.outer', 74 | [']b'] = '@block.outer', 75 | [']]'] = '@class.outer', 76 | }, 77 | goto_next_end = { 78 | [']F'] = '@function.outer', 79 | [']B'] = '@block.outer', 80 | [']['] = '@class.outer', 81 | }, 82 | goto_previous_start = { 83 | ['[f'] = '@function.outer', 84 | ['[b'] = '@block.outer', 85 | ['[['] = '@class.outer', 86 | }, 87 | goto_previous_end = { 88 | ['[F'] = '@function.outer', 89 | ['[B'] = '@block.outer', 90 | ['[]'] = '@class.outer', 91 | }, 92 | }, 93 | swap = { 94 | enable = true, 95 | swap_next = { 96 | ['a'] = '@parameter.inner', 97 | }, 98 | swap_previous = { 99 | ['A'] = '@parameter.inner', 100 | }, 101 | }, 102 | }, 103 | }, 104 | config = function(_, opts) 105 | require('nvim-treesitter.configs').setup(opts) 106 | end, 107 | } 108 | -------------------------------------------------------------------------------- /lua/plugins/trouble.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'folke/trouble.nvim', 3 | cmd = 'Trouble', 4 | keys = { 5 | { 'df', 'Trouble diagnostics toggle filter.buf=0' }, 6 | { 'dw', 'Trouble diagnostics toggle' }, 7 | }, 8 | opts = {}, 9 | } 10 | -------------------------------------------------------------------------------- /lua/plugins/ufo.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'kevinhwang91/nvim-ufo', 3 | event = 'BufEnter', 4 | dependencies = { 5 | 'kevinhwang91/promise-async', 6 | }, 7 | keys = { 8 | { 9 | 'zR', 10 | function() 11 | require('ufo').openAllFolds() 12 | end, 13 | mode = 'n', 14 | }, 15 | { 16 | 'zM', 17 | function() 18 | require('ufo').closeAllFolds() 19 | end, 20 | mode = 'n', 21 | }, 22 | }, 23 | opts = function() 24 | local virtual_text_handler = function(virtText, lnum, endLnum, width, truncate) 25 | local newVirtText = {} 26 | local suffix = (' 󱞦 %d '):format(endLnum - lnum) 27 | local sufWidth = vim.fn.strdisplaywidth(suffix) 28 | local targetWidth = width - sufWidth 29 | local curWidth = 0 30 | 31 | for _, chunk in ipairs(virtText) do 32 | local chunkText = chunk[1] 33 | local chunkWidth = vim.fn.strdisplaywidth(chunkText) 34 | 35 | if targetWidth > curWidth + chunkWidth then 36 | table.insert(newVirtText, chunk) 37 | else 38 | local hlGroup = chunk[2] 39 | 40 | chunkText = truncate(chunkText, targetWidth - curWidth) 41 | table.insert(newVirtText, { chunkText, hlGroup }) 42 | chunkWidth = vim.fn.strdisplaywidth(chunkText) 43 | 44 | if curWidth + chunkWidth < targetWidth then 45 | suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth) 46 | end 47 | 48 | break 49 | end 50 | 51 | curWidth = curWidth + chunkWidth 52 | end 53 | 54 | table.insert(newVirtText, { suffix, 'MoreMsg' }) 55 | 56 | return newVirtText 57 | end 58 | 59 | return { 60 | fold_virt_text_handler = virtual_text_handler, 61 | } 62 | end, 63 | } 64 | -------------------------------------------------------------------------------- /lua/plugins/vgit.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'tanvirtin/vgit.nvim', 3 | keys = { 4 | { 5 | 'gk', 6 | function() 7 | require('vgit').hunk_up() 8 | end, 9 | mode = 'n', 10 | }, 11 | { 12 | 'gj', 13 | function() 14 | require('vgit').hunk_down() 15 | end, 16 | mode = 'n', 17 | }, 18 | { 19 | 'gh', 20 | function() 21 | require('vgit').buffer_history_preview() 22 | end, 23 | mode = 'n', 24 | }, 25 | { 26 | 'gs', 27 | function() 28 | require('vgit').buffer_diff_preview() 29 | end, 30 | mode = 'n', 31 | }, 32 | }, 33 | opts = { 34 | settings = { 35 | live_blame = { 36 | enabled = false, 37 | }, 38 | authorship_code_lens = { 39 | enabled = false, 40 | }, 41 | scene = { 42 | diff_preference = 'split', 43 | }, 44 | }, 45 | }, 46 | } 47 | -------------------------------------------------------------------------------- /lua/plugins/vimtex.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'lervag/vimtex', 3 | event = { 4 | 'BufReadPre **.tex', 5 | 'BufNewFile **.tex', 6 | }, 7 | keys = { 8 | { 'lc', 'VimtexCompile', mode = 'n' }, 9 | { 'lx', 'VimtexClean', mode = 'n' }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /lua/plugins/virt-column.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'lukas-reineke/virt-column.nvim', 3 | opts = { char = '▕' }, 4 | } 5 | -------------------------------------------------------------------------------- /lua/ui/utils.lua: -------------------------------------------------------------------------------- 1 | local function get_color(group, attr) 2 | return vim.fn.synIDattr(vim.fn.synIDtrans(vim.fn.hlID(group)), attr) 3 | end 4 | 5 | local M = {} 6 | 7 | M.separators = { 8 | vert = '┃', 9 | bar = '█', 10 | bar_small = '▊', 11 | dot = '●', 12 | left = '', 13 | right = '', 14 | left_small = '', 15 | right_small = '', 16 | slant_bottom_left = '', 17 | slant_bottom_right = '', 18 | slant_top_left = '', 19 | slant_top_right = '', 20 | } 21 | 22 | M.colors = { 23 | fg = get_color('Normal', 'fg'), 24 | bg = get_color('Normal', 'bg'), 25 | status_line_fg = get_color('StatusLine', 'fg'), 26 | status_line_bg = get_color('StatusLine', 'bg'), 27 | success = get_color('diffAdded', 'fg'), 28 | error = get_color('diffRemoved', 'fg'), 29 | warning = get_color('diffChanged', 'fg'), 30 | info = get_color('DiagnosticInfo', 'fg'), 31 | } 32 | 33 | M.conditions = { 34 | buffer_not_empty = function() 35 | return vim.fn.empty(vim.fn.expand('%:t')) ~= 1 36 | end, 37 | } 38 | 39 | return M 40 | --------------------------------------------------------------------------------