├── .gitignore ├── .stylua.toml ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── init.lua ├── install.sh ├── lua ├── config │ ├── autocmds.lua │ ├── icons.lua │ ├── init.lua │ ├── keymaps.lua │ ├── lazy.lua │ └── options.lua ├── pde │ ├── ai.lua │ ├── cpp.lua │ ├── docker.lua │ ├── elixir.lua │ ├── flutter.lua │ ├── html.lua │ ├── json.lua │ ├── jupyter.lua │ ├── kotlin.lua │ ├── lua.lua │ ├── markdown.lua │ ├── python.lua │ ├── ruby.lua │ ├── rust.lua │ ├── terraform.lua │ ├── typescript.lua │ └── yaml.lua ├── plugins │ ├── ai │ │ ├── backseat.lua │ │ ├── codegpt.lua │ │ └── neural.lua │ ├── bufferline.lua │ ├── codewindow.lua │ ├── colorful-winsep.lua │ ├── colorscheme │ │ ├── colors.lua │ │ └── init.lua │ ├── compiler-explorer.lua │ ├── completion │ │ ├── init.lua │ │ └── snippets │ │ │ ├── all.lua │ │ │ ├── lua.lua │ │ │ └── python.lua │ ├── dap │ │ └── init.lua │ ├── dashboard │ │ ├── init.lua │ │ └── logo.lua │ ├── db │ │ └── init.lua │ ├── dooku.lua │ ├── guess-indent.lua │ ├── hardtime.lua │ ├── hydra │ │ ├── file-action.lua │ │ ├── folder-action.lua │ │ ├── git-action.lua │ │ └── init.lua │ ├── init.lua │ ├── keyseer.lua │ ├── lsp │ │ ├── bun.lua │ │ ├── format.lua │ │ ├── init.lua │ │ ├── keymaps.lua │ │ ├── servers.lua │ │ └── utils.lua │ ├── mini │ │ ├── init.lua │ │ └── utils.lua │ ├── motion │ │ ├── init.lua │ │ └── utils.lua │ ├── navbuddy.lua │ ├── neogen.lua │ ├── neovim-project.lua │ ├── notes │ │ ├── init.lua │ │ ├── latex.lua │ │ ├── markdown.lua │ │ ├── norg.lua │ │ └── orgmode.lua │ ├── nvim-devdocs.lua │ ├── nvim-traveller.lua │ ├── nvim-tree.lua │ ├── nvim-ufo.lua │ ├── portal.lua │ ├── refactoring.lua │ ├── replacer.lua │ ├── rgflow.lua │ ├── satellite.lua │ ├── search │ │ └── init.lua │ ├── sniprun.lua │ ├── statusline │ │ ├── components.lua │ │ └── init.lua │ ├── telescope │ │ ├── init.lua │ │ └── pickers.lua │ ├── test │ │ └── init.lua │ ├── textobjs.lua │ ├── todo-comments.lua │ ├── toggleterm.lua │ ├── treesitter │ │ └── init.lua │ ├── ui │ │ ├── edgy.lua │ │ ├── editor.lua │ │ ├── hbac.lua │ │ ├── highlight.lua │ │ ├── noice.lua │ │ ├── nvim-early-retirement.lua │ │ ├── scope.lua │ │ └── screensaver.lua │ ├── vcs │ │ └── init.lua │ ├── whichkey.lua │ ├── wildfire.lua │ └── yanky.lua └── utils │ ├── ai │ ├── init.lua │ ├── openai_api.lua │ ├── test_ai.lua │ └── ui.lua │ ├── coding.lua │ ├── contextmenu.lua │ ├── init.lua │ ├── notepad.lua │ └── textobjects.lua ├── mnv.sh ├── rplugin └── python3 │ ├── openai_api.py │ ├── requirements.txt │ └── test_openai_api.py └── vim.toml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | __pycache__/ 43 | .luarc.json 44 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 160 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | no_call_parentheses = true 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest AS base 2 | 3 | RUN apk --no-cache add \ 4 | autoconf \ 5 | automake \ 6 | build-base \ 7 | cmake \ 8 | ninja \ 9 | coreutils \ 10 | curl \ 11 | gettext-tiny-dev \ 12 | git \ 13 | libtool \ 14 | pkgconf \ 15 | unzip \ 16 | stow \ 17 | npm 18 | 19 | # Build neovim (and use it as an example codebase 20 | RUN git clone https://github.com/neovim/neovim.git 21 | 22 | ARG VERSION=master 23 | RUN cd neovim && git checkout ${VERSION} && make CMAKE_BUILD_TYPE=RelWithDebInfo install 24 | 25 | # To support kickstart.nvim 26 | RUN apk --no-cache add \ 27 | fd \ 28 | ctags \ 29 | ripgrep \ 30 | git 31 | 32 | ENV work_dir="/workspace" 33 | ENV modern_neovim="$work_dir/modern-neovim" 34 | 35 | WORKDIR $work_dir 36 | 37 | COPY . ./ 38 | 39 | RUN mkdir -p "$modern_neovim/nvim" 40 | RUN cd $work_dir && stow --restow --target="$modern_neovim/nvim" . 41 | 42 | 43 | RUN mkdir -p "$modern_neovim/share" 44 | 45 | ENV XDG_DATA_HOME="$modern_neovim/share" 46 | ENV XDG_CACHE_HOME="$modern_neovim" 47 | ENV XDG_CONFIG_HOME="$modern_neovim" 48 | 49 | EXPOSE 6666 50 | CMD [ "nvim", "--headless", "--listen", "0.0.0.0:6666" ] 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 alpha2phi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modern Neovim 2 | 3 | Crafting a modernized development environment with Neovim. 4 | 5 | Check out the [Medium articles](https://alpha2phi.medium.com/). 6 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | nvim: 5 | build: . 6 | restart: always 7 | ports: 8 | - 6666:6666 9 | cap_add: 10 | - SYS_PTRACE 11 | security_opt: 12 | - seccomp:unconfined 13 | - apparmor:unconfined 14 | networks: 15 | - app_network 16 | container_name: nvim 17 | # Uncomment this to map the docker volume 18 | # volumes: 19 | # - ./workspace:/workspace 20 | 21 | networks: 22 | app_network: 23 | driver: bridge 24 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | require "config.options" 2 | require "config.lazy" 3 | 4 | if vim.fn.argc(-1) == 0 then 5 | vim.api.nvim_create_autocmd("User", { 6 | group = vim.api.nvim_create_augroup("ModernNeovim", { clear = true }), 7 | pattern = "VeryLazy", 8 | callback = function() 9 | require "config.autocmds" 10 | require "config.keymaps" 11 | require "utils.contextmenu" 12 | end, 13 | }) 14 | else 15 | require "config.autocmds" 16 | require "config.keymaps" 17 | require "utils.contextmenu" 18 | end 19 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MNV_APP_NAME=modern-neovim 4 | MNV_APP_CONFIG=~/.config/$MNV_APP_NAME 5 | export MNV_APP_NAME MNV_APP_CONFIG 6 | 7 | rm -rf $MNV_APP_CONFIG && mkdir -p $MNV_APP_CONFIG 8 | 9 | stow --restow --target=$MNV_APP_CONFIG . 10 | 11 | alias mnv="NVIM_APPNAME=$MNV_APP_NAME nvim" 12 | -------------------------------------------------------------------------------- /lua/config/autocmds.lua: -------------------------------------------------------------------------------- 1 | local function augroup(name) 2 | return vim.api.nvim_create_augroup("mnv_" .. name, { clear = true }) 3 | end 4 | 5 | -- See `:help vim.highlight.on_yank()` 6 | vim.api.nvim_create_autocmd("TextYankPost", { 7 | callback = function() 8 | vim.highlight.on_yank() 9 | end, 10 | group = augroup "highlight_yank", 11 | pattern = "*", 12 | }) 13 | 14 | -- Check if we need to reload the file when it changed 15 | vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, { 16 | group = augroup "checktime", 17 | command = "checktime", 18 | }) 19 | 20 | -- Go to last loction when opening a buffer 21 | vim.api.nvim_create_autocmd("BufReadPost", { 22 | group = augroup "last_loc", 23 | callback = function() 24 | local mark = vim.api.nvim_buf_get_mark(0, '"') 25 | local lcount = vim.api.nvim_buf_line_count(0) 26 | if mark[1] > 0 and mark[1] <= lcount then 27 | pcall(vim.api.nvim_win_set_cursor, 0, mark) 28 | end 29 | end, 30 | }) 31 | 32 | -- Auto toggle hlsearch 33 | local ns = vim.api.nvim_create_namespace "toggle_hlsearch" 34 | local function toggle_hlsearch(char) 35 | if vim.fn.mode() == "n" then 36 | local keys = { "", "n", "N", "*", "#", "?", "/" } 37 | local new_hlsearch = vim.tbl_contains(keys, vim.fn.keytrans(char)) 38 | 39 | if vim.opt.hlsearch:get() ~= new_hlsearch then 40 | vim.opt.hlsearch = new_hlsearch 41 | end 42 | end 43 | end 44 | vim.on_key(toggle_hlsearch, ns) 45 | 46 | -- windows to close 47 | vim.api.nvim_create_autocmd("FileType", { 48 | group = augroup "close_with_q", 49 | pattern = { 50 | "OverseerForm", 51 | "OverseerList", 52 | "checkhealth", 53 | "floggraph", 54 | "fugitive", 55 | "git", 56 | "help", 57 | "lspinfo", 58 | "man", 59 | "neotest-output", 60 | "neotest-summary", 61 | "qf", 62 | "query", 63 | "spectre_panel", 64 | "startuptime", 65 | "toggleterm", 66 | "tsplayground", 67 | "vim", 68 | "neoai-input", 69 | "neoai-output", 70 | "netrw", 71 | "notify", 72 | }, 73 | callback = function(event) 74 | vim.bo[event.buf].buflisted = false 75 | vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true }) 76 | end, 77 | }) 78 | 79 | vim.api.nvim_set_hl(0, "TerminalCursorShape", { underline = true }) 80 | vim.api.nvim_create_autocmd("TermEnter", { 81 | callback = function() 82 | vim.cmd [[setlocal winhighlight=TermCursor:TerminalCursorShape]] 83 | end, 84 | }) 85 | 86 | vim.api.nvim_create_autocmd("VimLeave", { 87 | callback = function() 88 | vim.cmd [[set guicursor=a:ver25]] 89 | end, 90 | }) 91 | 92 | -- -- show line diagnostics 93 | vim.api.nvim_create_autocmd("CursorHold", { 94 | callback = function() 95 | if require("plugins.lsp.utils").show_diagnostics() then 96 | vim.schedule(vim.diagnostic.open_float) 97 | end 98 | end, 99 | }) 100 | 101 | -- Auto create dir when saving a file, in case some intermediate directory does not exist 102 | vim.api.nvim_create_autocmd({ "BufWritePre" }, { 103 | group = augroup "auto_create_dir", 104 | callback = function(event) 105 | local file = vim.loop.fs_realpath(event.match) or event.match 106 | vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") 107 | end, 108 | }) 109 | 110 | -- wrap and check for spell in text filetypes 111 | vim.api.nvim_create_autocmd("FileType", { 112 | group = augroup "wrap_spell", 113 | pattern = { "gitcommit", "markdown" }, 114 | callback = function() 115 | vim.opt_local.wrap = true 116 | vim.opt_local.spell = true 117 | end, 118 | }) 119 | 120 | vim.api.nvim_create_autocmd({ "BufWinEnter" }, { 121 | group = augroup "auto_format_options", 122 | callback = function() 123 | vim.cmd "set formatoptions-=cro" 124 | end, 125 | }) 126 | 127 | -- start git messages in insert mode 128 | vim.api.nvim_create_autocmd("FileType", { 129 | group = augroup "buf_check", 130 | pattern = { "NeogitCommitMessage" }, 131 | command = "startinsert | 1", 132 | }) 133 | 134 | -- -- Start insert mode 135 | -- vim.api.nvim_create_autocmd({ "TermOpen" }, { 136 | -- group = augroup "auto_start_insert", 137 | -- callback = function(event) 138 | -- local bufnr = event.buf 139 | -- local hide = vim.api.nvim_get_option_value("bufhidden", { buf = bufnr }) 140 | -- local filetype = vim.api.nvim_get_option_value("filetype", { buf = bufnr }) 141 | -- if hide ~= "hide" and filetype ~= "harpoon" then 142 | -- vim.cmd.startinsert() 143 | -- end 144 | -- end, 145 | -- }) 146 | -------------------------------------------------------------------------------- /lua/config/icons.lua: -------------------------------------------------------------------------------- 1 | return { 2 | kind = { 3 | Array = " ", 4 | Boolean = " ", 5 | Class = " ", 6 | Color = " ", 7 | Constant = " ", 8 | Constructor = " ", 9 | Copilot = " ", 10 | Enum = " ", 11 | EnumMember = " ", 12 | Event = " ", 13 | Field = " ", 14 | File = " ", 15 | Folder = " ", 16 | Function = " ", 17 | Interface = " ", 18 | Key = " ", 19 | Keyword = " ", 20 | Method = " ", 21 | Module = " ", 22 | Namespace = " ", 23 | Null = " ", 24 | Number = " ", 25 | Object = " ", 26 | Operator = " ", 27 | Package = " ", 28 | Property = " ", 29 | Reference = " ", 30 | Snippet = " ", 31 | String = " ", 32 | Struct = " ", 33 | Text = " ", 34 | TypeParameter = " ", 35 | Unit = " ", 36 | Value = " ", 37 | Variable = " ", 38 | }, 39 | git = { 40 | LineAdded = "", 41 | LineModified = "", 42 | LineRemoved = "", 43 | FileDeleted = "", 44 | FileIgnored = "◌", 45 | FileRenamed = "", 46 | FileStaged = "S", 47 | FileUnmerged = "", 48 | FileUnstaged = "", 49 | FileUntracked = "U", 50 | Diff = "", 51 | Repo = "", 52 | Octoface = "", 53 | Branch = "", 54 | }, 55 | ui = { 56 | ArrowCircleDown = "", 57 | ArrowCircleLeft = "", 58 | ArrowCircleRight = "", 59 | ArrowCircleUp = "", 60 | BoldArrowDown = "", 61 | BoldArrowLeft = "", 62 | BoldArrowRight = "", 63 | BoldArrowUp = "", 64 | BoldClose = "", 65 | BoldDividerLeft = "", 66 | BoldDividerRight = "", 67 | BoldLineLeft = "▎", 68 | BookMark = "", 69 | BoxChecked = "", 70 | Bug = "", 71 | Stacks = "", 72 | Scopes = "", 73 | Watches = "", 74 | DebugConsole = "", 75 | Calendar = "", 76 | Check = "", 77 | ChevronRight = ">", 78 | ChevronShortDown = "", 79 | ChevronShortLeft = "", 80 | ChevronShortRight = "", 81 | ChevronShortUp = "", 82 | Circle = "", 83 | Close = "", 84 | CloudDownload = "", 85 | Code = "", 86 | Comment = "", 87 | Dashboard = "", 88 | DividerLeft = "", 89 | DividerRight = "", 90 | DoubleChevronRight = "»", 91 | Ellipsis = "", 92 | EmptyFolder = "", 93 | EmptyFolderOpen = "", 94 | File = "", 95 | FileSymlink = "", 96 | Files = "", 97 | FindFile = "", 98 | FindText = "", 99 | Fire = "", 100 | Folder = "", 101 | FolderOpen = "", 102 | FolderSymlink = "", 103 | Forward = "", 104 | Gear = "", 105 | History = "", 106 | Lightbulb = "", 107 | LineLeft = "▏", 108 | LineMiddle = "│", 109 | List = "", 110 | Lock = "", 111 | NewFile = "", 112 | Note = "", 113 | Package = "", 114 | Pencil = "", 115 | Plus = "", 116 | Project = "", 117 | Search = "", 118 | SignIn = "", 119 | SignOut = "", 120 | Tab = "", 121 | Table = "", 122 | Target = "", 123 | Telescope = "", 124 | Text = "", 125 | Tree = "", 126 | Triangle = "契", 127 | TriangleShortArrowDown = "", 128 | TriangleShortArrowLeft = "", 129 | TriangleShortArrowRight = "", 130 | TriangleShortArrowUp = "", 131 | }, 132 | diagnostics = { 133 | BoldError = "", 134 | Error = "", 135 | BoldWarning = "", 136 | Warning = "", 137 | BoldInformation = "", 138 | Information = "", 139 | BoldQuestion = "", 140 | Question = "", 141 | BoldHint = "", 142 | Hint = "", 143 | Debug = "", 144 | Trace = "✎", 145 | }, 146 | misc = { 147 | Robot = "ﮧ", 148 | Squirrel = "", 149 | Tag = "", 150 | Watch = "", 151 | Smiley = "", 152 | Package = "", 153 | CircuitBoard = "", 154 | }, 155 | dap = { 156 | Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" }, 157 | Breakpoint = " ", 158 | BreakpointCondition = " ", 159 | BreakpointRejected = { " ", "DiagnosticError" }, 160 | LogPoint = ".>", 161 | }, 162 | } 163 | -------------------------------------------------------------------------------- /lua/config/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | keymenu = { 3 | which_key = true, 4 | mini_clue = false, 5 | }, 6 | pde = { 7 | ai = true, 8 | angular = false, 9 | cpp = false, 10 | csharp = false, 11 | docker = true, 12 | elixir = false, 13 | flutter = false, 14 | go = false, 15 | html = true, 16 | java = false, 17 | json = true, 18 | julia = false, 19 | jupyter = false, 20 | lua = true, 21 | python = true, 22 | r = false, 23 | react = true, 24 | ruby = false, 25 | rust = true, 26 | solidity = false, 27 | svelte = false, 28 | tailwind = true, 29 | terraform = false, 30 | typescript = true, 31 | vuejs = false, 32 | yaml = true, 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /lua/config/keymaps.lua: -------------------------------------------------------------------------------- 1 | local keymap = vim.keymap.set 2 | 3 | -- Remap for dealing with word wrap 4 | keymap("n", "k", "v:count == 0 ? 'gk' : 'k'", { expr = true }) 5 | keymap("n", "j", "v:count == 0 ? 'gj' : 'j'", { expr = true }) 6 | 7 | -- Better viewing 8 | keymap("n", "n", "nzzzv") 9 | keymap("n", "N", "Nzzzv") 10 | keymap("n", "g,", "g,zvzz") 11 | keymap("n", "g;", "g;zvzz") 12 | 13 | -- Scrolling 14 | keymap("n", "", "zz") 15 | keymap("n", "", "zz") 16 | 17 | -- Paste 18 | -- keymap("n", "]p", "op", { desc = "Paste below" }) 19 | -- keymap("n", "]P", "Op", { desc = "Paste above" }) 20 | 21 | -- Better escape using jk in insert and terminal mode 22 | -- keymap("i", "jk", "") 23 | keymap("t", "", "") 24 | keymap("t", "", "h") 25 | keymap("t", "", "j") 26 | keymap("t", "", "k") 27 | keymap("t", "", "l") 28 | 29 | -- Add undo break-points 30 | keymap("i", ",", ",u") 31 | keymap("i", ".", ".u") 32 | keymap("i", ";", ";u") 33 | 34 | -- Better indent 35 | keymap("v", "<", "", ">gv") 37 | 38 | -- Paste over currently selected text without yanking it 39 | keymap("v", "p", '"_dp') 40 | 41 | -- Move Lines 42 | -- keymap("n", "", ":m .+1==") 43 | -- keymap("v", "", ":m '>+1gv=gv") 44 | -- keymap("i", "", ":m .+1==gi") 45 | -- keymap("n", "", ":m .-2==") 46 | -- keymap("v", "", ":m '<-2gv=gv") 47 | -- keymap("i", "", ":m .-2==gi") 48 | 49 | -- Resize window using arrow keys 50 | keymap("n", "", "resize +2") 51 | keymap("n", "", "resize -2") 52 | keymap("n", "", "vertical resize -2") 53 | keymap("n", "", "vertical resize +2") 54 | 55 | -- Insert blank line 56 | keymap("n", "]", "o") 57 | keymap("n", "[", "O") 58 | 59 | -- Auto indent 60 | keymap("n", "i", function() 61 | if #vim.fn.getline "." == 0 then 62 | return [["_cc]] 63 | else 64 | return "i" 65 | end 66 | end, { expr = true }) 67 | -------------------------------------------------------------------------------- /lua/config/lazy.lua: -------------------------------------------------------------------------------- 1 | --- Install lazy.nvim 2 | local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" 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 | vim.opt.rtp:prepend(lazypath) 14 | 15 | -- Configure lazy.nvim 16 | require("lazy").setup { 17 | spec = { 18 | { import = "plugins" }, 19 | { import = "plugins.ui" }, 20 | { import = "plugins.notes" }, 21 | { import = "plugins.ai" }, 22 | { import = "pde" }, 23 | }, 24 | defaults = { lazy = true, version = nil }, 25 | install = { missing = true, colorscheme = { "tokyonight", "gruvbox" } }, 26 | dev = { patterns = jit.os:find "Windows" and {} or { "alpha2phi" } }, 27 | checker = { enabled = true }, 28 | performance = { 29 | cache = { 30 | enabled = true, 31 | }, 32 | rtp = { 33 | disabled_plugins = { 34 | "gzip", 35 | "matchit", 36 | "matchparen", 37 | "tarPlugin", 38 | "tohtml", 39 | "tutor", 40 | "zipPlugin", 41 | -- "netrwPlugin", 42 | }, 43 | }, 44 | }, 45 | } 46 | vim.keymap.set("n", "zz", ":Lazy", { desc = "Manage Plugins" }) 47 | -------------------------------------------------------------------------------- /lua/config/options.lua: -------------------------------------------------------------------------------- 1 | local opt = vim.opt 2 | 3 | opt.autoindent = true 4 | opt.breakindent = true 5 | opt.clipboard = "unnamedplus" -- Access system clipboard 6 | opt.cmdheight = 0 7 | opt.completeopt = "menuone,noselect" 8 | opt.conceallevel = 0 9 | opt.confirm = true 10 | opt.cursorline = true 11 | opt.expandtab = true 12 | opt.fillchars = [[eob: ,fold: ,foldopen:,foldsep: ,foldclose:]] 13 | opt.foldcolumn = "1" -- '0' is not bad 14 | opt.foldenable = true 15 | opt.foldlevel = 99 -- Using ufo provider need a large value, feel free to decrease the value 16 | opt.foldlevelstart = 99 17 | opt.formatoptions = "jqlnt" -- tcqj 18 | opt.hidden = true 19 | opt.hlsearch = false 20 | opt.ignorecase = true 21 | opt.inccommand = "nosplit" 22 | opt.joinspaces = false 23 | opt.laststatus = 3 24 | opt.list = true 25 | opt.mouse = "a" 26 | opt.number = true 27 | opt.pumblend = 10 28 | opt.pumheight = 10 29 | opt.relativenumber = true 30 | opt.scrollback = 100000 31 | opt.scrolloff = 8 32 | opt.sessionoptions = { "buffers", "curdir", "tabpages", "winsize" } 33 | opt.shiftround = true 34 | opt.shiftwidth = 2 35 | opt.shortmess:append { W = true, I = true, c = true, C = true } 36 | opt.showcmd = false 37 | opt.showmode = false 38 | opt.sidescrolloff = 8 39 | opt.signcolumn = "yes" 40 | opt.smartcase = true 41 | opt.smartindent = true 42 | opt.splitbelow = true 43 | opt.splitkeep = "screen" 44 | opt.splitright = true 45 | opt.tabstop = 2 46 | opt.termguicolors = true 47 | opt.timeoutlen = 300 48 | opt.title = true 49 | opt.undofile = true 50 | opt.updatetime = 200 51 | opt.wildmode = "longest:full,full" 52 | 53 | vim.g.mapleader = " " 54 | vim.g.maplocalleader = "," 55 | 56 | vim.g.markdown_recommended_style = 0 57 | 58 | vim.keymap.set({ "n", "v" }, "", "", { silent = true }) 59 | -------------------------------------------------------------------------------- /lua/pde/ai.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.ai then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "zbirenbaum/copilot.lua", 8 | enabled = false, 9 | cmd = "Copilot", 10 | build = ":Copilot auth", 11 | opts = { 12 | filetypes = { 13 | markdown = true, 14 | help = true, 15 | }, 16 | }, 17 | }, 18 | { 19 | "nvim-lualine/lualine.nvim", 20 | optional = true, 21 | event = "VeryLazy", 22 | opts = function(_, opts) 23 | local Utils = require "utils" 24 | local colors = { 25 | [""] = Utils.fg "Special", 26 | ["Normal"] = Utils.fg "Special", 27 | ["Warning"] = Utils.fg "DiagnosticError", 28 | ["InProgress"] = Utils.fg "DiagnosticWarn", 29 | } 30 | table.insert(opts.sections.lualine_x, 2, { 31 | function() 32 | local icon = require("config.icons").icons.kinds.Copilot 33 | local status = require("copilot.api").status.data 34 | return icon .. (status.message or "") 35 | end, 36 | cond = function() 37 | local ok, clients = pcall(vim.lsp.get_active_clients, { name = "copilot", bufnr = 0 }) 38 | return ok and #clients > 0 39 | end, 40 | color = function() 41 | if not package.loaded["copilot"] then 42 | return 43 | end 44 | local status = require("copilot.api").status.data 45 | return colors[status.status] or colors[""] 46 | end, 47 | }) 48 | end, 49 | }, 50 | { 51 | "Exafunction/codeium.vim", 52 | event = "InsertEnter", 53 | enabled = true, 54 | -- stylua: ignore 55 | config = function () 56 | vim.g.codeium_disable_bindings = 1 57 | vim.keymap.set("i", "", function() return vim.fn["codeium#Accept"]() end, { expr = true }) 58 | vim.keymap.set("i", "", function() return vim.fn["codeium#CycleCompletions"](1) end, { expr = true }) 59 | vim.keymap.set("i", "", function() return vim.fn["codeium#CycleCompletions"](-1) end, { expr = true }) 60 | vim.keymap.set("i", "", function() return vim.fn["codeium#Clear"]() end, { expr = true }) 61 | vim.keymap.set("i", "", function() return vim.fn["codeium#Complete"]() end, { expr = true }) 62 | end, 63 | }, 64 | { 65 | "huggingface/hfcc.nvim", 66 | event = "InsertEnter", 67 | enabled = false, 68 | opts = { 69 | model = "bigcode/starcoder", 70 | }, 71 | }, 72 | { 73 | "codota/tabnine-nvim", 74 | enabled = false, 75 | build = "./dl_binaries.sh", 76 | event = "VeryLazy", 77 | config = function() 78 | require("tabnine").setup { 79 | disable_auto_comment = true, 80 | accept_keymap = "", 81 | dismiss_keymap = "", 82 | debounce_ms = 800, 83 | suggestion_color = { gui = "#808080", cterm = 244 }, 84 | exclude_filetypes = { "TelescopePrompt" }, 85 | } 86 | end, 87 | }, 88 | { 89 | "mthbernardes/codeexplain.nvim", 90 | enabled = false, 91 | cmd = "CodeExplain", 92 | build = function() 93 | vim.cmd [[silent UpdateRemotePlugins]] 94 | end, 95 | }, 96 | { 97 | "jackMort/ChatGPT.nvim", 98 | cmd = { "ChatGPT", "ChatGPTRun", "ChatGPTActAs", "ChatGPTCompleteCode", "ChatGPTEditWithInstructions" }, 99 | keys = { 100 | { "aa", "ChatGPT", desc = "Chat" }, 101 | { "ac", "ChatGPTRun complete_code", mode = { "n", "v" }, desc = "Complete Code" }, 102 | { "ae", "ChatGPTEditWithInstructions", mode = { "n", "v" }, desc = "Edit with Instructions" }, 103 | }, 104 | opts = {}, 105 | dependencies = { 106 | "MunifTanjim/nui.nvim", 107 | "nvim-lua/plenary.nvim", 108 | "nvim-telescope/telescope.nvim", 109 | }, 110 | }, 111 | { 112 | "Bryley/neoai.nvim", 113 | dependencies = { 114 | "MunifTanjim/nui.nvim", 115 | }, 116 | cmd = { 117 | "NeoAI", 118 | "NeoAIOpen", 119 | "NeoAIClose", 120 | "NeoAIToggle", 121 | "NeoAIContext", 122 | "NeoAIContextOpen", 123 | "NeoAIContextClose", 124 | "NeoAIInject", 125 | "NeoAIInjectCode", 126 | "NeoAIInjectContext", 127 | "NeoAIInjectContextCode", 128 | "NeoAIShortcut", 129 | }, 130 | keys = { 131 | { "as", desc = "Summarize Text" }, 132 | { "ag", desc = "Generate Git Message" }, 133 | }, 134 | opts = {}, 135 | config = function() 136 | require("neoai").setup { 137 | -- Options go here 138 | } 139 | end, 140 | }, 141 | { 142 | "sourcegraph/sg.nvim", 143 | enabled = false, 144 | event = "VeryLazy", 145 | opts = {}, 146 | dependencies = { "nvim-lua/plenary.nvim" }, 147 | }, 148 | { 149 | "piersolenski/wtf.nvim", 150 | dependencies = { 151 | "MunifTanjim/nui.nvim", 152 | }, 153 | opts = {}, 154 | --stylua: ignore 155 | keys = { 156 | { "sD", function() require("wtf").ai() end, desc = "Search Diagnostic with AI" }, 157 | { "sd", function() require("wtf").search() end, desc = "Search Diagnostic with Google" }, 158 | }, 159 | }, 160 | } 161 | -------------------------------------------------------------------------------- /lua/pde/cpp.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.cpp then 2 | return {} 3 | end 4 | 5 | local function get_codelldb() 6 | local mason_registry = require "mason-registry" 7 | local codelldb = mason_registry.get_package "codelldb" 8 | local extension_path = codelldb:get_install_path() .. "/extension/" 9 | local codelldb_path = extension_path .. "adapter/codelldb" 10 | local liblldb_path = extension_path .. "lldb/lib/liblldb.so" 11 | return codelldb_path, liblldb_path 12 | end 13 | 14 | return { 15 | { 16 | "nvim-treesitter/nvim-treesitter", 17 | opts = function(_, opts) 18 | vim.list_extend(opts.ensure_installed, { "c", "cpp" }) 19 | end, 20 | }, 21 | { 22 | "williamboman/mason.nvim", 23 | opts = function(_, opts) 24 | vim.list_extend(opts.ensure_installed, { "codelldb" }) 25 | end, 26 | }, 27 | { 28 | "neovim/nvim-lspconfig", 29 | dependencies = { "p00f/clangd_extensions.nvim" }, 30 | opts = { 31 | servers = { 32 | clangd = { 33 | server = { 34 | root_dir = function(...) 35 | -- using a root .clang-format or .clang-tidy file messes up projects, so remove them 36 | return require("lspconfig.util").root_pattern("compile_commands.json", "compile_flags.txt", "configure.ac", ".git")(...) 37 | end, 38 | capabilities = { 39 | offsetEncoding = { "utf-16" }, 40 | }, 41 | cmd = { 42 | "clangd", 43 | "--background-index", 44 | "--clang-tidy", 45 | "--header-insertion=iwyu", 46 | "--completion-style=detailed", 47 | "--function-arg-placeholders", 48 | "--fallback-style=llvm", 49 | }, 50 | init_options = { 51 | usePlaceholders = true, 52 | completeUnimported = true, 53 | clangdFileStatus = true, 54 | }, 55 | }, 56 | extensions = { 57 | inlay_hints = { 58 | inline = false, 59 | }, 60 | ast = { 61 | --These require codicons (https://github.com/microsoft/vscode-codicons) 62 | role_icons = { 63 | type = "", 64 | declaration = "", 65 | expression = "", 66 | specifier = "", 67 | statement = "", 68 | ["template argument"] = "", 69 | }, 70 | kind_icons = { 71 | Compound = "", 72 | Recovery = "", 73 | TranslationUnit = "", 74 | PackExpansion = "", 75 | TemplateTypeParm = "", 76 | TemplateTemplateParm = "", 77 | TemplateParamObject = "", 78 | }, 79 | }, 80 | }, 81 | }, 82 | }, 83 | setup = { 84 | clangd = function(_, opts) 85 | require("clangd_extensions").setup { 86 | server = opts.server, 87 | extensions = opts.extensions, 88 | } 89 | return true 90 | end, 91 | }, 92 | }, 93 | }, 94 | { 95 | "mfussenegger/nvim-dap", 96 | opts = { 97 | setup = { 98 | codelldb = function() 99 | local codelldb_path, _ = get_codelldb() 100 | local dap = require "dap" 101 | dap.adapters.codelldb = { 102 | type = "server", 103 | host = "localhost", 104 | port = "${port}", 105 | executable = { 106 | command = codelldb_path, 107 | args = { "--port", "${port}" }, 108 | 109 | -- On windows you may have to uncomment this: 110 | -- detached = false, 111 | }, 112 | } 113 | dap.configurations.cpp = { 114 | { 115 | name = "Launch file", 116 | type = "codelldb", 117 | request = "launch", 118 | program = function() 119 | return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file") 120 | end, 121 | cwd = "${workspaceFolder}", 122 | stopOnEntry = false, 123 | }, 124 | } 125 | 126 | dap.configurations.c = dap.configurations.cpp 127 | dap.configurations.rust = dap.configurations.cpp 128 | end, 129 | }, 130 | }, 131 | }, 132 | { 133 | "nvim-cmp", 134 | opts = function(_, opts) 135 | table.insert(opts.sorting.comparators, 1, require "clangd_extensions.cmp_scores") 136 | end, 137 | }, 138 | { 139 | "nvim-neotest/neotest", 140 | dependencies = { 141 | { "alfaix/neotest-gtest", opts = {} }, 142 | }, 143 | opts = function(_, opts) 144 | vim.list_extend(opts.adapters, { 145 | require "neotest-gtest", 146 | }) 147 | end, 148 | }, 149 | } 150 | -------------------------------------------------------------------------------- /lua/pde/docker.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.docker then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | if type(opts.ensure_installed) == "table" then 10 | vim.list_extend(opts.ensure_installed, { "dockerfile" }) 11 | end 12 | end, 13 | }, 14 | { 15 | "nvimtools/none-ls.nvim", 16 | opts = function(_, opts) 17 | local nls = require "null-ls" 18 | opts.sources = opts.sources or {} 19 | vim.list_extend(opts.sources, { 20 | nls.builtins.diagnostics.hadolint, 21 | }) 22 | end, 23 | dependencies = { 24 | "mason.nvim", 25 | opts = function(_, opts) 26 | opts.ensure_installed = opts.ensure_installed or {} 27 | vim.list_extend(opts.ensure_installed, { "hadolint" }) 28 | end, 29 | }, 30 | }, 31 | { 32 | "neovim/nvim-lspconfig", 33 | opts = { 34 | servers = { 35 | dockerls = {}, 36 | docker_compose_language_service = {}, 37 | }, 38 | }, 39 | }, 40 | { 41 | "telescope.nvim", 42 | dependencies = { 43 | { 44 | "lpoto/telescope-docker.nvim", 45 | opts = {}, 46 | config = function(_, opts) 47 | require("telescope").load_extension "docker" 48 | end, 49 | keys = { 50 | { "fd", "Telescope docker", desc = "Docker" }, 51 | }, 52 | }, 53 | }, 54 | }, 55 | } 56 | -------------------------------------------------------------------------------- /lua/pde/elixir.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.elixir then 2 | return {} 3 | end 4 | 5 | return {} 6 | -------------------------------------------------------------------------------- /lua/pde/flutter.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.flutter then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | vim.list_extend(opts.ensure_installed, { "dart" }) 10 | end, 11 | }, 12 | { 13 | "akinsho/flutter-tools.nvim", 14 | event = "VeryLazy", 15 | opts = function() 16 | return { 17 | -- ui = { border = as.ui.current.border }, 18 | debugger = { 19 | -- enabled = is_nightly, 20 | -- run_via_dap = is_nightly, 21 | exception_breakpoints = {}, 22 | }, 23 | outline = { auto_open = false }, 24 | decorations = { 25 | statusline = { device = true, app_version = true }, 26 | }, 27 | widget_guides = { enabled = true, debug = false }, 28 | -- dev_log = { enabled = not is_nightly, open_cmd = 'tabedit' }, 29 | lsp = { 30 | color = { 31 | enabled = true, 32 | background = true, 33 | virtual_text = false, 34 | }, 35 | settings = { 36 | showTodos = false, 37 | renameFilesWithClasses = "always", 38 | updateImportsOnRename = true, 39 | completeFunctionCalls = true, 40 | lineLength = 100, 41 | }, 42 | }, 43 | } 44 | end, 45 | dependencies = { 46 | { "RobertBrunhage/flutter-riverpod-snippets" }, 47 | }, 48 | }, 49 | { 50 | "nvim-neotest/neotest", 51 | dependencies = { 52 | { "sidlatau/neotest-dart" }, 53 | }, 54 | opts = function(_, opts) 55 | vim.list_extend(opts.adapters, { 56 | require "neotest-dart" { command = "flutter" }, 57 | }) 58 | end, 59 | }, 60 | } 61 | -------------------------------------------------------------------------------- /lua/pde/html.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.html then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | vim.list_extend(opts.ensure_installed, { "html", "css" }) 10 | end, 11 | }, 12 | { 13 | "williamboman/mason.nvim", 14 | opts = function(_, opts) 15 | vim.list_extend(opts.ensure_installed, { "prettierd" }) 16 | end, 17 | }, 18 | { 19 | "neovim/nvim-lspconfig", 20 | opts = { 21 | -- make sure mason installs the server 22 | servers = { 23 | -- html 24 | html = { 25 | filetypes = { "html", "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" }, 26 | }, 27 | -- Emmet 28 | emmet_ls = { 29 | init_options = { 30 | html = { 31 | options = { 32 | -- For possible options, see: https://github.com/emmetio/emmet/blob/master/src/config.ts#L79-L267 33 | ["bem.enabled"] = true, 34 | }, 35 | }, 36 | }, 37 | }, 38 | -- CSS 39 | cssls = {}, 40 | }, 41 | }, 42 | }, 43 | { 44 | "nvimtools/none-ls.nvim", 45 | opts = function(_, opts) 46 | local nls = require "null-ls" 47 | table.insert(opts.sources, nls.builtins.formatting.prettierd) 48 | end, 49 | }, 50 | { 51 | "uga-rosa/ccc.nvim", 52 | opts = {}, 53 | cmd = { "CccPick", "CccConvert", "CccHighlighterEnable", "CccHighlighterDisable", "CccHighlighterToggle" }, 54 | keys = { 55 | { "zC", desc = "+Color" }, 56 | { "zCp", "CccPick", desc = "Pick" }, 57 | { "zCc", "CccConvert", desc = "Convert" }, 58 | { "zCh", "CccHighlighterToggle", desc = "Toggle Highlighter" }, 59 | }, 60 | }, 61 | } 62 | -------------------------------------------------------------------------------- /lua/pde/json.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.json then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | if type(opts.ensure_installed) == "table" then 10 | vim.list_extend(opts.ensure_installed, { "json", "json5", "jsonc" }) 11 | end 12 | end, 13 | }, 14 | 15 | { 16 | "neovim/nvim-lspconfig", 17 | dependencies = { 18 | "b0o/SchemaStore.nvim", 19 | }, 20 | opts = { 21 | servers = { 22 | jsonls = { 23 | on_new_config = function(new_config) 24 | new_config.settings.json.schemas = new_config.settings.json.schemas or {} 25 | vim.list_extend(new_config.settings.json.schemas, require("schemastore").json.schemas()) 26 | end, 27 | settings = { 28 | json = { 29 | format = { 30 | enable = true, 31 | }, 32 | validate = { enable = true }, 33 | }, 34 | }, 35 | }, 36 | }, 37 | }, 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /lua/pde/kotlin.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.kotlin then 2 | return {} 3 | end 4 | -------------------------------------------------------------------------------- /lua/pde/lua.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.lua then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | vim.list_extend(opts.ensure_installed, { "lua", "luadoc", "luap" }) 10 | end, 11 | }, 12 | { 13 | "williamboman/mason.nvim", 14 | opts = function(_, opts) 15 | vim.list_extend(opts.ensure_installed, { "stylua" }) 16 | end, 17 | }, 18 | { 19 | "nvimtools/none-ls.nvim", 20 | opts = function(_, opts) 21 | local nls = require "null-ls" 22 | table.insert(opts.sources, nls.builtins.formatting.stylua) 23 | end, 24 | }, 25 | { 26 | "neovim/nvim-lspconfig", 27 | dependencies = { 28 | { 29 | "folke/neodev.nvim", 30 | opts = { 31 | library = { plugins = { "neotest", "nvim-dap-ui" }, types = true }, 32 | }, 33 | }, 34 | }, 35 | opts = { 36 | servers = { 37 | lua_ls = { 38 | settings = { 39 | Lua = { 40 | workspace = { 41 | checkThirdParty = false, 42 | }, 43 | completion = { callSnippet = "Replace" }, 44 | telemetry = { enable = false }, 45 | hint = { 46 | enable = false, 47 | }, 48 | }, 49 | }, 50 | }, 51 | }, 52 | setup = { 53 | lua_ls = function(_, _) 54 | local lsp_utils = require "plugins.lsp.utils" 55 | lsp_utils.on_attach(function(client, buffer) 56 | -- stylua: ignore 57 | if client.name == "lua_ls" then 58 | vim.keymap.set("n", "dX", function() require("osv").run_this() end, { buffer = buffer, desc = "OSV Run" }) 59 | vim.keymap.set("n", "dL", function() require("osv").launch({ port = 8086 }) end, { buffer = buffer, desc = "OSV Launch" }) 60 | end 61 | end) 62 | end, 63 | }, 64 | }, 65 | }, 66 | -- Debugging 67 | { 68 | "mfussenegger/nvim-dap", 69 | dependencies = { 70 | { "jbyuki/one-small-step-for-vimkind" }, 71 | }, 72 | opts = { 73 | setup = { 74 | osv = function(_, _) 75 | local dap = require "dap" 76 | dap.configurations.lua = { 77 | { 78 | type = "nlua", 79 | request = "attach", 80 | name = "Attach to running Neovim instance", 81 | host = function() 82 | local value = vim.fn.input "Host [127.0.0.1]: " 83 | if value ~= "" then 84 | return value 85 | end 86 | return "127.0.0.1" 87 | end, 88 | port = function() 89 | local val = tonumber(vim.fn.input("Port: ", "8086")) 90 | assert(val, "Please provide a port number") 91 | return val 92 | end, 93 | }, 94 | } 95 | 96 | dap.adapters.nlua = function(callback, config) 97 | callback { type = "server", host = config.host, port = config.port } 98 | end 99 | end, 100 | }, 101 | }, 102 | }, 103 | { 104 | "nvim-neotest/neotest", 105 | dependencies = { 106 | "nvim-neotest/neotest-plenary", 107 | }, 108 | opts = function(_, opts) 109 | vim.list_extend(opts.adapters, { 110 | require "neotest-plenary", 111 | }) 112 | end, 113 | }, 114 | } 115 | -------------------------------------------------------------------------------- /lua/pde/markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- correctly setup lspconfig 3 | { 4 | "neovim/nvim-lspconfig", 5 | opts = { 6 | -- make sure mason installs the server 7 | servers = { 8 | marksman = {}, 9 | -- zk = {}, 10 | }, 11 | }, 12 | }, 13 | { 14 | "Zeioth/markmap.nvim", 15 | build = "yarn global add markmap-cli", 16 | cmd = { "MarkmapOpen", "MarkmapSave", "MarkmapWatch", "MarkmapWatchStop" }, 17 | opts = { 18 | html_output = "/tmp/markmap.html", -- (default) Setting a empty string "" here means: [Current buffer path].html 19 | hide_toolbar = false, -- (default) 20 | grace_period = 3600000, -- (default) Stops markmap watch after 60 minutes. Set it to 0 to disable the grace_period. 21 | }, 22 | config = function(_, opts) 23 | require("markmap").setup(opts) 24 | end, 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /lua/pde/python.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.python then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | vim.list_extend(opts.ensure_installed, { "ninja", "python", "rst", "toml" }) 10 | end, 11 | }, 12 | { 13 | "nvimtools/none-ls.nvim", 14 | opts = function(_, opts) 15 | local nls = require "null-ls" 16 | table.insert(opts.sources, nls.builtins.formatting.black) 17 | end, 18 | }, 19 | { 20 | "williamboman/mason.nvim", 21 | opts = function(_, opts) 22 | vim.list_extend(opts.ensure_installed, { "debugpy", "black", "ruff" }) 23 | end, 24 | }, 25 | { 26 | "neovim/nvim-lspconfig", 27 | opts = { 28 | servers = { 29 | ruff_lsp = {}, 30 | pyright = { 31 | settings = { 32 | python = { 33 | analysis = { 34 | autoImportCompletions = true, 35 | typeCheckingMode = "off", 36 | autoSearchPaths = true, 37 | useLibraryCodeForTypes = true, 38 | diagnosticMode = "openFilesOnly", 39 | stubPath = vim.fn.stdpath "data" .. "/lazy/python-type-stubs/stubs", 40 | }, 41 | }, 42 | }, 43 | }, 44 | }, 45 | setup = { 46 | ruff_lsp = function() 47 | local lsp_utils = require "plugins.lsp.utils" 48 | lsp_utils.on_attach(function(client, _) 49 | if client.name == "ruff_lsp" then 50 | -- Disable hover in favor of Pyright 51 | client.server_capabilities.hoverProvider = false 52 | end 53 | end) 54 | end, 55 | pyright = function(_, _) 56 | local lsp_utils = require "plugins.lsp.utils" 57 | lsp_utils.on_attach(function(client, bufnr) 58 | local map = function(mode, lhs, rhs, desc) 59 | if desc then 60 | desc = desc 61 | end 62 | vim.keymap.set(mode, lhs, rhs, { silent = true, desc = desc, buffer = bufnr, noremap = true }) 63 | end 64 | -- stylua: ignore 65 | if client.name == "pyright" then 66 | map("n", "lo", "PyrightOrganizeImports", "Organize Imports" ) 67 | map("n", "lC", function() require("dap-python").test_class() end, "Debug Class" ) 68 | map("n", "lM", function() require("dap-python").test_method() end, "Debug Method" ) 69 | map("v", "lE", function() require("dap-python").debug_selection() end, "Debug Selection" ) 70 | end 71 | end) 72 | end, 73 | }, 74 | }, 75 | }, 76 | { 77 | "mfussenegger/nvim-dap", 78 | dependencies = { 79 | "mfussenegger/nvim-dap-python", 80 | config = function() 81 | local path = require("mason-registry").get_package("debugpy"):get_install_path() 82 | require("dap-python").setup(path .. "/venv/bin/python") 83 | end, 84 | }, 85 | }, 86 | { 87 | "nvim-neotest/neotest", 88 | dependencies = { 89 | "nvim-neotest/neotest-python", 90 | }, 91 | opts = function(_, opts) 92 | vim.list_extend(opts.adapters, { 93 | require "neotest-python" { 94 | dap = { justmycode = false }, 95 | runner = "unittest", 96 | }, 97 | }) 98 | end, 99 | }, 100 | { 101 | "microsoft/python-type-stubs", 102 | cond = false, 103 | }, 104 | { 105 | "linux-cultist/venv-selector.nvim", 106 | cmd = "VenvSelect", 107 | opts = {}, 108 | keys = { { "lv", ":VenvSelect", desc = "Select VirtualEnv" } }, 109 | }, 110 | } 111 | -------------------------------------------------------------------------------- /lua/pde/ruby.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.ruby then 2 | return {} 3 | end 4 | 5 | return {} 6 | -------------------------------------------------------------------------------- /lua/pde/rust.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.rust then 2 | return {} 3 | end 4 | 5 | local function get_codelldb() 6 | local mason_registry = require "mason-registry" 7 | local codelldb = mason_registry.get_package "codelldb" 8 | local extension_path = codelldb:get_install_path() .. "/extension/" 9 | local codelldb_path = extension_path .. "adapter/codelldb" 10 | local liblldb_path = "" 11 | if vim.loop.os_uname().sysname:find "Windows" then 12 | liblldb_path = extension_path .. "lldb\\bin\\liblldb.dll" 13 | elseif vim.fn.has "mac" == 1 then 14 | liblldb_path = extension_path .. "lldb/lib/liblldb.dylib" 15 | else 16 | liblldb_path = extension_path .. "lldb/lib/liblldb.so" 17 | end 18 | return codelldb_path, liblldb_path 19 | end 20 | 21 | return { 22 | { 23 | "nvim-treesitter/nvim-treesitter", 24 | opts = function(_, opts) 25 | vim.list_extend(opts.ensure_installed, { "ron", "rust", "toml" }) 26 | end, 27 | }, 28 | { 29 | "williamboman/mason.nvim", 30 | opts = function(_, opts) 31 | vim.list_extend(opts.ensure_installed, { "codelldb" }) 32 | end, 33 | }, 34 | { 35 | "neovim/nvim-lspconfig", 36 | dependencies = { "simrat39/rust-tools.nvim", "rust-lang/rust.vim" }, 37 | opts = { 38 | servers = { 39 | rust_analyzer = { 40 | settings = { 41 | ["rust-analyzer"] = { 42 | cargo = { 43 | allFeatures = true, 44 | loadOutDirsFromCheck = true, 45 | runBuildScripts = true, 46 | }, 47 | -- Add clippy lints for Rust. 48 | checkOnSave = { 49 | allFeatures = true, 50 | command = "clippy", 51 | extraArgs = { "--no-deps" }, 52 | }, 53 | procMacro = { 54 | enable = true, 55 | ignored = { 56 | ["async-trait"] = { "async_trait" }, 57 | ["napi-derive"] = { "napi" }, 58 | ["async-recursion"] = { "async_recursion" }, 59 | }, 60 | }, 61 | }, 62 | }, 63 | }, 64 | taplo = {}, 65 | }, 66 | setup = { 67 | rust_analyzer = function(_, opts) 68 | local codelldb_path, liblldb_path = get_codelldb() 69 | local lsp_utils = require "plugins.lsp.utils" 70 | lsp_utils.on_attach(function(client, bufnr) 71 | local map = function(mode, lhs, rhs, desc) 72 | if desc then 73 | desc = desc 74 | end 75 | vim.keymap.set(mode, lhs, rhs, { silent = true, desc = desc, buffer = bufnr, noremap = true }) 76 | end 77 | -- stylua: ignore 78 | if client.name == "rust_analyzer" then 79 | map("n", "le", "RustRunnables", "Runnables") 80 | map("n", "ll", function() vim.lsp.codelens.run() end, "Code Lens" ) 81 | map("n", "lt", "Cargo test", "Cargo test" ) 82 | map("n", "lR", "Cargo run", "Cargo run" ) 83 | end 84 | end) 85 | 86 | vim.api.nvim_create_autocmd({ "BufEnter" }, { 87 | pattern = { "Cargo.toml" }, 88 | callback = function(event) 89 | local bufnr = event.buf 90 | 91 | -- Register keymappings 92 | -- local wk = require "which-key" 93 | -- local keys = { mode = { "n", "v" }, ["lc"] = { name = "+Crates" } } 94 | -- wk.register(keys) 95 | 96 | local map = function(mode, lhs, rhs, desc) 97 | if desc then 98 | desc = desc 99 | end 100 | vim.keymap.set(mode, lhs, rhs, { silent = true, desc = desc, buffer = bufnr, noremap = true }) 101 | end 102 | map("n", "lc", function() end, "+Crates") 103 | map("n", "lcy", "lua require'crates'.open_repository()", "Open Repository") 104 | map("n", "lcp", "lua require'crates'.show_popup()", "Show Popup") 105 | map("n", "lci", "lua require'crates'.show_crate_popup()", "Show Info") 106 | map("n", "lcf", "lua require'crates'.show_features_popup()", "Show Features") 107 | map("n", "lcd", "lua require'crates'.show_dependencies_popup()", "Show Dependencies") 108 | end, 109 | }) 110 | 111 | require("rust-tools").setup { 112 | tools = { 113 | hover_actions = { border = "solid" }, 114 | on_initialized = function() 115 | vim.cmd [[ 116 | augroup RustLSP 117 | autocmd CursorHold *.rs silent! lua vim.lsp.buf.document_highlight() 118 | autocmd CursorMoved,InsertEnter *.rs silent! lua vim.lsp.buf.clear_references() 119 | autocmd BufEnter,CursorHold,InsertLeave *.rs silent! lua vim.lsp.codelens.refresh() 120 | augroup END 121 | ]] 122 | end, 123 | }, 124 | server = opts, 125 | dap = { 126 | adapter = require("rust-tools.dap").get_codelldb_adapter(codelldb_path, liblldb_path), 127 | }, 128 | } 129 | return true 130 | end, 131 | }, 132 | }, 133 | }, 134 | { 135 | "Saecki/crates.nvim", 136 | event = { "BufRead Cargo.toml" }, 137 | opts = { 138 | null_ls = { 139 | enabled = true, 140 | name = "crates.nvim", 141 | }, 142 | popup = { 143 | border = "rounded", 144 | }, 145 | }, 146 | config = function(_, opts) 147 | require("crates").setup(opts) 148 | end, 149 | }, 150 | { 151 | "hrsh7th/nvim-cmp", 152 | dependencies = { 153 | { 154 | "Saecki/crates.nvim", 155 | event = { "BufRead Cargo.toml" }, 156 | config = true, 157 | }, 158 | }, 159 | opts = function(_, opts) 160 | local cmp = require "cmp" 161 | opts.sources = cmp.config.sources(vim.list_extend(opts.sources, { 162 | { name = "crates" }, 163 | })) 164 | end, 165 | }, 166 | { 167 | "mfussenegger/nvim-dap", 168 | opts = { 169 | setup = { 170 | codelldb = function() 171 | local codelldb_path, _ = get_codelldb() 172 | local dap = require "dap" 173 | dap.adapters.codelldb = { 174 | type = "server", 175 | port = "${port}", 176 | executable = { 177 | command = codelldb_path, 178 | args = { "--port", "${port}" }, 179 | 180 | -- On windows you may have to uncomment this: 181 | -- detached = false, 182 | }, 183 | } 184 | dap.configurations.cpp = { 185 | { 186 | name = "Launch file", 187 | type = "codelldb", 188 | request = "launch", 189 | program = function() 190 | return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file") 191 | end, 192 | cwd = "${workspaceFolder}", 193 | stopOnEntry = false, 194 | }, 195 | } 196 | 197 | dap.configurations.c = dap.configurations.cpp 198 | dap.configurations.rust = dap.configurations.cpp 199 | end, 200 | }, 201 | }, 202 | }, 203 | { 204 | "nvim-neotest/neotest", 205 | dependencies = { 206 | "rouge8/neotest-rust", 207 | }, 208 | opts = function(_, opts) 209 | vim.list_extend(opts.adapters, { 210 | require "neotest-rust", 211 | }) 212 | end, 213 | }, 214 | } 215 | -------------------------------------------------------------------------------- /lua/pde/terraform.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.terraform then 2 | return {} 3 | end 4 | 5 | return {} 6 | -------------------------------------------------------------------------------- /lua/pde/typescript.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.typescript then 2 | return {} 3 | end 4 | 5 | return { 6 | { 7 | "nvim-treesitter/nvim-treesitter", 8 | opts = function(_, opts) 9 | vim.list_extend(opts.ensure_installed, { "javascript", "typescript", "tsx" }) 10 | end, 11 | }, 12 | { 13 | "williamboman/mason.nvim", 14 | opts = function(_, opts) 15 | vim.list_extend(opts.ensure_installed, { "typescript-language-server", "js-debug-adapter" }) 16 | end, 17 | }, 18 | { 19 | "pmizio/typescript-tools.nvim", 20 | dependencies = { "folke/neoconf.nvim", cmd = "Neoconf", config = true }, 21 | opts = { 22 | tsserver_file_preferences = { 23 | -- Inlay Hints 24 | includeInlayParameterNameHints = "all", 25 | includeInlayParameterNameHintsWhenArgumentMatchesName = true, 26 | includeInlayFunctionParameterTypeHints = true, 27 | includeInlayVariableTypeHints = true, 28 | includeInlayVariableTypeHintsWhenTypeMatchesName = true, 29 | includeInlayPropertyDeclarationTypeHints = true, 30 | includeInlayFunctionLikeReturnTypeHints = true, 31 | includeInlayEnumMemberValueHints = true, 32 | }, 33 | }, 34 | config = function(_, opts) 35 | require("plugins.lsp.utils").on_attach(function(client, bufnr) 36 | if client.name == "tsserver" then 37 | vim.keymap.set("n", "lo", "TSToolsOrganizeImports", { buffer = bufnr, desc = "Organize Imports" }) 38 | vim.keymap.set("n", "lO", "TSToolsSortImports", { buffer = bufnr, desc = "Sort Imports" }) 39 | vim.keymap.set("n", "lu", "TSToolsRemoveUnused", { buffer = bufnr, desc = "Removed Unused" }) 40 | vim.keymap.set("n", "lz", "TSToolsGoToSourceDefinition", { buffer = bufnr, desc = "Go To Source Definition" }) 41 | vim.keymap.set("n", "lR", "TSToolsRemoveUnusedImports", { buffer = bufnr, desc = "Removed Unused Imports" }) 42 | vim.keymap.set("n", "lF", "TSToolsFixAll", { buffer = bufnr, desc = "Fix All" }) 43 | vim.keymap.set("n", "lA", "TSToolsAddMissingImports", { buffer = bufnr, desc = "Add Missing Imports" }) 44 | end 45 | end) 46 | require("typescript-tools").setup(opts) 47 | end, 48 | }, 49 | { 50 | "neovim/nvim-lspconfig", 51 | dependencies = { "pmizio/typescript-tools.nvim" }, 52 | opts = { 53 | -- make sure mason installs the server 54 | servers = { 55 | -- ESLint 56 | eslint = { 57 | settings = { 58 | -- helps eslint find the eslintrc when it's placed in a subfolder instead of the cwd root 59 | workingDirectory = { mode = "auto" }, 60 | }, 61 | }, 62 | }, 63 | setup = { 64 | eslint = function() 65 | vim.api.nvim_create_autocmd("BufWritePre", { 66 | callback = function(event) 67 | local client = vim.lsp.get_active_clients({ bufnr = event.buf, name = "eslint" })[1] 68 | if client then 69 | local diag = vim.diagnostic.get(event.buf, { namespace = vim.lsp.diagnostic.get_namespace(client.id) }) 70 | if #diag > 0 then 71 | vim.cmd "EslintFixAll" 72 | end 73 | end 74 | end, 75 | }) 76 | end, 77 | }, 78 | }, 79 | }, 80 | { 81 | "mfussenegger/nvim-dap", 82 | opts = { 83 | setup = { 84 | vscode_js_debug = function() 85 | local function get_js_debug() 86 | local install_path = require("mason-registry").get_package("js-debug-adapter"):get_install_path() 87 | return install_path .. "/js-debug/src/dapDebugServer.js" 88 | end 89 | 90 | for _, adapter in ipairs { "pwa-node", "pwa-chrome", "pwa-msedge", "node-terminal", "pwa-extensionHost" } do 91 | require("dap").adapters[adapter] = { 92 | type = "server", 93 | host = "localhost", 94 | port = "${port}", 95 | executable = { 96 | command = "node", 97 | args = { 98 | get_js_debug(), 99 | "${port}", 100 | }, 101 | }, 102 | } 103 | end 104 | 105 | for _, language in ipairs { "typescript", "javascript" } do 106 | require("dap").configurations[language] = { 107 | { 108 | type = "pwa-node", 109 | request = "launch", 110 | name = "Launch file", 111 | program = "${file}", 112 | cwd = "${workspaceFolder}", 113 | }, 114 | { 115 | type = "pwa-node", 116 | request = "attach", 117 | name = "Attach", 118 | processId = require("dap.utils").pick_process, 119 | cwd = "${workspaceFolder}", 120 | }, 121 | { 122 | type = "pwa-node", 123 | request = "launch", 124 | name = "Debug Jest Tests", 125 | -- trace = true, -- include debugger info 126 | runtimeExecutable = "node", 127 | runtimeArgs = { 128 | "./node_modules/jest/bin/jest.js", 129 | "--runInBand", 130 | }, 131 | rootPath = "${workspaceFolder}", 132 | cwd = "${workspaceFolder}", 133 | console = "integratedTerminal", 134 | internalConsoleOptions = "neverOpen", 135 | }, 136 | { 137 | type = "pwa-chrome", 138 | name = "Attach - Remote Debugging", 139 | request = "attach", 140 | program = "${file}", 141 | cwd = vim.fn.getcwd(), 142 | sourceMaps = true, 143 | protocol = "inspector", 144 | port = 9222, -- Start Chrome google-chrome --remote-debugging-port=9222 145 | webRoot = "${workspaceFolder}", 146 | }, 147 | { 148 | type = "pwa-chrome", 149 | name = "Launch Chrome", 150 | request = "launch", 151 | url = "http://localhost:5173", -- This is for Vite. Change it to the framework you use 152 | webRoot = "${workspaceFolder}", 153 | userDataDir = "${workspaceFolder}/.vscode/vscode-chrome-debug-userdatadir", 154 | }, 155 | } 156 | end 157 | 158 | for _, language in ipairs { "typescriptreact", "javascriptreact" } do 159 | require("dap").configurations[language] = { 160 | { 161 | type = "pwa-chrome", 162 | name = "Attach - Remote Debugging", 163 | request = "attach", 164 | program = "${file}", 165 | cwd = vim.fn.getcwd(), 166 | sourceMaps = true, 167 | protocol = "inspector", 168 | port = 9222, -- Start Chrome google-chrome --remote-debugging-port=9222 169 | webRoot = "${workspaceFolder}", 170 | }, 171 | { 172 | type = "pwa-chrome", 173 | name = "Launch Chrome", 174 | request = "launch", 175 | url = "http://localhost:5173", -- This is for Vite. Change it to the framework you use 176 | webRoot = "${workspaceFolder}", 177 | userDataDir = "${workspaceFolder}/.vscode/vscode-chrome-debug-userdatadir", 178 | }, 179 | } 180 | end 181 | end, 182 | }, 183 | }, 184 | }, 185 | { 186 | "nvim-neotest/neotest", 187 | dependencies = { 188 | "nvim-neotest/neotest-jest", 189 | "marilari88/neotest-vitest", 190 | "thenbe/neotest-playwright", 191 | }, 192 | opts = function(_, opts) 193 | vim.list_extend(opts.adapters, { 194 | require "neotest-jest", 195 | require "neotest-vitest", 196 | require("neotest-playwright").adapter { 197 | options = { 198 | persist_project_selection = true, 199 | enable_dynamic_test_discovery = true, 200 | }, 201 | }, 202 | }) 203 | end, 204 | }, 205 | } 206 | -------------------------------------------------------------------------------- /lua/pde/yaml.lua: -------------------------------------------------------------------------------- 1 | if not require("config").pde.yaml then 2 | return {} 3 | end 4 | 5 | return { 6 | -- add yaml specific modules to treesitter 7 | { 8 | "nvim-treesitter/nvim-treesitter", 9 | opts = function(_, opts) 10 | if type(opts.ensure_installed) == "table" then 11 | vim.list_extend(opts.ensure_installed, { "yaml" }) 12 | end 13 | end, 14 | }, 15 | 16 | -- correctly setup lspconfig 17 | { 18 | "neovim/nvim-lspconfig", 19 | dependencies = { 20 | "b0o/SchemaStore.nvim", 21 | version = false, -- last release is way too old 22 | }, 23 | opts = { 24 | -- make sure mason installs the server 25 | servers = { 26 | yamlls = { 27 | -- lazy-load schemastore when needed 28 | on_new_config = function(new_config) 29 | new_config.settings.yaml.schemas = new_config.settings.yaml.schemas or {} 30 | vim.list_extend(new_config.settings.yaml.schemas, require("schemastore").yaml.schemas()) 31 | end, 32 | settings = { 33 | redhat = { telemetry = { enabled = false } }, 34 | yaml = { 35 | keyOrdering = false, 36 | format = { 37 | enable = true, 38 | }, 39 | validate = { enable = true }, 40 | schemaStore = { 41 | -- Must disable built-in schemaStore support to use 42 | -- schemas from SchemaStore.nvim plugin 43 | enable = false, 44 | -- Avoid TypeError: Cannot read properties of undefined (reading 'length') 45 | url = "", 46 | }, 47 | }, 48 | }, 49 | }, 50 | }, 51 | }, 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /lua/plugins/ai/backseat.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "james1236/backseat.nvim", 4 | cmd = { "Backseat", "BackseatAsk", "BackseatClear", "BackseatClearLine" }, 5 | config = true, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /lua/plugins/ai/codegpt.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "dpayne/CodeGPT.nvim", 4 | build = "pip install tiktoken", 5 | cmd = { "Chat" }, 6 | dependencies = { 7 | "nvim-lua/plenary.nvim", 8 | "MunifTanjim/nui.nvim", 9 | }, 10 | config = function() 11 | require "codegpt.config" 12 | end, 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /lua/plugins/ai/neural.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "dense-analysis/neural", 4 | enabled = false, 5 | dependencies = { 6 | "elpiloto/significant.nvim", 7 | }, 8 | cmd = { "Neural" }, 9 | opts = { 10 | source = { 11 | openai = { 12 | api_key = vim.env.OPENAI_API_KEY, 13 | }, 14 | }, 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /lua/plugins/bufferline.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "akinsho/nvim-bufferline.lua", 4 | event = "VeryLazy", 5 | opts = { 6 | options = { 7 | mode = "tabs", -- tabs or buffers 8 | numbers = "buffer_id", 9 | diagnostics = "nvim_lsp", 10 | always_show_bufferline = false, 11 | separator_style = "slant" or "padded_slant", 12 | show_tab_indicators = true, 13 | show_buffer_close_icons = false, 14 | show_close_icon = false, 15 | color_icons = true, 16 | enforce_regular_tabs = false, 17 | custom_filter = function(buf_number, _) 18 | local tab_num = 0 19 | for _ in pairs(vim.api.nvim_list_tabpages()) do 20 | tab_num = tab_num + 1 21 | end 22 | 23 | if tab_num > 1 then 24 | if not not vim.api.nvim_buf_get_name(buf_number):find(vim.fn.getcwd(), 0, true) then 25 | return true 26 | end 27 | else 28 | return true 29 | end 30 | end, 31 | -- sort_by = function(buffer_a, buffer_b) 32 | -- local mod_a = ((vim.loop.fs_stat(buffer_a.path) or {}).mtime or {}).sec or 0 33 | -- local mod_b = ((vim.loop.fs_stat(buffer_b.path) or {}).mtime or {}).sec or 0 34 | -- return mod_a > mod_b 35 | -- end, 36 | }, 37 | }, 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /lua/plugins/codewindow.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "gorbit99/codewindow.nvim", 3 | enabled = false, 4 | keys = { { "m", mode = { "n", "v" } } }, 5 | config = function() 6 | local codewindow = require "codewindow" 7 | codewindow.setup() 8 | codewindow.apply_default_keybinds() 9 | end, 10 | } 11 | -------------------------------------------------------------------------------- /lua/plugins/colorful-winsep.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-zh/colorful-winsep.nvim", 3 | enabled = false, 4 | config = true, 5 | event = { "WinNew" }, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/colorscheme/colors.lua: -------------------------------------------------------------------------------- 1 | return { 2 | white = "#c0caf5", 3 | darker_black = "#16161e", 4 | black = "#1a1b26", -- nvim bg 5 | black2 = "#1f2336", 6 | one_bg = "#24283b", 7 | one_bg2 = "#414868", 8 | one_bg3 = "#353b45", 9 | grey = "#40486a", 10 | grey_fg = "#565f89", 11 | grey_fg2 = "#4f5779", 12 | light_grey = "#545c7e", 13 | red = "#f7768e", 14 | baby_pink = "#DE8C92", 15 | pink = "#ff75a0", 16 | line = "#32333e", -- for lines like vertsplit 17 | green = "#9ece6a", 18 | vibrant_green = "#73daca", 19 | nord_blue = "#80a8fd", 20 | blue = "#7aa2f7", 21 | yellow = "#e0af68", 22 | sun = "#EBCB8B", 23 | purple = "#bb9af7", 24 | dark_purple = "#9d7cd8", 25 | teal = "#1abc9c", 26 | orange = "#ff9e64", 27 | cyan = "#7dcfff", 28 | statusline_bg = "#1d1e29", 29 | lightbg = "#32333e", 30 | pmenu_bg = "#7aa2f7", 31 | folder_bg = "#7aa2f7", 32 | } 33 | -------------------------------------------------------------------------------- /lua/plugins/colorscheme/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "folke/styler.nvim", 4 | enabled = false, 5 | event = "VeryLazy", 6 | opts = { 7 | themes = { 8 | markdown = { colorscheme = "tokyonight" }, 9 | help = { colorscheme = "tokyonight" }, 10 | }, 11 | }, 12 | }, 13 | { 14 | "folke/tokyonight.nvim", 15 | lazy = false, 16 | opts = { 17 | style = "moon", 18 | transparent = false, 19 | styles = { 20 | sidebars = "transparent", 21 | floats = "transparent", 22 | }, 23 | }, 24 | config = function(_, opts) 25 | local tokyonight = require "tokyonight" 26 | tokyonight.setup(opts) 27 | tokyonight.load() 28 | end, 29 | }, 30 | { 31 | "catppuccin/nvim", 32 | lazy = true, 33 | name = "catppuccin", 34 | opts = { 35 | integrations = { 36 | alpha = true, 37 | cmp = true, 38 | flash = true, 39 | gitsigns = true, 40 | illuminate = true, 41 | indent_blankline = { enabled = true }, 42 | lsp_trouble = true, 43 | mason = true, 44 | mini = true, 45 | native_lsp = { 46 | enabled = true, 47 | underlines = { 48 | errors = { "undercurl" }, 49 | hints = { "undercurl" }, 50 | warnings = { "undercurl" }, 51 | information = { "undercurl" }, 52 | }, 53 | }, 54 | navic = { enabled = true, custom_bg = "lualine" }, 55 | neotest = true, 56 | noice = true, 57 | notify = true, 58 | neotree = true, 59 | semantic_tokens = true, 60 | telescope = true, 61 | treesitter = true, 62 | which_key = true, 63 | }, 64 | }, 65 | }, 66 | { "rebelot/kanagawa.nvim", enabled = false, lazy = true, name = "kanagawa" }, 67 | { "sainnhe/gruvbox-material", enabled = false, lazy = true, name = "gruvbox-material" }, 68 | { 69 | "sainnhe/everforest", 70 | enabled = false, 71 | lazy = true, 72 | name = "everforest", 73 | config = function() 74 | vim.cmd.colorscheme "gruvbox-material" 75 | end, 76 | }, 77 | { 78 | "ellisonleao/gruvbox.nvim", 79 | enabled = false, 80 | lazy = true, 81 | config = function() 82 | require("gruvbox").setup() 83 | end, 84 | }, 85 | } 86 | -------------------------------------------------------------------------------- /lua/plugins/compiler-explorer.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "krady21/compiler-explorer.nvim", 3 | cmd = { "CECompile", "CECompileLive", "CEFormat", "CEAddLibrary", "CELoadExample", "CEOpenWebsite", "CEDeleteCache", "CEShowTooltip", "CEGotoLabel" }, 4 | opts = {}, 5 | } 6 | -------------------------------------------------------------------------------- /lua/plugins/completion/snippets/all.lua: -------------------------------------------------------------------------------- 1 | local ls = require "luasnip" 2 | local s = ls.snippet 3 | local f = ls.function_node 4 | local p = require("luasnip.extras").partial 5 | 6 | local snippets = { 7 | s({ trig = "$ymd", name = "Current date", dscr = "Insert the current date" }, { 8 | p(os.date, "%Y-%m-%d"), 9 | }), 10 | 11 | s( 12 | "$date", 13 | f(function() 14 | return os.date "%D - %H:%M" 15 | end) 16 | ), 17 | } 18 | 19 | return snippets 20 | -------------------------------------------------------------------------------- /lua/plugins/completion/snippets/lua.lua: -------------------------------------------------------------------------------- 1 | local ls = require "luasnip" 2 | local s = ls.snippet 3 | local i = ls.insert_node 4 | local fmt = require("luasnip.extras.fmt").fmt 5 | local l = require("luasnip.extras").lambda 6 | local t = ls.text_node 7 | 8 | local newline = function(text) 9 | return t { "", text } 10 | end 11 | 12 | local snippets = { 13 | ls.parser.parse_snippet("lm", "local M = {}\n\nfunction M.setup()\n $1 \nend\n\nreturn M"), 14 | ls.parser.parse_snippet("for", "for ${1:i} = ${2:1}, ${3:n} do\n\t$0\nend"), 15 | ls.parser.parse_snippet("fun", "local function ${1:name}($2)\n\t$0\nend"), 16 | ls.parser.parse_snippet("while", "while ${1:cond} do\n\t$0\nend"), 17 | ls.parser.parse_snippet("mfun", "function M.${1:name}($2)\n\t$0\nend"), 18 | ls.parser.parse_snippet("pairs", "for ${1:key}, ${2:value} in pairs($3) do\n\t$0\nend"), 19 | ls.parser.parse_snippet("ipairs", "for ${1:i}, ${2:value} in ipairs($3) do\n\t$0\nend"), 20 | ls.parser.parse_snippet("if", "if ${1:cond} then\n\t$0\nend"), 21 | ls.parser.parse_snippet("ifn", "if not ${1:cond} then\n\t$0\nend"), 22 | s( 23 | "localreq", 24 | fmt('local {} = require("{}")', { 25 | l(l._1:match("[^.]*$"):gsub("[^%a]+", "_"), 1), 26 | i(1, "module"), 27 | }) 28 | ), 29 | s( 30 | "preq", 31 | fmt('local {1}_ok, {1} = pcall(require, "{}")\nif not {1}_ok then return end', { 32 | l(l._1:match("[^.]*$"):gsub("[^%a]+", "_"), 1), 33 | i(1, "module"), 34 | }) 35 | ), 36 | 37 | ls.parser.parse_snippet("ign", "--stylua: ignore"), 38 | } 39 | 40 | return snippets 41 | -------------------------------------------------------------------------------- /lua/plugins/completion/snippets/python.lua: -------------------------------------------------------------------------------- 1 | local ls = require "luasnip" 2 | local s = ls.snippet 3 | local t = ls.text_node 4 | local i = ls.insert_node 5 | 6 | local snippets = { 7 | s("$pyenv", { 8 | t { "#!/usr/bin/env python", "" }, 9 | i(0), 10 | }), 11 | } 12 | 13 | return snippets 14 | -------------------------------------------------------------------------------- /lua/plugins/dap/init.lua: -------------------------------------------------------------------------------- 1 | local function dap_menu() 2 | local dap = require "dap" 3 | local dapui = require "dapui" 4 | local dap_widgets = require "dap.ui.widgets" 5 | 6 | local hint = [[ 7 | _t_: Toggle Breakpoint _R_: Run to Cursor 8 | _s_: Start _E_: Evaluate Input 9 | _c_: Continue _C_: Conditional Breakpoint 10 | _b_: Step Back _U_: Toggle UI 11 | _d_: Disconnect _S_: Scopes 12 | _e_: Evaluate _X_: Close 13 | _g_: Get Session _i_: Step Into 14 | _h_: Hover Variables _o_: Step Over 15 | _r_: Toggle REPL _u_: Step Out 16 | _x_: Terminate _p_: Pause 17 | ^ ^ _q_: Quit 18 | ]] 19 | 20 | return { 21 | name = "Debug", 22 | hint = hint, 23 | config = { 24 | color = "pink", 25 | invoke_on_body = true, 26 | hint = { 27 | border = "rounded", 28 | position = "middle-right", 29 | }, 30 | }, 31 | mode = "n", 32 | body = "", 33 | -- stylua: ignore 34 | heads = { 35 | { "C", function() dap.set_breakpoint(vim.fn.input "[Condition] > ") end, desc = "Conditional Breakpoint", }, 36 | { "E", function() dapui.eval(vim.fn.input "[Expression] > ") end, desc = "Evaluate Input", }, 37 | { "R", function() dap.run_to_cursor() end, desc = "Run to Cursor", }, 38 | { "S", function() dap_widgets.scopes() end, desc = "Scopes", }, 39 | { "U", function() dapui.toggle() end, desc = "Toggle UI", }, 40 | { "X", function() dap.close() end, desc = "Quit", }, 41 | { "b", function() dap.step_back() end, desc = "Step Back", }, 42 | { "c", function() dap.continue() end, desc = "Continue", }, 43 | { "d", function() dap.disconnect() end, desc = "Disconnect", }, 44 | { "e", function() dapui.eval() end, mode = {"n", "v"}, desc = "Evaluate", }, 45 | { "g", function() dap.session() end, desc = "Get Session", }, 46 | { "h", function() dap_widgets.hover() end, desc = "Hover Variables", }, 47 | { "i", function() dap.step_into() end, desc = "Step Into", }, 48 | { "o", function() dap.step_over() end, desc = "Step Over", }, 49 | { "p", function() dap.pause.toggle() end, desc = "Pause", }, 50 | { "r", function() dap.repl.toggle() end, desc = "Toggle REPL", }, 51 | { "s", function() dap.continue() end, desc = "Start", }, 52 | { "t", function() dap.toggle_breakpoint() end, desc = "Toggle Breakpoint", }, 53 | { "u", function() dap.step_out() end, desc = "Step Out", }, 54 | { "x", function() dap.terminate() end, desc = "Terminate", }, 55 | { "q", nil, { exit = true, nowait = true, desc = "Exit" } }, 56 | }, 57 | } 58 | end 59 | 60 | local M = { 61 | { 62 | "mfussenegger/nvim-dap", 63 | dependencies = { 64 | { "rcarriga/nvim-dap-ui" }, 65 | { "theHamsta/nvim-dap-virtual-text" }, 66 | { "nvim-telescope/telescope-dap.nvim" }, 67 | { "jay-babu/mason-nvim-dap.nvim" }, 68 | { "LiadOz/nvim-dap-repl-highlights", opts = {} }, 69 | }, 70 | -- stylua: ignore 71 | keys = { 72 | { "dR", function() require("dap").run_to_cursor() end, desc = "Run to Cursor", }, 73 | { "dE", function() require("dapui").eval(vim.fn.input "[Expression] > ") end, desc = "Evaluate Input", }, 74 | { "dC", function() require("dap").set_breakpoint(vim.fn.input "[Condition] > ") end, desc = "Conditional Breakpoint", }, 75 | { "dU", function() require("dapui").toggle() end, desc = "Toggle UI", }, 76 | { "db", function() require("dap").step_back() end, desc = "Step Back", }, 77 | { "dc", function() require("dap").continue() end, desc = "Continue", }, 78 | { "dd", function() require("dap").disconnect() end, desc = "Disconnect", }, 79 | { "de", function() require("dapui").eval() end, mode = {"n", "v"}, desc = "Evaluate", }, 80 | { "dg", function() require("dap").session() end, desc = "Get Session", }, 81 | { "dh", function() require("dap.ui.widgets").hover() end, desc = "Hover Variables", }, 82 | { "dS", function() require("dap.ui.widgets").scopes() end, desc = "Scopes", }, 83 | { "di", function() require("dap").step_into() end, desc = "Step Into", }, 84 | { "do", function() require("dap").step_over() end, desc = "Step Over", }, 85 | { "dl", function() require("dap").run_last() end, desc = "Run Last" }, 86 | { "dp", function() require("dap").pause.toggle() end, desc = "Pause", }, 87 | { "dq", function() require("dap").close() end, desc = "Quit", }, 88 | { "dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL", }, 89 | { "ds", function() require("dap").continue() end, desc = "Start", }, 90 | { "dt", function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint", }, 91 | { "dx", function() require("dap").terminate() end, desc = "Terminate", }, 92 | { "du", function() require("dap").step_out() end, desc = "Step Out", }, 93 | }, 94 | opts = { 95 | setup = {}, 96 | }, 97 | config = function(plugin, opts) 98 | local icons = require "config.icons" 99 | vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) 100 | 101 | for name, sign in pairs(icons.dap) do 102 | sign = type(sign) == "table" and sign or { sign } 103 | vim.fn.sign_define("Dap" .. name, { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] }) 104 | end 105 | 106 | require("nvim-dap-virtual-text").setup { 107 | commented = true, 108 | } 109 | 110 | local dap, dapui = require "dap", require "dapui" 111 | dapui.setup {} 112 | 113 | dap.listeners.after.event_initialized["dapui_config"] = function() 114 | dapui.open() 115 | end 116 | dap.listeners.before.event_terminated["dapui_config"] = function() 117 | dapui.close() 118 | end 119 | dap.listeners.before.event_exited["dapui_config"] = function() 120 | dapui.close() 121 | end 122 | 123 | -- set up debugger 124 | for k, _ in pairs(opts.setup) do 125 | opts.setup[k](plugin, opts) 126 | end 127 | end, 128 | }, 129 | { 130 | "anuvyklack/hydra.nvim", 131 | opts = { 132 | specs = { 133 | dap = dap_menu, 134 | }, 135 | }, 136 | }, 137 | --TODO: to configure 138 | { 139 | "jay-babu/mason-nvim-dap.nvim", 140 | dependencies = "mason.nvim", 141 | cmd = { "DapInstall", "DapUninstall" }, 142 | opts = { 143 | automatic_setup = true, 144 | handlers = {}, 145 | ensure_installed = {}, 146 | }, 147 | }, 148 | } 149 | 150 | return M 151 | -------------------------------------------------------------------------------- /lua/plugins/dashboard/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "goolord/alpha-nvim", 3 | event = "VimEnter", 4 | config = function() 5 | local dashboard = require "alpha.themes.dashboard" 6 | dashboard.section.header.val = require("plugins.dashboard.logo")["random"] 7 | dashboard.section.buttons.val = { 8 | dashboard.button("c", " " .. " Config", ":e $MYVIMRC "), 9 | dashboard.button("f", " " .. " Find file", ":Telescope find_files "), 10 | dashboard.button("g", " " .. " Find text", ":Telescope live_grep "), 11 | dashboard.button("l", "鈴" .. " Lazy", ":Lazy"), 12 | dashboard.button("n", " " .. " New file", ":ene startinsert "), 13 | dashboard.button("p", " " .. " Projects", ":Telescope projects "), 14 | dashboard.button("q", " " .. " Quit", ":qa"), 15 | dashboard.button("r", " " .. " Recent files", ":Telescope oldfiles "), 16 | dashboard.button("s", "勒" .. " Restore Session", [[:lua require("persistence").load() ]]), 17 | } 18 | for _, button in ipairs(dashboard.section.buttons.val) do 19 | button.opts.hl = "AlphaButtons" 20 | button.opts.hl_shortcut = "AlphaShortcut" 21 | end 22 | dashboard.section.footer.opts.hl = "Constant" 23 | dashboard.section.header.opts.hl = "AlphaHeader" 24 | dashboard.section.buttons.opts.hl = "AlphaButtons" 25 | dashboard.opts.layout[1].val = 0 26 | 27 | -- close Lazy and re-open when the dashboard is ready 28 | if vim.o.filetype == "lazy" then 29 | vim.cmd.close() 30 | vim.api.nvim_create_autocmd("User", { 31 | pattern = "AlphaReady", 32 | callback = function() 33 | require("lazy").show() 34 | end, 35 | }) 36 | end 37 | 38 | require("alpha").setup(dashboard.opts) 39 | 40 | vim.api.nvim_create_autocmd("User", { 41 | pattern = "LazyVimStarted", 42 | callback = function() 43 | local stats = require("lazy").stats() 44 | local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100) 45 | 46 | -- local now = os.date "%d-%m-%Y %H:%M:%S" 47 | local version = "  v" .. vim.version().major .. "." .. vim.version().minor .. "." .. vim.version().patch 48 | local fortune = require "alpha.fortune" 49 | local quote = table.concat(fortune(), "\n") 50 | local plugins = "⚡Neovim loaded " .. stats.count .. " plugins in " .. ms .. "ms" 51 | local footer = "\t" .. version .. "\t" .. plugins .. "\n" .. quote 52 | dashboard.section.footer.val = footer 53 | pcall(vim.cmd.AlphaRedraw) 54 | end, 55 | }) 56 | end, 57 | } 58 | -------------------------------------------------------------------------------- /lua/plugins/db/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "tpope/vim-dadbod", 4 | dependencies = { 5 | "kristijanhusak/vim-dadbod-ui", 6 | "kristijanhusak/vim-dadbod-completion", 7 | }, 8 | opts = { 9 | db_competion = function() 10 | require("cmp").setup.buffer { sources = { { name = "vim-dadbod-completion" } } } 11 | end, 12 | }, 13 | config = function(_, opts) 14 | vim.g.db_ui_save_location = vim.fn.stdpath "config" .. require("plenary.path").path.sep .. "db_ui" 15 | 16 | vim.api.nvim_create_autocmd("FileType", { 17 | pattern = { 18 | "sql", 19 | }, 20 | command = [[setlocal omnifunc=vim_dadbod_completion#omni]], 21 | }) 22 | 23 | vim.api.nvim_create_autocmd("FileType", { 24 | pattern = { 25 | "sql", 26 | "mysql", 27 | "plsql", 28 | }, 29 | callback = function() 30 | vim.schedule(opts.db_completion) 31 | end, 32 | }) 33 | end, 34 | keys = { 35 | { "Dt", "DBUIToggle", desc = "Toggle UI" }, 36 | { "Df", "DBUIFindBuffer", desc = "Find Buffer" }, 37 | { "Dr", "DBUIRenameBuffer", desc = "Rename Buffer" }, 38 | { "Dq", "DBUILastQueryInfo", desc = "Last Query Info" }, 39 | }, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /lua/plugins/dooku.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "Zeioth/dooku.nvim", 3 | enabled = false, 4 | cmd = { "DookuGenerate", "DookuOpen", "DookuAutoSetup" }, 5 | opts = {}, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/guess-indent.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nmac427/guess-indent.nvim", 3 | enabled = false, 4 | event = { "BufReadPre" }, 5 | opts = {}, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/hardtime.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "m4xshen/hardtime.nvim", 3 | cmd = { "HardTime" }, 4 | enabled = true, 5 | dependencies = { "MunifTanjim/nui.nvim" }, 6 | opts = {}, 7 | } 8 | -------------------------------------------------------------------------------- /lua/plugins/hydra/file-action.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.open = function(file_path, buffer, pre_hook) 4 | local ok, Hydra = pcall(require, "hydra") 5 | if not ok then 6 | return 7 | end 8 | 9 | local _ = function(callback) 10 | return function() 11 | if pre_hook then 12 | pre_hook() 13 | else 14 | vim.cmd "wincmd w" 15 | end 16 | vim.schedule(callback) 17 | end 18 | end 19 | 20 | local hydra = Hydra { 21 | name = "", 22 | mode = { "n", "i" }, 23 | config = { 24 | buffer = buffer, 25 | hint = { 26 | border = "rounded", 27 | position = "bottom", 28 | }, 29 | }, 30 | heads = { 31 | { "y", _(function() 32 | vim.fn.setreg("+", file_path) 33 | end), { private = true, desc = "Copy", exit = true } }, 34 | { 35 | "Y", 36 | _(function() 37 | local relative_path = vim.fn.fnamemodify(file_path, ":~:.") 38 | vim.fn.setreg("+", relative_path) 39 | end), 40 | { 41 | private = true, 42 | desc = "Copy relative", 43 | exit = true, 44 | }, 45 | }, 46 | }, 47 | } 48 | 49 | hydra:activate() 50 | end 51 | 52 | return M 53 | -------------------------------------------------------------------------------- /lua/plugins/hydra/folder-action.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local utils = require "utils" 4 | 5 | M.open = function(cwd, buffer, pre_hook) 6 | local ok, Hydra = pcall(require, "hydra") 7 | if not ok then 8 | return 9 | end 10 | cwd = utils.remove_path_last_separator(cwd) 11 | 12 | local _ = function(callback) 13 | return function() 14 | if pre_hook then 15 | pre_hook() 16 | else 17 | vim.cmd "wincmd w" 18 | end 19 | vim.schedule(callback) 20 | end 21 | end 22 | 23 | local hydra = Hydra { 24 | name = "", 25 | mode = { "n", "i" }, 26 | config = { 27 | buffer = buffer, 28 | }, 29 | heads = { 30 | { 31 | "f", 32 | _(function() 33 | project_files { 34 | cwd = cwd, 35 | use_all_files = true, 36 | } 37 | end), 38 | { 39 | private = true, 40 | exit = true, 41 | desc = "T.Files", 42 | }, 43 | }, 44 | { 45 | "p", 46 | _(function() 47 | require("telescope").extensions.file_browser.file_browser { 48 | files = false, 49 | use_fd = true, 50 | cwd = cwd, 51 | respect_gitignore = true, 52 | } 53 | end), 54 | { 55 | private = true, 56 | desc = "Folders", 57 | exit = true, 58 | }, 59 | }, 60 | { 61 | "s", 62 | _(function() 63 | require "userlib.telescope.live_grep_call" { 64 | cwd = cwd, 65 | } 66 | end), 67 | { 68 | desc = "Content", 69 | private = true, 70 | exit = true, 71 | }, 72 | }, 73 | { 74 | "r", 75 | _(function() 76 | require("userlib.telescope.pickers").project_files { 77 | oldfiles = true, 78 | cwd_only = false, 79 | cwd = cwd, 80 | } 81 | end), 82 | { 83 | private = true, 84 | desc = "Recent", 85 | exit = true, 86 | }, 87 | }, 88 | { 89 | "w", 90 | _(function() 91 | require("userlib.runtime.utils").change_cwd(cwd, "tcd") 92 | vim.schedule(function() 93 | au.exec_useraucmd(au.user_autocmds.DoEnterDashboard) 94 | end) 95 | end), 96 | { 97 | private = true, 98 | desc = "Cwd", 99 | exit = true, 100 | }, 101 | }, 102 | { 103 | "", 104 | _(function() 105 | -- require('userlib.runtime.utils').change_cwd(cwd, 'tcd') 106 | require("oil").open(cwd) 107 | -- require('mini.files').open(cwd) 108 | end), 109 | { 110 | private = true, 111 | desc = "Browser", 112 | exit = true, 113 | }, 114 | }, 115 | { 116 | "t", 117 | _(function() 118 | vim.cmd("tabfind " .. cwd) 119 | end), 120 | { 121 | private = true, 122 | desc = "Open in tab", 123 | exit = true, 124 | }, 125 | }, 126 | }, 127 | } 128 | hydra:activate() 129 | end 130 | 131 | return M 132 | -------------------------------------------------------------------------------- /lua/plugins/hydra/git-action.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.open_git_conflict_hydra = function() 4 | local hint = [[ 5 | Git Conflict 6 | _b_: Choose both _n_: Move to next conflict → 7 | _o_: Choose ours _p_: Move to prev conflict ← 8 | _t_: Choose theirs _q_: Exit 9 | _x_: Choose none 10 | ]] 11 | local Hydra = require "hydra" 12 | Hydra({ 13 | name = "Git conflict", 14 | color = "blue", 15 | hint = hint, 16 | config = { 17 | color = "pink", 18 | hint = { 19 | border = true, 20 | }, 21 | }, 22 | heads = { 23 | { "b", "GitConflictChooseBoth", { desc = "choose both", exit = false } }, 24 | { "x", "GitConflictChooseNone", { desc = "choose none", exit = true } }, 25 | { "n", "GitConflictNextConflict", { desc = "move to next conflict", exit = false } }, 26 | { "o", "GitConflictChooseOurs", { desc = "choose ours", exit = false } }, 27 | { "p", "GitConflictPrevConflict", { desc = "move to prev conflict", exit = false } }, 28 | { "t", "GitConflictChooseTheirs", { desc = "choose theirs", exit = false } }, 29 | { "q", nil, { exit = true, nowait = true, desc = "exit" } }, 30 | }, 31 | }):activate() 32 | end 33 | 34 | M.open_git_signs_hydra = function() 35 | local hint = [[ 36 | _d_: Diff this _s_: Stage hunk _r_: Reset hunk 37 | _S_: Stage buffer _u_: Undo stage _R_: Reset buffer 38 | _p_: Preview hunk _b_: Blame line _B_: Toggle blame 39 | _x_: Select hunk _q_: Exit _]_: Next hunk 40 | _[_: Prev hunk 41 | ]] 42 | local Hydra = require "hydra" 43 | Hydra({ 44 | config = { 45 | exit = true, 46 | color = "pink", 47 | hint = { 48 | border = true, 49 | }, 50 | }, 51 | name = "Gitsigns", 52 | hint = hint, 53 | heads = { 54 | { "d", "Gitsigns diffthis", { desc = "Diff this" } }, 55 | { "s", "Gitsigns stage_hunk", { desc = "Stage hunk" } }, 56 | { "r", "Gitsigns reset_hunk", { desc = "Reset hunk" } }, 57 | { "S", "Gitsigns stage_buffer", { desc = "Stage the buffer " } }, 58 | { "u", "Gitsigns undo_stage_hunk", { desc = "Undo stage hunk" } }, 59 | { "R", "Gitsigns reset_buffer", { desc = "Reset buffer" } }, 60 | { "p", "Gitsigns preview_hunk", { desc = "Preview hunk" } }, 61 | { "b", "Gitsigns blame_line", { desc = "Blame line" } }, 62 | { "B", "Gitsigns toggle_current_line_blame", { desc = "Toggle current line blame" } }, 63 | { "x", "Gitsigns select_hunk", { desc = "Select hunk" } }, 64 | { 65 | "]", 66 | function() 67 | local gs = require "gitsigns" 68 | if vim.wo.diff then 69 | return 70 | end 71 | vim.schedule(function() 72 | gs.next_hunk() 73 | end) 74 | end, 75 | { desc = "Next hunk" }, 76 | }, 77 | { 78 | "[", 79 | function() 80 | local gs = require "gitsigns" 81 | if vim.wo.diff then 82 | return 83 | end 84 | vim.schedule(function() 85 | gs.prev_hunk() 86 | end) 87 | end, 88 | { desc = "Prev hunk" }, 89 | }, 90 | { "q", nil, { exit = true, nowait = true, desc = "Exit" } }, 91 | }, 92 | }):activate() 93 | end 94 | 95 | return M 96 | -------------------------------------------------------------------------------- /lua/plugins/hydra/init.lua: -------------------------------------------------------------------------------- 1 | local function gitsigns_menu() 2 | local gitsigns = require "gitsigns" 3 | 4 | local hint = [[ 5 | _J_: Next hunk _s_: Stage Hunk _d_: Show Deleted _b_: Blame Line 6 | _K_: Prev hunk _u_: Undo Last Stage _p_: Preview Hunk _B_: Blame Show Full 7 | ^ ^ _S_: Stage Buffer ^ ^ _/_: Show Base File 8 | ^ 9 | ^ ^ __: Neogit _q_: Exit 10 | ]] 11 | 12 | return { 13 | name = "Git", 14 | hint = hint, 15 | config = { 16 | color = "pink", 17 | invoke_on_body = true, 18 | hint = { 19 | border = "rounded", 20 | position = "bottom", 21 | }, 22 | on_enter = function() 23 | vim.cmd "mkview" 24 | vim.cmd "silent! %foldopen!" 25 | vim.bo.modifiable = false 26 | gitsigns.toggle_signs(true) 27 | gitsigns.toggle_linehl(true) 28 | end, 29 | on_exit = function() 30 | local cursor_pos = vim.api.nvim_win_get_cursor(0) 31 | vim.cmd "loadview" 32 | vim.api.nvim_win_set_cursor(0, cursor_pos) 33 | vim.cmd "normal zv" 34 | gitsigns.toggle_signs(false) 35 | gitsigns.toggle_linehl(false) 36 | gitsigns.toggle_deleted(false) 37 | end, 38 | }, 39 | body = "", 40 | heads = { 41 | { 42 | "J", 43 | function() 44 | if vim.wo.diff then 45 | return "]c" 46 | end 47 | vim.schedule(function() 48 | gitsigns.next_hunk() 49 | end) 50 | return "" 51 | end, 52 | { expr = true, desc = "Next Hunk" }, 53 | }, 54 | { 55 | "K", 56 | function() 57 | if vim.wo.diff then 58 | return "[c" 59 | end 60 | vim.schedule(function() 61 | gitsigns.prev_hunk() 62 | end) 63 | return "" 64 | end, 65 | { expr = true, desc = "Prev Hunk" }, 66 | }, 67 | { "s", ":Gitsigns stage_hunk", { silent = true, desc = "Stage Hunk" } }, 68 | { "u", gitsigns.undo_stage_hunk, { desc = "Undo Last Stage" } }, 69 | { "S", gitsigns.stage_buffer, { desc = "Stage Buffer" } }, 70 | { "p", gitsigns.preview_hunk, { desc = "Preview Hunk" } }, 71 | { "d", gitsigns.toggle_deleted, { nowait = true, desc = "Toggle Deleted" } }, 72 | { "b", gitsigns.blame_line, { desc = "Blame" } }, 73 | { 74 | "B", 75 | function() 76 | gitsigns.blame_line { full = true } 77 | end, 78 | { desc = "Blame Show Full" }, 79 | }, 80 | { "/", gitsigns.show, { exit = true, desc = "Show Base File" } }, -- show the base of the file 81 | { "", "Neogit", { exit = true, desc = "Neogit" } }, 82 | { "q", nil, { exit = true, nowait = true, desc = "Exit" } }, 83 | }, 84 | } 85 | end 86 | 87 | local function lsp_menu() 88 | local cmd = require("hydra.keymap-util").cmd 89 | return { 90 | name = "LSP Mode", 91 | mode = { "n" }, 92 | config = { 93 | color = "pink", 94 | invoke_on_body = true, 95 | hint = { 96 | type = "window", 97 | position = "bottom-right", 98 | border = "rounded", 99 | show_name = true, 100 | }, 101 | }, 102 | hint = [[ 103 | LSP 104 | ^ 105 | Common Actions 106 | - _h_: Show Hover Doc 107 | - _f_: Format Buffer 108 | - _a_: Code Actions 109 | - _s_: Jump to Definition 110 | - _d_: Show Diagnostics 111 | - _w_: Show Workspace Diagnostics 112 | ^ 113 | Help 114 | - _e_: Show Declarations 115 | - _D_: Show Type Definition 116 | - _j_: Show Sig Help 117 | - _o_: Show Implementation 118 | - _r_: Show References 119 | ^ 120 | _;_/_q_/__: Exit Hydra 121 | ]], 122 | body = "", 123 | heads = { 124 | { "s", cmd "TroubleToggle lsp_definitions", { desc = "Jump to Definition", silent = true } }, 125 | { "h", cmd "Lspsaga hover_doc", { desc = "Show Hover Doc", silent = true } }, 126 | { "o", cmd "TroubleToggle lsp_implementations", { desc = "Show Implementations", silent = true } }, 127 | { "j", vim.lsp.buf.signature_help, { desc = "Show Sig Help", silent = true } }, 128 | { "r", cmd "TroubleToggle lsp_references", { desc = "Show References", silent = true } }, 129 | { 130 | "f", 131 | function() 132 | vim.lsp.buf.format { async = true } 133 | end, 134 | { desc = "Format Buffer", silent = true }, 135 | }, 136 | { "a", vim.lsp.buf.code_action, { desc = "Show Code Actions", silent = true } }, 137 | { "d", cmd "TroubleToggle document_diagnostics", { desc = "Show Diagnostics", silent = true } }, 138 | { "w", cmd "TroubleToggle workspace_diagnostics", { desc = "Show Workspace Diagnostics", silent = true } }, 139 | { "D", cmd "TroubleToggle lsp_definitions", { desc = "Show Type Definition", silent = true } }, 140 | { "e", vim.lsp.buf.declaration, { desc = "Show Declaration", silent = true } }, 141 | { ";", nil, { desc = "quit", exit = true, nowait = true } }, 142 | { "q", nil, { desc = "quit", exit = true, nowait = true } }, 143 | { "", nil, { desc = "quit", exit = true, nowait = true } }, 144 | }, 145 | } 146 | end 147 | 148 | local function quick_menu() 149 | local cmd = require("hydra.keymap-util").cmd 150 | return { 151 | name = "Quick Menu", 152 | mode = { "n" }, 153 | hint = [[ 154 | Quick Menu 155 | ^ 156 | _f_: Show Terminal (float) 157 | _v_: Open Terminal (vertical) 158 | _h_: Open Terminal (horizontal) 159 | 160 | _x_: Open Quickfix 161 | _l_: Open Location List 162 | 163 | _s_: Buffer Fuzzy Search 164 | _o_: Open Symbols Outline 165 | 166 | _t_: Show Help Tags 167 | _k_: Show Keymaps 168 | _c_: Show Vim Commands 169 | _m_: Show Man Pages 170 | ^ 171 | ^ ^ _q_/__: Exit Hydra 172 | ]], 173 | config = { 174 | color = "teal", 175 | invoke_on_body = true, 176 | hint = { 177 | type = "window", 178 | position = "bottom", 179 | border = "rounded", 180 | show_name = true, 181 | }, 182 | }, 183 | body = "", 184 | heads = { 185 | { "t", cmd "Telescope help_tags", { desc = "Open Help Tags", silent = true } }, 186 | { "k", ":lua require('telescope.builtin').keymaps()", { desc = "Open Neovim Keymaps", silent = true } }, 187 | { "c", cmd "Telescope commands", { desc = "Open Available Telescope Commands", silent = true } }, 188 | { "m", cmd "Telescope man_pages", { desc = "Opens Man Pages", silent = true } }, 189 | 190 | { "s", cmd "Telescope current_buffer_fuzzy_find skip_empty_lines=true", { desc = "Fuzzy find in current buffer", silent = true } }, 191 | { "o", cmd "Telescope aerial", { desc = "Opens Symbols Outline", exit = true, silent = true } }, 192 | 193 | { "x", cmd "TroubleToggle quickfix", { desc = "Opens Quickfix", silent = true } }, 194 | { "l", cmd "TroubleToggle loclist", { desc = "Opens Location List", silent = true } }, 195 | 196 | { "f", cmd "ToggleTerm direction=float", { desc = "Floating Terminal", silent = true } }, 197 | { "v", cmd "ToggleTerm direction=vertical", { desc = "Vertical Terminal", silent = true } }, 198 | { "h", cmd "ToggleTerm direction=horizontal", { desc = "Horizontal Terminal", silent = true } }, 199 | 200 | { "q", nil, { desc = "quit", exit = true, nowait = true } }, 201 | { "", nil, { desc = "quit", exit = true, nowait = true } }, 202 | }, 203 | } 204 | end 205 | 206 | return { 207 | { 208 | "anuvyklack/hydra.nvim", 209 | event = { "BufReadPre" }, 210 | opts = { 211 | specs = { 212 | gitsigns = gitsigns_menu, 213 | quick = quick_menu, 214 | }, 215 | }, 216 | config = function(_, opts) 217 | local hydra = require "hydra" 218 | for s, _ in pairs(opts.specs) do 219 | hydra(opts.specs[s]()) 220 | end 221 | end, 222 | }, 223 | } 224 | -------------------------------------------------------------------------------- /lua/plugins/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-lua/plenary.nvim", 3 | "MunifTanjim/nui.nvim", 4 | { 5 | "nvim-tree/nvim-web-devicons", 6 | dependencies = { "DaikyXendo/nvim-material-icon" }, 7 | config = function() 8 | require("nvim-web-devicons").setup { 9 | override = require("nvim-material-icon").get_icons(), 10 | } 11 | end, 12 | }, 13 | { "yamatsum/nvim-nonicons", config = true, enabled = false }, 14 | { "tpope/vim-repeat", event = "VeryLazy" }, 15 | { "nacro90/numb.nvim", event = "BufReadPre", config = true }, 16 | { 17 | "lukas-reineke/indent-blankline.nvim", 18 | event = { "BufReadPost", "BufNewFile" }, 19 | opts = { 20 | indent = { 21 | char = "│", 22 | tab_char = "│", 23 | }, 24 | scope = { enabled = false }, 25 | exclude = { 26 | filetypes = { 27 | "help", 28 | "alpha", 29 | "dashboard", 30 | "neo-tree", 31 | "Trouble", 32 | "lazy", 33 | "mason", 34 | "notify", 35 | "toggleterm", 36 | "lazyterm", 37 | }, 38 | }, 39 | }, 40 | main = "ibl", 41 | }, 42 | { 43 | "stevearc/dressing.nvim", 44 | event = "VeryLazy", 45 | opts = { 46 | input = { relative = "editor" }, 47 | select = { 48 | backend = { "telescope", "fzf", "builtin" }, 49 | }, 50 | }, 51 | }, 52 | { 53 | "rcarriga/nvim-notify", 54 | event = "VeryLazy", 55 | opts = { 56 | -- background_colour = "#A3CCBE", 57 | timeout = 3000, 58 | max_height = function() 59 | return math.floor(vim.o.lines * 0.75) 60 | end, 61 | max_width = function() 62 | return math.floor(vim.o.columns * 0.75) 63 | end, 64 | }, 65 | config = function(_, opts) 66 | require("notify").setup(opts) 67 | vim.notify = require "notify" 68 | end, 69 | }, 70 | { 71 | "monaqa/dial.nvim", 72 | keys = { { "", mode = { "n", "v" } }, { "", mode = { "n", "v" } }, { "g", mode = { "v" } }, { "g", mode = { "v" } } }, 73 | -- stylua: ignore 74 | config = function() 75 | vim.api.nvim_set_keymap("n", "", require("dial.map").inc_normal(), { desc = "Increment", noremap = true }) 76 | vim.api.nvim_set_keymap("n", "", require("dial.map").dec_normal(), { desc = "Decrement", noremap = true }) 77 | vim.api.nvim_set_keymap("v", "", require("dial.map").inc_visual(), { desc = "Increment", noremap = true }) 78 | vim.api.nvim_set_keymap("v", "", require("dial.map").dec_visual(), { desc = "Decrement", noremap = true }) 79 | vim.api.nvim_set_keymap("v", "g", require("dial.map").inc_gvisual(), { desc = "Increment", noremap = true }) 80 | vim.api.nvim_set_keymap("v", "g", require("dial.map").dec_gvisual(), { desc = "Decrement", noremap = true }) 81 | end, 82 | }, 83 | { 84 | "andymass/vim-matchup", 85 | event = { "BufReadPost" }, 86 | config = function() 87 | vim.g.matchup_matchparen_offscreen = { method = "popup" } 88 | end, 89 | }, 90 | { "tpope/vim-surround", event = "BufReadPre", enabled = false }, 91 | { 92 | "kylechui/nvim-surround", 93 | event = "BufReadPre", 94 | opts = {}, 95 | }, 96 | { 97 | "numToStr/Comment.nvim", 98 | dependencies = { "JoosepAlviste/nvim-ts-context-commentstring" }, 99 | keys = { { "gc", mode = { "n", "v" } }, { "gcc", mode = { "n", "v" } }, { "gbc", mode = { "n", "v" } } }, 100 | config = function(_, _) 101 | local opts = { 102 | ignore = "^$", 103 | pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(), 104 | } 105 | require("Comment").setup(opts) 106 | end, 107 | }, 108 | -- session management 109 | { 110 | "folke/persistence.nvim", 111 | event = "BufReadPre", 112 | opts = { options = { "buffers", "curdir", "tabpages", "winsize", "help" } }, 113 | -- stylua: ignore 114 | keys = { 115 | { "qs", function() require("persistence").load() end, desc = "Restore Session" }, 116 | { "ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" }, 117 | { "qd", function() require("persistence").stop() end, desc = "Don't Save Current Session" }, 118 | }, 119 | }, 120 | { 121 | "max397574/better-escape.nvim", 122 | enabled = true, 123 | event = "InsertEnter", 124 | config = function() 125 | require("better_escape").setup { 126 | mapping = { "jk" }, 127 | } 128 | end, 129 | }, 130 | { 131 | "TheBlob42/houdini.nvim", 132 | enabled = false, 133 | event = "VeryLazy", 134 | opts = { 135 | escape_sequences = { 136 | ["t"] = "", 137 | ["c"] = "", 138 | }, 139 | }, 140 | }, 141 | } 142 | -------------------------------------------------------------------------------- /lua/plugins/keyseer.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "jokajak/keyseer.nvim", 3 | enabled = false, 4 | opts = {}, 5 | event = "VeryLazy", 6 | cmd = { "KeySeer" }, 7 | } 8 | -------------------------------------------------------------------------------- /lua/plugins/lsp/bun.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local bun_servers = { "tsserver", "volar", "tailwindcss", "eslint" } 4 | 5 | local function is_bun_server(name) 6 | for _, server in ipairs(bun_servers) do 7 | if server == name then 8 | return true 9 | end 10 | end 11 | return false 12 | end 13 | 14 | local function is_bun_available() 15 | local bunx = vim.fn.executable "bunx" 16 | if bunx == 0 then 17 | return false 18 | end 19 | return true 20 | end 21 | 22 | M.add_bun_prefix = function(config, _) 23 | if config.cmd and is_bun_available() and is_bun_server(config.name) then 24 | config.cmd = vim.list_extend({ 25 | "bunx", 26 | }, config.cmd) 27 | end 28 | end 29 | 30 | return M 31 | -------------------------------------------------------------------------------- /lua/plugins/lsp/format.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.autoformat = true 4 | M.format_notify = false 5 | 6 | function M.toggle() 7 | M.autoformat = not M.autoformat 8 | vim.notify(M.autoformat and "Enabled format on save" or "Disabled format on save") 9 | end 10 | 11 | function M.format() 12 | local buf = vim.api.nvim_get_current_buf() 13 | 14 | local formatters = M.get_formatters(buf) 15 | local client_ids = vim.tbl_map(function(client) 16 | return client.id 17 | end, formatters.active) 18 | 19 | if #client_ids == 0 then 20 | return 21 | end 22 | 23 | if M.format_notify then 24 | M.notify(formatters) 25 | end 26 | 27 | vim.lsp.buf.format(vim.tbl_deep_extend("force", { 28 | bufnr = buf, 29 | filter = function(client) 30 | return vim.tbl_contains(client_ids, client.id) 31 | end, 32 | }, require("plugins.lsp.utils").opts("nvim-lspconfig").format or {})) 33 | end 34 | 35 | function M.notify(formatters) 36 | local lines = { "# Active:" } 37 | 38 | for _, client in ipairs(formatters.active) do 39 | local line = "- **" .. client.name .. "**" 40 | if client.name == "null-ls" then 41 | line = line 42 | .. " (" 43 | .. table.concat( 44 | vim.tbl_map(function(f) 45 | return "`" .. f.name .. "`" 46 | end, formatters.null_ls), 47 | ", " 48 | ) 49 | .. ")" 50 | end 51 | table.insert(lines, line) 52 | end 53 | 54 | if #formatters.available > 0 then 55 | table.insert(lines, "") 56 | table.insert(lines, "# Disabled:") 57 | for _, client in ipairs(formatters.available) do 58 | table.insert(lines, "- **" .. client.name .. "**") 59 | end 60 | end 61 | 62 | vim.notify(table.concat(lines, "\n"), vim.log.levels.INFO, { 63 | title = "Formatting", 64 | on_open = function(win) 65 | vim.api.nvim_win_set_option(win, "conceallevel", 3) 66 | vim.api.nvim_win_set_option(win, "spell", false) 67 | local buf = vim.api.nvim_win_get_buf(win) 68 | vim.treesitter.start(buf, "markdown") 69 | end, 70 | }) 71 | end 72 | 73 | function M.supports_format(client) 74 | if client.config and client.config.capabilities and client.config.capabilities.documentFormattingProvider == false then 75 | return false 76 | end 77 | return client.supports_method "textDocument/formatting" or client.supports_method "textDocument/rangeFormatting" 78 | end 79 | 80 | function M.get_formatters(bufnr) 81 | local ft = vim.bo[bufnr].filetype 82 | -- check if we have any null-ls formatters for the current filetype 83 | local null_ls = package.loaded["null-ls"] and require("null-ls.sources").get_available(ft, "NULL_LS_FORMATTING") or {} 84 | 85 | local ret = { 86 | active = {}, 87 | available = {}, 88 | null_ls = null_ls, 89 | } 90 | 91 | local clients = vim.lsp.get_active_clients { bufnr = bufnr } 92 | for _, client in ipairs(clients) do 93 | if M.supports_format(client) then 94 | if (#null_ls > 0 and client.name == "null-ls") or #null_ls == 0 then 95 | table.insert(ret.active, client) 96 | else 97 | table.insert(ret.available, client) 98 | end 99 | end 100 | end 101 | 102 | return ret 103 | end 104 | 105 | function M.on_attach(_, bufnr) 106 | vim.api.nvim_create_autocmd("BufWritePre", { 107 | group = vim.api.nvim_create_augroup("LspFormat." .. bufnr, {}), 108 | buffer = bufnr, 109 | callback = function() 110 | if M.autoformat then 111 | M.format() 112 | end 113 | end, 114 | }) 115 | end 116 | 117 | return M 118 | -------------------------------------------------------------------------------- /lua/plugins/lsp/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "neovim/nvim-lspconfig", 4 | event = { "BufReadPre", "BufNewFile" }, 5 | dependencies = { 6 | { "folke/neoconf.nvim", cmd = "Neoconf", config = true }, 7 | { "j-hui/fidget.nvim", config = true }, 8 | { "smjonas/inc-rename.nvim", config = true }, 9 | "williamboman/mason.nvim", 10 | "williamboman/mason-lspconfig.nvim", 11 | "jay-babu/mason-null-ls.nvim", 12 | }, 13 | opts = { 14 | servers = { 15 | dockerls = {}, 16 | }, 17 | setup = {}, 18 | format = { 19 | timeout_ms = 3000, 20 | }, 21 | }, 22 | config = function(plugin, opts) 23 | require("plugins.lsp.servers").setup(plugin, opts) 24 | end, 25 | }, 26 | { 27 | "williamboman/mason.nvim", 28 | build = ":MasonUpdate", 29 | cmd = "Mason", 30 | keys = { { "lm", "Mason", desc = "Mason" } }, 31 | opts = { 32 | ensure_installed = { 33 | "shfmt", 34 | }, 35 | }, 36 | config = function(_, opts) 37 | require("mason").setup(opts) 38 | local mr = require "mason-registry" 39 | local function ensure_installed() 40 | for _, tool in ipairs(opts.ensure_installed) do 41 | local p = mr.get_package(tool) 42 | if not p:is_installed() then 43 | p:install() 44 | end 45 | end 46 | end 47 | if mr.refresh then 48 | mr.refresh(ensure_installed) 49 | else 50 | ensure_installed() 51 | end 52 | end, 53 | }, 54 | { 55 | "utilyre/barbecue.nvim", 56 | event = "VeryLazy", 57 | dependencies = { 58 | "neovim/nvim-lspconfig", 59 | "SmiteshP/nvim-navic", 60 | "nvim-tree/nvim-web-devicons", 61 | }, 62 | enabled = false, -- use lspsaga 63 | config = true, 64 | }, 65 | { 66 | "folke/trouble.nvim", 67 | cmd = { "TroubleToggle", "Trouble" }, 68 | opts = { use_diagnostic_signs = true }, 69 | keys = { 70 | { "ld", "TroubleToggle document_diagnostics", desc = "Document Diagnostics" }, 71 | { "lD", "TroubleToggle workspace_diagnostics", desc = "Workspace Diagnostics" }, 72 | }, 73 | }, 74 | { 75 | "nvimdev/lspsaga.nvim", 76 | event = "VeryLazy", 77 | opts = { 78 | symbol_in_winbar = { 79 | enable = false, 80 | }, 81 | lightbulb = { 82 | enable = false, 83 | }, 84 | }, 85 | }, 86 | { 87 | "Bekaboo/dropbar.nvim", 88 | event = "VeryLazy", 89 | enabled = function() 90 | return vim.fn.has "nvim-0.10.0" == 1 91 | end, 92 | }, 93 | { 94 | "nvimtools/none-ls.nvim", 95 | event = { "BufReadPre", "BufNewFile" }, 96 | dependencies = { "mason.nvim" }, 97 | opts = function() 98 | local nls = require "null-ls" 99 | return { 100 | root_dir = require("null-ls.utils").root_pattern(".null-ls-root", ".neoconf.json", "Makefile", ".git"), 101 | sources = { 102 | nls.builtins.formatting.shfmt, 103 | }, 104 | } 105 | end, 106 | }, 107 | { "jay-babu/mason-null-ls.nvim", opts = { ensure_installed = nil, automatic_installation = true, automatic_setup = false } }, 108 | -- { 109 | -- "ray-x/lsp_signature.nvim", 110 | -- event = "VeryLazy", 111 | -- opts = {}, 112 | -- }, 113 | -- { "rafcamlet/nvim-luapad", cmd = { "LuaRun", "Luapad" } }, 114 | { 115 | "stevearc/conform.nvim", 116 | enabled = false, 117 | event = "BufReadPre", 118 | opts = {}, 119 | }, 120 | { 121 | "mfussenegger/nvim-lint", 122 | enabled = false, 123 | event = "BufReadPre", 124 | opts = { ft = {} }, 125 | config = function(_, opts) 126 | require("lint").linters_by_ft = opts.ft 127 | vim.api.nvim_create_autocmd({ "BufWritePost" }, { 128 | callback = function() 129 | require("lint").try_lint() 130 | end, 131 | }) 132 | end, 133 | }, 134 | { 135 | "dnlhc/glance.nvim", 136 | enabled = false, 137 | cmd = { "Glance" }, 138 | opts = {}, 139 | }, 140 | { 141 | "luckasRanarison/clear-action.nvim", 142 | enabled = false, 143 | event = "VeryLazy", 144 | cmd = { "CodeActionToggleSigns", "CodeActionToggleLabel" }, 145 | opts = {}, 146 | }, 147 | } 148 | -------------------------------------------------------------------------------- /lua/plugins/lsp/keymaps.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.on_attach(client, buffer) 4 | local self = M.new(client, buffer) 5 | 6 | -- stylua: ignore 7 | self:map("gd", function() require("telescope.builtin").lsp_definitions({ reuse_win = true }) end, { desc = "Goto Definition" }) 8 | self:map("gr", "Telescope lsp_references", { desc = "References" }) 9 | self:map("gD", "Lspsaga peek_definition", { desc = "Peek Definition" }) 10 | -- stylua: ignore 11 | self:map("gI", function() require("telescope.builtin").lsp_implementations({ reuse_win = true }) end, { desc = "Goto Implementation" }) 12 | -- stylua: ignore 13 | self:map("gy", function() require("telescope.builtin").lsp_type_definitions({ reuse_win = true }) end, { desc = "Goto Type Definition" }) 14 | self:map("K", "Lspsaga hover_doc", { desc = "Hover" }) 15 | self:map("gK", vim.lsp.buf.signature_help, { desc = "Signature Help", has = "signatureHelp" }) 16 | self:map("]d", M.diagnostic_goto(true), { desc = "Next Diagnostic" }) 17 | self:map("[d", M.diagnostic_goto(false), { desc = "Prev Diagnostic" }) 18 | self:map("]e", M.diagnostic_goto(true, "ERROR"), { desc = "Next Error" }) 19 | self:map("[e", M.diagnostic_goto(false, "ERROR"), { desc = "Prev Error" }) 20 | self:map("]w", M.diagnostic_goto(true, "WARNING"), { desc = "Next Warning" }) 21 | self:map("[w", M.diagnostic_goto(false, "WARNING"), { desc = "Prev Warning" }) 22 | self:map("la", "Lspsaga code_action", { desc = "Code Action", mode = { "n", "v" }, has = "codeAction" }) 23 | 24 | local format = require("plugins.lsp.format").format 25 | self:map("lf", format, { desc = "Format Document", has = "documentFormatting" }) 26 | self:map("lf", format, { desc = "Format Range", mode = "v", has = "documentRangeFormatting" }) 27 | self:map("lr", M.rename, { expr = true, desc = "Rename", has = "rename" }) 28 | 29 | self:map("ls", require("telescope.builtin").lsp_document_symbols, { desc = "Document Symbols" }) 30 | self:map("lS", require("telescope.builtin").lsp_dynamic_workspace_symbols, { desc = "Workspace Symbols" }) 31 | self:map("lw", require("plugins.lsp.utils").toggle_diagnostics, { desc = "Toggle Inline Diagnostics" }) 32 | end 33 | 34 | function M.new(client, buffer) 35 | return setmetatable({ client = client, buffer = buffer }, { __index = M }) 36 | end 37 | 38 | function M:has(cap) 39 | return self.client.server_capabilities[cap .. "Provider"] 40 | end 41 | 42 | function M:map(lhs, rhs, opts) 43 | opts = opts or {} 44 | if opts.has and not self:has(opts.has) then 45 | return 46 | end 47 | vim.keymap.set( 48 | opts.mode or "n", 49 | lhs, 50 | type(rhs) == "string" and ("%s"):format(rhs) or rhs, 51 | ---@diagnostic disable-next-line: no-unknown 52 | { silent = true, buffer = self.buffer, expr = opts.expr, desc = opts.desc } 53 | ) 54 | end 55 | 56 | function M.rename() 57 | if pcall(require, "inc_rename") then 58 | return ":IncRename " .. vim.fn.expand "" 59 | else 60 | vim.lsp.buf.rename() 61 | end 62 | end 63 | 64 | function M.diagnostic_goto(next, severity) 65 | local go = next and vim.diagnostic.goto_next or vim.diagnostic.goto_prev 66 | severity = severity and vim.diagnostic.severity[severity] or nil 67 | return function() 68 | go { severity = severity } 69 | end 70 | end 71 | 72 | return M 73 | -------------------------------------------------------------------------------- /lua/plugins/lsp/servers.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local lsp_utils = require "plugins.lsp.utils" 4 | local icons = require "config.icons" 5 | 6 | local function lsp_init() 7 | local signs = { 8 | { name = "DiagnosticSignError", text = icons.diagnostics.Error }, 9 | { name = "DiagnosticSignWarn", text = icons.diagnostics.Warning }, 10 | { name = "DiagnosticSignHint", text = icons.diagnostics.Hint }, 11 | { name = "DiagnosticSignInfo", text = icons.diagnostics.Info }, 12 | } 13 | for _, sign in ipairs(signs) do 14 | vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name }) 15 | end 16 | 17 | -- LSP handlers configuration 18 | local config = { 19 | float = { 20 | focusable = true, 21 | style = "minimal", 22 | border = "rounded", 23 | }, 24 | 25 | diagnostic = { 26 | -- virtual_text = false, 27 | -- virtual_text = { spacing = 4, prefix = "●" }, 28 | virtual_text = { 29 | severity = { 30 | min = vim.diagnostic.severity.ERROR, 31 | }, 32 | }, 33 | signs = { 34 | active = signs, 35 | }, 36 | underline = false, 37 | update_in_insert = false, 38 | severity_sort = true, 39 | float = { 40 | focusable = true, 41 | style = "minimal", 42 | border = "rounded", 43 | source = "always", 44 | header = "", 45 | prefix = "", 46 | }, 47 | -- virtual_lines = true, 48 | }, 49 | } 50 | 51 | -- Diagnostic configuration 52 | vim.diagnostic.config(config.diagnostic) 53 | 54 | -- Hover configuration 55 | -- vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, config.float) 56 | 57 | -- Signature help configuration 58 | -- vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, config.float) 59 | end 60 | 61 | function M.setup(_, opts) 62 | lsp_utils.on_attach(function(client, bufnr) 63 | require("plugins.lsp.format").on_attach(client, bufnr) 64 | require("plugins.lsp.keymaps").on_attach(client, bufnr) 65 | end) 66 | 67 | lsp_init() -- diagnostics, handlers 68 | 69 | local servers = opts.servers 70 | local capabilities = lsp_utils.capabilities() 71 | 72 | local function setup(server) 73 | local server_opts = vim.tbl_deep_extend("force", { 74 | capabilities = capabilities, 75 | }, servers[server] or {}) 76 | 77 | if opts.setup[server] then 78 | if opts.setup[server](server, server_opts) then 79 | return 80 | end 81 | elseif opts.setup["*"] then 82 | if opts.setup["*"](server, server_opts) then 83 | return 84 | end 85 | end 86 | require("lspconfig")[server].setup(server_opts) 87 | end 88 | 89 | -- Add bun for Node.js-based servers 90 | -- local lspconfig_util = require "lspconfig.util" 91 | -- local add_bun_prefix = require("plugins.lsp.bun").add_bun_prefix 92 | -- lspconfig_util.on_setup = lspconfig_util.add_hook_before(lspconfig_util.on_setup, add_bun_prefix) 93 | 94 | -- get all the servers that are available thourgh mason-lspconfig 95 | local has_mason, mlsp = pcall(require, "mason-lspconfig") 96 | local all_mslp_servers = {} 97 | if has_mason then 98 | all_mslp_servers = vim.tbl_keys(require("mason-lspconfig.mappings.server").lspconfig_to_package) 99 | end 100 | 101 | local ensure_installed = {} ---@type string[] 102 | for server, server_opts in pairs(servers) do 103 | if server_opts then 104 | server_opts = server_opts == true and {} or server_opts 105 | -- run manual setup if mason=false or if this is a server that cannot be installed with mason-lspconfig 106 | if server_opts.mason == false or not vim.tbl_contains(all_mslp_servers, server) then 107 | setup(server) 108 | else 109 | ensure_installed[#ensure_installed + 1] = server 110 | end 111 | end 112 | end 113 | 114 | if has_mason then 115 | mlsp.setup { ensure_installed = ensure_installed } 116 | mlsp.setup_handlers { setup } 117 | end 118 | end 119 | 120 | return M 121 | -------------------------------------------------------------------------------- /lua/plugins/lsp/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local loaded = false 4 | local FORMATTING = nil 5 | local DIAGNOSTICS = nil 6 | local COMPLETION = nil 7 | local CODE_ACTION = nil 8 | local HOVER = nil 9 | 10 | local function init() 11 | local nls_methods = require("null-ls").methods 12 | FORMATTING = nls_methods.FORMATTING 13 | DIAGNOSTICS = nls_methods.DIAGNOSTICS 14 | COMPLETION = nls_methods.COMPLETION 15 | CODE_ACTION = nls_methods.CODE_ACTION 16 | HOVER = nls_methods.HOVER 17 | loaded = true 18 | end 19 | 20 | local function list_registered_providers_names(ft) 21 | if not loaded then 22 | init() 23 | end 24 | local s = require "null-ls.sources" 25 | local available_sources = s.get_available(ft) 26 | local registered = {} 27 | for _, source in ipairs(available_sources) do 28 | for method in pairs(source.methods) do 29 | registered[method] = registered[method] or {} 30 | table.insert(registered[method], source.name) 31 | end 32 | end 33 | return registered 34 | end 35 | 36 | function M.list_formatters(ft) 37 | local providers = list_registered_providers_names(ft) 38 | return providers[FORMATTING] or {} 39 | end 40 | 41 | function M.list_linters(ft) 42 | local providers = list_registered_providers_names(ft) 43 | return providers[DIAGNOSTICS] or {} 44 | end 45 | 46 | function M.list_completions(ft) 47 | local providers = list_registered_providers_names(ft) 48 | return providers[COMPLETION] or {} 49 | end 50 | 51 | function M.list_code_actions(ft) 52 | local providers = list_registered_providers_names(ft) 53 | return providers[CODE_ACTION] or {} 54 | end 55 | 56 | function M.list_hovers(ft) 57 | local providers = list_registered_providers_names(ft) 58 | return providers[HOVER] or {} 59 | end 60 | 61 | function M.capabilities() 62 | local capabilities = vim.lsp.protocol.make_client_capabilities() 63 | capabilities.textDocument.completion.completionItem.snippetSupport = true 64 | capabilities.textDocument.foldingRange = { 65 | dynamicRegistration = false, 66 | lineFoldingOnly = true, 67 | } 68 | return require("cmp_nvim_lsp").default_capabilities(capabilities) 69 | end 70 | 71 | function M.on_attach(on_attach) 72 | vim.api.nvim_create_autocmd("LspAttach", { 73 | callback = function(args) 74 | local bufnr = args.buf 75 | local client = vim.lsp.get_client_by_id(args.data.client_id) 76 | on_attach(client, bufnr) 77 | end, 78 | }) 79 | end 80 | 81 | local diagnostics_active = false 82 | 83 | function M.show_diagnostics() 84 | return diagnostics_active 85 | end 86 | 87 | function M.toggle_diagnostics() 88 | diagnostics_active = not diagnostics_active 89 | if diagnostics_active then 90 | vim.diagnostic.show() 91 | else 92 | vim.diagnostic.hide() 93 | end 94 | end 95 | 96 | function M.opts(name) 97 | local plugin = require("lazy.core.config").plugins[name] 98 | if not plugin then 99 | return {} 100 | end 101 | local Plugin = require "lazy.core.plugin" 102 | return Plugin.values(plugin, "opts", false) 103 | end 104 | 105 | return M 106 | -------------------------------------------------------------------------------- /lua/plugins/mini/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local show_dotfiles = true 4 | local mf = require "mini.files" 5 | 6 | function M.map_split(buf_id, lhs, direction) 7 | local rhs = function() 8 | local fsentry = mf.get_fs_entry() 9 | if fsentry.fs_type ~= "file" then 10 | return 11 | end 12 | -- Make new window and set it as target 13 | local new_target_window 14 | vim.api.nvim_win_call(mf.get_target_window(), function() 15 | vim.cmd(direction .. " split") 16 | new_target_window = vim.api.nvim_get_current_win() 17 | end) 18 | 19 | mf.set_target_window(new_target_window) 20 | mf.go_in() 21 | mf.close() 22 | end 23 | 24 | -- Adding `desc` will result into `show_help` entries 25 | local desc = "Split " .. direction 26 | vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc }) 27 | end 28 | 29 | local function filter_show(fs_entry) 30 | return true 31 | end 32 | 33 | local function filter_hide(fs_entry) 34 | return not vim.startswith(fs_entry.name, ".") 35 | end 36 | 37 | function M.toggle_dotfiles() 38 | show_dotfiles = not show_dotfiles 39 | local new_filter = show_dotfiles and filter_show or filter_hide 40 | mf.refresh { content = { filter = new_filter } } 41 | end 42 | 43 | function M.get_current_dir() 44 | local fsentry = mf.get_fs_entry() 45 | if not fsentry then 46 | return nil 47 | end 48 | return vim.fs.dirname(fsentry.path) 49 | end 50 | 51 | function M.files_set_cwd(path) 52 | -- Works only if cursor is on the valid file system entry 53 | local cur_entry_path = mf.get_fs_entry().path 54 | local cur_directory = vim.fs.dirname(cur_entry_path) 55 | vim.fn.chdir(cur_directory) 56 | end 57 | 58 | function M.jump() 59 | require("flash").jump { 60 | search = { 61 | mode = "search", 62 | max_length = 0, 63 | exclude = { 64 | function(win) 65 | return vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "minifiles" 66 | end, 67 | }, 68 | }, 69 | label = { after = { 0, 0 } }, 70 | pattern = "^", 71 | } 72 | end 73 | 74 | function M.file_actions(bufnr) 75 | local cwd = M.get_current_dir() 76 | require("plugins.hydra.file-action").open(cwd, bufnr, function() 77 | mf.close() 78 | end) 79 | end 80 | 81 | function M.folder_actions(bufnr) 82 | local fsentry = mf.get_fs_entry() 83 | if not fsentry then 84 | return nil 85 | end 86 | require("plugins.hydra.folder-action").open(fsentry.path, bufnr, function() 87 | mf.close() 88 | end) 89 | end 90 | 91 | return M 92 | -------------------------------------------------------------------------------- /lua/plugins/motion/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "ggandor/flit.nvim", 4 | enabled = false, 5 | keys = function() 6 | local ret = {} 7 | for _, key in ipairs { "f", "F", "t", "T" } do 8 | ret[#ret + 1] = { key, mode = { "n", "x", "o" }, desc = key } 9 | end 10 | return ret 11 | end, 12 | opts = { labeled_modes = "nx" }, 13 | }, 14 | { 15 | "ggandor/leap.nvim", 16 | enabled = false, 17 | keys = { 18 | { "s", mode = { "n", "x", "o" }, desc = "Leap forward to" }, 19 | { "S", mode = { "n", "x", "o" }, desc = "Leap backward to" }, 20 | { "gs", mode = { "n", "x", "o" }, desc = "Leap from windows" }, 21 | }, 22 | config = function(_, opts) 23 | local leap = require "leap" 24 | for k, v in pairs(opts) do 25 | leap.opts[k] = v 26 | end 27 | leap.add_default_mappings(true) 28 | vim.keymap.del({ "x", "o" }, "x") 29 | vim.keymap.del({ "x", "o" }, "X") 30 | end, 31 | }, 32 | { 33 | "folke/flash.nvim", 34 | event = "VeryLazy", 35 | vscode = true, 36 | opts = {}, 37 | keys = { 38 | { 39 | "s", 40 | mode = { "n", "x", "o" }, 41 | function() 42 | require("flash").jump() 43 | end, 44 | desc = "Flash", 45 | }, 46 | { 47 | "S", 48 | mode = { "n", "o", "x" }, 49 | function() 50 | require("flash").treesitter() 51 | end, 52 | desc = "Flash Treesitter", 53 | }, 54 | { 55 | "r", 56 | mode = "o", 57 | function() 58 | require("flash").remote() 59 | end, 60 | desc = "Remote Flash", 61 | }, 62 | { 63 | "R", 64 | mode = { "o", "x" }, 65 | function() 66 | require("flash").treesitter_search() 67 | end, 68 | desc = "Treesitter Search", 69 | }, 70 | }, 71 | }, 72 | { 73 | "abecodes/tabout.nvim", 74 | enabled = false, 75 | event = "InsertEnter", 76 | dependencies = { 77 | "nvim-treesitter/nvim-treesitter", 78 | "hrsh7th/nvim-cmp", 79 | }, 80 | config = true, 81 | }, 82 | { 83 | "ThePrimeagen/harpoon", 84 | --stylua: ignore 85 | keys = { 86 | { "ja", function() require("harpoon.mark").add_file() end, desc = "Add File" }, 87 | { "jm", function() require("harpoon.ui").toggle_quick_menu() end, desc = "File Menu" }, 88 | { "jc", function() require("harpoon.cmd-ui").toggle_quick_menu() end, desc = "Command Menu" }, 89 | { "1", function() require("harpoon.ui").nav_file(1) end, desc = "File 1" }, 90 | { "2", function() require("harpoon.ui").nav_file(2) end, desc = "File 2" }, 91 | { "3", function() require("harpoon.term").gotoTerminal(1) end, desc = "Terminal 1" }, 92 | { "4", function() require("harpoon.term").gotoTerminal(2) end, desc = "Terminal 2" }, 93 | { "5", function() require("harpoon.term").sendCommand(1,1) end, desc = "Command 1" }, 94 | { "6", function() require("harpoon.term").sendCommand(1,2) end, desc = "Command 2" }, 95 | }, 96 | opts = { 97 | global_settings = { 98 | save_on_toggle = true, 99 | enter_on_sendcmd = true, 100 | }, 101 | }, 102 | }, 103 | { "chentoast/marks.nvim", event = "BufReadPre", opts = {} }, 104 | { 105 | "LeonHeidelbach/trailblazer.nvim", 106 | enabled = false, 107 | keys = { 108 | "", 109 | { "ma", require("plugins.motion.utils").add_trail_mark_stack, desc = "TrailBlazer: Add Stack" }, 110 | { 111 | "md", 112 | require("plugins.motion.utils").delete_trail_mark_stack, 113 | desc = "TrailBlazer: Delete Stack", 114 | }, 115 | { 116 | "mg", 117 | function() 118 | require("plugins.motion.utils").get_available_stacks(true) 119 | end, 120 | desc = "TrailBlazer: Get Stacks", 121 | }, 122 | { 123 | "ms", 124 | "TrailBlazerSaveSession", 125 | desc = "TrailBlazer: Save Session", 126 | }, 127 | { 128 | "ml", 129 | "TrailBlazerLoadSession", 130 | desc = "Trailblazer: Load Session", 131 | }, 132 | }, 133 | opts = function() 134 | local bookmark = require("config.icons").ui.BookMark 135 | return { 136 | auto_save_trailblazer_state_on_exit = true, 137 | auto_load_trailblazer_state_on_enter = false, 138 | trail_mark_symbol_line_indicators_enabled = true, 139 | trail_options = { 140 | newest_mark_symbol = bookmark, 141 | cursor_mark_symbol = bookmark, 142 | next_mark_symbol = bookmark, 143 | previous_mark_symbol = bookmark, 144 | number_line_color_enabled = false, 145 | }, 146 | mappings = { 147 | nv = { 148 | motions = { 149 | peek_move_next_down = "", 150 | peek_move_previous_up = "", 151 | }, 152 | }, 153 | }, 154 | } 155 | end, 156 | }, 157 | } 158 | -------------------------------------------------------------------------------- /lua/plugins/motion/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | local fmt = string.format 3 | local find_string = require("utils").find_string 4 | 5 | function M.get_available_stacks(notify) 6 | local available_stacks = require("trailblazer.trails").stacks.get_sorted_stack_names() 7 | if notify then 8 | vim.notify(fmt("Available stacks: %s", table.concat(available_stacks, ", ")), "info", { title = "TrailBlazer" }) 9 | end 10 | return available_stacks 11 | end 12 | 13 | function M.add_trail_mark_stack() 14 | vim.ui.input({ prompt = "stack name: " }, function(name) 15 | if not name then 16 | return 17 | end 18 | local available_stacks = M.get_available_stacks() 19 | if find_string(available_stacks, name) then 20 | vim.notify(fmt('"%s" stack already exists.', name), "warn", { title = "TrailBlazer" }) 21 | return 22 | end 23 | local tb = require "trailblazer" 24 | tb.add_trail_mark_stack(name) 25 | vim.notify(fmt('"%s" stack created.', name), "info", { title = "TrailBlazer" }) 26 | end) 27 | end 28 | 29 | function M.delete_trail_mark_stack() 30 | vim.ui.input({ prompt = "stack name: " }, function(name) 31 | if not name then 32 | return 33 | end 34 | local available_stacks = M.get_available_stacks() 35 | if not find_string(available_stacks, name) then 36 | vim.notify(fmt('"%s" stack does not exist.', name), "warn", { title = "TrailBlazer" }) 37 | return 38 | end 39 | local tb = require "trailblazer" 40 | tb.delete_trail_mark_stack(name) 41 | vim.notify(fmt('"%s" stack deleted.', name), "info", { title = "TrailBlazer" }) 42 | end) 43 | end 44 | 45 | return M 46 | -------------------------------------------------------------------------------- /lua/plugins/navbuddy.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "neovim/nvim-lspconfig", 4 | dependencies = { 5 | { 6 | "SmiteshP/nvim-navbuddy", 7 | dependencies = { 8 | "neovim/nvim-lspconfig", 9 | "SmiteshP/nvim-navic", 10 | "MunifTanjim/nui.nvim", 11 | }, 12 | opts = { lsp = { auto_attach = true } }, 13 | }, 14 | }, 15 | --stylua: ignore 16 | keys = { 17 | { "vO", function() require("nvim-navbuddy").open() end, desc = "Code Outline (navbuddy)", }, 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /lua/plugins/neogen.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "danymat/neogen", 3 | opts = { 4 | snippet_engine = "luasnip", 5 | enabled = true, 6 | languages = { 7 | lua = { 8 | template = { 9 | annotation_convention = "ldoc", 10 | }, 11 | }, 12 | python = { 13 | template = { 14 | annotation_convention = "google_docstrings", 15 | }, 16 | }, 17 | rust = { 18 | template = { 19 | annotation_convention = "rustdoc", 20 | }, 21 | }, 22 | javascript = { 23 | template = { 24 | annotation_convention = "jsdoc", 25 | }, 26 | }, 27 | typescript = { 28 | template = { 29 | annotation_convention = "tsdoc", 30 | }, 31 | }, 32 | typescriptreact = { 33 | template = { 34 | annotation_convention = "tsdoc", 35 | }, 36 | }, 37 | }, 38 | }, 39 | --stylua: ignore 40 | keys = { 41 | { "lgd", function() require("neogen").generate() end, desc = "Annotation", }, 42 | { "lgc", function() require("neogen").generate { type = "class" } end, desc = "Class", }, 43 | { "lgf", function() require("neogen").generate { type = "func" } end, desc = "Function", }, 44 | { "lgt", function() require("neogen").generate { type = "type" } end, desc = "Type", }, 45 | }, 46 | } 47 | -------------------------------------------------------------------------------- /lua/plugins/neovim-project.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "coffebar/neovim-project", 3 | enabled = false, 4 | event = "VeryLazy", 5 | opts = { 6 | projects = { 7 | "~/workspace/alpha2phi/*", 8 | "~/workspace/platform/*", 9 | "~/workspace/temp/*", 10 | "~/workspace/software/*", 11 | }, 12 | }, 13 | init = function() 14 | vim.opt.sessionoptions:append "globals" 15 | end, 16 | dependencies = { 17 | { "nvim-lua/plenary.nvim" }, 18 | { "nvim-telescope/telescope.nvim" }, 19 | { "Shatur/neovim-session-manager" }, 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /lua/plugins/notes/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { "itchyny/calendar.vim", cmd = { "Calendar" } }, 3 | { "folke/twilight.nvim", config = true, cmd = { "Twilight", "TwilightEnable", "TwilightDisable" } }, 4 | { "folke/zen-mode.nvim", config = true, cmd = { "ZenMode" } }, 5 | { "dhruvasagar/vim-table-mode", ft = { "markdown", "org", "norg" } }, 6 | { "lukas-reineke/headlines.nvim", config = true, ft = { "markdown", "org", "norg" } }, 7 | { 8 | "jbyuki/nabla.nvim", 9 | --stylua: ignore 10 | keys = { 11 | { "nN", function() require("nabla").popup() end, desc = "Notation", }, 12 | }, 13 | config = function() 14 | require("nabla").enable_virt() 15 | end, 16 | }, 17 | { 18 | "vim-pandoc/vim-pandoc", 19 | event = "VeryLazy", 20 | enabled = false, 21 | dependencies = { "vim-pandoc/vim-pandoc-syntax" }, 22 | }, 23 | { 24 | "frabjous/knap", 25 | init = function() 26 | -- Configure vim.g.knap_settings 27 | end, 28 | --stylua: ignore 29 | keys = { 30 | { "np", function() require("knap").process_once() end, desc = "Preview", }, 31 | { "nc", function() require("knap").close_viewer() end, desc = "Close Preview", }, 32 | { "nt", function() require("knap").close_viewer() end, desc = "Toggle Preview", }, 33 | { "nj", function() require("knap").forward_jump() end, desc = "Forward jump", }, 34 | { "nn", function() require("utils").launch_notepad() end, desc = "Temporary Notepad", }, 35 | }, 36 | ft = { "markdown", "tex" }, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /lua/plugins/notes/latex.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "neovim/nvim-lspconfig", 4 | opts = { 5 | servers = { 6 | texlab = {}, 7 | ltex = { filetypes = { "tex", "pandoc", "bib" } }, 8 | }, 9 | }, 10 | }, 11 | { 12 | "lervag/vimtex", 13 | ft = { "tex" }, 14 | opts = { patterns = { "*.tex" } }, 15 | config = function(_, opts) 16 | vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, { 17 | pattern = opts.patterns, 18 | callback = function() 19 | vim.cmd [[VimtexCompile]] 20 | end, 21 | }) 22 | 23 | -- Live compilation 24 | vim.g.vimtex_compiler_latexmk = { 25 | build_dir = ".out", 26 | options = { 27 | "-shell-escape", 28 | "-verbose", 29 | "-file-line-error", 30 | "-interaction=nonstopmode", 31 | "-synctex=1", 32 | }, 33 | } 34 | vim.g.vimtex_view_method = "sioyek" 35 | vim.g.vimtex_fold_enabled = true 36 | vim.g.vimtex_syntax_conceal = { 37 | accents = 1, 38 | ligatures = 1, 39 | cites = 1, 40 | fancy = 1, 41 | spacing = 0, -- default: 1 42 | greek = 1, 43 | math_bounds = 1, 44 | math_delimiters = 1, 45 | math_fracs = 1, 46 | math_super_sub = 1, 47 | math_symbols = 1, 48 | sections = 0, 49 | styles = 1, 50 | } 51 | end, 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /lua/plugins/notes/markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "jakewvincent/mkdnflow.nvim", 4 | ft = { "markdown" }, 5 | rocks = "luautf8", 6 | opts = {}, 7 | enabled = false, 8 | }, 9 | { "AckslD/nvim-FeMaco.lua", ft = { "markdown" }, opts = {} }, 10 | { 11 | "iamcco/markdown-preview.nvim", 12 | ft = { "markdown" }, 13 | build = "cd app && npm install", 14 | init = function() 15 | vim.g.mkdp_filetypes = { "markdown" } 16 | end, 17 | }, 18 | { "mzlogin/vim-markdown-toc", ft = { "markdown" } }, 19 | { 20 | "renerocksai/telekasten.nvim", 21 | dependencies = { "nvim-telescope/telescope.nvim" }, 22 | opts = { 23 | home = vim.env.HOME .. "/zettelkasten", 24 | }, 25 | enabled = false, 26 | ft = { "markdown" }, 27 | }, 28 | { 29 | "epwalsh/obsidian.nvim", 30 | opts = { 31 | dir = vim.env.HOME .. "/obsidian", 32 | completion = { 33 | nvim_cmp = true, 34 | }, 35 | }, 36 | enabled = false, 37 | ft = { "markdown" }, 38 | }, 39 | { "ellisonleao/glow.nvim", config = true, cmd = "Glow", enabled = true }, 40 | { "toppair/peek.nvim", config = true, ft = { "markdown" }, enabled = false, build = "deno task --quiet build:fast" }, 41 | -- glow.nvim 42 | -- https://github.com/rockerBOO/awesome-neovim#markdown-and-latex 43 | } 44 | -------------------------------------------------------------------------------- /lua/plugins/notes/norg.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "nvim-neorg/neorg", 4 | enabled = false, 5 | ft = { "norg" }, 6 | build = ":Neorg sync-parsers", 7 | opts = { 8 | load = { 9 | ["core.defaults"] = {}, -- Loads default behaviour 10 | ["core.norg.concealer"] = {}, -- Adds pretty icons to your documents 11 | ["core.norg.qol.toc"] = {}, 12 | ["core.norg.dirman"] = { -- Manages Neorg workspaces 13 | config = { 14 | workspaces = { 15 | notes = vim.env.HOME .. "/norg-notes/", 16 | }, 17 | }, 18 | }, 19 | ["core.presenter"] = { 20 | config = { 21 | zen_mode = "zen-mode", 22 | }, 23 | }, 24 | }, 25 | }, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /lua/plugins/notes/orgmode.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "nvim-orgmode/orgmode", 4 | enabled = false, 5 | ft = { "org" }, 6 | opts = { 7 | org_agenda_files = { vim.env.HOME .. "/org-notes/agenda/*" }, 8 | org_default_notes_file = vim.env.HOME .. "/org-notes/default.org", 9 | }, 10 | config = function(plugin, opts) 11 | require("orgmode").setup_ts_grammar() 12 | require("orgmode").setup(opts) 13 | end, 14 | }, 15 | { "akinsho/org-bullets.nvim", enabled = false, config = true, ft = { "org" } }, 16 | } 17 | -------------------------------------------------------------------------------- /lua/plugins/nvim-devdocs.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "luckasRanarison/nvim-devdocs", 3 | enabled = false, 4 | dependencies = { 5 | "nvim-lua/plenary.nvim", 6 | "nvim-telescope/telescope.nvim", 7 | "nvim-treesitter/nvim-treesitter", 8 | }, 9 | opts = {}, 10 | cmd = { 11 | "DevdocsFetch", 12 | "DevdocsInstall", 13 | "DevdocsUninstall", 14 | "DevdocsOpen", 15 | "DevdocsOpenFloat", 16 | "DevdocsOpenCurrent", 17 | "DevdocsOpenCurrentFloat", 18 | "DevdocsUpdate", 19 | "DevdocsUpdateAll", 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /lua/plugins/nvim-traveller.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "norlock/nvim-traveller", 3 | enabled = false, 4 | event = "VeryLazy", 5 | opts = {}, 6 | } 7 | -------------------------------------------------------------------------------- /lua/plugins/nvim-tree.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-tree/nvim-tree.lua", 3 | enabled = false, 4 | cmd = { "NvimTreeToggle" }, 5 | keys = { 6 | { "fe", "NvimTreeToggle", desc = "Explorer" }, 7 | }, 8 | opts = { 9 | disable_netrw = false, 10 | hijack_netrw = true, 11 | respect_buf_cwd = true, 12 | view = { 13 | number = true, 14 | relativenumber = true, 15 | }, 16 | filters = { 17 | custom = { ".git" }, 18 | }, 19 | sync_root_with_cwd = true, 20 | update_focused_file = { 21 | enable = true, 22 | update_root = true, 23 | }, 24 | actions = { 25 | open_file = { 26 | quit_on_open = true, 27 | }, 28 | }, 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /lua/plugins/nvim-ufo.lua: -------------------------------------------------------------------------------- 1 | local handler = function(virtText, lnum, endLnum, width, truncate) 2 | local newVirtText = {} 3 | local totalLines = vim.api.nvim_buf_line_count(0) 4 | local foldedLines = endLnum - lnum 5 | local suffix = ("  %d %d%%"):format(foldedLines, foldedLines / totalLines * 100) 6 | local sufWidth = vim.fn.strdisplaywidth(suffix) 7 | local targetWidth = width - sufWidth 8 | local curWidth = 0 9 | for _, chunk in ipairs(virtText) do 10 | local chunkText = chunk[1] 11 | local chunkWidth = vim.fn.strdisplaywidth(chunkText) 12 | if targetWidth > curWidth + chunkWidth then 13 | table.insert(newVirtText, chunk) 14 | else 15 | chunkText = truncate(chunkText, targetWidth - curWidth) 16 | local hlGroup = chunk[2] 17 | table.insert(newVirtText, { chunkText, hlGroup }) 18 | chunkWidth = vim.fn.strdisplaywidth(chunkText) 19 | -- str width returned from truncate() may less than 2nd argument, need padding 20 | if curWidth + chunkWidth < targetWidth then 21 | suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) 22 | end 23 | break 24 | end 25 | curWidth = curWidth + chunkWidth 26 | end 27 | local rAlignAppndx = math.max(math.min(vim.opt.textwidth["_value"], width - 1) - curWidth - sufWidth, 0) 28 | suffix = (" "):rep(rAlignAppndx) .. suffix 29 | table.insert(newVirtText, { suffix, "MoreMsg" }) 30 | return newVirtText 31 | end 32 | 33 | return { 34 | { 35 | "kevinhwang91/nvim-ufo", 36 | dependencies = { 37 | "kevinhwang91/promise-async", 38 | { 39 | "luukvbaal/statuscol.nvim", 40 | config = function() 41 | local builtin = require "statuscol.builtin" 42 | require("statuscol").setup { 43 | relculright = true, 44 | segments = { 45 | { text = { builtin.foldfunc }, click = "v:lua.ScFa" }, 46 | { text = { "%s" }, click = "v:lua.ScSa" }, 47 | { text = { builtin.lnumfunc, " " }, click = "v:lua.ScLa" }, 48 | }, 49 | } 50 | end, 51 | }, 52 | }, 53 | --stylua: ignore 54 | keys = { 55 | { "zc" }, 56 | { "zo" }, 57 | { "zC" }, 58 | { "zO" }, 59 | { "za" }, 60 | { "zA" }, 61 | { "zr", function() require("ufo").openFoldsExceptKinds() end, desc = "Open Folds Except Kinds", }, 62 | { "zR", function() require("ufo").openAllFolds() end, desc = "Open All Folds", }, 63 | { "zM", function() require("ufo").closeAllFolds() end, desc = "Close All Folds", }, 64 | { "zm", function() require("ufo").closeFoldsWith() end, desc = "Close Folds With", }, 65 | { "zp", function() 66 | local winid = require('ufo').peekFoldedLinesUnderCursor() 67 | if not winid then 68 | vim.lsp.buf.hover() 69 | end 70 | end, desc = "Peek Fold", }, 71 | }, 72 | opts = { 73 | fold_virt_text_handler = handler, 74 | }, 75 | config = function(_, opts) 76 | require("ufo").setup(opts) 77 | end, 78 | }, 79 | } 80 | -------------------------------------------------------------------------------- /lua/plugins/portal.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "cbochs/portal.nvim", 4 | keys = { 5 | { "", "Portal jumplist backward", desc = "Jump Backward" }, 6 | { "", "Portal jumplist forward", desc = "Jump Forward" }, 7 | { "g;", "Portal changelist backward", desc = "Change Backward" }, 8 | { "g,", "Portal changelist forward", desc = "Change Forward" }, 9 | }, 10 | dependencies = { 11 | "cbochs/grapple.nvim", 12 | "ThePrimeagen/harpoon", 13 | }, 14 | enabled = false, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /lua/plugins/refactoring.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "ThePrimeagen/refactoring.nvim", 4 | dependencies = { 5 | "nvim-lua/plenary.nvim", 6 | "nvim-treesitter/nvim-treesitter", 7 | }, 8 | opts = {}, 9 | config = function(_, opts) 10 | require("refactoring").setup(opts) 11 | require("telescope").load_extension "refactoring" 12 | end, 13 | -- stylua: ignore 14 | keys = { 15 | { "rs", function() require("telescope").extensions.refactoring.refactors() end, mode = { "v" }, desc = "Refactor", }, 16 | { "ri", function() require("refactoring").refactor("Inline Variable") end, mode = {"n","v"}, desc = "Inline Variable" }, 17 | { "rb", function() require('refactoring').refactor('Exract Block') end, mode = {"n"}, desc = "Extract Block" }, 18 | { "rf", function() require('refactoring').refactor('Exract Block To File') end, mode = {"n"}, desc = "Extract Block to File" }, 19 | { "rP", function() require('refactoring').debug.printf({below = false}) end, mode = {"n"}, desc = "Debug Print" }, 20 | { "rp", function() require('refactoring').debug.print_var({normal = true}) end, mode = {"n"}, desc = "Debug Print Variable" }, 21 | { "rc", function() require('refactoring').debug.cleanup({}) end, mode = {"n"}, desc = "Debug Cleanup" }, 22 | { "rf", function() require('refactoring').refactor('Extract Function') end, mode = {"v"}, desc = "Extract Function" }, 23 | { "rF", function() require('refactoring').refactor('Extract Function to File') end, mode = {"v"}, desc = "Extract Function to File" }, 24 | { "rx", function() require('refactoring').refactor('Extract Variable') end, mode = {"v"}, desc = "Extract Variable" }, 25 | { "rp", function() require('refactoring').debug.print_var({}) end, mode = {"v"}, desc = "Debug Print Variable" }, 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /lua/plugins/replacer.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "gabrielpoca/replacer.nvim", 3 | opts = {}, 4 | keys = { 5 | { 6 | "rr", 7 | function() 8 | require("replacer").run() 9 | end, 10 | desc = "Replacer", 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /lua/plugins/rgflow.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "mangelozzi/nvim-rgflow.lua", 3 | enabled = false, 4 | event = "VeryLazy", 5 | config = function() 6 | require("rgflow").setup { 7 | default_trigger_mappings = true, 8 | default_ui_mappings = true, 9 | default_quickfix_mappings = true, 10 | 11 | -- WARNING !!! Glob for '-g *{*}' will not use .gitignore file: https://github.com/BurntSushi/ripgrep/issues/2252 12 | cmd_flags = ( 13 | "--smart-case -g *.{*,py} -g !*.{min.js,pyc} --fixed-strings --no-fixed-strings --no-ignore -M 500" 14 | -- Exclude globs 15 | .. " -g !**/.angular/" 16 | .. " -g !**/node_modules/" 17 | .. " -g !**/static/*/jsapp/" 18 | .. " -g !**/static/*/wcapp/" 19 | ), 20 | } 21 | end, 22 | } 23 | -------------------------------------------------------------------------------- /lua/plugins/satellite.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "lewis6991/satellite.nvim", 3 | enabled = function() 4 | return vim.fn.has "nvim-0.10.0" == 1 5 | end, 6 | event = { "BufReadPre" }, 7 | opts = {}, 8 | } 9 | -------------------------------------------------------------------------------- /lua/plugins/search/init.lua: -------------------------------------------------------------------------------- 1 | local fn = vim.fn 2 | 3 | function _G.qftf(info) 4 | local items 5 | local ret = {} 6 | -- The name of item in list is based on the directory of quickfix window. 7 | -- Change the directory for quickfix window make the name of item shorter. 8 | -- It's a good opportunity to change current directory in quickfixtextfunc :) 9 | -- 10 | -- local alterBufnr = fn.bufname('#') -- alternative buffer is the buffer before enter qf window 11 | -- local root = getRootByAlterBufnr(alterBufnr) 12 | -- vim.cmd(('noa lcd %s'):format(fn.fnameescape(root))) 13 | -- 14 | if info.quickfix == 1 then 15 | items = fn.getqflist({ id = info.id, items = 0 }).items 16 | else 17 | items = fn.getloclist(info.winid, { id = info.id, items = 0 }).items 18 | end 19 | local limit = 31 20 | local fnameFmt1, fnameFmt2 = "%-" .. limit .. "s", "…%." .. (limit - 1) .. "s" 21 | local validFmt = "%s │%5d:%-3d│%s %s" 22 | for i = info.start_idx, info.end_idx do 23 | local e = items[i] 24 | local fname = "" 25 | local str 26 | if e.valid == 1 then 27 | if e.bufnr > 0 then 28 | fname = fn.bufname(e.bufnr) 29 | if fname == "" then 30 | fname = "[No Name]" 31 | else 32 | fname = fname:gsub("^" .. vim.env.HOME, "~") 33 | end 34 | -- char in fname may occur more than 1 width, ignore this issue in order to keep performance 35 | if #fname <= limit then 36 | fname = fnameFmt1:format(fname) 37 | else 38 | fname = fnameFmt2:format(fname:sub(1 - limit)) 39 | end 40 | end 41 | local lnum = e.lnum > 99999 and -1 or e.lnum 42 | local col = e.col > 999 and -1 or e.col 43 | local qtype = e.type == "" and "" or " " .. e.type:sub(1, 1):upper() 44 | str = validFmt:format(fname, lnum, col, qtype, e.text) 45 | else 46 | str = e.text 47 | end 48 | table.insert(ret, str) 49 | end 50 | return ret 51 | end 52 | 53 | vim.o.qftf = "{info -> v:lua._G.qftf(info)}" 54 | 55 | return { 56 | { 57 | "nvim-pack/nvim-spectre", 58 | -- stylua: ignore 59 | keys = { 60 | { "sr", function() require("spectre").open() end, desc = "Search and Replace (Spectre)" }, 61 | }, 62 | }, 63 | { 64 | "kevinhwang91/nvim-bqf", 65 | opts = { 66 | filter = { 67 | fzf = { 68 | extra_opts = { "--bind", "ctrl-o:toggle-all", "--delimiter", "│" }, 69 | }, 70 | }, 71 | }, 72 | ft = "qf", 73 | }, 74 | { 75 | "kevinhwang91/nvim-hlslens", 76 | keys = { 77 | { "n", [[execute('normal! ' . v:count1 . 'n')lua require('hlslens').start()]] }, 78 | { "N", [[execute('normal! ' . v:count1 . 'N')lua require('hlslens').start()]] }, 79 | { "*", [[*lua require('hlslens').start()]] }, 80 | { "#", [[#lua require('hlslens').start()]] }, 81 | { "g*", [[g*lua require('hlslens').start()]] }, 82 | { "g#", [[g#lua require('hlslens').start()]] }, 83 | }, 84 | config = function() 85 | require("hlslens").setup() 86 | end, 87 | }, 88 | { 89 | "cshuaimin/ssr.nvim", 90 | opts = { 91 | border = "rounded", 92 | min_width = 50, 93 | min_height = 5, 94 | max_width = 120, 95 | max_height = 25, 96 | keymaps = { 97 | close = "q", 98 | next_match = "n", 99 | prev_match = "N", 100 | replace_confirm = "", 101 | replace_all = "", 102 | }, 103 | }, 104 | --stylua: ignore 105 | keys = { 106 | { "sR", function() require("ssr").open() end, mode = {"n", "x"}, desc = "Search and Replace (SSR)" }, 107 | }, 108 | }, 109 | { 110 | "AckslD/muren.nvim", 111 | event = "VeryLazy", 112 | enabled = false, 113 | config = true, 114 | }, 115 | } 116 | -------------------------------------------------------------------------------- /lua/plugins/sniprun.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "michaelb/sniprun", 4 | enabled = false, 5 | build = "bash ./install.sh", 6 | opts = { 7 | display = { "Terminal" }, 8 | live_display = { "VirtualTextOk", "TerminalOk" }, 9 | selected_interpreters = { "Python3_fifo" }, 10 | repl_enable = { "Python3_fifo" }, 11 | }, 12 | config = function(_, opts) 13 | require("sniprun").setup(opts) 14 | end, 15 | --stylua: ignore 16 | keys = { 17 | { "xA", function() require("sniprun.api").run_range(1, vim.fn.line("$")) end, desc = "All", }, 18 | { "xC", function() require("sniprun.display").close_all() end, desc = "Close", }, 19 | { "xc", function() require("sniprun").run() end, desc = "Current"}, 20 | { "xi", function() require("sniprun").info() end, desc = "Info", }, 21 | { "xl", function() require("sniprun.live_mode").toggle() end, desc = "Live Mode", }, 22 | { "xp", function() require("sniprun").clear_repl() end, desc = "Clear REPL", }, 23 | { "xr", function() require("sniprun").reset() end, desc = "Reset", }, 24 | { "xs", function() require("sniprun").run("v") end, mode = {"v"}, desc = "Selection", }, 25 | }, 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /lua/plugins/statusline/components.lua: -------------------------------------------------------------------------------- 1 | local icons = require "config.icons" 2 | local Job = require "plenary.job" 3 | local Utils = require "utils" 4 | 5 | return { 6 | spaces = { 7 | function() 8 | local shiftwidth = vim.api.nvim_get_option_value("shiftwidth", { buf = 0 }) 9 | return icons.ui.Tab .. " " .. shiftwidth 10 | end, 11 | padding = 1, 12 | }, 13 | git_repo = { 14 | function() 15 | local results = {} 16 | local job = Job:new { 17 | command = "git", 18 | args = { "rev-parse", "--show-toplevel" }, 19 | cwd = vim.fn.expand "%:p:h", 20 | on_stdout = function(_, line) 21 | table.insert(results, line) 22 | end, 23 | } 24 | job:sync() 25 | if results[1] ~= nil then 26 | return vim.fn.fnamemodify(results[1], ":t") 27 | else 28 | return "" 29 | end 30 | end, 31 | }, 32 | separator = { 33 | function() 34 | return "%=" 35 | end, 36 | }, 37 | diff = { 38 | "diff", 39 | source = function() 40 | local gitsigns = vim.b.gitsigns_status_dict 41 | if gitsigns then 42 | return { 43 | added = gitsigns.added, 44 | modified = gitsigns.changed, 45 | removed = gitsigns.removed, 46 | } 47 | end 48 | end, 49 | }, 50 | diagnostics = { 51 | "diagnostics", 52 | sources = { "nvim_diagnostic" }, 53 | diagnostics_color = { 54 | error = "DiagnosticError", 55 | warn = "DiagnosticWarn", 56 | info = "DiagnosticInfo", 57 | hint = "DiagnosticHint", 58 | }, 59 | colored = true, 60 | }, 61 | lsp_client = { 62 | function(msg) 63 | msg = msg or "" 64 | local buf_clients = vim.lsp.get_active_clients { bufnr = 0 } 65 | 66 | if next(buf_clients) == nil then 67 | if type(msg) == "boolean" or #msg == 0 then 68 | return "" 69 | end 70 | return msg 71 | end 72 | 73 | local buf_ft = vim.bo.filetype 74 | local buf_client_names = {} 75 | 76 | -- add client 77 | for _, client in pairs(buf_clients) do 78 | if client.name ~= "null-ls" then 79 | table.insert(buf_client_names, client.name) 80 | end 81 | end 82 | 83 | -- add formatter 84 | local lsp_utils = require "plugins.lsp.utils" 85 | local formatters = lsp_utils.list_formatters(buf_ft) 86 | vim.list_extend(buf_client_names, formatters) 87 | 88 | -- add linter 89 | local linters = lsp_utils.list_linters(buf_ft) 90 | vim.list_extend(buf_client_names, linters) 91 | 92 | -- add hover 93 | local hovers = lsp_utils.list_hovers(buf_ft) 94 | vim.list_extend(buf_client_names, hovers) 95 | 96 | -- add code action 97 | local code_actions = lsp_utils.list_code_actions(buf_ft) 98 | vim.list_extend(buf_client_names, code_actions) 99 | 100 | local hash = {} 101 | local client_names = {} 102 | for _, v in ipairs(buf_client_names) do 103 | if not hash[v] then 104 | client_names[#client_names + 1] = v 105 | hash[v] = true 106 | end 107 | end 108 | table.sort(client_names) 109 | return icons.ui.Code .. " " .. table.concat(client_names, ", ") .. " " .. icons.ui.Code 110 | end, 111 | -- icon = icons.ui.Code, 112 | colored = true, 113 | on_click = function() 114 | vim.cmd [[LspInfo]] 115 | end, 116 | }, 117 | noice_mode = { 118 | function() 119 | return require("noice").api.status.mode.get() 120 | end, 121 | cond = function() 122 | return package.loaded["noice"] and require("noice").api.status.mode.has() 123 | end, 124 | color = Utils.fg "Constant", 125 | }, 126 | noice_command = { 127 | function() 128 | return require("noice").api.status.command.get() 129 | end, 130 | cond = function() 131 | return package.loaded["noice"] and require("noice").api.status.command.has() 132 | end, 133 | color = Utils.fg "Statement", 134 | }, 135 | battery = { 136 | function() 137 | local enabled = require("pigeon.config").options.battery.enabled 138 | local battery = require("pigeon.battery").battery() 139 | 140 | if enabled then 141 | return battery 142 | else 143 | return "" 144 | end 145 | end, 146 | colored = true, 147 | }, 148 | } 149 | -------------------------------------------------------------------------------- /lua/plugins/statusline/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "nvim-lualine/lualine.nvim", 4 | dependencies = { 5 | "meuter/lualine-so-fancy.nvim", 6 | { "Pheon-Dev/pigeon", opts = {} }, 7 | }, 8 | event = "VeryLazy", 9 | opts = function() 10 | local components = require "plugins.statusline.components" 11 | return { 12 | options = { 13 | icons_enabled = true, 14 | theme = "auto", 15 | component_separators = {}, 16 | section_separators = {}, 17 | disabled_filetypes = { 18 | statusline = { "dashboard", "alpha", "lazy", "fugitive" }, 19 | winbar = { 20 | "help", 21 | "alpha", 22 | "lazy", 23 | }, 24 | }, 25 | always_divide_middle = true, 26 | globalstatus = true, 27 | }, 28 | sections = { 29 | lualine_a = { { "fancy_mode", width = 3 } }, 30 | lualine_b = { components.git_repo, "branch" }, 31 | lualine_c = { 32 | "filename", 33 | { "fancy_cwd", substitute_home = true }, 34 | components.diff, 35 | { "fancy_diagnostics" }, 36 | components.noice_command, 37 | components.noice_mode, 38 | -- { require("NeoComposer.ui").status_recording }, 39 | components.separator, 40 | components.lsp_client, 41 | }, 42 | lualine_x = { components.battery, components.spaces, "encoding", "fileformat", "filetype", "progress" }, 43 | lualine_y = {}, 44 | lualine_z = { "location" }, 45 | }, 46 | inactive_sections = { 47 | lualine_a = {}, 48 | lualine_b = {}, 49 | lualine_c = { "filename" }, 50 | lualine_x = { "location" }, 51 | lualine_y = {}, 52 | lualine_z = {}, 53 | }, 54 | extensions = { "nvim-tree", "toggleterm", "quickfix" }, 55 | } 56 | end, 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /lua/plugins/telescope/pickers.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local pickers = require "telescope.pickers" 4 | local Path = require "plenary.path" 5 | local action_set = require "telescope.actions.set" 6 | local action_state = require "telescope.actions.state" 7 | local transform_mod = require("telescope.actions.mt").transform_mod 8 | local actions = require "telescope.actions" 9 | local conf = require("telescope.config").values 10 | local finders = require "telescope.finders" 11 | local make_entry = require "telescope.make_entry" 12 | local os_sep = Path.path.sep 13 | local scan = require "plenary.scandir" 14 | 15 | ---Keep track of the active extension and folders for `live_grep` 16 | local live_grep_filters = { 17 | ---@type nil|string 18 | extension = nil, 19 | ---@type nil|string[] 20 | directories = nil, 21 | } 22 | 23 | local function run_live_grep(current_input) 24 | require("telescope.builtin").live_grep { 25 | additional_args = live_grep_filters.extension and function() 26 | return { "-g", "*." .. live_grep_filters.extension } 27 | end, 28 | search_dirs = live_grep_filters.directories, 29 | -- default_text = current_input, 30 | } 31 | end 32 | 33 | function M.git_diff_picker(opts) 34 | opts = opts or require("telescope.themes").get_dropdown {} 35 | local list = vim.fn.systemlist "git diff --name-only" 36 | pickers.new(opts, { prompt_title = "Git Diff Files", finder = finders.new_table { results = list }, sorter = conf.generic_sorter(opts) }):find() 37 | end 38 | 39 | M.actions = transform_mod { 40 | 41 | set_extension = function(prompt_bufnr) 42 | local current_input = action_state.get_current_line() 43 | vim.ui.input({ prompt = "*." }, function(input) 44 | if input == nil then 45 | return 46 | end 47 | live_grep_filters.extension = input 48 | actions.close(prompt_bufnr) 49 | run_live_grep(current_input) 50 | end) 51 | end, 52 | 53 | set_folders = function(prompt_bufnr) 54 | local current_input = action_state.get_current_line() 55 | local data = {} 56 | scan.scan_dir(vim.loop.cwd(), { 57 | hidden = true, 58 | only_dirs = true, 59 | respect_gitignore = true, 60 | on_insert = function(entry) 61 | table.insert(data, entry .. os_sep) 62 | end, 63 | }) 64 | table.insert(data, 1, "." .. os_sep) 65 | actions.close(prompt_bufnr) 66 | pickers 67 | .new({}, { 68 | prompt_title = "Folders for Live Grep", 69 | finder = finders.new_table { results = data, entry_maker = make_entry.gen_from_file {} }, 70 | previewer = conf.file_previewer {}, 71 | sorter = conf.file_sorter {}, 72 | attach_mappings = function(bufnr) 73 | action_set.select:replace(function() 74 | local current_picker = action_state.get_current_picker(bufnr) 75 | 76 | local dirs = {} 77 | local selections = current_picker:get_multi_selection() 78 | if vim.tbl_isempty(selections) then 79 | table.insert(dirs, action_state.get_selected_entry().value) 80 | else 81 | for _, selection in ipairs(selections) do 82 | table.insert(dirs, selection.value) 83 | end 84 | end 85 | live_grep_filters.directories = dirs 86 | actions.close(bufnr) 87 | run_live_grep(current_input) 88 | end) 89 | return true 90 | end, 91 | }) 92 | :find() 93 | end, 94 | } 95 | 96 | return M 97 | -------------------------------------------------------------------------------- /lua/plugins/test/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "vim-test/vim-test", 4 | keys = { 5 | { "tc", "w|TestClass", desc = "Class" }, 6 | { "tf", "w|TestFile", desc = "File" }, 7 | { "tl", "w|TestLast", desc = "Last" }, 8 | { "tn", "w|TestNearest", desc = "Nearest" }, 9 | { "ts", "w|TestSuite", desc = "Suite" }, 10 | { "tv", "w|TestVisit", desc = "Visit" }, 11 | }, 12 | config = function() 13 | vim.g["test#strategy"] = "neovim" 14 | vim.g["test#neovim#term_position"] = "belowright" 15 | vim.g["test#neovim#preserve_screen"] = 1 16 | 17 | vim.g["test#python#runner"] = "pyunit" -- pytest 18 | end, 19 | }, 20 | { 21 | "nvim-neotest/neotest", 22 | keys = { 23 | { "tNF", "w|lua require('neotest').run.run({vim.fn.expand('%'), strategy = 'dap'})", desc = "Debug File" }, 24 | { "tNL", "w|lua require('neotest').run.run_last({strategy = 'dap'})", desc = "Debug Last" }, 25 | { "tNa", "w|lua require('neotest').run.attach()", desc = "Attach" }, 26 | { "tNf", "w|lua require('neotest').run.run(vim.fn.expand('%'))", desc = "File" }, 27 | { "tNl", "w|lua require('neotest').run.run_last()", desc = "Last" }, 28 | { "tNn", "w|lua require('neotest').run.run()", desc = "Nearest" }, 29 | { "tNN", "w|lua require('neotest').run.run({strategy = 'dap'})", desc = "Debug Nearest" }, 30 | { "tNo", "w|lua require('neotest').output.open({ enter = true })", desc = "Output" }, 31 | { "tNs", "w|lua require('neotest').run.stop()", desc = "Stop" }, 32 | { "tNS", "w|lua require('neotest').summary.toggle()", desc = "Summary" }, 33 | }, 34 | dependencies = { 35 | "nvim-lua/plenary.nvim", 36 | "nvim-treesitter/nvim-treesitter", 37 | "antoinemadec/FixCursorHold.nvim", 38 | "nvim-neotest/neotest-vim-test", 39 | "vim-test/vim-test", 40 | "stevearc/overseer.nvim", 41 | }, 42 | opts = function() 43 | return { 44 | adapters = { 45 | require "neotest-vim-test" { 46 | ignore_file_types = { "python", "vim", "lua" }, 47 | }, 48 | }, 49 | status = { virtual_text = true }, 50 | output = { open_on_run = true }, 51 | quickfix = { 52 | open = function() 53 | if require("utils").has "trouble.nvim" then 54 | vim.cmd "Trouble quickfix" 55 | else 56 | vim.cmd "copen" 57 | end 58 | end, 59 | }, 60 | -- overseer.nvim 61 | consumers = { 62 | overseer = require "neotest.consumers.overseer", 63 | }, 64 | overseer = { 65 | enabled = true, 66 | force_default = true, 67 | }, 68 | } 69 | end, 70 | config = function(_, opts) 71 | local neotest_ns = vim.api.nvim_create_namespace "neotest" 72 | vim.diagnostic.config({ 73 | virtual_text = { 74 | format = function(diagnostic) 75 | local message = diagnostic.message:gsub("\n", " "):gsub("\t", " "):gsub("%s+", " "):gsub("^%s+", "") 76 | return message 77 | end, 78 | }, 79 | }, neotest_ns) 80 | require("neotest").setup(opts) 81 | end, 82 | }, 83 | { 84 | "stevearc/overseer.nvim", 85 | keys = { 86 | { "toR", "OverseerRunCmd", desc = "Run Command" }, 87 | { "toa", "OverseerTaskAction", desc = "Task Action" }, 88 | { "tob", "OverseerBuild", desc = "Build" }, 89 | { "toc", "OverseerClose", desc = "Close" }, 90 | { "tod", "OverseerDeleteBundle", desc = "Delete Bundle" }, 91 | { "tol", "OverseerLoadBundle", desc = "Load Bundle" }, 92 | { "too", "OverseerOpen", desc = "Open" }, 93 | { "toq", "OverseerQuickAction", desc = "Quick Action" }, 94 | { "tor", "OverseerRun", desc = "Run" }, 95 | { "tos", "OverseerSaveBundle", desc = "Save Bundle" }, 96 | { "tot", "OverseerToggle", desc = "Toggle" }, 97 | }, 98 | config = true, 99 | }, 100 | { 101 | "anuvyklack/hydra.nvim", 102 | opts = { 103 | specs = { 104 | test = function() 105 | local cmd = require("hydra.keymap-util").cmd 106 | local hint = [[ 107 | ^ 108 | _f_: File 109 | _F_: All Files 110 | _l_: Last 111 | _n_: Nearest 112 | ^ 113 | _d_: Debug File 114 | _L_: Debug Last 115 | _N_: Debug Nearest 116 | ^ 117 | _o_: Output 118 | _S_: Summary 119 | ^ 120 | _a_: Attach 121 | _s_: Stop 122 | ^ 123 | ^ ^ _q_: Quit 124 | ]] 125 | return { 126 | name = "Test", 127 | hint = hint, 128 | config = { 129 | color = "pink", 130 | invoke_on_body = true, 131 | hint = { 132 | border = "rounded", 133 | position = "top-left", 134 | }, 135 | }, 136 | mode = "n", 137 | body = "", 138 | heads = { 139 | { "F", cmd "w|lua require('neotest').run.run(vim.loop.cwd())", desc = "All Files" }, 140 | { "L", cmd "w|lua require('neotest').run.run_last({strategy = 'dap'})", desc = "Debug Last" }, 141 | { "N", cmd "w|lua require('neotest').run.run({strategy = 'dap'})", desc = "Debug Nearest" }, 142 | { "S", cmd "w|lua require('neotest').summary.toggle()", desc = "Summary" }, 143 | { "a", cmd "w|lua require('neotest').run.attach()", desc = "Attach" }, 144 | { "d", cmd "w|lua require('neotest').run.run({vim.fn.expand('%'), strategy = 'dap'}", desc = "Debug File" }, 145 | { "f", cmd "w|lua require('neotest').run.run(vim.fn.expand('%'))", desc = "File" }, 146 | { "l", cmd "w|lua require('neotest').run.run_last()", desc = "Last" }, 147 | { "n", cmd "w|lua require('neotest').run.run()", desc = "Nearest" }, 148 | { "o", cmd "w|lua require('neotest').output.open({ enter = true })", desc = "Output" }, 149 | { "s", cmd "w|lua require('neotest').run.stop()", desc = "Stop" }, 150 | { "q", nil, { exit = true, nowait = true, desc = "Exit" } }, 151 | }, 152 | } 153 | end, 154 | }, 155 | }, 156 | }, 157 | { 158 | "andythigpen/nvim-coverage", 159 | cmd = { "Coverage" }, 160 | config = function() 161 | require("coverage").setup() 162 | end, 163 | }, 164 | { 165 | "Zeioth/compiler.nvim", 166 | cmd = { "CompilerOpen", "CompilerToggleResults", "CompilerRedo" }, 167 | dependencies = { "stevearc/overseer.nvim" }, 168 | opts = {}, 169 | }, 170 | } 171 | -------------------------------------------------------------------------------- /lua/plugins/textobjs.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "chrisgrieser/nvim-various-textobjs", 4 | config = function() 5 | require("various-textobjs").setup { useDefaultKeymaps = true } 6 | end, 7 | event = "VeryLazy", 8 | enabled = false, 9 | }, 10 | { "axieax/urlview.nvim", enabled = false, cmd = { "UrlView" } }, 11 | } 12 | -------------------------------------------------------------------------------- /lua/plugins/todo-comments.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "folke/todo-comments.nvim", 4 | cmd = { "TodoTrouble", "TodoTelescope" }, 5 | event = "BufReadPost", 6 | config = true, 7 | -- stylua: ignore 8 | keys = { 9 | { "]t", function() require("todo-comments").jump_next() end, desc = "Next ToDo" }, 10 | { "[t", function() require("todo-comments").jump_prev() end, desc = "Previous ToDo" }, 11 | { "lt", "TodoTrouble", desc = "ToDo (Trouble)" }, 12 | { "lT", "TodoTelescope", desc = "ToDo" }, 13 | }, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /lua/plugins/toggleterm.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "akinsho/toggleterm.nvim", 3 | keys = { 4 | { [[]] }, 5 | { "0", "2ToggleTerm", desc = "Terminal #2" }, 6 | }, 7 | cmd = { "ToggleTerm", "TermExec" }, 8 | opts = { 9 | size = 20, 10 | hide_numbers = true, 11 | open_mapping = [[]], 12 | shade_filetypes = {}, 13 | shade_terminals = false, 14 | shading_factor = 0.3, 15 | start_in_insert = true, 16 | persist_size = true, 17 | direction = "float", 18 | winbar = { 19 | enabled = false, 20 | name_formatter = function(term) 21 | return term.name 22 | end, 23 | }, 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /lua/plugins/treesitter/init.lua: -------------------------------------------------------------------------------- 1 | local swap_next, swap_prev = (function() 2 | local swap_objects = { 3 | p = "@parameter.inner", 4 | f = "@function.outer", 5 | c = "@class.outer", 6 | } 7 | 8 | local n, p = {}, {} 9 | for key, obj in pairs(swap_objects) do 10 | n[string.format("lx%s", key)] = obj 11 | p[string.format("lX%s", key)] = obj 12 | end 13 | 14 | return n, p 15 | end)() 16 | 17 | return { 18 | { 19 | "nvim-treesitter/nvim-treesitter", 20 | dependencies = { 21 | "nvim-treesitter/nvim-treesitter-textobjects", 22 | "JoosepAlviste/nvim-ts-context-commentstring", 23 | "RRethy/nvim-treesitter-endwise", 24 | "windwp/nvim-ts-autotag", 25 | "nvim-treesitter/playground", 26 | }, 27 | build = ":TSUpdate", 28 | event = { "BufReadPost", "BufNewFile" }, 29 | opts = { 30 | sync_install = false, 31 | ensure_installed = { 32 | "bash", 33 | -- "dapl_repl", 34 | "dockerfile", 35 | "html", 36 | "markdown", 37 | "markdown_inline", 38 | "org", 39 | "query", 40 | "regex", 41 | "latex", 42 | "vim", 43 | "vimdoc", 44 | "yaml", 45 | }, 46 | highlight = { enable = true, additional_vim_regex_highlighting = { "org", "markdown" } }, 47 | indent = { enable = true }, 48 | context_commentstring = { enable = true, enable_autocmd = false }, 49 | incremental_selection = { 50 | enable = true, 51 | keymaps = { 52 | -- init_selection = "", 53 | node_incremental = "v", 54 | node_decremental = "V", 55 | -- scope_incremental = "", 56 | }, 57 | }, 58 | textobjects = { 59 | select = { 60 | enable = true, 61 | lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim 62 | keymaps = { 63 | -- You can use the capture groups defined in textobjects.scm 64 | ["aa"] = "@parameter.outer", 65 | ["ia"] = "@parameter.inner", 66 | ["af"] = "@function.outer", 67 | ["if"] = "@function.inner", 68 | ["ac"] = "@class.outer", 69 | ["ic"] = "@class.inner", 70 | }, 71 | }, 72 | move = { 73 | enable = true, 74 | set_jumps = true, -- whether to set jumps in the jumplist 75 | goto_next_start = { 76 | ["]m"] = "@function.outer", 77 | ["]]"] = "@class.outer", 78 | }, 79 | goto_next_end = { 80 | ["]M"] = "@function.outer", 81 | ["]["] = "@class.outer", 82 | }, 83 | goto_previous_start = { 84 | ["[m"] = "@function.outer", 85 | ["[["] = "@class.outer", 86 | }, 87 | goto_previous_end = { 88 | ["[M"] = "@function.outer", 89 | ["[]"] = "@class.outer", 90 | }, 91 | }, 92 | swap = { 93 | enable = true, 94 | swap_next = swap_next, 95 | swap_previous = swap_prev, 96 | }, 97 | }, 98 | matchup = { 99 | enable = true, 100 | }, 101 | endwise = { 102 | enable = true, 103 | }, 104 | autotag = { 105 | enable = true, 106 | }, 107 | }, 108 | config = function(_, opts) 109 | if type(opts.ensure_installed) == "table" then 110 | ---@type table 111 | local added = {} 112 | opts.ensure_installed = vim.tbl_filter(function(lang) 113 | if added[lang] then 114 | return false 115 | end 116 | added[lang] = true 117 | return true 118 | end, opts.ensure_installed) 119 | end 120 | require("nvim-treesitter.configs").setup(opts) 121 | 122 | -- local ts_repeat_move = require "nvim-treesitter.textobjects.repeatable_move" 123 | 124 | -- -- vim way: ; goes to the direction you were moving. 125 | -- vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move) 126 | -- vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_opposite) 127 | 128 | -- -- Optionally, make builtin f, F, t, T also repeatable with ; and , 129 | -- vim.keymap.set({ "n", "x", "o" }, "f", ts_repeat_move.builtin_f) 130 | -- vim.keymap.set({ "n", "x", "o" }, "F", ts_repeat_move.builtin_F) 131 | -- vim.keymap.set({ "n", "x", "o" }, "t", ts_repeat_move.builtin_t) 132 | -- vim.keymap.set({ "n", "x", "o" }, "T", ts_repeat_move.builtin_T) 133 | end, 134 | }, 135 | { 136 | "windwp/nvim-autopairs", 137 | event = "InsertEnter", 138 | enabled = true, 139 | config = function() 140 | local npairs = require "nvim-autopairs" 141 | npairs.setup { 142 | check_ts = true, 143 | } 144 | end, 145 | }, 146 | { 147 | "altermo/ultimate-autopair.nvim", 148 | enabled = false, 149 | event = { "InsertEnter", "CmdlineEnter" }, 150 | branch = "v0.6", 151 | opts = {}, 152 | }, 153 | { 154 | "ckolkey/ts-node-action", 155 | dependencies = { "nvim-treesitter" }, 156 | enabled = true, 157 | opts = {}, 158 | keys = { 159 | { 160 | "ln", 161 | function() 162 | require("ts-node-action").node_action() 163 | end, 164 | desc = "Node Action", 165 | }, 166 | }, 167 | }, 168 | { 169 | "Wansmer/treesj", 170 | cmd = { "TSJToggle", "TSJSplit", "TSJJoin" }, 171 | keys = { 172 | { "lj", "TSJToggle", desc = "Toggle Split/Join" }, 173 | }, 174 | dependencies = { "nvim-treesitter/nvim-treesitter" }, 175 | config = function() 176 | require("treesj").setup { 177 | use_default_keymaps = false, 178 | } 179 | end, 180 | }, 181 | } 182 | -------------------------------------------------------------------------------- /lua/plugins/ui/edgy.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "folke/edgy.nvim", 4 | enabled = false, 5 | event = "VeryLazy", 6 | keys = { 7 | { 8 | "ze", 9 | function() 10 | require("edgy").toggle() 11 | end, 12 | desc = "Edgy Toggle", 13 | }, 14 | -- stylua: ignore 15 | { "zE", function() require("edgy").select() end, desc = "Edgy Select Window" }, 16 | }, 17 | opts = { 18 | bottom = { 19 | { 20 | ft = "toggleterm", 21 | size = { height = 0.4 }, 22 | filter = function(buf, win) 23 | return vim.api.nvim_win_get_config(win).relative == "" 24 | end, 25 | }, 26 | { 27 | ft = "noice", 28 | size = { height = 0.4 }, 29 | filter = function(buf, win) 30 | return vim.api.nvim_win_get_config(win).relative == "" 31 | end, 32 | }, 33 | { 34 | ft = "lazyterm", 35 | title = "LazyTerm", 36 | size = { height = 0.4 }, 37 | filter = function(buf) 38 | return not vim.b[buf].lazyterm_cmd 39 | end, 40 | }, 41 | "Trouble", 42 | { ft = "qf", title = "QuickFix" }, 43 | { 44 | ft = "help", 45 | size = { height = 20 }, 46 | -- don't open help files in edgy that we're editing 47 | filter = function(buf) 48 | return vim.bo[buf].buftype == "help" 49 | end, 50 | }, 51 | { ft = "spectre_panel", size = { height = 0.4 } }, 52 | { title = "Neotest Output", ft = "neotest-output-panel", size = { height = 15 } }, 53 | }, 54 | left = { 55 | { title = "Neotest Summary", ft = "neotest-summary" }, 56 | { ft = "hydra_hint", title = "Hydra", size = { height = 0.5 }, pinned = true }, 57 | }, 58 | keys = { 59 | -- increase width 60 | [""] = function(win) 61 | win:resize("width", 2) 62 | end, 63 | -- decrease width 64 | [""] = function(win) 65 | win:resize("width", -2) 66 | end, 67 | -- increase height 68 | [""] = function(win) 69 | win:resize("height", 2) 70 | end, 71 | -- decrease height 72 | [""] = function(win) 73 | win:resize("height", -2) 74 | end, 75 | }, 76 | }, 77 | }, 78 | } 79 | -------------------------------------------------------------------------------- /lua/plugins/ui/editor.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "xiyaowong/nvim-transparent", 4 | cmd = { "TransparentEnable", "TransparentDisable", "TransparentToggle" }, 5 | opts = { 6 | extra_groups = { -- table/string: additional groups that should be cleared 7 | -- In particular, when you set it to 'all', that means all available groups 8 | 9 | -- example of akinsho/nvim-bufferline.lua 10 | "BufferLineTabClose", 11 | "BufferlineBufferSelected", 12 | "BufferLineFill", 13 | "BufferLineBackground", 14 | "BufferLineSeparator", 15 | "BufferLineIndicatorSelected", 16 | }, 17 | exclude_groups = {}, -- table: groups you don't want to clear 18 | }, 19 | config = function(_, opts) 20 | require("transparent").setup(opts) 21 | end, 22 | }, 23 | { 24 | "gen740/SmoothCursor.nvim", 25 | enabled = false, 26 | event = { "BufReadPre" }, 27 | config = function() 28 | require("smoothcursor").setup { fancy = { enable = true } } 29 | end, 30 | }, 31 | { 32 | "declancm/cinnamon.nvim", 33 | enabled = false, 34 | event = { "BufReadPre" }, 35 | config = function() 36 | require("cinnamon").setup() 37 | end, 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /lua/plugins/ui/hbac.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "axkirillov/hbac.nvim", 3 | event = "VeryLazy", 4 | opts = { 5 | autoclose = true, 6 | threshold = 10, 7 | }, 8 | enabled = true, 9 | } 10 | -------------------------------------------------------------------------------- /lua/plugins/ui/highlight.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "RRethy/vim-illuminate", 4 | event = "BufReadPost", 5 | opts = { delay = 200 }, 6 | config = function(_, opts) 7 | require("illuminate").configure(opts) 8 | end, 9 | }, 10 | { 11 | "m-demare/hlargs.nvim", 12 | event = "VeryLazy", 13 | opts = { 14 | color = "#ef9062", 15 | use_colorpalette = false, 16 | disable = function(_, bufnr) 17 | if vim.b.semantic_tokens then 18 | return true 19 | end 20 | local clients = vim.lsp.get_active_clients { bufnr = bufnr } 21 | for _, c in pairs(clients) do 22 | local caps = c.server_capabilities 23 | if c.name ~= "null-ls" and caps.semanticTokensProvider and caps.semanticTokensProvider.full then 24 | vim.b.semantic_tokens = true 25 | return vim.b.semantic_tokens 26 | end 27 | end 28 | end, 29 | }, 30 | }, 31 | { 32 | "tzachar/highlight-undo.nvim", 33 | event = "VeryLazy", 34 | opts = {}, 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /lua/plugins/ui/noice.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/noice.nvim", 3 | event = "VeryLazy", 4 | enabled = true, 5 | opts = { 6 | lsp = { 7 | override = { 8 | ["vim.lsp.util.convert_input_to_markdown_lines"] = true, 9 | ["vim.lsp.util.stylize_markdown"] = true, 10 | ["cmp.entry.get_documentation"] = true, 11 | }, 12 | }, 13 | routes = { 14 | { 15 | filter = { 16 | event = "msg_show", 17 | any = { 18 | { find = "%d+L, %d+B" }, 19 | { find = "; after #%d+" }, 20 | { find = "; before #%d+" }, 21 | }, 22 | }, 23 | view = "mini", 24 | }, 25 | }, 26 | presets = { 27 | bottom_search = true, -- use a classic bottom cmdline for search 28 | command_palette = true, -- position the cmdline and popupmenu together 29 | long_message_to_split = true, -- long messages will be sent to a split 30 | inc_rename = true, -- enables an input dialog for inc-rename.nvim 31 | lsp_doc_border = true, -- add a border to hover docs and signature help 32 | }, 33 | }, 34 | --stylua: ignore 35 | keys = { 36 | { "", function() require("noice").redirect(vim.fn.getcmdline()) end, mode = "c", desc = "Redirect Cmdline" }, 37 | { "", function() if not require("noice.lsp").scroll(4) then return "" end end, silent = true, expr = true, desc = "Scroll forward" }, 38 | { "", function() if not require("noice.lsp").scroll(-4) then return "" end end, silent = true, expr = true, desc = "Scroll backward"}, 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /lua/plugins/ui/nvim-early-retirement.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "chrisgrieser/nvim-early-retirement", 3 | opts = { 4 | retirementAgeMins = 20, 5 | }, 6 | event = "VeryLazy", 7 | enabled = false, 8 | } 9 | -------------------------------------------------------------------------------- /lua/plugins/ui/scope.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { "tiagovla/scope.nvim", event = "VeryLazy", opts = {} }, 3 | } 4 | -------------------------------------------------------------------------------- /lua/plugins/ui/screensaver.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "tamton-aquib/duck.nvim", 4 | enabled = false, 5 | keys = { 6 | -- stylua: ignore 7 | { "zd", function() require("duck").hatch() end, desc = "Duck Hatch" }, 8 | -- stylua: ignore 9 | { "zD", function() require("duck").cook() end, desc = "Duck Cook" }, 10 | }, 11 | }, 12 | { 13 | "folke/drop.nvim", 14 | enabled = false, 15 | event = "VeryLazy", 16 | opts = function() 17 | math.randomseed(os.time()) 18 | local theme = ({ "leaves", "snow", "stars", "xmas", "spring", "summer" })[math.random(1, 6)] 19 | return { 20 | max = 80, -- maximum number of drops on the screen 21 | interval = 150, -- every 150ms we update the drops 22 | screensaver = 1000 * 60 * 5, -- 5 minutes 23 | theme = theme, 24 | } 25 | end, 26 | }, 27 | { 28 | "giusgad/pets.nvim", 29 | enabled = false, 30 | cmd = { 31 | "PetsNew", 32 | "PetsNewCustom", 33 | "PetsList", 34 | "PetsKill", 35 | "PetsKillAll", 36 | "PetsRemove", 37 | "PetsRemoveAll", 38 | "PetsPauseToggle", 39 | "PetsHideToggle", 40 | "PetsIdleToggle", 41 | "PetsSleepToggle", 42 | }, 43 | requires = { 44 | "giusgad/hologram.nvim", 45 | "MunifTanjim/nui.nvim", 46 | }, 47 | }, 48 | } 49 | -------------------------------------------------------------------------------- /lua/plugins/vcs/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "sindrets/diffview.nvim", 4 | cmd = { "DiffviewOpen", "DiffviewClose", "DiffviewToggleFiles", "DiffviewFocusFiles" }, 5 | config = true, 6 | }, 7 | { 8 | "NeogitOrg/neogit", 9 | cmd = "Neogit", 10 | opts = { 11 | integrations = { diffview = true }, 12 | disable_commit_confirmation = true, 13 | }, 14 | keys = { 15 | { "gs", "Neogit kind=tab", desc = "Status" }, 16 | }, 17 | }, 18 | { 19 | "tpope/vim-fugitive", 20 | cmd = { "Git", "GBrowse", "Gdiffsplit", "Gvdiffsplit" }, 21 | dependencies = { 22 | "tpope/vim-rhubarb", 23 | }, 24 | }, 25 | { 26 | "lewis6991/gitsigns.nvim", 27 | event = "BufReadPre", 28 | opts = { 29 | signs = { 30 | add = { hl = "GitSignsAdd", text = "▍", numhl = "GitSignsAddNr", linehl = "GitSignsAddLn" }, 31 | change = { 32 | hl = "GitSignsChange", 33 | text = "▍", 34 | numhl = "GitSignsChangeNr", 35 | linehl = "GitSignsChangeLn", 36 | }, 37 | delete = { 38 | hl = "GitSignsDelete", 39 | text = "▸", 40 | numhl = "GitSignsDeleteNr", 41 | linehl = "GitSignsDeleteLn", 42 | }, 43 | topdelete = { 44 | hl = "GitSignsDelete", 45 | text = "▾", 46 | numhl = "GitSignsDeleteNr", 47 | linehl = "GitSignsDeleteLn", 48 | }, 49 | changedelete = { 50 | hl = "GitSignsChange", 51 | text = "▍", 52 | numhl = "GitSignsChangeNr", 53 | linehl = "GitSignsChangeLn", 54 | }, 55 | }, 56 | -- update_debounce = 100, 57 | on_attach = function(bufnr) 58 | local gs = package.loaded.gitsigns 59 | local function map(mode, l, r, opts) 60 | opts = opts or {} 61 | opts.buffer = bufnr 62 | vim.keymap.set(mode, l, r, opts) 63 | end 64 | 65 | map("n", "]c", function() 66 | if vim.wo.diff then 67 | return "]c" 68 | end 69 | vim.schedule(function() 70 | gs.next_hunk() 71 | end) 72 | return "" 73 | end, { expr = true }) 74 | 75 | map("n", "[c", function() 76 | if vim.wo.diff then 77 | return "[c" 78 | end 79 | vim.schedule(function() 80 | gs.prev_hunk() 81 | end) 82 | return "" 83 | end, { expr = true }) 84 | 85 | -- Actions 86 | map({ "n", "v" }, "ghs", ":Gitsigns stage_hunk", { desc = "Stage Hunk" }) 87 | map({ "n", "v" }, "ghr", ":Gitsigns reset_hunk", { desc = "Reset Hunk" }) 88 | map("n", "ghS", gs.stage_buffer, { desc = "Stage Buffer" }) 89 | map("n", "ghu", gs.undo_stage_hunk, { desc = "Undo Stage Hunk" }) 90 | map("n", "ghR", gs.reset_buffer, { desc = "Reset Buffer" }) 91 | map("n", "ghp", gs.preview_hunk, { desc = "Preview Hunk" }) 92 | map("n", "ghb", function() 93 | gs.blame_line { full = true } 94 | end, { desc = "Blame Line" }) 95 | map("n", "gtb", gs.toggle_current_line_blame, { desc = "Toggle Line Blame" }) 96 | map("n", "ghd", gs.diffthis, { desc = "Diff This" }) 97 | map("n", "ghD", function() 98 | gs.diffthis "~" 99 | end, { desc = "Diff This ~" }) 100 | map("n", "gtd", gs.toggle_deleted, { desc = "Toggle Delete" }) 101 | 102 | -- Text object 103 | map({ "o", "x" }, "ih", ":Gitsigns select_hunk", { desc = "Select Hunk" }) 104 | end, 105 | }, 106 | }, 107 | { 108 | "mattn/vim-gist", 109 | dependencies = { "mattn/webapi-vim" }, 110 | cmd = { "Gist" }, 111 | config = function() 112 | vim.g.gist_open_browser_after_post = 1 113 | end, 114 | }, 115 | { 116 | "rawnly/gist.nvim", 117 | cmd = { "CreateGist", "CreateGistFromFile" }, 118 | }, 119 | { 120 | "aaronhallaert/advanced-git-search.nvim", 121 | config = function() 122 | require("telescope").load_extension "advanced_git_search" 123 | end, 124 | dependencies = { 125 | "nvim-telescope/telescope.nvim", 126 | "tpope/vim-fugitive", 127 | }, 128 | }, 129 | { 130 | "ThePrimeagen/git-worktree.nvim", 131 | opts = {}, 132 | config = function() 133 | require("telescope").load_extension "git_worktree" 134 | end, 135 | dependencies = { 136 | "nvim-telescope/telescope.nvim", 137 | }, 138 | --stylua: ignore 139 | keys = { 140 | {"gwm", function() require("telescope").extensions.git_worktree.git_worktrees() end, desc = "Manage"}, 141 | {"gwc", function() require("telescope").extensions.git_worktree.create_git_worktree() end, desc = "Create"}, 142 | }, 143 | }, 144 | { 145 | "akinsho/git-conflict.nvim", 146 | --stylua: ignore 147 | keys = { 148 | {"gC", function() require("plugins.hydra.git-action").open_git_conflict_hydra() end, desc = "Conflict"}, 149 | {"gS", function() require("plugins.hydra.git-action").open_git_signs_hydra() end, desc = "Signs"}, 150 | }, 151 | cmd = { 152 | "GitConflictChooseBoth", 153 | "GitConflictNextConflict", 154 | "GitConflictChooseOurs", 155 | "GitConflictPrevConflict", 156 | "GitConflictChooseTheirs", 157 | "GitConflictListQf", 158 | "GitConflictChooseNone", 159 | "GitConflictRefresh", 160 | }, 161 | opts = { 162 | default_mappings = true, 163 | default_commands = true, 164 | disable_diagnostics = true, 165 | }, 166 | }, 167 | } 168 | -------------------------------------------------------------------------------- /lua/plugins/whichkey.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "mrjones2014/legendary.nvim", 4 | keys = { 5 | { "", "Legendary", desc = "Legendary" }, 6 | { "hc", "Legendary", desc = "Command Palette" }, 7 | }, 8 | opts = { 9 | which_key = { auto_register = true }, 10 | }, 11 | }, 12 | { 13 | "folke/which-key.nvim", 14 | cond = function() 15 | return require("config").keymenu.which_key 16 | end, 17 | dependencies = { 18 | "mrjones2014/legendary.nvim", 19 | }, 20 | event = "VeryLazy", 21 | opts = { 22 | setup = { 23 | show_help = true, 24 | plugins = { spelling = true }, 25 | key_labels = { [""] = "SPC" }, 26 | triggers = "auto", 27 | window = { 28 | border = "single", -- none, single, double, shadow 29 | position = "bottom", -- bottom, top 30 | margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left] 31 | padding = { 1, 1, 1, 1 }, -- extra window padding [top, right, bottom, left] 32 | winblend = 0, 33 | }, 34 | layout = { 35 | height = { min = 4, max = 25 }, -- min and max height of the columns 36 | width = { min = 20, max = 50 }, -- min and max width of the columns 37 | spacing = 3, -- spacing between columns 38 | align = "left", -- align columns left, center or right 39 | }, 40 | }, 41 | defaults = { 42 | prefix = "", 43 | mode = { "n", "v" }, 44 | w = { "update!", "Save" }, 45 | -- stylua: ignore 46 | q = { name = "Quit/Session", 47 | q = { function() require("utils").quit() end, "Quit", }, 48 | t = { "tabclose", "Close Tab" }, 49 | }, 50 | a = { name = "+AI" }, 51 | b = { name = "+Buffer" }, 52 | d = { name = "+Debug" }, 53 | D = { name = "+Database" }, 54 | -- stylua: ignore 55 | f = { 56 | name = "+File" , 57 | t = { function() require("utils").open_term("yazi") end, "Terminal File Manager", }, 58 | }, 59 | h = { name = "+Help" }, 60 | j = { name = "+Jump" }, 61 | g = { name = "+Git", h = { name = "+Hunk" }, t = { name = "+Toggle" }, w = { name = "+Work Tree" } }, 62 | n = { name = "+Notes" }, 63 | p = { name = "+Project" }, 64 | -- o = { name = "+Orgmode" }, 65 | r = { name = "+Refactor" }, 66 | t = { name = "+Test", N = { name = "+Neotest" }, o = { "+Overseer" } }, 67 | v = { name = "+View" }, 68 | z = { name = "+System" }, 69 | -- stylua: ignore 70 | s = { 71 | name = "+Search", 72 | c = { function() require("utils.coding").cht() end, "Cheatsheets", }, 73 | o = { function() require("utils.coding").stack_overflow() end, "Stack Overflow", }, 74 | }, 75 | l = { 76 | name = "+Language", 77 | g = { name = "Annotation" }, 78 | x = { 79 | name = "Swap Next", 80 | f = "Function", 81 | p = "Parameter", 82 | c = "Class", 83 | }, 84 | X = { 85 | name = "Swap Previous", 86 | f = "Function", 87 | p = "Parameter", 88 | c = "Class", 89 | }, 90 | }, 91 | }, 92 | }, 93 | config = function(_, opts) 94 | local wk = require "which-key" 95 | wk.setup(opts.setup) 96 | wk.register(opts.defaults) 97 | end, 98 | }, 99 | } 100 | -------------------------------------------------------------------------------- /lua/plugins/wildfire.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "sustech-data/wildfire.nvim", 3 | enabled = false, 4 | event = "VeryLazy", 5 | dependencies = { "nvim-treesitter/nvim-treesitter" }, 6 | opts = {}, 7 | } 8 | -------------------------------------------------------------------------------- /lua/plugins/yanky.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- better yank/paste 3 | { 4 | "gbprod/yanky.nvim", 5 | dependencies = { { "kkharji/sqlite.lua", enabled = not jit.os:find "Windows" } }, 6 | opts = function() 7 | local mapping = require "yanky.telescope.mapping" 8 | local mappings = mapping.get_defaults() 9 | mappings.i[""] = nil 10 | return { 11 | highlight = { timer = 200 }, 12 | ring = { storage = jit.os:find "Windows" and "shada" or "sqlite" }, 13 | picker = { 14 | telescope = { 15 | use_default_mappings = false, 16 | mappings = mappings, 17 | }, 18 | }, 19 | } 20 | end, 21 | keys = { 22 | -- stylua: ignore 23 | { "zp", function() require("telescope").extensions.yank_history.yank_history({ }) end, desc = "Open Yank History" }, 24 | { "y", "(YankyYank)", mode = { "n", "x" }, desc = "Yank text" }, 25 | { "p", "(YankyPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after cursor" }, 26 | { "P", "(YankyPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before cursor" }, 27 | { "gp", "(YankyGPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after selection" }, 28 | { "gP", "(YankyGPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before selection" }, 29 | { "[y", "(YankyCycleForward)", desc = "Cycle forward through yank history" }, 30 | { "]y", "(YankyCycleBackward)", desc = "Cycle backward through yank history" }, 31 | { "]p", "(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" }, 32 | { "[p", "(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" }, 33 | { "]P", "(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" }, 34 | { "[P", "(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" }, 35 | { ">p", "(YankyPutIndentAfterShiftRight)", desc = "Put and indent right" }, 36 | { "(YankyPutIndentAfterShiftLeft)", desc = "Put and indent left" }, 37 | { ">P", "(YankyPutIndentBeforeShiftRight)", desc = "Put before and indent right" }, 38 | { "(YankyPutIndentBeforeShiftLeft)", desc = "Put before and indent left" }, 39 | { "=p", "(YankyPutAfterFilter)", desc = "Put after applying a filter" }, 40 | { "=P", "(YankyPutBeforeFilter)", desc = "Put before applying a filter" }, 41 | }, 42 | }, 43 | } 44 | -------------------------------------------------------------------------------- /lua/utils/ai/init.lua: -------------------------------------------------------------------------------- 1 | local ui = require "utils.ai.ui" 2 | 3 | local M = {} 4 | 5 | function M.toggle(toggle, type, prompt) 6 | local open = (toggle ~= "" and toggle) or (toggle == "" and not ui.is_open()) 7 | if open then 8 | local openai = require "utils.ai.openai_api" 9 | ui.create_ui(openai, type) 10 | if prompt ~= nil then 11 | ui.send_prompt(prompt) 12 | end 13 | return true 14 | else 15 | ui.destroy_ui() 16 | return false 17 | end 18 | end 19 | 20 | return M 21 | -------------------------------------------------------------------------------- /lua/utils/ai/openai_api.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local Job = require "plenary.job" 4 | 5 | local OPENAI_COMPLETION_URL = "https://api.openai.com/v1/completions" 6 | local OPENAI_COMPLETION_MODEL = "text-davinci-003" 7 | local OPENAI_CHAT_URL = "https://api.openai.com/v1/chat/completions" 8 | local OPENAI_CHAT_MODEL = "gpt-3.5-turbo" 9 | local TEMPERATURE = 1 10 | local TOP_P = 1 11 | local MAX_TOKENS = 2048 12 | 13 | local function get_api_key() 14 | return vim.env.OPENAI_API_KEY 15 | end 16 | 17 | local function trim(s) 18 | return (string.gsub(s, "^%s*(.-)%s*$", "%1")) 19 | end 20 | 21 | local function get_prompt() 22 | local prompt = nil 23 | local start_pos = vim.fn.getpos "'<" 24 | local end_pos = vim.fn.getpos "'>" 25 | local start_row, start_col = start_pos[2], start_pos[3] 26 | local end_row, end_col = end_pos[2], end_pos[3] 27 | if start_row ~= end_row or start_col ~= end_col then 28 | prompt = vim.fn.getline(start_row, end_row) 29 | prompt = trim(table.concat(prompt, "\n")) 30 | vim.fn.setpos("'<", { 0, 0, 0, 0 }) 31 | vim.fn.setpos("'>", { 0, 0, 0, 0 }) 32 | end 33 | return prompt 34 | end 35 | 36 | local function http_request(url, request) 37 | local api_key = get_api_key() 38 | if api_key == nil then 39 | vim.notify "OpenAI API key not found" 40 | return nil 41 | end 42 | local body = vim.fn.json_encode(request) 43 | local job = Job:new { 44 | command = "curl", 45 | args = { 46 | url, 47 | "-H", 48 | "Content-Type: application/json", 49 | "-H", 50 | string.format("Authorization: Bearer %s", api_key), 51 | "-d", 52 | body, 53 | }, 54 | } 55 | local is_completed = pcall(job.sync, job, 10000) 56 | if is_completed then 57 | local result = job:result() 58 | local ok, parsed = pcall(vim.json.decode, table.concat(result, "")) 59 | if not ok then 60 | vim.notify "Failed to parse OpenAI result" 61 | return nil 62 | end 63 | return parsed 64 | end 65 | return nil 66 | end 67 | 68 | function M.chat(input) 69 | local prompt = get_prompt() or input or "" 70 | local request = {} 71 | request["model"] = OPENAI_CHAT_MODEL 72 | request["temperature"] = TEMPERATURE 73 | request["top_p"] = TOP_P 74 | msgs = {} 75 | msg = {} 76 | msg["role"] = "user" 77 | msg["content"] = prompt 78 | table.insert(msgs, msg) 79 | request["messages"] = msgs 80 | 81 | local result = http_request(OPENAI_CHAT_URL, request) 82 | local text = "" 83 | if result ~= nil and result["choices"] ~= nil then 84 | text = result["choices"][1]["message"]["content"] 85 | end 86 | return text 87 | end 88 | 89 | function M.completion(input) 90 | local prompt = get_prompt() or input or "" 91 | 92 | local request = {} 93 | request["model"] = OPENAI_COMPLETION_MODEL 94 | request["max_tokens"] = MAX_TOKENS 95 | request["temperature"] = TEMPERATURE 96 | request["top_p"] = TOP_P 97 | request["prompt"] = prompt 98 | 99 | local result = http_request(OPENAI_COMPLETION_URL, request) 100 | local text = "" 101 | if result ~= nil and result["choices"] ~= nil then 102 | text = result["choices"][1]["text"] 103 | end 104 | return text 105 | end 106 | 107 | return M 108 | -------------------------------------------------------------------------------- /lua/utils/ai/test_ai.lua: -------------------------------------------------------------------------------- 1 | local function InvokePythonAPI() 2 | local output = vim.api.nvim_call_function("OpenAIGPTCompletion", { "Write a Python hello world program" }) 3 | vim.print(output) 4 | end 5 | 6 | local function InvokeLuaAPI() 7 | local ai = require "utils.ai.openai_api" 8 | local result = ai.chat "Write a hello world program in Rust" 9 | vim.print(result) 10 | end 11 | 12 | local function Chat_UI() 13 | local ai = require "utils.ai" 14 | ai.toggle(true, "chat", "Write a HTTP server in Node.js") 15 | end 16 | 17 | local function Completion_UI() 18 | local ai = require "utils.ai" 19 | ai.toggle(true, "completion", "Write a HTTP server in Go language") 20 | end 21 | 22 | -- InvokePythonAPI() 23 | 24 | -- InvokeLuaAPI() 25 | 26 | Completion_UI() 27 | 28 | -- Chat_UI() 29 | -------------------------------------------------------------------------------- /lua/utils/coding.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local lang = "" 4 | local file_type = "" 5 | local utils = require "utils" 6 | 7 | local function cht_on_open(term) 8 | vim.cmd "stopinsert" 9 | vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) 10 | vim.api.nvim_buf_set_name(term.bufnr, "cheatsheet-" .. term.bufnr) 11 | vim.api.nvim_set_option_value("filetype", "cheat", { buf = term.bufnr }) 12 | vim.api.nvim_set_option_value("syntax", lang, { buf = term.bufnr }) 13 | end 14 | 15 | local function cht_on_exit(_) 16 | vim.cmd [[normal gg]] 17 | end 18 | 19 | function M.cht() 20 | local buf = vim.api.nvim_get_current_buf() 21 | lang = "" 22 | file_type = vim.api.nvim_get_option_value("filetype", { buf = buf }) 23 | vim.ui.input({ prompt = "cht.sh input: ", default = file_type .. " " }, function(input) 24 | local cmd = "" 25 | if input == "" or not input then 26 | return 27 | elseif input == "h" then 28 | cmd = "" 29 | else 30 | local search = "" 31 | local delimiter = " " 32 | for w in (input .. delimiter):gmatch("(.-)" .. delimiter) do 33 | if lang == "" then 34 | lang = w 35 | else 36 | if search == "" then 37 | search = w 38 | else 39 | search = search .. "+" .. w 40 | end 41 | end 42 | end 43 | cmd = lang 44 | if search ~= "" then 45 | cmd = cmd .. "/" .. search 46 | end 47 | end 48 | cmd = "curl cht.sh/" .. cmd 49 | utils.open_term(cmd, { direction = "vertical", on_open = cht_on_open, on_exit = cht_on_exit }) 50 | end) 51 | end 52 | 53 | function M.stack_overflow() 54 | local buf = vim.api.nvim_get_current_buf() 55 | file_type = vim.api.nvim_get_option_value("filetype", { buf = buf }) 56 | vim.ui.input({ prompt = "so input: ", default = file_type .. " " }, function(input) 57 | local cmd = "" 58 | if input == "" or not input then 59 | return 60 | elseif input == "h" then 61 | cmd = "-h" 62 | else 63 | cmd = input 64 | end 65 | cmd = "so " .. cmd 66 | utils.open_term(cmd, { direction = "float" }) 67 | end) 68 | end 69 | 70 | function M.reddit() 71 | local cmd = "tuir" 72 | utils.open_term(cmd, { direction = "float" }) 73 | end 74 | 75 | function M.gh_dash() 76 | local cmd = "gh dash" 77 | utils.open_term(cmd, { direction = "float" }) 78 | end 79 | 80 | return M 81 | -------------------------------------------------------------------------------- /lua/utils/contextmenu.lua: -------------------------------------------------------------------------------- 1 | vim.cmd [[:amenu 10.100 Alpha2phi.Definition :Telescope lsp_defintions]] 2 | vim.cmd [[:amenu 10.110 Alpha2phi.Peek\ Definition :Lspsaga peek_definition]] 3 | vim.cmd [[:amenu 10.120 Alpha2phi.Type\ Definition :Telescope lsp_type_definitions]] 4 | vim.cmd [[:amenu 10.130 Alpha2phi.Implementations :Telescope lsp_implementations]] 5 | vim.cmd [[:amenu 10.140 Alpha2phi.References :Telescope lsp_references]] 6 | vim.cmd [[:amenu 10.150 Alpha2phi.-sep- *]] 7 | vim.cmd [[:amenu 10.160 Alpha2phi.Rename :Lspsaga rename]] 8 | vim.cmd [[:amenu 10.170 Alpha2phi.Code\ Actions :Lspsaga code_action]] 9 | 10 | vim.keymap.set("n", "", ":popup Alpha2phi") 11 | vim.keymap.set("n", "", ":popup Alpha2phi") 12 | -------------------------------------------------------------------------------- /lua/utils/init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.root_patterns = { ".git", "lua" } 4 | 5 | local function default_on_open(term) 6 | vim.cmd "startinsert" 7 | vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) 8 | end 9 | 10 | function M.open_term(cmd, opts) 11 | opts = opts or {} 12 | opts.size = opts.size or vim.o.columns * 0.5 13 | opts.direction = opts.direction or "float" 14 | opts.on_open = opts.on_open or default_on_open 15 | opts.on_exit = opts.on_exit or nil 16 | opts.dir = opts.dir or "git_dir" 17 | 18 | local Terminal = require("toggleterm.terminal").Terminal 19 | local new_term = Terminal:new { 20 | cmd = cmd, 21 | dir = opts.dir, 22 | auto_scroll = false, 23 | close_on_exit = false, 24 | on_open = opts.on_open, 25 | on_exit = opts.on_exit, 26 | } 27 | new_term:open(opts.size, opts.direction) 28 | end 29 | 30 | function M.quit() 31 | local bufnr = vim.api.nvim_get_current_buf() 32 | local buf_windows = vim.call("win_findbuf", bufnr) 33 | local modified = vim.api.nvim_get_option_value("modified", { buf = bufnr }) 34 | if modified and #buf_windows == 1 then 35 | vim.ui.input({ 36 | prompt = "You have unsaved changes. Quit anyway? (y/n) ", 37 | }, function(input) 38 | if input == "y" then 39 | vim.cmd "qa!" 40 | end 41 | end) 42 | else 43 | vim.cmd "qa!" 44 | end 45 | end 46 | 47 | function M.fg(name) 48 | local hl = vim.api.nvim_get_hl and vim.api.nvim_get_hl(0, { name = name }) or vim.api.nvim_get_hl_by_name(name, true) 49 | local fg = hl and hl.fg or hl.foreground 50 | return fg and { fg = string.format("#%06x", fg) } 51 | end 52 | 53 | function M.bg(group, color) 54 | vim.cmd("hi " .. group .. " guibg=" .. color) 55 | end 56 | 57 | function M.fg_bg(group, fg_color, bg_color) 58 | vim.cmd("hi " .. group .. " guifg=" .. fg_color .. " guibg=" .. bg_color) 59 | end 60 | 61 | function M.find_files() 62 | local opts = {} 63 | local telescope = require "telescope.builtin" 64 | 65 | local ok = pcall(telescope.git_files, opts) 66 | if not ok then 67 | telescope.find_files(opts) 68 | end 69 | end 70 | 71 | function M.reload_module(name) 72 | require("plenary.reload").reload_module(name) 73 | end 74 | 75 | ---@param plugin string 76 | function M.has(plugin) 77 | return require("lazy.core.config").plugins[plugin] ~= nil 78 | end 79 | 80 | function M.get_root() 81 | ---@type string? 82 | local path = vim.api.nvim_buf_get_name(0) 83 | path = path ~= "" and vim.loop.fs_realpath(path) or nil 84 | ---@type string[] 85 | local roots = {} 86 | if path then 87 | for _, client in pairs(vim.lsp.get_active_clients { bufnr = 0 }) do 88 | local workspace = client.config.workspace_folders 89 | local paths = workspace and vim.tbl_map(function(ws) 90 | return vim.uri_to_fname(ws.uri) 91 | end, workspace) or client.config.root_dir and { client.config.root_dir } or {} 92 | for _, p in ipairs(paths) do 93 | local r = vim.loop.fs_realpath(p) 94 | if path:find(r, 1, true) then 95 | roots[#roots + 1] = r 96 | end 97 | end 98 | end 99 | end 100 | table.sort(roots, function(a, b) 101 | return #a > #b 102 | end) 103 | ---@type string? 104 | local root = roots[1] 105 | if not root then 106 | path = path and vim.fs.dirname(path) or vim.loop.cwd() 107 | ---@type string? 108 | root = vim.fs.find(M.root_patterns, { path = path, upward = true })[1] 109 | root = root and vim.fs.dirname(root) or vim.loop.cwd() 110 | end 111 | ---@cast root string 112 | return root 113 | end 114 | 115 | function M.telescope(builtin, opts) 116 | local params = { builtin = builtin, opts = opts } 117 | return function() 118 | builtin = params.builtin 119 | opts = params.opts 120 | opts = vim.tbl_deep_extend("force", { cwd = M.get_root() }, opts or {}) 121 | if builtin == "files" then 122 | if vim.loop.fs_stat((opts.cwd or vim.loop.cwd()) .. "/.git") then 123 | opts.show_untracked = true 124 | builtin = "git_files" 125 | else 126 | builtin = "find_files" 127 | end 128 | end 129 | if opts.cwd and opts.cwd ~= vim.loop.cwd() then 130 | opts.attach_mappings = function(_, map) 131 | map("i", "", function() 132 | local action_state = require "telescope.actions.state" 133 | local line = action_state.get_current_line() 134 | M.telescope(params.builtin, vim.tbl_deep_extend("force", {}, params.opts or {}, { cwd = false, default_text = line }))() 135 | end) 136 | return true 137 | end 138 | end 139 | require("telescope.builtin")[builtin](opts) 140 | end 141 | end 142 | 143 | function M.join_paths(...) 144 | local path_sep = vim.loop.os_uname().version:match "Windows" and "\\" or "/" 145 | local result = table.concat({ ... }, path_sep) 146 | return result 147 | end 148 | 149 | function M.find_string(table, string) 150 | local found = false 151 | for _, v in pairs(table) do 152 | if v == string then 153 | found = true 154 | break 155 | end 156 | end 157 | return found 158 | end 159 | 160 | local is_windows = vim.loop.os_uname().version:match "Windows" 161 | local path_separator = is_windows and "\\" or "/" 162 | 163 | function M.remove_path_last_separator(path) 164 | if not path then 165 | return "" 166 | end 167 | if path:sub(#path) == path_separator then 168 | return path:sub(1, #path - 1) 169 | end 170 | return path 171 | end 172 | 173 | return M 174 | -------------------------------------------------------------------------------- /lua/utils/notepad.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | --[[ launch_notepad() 4 | -- Launch a small, transparent floating window with a scartch buffer that persists until Neovim closes 5 | -- 6 | -- @requires M.notepad_loaded, M.notepad_buf, M.notepad_win variables in util (this) module 7 | --]] 8 | M.notepad_loaded = false 9 | M.notepad_buf, M.notepad_win = nil, nil 10 | 11 | function M.launch_notepad() 12 | if not M.notepad_loaded or not vim.api.nvim_win_is_valid(M.notepad_win) then 13 | if not M.notepad_buf or not vim.api.nvim_buf_is_valid(M.notepad_buf) then 14 | -- Create a buffer if it none existed 15 | M.notepad_buf = vim.api.nvim_create_buf(false, true) 16 | vim.api.nvim_buf_set_option(M.notepad_buf, "bufhidden", "hide") 17 | vim.api.nvim_buf_set_option(M.notepad_buf, "filetype", "markdown") 18 | vim.api.nvim_buf_set_lines(M.notepad_buf, 0, 1, false, { 19 | "# Notepad", 20 | "", 21 | "> Notepad clears when the current Neovim session closes", 22 | }) 23 | end 24 | -- Create a window 25 | M.notepad_win = vim.api.nvim_open_win(M.notepad_buf, true, { 26 | border = "rounded", 27 | relative = "editor", 28 | style = "minimal", 29 | height = math.ceil(vim.o.lines * 0.5), 30 | width = math.ceil(vim.o.columns * 0.5), 31 | row = 1, --> Top of the window 32 | col = math.ceil(vim.o.columns * 0.5), --> Far right; should add up to 1 with win_width 33 | }) 34 | vim.api.nvim_win_set_option(M.notepad_win, "winblend", 30) --> Semi transparent buffer 35 | 36 | -- Keymaps 37 | local keymaps_opts = { silent = true, buffer = M.notepad_buf } 38 | vim.keymap.set("n", "", function() 39 | M.launch_notepad() 40 | end, keymaps_opts) 41 | vim.keymap.set("n", "q", function() 42 | M.launch_notepad() 43 | end, keymaps_opts) 44 | else 45 | vim.api.nvim_win_hide(M.notepad_win) 46 | end 47 | M.notepad_loaded = not M.notepad_loaded 48 | end 49 | 50 | return M 51 | -------------------------------------------------------------------------------- /lua/utils/textobjects.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.basic_text_objects() 4 | local chars = { "_", ".", ":", ",", ";", "|", "/", "\\", "*", "+", "%", "`", "?" } 5 | for _, char in ipairs(chars) do 6 | for _, mode in ipairs { "x", "o" } do 7 | vim.api.nvim_set_keymap(mode, "i" .. char, string.format(":silent! normal! f%sF%slvt%s", char, char, char), { noremap = true, silent = true }) 8 | vim.api.nvim_set_keymap(mode, "a" .. char, string.format(":silent! normal! f%sF%svf%s", char, char, char), { noremap = true, silent = true }) 9 | end 10 | end 11 | end 12 | 13 | return M 14 | -------------------------------------------------------------------------------- /mnv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # https://github.com/neovim/neovim/pull/22128 4 | MNV_APP_NAME=modern-neovim 5 | alias mnv="NVIM_APPNAME=$MNV_APP_NAME nvim" 6 | mnv 7 | -------------------------------------------------------------------------------- /rplugin/python3/openai_api.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import openai 4 | import pynvim 5 | from pynvim import Nvim 6 | 7 | MODEL_CHAT = "gpt-3.5-turbo" 8 | MODEL_COMPLETION = "text-davinci-003" 9 | 10 | TEMPERATURE = 1 11 | TOP_P = 1 12 | MAX_TOKENS = 2048 13 | 14 | 15 | def get_api_key(): 16 | return os.environ.get("OPENAI_API_KEY") 17 | 18 | 19 | def get_prompt(nvim: Nvim, args): 20 | prompt = "" 21 | start_row, start_col = nvim.funcs.getpos("'<")[1:3] 22 | end_row, end_col = nvim.funcs.getpos("'>")[1:3] 23 | if start_row != end_row or start_col != end_col: 24 | prompt = nvim.funcs.getline(start_row, end_row) 25 | prompt = "\n".join(map(str, prompt)) 26 | nvim.funcs.setpos("'<", (0, 0, 0, 0)) 27 | nvim.funcs.setpos("'>", (0, 0, 0, 0)) 28 | else: 29 | if len(args) > 0: 30 | prompt = " ".join(args) 31 | return prompt 32 | 33 | 34 | @pynvim.function("OpenAIGPTChat", sync=True) 35 | def chat(nvim: Nvim, args) -> str: 36 | api_key = get_api_key() 37 | if api_key is not None: 38 | openai.api_key = api_key 39 | prompt = get_prompt(nvim, args) 40 | response = openai.ChatCompletion.create( 41 | model=MODEL_CHAT, 42 | temperature=TEMPERATURE, 43 | top_p=TOP_P, 44 | messages=[{"role": "user", "content": prompt}], 45 | ) 46 | return response["choices"][0]["message"]["content"].strip() 47 | else: 48 | nvim.err_write("OPENAI_API_KEY is not set\n") 49 | return "" 50 | 51 | 52 | @pynvim.function("OpenAIGPTCompletion", sync=True) 53 | def completion(nvim: Nvim, args) -> str: 54 | api_key = get_api_key() 55 | if api_key is not None: 56 | openai.api_key = api_key 57 | prompt = get_prompt(nvim, args) 58 | response = openai.Completion.create( 59 | model=MODEL_COMPLETION, 60 | prompt=prompt, 61 | temperature=TEMPERATURE, 62 | top_p=TOP_P, 63 | max_tokens=MAX_TOKENS, 64 | ) 65 | return response["choices"][0]["text"].strip() 66 | else: 67 | nvim.err_write("OPENAI_API_KEY is not set\n") 68 | return "" 69 | -------------------------------------------------------------------------------- /rplugin/python3/requirements.txt: -------------------------------------------------------------------------------- 1 | openai 2 | pynvim 3 | -------------------------------------------------------------------------------- /rplugin/python3/test_openai_api.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import unittest 4 | 5 | import openai 6 | 7 | MODEL_CHAT = "gpt-3.5-turbo" 8 | MODEL_COMPLETION = "text-davinci-003" 9 | 10 | TEMPERATURE = 1 11 | TOP_P = 1 12 | MAX_TOKENS = 2048 13 | 14 | 15 | class TestOpenAIGPT(unittest.TestCase): 16 | api_key: str 17 | 18 | def setUp(self) -> None: 19 | self.api_key = os.getenv("OPENAI_API_KEY") 20 | openai.api_key = self.api_key 21 | 22 | def test_api_key(self): 23 | self.assertIsNotNone(self.api_key, "API key is not configured") 24 | 25 | def test_completion(self): 26 | response = openai.Completion.create( 27 | model=MODEL_COMPLETION, 28 | prompt="Write a Python hello world program", 29 | temperature=TEMPERATURE, 30 | top_p=TOP_P, 31 | max_tokens=MAX_TOKENS, 32 | ) 33 | print(response) 34 | text = response["choices"][0]["text"].strip() 35 | print(text) 36 | self.assertIsNotNone(response, "Chat response is empty") 37 | 38 | def test_chat(self): 39 | response = openai.ChatCompletion.create( 40 | model=MODEL_CHAT, 41 | temperature=TEMPERATURE, 42 | top_p=TOP_P, 43 | messages=[ 44 | {"role": "user", "content": "Write a Python hello world program"} 45 | ], 46 | ) 47 | content = response["choices"][0]["message"]["content"].strip() 48 | self.assertIsNotNone(content, "Chat response is empty") 49 | -------------------------------------------------------------------------------- /vim.toml: -------------------------------------------------------------------------------- 1 | [vim] 2 | any = true 3 | --------------------------------------------------------------------------------