├── .gitignore ├── .neoconf.json ├── LICENSE ├── README-img ├── dash-img.png └── window-img.png ├── README.md ├── init.lua ├── lazyvim.json ├── lua ├── chadrc.lua ├── config │ ├── autocmds.lua │ ├── keymaps.lua │ ├── lazy.lua │ ├── options.lua │ └── tailwind.lua ├── custom │ ├── buffers.lua │ ├── copilot-stl.lua │ ├── hl.lua │ ├── multi-grep.lua │ └── utils.lua └── plugins │ ├── avante.lua │ ├── blink.lua │ ├── codecompanion.lua │ ├── copilot.lua │ ├── dap.lua │ ├── diffview.lua │ ├── disabled.lua │ ├── ecolog.lua │ ├── gitsigns.lua │ ├── lspconfig.lua │ ├── markdown.lua │ ├── minifiles.lua │ ├── minipairs.lua │ ├── minipick.lua │ ├── misc.lua │ ├── multicursors.lua │ ├── noice.lua │ ├── obsidian.lua │ ├── rainbow-delimiters.lua │ ├── snacks.lua │ ├── tailwind-tools.lua │ ├── ts.lua │ ├── ui.lua │ └── windows.lua └── stylua.toml /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | tt.* 3 | .tests 4 | doc/tags 5 | debug 6 | .repro 7 | foo.* 8 | *.log 9 | data 10 | .ltex-dictionary 11 | .luarc.json 12 | lazy-lock.json 13 | spell/ 14 | startup_Times.log 15 | # IDK wtf is this tbh 16 | command\ list-panes:\ too\ many\ arguments\ \(need\ at\ most\ 0\) 17 | -------------------------------------------------------------------------------- /.neoconf.json: -------------------------------------------------------------------------------- 1 | { 2 | "neodev": { 3 | "library": { 4 | "enabled": true, 5 | "plugins": true 6 | } 7 | }, 8 | "neoconf": { 9 | "plugins": { 10 | "lua_ls": { 11 | "enabled": true 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README-img/dash-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d7omdev/nvim/da7fafba7a11fb035e48968698df9c9ab2730cb2/README-img/dash-img.png -------------------------------------------------------------------------------- /README-img/window-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d7omdev/nvim/da7fafba7a11fb035e48968698df9c9ab2730cb2/README-img/window-img.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Neovim Configuration 2 | 3 | This repository contains my personal Neovim configuration. 4 | 5 | ![Dashvoard](./README-img/dash-img.png) 6 | ![Window](./README-img/window-img.png) 7 | 8 | ## Installation 9 | 10 | To use this configuration, clone this repository to your Neovim configuration directory. 11 | 12 | ```bash 13 | git clone https://github.com/d7omdev/nvim.git ~/.config/nvim 14 | ``` 15 | 16 | Then, open Neovim and let the magic Happen!. 17 | 18 | ```bash 19 | nvim 20 | ``` 21 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | require("config.lazy") 2 | require("custom.hl").setup_highlights() 3 | -------------------------------------------------------------------------------- /lazyvim.json: -------------------------------------------------------------------------------- 1 | { 2 | "extras": [ 3 | "lazyvim.plugins.extras.ai.copilot", 4 | "lazyvim.plugins.extras.coding.blink", 5 | "lazyvim.plugins.extras.coding.luasnip", 6 | "lazyvim.plugins.extras.coding.mini-comment", 7 | "lazyvim.plugins.extras.coding.mini-surround", 8 | "lazyvim.plugins.extras.coding.yanky", 9 | "lazyvim.plugins.extras.editor.dial", 10 | "lazyvim.plugins.extras.editor.harpoon2", 11 | "lazyvim.plugins.extras.editor.illuminate", 12 | "lazyvim.plugins.extras.editor.inc-rename", 13 | "lazyvim.plugins.extras.editor.mini-diff", 14 | "lazyvim.plugins.extras.editor.mini-move", 15 | "lazyvim.plugins.extras.editor.refactoring", 16 | "lazyvim.plugins.extras.editor.snacks_picker", 17 | "lazyvim.plugins.extras.lang.astro", 18 | "lazyvim.plugins.extras.lang.git", 19 | "lazyvim.plugins.extras.lang.go", 20 | "lazyvim.plugins.extras.lang.json", 21 | "lazyvim.plugins.extras.lang.python", 22 | "lazyvim.plugins.extras.lang.toml", 23 | "lazyvim.plugins.extras.lang.vue", 24 | "lazyvim.plugins.extras.lang.yaml", 25 | "lazyvim.plugins.extras.ui.mini-animate", 26 | "lazyvim.plugins.extras.ui.treesitter-context", 27 | "lazyvim.plugins.extras.util.chezmoi", 28 | "lazyvim.plugins.extras.util.dot", 29 | "lazyvim.plugins.extras.util.mini-hipatterns", 30 | "lazyvim.plugins.extras.util.startuptime", 31 | "lazyvim.plugins.extras.vscode" 32 | ], 33 | "install_version": 7, 34 | "news": { 35 | "NEWS.md": "10960" 36 | }, 37 | "version": 8 38 | } -------------------------------------------------------------------------------- /lua/chadrc.lua: -------------------------------------------------------------------------------- 1 | local utils = require("nvchad.stl.utils") 2 | local sep_icons = utils.separators 3 | local separators = sep_icons["default"] 4 | local sep_l = separators["left"] 5 | 6 | local lazy_status = require("lazy.status") 7 | 8 | local options = { 9 | base46 = { 10 | theme = "gruvchad", 11 | hl_add = {}, 12 | integrations = {}, 13 | changed_themes = {}, 14 | transparency = true, 15 | theme_toggle = { "gruvchad", "catppuccin" }, 16 | hl_override = { 17 | ["@keyword.repeat"] = { italic = true, bold = true }, 18 | ["Keyword"] = { italic = true, bold = true }, 19 | }, 20 | }, 21 | } 22 | 23 | if options.base46.transparency then 24 | options.base46.hl_override = { 25 | TbBufOn = { 26 | bg = "#1E2122", 27 | italic = true, 28 | }, 29 | TbBufOnClose = { fg = "#CA6169", bg = "#2D3031" }, 30 | ["@keyword.function"] = { italic = true, bold = true }, 31 | ["@keyword.directive"] = { italic = true, bold = true }, 32 | ["@keyword.exception"] = { italic = true, bold = true }, 33 | ["@keyword.conditional"] = { italic = true, bold = true }, 34 | ["@keyword.conditional.ternary"] = { italic = true, bold = true }, 35 | ["@keyword.repeat"] = { italic = true, bold = true }, 36 | ["@keyword.operator"] = { italic = true, bold = true }, 37 | } 38 | end 39 | 40 | options.ui = { 41 | cmp = { 42 | icons_left = false, -- only for non-atom styles! 43 | lspkind_text = false, 44 | style = "default", -- default/flat_light/flat_dark/atom/atom_colored 45 | format_colors = { 46 | tailwind = true, -- works for CSS LSP too 47 | icon = "󱓻", 48 | }, 49 | }, 50 | 51 | telescope = { style = "borderless" }, -- borderless / bordered 52 | 53 | statusline = { 54 | enabled = true, 55 | theme = "default", -- default/vscode/vscode_colored/minimal 56 | separator_style = "default", -- default/round/block/arrow 57 | order = { 58 | "mode", 59 | "file", 60 | "git", 61 | "%=", 62 | "diagnostics", 63 | "live_server", 64 | "lsp", 65 | -- "copilot", 66 | "macro", 67 | "updates", 68 | "cwd", 69 | "cursor", 70 | }, 71 | 72 | modules = { 73 | lsp = function() 74 | if not rawget(vim, "lsp") then 75 | return "" 76 | end 77 | 78 | local bufnr = vim.api.nvim_win_get_buf(vim.g.statusline_winid or 0) 79 | local clients = vim.lsp.get_clients({ bufnr = bufnr }) 80 | 81 | if #clients == 0 then 82 | return "" 83 | end 84 | 85 | -- Check if expanded mode is enabled 86 | local expanded = vim.g.lsp_status_expanded or false 87 | local output = "%#St_Lsp# " 88 | 89 | -- Function to shorten client names 90 | local function format_client_name(name) 91 | if name == "typescript-tools" then 92 | return "ts-tools" 93 | elseif name == "tailwind-tools" then 94 | return "tw-tools" 95 | else 96 | return name 97 | end 98 | end 99 | 100 | if expanded then 101 | local names = {} 102 | for _, client in ipairs(clients) do 103 | table.insert(names, format_client_name(client.name)) 104 | end 105 | output = output .. " " .. table.concat(names, ", ") .. " " 106 | else 107 | local main_client = format_client_name(clients[1].name) 108 | for _, client in ipairs(clients) do 109 | if client.name == "typescript-tools" then 110 | main_client = format_client_name(client.name) 111 | break 112 | end 113 | end 114 | output = output .. " 󰜥" .. main_client .. " " 115 | end 116 | 117 | -- Make the entire component clickable to toggle expanded view 118 | return "%@v:lua.ToggleLspStatus@" .. output .. "%X" 119 | end, 120 | 121 | cursor = function() 122 | local current_line = vim.fn.line(".") 123 | local total_lines = vim.fn.line("$") 124 | local prec = math.floor((current_line / total_lines) * 100 + 0.5) 125 | local percent = (current_line == 1) and "Top" or (current_line == total_lines and "Bot" or prec .. "%%") 126 | return ( 127 | "%#St_pos_sep#" 128 | .. sep_l 129 | .. "%#St_pos_icon# %#St_pos_text# " 130 | .. percent 131 | .. " " 132 | .. current_line 133 | .. ":" 134 | .. vim.fn.col(".") 135 | .. " " 136 | ) 137 | end, 138 | 139 | macro = function() 140 | local macro_reg = vim.fn.reg_recording() 141 | return macro_reg ~= "" and ("%#St_macro_recording# " .. macro_reg .. " ") or "" 142 | end, 143 | 144 | copilot = function() 145 | return " " .. require("copilot_status").status_string() .. " " 146 | end, 147 | 148 | updates = function() 149 | if lazy_status.has_updates() then 150 | local updates_count = lazy_status.updates():match("%d+") or "0" 151 | -- return ("%#St_Updates_sep#" .. sep_l .. "%#St_Updates_Icon# %#Updates# " .. updates_count .. " ") 152 | return ("%#St_Updates_Icon# %#Updates#" .. updates_count .. " ") 153 | end 154 | return "" 155 | end, 156 | 157 | live_server = function() 158 | if vim.bo.filetype ~= "html" then 159 | return "" 160 | end 161 | 162 | local server_active = vim.g.live_server_active or false 163 | local output = "%#St_HtmlServer#" 164 | 165 | if server_active then 166 | -- Server is running, show stop icon 167 | output = output .. " 󰒏" 168 | -- Make clickable to stop server 169 | return "%@v:lua.StopLiveServer@" .. output .. "%X" 170 | else 171 | -- Server not running, show start icon 172 | output = output .. " 󰒋" 173 | -- Make clickable to start server 174 | return "%@v:lua.StartLiveServer@" .. output .. "%X" 175 | end 176 | end, 177 | }, 178 | }, 179 | 180 | tabufline = { 181 | enabled = false, 182 | lazyload = true, 183 | order = { "treeOffset", "buffers", "tabs", "btns" }, 184 | modules = nil, 185 | }, 186 | } 187 | 188 | options.colorify = { 189 | enabled = false, 190 | mode = "virtual", -- fg, bg, virtual 191 | virt_text = "󱓻 ", 192 | highlight = { hex = true, lspvars = true }, 193 | } 194 | 195 | -- Keybindings 196 | local map = vim.keymap.set 197 | map("n", "cH", " NvCheatsheet ", { desc = "Mapping cheatsheet" }) 198 | map("n", "tp", function() 199 | require("nvchad.themes").open() 200 | end, { desc = "Theme picker" }) 201 | map("n", "cN", require("nvchad.lsp.renamer"), { desc = "Nvchad Rename" }) 202 | map("n", "tT", function() 203 | require("base46").toggle_transparency() 204 | end, { desc = "Toggle transparency" }) 205 | 206 | -- Merge with external config if exists 207 | local status, chadrc = pcall(require, "chadrc") 208 | if status then 209 | vim.tbl_deep_extend("force", options, chadrc) 210 | end 211 | 212 | return options 213 | -------------------------------------------------------------------------------- /lua/config/autocmds.lua: -------------------------------------------------------------------------------- 1 | local autocmd = vim.api.nvim_create_autocmd 2 | 3 | -- Automatically sort classes in a .tsx file on save 4 | autocmd("BufWritePost", { 5 | pattern = { "*.tsx", "*.vue" }, 6 | callback = function() 7 | local clients = vim.lsp.get_clients({ name = "tailwindcss" }) 8 | if #clients > 0 then 9 | local ok, lsp = pcall(require, "tailwind-tools.lsp") 10 | if ok and lsp.sort_classes then 11 | pcall(lsp.sort_classes, true) 12 | end 13 | end 14 | end, 15 | }) 16 | 17 | local group = vim.api.nvim_create_augroup("CodeCompanionHooks", {}) 18 | 19 | autocmd({ "User" }, { 20 | pattern = "CodeCompanionInline*", 21 | group = group, 22 | callback = function(request) 23 | if request.match == "CodeCompanionInlineFinished" then 24 | -- Format the buffer after the inline request has completed 25 | require("conform").format({ bufnr = request.buf }) 26 | end 27 | end, 28 | }) 29 | 30 | local gdproject = io.open(vim.fn.getcwd() .. "/project.godot", "r") 31 | local godotserver = io.open("./godothost", "r") 32 | if gdproject then 33 | io.close(gdproject) 34 | if godotserver then 35 | io.close(godotserver) 36 | return 37 | end 38 | vim.fn.serverstart("./godothost") 39 | end 40 | 41 | -- Auto save buffer on leave 42 | autocmd("BufLeave", { 43 | pattern = "*", 44 | callback = function() 45 | vim.cmd("silent! wa") 46 | end, 47 | }) 48 | 49 | -- Remove trailing whitespace on save 50 | autocmd("BufWritePre", { 51 | pattern = "*", 52 | callback = function() 53 | vim.cmd([[silent! %s/\s\+$//e]]) 54 | end, 55 | }) 56 | 57 | -- Setup filetype for .aliasesrc 58 | autocmd({ "BufRead", "BufNewFile" }, { 59 | pattern = ".aliasesrc", 60 | callback = function() 61 | vim.bo.filetype = "zsh" 62 | end, 63 | }) 64 | 65 | autocmd("FileType", { 66 | pattern = "hyprlang", 67 | callback = function() 68 | vim.bo.commentstring = "# %s" 69 | end, 70 | }) 71 | -------------------------------------------------------------------------------- /lua/config/keymaps.lua: -------------------------------------------------------------------------------- 1 | -- Helper function for keymap options 2 | local function opts(desc, extra) 3 | local default = { noremap = true, silent = true, desc = desc } 4 | return extra and vim.tbl_extend("force", default, extra) or default 5 | end 6 | 7 | local N = "n" 8 | local V = "v" 9 | local I = "i" 10 | local T = "t" 11 | local N_V = { N, V } 12 | local N_I = { N, I } 13 | 14 | -- WhichKey group definitions 15 | local wk = require("which-key") 16 | wk.add({ 17 | { "a", group = "+AI" }, 18 | { "t", group = "+Themes & Tailwind" }, 19 | { "G", group = "+Gitsigns" }, 20 | { "E", group = "+Ecolog" }, 21 | }) 22 | 23 | -- Keymap definitions 24 | local keymaps = { 25 | -- =================== 26 | -- General Keymaps 27 | -- =================== 28 | { I, "", "", opts("Insert tab") }, 29 | { N, "", "yy[P", opts("Duplicate line up") }, 30 | { N, "", "yy]p", opts("Duplicate line down") }, 31 | { V, "", "yP", opts("Duplicate selection up") }, 32 | { V, "", "y]p", opts("Duplicate selection down") }, 33 | 34 | { N, "", "", opts("Block selection") }, 35 | 36 | { V, "d", '"ad', opts("Delete without yanking") }, 37 | { N_V, "p", '"+p', opts("Paste from system clipboard") }, 38 | { N, "c", '"ac', opts("Change without yanking") }, 39 | { V, "c", '"ac', opts("Change without yanking") }, 40 | { N, "x", '"ax', opts("Delete character without yanking") }, 41 | 42 | { I, "jj", "", opts("Exit insert mode") }, 43 | { N_I, "qq", "q", opts("Quick quit") }, 44 | { 45 | N, 46 | "QQ", 47 | function() 48 | Utils.close_all_buffers() 49 | end, 50 | opts("Quit all buffers"), 51 | }, 52 | 53 | { N, "", "zz", opts("Scroll down and center") }, 54 | { N, "", "zz", opts("Scroll up and center") }, 55 | 56 | -- =================== 57 | -- Plugin Keymaps 58 | -- =================== 59 | -- Lspsaga 60 | { N, "", "Lspsaga hover_doc", opts("Show hover doc") }, 61 | { N, "ol", "Lspsaga outline", opts("Show outline") }, 62 | { N, "d", "Lspsaga peek_definition", opts("Peek definition") }, 63 | { N, "t", "Lspsaga peek_type_definition", opts("Peek type definition") }, 64 | { 65 | N, 66 | "[d", 67 | function() 68 | require("lspsaga.diagnostic"):goto_prev() 69 | end, 70 | opts("Previous diagnostic"), 71 | }, 72 | { 73 | N, 74 | "]d", 75 | function() 76 | require("lspsaga.diagnostic"):goto_next() 77 | end, 78 | opts("Next diagnostic"), 79 | }, 80 | { 81 | N, 82 | "[e", 83 | function() 84 | require("lspsaga.diagnostic"):goto_prev({ severity = vim.diagnostic.severity.ERROR }) 85 | end, 86 | opts("Previous error"), 87 | }, 88 | { 89 | N, 90 | "]e", 91 | function() 92 | require("lspsaga.diagnostic"):goto_next({ severity = vim.diagnostic.severity.ERROR }) 93 | end, 94 | opts("Next error"), 95 | }, 96 | 97 | -- Obsidian 98 | { N, "On", ":execute 'ObsidianNew ' . input('Enter a name: ')", opts("New note") }, 99 | { N, "Os", "ObsidianQuickSwitch", opts("Quick switch") }, 100 | { 101 | N, 102 | "Of", 103 | function() 104 | require("custom.obsidian").follow_link() 105 | end, 106 | opts("Follow link"), 107 | }, 108 | { N, "Ob", "ObsidianBacklinks", opts("Backlinks") }, 109 | { N, "Od", "ObsidianDailies", opts("Dailies") }, 110 | { N, "Ot", "ObsidianTemplate", opts("Insert template") }, 111 | { N, "sO", "ObsidianSearch", opts("Search notes") }, 112 | { N, "Or", ":execute 'ObsidianRename ' . input('Enter new name: ')", opts("Rename note") }, 113 | { N, "Oc", "ObsidianToggleCheckbox", opts("Toggle checkbox") }, 114 | { N, "OT", "ObsidianTags", opts("Search tags") }, 115 | 116 | -- Sessions 117 | { 118 | N, 119 | "qS", 120 | function() 121 | require("persistence").select() 122 | end, 123 | opts("Select session"), 124 | }, 125 | { 126 | N, 127 | "ql", 128 | function() 129 | require("persistence").load({ last = true }) 130 | end, 131 | opts("Load last session"), 132 | }, 133 | { 134 | N, 135 | "qd", 136 | function() 137 | require("persistence").stop() 138 | end, 139 | opts("Don't save current session"), 140 | }, 141 | 142 | -- Tailwind Tools 143 | { N, "tts", "TailwindSort", opts("Tailwind Sort") }, 144 | { N, "ttS", "TailwindSortSelection", opts("Tailwind Sort Selection") }, 145 | { N, "ttc", "TailwindConcealToggle", opts("Tailwind Conceal Toggle") }, 146 | 147 | -- Buffers 148 | -- { 149 | -- N, 150 | -- "]b", 151 | -- function() 152 | -- require("custom.buffers").next_buffer_in_tab() 153 | -- end, 154 | -- opts("Next buffer in tab"), 155 | -- }, 156 | -- { 157 | -- N, 158 | -- "[b", 159 | -- function() 160 | -- require("custom.buffers").prev_buffer_in_tab() 161 | -- end, 162 | -- opts("Previous buffer in tab"), 163 | -- }, 164 | -- { 165 | -- N, 166 | -- "[B", 167 | -- function() 168 | -- require("nvchad.tabufline").move_buf(-1) 169 | -- end, 170 | -- opts("Move buffer left"), 171 | -- }, 172 | -- { 173 | -- N, 174 | -- "]B", 175 | -- function() 176 | -- require("nvchad.tabufline").move_buf(1) 177 | -- end, 178 | -- opts("Move buffer right"), 179 | -- }, 180 | { N, "bd", "lua Snacks.bufdelete()", opts("Delete buffer") }, 181 | 182 | -- Treewalker 183 | { N_V, "", "Treewalker Up", opts("Treewalker Up") }, 184 | { N_V, "", "Treewalker Down", opts("Treewalker Down") }, 185 | { N_V, "", "Treewalker Right", opts("Treewalker Right") }, 186 | { N_V, "", "Treewalker Left", opts("Treewalker Left") }, 187 | { N, "", "Treewalker SwapDown", opts("Swap Down") }, 188 | { N, "", "Treewalker SwapUp", opts("Swap Up") }, 189 | { N, "", "Treewalker SwapRight", opts("Swap Right") }, 190 | { N, "", "Treewalker SwapLeft", opts("Swap Left") }, 191 | 192 | -- Tabs 193 | { N, "", "tabnext", opts("Switch Tab") }, 194 | 195 | -- Miscellaneous 196 | { I, "::", ":", opts("Enter command mode in insert mode") }, 197 | { 198 | N, 199 | "Q", 200 | function() 201 | require("quicker").toggle() 202 | end, 203 | opts("Toggle quickfix"), 204 | }, 205 | { 206 | N, 207 | "L", 208 | function() 209 | require("quicker").toggle({ loclist = true }) 210 | end, 211 | opts("Toggle loclist"), 212 | }, 213 | { 214 | N, 215 | "z=", 216 | function() 217 | Utils.select("spelling") 218 | end, 219 | opts("Spelling suggestions"), 220 | }, 221 | { N, "", "BufferLinePick", opts("Bufferline picke") }, 222 | { 223 | N, 224 | "gp", 225 | function() 226 | Utils.open_github_repo() 227 | end, 228 | opts("Open Github repo"), 229 | }, 230 | { { N, T }, "", "Lspsaga term_toggle", opts("Toggle terminal") }, 231 | { 232 | N, 233 | "Mp", 234 | function() 235 | if vim.bo.filetype == "markdown" then 236 | vim.fn.system("xdg-open http://localhost:8989") 237 | else 238 | vim.notify("Not a markdown file!", "warn") 239 | end 240 | end, 241 | opts("Markdown preview"), 242 | }, 243 | { 244 | V, 245 | "cW", 246 | function() 247 | Utils.wrap_with_tag() 248 | end, 249 | opts("Wrap selection with tag"), 250 | }, 251 | { 252 | N, 253 | "sk", 254 | function() 255 | Utils.vertical_picker("keymaps") 256 | end, 257 | }, 258 | -- { 259 | -- N, 260 | -- "cL", 261 | -- require("lsp_lines").toggle, 262 | -- opts("Toggle LSP Lines"), 263 | -- }, 264 | { 265 | N, 266 | "R", 267 | "OverseerRunC", 268 | opts("Overseer Run"), 269 | }, 270 | { 271 | N, 272 | "Rt", 273 | "OverseerToggle", 274 | opts("Overseer Toggle"), 275 | }, 276 | { 277 | N, 278 | "", 279 | "gcc", 280 | opts("Comment line", { remap = true }), 281 | }, 282 | { 283 | N, 284 | "Q", 285 | "q", 286 | opts("Record macro"), 287 | }, 288 | { 289 | N, 290 | "q", 291 | "", 292 | opts("Disable default macro key"), 293 | }, 294 | { 295 | N_V, 296 | "", 297 | "gcc", 298 | opts("Comment selection", { remap = true }), 299 | }, 300 | { 301 | I, 302 | "", 303 | ":normal gcca", 304 | opts("Comment line and return to insert mode"), 305 | }, 306 | { 307 | N, 308 | "", 309 | "", 310 | }, 311 | { 312 | N, 313 | "sm", 314 | require("recall.snacks").pick, 315 | opts("Search Marks"), 316 | }, 317 | { 318 | N, 319 | "", 320 | "RecallToggle", 321 | opts("Recall Toggle"), 322 | }, 323 | { 324 | N, 325 | "mr", 326 | "RecallUnmark", 327 | opts("Recall Unmark"), 328 | }, 329 | { 330 | N, 331 | "ma", 332 | "RecallMark", 333 | opts("Recall Mark"), 334 | }, 335 | { 336 | N, 337 | "]'", 338 | "RecallNext", 339 | opts("Recall Next"), 340 | }, 341 | { 342 | N, 343 | "['", 344 | "RecallPrevious", 345 | opts("Recall Prev"), 346 | }, 347 | { 348 | N, 349 | "mX", 350 | "RecallClear", 351 | opts("Recall Clear"), 352 | }, 353 | { 354 | N, 355 | "]m", 356 | function() 357 | local inst = require("grug-far").get_instance() 358 | if inst then 359 | inst:goto_next_match({ wrap = true }) 360 | inst:open_location() 361 | end 362 | end, 363 | opts("Grug-far next match"), 364 | }, 365 | } 366 | 367 | -- Apply all keymaps 368 | for _, keymap in ipairs(keymaps) do 369 | local mode = keymap[1] 370 | local lhs = keymap[2] 371 | local rhs = keymap[3] 372 | local options = keymap[4] 373 | vim.keymap.set(mode, lhs, rhs, options) 374 | end 375 | -------------------------------------------------------------------------------- /lua/config/lazy.lua: -------------------------------------------------------------------------------- 1 | vim.g.base46_cache = vim.fn.stdpath("data") .. "/base46_cache/" 2 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 3 | 4 | if not (vim.uv or vim.loop).fs_stat(lazypath) then 5 | vim.fn.system({ 6 | "git", 7 | "clone", 8 | "--filter=blob:none", 9 | "https://github.com/folke/lazy.nvim.git", 10 | "--branch=stable", 11 | lazypath, 12 | }) 13 | end 14 | vim.opt.rtp:prepend(lazypath) 15 | 16 | require("lazy").setup({ 17 | rocks = { 18 | hererocks = true, 19 | }, 20 | spec = { 21 | { 22 | "LazyVim/LazyVim", 23 | import = "lazyvim.plugins", 24 | opts = { 25 | colorscheme = "nvchad", 26 | }, 27 | }, 28 | { import = "plugins" }, 29 | }, 30 | ui = { 31 | border = "single", 32 | }, 33 | defaults = { 34 | lazy = false, 35 | version = false, -- always use the latest git commit 36 | -- version = "*", -- try installing the latest stable version for plugins that support semver 37 | }, 38 | checker = { enabled = true }, -- automatically check for plugin updates 39 | performance = { 40 | rtp = { 41 | -- disable some rtp plugins 42 | disabled_plugins = { 43 | "gzip", 44 | -- "matchit", 45 | -- "matchparen", 46 | -- "netrwPlugin", 47 | "tarPlugin", 48 | "tohtml", 49 | "tutor", 50 | "zipPlugin", 51 | }, 52 | }, 53 | }, 54 | }) 55 | 56 | for _, v in ipairs(vim.fn.readdir(vim.g.base46_cache)) do 57 | dofile(vim.g.base46_cache .. v) 58 | end 59 | -------------------------------------------------------------------------------- /lua/config/options.lua: -------------------------------------------------------------------------------- 1 | -- Options are automatically loaded before lazy.nvim startup 2 | -- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua 3 | -- Add any additional options here 4 | local opt = vim.opt 5 | 6 | vim.g.lazygit_config = true 7 | vim.g.node_host_prog = "$HOME/.bun/bin/neovim-node-host" 8 | 9 | opt.laststatus = 3 10 | 11 | opt.clipboard = "unnamedplus" 12 | 13 | -- Make cursor blink 14 | opt.guicursor = { 15 | "n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50", 16 | "a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor", 17 | "sm:block-blinkwait175-blinkoff150-blinkon175", 18 | } 19 | opt.linebreak = true 20 | -- Set tab width 21 | opt.expandtab = false 22 | opt.tabstop = 4 23 | opt.shiftwidth = 4 24 | opt.autoindent = true 25 | 26 | vim.cmd([[cab Wq wq]]) 27 | 28 | vim.diagnostic.config({ 29 | virtual_text = false, 30 | float = { 31 | border = "rounded", 32 | max_width = 60, 33 | max_height = 10, 34 | }, 35 | }) 36 | 37 | vim.cmd([[tnoremap pwd\|wl-copy:cd +]]) 38 | 39 | opt.fillchars = { 40 | diff = "╱", 41 | } 42 | 43 | opt.diffopt = { 44 | "internal", 45 | "filler", 46 | "closeoff", 47 | "context:12", 48 | "algorithm:histogram", 49 | "linematch:200", 50 | "indent-heuristic", 51 | } 52 | 53 | vim.opt_local.conceallevel = 2 54 | opt.fillchars:append({ eob = " " }) 55 | 56 | vim.loader.enable() 57 | 58 | -- Scss syntax highlighting in Vue files 59 | vim.cmd([[ 60 | autocmd FileType vue syntax include @scss syntax/scss.vim 61 | autocmd FileType vue syntax region vueStyle matchgroup=vueTag start=// end=/<\/style>/ contains=@scss keepend 62 | ]]) 63 | 64 | vim.opt.conceallevel = 2 65 | 66 | opt.exrc = true 67 | opt.secure = true 68 | -------------------------------------------------------------------------------- /lua/config/tailwind.lua: -------------------------------------------------------------------------------- 1 | local tailwind_lsp_name = "tailwindcss" 2 | local stop_timer = nil 3 | 4 | -- Check if cursor is inside the value of class="" or className="" 5 | local function is_cursor_inside_class_attr() 6 | local row, col = unpack(vim.api.nvim_win_get_cursor(0)) 7 | local line = vim.api.nvim_get_current_line() 8 | 9 | for attr_start, attr, val_start, value in line:gmatch('()%f[%w](className?)%s*=%s*"(.-)"()') do 10 | local value_start_col = line:find(attr .. '%s*=%s*"', attr_start) + #attr + 1 11 | if value_start_col and col >= value_start_col and col <= value_start_col + #value then 12 | return true 13 | end 14 | end 15 | 16 | return false 17 | end 18 | 19 | -- Start TailwindCSS LSP if not already running 20 | local function maybe_start_tailwind() 21 | local clients = vim.lsp.get_clients({ name = tailwind_lsp_name, bufnr = 0 }) 22 | local attached = #clients > 0 and clients[1].initialized and not clients[1].is_stopping() 23 | 24 | if not attached then 25 | vim.lsp.start({ 26 | name = tailwind_lsp_name, 27 | cmd = { "tailwindcss-language-server", "--stdio" }, 28 | root_dir = require("lspconfig.util").root_pattern( 29 | "tailwind.config.js", 30 | "tailwind.config.ts", 31 | "postcss.config.js", 32 | "package.json", 33 | ".git" 34 | ), 35 | }) 36 | end 37 | end 38 | 39 | -- Stop TailwindCSS LSP after delay using libuv timer 40 | local function delayed_stop() 41 | if stop_timer then 42 | stop_timer:stop() 43 | stop_timer:close() 44 | stop_timer = nil 45 | end 46 | 47 | stop_timer = vim.loop.new_timer() 48 | stop_timer:start(1000, 0, function() 49 | vim.schedule(function() 50 | local clients = vim.lsp.get_clients({ name = tailwind_lsp_name, bufnr = 0 }) 51 | for _, client in ipairs(clients) do 52 | if not client.is_stopping() then 53 | client.stop() 54 | end 55 | end 56 | end) 57 | end) 58 | end 59 | 60 | -- Autocommands 61 | vim.api.nvim_create_autocmd("InsertEnter", { 62 | pattern = { "*.html", "*.jsx", "*.tsx", "*.vue" }, 63 | callback = function() 64 | if is_cursor_inside_class_attr() then 65 | maybe_start_tailwind() 66 | end 67 | end, 68 | }) 69 | 70 | vim.api.nvim_create_autocmd("InsertLeave", { 71 | pattern = { "*.html", "*.jsx", "*.tsx", "*.vue" }, 72 | callback = function() 73 | delayed_stop() 74 | end, 75 | }) 76 | -------------------------------------------------------------------------------- /lua/custom/buffers.lua: -------------------------------------------------------------------------------- 1 | -- Buffers utils 2 | local M = {} 3 | 4 | function M.next_buffer_in_tab() 5 | local current_buf = vim.api.nvim_get_current_buf() 6 | 7 | -- Get all buffers in the current tab 8 | local tab_bufs = vim.t.bufs or {} 9 | 10 | -- Find the index of the current buffer 11 | local current_index = nil 12 | for i, buf in ipairs(tab_bufs) do 13 | if buf == current_buf then 14 | current_index = i 15 | break 16 | end 17 | end 18 | 19 | if current_index then 20 | -- Cycle to the next buffer in the tab 21 | local next_index = current_index % #tab_bufs + 1 22 | local next_buf = tab_bufs[next_index] 23 | vim.api.nvim_set_current_buf(next_buf) 24 | end 25 | end 26 | 27 | function M.prev_buffer_in_tab() 28 | local current_buf = vim.api.nvim_get_current_buf() 29 | 30 | -- Get all buffers in the current tab 31 | local tab_bufs = vim.t.bufs or {} 32 | 33 | -- Find the index of the current buffer 34 | local current_index = nil 35 | for i, buf in ipairs(tab_bufs) do 36 | if buf == current_buf then 37 | current_index = i 38 | break 39 | end 40 | end 41 | 42 | if current_index then 43 | -- Cycle to the previous buffer in the tab 44 | local prev_index = (current_index - 2 + #tab_bufs) % #tab_bufs + 1 45 | local prev_buf = tab_bufs[prev_index] 46 | vim.api.nvim_set_current_buf(prev_buf) 47 | end 48 | end 49 | 50 | return M 51 | -------------------------------------------------------------------------------- /lua/custom/copilot-stl.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | -- Configuration 4 | local config = { 5 | icons = { 6 | enabled = " ", 7 | sleep = " ", 8 | disabled = " ", 9 | warning = " ", 10 | unknown = " ", 11 | }, 12 | colors = { 13 | enabled = "#89AF6D", 14 | sleep = "#AEB7D0", 15 | disabled = "#6272A4", 16 | warning = "#FFB86C", 17 | unknown = "#42464E", 18 | }, 19 | highlights = { 20 | enabled = "St_copilot_enabled", 21 | sleep = "St_copilot_sleep", 22 | disabled = "St_copilot_disabled", 23 | warning = "St_copilot_warning", 24 | unknown = "St_copilot_unknown", 25 | }, 26 | } 27 | 28 | -- Spinner configuration 29 | local spinner = { 30 | frames = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }, 31 | current_frame = 1, 32 | timer = nil, 33 | } 34 | 35 | -- Setup highlight groups 36 | local function setup_highlights() 37 | for state, hl_name in pairs(config.highlights) do 38 | local bg = "#000000" -- Default fallback 39 | local status_bg = vim.fn.synIDattr(vim.fn.hlID("StatusLine"), "bg#") 40 | 41 | -- Handle empty or invalid bg color 42 | if status_bg and status_bg ~= "" then 43 | bg = status_bg 44 | end 45 | 46 | vim.api.nvim_set_hl(0, hl_name, { 47 | fg = config.colors[state], 48 | bg = bg, 49 | default = true, -- This allows other colorschemes to override if needed 50 | }) 51 | end 52 | end 53 | 54 | -- Get next spinner frame 55 | local function get_next_spinner() 56 | local frame = spinner.frames[spinner.current_frame] 57 | spinner.current_frame = spinner.current_frame + 1 58 | if spinner.current_frame > #spinner.frames then 59 | spinner.current_frame = 1 60 | end 61 | return frame 62 | end 63 | 64 | -- Start spinner animation 65 | local function start_spinner() 66 | if not spinner.timer then 67 | spinner.timer = vim.loop.new_timer() 68 | spinner.timer:start( 69 | 0, 70 | 100, 71 | vim.schedule_wrap(function() 72 | vim.cmd("redrawstatus") 73 | end) 74 | ) 75 | end 76 | end 77 | 78 | -- Stop spinner animation 79 | local function stop_spinner() 80 | if spinner.timer then 81 | spinner.timer:stop() 82 | spinner.timer:close() 83 | spinner.timer = nil 84 | end 85 | end 86 | 87 | -- Helper function to check if buffer is attached 88 | local function is_buffer_attached() 89 | local buf = vim.api.nvim_get_current_buf() 90 | 91 | -- Handle both newer and older Neovim API 92 | local get_clients = vim.lsp.get_active_clients or vim.lsp.get_clients 93 | local clients = get_clients({ bufnr = buf }) 94 | 95 | for _, client in pairs(clients) do 96 | if client.name == "copilot" then 97 | -- Check if buffer is attached using the available method 98 | if vim.lsp.buf_is_attached then 99 | return vim.lsp.buf_is_attached(buf, client.id) 100 | elseif client.attached_buffers then 101 | return client.attached_buffers[buf] or false 102 | end 103 | -- Default to true if we can't specifically check 104 | return true 105 | end 106 | end 107 | return false 108 | end 109 | 110 | function M.get_status() 111 | if not package.loaded["copilot"] then 112 | stop_spinner() 113 | return { 114 | state = "unknown", 115 | icon = config.icons.unknown, 116 | hl = config.highlights.unknown, 117 | } 118 | end 119 | 120 | local has_copilot_suggestion = pcall(require, "copilot.suggestion") 121 | local has_copilot_client, copilot_client = pcall(require, "copilot.client") 122 | local has_copilot_api, copilot_api = pcall(require, "copilot.api") 123 | local has_copilot_config, copilot_config = pcall(require, "copilot.config") 124 | 125 | -- Get auto trigger status more safely 126 | local auto_trigger = vim.b.copilot_suggestion_auto_trigger 127 | if auto_trigger == nil and has_copilot_config then 128 | auto_trigger = copilot_config.get("suggestion").auto_trigger 129 | end 130 | 131 | -- Check if disabled 132 | local disabled = false 133 | if has_copilot_client then 134 | pcall(function() 135 | disabled = copilot_client.is_disabled() 136 | end) 137 | end 138 | 139 | if disabled then 140 | stop_spinner() 141 | return { 142 | state = "disabled", 143 | icon = config.icons.disabled, 144 | hl = config.highlights.disabled, 145 | } 146 | end 147 | 148 | if not is_buffer_attached() then 149 | stop_spinner() 150 | return { 151 | state = "unknown", 152 | icon = config.icons.unknown, 153 | hl = config.highlights.unknown, 154 | } 155 | end 156 | 157 | -- Check warning status 158 | local warning = false 159 | if has_copilot_api then 160 | pcall(function() 161 | if copilot_api.status and copilot_api.status.data then 162 | warning = copilot_api.status.data.status == "Warning" 163 | end 164 | end) 165 | end 166 | 167 | if warning then 168 | stop_spinner() 169 | return { 170 | state = "warning", 171 | icon = config.icons.warning, 172 | hl = config.highlights.warning, 173 | } 174 | end 175 | 176 | -- Check loading status 177 | local loading = false 178 | if has_copilot_api then 179 | pcall(function() 180 | if copilot_api.status and copilot_api.status.data then 181 | loading = copilot_api.status.data.status == "InProgress" 182 | end 183 | end) 184 | end 185 | 186 | if loading then 187 | start_spinner() 188 | return { 189 | state = "loading", 190 | icon = get_next_spinner(), 191 | hl = config.highlights.enabled, 192 | } 193 | end 194 | 195 | if auto_trigger == false then 196 | stop_spinner() 197 | return { 198 | state = "sleep", 199 | icon = config.icons.sleep, 200 | hl = config.highlights.sleep, 201 | } 202 | end 203 | 204 | stop_spinner() 205 | return { 206 | state = "enabled", 207 | icon = config.icons.enabled, 208 | hl = config.highlights.enabled, 209 | } 210 | end 211 | 212 | function M.setup(user_config) 213 | if user_config then 214 | config.icons = vim.tbl_deep_extend("force", config.icons, user_config.icons or {}) 215 | config.colors = vim.tbl_deep_extend("force", config.colors, user_config.colors or {}) 216 | config.highlights = vim.tbl_deep_extend("force", config.highlights, user_config.highlights or {}) 217 | end 218 | setup_highlights() 219 | end 220 | 221 | function M.cleanup() 222 | stop_spinner() 223 | end 224 | 225 | -- Initialize highlights on load 226 | setup_highlights() 227 | 228 | return M 229 | -------------------------------------------------------------------------------- /lua/custom/hl.lua: -------------------------------------------------------------------------------- 1 | local colors = dofile(vim.g.base46_cache .. "colors") 2 | local isTransparent = require("custom.utils").is_transparent_theme() 3 | _G.Colors = dofile(vim.g.base46_cache .. "colors") 4 | 5 | local M = {} 6 | M.is_transparent = isTransparent 7 | local hl = vim.api.nvim_set_hl 8 | 9 | if not isTransparent then 10 | hl(0, "TelescopeBorder", { fg = "#242728", bg = "#242728" }) 11 | hl(0, "SnacksPickerBorder", { fg = "#1E2122", bg = "#1E2122" }) 12 | hl(0, "SnacksPickerInputBorder", { fg = "#242728", bg = "#242728" }) 13 | else 14 | hl(0, "SnacksPickerBorder", { fg = "#1E2122", bg = "None" }) 15 | hl(0, "AvantePromptInput", { fg = Colors.white, bg = "#1E2122" }) 16 | hl(0, "AvantePromptInputBorder", { fg = "#2D3031", bg = "#1E2122" }) 17 | hl(0, "TinyInlineDiagnosticVirtualTextArrow", { fg = Colors.white, bg = "NONE" }) 18 | end 19 | 20 | hl(0, "St_HtmlServer", { fg = Colors.teal, bg = "NONE" }) 21 | 22 | local highlight_maps = { 23 | -- Basic mappings 24 | menu = { 25 | ["BlinkCmpMenu"] = "CmpPmenu", 26 | ["BlinkCmpMenuBorder"] = "CmpBorder", 27 | ["BlinkCmpDoc"] = "CmpDoc", 28 | ["BlinkCmpDocBorder"] = "CmpDocBorder", 29 | ["BlinkCmpMenuSelection"] = "CmpSel", 30 | }, 31 | 32 | lspSaga = { 33 | ["HoverNormal"] = "CmpPmenu", 34 | ["HoverBorder"] = "CmpDocBorder", 35 | }, 36 | 37 | -- Label mappings 38 | label = { 39 | ["BlinkCmpLabel"] = "CmpItemAbbr", 40 | ["BlinkCmpLabelMatch"] = "CmpItemAbbrMatch", 41 | }, 42 | 43 | -- Additional UI elements 44 | ui = { 45 | ["BlinkCmpScrollBarThumb"] = "CmpBorder", 46 | ["BlinkCmpScrollBarGutter"] = "CmpPmenu", 47 | ["BlinkCmpSignatureHelp"] = "CmpDoc", 48 | ["BlinkCmpSignatureHelpBorder"] = "CmpDocBorder", 49 | ["BlinkCmpSignatureHelpActiveParameter"] = "CmpItemAbbrMatch", 50 | ["BlinkCmpGhostText"] = "CmpBorder", 51 | ["BlinkCmpDocSeparator"] = "CmpDocBorder", 52 | ["BlinkCmpDocCursorLine"] = "PmenuSel", 53 | }, 54 | 55 | -- SnacksPicker mappings to Telescope highlights 56 | snacksPicker = { 57 | ["SnacksPickerBorder"] = "TelescopeBorder", 58 | ["SnacksPickerInput"] = "TelescopePromptNormal", 59 | ["SnacksPickerInputBorder"] = "TelescopePromptBorder", 60 | ["SnacksPickerBoxBorder"] = "TelescopeBorder", 61 | ["SnacksPickerTitle"] = "TelescopePromptTitle", 62 | ["SnacksPickerBoxTitle"] = "TelescopePromptTitle", 63 | ["SnacksPickerList"] = "TelescopePromptNormal", 64 | ["SnacksPickerPrompt"] = "TelescopePromptPrefix", 65 | ["SnacksPickerPreviewTitle"] = "TelescopePreviewTitle", 66 | ["SnacksPickerPreview"] = "TelescopePreviewNormal", 67 | ["SnacksPickerToggle"] = "TelescopeSelectionCaret", 68 | ["SnacksNormal"] = "TelescopeNormal", 69 | ["SnacksBackdrop"] = "TelescopeNormal", 70 | }, 71 | 72 | minifiles = { 73 | ["MiniFilesBorder"] = "Comment", 74 | ["MiniFilesBorderModified"] = "TelescopeBorder", 75 | ["MiniFilesDirectory"] = "TelescopePreviewDirectory", 76 | -- ["MiniFilesFile"] = "TelescopePreviewNormal", 77 | ["MiniFilesNormal"] = "TelescopeNormal", 78 | ["MiniFilesTitle"] = "TelescopePreviewTitle", 79 | ["MiniFilesTitleFocused"] = "TelescopePromptTitle", 80 | }, 81 | 82 | misc = { 83 | ["SagaBorder"] = "@symbol", 84 | ["MiniPickBorder"] = "TelescopeBorder", 85 | }, 86 | } 87 | 88 | -- Kind mappings table 89 | local kind_types = { 90 | "SuperMaven", 91 | "TabNine", 92 | "Codium", 93 | "Copilot", 94 | "TypeParameter", 95 | "Operator", 96 | "Event", 97 | "Value", 98 | "Struct", 99 | "EnumMember", 100 | "Reference", 101 | "Color", 102 | "Interface", 103 | "File", 104 | "Class", 105 | "Unit", 106 | "Enum", 107 | "Property", 108 | "Module", 109 | "Folder", 110 | "Constructor", 111 | "Method", 112 | "Keyword", 113 | "Type", 114 | "Structure", 115 | "Text", 116 | "Snippet", 117 | "Variable", 118 | "Identifier", 119 | "Function", 120 | "Constant", 121 | "Field", 122 | } 123 | 124 | function M.setup_highlights() 125 | for _, group in pairs(highlight_maps) do 126 | for blink_hl, cmp_hl in pairs(group) do 127 | vim.cmd(string.format("hi! link %s %s", blink_hl, cmp_hl)) 128 | end 129 | end 130 | 131 | for _, kind in ipairs(kind_types) do 132 | local blink_hl = string.format("BlinkCmpKind%s", kind) 133 | local cmp_hl = string.format("CmpItemKind%s", kind) 134 | vim.cmd(string.format("hi! link %s %s", blink_hl, cmp_hl)) 135 | end 136 | vim.api.nvim_set_hl(0, "@keyword.repeat", { fg = colors.yellow, italic = true, bold = true }) 137 | end 138 | 139 | -- ======================== 140 | -- Custom highlights 141 | -- ======================== 142 | 143 | function M.set_hl(group, fg, bg, opts) 144 | opts = opts or {} 145 | opts.fg = fg 146 | opts.bg = bg 147 | hl(0, group, opts) 148 | end 149 | 150 | M.statusline_bg = Snacks.util.color("StatusLine", "bg") 151 | M.file_bg = Snacks.util.color("St_file", "bg") 152 | 153 | M.highlights = { 154 | St_macro_recording = { fg = "#CA6169", bg = M.statusline_bg, opts = { bold = true } }, 155 | Updates = { fg = colors.teal, bg = "NONE" }, 156 | St_Updates_Icon = { fg = colors.teal, bg = "NONE" }, 157 | St_Updates_sep = { fg = colors.teal, bg = M.statusline_bg }, 158 | } 159 | 160 | function M.apply_highlights() 161 | for group, highlight in pairs(M.highlights) do 162 | M.set_hl(group, highlight.fg, highlight.bg, highlight.opts) 163 | end 164 | end 165 | 166 | M.apply_highlights() 167 | 168 | vim.api.nvim_create_autocmd({ "ColorScheme", "BufWritePost", "FileType" }, { 169 | pattern = { "NvThemeReload" }, 170 | callback = function() 171 | M.setup_highlights() 172 | end, 173 | }) 174 | 175 | return M 176 | -------------------------------------------------------------------------------- /lua/custom/multi-grep.lua: -------------------------------------------------------------------------------- 1 | local MiniPick = require("mini.pick") 2 | 3 | local M = {} 4 | local symbol = "::" 5 | local function create_multigrep_picker() 6 | return function() 7 | local process 8 | local set_items_opts = { do_match = false } 9 | ---@diagnostic disable-next-line: undefined-field 10 | local spawn_opts = { cwd = vim.uv.cwd() } 11 | 12 | local match = function(_, _, query) 13 | -- Kill previous process 14 | ---@diagnostic disable-next-line: undefined-field 15 | pcall(vim.loop.process_kill, process) 16 | 17 | -- For empty query, explicitly set empty items to indicate "not working" 18 | if #query == 0 then 19 | return MiniPick.set_picker_items({}, set_items_opts) 20 | end 21 | 22 | -- Get the full query string 23 | local full_query = table.concat(query) 24 | -- Split on symbol 25 | -- old one which doesn't need if statment: local search_pattern, file_pattern = unpack(vim.split(full_query, symbol, { plain = true })) 26 | local search_pattern, file_pattern = full_query:match("^(.-)" .. symbol .. "(.*)$") 27 | if not file_pattern then 28 | search_pattern = full_query 29 | end 30 | 31 | -- Build command 32 | local command = { 33 | "rg", 34 | "--color=never", 35 | "--no-heading", 36 | "--with-filename", 37 | "--line-number", 38 | "--column", 39 | "--smart-case", 40 | } 41 | 42 | -- Add search pattern 43 | if search_pattern and search_pattern ~= "" then 44 | table.insert(command, "-e") 45 | table.insert(command, search_pattern) 46 | end 47 | 48 | -- Add file/dir pattern if provided 49 | if file_pattern and file_pattern ~= "" then 50 | table.insert(command, "-g") 51 | table.insert(command, file_pattern) 52 | end 53 | 54 | process = MiniPick.set_picker_items_from_cli(command, { 55 | postprocess = function(lines) 56 | local results = {} 57 | for _, line in ipairs(lines) do 58 | if line ~= "" then 59 | -- I had nightmare doing this line, I hope there will be a better way 60 | local file, lnum, col, text = line:match("([^:]+):(%d+):(%d+):(.*)") 61 | if file then 62 | -- Format the item in a way that default_choose can handle - yay 63 | results[#results + 1] = { 64 | path = file, 65 | lnum = tonumber(lnum), 66 | col = tonumber(col), 67 | text = line, 68 | } 69 | end 70 | end 71 | end 72 | return results 73 | end, 74 | set_items_opts = set_items_opts, 75 | spawn_opts = spawn_opts, 76 | }) 77 | end 78 | 79 | return MiniPick.start({ 80 | source = { 81 | items = {}, 82 | name = "Multi Grep", 83 | match = match, 84 | show = function(buf_id, items_to_show, query) 85 | MiniPick.default_show(buf_id, items_to_show, query, { show_icons = true }) 86 | end, 87 | choose = MiniPick.default_choose, 88 | }, 89 | }) 90 | end 91 | end 92 | 93 | function M.setup() 94 | MiniPick.registry.multigrep = create_multigrep_picker() 95 | vim.keymap.set("n", "fm", function() 96 | MiniPick.registry.multigrep() 97 | end) 98 | end 99 | 100 | return M 101 | -------------------------------------------------------------------------------- /lua/custom/utils.lua: -------------------------------------------------------------------------------- 1 | _G.Utils = {} 2 | 3 | -- UI-related functions 4 | function Utils.is_transparent_theme() 5 | return require("nvconfig").base46.transparency 6 | end 7 | 8 | function _G.ToggleLspStatus() 9 | vim.g.lsp_status_expanded = not (vim.g.lsp_status_expanded or false) 10 | -- Force statusline update 11 | vim.cmd("redrawstatus") 12 | end 13 | 14 | function _G.StartLiveServer() 15 | vim.cmd("LiveServerStart") 16 | vim.g.live_server_active = true 17 | -- Force statusline update 18 | vim.cmd("redrawstatus") 19 | end 20 | 21 | function _G.StopLiveServer() 22 | vim.cmd("LiveServerStop") 23 | vim.g.live_server_active = false 24 | -- Force statusline update 25 | vim.cmd("redrawstatus") 26 | end 27 | 28 | -- HTML/markup functions 29 | function Utils.wrap_with_tag() 30 | -- Save the current visual selection 31 | vim.cmd('normal! "xy') 32 | local selected_text = vim.fn.getreg("x") 33 | 34 | if not selected_text or selected_text == "" then 35 | vim.api.nvim_echo({ { "No text selected", "ErrorMsg" } }, false, {}) 36 | return 37 | end 38 | 39 | -- Common HTML tags 40 | local common_tags = { 41 | "div", 42 | "span", 43 | "section", 44 | "article", 45 | "header", 46 | "footer", 47 | "nav", 48 | "aside", 49 | "main", 50 | "p", 51 | "h1", 52 | "h2", 53 | "h3", 54 | "strong", 55 | "em", 56 | "code", 57 | "pre", 58 | "ul", 59 | "ol", 60 | "li", 61 | "table", 62 | "thead", 63 | "tbody", 64 | "tr", 65 | "th", 66 | "td", 67 | "a", 68 | "button", 69 | "form", 70 | } 71 | 72 | -- Create menu items for vim.ui.select 73 | local menu_items = vim.tbl_extend("force", common_tags, { "Custom..." }) 74 | 75 | -- Show selection menu 76 | Utils.items_select(menu_items, { 77 | prompt = "Select HTML tag:", 78 | format_item = function(item) 79 | return item 80 | end, 81 | }, function(choice, idx) 82 | if not choice then 83 | return 84 | end 85 | 86 | local tag 87 | if choice == "Custom..." then 88 | -- Prompt for custom tag if user selects "Custom..." 89 | tag = vim.fn.input("Enter custom HTML tag: ") 90 | else 91 | tag = choice 92 | end 93 | 94 | if tag == "" then 95 | return 96 | end 97 | 98 | -- Extract the tag name for closing tag 99 | local tag_name = string.match(tag, "^([%w-]+)") or tag 100 | 101 | -- Create wrapped text with the selected/custom tag 102 | local wrapped_text = "<" .. tag .. ">" .. selected_text .. "" 103 | 104 | -- Replace the selection with the wrapped text 105 | vim.fn.setreg("x", wrapped_text) 106 | vim.cmd('normal! gv"xp') 107 | 108 | -- Report success 109 | vim.api.nvim_echo({ { string.format("Wrapped with <%s>", tag), "Normal" } }, false, {}) 110 | end) 111 | end 112 | 113 | -- Web/URL functions 114 | function Utils.open_github_repo() 115 | local line = vim.api.nvim_get_current_line() 116 | 117 | -- Match text inside quotes on the current line 118 | local repo = line:match('".-"') or line:match("'.-'") 119 | if not repo then 120 | vim.notify("No valid repo found on this line.", vim.log.levels.ERROR) 121 | return 122 | end 123 | 124 | -- Remove the quotes from the matched text 125 | repo = repo:sub(2, -2) 126 | 127 | -- Ensure it's in the format user/repo 128 | if not repo:match("^[%w._-]+/[%w._-]+$") then 129 | vim.notify("Invalid GitHub repo format.", vim.log.levels.ERROR) 130 | return 131 | end 132 | 133 | -- Construct the GitHub URL 134 | local url = "https://github.com/" .. repo 135 | vim.notify("Opening: " .. url, vim.log.levels.INFO) 136 | 137 | -- Open the URL in the default browser 138 | vim.fn.jobstart({ "xdg-open", url }, { detach = true }) 139 | end 140 | 141 | -- Setup commands 142 | local function setup_commands() 143 | vim.api.nvim_create_user_command( 144 | "WrapWithTag", 145 | Utils.wrap_with_tag, 146 | { range = true, desc = "Wrap visual selection with HTML tag" } 147 | ) 148 | 149 | vim.api.nvim_create_user_command( 150 | "OpenGitHubRepo", 151 | Utils.open_github_repo, 152 | { desc = "Open GitHub repository from cursor position" } 153 | ) 154 | end 155 | 156 | Utils.vertical_picker = function(picker_type) 157 | if not picker_type or not Snacks.picker[picker_type] then 158 | return vim.notify(string.format("Invalid picker type: %s", tostring(picker_type)), vim.log.levels.ERROR) 159 | end 160 | 161 | Snacks.picker[picker_type]({ 162 | layout = { 163 | layout = { 164 | backdrop = false, 165 | row = 1, 166 | width = 0.7, 167 | min_width = 80, 168 | height = 0.8, 169 | border = "none", 170 | box = "vertical", 171 | { win = "input", height = 1, border = "single", title = "{title} {live} {flags}", title_pos = "center" }, 172 | { win = "list", height = 0.4 }, 173 | { 174 | win = "preview", 175 | title = "{preview}", 176 | border = "single", 177 | title_pos = "center", 178 | }, 179 | }, 180 | }, 181 | }) 182 | end 183 | 184 | Utils.select = function(picker_type) 185 | if not picker_type or not Snacks.picker[picker_type] then 186 | return vim.notify(string.format("Invalid picker type: %s", tostring(picker_type)), vim.log.levels.ERROR) 187 | end 188 | 189 | Snacks.picker[picker_type]({ 190 | layout = { 191 | preview = false, 192 | layout = { 193 | backdrop = false, 194 | width = 0.5, 195 | min_width = 80, 196 | height = 0.4, 197 | min_height = 3, 198 | box = "vertical", 199 | border = "rounded", 200 | title = "{title}", 201 | title_pos = "center", 202 | { win = "input", height = 1, border = "bottom" }, 203 | { win = "list", border = "none" }, 204 | { win = "preview", title = "{preview}", height = 0.4, border = "top" }, 205 | }, 206 | }, 207 | }) 208 | end 209 | 210 | Utils.items_select = function(items, opts, on_choice) 211 | assert(type(on_choice) == "function", "on_choice must be a function") 212 | opts = opts or {} 213 | 214 | ---@type snacks.picker.finder.Item[] 215 | local finder_items = {} 216 | for idx, item in ipairs(items) do 217 | local text = (opts.format_item or tostring)(item) 218 | table.insert(finder_items, { 219 | formatted = text, 220 | text = idx .. " " .. text, 221 | item = item, 222 | idx = idx, 223 | }) 224 | end 225 | 226 | local title = opts.prompt or "Select" 227 | title = title:gsub("^%s*", ""):gsub("[%s:]*$", "") 228 | local completed = false 229 | 230 | ---@type snacks.picker.finder.Item[] 231 | return Snacks.picker.pick({ 232 | source = "select", 233 | items = finder_items, 234 | format = Snacks.picker.format.ui_select(opts.kind, #items), 235 | title = title, 236 | layout = { 237 | preview = nil, 238 | layout = { 239 | backdrop = false, 240 | width = 0.5, 241 | min_width = 80, 242 | height = 0.4, 243 | min_height = 3, 244 | box = "vertical", 245 | border = "rounded", 246 | title = "{title}", 247 | title_pos = "center", 248 | { win = "input", height = 1, border = "bottom" }, 249 | { win = "list", border = "none" }, 250 | }, 251 | }, 252 | actions = { 253 | confirm = function(picker, item) 254 | if completed then 255 | return 256 | end 257 | completed = true 258 | picker:close() 259 | vim.schedule(function() 260 | on_choice(item and item.item, item and item.idx) 261 | end) 262 | end, 263 | }, 264 | on_close = function() 265 | if completed then 266 | return 267 | end 268 | completed = true 269 | vim.schedule(on_choice) 270 | end, 271 | }) 272 | end 273 | 274 | Utils.close_all_buffers = function() 275 | for _, e in ipairs(require("bufferline").get_elements().elements) do 276 | vim.schedule(function() 277 | vim.cmd("bd " .. e.id) 278 | end) 279 | end 280 | end 281 | 282 | -- Initialize 283 | local function init() 284 | setup_commands() 285 | end 286 | 287 | init() 288 | 289 | return Utils 290 | -------------------------------------------------------------------------------- /lua/plugins/avante.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "yetone/avante.nvim", 4 | lazy = true, 5 | event = "BufRead", 6 | build = "make", 7 | 8 | opts = { 9 | provider = "copilot", 10 | hints = { enabled = false }, 11 | file_selector = { 12 | provider = "snacks", 13 | }, 14 | }, 15 | 16 | dependencies = { 17 | { 18 | "MeanderingProgrammer/render-markdown.nvim", 19 | lazy = true, 20 | ft = { "Avante" }, 21 | }, 22 | }, 23 | }, 24 | { 25 | "stevearc/dressing.nvim", 26 | lazy = true, 27 | opts = { 28 | input = { enabled = false }, 29 | select = { enabled = false }, 30 | }, 31 | }, 32 | { 33 | "saghen/blink.compat", 34 | lazy = true, 35 | opts = {}, 36 | config = function() 37 | -- monkeypatch cmp.ConfirmBehavior for Avante 38 | require("cmp").ConfirmBehavior = { 39 | Insert = "insert", 40 | Replace = "replace", 41 | } 42 | end, 43 | }, 44 | { 45 | "saghen/blink.cmp", 46 | lazy = true, 47 | opts = { 48 | sources = { 49 | compat = { "avante_commands", "avante_mentions", "avante_files" }, 50 | }, 51 | }, 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /lua/plugins/blink.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "saghen/blink.cmp", 3 | opts_extend = { 4 | "sources.completion.enabled_providers", 5 | "sources.compat", 6 | "sources.default", 7 | "ecolog", 8 | }, 9 | enabled = function() 10 | return not vim.tbl_contains({ "AvanteInput", "minifiles" }, vim.bo.filetype) 11 | and vim.bo.buftype ~= "prompt" 12 | and vim.b.completion ~= false 13 | end, 14 | event = "InsertEnter", 15 | 16 | ---@module 'blink.cmp' 17 | ---@type blink.cmp.Config 18 | opts = { 19 | completion = { 20 | accept = { 21 | auto_brackets = { 22 | enabled = true, 23 | }, 24 | }, 25 | menu = { 26 | border = "single", 27 | draw = { 28 | columns = { 29 | { "label", gap = 10 }, 30 | { "kind_icon", gap = 1 }, 31 | { "kind" }, 32 | { "label_description" }, 33 | }, 34 | 35 | gap = 1, 36 | treesitter = { "lsp" }, 37 | }, 38 | }, 39 | list = { 40 | selection = { preselect = false, auto_insert = true }, 41 | }, 42 | documentation = { 43 | auto_show = true, 44 | auto_show_delay_ms = 200, 45 | window = { 46 | border = "single", 47 | }, 48 | }, 49 | ghost_text = { 50 | enabled = true, 51 | }, 52 | }, 53 | signature = { enabled = true, window = { border = "single" } }, 54 | -- sources = { 55 | -- providers = { 56 | -- ecolog = { name = "ecolog", module = "ecolog.integrations.cmp.blink_cmp" }, 57 | -- codecompanion = { 58 | -- name = "CodeCompanion", 59 | -- module = "codecompanion.providers.completion.blink", 60 | -- }, 61 | -- }, 62 | -- default = { "lsp", "path", "snippets", "buffer" }, 63 | -- }, 64 | sources = { 65 | default = { "snippets", "lsp", "path", "buffer" }, 66 | providers = { 67 | snippets = { 68 | min_keyword_length = 1, 69 | score_offset = 4, 70 | }, 71 | lsp = { 72 | min_keyword_length = 0, 73 | score_offset = 3, 74 | name = "LSP", 75 | module = "blink.cmp.sources.lsp", 76 | fallbacks = {}, 77 | }, 78 | path = { 79 | min_keyword_length = 0, 80 | score_offset = 2, 81 | }, 82 | buffer = { 83 | min_keyword_length = 1, 84 | score_offset = 1, 85 | }, 86 | }, 87 | }, 88 | cmdline = { 89 | enabled = true, 90 | ---@diagnostic disable-next-line: assign-type-mismatch 91 | sources = function() 92 | local type = vim.fn.getcmdtype() 93 | -- Search forward and backward 94 | if type == "/" or type == "?" then 95 | return { "buffer" } 96 | end 97 | -- Commands 98 | if type == ":" or type == "@" then 99 | return { "cmdline" } 100 | end 101 | return {} 102 | end, 103 | keymap = { 104 | [""] = { "select_next", "fallback" }, 105 | [""] = { "select_prev", "fallback" }, 106 | }, 107 | completion = { 108 | menu = { 109 | auto_show = true, 110 | draw = { 111 | columns = { { "kind_icon", "label", "label_description", gap = 1 } }, 112 | }, 113 | }, 114 | }, 115 | }, 116 | appearance = { 117 | kind_icons = { 118 | Text = "󰉿", 119 | Method = "", 120 | Function = "󰊕", 121 | Constructor = "󰒓", 122 | Field = "", 123 | Variable = "󰆦", 124 | Property = "󰖷", 125 | Class = "", 126 | Interface = "", 127 | Struct = "󱡠", 128 | Module = "󰅩", 129 | Unit = "󰪚", 130 | Value = "", 131 | Enum = "", 132 | EnumMember = "", 133 | Keyword = "", 134 | Constant = "󰏿", 135 | Snippet = "", 136 | Color = "󰏘", 137 | File = "󰈔", 138 | Reference = "󰬲", 139 | Folder = "󰉋", 140 | Event = "󱐋", 141 | Operator = "󰪚", 142 | TypeParameter = "󰬛", 143 | Error = "󰏭", 144 | Warning = "", 145 | Information = "󰋼", 146 | Hint = "", 147 | }, 148 | }, 149 | keymap = { 150 | preset = "enter", 151 | [""] = { "select_and_accept" }, 152 | }, 153 | }, 154 | } 155 | -------------------------------------------------------------------------------- /lua/plugins/codecompanion.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "olimorris/codecompanion.nvim", 3 | -- version = "11.28.x", 4 | event = "VeryLazy", 5 | config = function() 6 | require("codecompanion").setup({ 7 | display = { 8 | diff = { 9 | provider = "mini_diff", 10 | }, 11 | }, 12 | strategies = { 13 | chat = { 14 | roles = { 15 | llm = " Copilot ", 16 | user = " D7OM", 17 | }, 18 | keymaps = { 19 | close = { 20 | modes = { 21 | i = "", 22 | n = "q", 23 | }, 24 | index = 3, 25 | callback = "keymaps.close", 26 | description = "Close Chat", 27 | }, 28 | }, 29 | }, 30 | }, 31 | -- PROMPTS ------------------------------------------------------ 32 | prompt_library = { 33 | ["Fix LSP Diagnostics"] = { 34 | strategy = "chat", 35 | description = "Fix the LSP diagnostics", 36 | opts = { 37 | default_prompt = true, 38 | short_name = "lsp-fix", 39 | modes = { "n", "v" }, 40 | slash_cmd = "lsp-fix", 41 | auto_submit = true, 42 | user_prompt = false, 43 | stop_context_insertion = true, 44 | }, 45 | prompts = { 46 | { 47 | role = "system", 48 | content = [[You are a skilled developer who helps fix LSP diagnostics. Use the buffer context and provide solutions with code snippets where necessary.]], 49 | opts = { 50 | visible = false, 51 | }, 52 | }, 53 | { 54 | role = "user", 55 | content = function(context) 56 | -- Get diagnostics for the current line 57 | local diagnostics = require("codecompanion.helpers.actions").get_diagnostics( 58 | context.start_line, 59 | context.start_line, -- Target the current line 60 | context.bufnr 61 | ) 62 | 63 | local diagnostic_message = diagnostics[1] and diagnostics[1].message or "No diagnostics found" 64 | 65 | -- Include the buffer using the `#buffer` variable 66 | return "Diagnostic message: " 67 | .. diagnostic_message 68 | .. "\n\nHere is the buffer context:\n" 69 | .. "#buffer:" 70 | .. context.start_line - 5 71 | .. "-" 72 | .. context.start_line + 5 73 | end, 74 | opts = { 75 | contains_code = true, 76 | }, 77 | }, 78 | }, 79 | }, 80 | }, 81 | }) 82 | 83 | -- Keymaps 84 | local map = vim.keymap.set 85 | map("n", "i", "CodeCompanion", { noremap = true, silent = true, desc = "CC Inline with Buffer" }) 86 | map("v", "i", function() 87 | -- Prompt user for input 88 | vim.ui.input({ 89 | prompt = "Prompt: ", 90 | }, function(input) 91 | -- If input is not empty, execute CodeCompanion command 92 | if input and input ~= "" then 93 | vim.cmd("'<,'>CodeCompanion /buffer " .. input) 94 | end 95 | end) 96 | end, { noremap = true, silent = true, desc = "CC Inline with Prompt" }) 97 | map( 98 | { "n", "v" }, 99 | "cca", 100 | "CodeCompanionActions", 101 | { noremap = true, silent = true, desc = "CC Actions" } 102 | ) 103 | map("n", "aca", "CodeCompanionChat Toggle", { noremap = true, silent = true, desc = "CC Toggle" }) 104 | map("v", "aca", "CodeCompanionChat Toggle", { noremap = true, silent = true, desc = "CC Toggle" }) 105 | map("v", "ga", "CodeCompanionAdd", { noremap = true, silent = true, desc = "CodeCompanion Add" }) 106 | 107 | -- Prompt Library 108 | map("v", "cce", "", { 109 | callback = function() 110 | require("codecompanion").prompt("explain") 111 | end, 112 | noremap = true, 113 | silent = true, 114 | desc = "CC Explain", 115 | }) 116 | map("v", "ccu", "", { 117 | callback = function() 118 | require("codecompanion").prompt("tests") 119 | end, 120 | noremap = true, 121 | silent = true, 122 | desc = "CC generate unit tests", 123 | }) 124 | map("v", "ccf", "", { 125 | callback = function() 126 | require("codecompanion").prompt("fix") 127 | end, 128 | noremap = true, 129 | silent = true, 130 | desc = "CC fix code", 131 | }) 132 | map("n", "cci", "", { 133 | callback = function() 134 | require("codecompanion").prompt("buffer") 135 | end, 136 | noremap = true, 137 | silent = true, 138 | desc = "CC insert current buffer", 139 | }) 140 | map("v", "ccx", "", { 141 | callback = function() 142 | require("codecompanion").prompt("lsp-explain") 143 | end, 144 | noremap = true, 145 | silent = true, 146 | desc = "CC explain LSP diagnostics", 147 | }) 148 | map("n", "ccf", "", { 149 | callback = function() 150 | require("codecompanion").prompt("lsp-fix") 151 | end, 152 | noremap = true, 153 | silent = true, 154 | desc = "CC fix LSP diagnostics", 155 | }) 156 | map("n", "ccm", "", { 157 | callback = function() 158 | require("codecompanion").prompt("commit") 159 | end, 160 | noremap = true, 161 | silent = true, 162 | desc = "CC generate a commit message", 163 | }) 164 | -- Expand 'cc' into 'CC' in the command line 165 | vim.cmd([[cab cc CC]]) 166 | end, 167 | } 168 | -------------------------------------------------------------------------------- /lua/plugins/copilot.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "zbirenbaum/copilot.lua", 3 | cmd = "Copilot", 4 | build = ":Copilot auth", 5 | config = function() 6 | require("copilot").setup({ 7 | suggestion = { 8 | auto_trigger = true, 9 | keymap = { 10 | accept = "", 11 | accept_word = "", 12 | accept_line = "", 13 | next = "", 14 | prev = "", 15 | dismiss = "", 16 | }, 17 | }, 18 | filetypes = { 19 | markdown = true, 20 | yaml = true, 21 | help = true, 22 | gitcommit = false, 23 | gitrebase = false, 24 | hgcommit = false, 25 | }, 26 | }) 27 | end, 28 | } 29 | -------------------------------------------------------------------------------- /lua/plugins/dap.lua: -------------------------------------------------------------------------------- 1 | local js_based_languages = { 2 | "typescript", 3 | "javascript", 4 | "typescriptreact", 5 | "javascriptreact", 6 | "astro", 7 | "vue", 8 | } 9 | 10 | return { 11 | { "nvim-neotest/nvim-nio", event = "BufReadPost" }, 12 | { 13 | "mfussenegger/nvim-dap", 14 | event = "BufReadPost", 15 | config = function() 16 | local dap = require("dap") 17 | 18 | local Config = require("lazyvim.config") 19 | vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) 20 | 21 | for name, sign in pairs(Config.icons.dap) do 22 | sign = type(sign) == "table" and sign or { sign } 23 | vim.fn.sign_define( 24 | "Dap" .. name, 25 | { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] } 26 | ) 27 | end 28 | 29 | dap.adapters.godot = { 30 | type = "server", 31 | host = "127.0.0.1", 32 | port = 6006, 33 | } 34 | 35 | dap.configurations.gdscript = { 36 | { 37 | type = "godot", 38 | request = "launch", 39 | name = "Launch scene", 40 | project = "${workspaceFolder}", 41 | launch_scene = true, 42 | }, 43 | } 44 | 45 | for _, language in ipairs(js_based_languages) do 46 | dap.configurations[language] = { 47 | -- Debug single nodejs files 48 | { 49 | type = "pwa-node", 50 | request = "launch", 51 | name = "Launch file", 52 | program = "${file}", 53 | cwd = vim.fn.getcwd(), 54 | sourceMaps = true, 55 | }, 56 | -- Debug nodejs processes (make sure to add --inspect when you run the process) 57 | { 58 | type = "pwa-node", 59 | request = "attach", 60 | name = "Attach", 61 | processId = require("dap.utils").pick_process, 62 | cwd = vim.fn.getcwd(), 63 | sourceMaps = true, 64 | }, 65 | -- Debug web applications (client side) 66 | { 67 | type = "firefox", 68 | request = "launch", 69 | name = "Launch & Debug Firefox", 70 | url = function() 71 | local co = coroutine.running() 72 | return coroutine.create(function() 73 | vim.ui.input({ 74 | prompt = "Enter URL: ", 75 | default = "http://localhost:3000", 76 | }, function(url) 77 | if url == nil or url == "" then 78 | return 79 | else 80 | coroutine.resume(co, url) 81 | end 82 | end) 83 | end) 84 | end, 85 | firefoxExecutable = "/usr/bin/zen-browser", 86 | webRoot = vim.fn.getcwd(), 87 | protocol = "inspector", 88 | sourceMaps = true, 89 | userDataDir = false, 90 | }, 91 | -- Divider for the launch.json derived configs 92 | { 93 | name = "----- ↓ launch.json configs ↓ -----", 94 | type = "", 95 | request = "launch", 96 | }, 97 | } 98 | end 99 | end, 100 | keys = { 101 | { 102 | "dO", 103 | function() 104 | require("dap").step_out() 105 | end, 106 | desc = "Step Out", 107 | }, 108 | { 109 | "do", 110 | function() 111 | require("dap").step_over() 112 | end, 113 | desc = "Step Over", 114 | }, 115 | { 116 | "da", 117 | function() 118 | if vim.fn.filereadable(".vscode/launch.json") then 119 | local dap_vscode = require("dap.ext.vscode") 120 | dap_vscode.load_launchjs(nil, { 121 | ["pwa-node"] = js_based_languages, 122 | ["firefox"] = js_based_languages, 123 | }) 124 | end 125 | require("dap").continue() 126 | end, 127 | desc = "Run with Args", 128 | }, 129 | }, 130 | dependencies = { 131 | -- Install the vscode-pwa-msedgejs-debug adapter 132 | { 133 | "microsoft/vscode-js-debug", 134 | -- After install, build it and rename the dist directory to out 135 | build = "npm install --legacy-peer-deps --no-save && npx gulp vsDebugServerBundle && rm -rf out && mv dist out", 136 | version = "1.*", 137 | }, 138 | { 139 | "mxsdev/nvim-dap-vscode-js", 140 | config = function() 141 | ---@diagnostic disable-next-line: missing-fields 142 | require("dap-vscode-js").setup({ 143 | -- Path of node executable. Defaults to $NODE_PATH, and then "node" 144 | -- node_path = "node", 145 | 146 | -- Path to vscode-js-debug installation. 147 | debugger_path = vim.fn.resolve(vim.fn.stdpath("data") .. "/lazy/vscode-js-debug"), 148 | 149 | -- Command to use to launch the debug server. Takes precedence over "node_path" and "debugger_path" 150 | -- debugger_cmd = { "js-debug-adapter" }, 151 | 152 | -- which adapters to register in nvim-dap 153 | adapters = { 154 | "chrome", 155 | "pwa-node", 156 | "pwa-chrome", 157 | "pwa-msedge", 158 | "pwa-extensionHost", 159 | "node-terminal", 160 | }, 161 | 162 | -- Path for file logging 163 | -- log_file_path = "(stdpath cache)/dap_vscode_js.log", 164 | 165 | -- Logging level for output to file. Set to false to disable logging. 166 | -- log_file_level = false, 167 | 168 | -- Logging level for output to console. Set to false to disable console output. 169 | -- log_console_level = vim.log.levels.ERROR, 170 | }) 171 | end, 172 | }, 173 | { 174 | "Joakker/lua-json5", 175 | build = "./install.sh", 176 | }, 177 | }, 178 | }, 179 | } 180 | -------------------------------------------------------------------------------- /lua/plugins/diffview.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "sindrets/diffview.nvim", 3 | keys = { 4 | { "gd", "DiffviewOpen", desc = "Open diff view" }, 5 | { "gh", "DiffviewFileHistory %", desc = "Open file history" }, 6 | { "gbr", "DiffviewOpen origin/HEAD...HEAD --imply-local", desc = "Review branch changes" }, 7 | { "gc", "DiffviewClose", desc = "close view" }, 8 | }, 9 | config = function() 10 | require("diffview").setup({ 11 | enhanced_diff_hl = true, 12 | git_cmd = { "git" }, 13 | use_icons = true, 14 | merge_tool = { 15 | layout = "diff4_mixed", 16 | disable_diagnostics = true, 17 | winbar_info = true, 18 | }, 19 | view = { 20 | merge_tool = { 21 | layout = "diff4_mixed", 22 | }, 23 | }, 24 | hooks = { 25 | view_opened = function(view) 26 | -- Store current colorscheme 27 | vim.g.old_colorscheme = vim.g.colors_name 28 | -- Switch to github theme 29 | end, 30 | view_closed = function() 31 | -- Restore previous colorscheme 32 | if vim.g.old_colorscheme then 33 | vim.cmd("colorscheme " .. vim.g.old_colorscheme) 34 | end 35 | end, 36 | }, 37 | }) 38 | end, 39 | } 40 | -------------------------------------------------------------------------------- /lua/plugins/disabled.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "nvim-neo-tree/neo-tree.nvim", 4 | enabled = false, 5 | }, 6 | -- Disabling these plugins if nvchad ui is used 7 | { "nvim-lualine/lualine.nvim", enabled = false }, 8 | { "echasnovski/mini.icons", enabled = false }, 9 | } 10 | -------------------------------------------------------------------------------- /lua/plugins/ecolog.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "philosofonusus/ecolog.nvim", 3 | event = "VeryLazy", 4 | config = function() 5 | require("ecolog").setup({ 6 | integrations = { 7 | lsp = true, 8 | blink_cmp = true, 9 | lspsaga = true, 10 | }, 11 | }) 12 | end, 13 | -- Optional: you can add some keybindings 14 | -- (I personally use lspsaga so check out lspsaga integration or lsp integration for a smoother experience without separate keybindings) 15 | keys = { 16 | { "ge", "EcologGoto", desc = "Go to env file" }, 17 | { "Ep", "EcologPeek", desc = "Ecolog peek variable" }, 18 | { "Es", "EcologSelect", desc = "Switch env file" }, 19 | }, 20 | opts = { 21 | -- Enables shelter mode for sensitive values 22 | shelter = { 23 | configuration = { 24 | partial_mode = false, -- false by default, disables partial mode, for more control check out shelter partial mode 25 | mask_char = "*", -- Character used for masking 26 | }, 27 | modules = { 28 | cmp = true, -- Mask values in completion 29 | peek = false, -- Mask values in peek view 30 | files = false, -- Mask values in files 31 | telescope = false, -- Mask values in telescope 32 | }, 33 | }, 34 | -- true by default, enables built-in types (database_url, url, etc.) 35 | types = true, 36 | path = vim.fn.getcwd(), -- Path to search for .env files 37 | preferred_environment = "development", -- Optional: prioritize specific env files 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /lua/plugins/gitsigns.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "lewis6991/gitsigns.nvim", 3 | event = "LazyFile", 4 | enabled = true, 5 | config = function() 6 | require("gitsigns").setup({ 7 | current_line_blame = true, 8 | numhl = false, 9 | signs = { 10 | add = { text = "▎" }, 11 | change = { text = "▎" }, 12 | delete = { text = "" }, 13 | topdelete = { text = "‾" }, 14 | changedelete = { text = "~" }, 15 | untracked = { text = "┆" }, 16 | }, 17 | signs_staged = { 18 | add = { text = "▎" }, 19 | change = { text = "▎" }, 20 | delete = { text = "" }, 21 | topdelete = { text = "‾" }, 22 | untracked = { text = "┆" }, 23 | }, 24 | current_line_blame_opts = { 25 | virt_text = true, 26 | virt_text_pos = "right_align", -- 'eol' | 'overlay' | 'right_align' 27 | delay = 1000, 28 | ignore_whitespace = false, 29 | virt_text_priority = 100, 30 | use_focus = true, 31 | }, 32 | on_attach = function(buffer) 33 | local gs = package.loaded.gitsigns 34 | local function map(mode, l, r, desc) 35 | vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) 36 | end 37 | -- stylua: ignore start 38 | map("n", "]h", function() 39 | if vim.wo.diff then 40 | vim.cmd.normal({ "]c", bang = true }) 41 | else 42 | gs.nav_hunk("next") 43 | end 44 | end, "Next Hunk") 45 | map("n", "[h", function() 46 | if vim.wo.diff then 47 | vim.cmd.normal({ "[c", bang = true }) 48 | else 49 | gs.nav_hunk("prev") 50 | end 51 | end, "Prev Hunk") 52 | map("n", "]H", function() gs.nav_hunk("last") end, "Last Hunk") 53 | map("n", "[H", function() gs.nav_hunk("first") end, "First Hunk") 54 | map({ "n", "v" }, "Ghs", ":Gitsigns stage_hunk", "Stage Hunk") 55 | map({ "n", "v" }, "Ghr", ":Gitsigns reset_hunk", "Reset Hunk") 56 | map("n", "GS", gs.stage_buffer, "Stage Buffer") 57 | map("n", "Ghu", gs.undo_stage_hunk, "Undo Stage Hunk") 58 | map("n", "GR", gs.reset_buffer, "Reset Buffer") 59 | map("n", "Gp", gs.preview_hunk_inline, "Preview Hunk Inline") 60 | map("n", "Gb", function() gs.blame_line() end, "Blame Line") 61 | map("n", "GB", function() gs.blame() end, "Blame Buffer") 62 | map("n", "Gd", gs.diffthis, "Diff This") 63 | map("n", "GD", function() gs.diffthis("~") end, "Diff This ~") 64 | map("n", "Gt", "Gitsigns toggle_deleted", "Toggle Deleted") 65 | map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") 66 | end, 67 | }) 68 | end, 69 | } 70 | -------------------------------------------------------------------------------- /lua/plugins/lspconfig.lua: -------------------------------------------------------------------------------- 1 | local lspconfig = require("lspconfig") 2 | local configs = require("lspconfig.configs") 3 | 4 | -- Set default LSP config options 5 | local default = lspconfig.util.default_config 6 | default.flags = vim.tbl_deep_extend("force", default.flags or {}, { 7 | debounce_text_changes = 300, -- milliseconds 8 | }) 9 | 10 | -- TS diagnostic handler function (reused by multiple servers) 11 | local function setup_ts_diagnostics(_, result, ctx, _) 12 | if not result.diagnostics then 13 | return 14 | end 15 | 16 | local idx = 1 17 | while idx <= #result.diagnostics do 18 | local entry = result.diagnostics[idx] 19 | local formatter = require("format-ts-errors")[entry.code] 20 | entry.message = formatter and formatter(entry.message) or entry.message 21 | 22 | -- Remove specific TS diagnostics (code 80001) 23 | if entry.code == 80001 then 24 | table.remove(result.diagnostics, idx) 25 | else 26 | idx = idx + 1 27 | end 28 | end 29 | 30 | vim.lsp.diagnostic.on_publish_diagnostics(_, result, ctx) 31 | end 32 | 33 | -- Configure GDScript (Godot) LSP 34 | lspconfig.gdscript.setup({ 35 | cmd = { "nc", "localhost", "6005" }, 36 | filetypes = { "gd", "gdscript", "gdscript3" }, 37 | root_dir = lspconfig.util.root_pattern("project.godot"), 38 | on_attach = function(_, bufNr) 39 | vim.keymap.set("n", "gd", vim.lsp.buf.definition, { 40 | desc = "Go to definition", 41 | silent = true, 42 | buffer = bufNr, 43 | }) 44 | end, 45 | }) 46 | 47 | lspconfig.qmlls.setup({ 48 | cmd = { "qmlls6" }, 49 | filetypes = { "qmljs", "qml" }, 50 | root_dir = function(fname) 51 | return vim.fs.dirname(vim.fs.find(".git", { path = fname, upward = true })[1]) 52 | end, 53 | single_file_support = true, 54 | }) 55 | 56 | return { 57 | { 58 | "neovim/nvim-lspconfig", 59 | opts = { 60 | diagnostics = { 61 | virtual_text = false, 62 | }, 63 | inlay_hints = { 64 | enabled = true, 65 | exclude = { "typescript", "typescriptreact", "javascript", "javascriptreact", "vue", "lua" }, 66 | }, 67 | codelens = { enabled = false }, 68 | servers = { 69 | ts_ls = { 70 | enabled = false, 71 | }, 72 | vtsls = { 73 | enabled = vim.fn.filereadable("src/App.vue") == 1 or vim.fn.filereadable("nuxt.config.ts") == 1, 74 | }, 75 | eslint = { 76 | enabled = false, 77 | }, 78 | volar = { 79 | init_options = { 80 | vue = { 81 | hybridMode = true, 82 | }, 83 | }, 84 | }, 85 | }, 86 | setup = { 87 | ["typescript-tools"] = function(_, opts) 88 | LazyVim.lsp.on_attach(function() 89 | opts.handlers = { 90 | ["textDocument/publishDiagnostics"] = setup_ts_diagnostics, 91 | } 92 | end) 93 | end, 94 | 95 | vtsls = function(_, opts) 96 | LazyVim.lsp.on_attach(function() 97 | opts.handlers = { 98 | ["textDocument/publishDiagnostics"] = setup_ts_diagnostics, 99 | } 100 | end) 101 | end, 102 | }, 103 | }, 104 | }, 105 | 106 | { 107 | "neovim/nvim-lspconfig", 108 | event = { "BufReadPre", "BufNewFile" }, 109 | opts = function() 110 | local Keys = require("lazyvim.plugins.lsp.keymaps").get() 111 | vim.list_extend(Keys, { { "K", false } }) 112 | end, 113 | }, 114 | 115 | -- LSPSaga Configuration 116 | { 117 | "nvimdev/lspsaga.nvim", 118 | enabled = true, 119 | config = function() 120 | require("lspsaga").setup({ 121 | ui = { border = "single" }, 122 | lightbulb = { enable = false, sign = false }, 123 | code_action = { extend_gitsigns = false, num_shortcut = true }, 124 | diagnostic = { 125 | show_layout = "float", 126 | max_height = 0.8, 127 | max_width = 0.6, 128 | keys = { quit = { "q", "" } }, 129 | }, 130 | hover = { 131 | max_width = 0.6, 132 | }, 133 | }) 134 | end, 135 | }, 136 | 137 | { 138 | "stevearc/conform.nvim", 139 | optional = true, 140 | opts = function(_, opts) 141 | opts.formatters_by_ft = opts.formatters_by_ft or {} 142 | opts.formatters = opts.formatters or {} 143 | 144 | local prettier_filetypes = { 145 | "javascript", 146 | "javascriptreact", 147 | "typescript", 148 | "typescriptreact", 149 | "vue", 150 | "json", 151 | "css", 152 | "scss", 153 | "less", 154 | "html", 155 | "yaml", 156 | } 157 | 158 | for _, ft in ipairs(prettier_filetypes) do 159 | opts.formatters_by_ft[ft] = opts.formatters_by_ft[ft] or {} 160 | table.insert(opts.formatters_by_ft[ft], "prettierd") 161 | end 162 | 163 | opts.formatters.prettierd = { 164 | condition = function(self, ctx) 165 | return vim.fs.find( 166 | { ".prettierrc", ".prettierrc.js", ".prettierrc.json", "prettier.config.js" }, 167 | { path = ctx.filename, upward = true } 168 | )[1] or vim.g.lazyvim_prettier_needs_config ~= true 169 | end, 170 | options = { 171 | ["vue"] = { 172 | indent_script_and_style = false, 173 | }, 174 | }, 175 | } 176 | end, 177 | }, 178 | } 179 | -------------------------------------------------------------------------------- /lua/plugins/markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "OXY2DEV/markview.nvim", 4 | event = "BufRead", 5 | dependencies = { 6 | "nvim-treesitter/nvim-treesitter", 7 | "nvim-tree/nvim-web-devicons", 8 | }, 9 | opts = { 10 | preview = { 11 | filetypes = { "codecompanion", "markdown" }, 12 | ignore_buftypes = {}, 13 | }, 14 | }, 15 | }, 16 | { 17 | "neovim/nvim-lspconfig", 18 | opts = { 19 | servers = { 20 | mpls = {}, 21 | }, 22 | setup = { 23 | mpls = function(_, opts) 24 | local lspconfig = require("lspconfig") 25 | local configs = require("lspconfig.configs") 26 | 27 | if not configs.mpls then 28 | configs.mpls = { 29 | default_config = { 30 | cmd = { "mpls", "--dark-mode", "--enable-emoji", "--no-auto", "--full-sync", "--port", "8989" }, 31 | filetypes = { "markdown" }, 32 | single_file_support = true, 33 | root_dir = function(startpath) 34 | return vim.fs.dirname(vim.fs.find(".git", { path = startpath or vim.fn.getcwd(), upward = true })[1]) 35 | end, 36 | settings = {}, 37 | }, 38 | docs = { 39 | description = [[https://github.com/mhersson/mpls 40 | 41 | Markdown Preview Language Server (MPLS) is a language server that provides 42 | live preview of markdown files in your browser while you edit them in your favorite editor. 43 | ]], 44 | }, 45 | } 46 | end 47 | 48 | lspconfig.mpls.setup(opts) 49 | 50 | -- Kill MPLS on detach 51 | opts.on_exit = function() 52 | vim.fn.jobstart("pkill -f mpls", { detach = true }) 53 | end 54 | end, 55 | }, 56 | }, 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /lua/plugins/minifiles.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "echasnovski/mini.files", 3 | opts = { 4 | mappings = { 5 | close = "q", 6 | go_in = "l", 7 | go_in_plus = "", 8 | go_out = "H", 9 | go_out_plus = "h", 10 | reset = ",", 11 | reveal_cwd = ".", 12 | show_help = "g?", 13 | synchronize = "s", 14 | trim_left = "<", 15 | trim_right = ">", 16 | }, 17 | windows = { 18 | preview = true, 19 | width_focus = 60, 20 | width_preview = 60, 21 | }, 22 | options = { 23 | use_as_default_explorer = true, 24 | permanent_delete = false, 25 | }, 26 | }, 27 | keys = { 28 | { 29 | "e", 30 | function() 31 | require("mini.files").open(vim.api.nvim_buf_get_name(0), true) 32 | end, 33 | desc = "Open mini.files (Directory of Current File)", 34 | }, 35 | { 36 | "B", 37 | function() 38 | require("mini.files").open(vim.uv.cwd(), true) 39 | end, 40 | desc = "Open mini.files (cwd)", 41 | }, 42 | }, 43 | config = function(_, opts) 44 | -- Initialize Git status integration first 45 | local nsMiniFiles = vim.api.nvim_create_namespace("mini_files_git") 46 | local autocmd = vim.api.nvim_create_autocmd 47 | local _, MiniFiles = pcall(require, "mini.files") 48 | 49 | -- Initialize cache before it's used 50 | local gitStatusCache = {} 51 | local cacheTimeout = 2000 -- Cache timeout in milliseconds 52 | 53 | -- State management for visibility toggles - both start as false (hidden) 54 | local show_dotfiles = false 55 | local show_ignored = false 56 | 57 | -- Define mapSymbols function in proper scope 58 | local function mapSymbols(status) 59 | local statusMap = { 60 | [" M"] = { symbol = "󰦒", hlGroup = "MiniDiffSignChange" }, 61 | ["M "] = { symbol = "•", hlGroup = "MiniDiffSignChange" }, 62 | ["MM"] = { symbol = "≠", hlGroup = "MiniDiffSignChange" }, 63 | ["A "] = { symbol = "+", hlGroup = "MiniDiffSignAdd" }, 64 | ["AA"] = { symbol = "≈", hlGroup = "MiniDiffSignAdd" }, 65 | ["D "] = { symbol = "-", hlGroup = "MiniDiffSignDelete" }, 66 | ["AM"] = { symbol = "⊕", hlGroup = "MiniDiffSignChange" }, 67 | ["AD"] = { symbol = "-•", hlGroup = "MiniDiffSignChange" }, 68 | ["R "] = { symbol = "→", hlGroup = "MiniDiffSignChange" }, 69 | ["U "] = { symbol = "‖", hlGroup = "MiniDiffSignChange" }, 70 | ["UU"] = { symbol = "⇄", hlGroup = "MiniDiffSignAdd" }, 71 | ["UA"] = { symbol = "⊕", hlGroup = "MiniDiffSignAdd" }, 72 | ["??"] = { symbol = "?", hlGroup = "MiniDiffSignDelete" }, 73 | ["!!"] = { symbol = "", hlGroup = "Comment" }, 74 | } 75 | 76 | local result = statusMap[status] or { symbol = "?", hlGroup = "NonText" } 77 | return result.symbol, result.hlGroup 78 | end 79 | 80 | -- Filter functions that use the cache 81 | local function is_ignored(fs_entry) 82 | if not gitStatusCache then 83 | return false 84 | end 85 | 86 | local cwd = vim.fn.getcwd() 87 | if not gitStatusCache[cwd] then 88 | return false 89 | end 90 | 91 | local relative_path = fs_entry.path:gsub("^" .. vim.fn.escape(cwd, "%-%.%+%[%]%(%)%$%^") .. "/", "") 92 | return gitStatusCache[cwd].statusMap and gitStatusCache[cwd].statusMap[relative_path] == "!!" 93 | end 94 | 95 | local function filter_entries(fs_entry) 96 | local is_dot = vim.startswith(fs_entry.name, ".") 97 | local is_ignored_file = is_ignored(fs_entry) 98 | 99 | return (not is_dot or show_dotfiles) and (not is_ignored_file or show_ignored) 100 | end 101 | 102 | -- Add the filter to the initial setup options 103 | opts.content = { 104 | filter = filter_entries, 105 | } 106 | 107 | -- Now set up mini.files with the modified opts 108 | require("mini.files").setup(opts) 109 | 110 | local function fetchGitStatus(cwd, callback) 111 | local function on_exit(content) 112 | if content.code == 0 then 113 | callback(content.stdout) 114 | end 115 | end 116 | vim.system({ "git", "status", "--ignored", "--porcelain" }, { text = true, cwd = cwd }, on_exit) 117 | end 118 | 119 | local function escapePattern(str) 120 | return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") 121 | end 122 | 123 | local function updateMiniWithGit(buf_id, gitStatusMap) 124 | vim.schedule(function() 125 | if not vim.api.nvim_buf_is_valid(buf_id) then 126 | return 127 | end 128 | 129 | local nlines = vim.api.nvim_buf_line_count(buf_id) 130 | local cwd = vim.fn.getcwd() 131 | local escapedcwd = escapePattern(cwd) 132 | if vim.fn.has("win32") == 1 then 133 | escapedcwd = escapedcwd:gsub("\\", "/") 134 | end 135 | 136 | -- Clear existing highlights 137 | vim.api.nvim_buf_clear_namespace(buf_id, nsMiniFiles, 0, -1) 138 | 139 | for i = 1, nlines do 140 | local entry = MiniFiles.get_fs_entry(buf_id, i) 141 | if not entry then 142 | break 143 | end 144 | local relativePath = entry.path:gsub("^" .. escapedcwd .. "/", "") 145 | local status = gitStatusMap[relativePath] 146 | 147 | if status then 148 | local symbol, hlGroup = mapSymbols(status) 149 | if status == "!!" then 150 | -- Apply Comment highlight to the whole line 151 | vim.api.nvim_buf_add_highlight(buf_id, nsMiniFiles, "Comment", i - 1, 0, -1) 152 | 153 | -- Add the symbol at EOL 154 | vim.api.nvim_buf_set_extmark(buf_id, nsMiniFiles, i - 1, 0, { 155 | virt_text = { { symbol, "Comment" } }, 156 | virt_text_pos = "eol", 157 | priority = 2, 158 | hl_mode = "combine", 159 | }) 160 | else 161 | vim.api.nvim_buf_set_extmark(buf_id, nsMiniFiles, i - 1, 0, { 162 | virt_text = { { symbol, hlGroup } }, 163 | virt_text_pos = "eol", 164 | priority = 2, 165 | hl_mode = "combine", 166 | }) 167 | end 168 | end 169 | end 170 | end) 171 | end 172 | 173 | local function parseGitStatus(content) 174 | local gitStatusMap = {} 175 | for line in content:gmatch("[^\r\n]+") do 176 | local status, filePath = string.match(line, "^(..)%s+(.*)") 177 | local parts = {} 178 | for part in filePath:gmatch("[^/]+") do 179 | table.insert(parts, part) 180 | end 181 | 182 | local currentPath = "" 183 | for i, part in ipairs(parts) do 184 | if i == 1 then 185 | currentPath = part 186 | else 187 | currentPath = currentPath .. "/" .. part 188 | end 189 | -- For ignored items, propagate !! status to all parent directories 190 | if status == "!!" then 191 | gitStatusMap[currentPath] = status 192 | end 193 | -- For the actual file/folder itself 194 | if i == #parts then 195 | gitStatusMap[currentPath] = status 196 | end 197 | end 198 | end 199 | return gitStatusMap 200 | end 201 | 202 | local function is_valid_git_repo() 203 | if vim.fn.isdirectory(".git") == 0 then 204 | return false 205 | end 206 | return true 207 | end 208 | 209 | -- Toggle functions 210 | local toggle_dotfiles = function() 211 | show_dotfiles = not show_dotfiles 212 | require("mini.files").refresh({ content = { filter = filter_entries } }) 213 | end 214 | 215 | local toggle_ignored = function() 216 | show_ignored = not show_ignored 217 | require("mini.files").refresh({ content = { filter = filter_entries } }) 218 | end 219 | 220 | local function updateGitStatus(buf_id) 221 | if not is_valid_git_repo() then 222 | return 223 | end 224 | local cwd = vim.fn.getcwd() 225 | local currentTime = os.time() 226 | if gitStatusCache[cwd] and currentTime - gitStatusCache[cwd].time < cacheTimeout then 227 | updateMiniWithGit(buf_id, gitStatusCache[cwd].statusMap) 228 | else 229 | fetchGitStatus(cwd, function(content) 230 | local gitStatusMap = parseGitStatus(content) 231 | gitStatusCache[cwd] = { 232 | time = currentTime, 233 | statusMap = gitStatusMap, 234 | } 235 | updateMiniWithGit(buf_id, gitStatusMap) 236 | end) 237 | end 238 | end 239 | 240 | local function clearCache() 241 | gitStatusCache = {} 242 | end 243 | 244 | local map_split = function(buf_id, lhs, direction, close_on_file) 245 | local rhs = function() 246 | local new_target_window 247 | local cur_target_window = require("mini.files").get_explorer_state().target_window 248 | if cur_target_window ~= nil then 249 | vim.api.nvim_win_call(cur_target_window, function() 250 | vim.cmd("belowright " .. direction .. " split") 251 | new_target_window = vim.api.nvim_get_current_win() 252 | end) 253 | 254 | require("mini.files").set_target_window(new_target_window) 255 | require("mini.files").go_in({ close_on_file = close_on_file }) 256 | end 257 | end 258 | 259 | local desc = "Open in " .. direction .. " split" 260 | if close_on_file then 261 | desc = desc .. " and close" 262 | end 263 | vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc }) 264 | end 265 | 266 | local files_set_cwd = function() 267 | local cur_entry_path = MiniFiles.get_fs_entry().path 268 | local cur_directory = vim.fs.dirname(cur_entry_path) 269 | if cur_directory ~= nil then 270 | vim.fn.chdir(cur_directory) 271 | end 272 | end 273 | 274 | -- Set up autocmds 275 | local function augroup(name) 276 | return vim.api.nvim_create_augroup("MiniFiles_" .. name, { clear = true }) 277 | end 278 | 279 | vim.api.nvim_create_autocmd("User", { 280 | pattern = "MiniFilesBufferCreate", 281 | callback = function(args) 282 | local buf_id = args.data.buf_id 283 | 284 | vim.keymap.set("n", "g.", toggle_dotfiles, { buffer = buf_id, desc = "Toggle hidden files" }) 285 | 286 | vim.keymap.set("n", "gi", toggle_ignored, { buffer = buf_id, desc = "Toggle ignored files" }) 287 | 288 | vim.keymap.set("n", "gc", files_set_cwd, { buffer = buf_id, desc = "Set cwd" }) 289 | 290 | map_split(buf_id, "s", "horizontal", false) 291 | map_split(buf_id, "v", "vertical", false) 292 | map_split(buf_id, "S", "horizontal", true) 293 | map_split(buf_id, "V", "vertical", true) 294 | end, 295 | }) 296 | 297 | vim.api.nvim_create_autocmd("User", { 298 | pattern = "MiniFilesActionRename", 299 | callback = function(event) 300 | Snacks.rename.on_rename_file(event.data.from, event.data.to) 301 | end, 302 | }) 303 | 304 | -- Set up git status autocmds 305 | autocmd("User", { 306 | group = augroup("start"), 307 | pattern = "MiniFilesExplorerOpen", 308 | callback = function() 309 | local bufnr = vim.api.nvim_get_current_buf() 310 | updateGitStatus(bufnr) 311 | end, 312 | }) 313 | 314 | autocmd("User", { 315 | group = augroup("close"), 316 | pattern = "MiniFilesExplorerClose", 317 | callback = function() 318 | clearCache() 319 | end, 320 | }) 321 | 322 | autocmd("User", { 323 | group = augroup("update"), 324 | pattern = "MiniFilesBufferUpdate", 325 | callback = function(sii) 326 | local bufnr = sii.data.buf_id 327 | local cwd = vim.fn.expand("%:p:h") 328 | if gitStatusCache[cwd] then 329 | updateMiniWithGit(bufnr, gitStatusCache[cwd].statusMap) 330 | end 331 | end, 332 | }) 333 | end, 334 | } 335 | -------------------------------------------------------------------------------- /lua/plugins/minipairs.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "echasnovski/mini.pairs", 3 | enabled = true, 4 | event = { "VeryLazy" }, 5 | version = "*", 6 | opts = { 7 | -- In which modes mappings from this `config` should be created 8 | modes = { insert = true, command = false, terminal = false }, 9 | 10 | -- Global mappings. Each right hand side should be a pair information, a 11 | -- table with at least these fields (see more in |MiniPairs.map|): 12 | -- - - one of 'open', 'close', 'closeopen'. 13 | -- - - two character string for pair to be used. 14 | -- By default pair is not inserted after `\`, quotes are not recognized by 15 | -- ``, `'` does not insert pair after a letter. 16 | -- Only parts of tables can be tweaked (others will use these defaults). 17 | mappings = { 18 | [")"] = { action = "close", pair = "()", neigh_pattern = "[^\\]." }, 19 | ["]"] = { action = "close", pair = "[]", neigh_pattern = "[^\\]." }, 20 | ["}"] = { action = "close", pair = "{}", neigh_pattern = "[^\\]." }, 21 | ["["] = { 22 | action = "open", 23 | pair = "[]", 24 | neigh_pattern = ".[%s%z%)}%]]", 25 | register = { cr = false }, 26 | -- foo|bar -> press "[" -> foo[bar 27 | -- foobar| -> press "[" -> foobar[] 28 | -- |foobar -> press "[" -> [foobar 29 | -- | foobar -> press "[" -> [] foobar 30 | -- foobar | -> press "[" -> foobar [] 31 | -- {|} -> press "[" -> {[]} 32 | -- (|) -> press "[" -> ([]) 33 | -- [|] -> press "[" -> [[]] 34 | }, 35 | ["{"] = { 36 | action = "open", 37 | pair = "{}", 38 | -- neigh_pattern = ".[%s%z%)}]", 39 | neigh_pattern = ".[%s%z%)}%]]", 40 | register = { cr = false }, 41 | -- foo|bar -> press "{" -> foo{bar 42 | -- foobar| -> press "{" -> foobar{} 43 | -- |foobar -> press "{" -> {foobar 44 | -- | foobar -> press "{" -> {} foobar 45 | -- foobar | -> press "{" -> foobar {} 46 | -- (|) -> press "{" -> ({}) 47 | -- {|} -> press "{" -> {{}} 48 | }, 49 | ["("] = { 50 | action = "open", 51 | pair = "()", 52 | -- neigh_pattern = ".[%s%z]", 53 | neigh_pattern = ".[%s%z%)]", 54 | register = { cr = false }, 55 | -- foo|bar -> press "(" -> foo(bar 56 | -- foobar| -> press "(" -> foobar() 57 | -- |foobar -> press "(" -> (foobar 58 | -- | foobar -> press "(" -> () foobar 59 | -- foobar | -> press "(" -> foobar () 60 | }, 61 | -- Single quote: Prevent pairing if either side is a letter 62 | ['"'] = { 63 | action = "closeopen", 64 | pair = '""', 65 | neigh_pattern = "[^%w\\][^%w]", 66 | register = { cr = false }, 67 | }, 68 | -- Single quote: Prevent pairing if either side is a letter 69 | ["'"] = { 70 | action = "closeopen", 71 | pair = "''", 72 | neigh_pattern = "[^%w\\][^%w]", 73 | register = { cr = false }, 74 | }, 75 | -- Backtick: Prevent pairing if either side is a letter 76 | ["`"] = { 77 | action = "closeopen", 78 | pair = "``", 79 | neigh_pattern = "[^%w\\][^%w]", 80 | register = { cr = false }, 81 | }, 82 | }, 83 | }, 84 | } 85 | -------------------------------------------------------------------------------- /lua/plugins/minipick.lua: -------------------------------------------------------------------------------- 1 | -- From: https://github.com/bassamsdata/nvim/blob/81e4c348140db5ee8f5786f10a67e20392f2c0fa/lua/plugins/minipick.lua 2 | if vim.env.NVIM_TESTING then 3 | return {} 4 | end 5 | 6 | return { 7 | { 8 | "echasnovski/mini.pick", 9 | enabled = false, 10 | dependencies = { 11 | { "echasnovski/mini.extra", opts = {} }, 12 | { "echasnovski/mini.visits", opts = {} }, 13 | { "echasnovski/mini.fuzzy", opts = {} }, 14 | }, 15 | cmd = "Pick", 16 | config = function() 17 | local MiniPick = require("mini.pick") 18 | local MiniExtra = require("mini.extra") 19 | require("custom.multi-grep").setup() 20 | vim.ui.select = require("mini.pick").ui_select 21 | 22 | -- copy the item under the cursor 23 | local copy_to_register = { 24 | char = "", 25 | func = function() 26 | local line = vim.fn.line(".") 27 | local current_line = vim.fn.getline(line) 28 | vim.fn.setreg("+", current_line) 29 | print("Copied '" .. current_line .. "'") 30 | end, 31 | } 32 | -- scrll by margin of 4 lines to not diorient 33 | local scroll_up = { 34 | char = "", 35 | func = function() 36 | -- this is special character in insert mode press C-v then y 37 | -- while holding Ctrl to invoke 38 | vim.cmd("normal! 4") 39 | end, 40 | } 41 | local scroll_down = { 42 | char = "", 43 | func = function() 44 | vim.cmpickd("norm! 4") 45 | end, 46 | } 47 | 48 | local delete_file = { 49 | char = "", 50 | func = function() 51 | local path = MiniPick.get_picker_matches()[MiniPick.get_picker_match_index()] 52 | if path then 53 | os.remove(path) 54 | MiniPick.refresh() 55 | end 56 | end, 57 | } 58 | 59 | -- Setup 'mini.pick' with default window in the ceneter 60 | MiniPick.setup({ 61 | use_cache = true, 62 | window = { 63 | prompt_prefix = " ", 64 | config = function() 65 | local height = math.floor(0.618 * vim.o.lines) 66 | local width = math.floor(0.618 * vim.o.columns) 67 | return { 68 | border = "single", 69 | anchor = "NW", 70 | height = height, 71 | width = width, 72 | row = math.floor(0.5 * (vim.o.lines - height)), 73 | col = math.floor(0.5 * (vim.o.columns - width)), 74 | } 75 | end, 76 | }, 77 | mappings = { 78 | copy_to_register = copy_to_register, 79 | scroll_up_a_bit = scroll_up, 80 | scroll_down_a_bit = scroll_down, 81 | delete_file = delete_file, 82 | refine = "", 83 | }, 84 | }) 85 | -- == Styles == 86 | -- 1 - File picker configuration that follows cursor 87 | local cursor_win_config = { 88 | -- stylua: ignore start 89 | border = "single", 90 | relative = "cursor", 91 | anchor = "NW", 92 | row = 0, 93 | col = 0, 94 | width = 70, 95 | height = 16, 96 | -- stylua: ignore end 97 | } 98 | -- 2 - Right side picker configuration 99 | local row = function() 100 | local has_statusline = vim.o.laststatus > 0 101 | local bottom_space = vim.o.cmdheight + (has_statusline and 1 or 0) 102 | return vim.o.lines - bottom_space 103 | end 104 | local right_win_config = { 105 | -- stylua: ignore start 106 | border = "single", 107 | relative = "editor", 108 | anchor = "SE", 109 | -- down in the right bottom 110 | row = row(), 111 | col = vim.o.columns - 1, 112 | height = 16, 113 | width = 50, 114 | -- stylua: ignore end 115 | } 116 | -- 3 - Center small window 117 | local height = math.floor(0.40 * vim.o.lines) 118 | local width = math.floor(0.40 * vim.o.columns) 119 | local center_small = { 120 | border = "single", 121 | anchor = "NW", 122 | height = height, 123 | width = width, 124 | row = math.floor(0.5 * (vim.o.lines - height)), 125 | col = math.floor(0.5 * (vim.o.columns - width)), 126 | -- relative = "editor", 127 | } 128 | 129 | -- Create new picker to search nvim config whatever the cwd is 130 | MiniPick.registry.config = function() 131 | local opts = { source = { cwd = vim.fn.stdpath("config") } } 132 | return MiniPick.builtin.files({}, opts) 133 | end 134 | 135 | -- Define a new picker for the quickfix list 136 | MiniPick.registry.quickfix = function() 137 | return MiniExtra.pickers.list({ scope = "quickfix" }, {}) 138 | end 139 | 140 | -- Modify the 'files' picker directly 141 | MiniPick.registry.files = function() 142 | return MiniPick.builtin.files({}, { window = { config = cursor_win_config } }) 143 | end 144 | 145 | -- Modify the 'old_files' picker directly 146 | MiniPick.registry.oldfiles = function() 147 | return MiniExtra.pickers.oldfiles({}, { window = { config = cursor_win_config } }) 148 | end 149 | 150 | -- Modify the 'buffers' picker directly 151 | MiniPick.registry.buffers = function() 152 | return MiniPick.builtin.buffers({}, { window = { config = right_win_config } }) 153 | end 154 | 155 | -- Modify the 'old_files' picker directly 156 | MiniPick.registry.history = function() 157 | return MiniExtra.pickers.history({}, { window = { config = center_small } }) 158 | end 159 | 160 | MiniPick.registry.registry = function() 161 | local items = vim.tbl_keys(MiniPick.registry) 162 | table.sort(items) 163 | local source = { items = items, name = "Registry", choose = function() end } 164 | local chosen_picker_name = MiniPick.start({ source = source }) 165 | if chosen_picker_name == nil then 166 | return 167 | end 168 | return MiniPick.registry[chosen_picker_name]() 169 | end 170 | 171 | -- thanks to https://github.com/echasnovski/mini.nvim/discussions/609# 172 | local function create_frecency_picker(opts) 173 | opts = opts or {} 174 | local directory = opts.directory or nil -- nil means current directory 175 | local window_config = opts.window_config or nil -- nil means default 176 | 177 | return function() 178 | local sort = MiniVisits.gen_sort.z() 179 | local visit_paths = MiniVisits.list_paths(directory, { sort = sort }) 180 | local current_file = vim.fn.expand("%") 181 | 182 | MiniPick.builtin.files(nil, { 183 | source = { 184 | cwd = directory, 185 | match = function(stritems, indices, query) 186 | -- Concatenate prompt to a single string 187 | local prompt = vim.pesc(table.concat(query)) 188 | 189 | -- If ignorecase is on and there are no uppercase letters in prompt, 190 | -- convert paths to lowercase for matching purposes 191 | local convert_path = function(str) 192 | return str 193 | end 194 | if vim.o.ignorecase and string.find(prompt, "%u") == nil then 195 | convert_path = function(str) 196 | return string.lower(str) 197 | end 198 | end 199 | 200 | local current_file_cased = convert_path(current_file) 201 | local paths_length = #visit_paths 202 | 203 | -- Flip visit_paths so that paths are lookup keys for the index values 204 | local flipped_visits = {} 205 | for index, path in ipairs(visit_paths) do 206 | local key = vim.fn.fnamemodify(path, ":.") 207 | flipped_visits[convert_path(key)] = index - 1 208 | end 209 | 210 | local result = {} 211 | for _, index in ipairs(indices) do 212 | local path = stritems[index] 213 | local match_score = prompt == "" and 0 or MiniFuzzy.match(prompt, path).score 214 | if match_score >= 0 then 215 | local visit_score = flipped_visits[path] or paths_length 216 | table.insert(result, { 217 | index = index, 218 | -- Give current file high value so it's ranked last 219 | score = path == current_file_cased and 999999 or match_score + visit_score * 10, 220 | }) 221 | end 222 | end 223 | 224 | table.sort(result, function(a, b) 225 | return a.score < b.score 226 | end) 227 | 228 | return vim.tbl_map(function(val) 229 | return val.index 230 | end, result) 231 | end, 232 | }, 233 | window = { config = window_config }, 234 | }) 235 | end 236 | end 237 | 238 | MiniPick.registry.config_frecency = create_frecency_picker({ 239 | directory = vim.fn.stdpath("config"), 240 | }) 241 | 242 | MiniPick.registry.nvim_data = create_frecency_picker({ 243 | directory = vim.fn.stdpath("data") .. "/lazy", 244 | }) 245 | 246 | MiniPick.registry.frecency = create_frecency_picker({ 247 | window_config = cursor_win_config, 248 | }) 249 | 250 | -- this is just was an idea 251 | MiniPick.registry.all_frecency = create_frecency_picker({ 252 | directories = { 253 | nil, -- current directory 254 | vim.fn.stdpath("config"), 255 | -- add more directories as needed 256 | }, 257 | cursor_win_config = cursor_win_config, 258 | }) 259 | 260 | -- MINIPICK TERMINAL 261 | MiniPick.registry.pick_term = function() 262 | local term_bufs = vim.g.nvchad_terms or {} 263 | local buffers = {} 264 | 265 | for buf, _ in pairs(term_bufs) do 266 | buf = tonumber(buf) 267 | local element = { bufnr = buf, flag = "", info = vim.fn.getbufinfo(buf)[1] } 268 | table.insert(buffers, element) 269 | end 270 | 271 | local bufnrs = vim.tbl_keys(term_bufs) 272 | 273 | if #bufnrs == 0 then 274 | print("No terminal buffers are opened/hidden!") 275 | return 276 | end 277 | 278 | local source = { 279 | items = buffers, 280 | name = "Terminal Buffers", 281 | choose = function(chosen_item) 282 | -- Open term only if its window isn't opened 283 | if vim.fn.bufwinid(chosen_item.bufnr) == -1 then 284 | local termopts = vim.g.nvchad_terms[tostring(chosen_item.bufnr)] 285 | require("nvterminal").display(termopts) 286 | end 287 | end, 288 | } 289 | 290 | MiniPick.start({ source = source }) 291 | end 292 | end, 293 | }, 294 | } 295 | -------------------------------------------------------------------------------- /lua/plugins/misc.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "aserowy/tmux.nvim", 4 | event = "VeryLazy", 5 | config = function() 6 | return require("tmux").setup({ copy_sync = { 7 | enable = false, 8 | } }) 9 | end, 10 | }, 11 | { 12 | "lambdalisue/vim-suda", 13 | event = "VeryLazy", 14 | config = function() 15 | vim.g.suda_smart_edit = 1 16 | -- Expand 'ss' into 'SudaWrite' in the command line 17 | vim.cmd([[cab ss SudaWrite]]) 18 | end, 19 | }, 20 | { "nvchad/volt", lazy = true }, 21 | { "nvchad/minty", lazy = true }, 22 | { 23 | "nvchad/ui", 24 | config = function() 25 | require("nvchad") 26 | end, 27 | }, 28 | { 29 | "nvchad/base46", 30 | priority = 1000, 31 | lazy = false, 32 | build = function() 33 | require("base46").load_all_highlights() 34 | end, 35 | }, 36 | 37 | { 38 | "bbjornstad/pretty-fold.nvim", 39 | event = "BufRead", 40 | config = function() 41 | require("pretty-fold").setup({ 42 | keep_indentation = true, 43 | fill_char = "", 44 | sections = { 45 | left = { 46 | "+", 47 | function() 48 | return string.rep("-", vim.v.foldlevel) 49 | end, 50 | " ", 51 | "number_of_folded_lines", 52 | ":", 53 | "content", 54 | }, 55 | }, 56 | }) 57 | end, 58 | }, 59 | { 60 | "andrewferrier/debugprint.nvim", 61 | event = "BufReadPost", 62 | opts = { 63 | keymaps = { 64 | normal = { 65 | plain_below = "g?p", 66 | plain_above = "g?P", 67 | variable_below = "g?v", 68 | variable_above = "g?V", 69 | variable_below_alwaysprompt = nil, 70 | variable_above_alwaysprompt = nil, 71 | textobj_below = "g?o", 72 | textobj_above = "g?O", 73 | toggle_comment_debug_prints = nil, 74 | delete_debug_prints = nil, 75 | }, 76 | insert = { 77 | plain = "p", 78 | variable = "v", 79 | }, 80 | visual = { 81 | variable_below = "g?v", 82 | variable_above = "g?V", 83 | }, 84 | }, 85 | commands = { 86 | toggle_comment_debug_prints = "ToggleCommentDebugPrints", 87 | delete_debug_prints = "DeleteDebugPrints", 88 | }, 89 | }, 90 | version = "*", 91 | }, 92 | { 93 | "smoka7/multicursors.nvim", 94 | enabled = false, 95 | event = "BufRead", 96 | dependencies = { 97 | "smoka7/hydra.nvim", 98 | }, 99 | opts = {}, 100 | cmd = { "MCstart", "MCvisual", "MCclear", "MCpattern", "MCvisualPattern", "MCunderCursor" }, 101 | keys = { 102 | { 103 | mode = { "v", "n" }, 104 | "m", 105 | "MCstart", 106 | desc = "Multi cursors", 107 | }, 108 | }, 109 | }, 110 | { 111 | "Aasim-A/scrollEOF.nvim", 112 | event = "BufRead", 113 | config = function() 114 | require("scrollEOF").setup({ 115 | disabled_filetypes = { "minifiles" }, 116 | }) 117 | end, 118 | }, 119 | { 120 | "chrisgrieser/nvim-rip-substitute", 121 | event = "BufRead", 122 | cmd = "RipSubstitute", 123 | keys = { 124 | { 125 | "fs", 126 | function() 127 | require("rip-substitute").sub() 128 | end, 129 | mode = { "n", "x" }, 130 | desc = " rip substitute", 131 | }, 132 | }, 133 | }, 134 | { 135 | "aaronik/treewalker.nvim", 136 | event = "BufRead", 137 | opts = { 138 | highlight = true, 139 | highlight_duration = 250, 140 | highlight_group = "CursorLine", 141 | }, 142 | }, 143 | { "habamax/vim-godot", event = "FileType gd" }, 144 | { { "RishabhRD/nvim-cheat.sh", event = "VeryLazy" }, { "RishabhRD/popfix", event = "VeryLazy" } }, 145 | { 146 | "stevearc/quicker.nvim", 147 | event = "FileType qf", 148 | config = function() 149 | require("quicker").setup() 150 | end, 151 | }, 152 | { 153 | "HakonHarnes/img-clip.nvim", 154 | event = "VeryLazy", 155 | opts = { 156 | default = { 157 | use_absolute_path = false, ---@type boolean 158 | relative_to_current_file = true, ---@type boolean 159 | dir_path = function() 160 | return vim.fn.expand("%:t:r") .. "-img" 161 | end, 162 | prompt_for_file_name = true, ---@type boolean 163 | file_name = "%Y-%m-%d-at-%H-%M-%S", ---@type string 164 | process_cmd = "convert - png:-", ---@type string 165 | }, 166 | filetypes = { 167 | markdown = { 168 | url_encode_path = true, ---@type boolean 169 | template = "![$FILE_NAME]($FILE_PATH)", ---@type string 170 | }, 171 | }, 172 | }, 173 | keys = { 174 | { "v", "PasteImage", desc = "Paste image from system clipboard" }, 175 | }, 176 | }, 177 | { 178 | "echasnovski/mini.diff", 179 | event = "VeryLazy", 180 | version = "*", 181 | }, 182 | { 183 | "barrett-ruth/live-server.nvim", 184 | event = "VeryLazy", 185 | build = "bun add -g live-server", 186 | cmd = { "LiveServerStart", "LiveServerStop" }, 187 | config = true, 188 | }, 189 | { 190 | "jonahgoldwastaken/copilot-status.nvim", 191 | lazy = true, 192 | event = "BufReadPost", 193 | }, 194 | { 195 | "stevearc/overseer.nvim", 196 | event = "VeryLazy", 197 | config = function() 198 | require("overseer").setup() 199 | end, 200 | }, 201 | { 202 | "fnune/recall.nvim", 203 | config = function() 204 | require("recall").setup({ 205 | sign = "", 206 | sign_highlight = "@comment.note", 207 | snacks = { 208 | mappings = { 209 | unmark_selected_entry = { 210 | normal = "d", 211 | insert = "", 212 | }, 213 | }, 214 | }, 215 | }) 216 | end, 217 | }, 218 | } 219 | -------------------------------------------------------------------------------- /lua/plugins/multicursors.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "jake-stewart/multicursor.nvim", 3 | enabled = false, 4 | config = function() 5 | local mc = require("multicursor-nvim") 6 | 7 | mc.setup() 8 | 9 | local set = vim.keymap.set 10 | 11 | -- Add or skip cursor above/below the main cursor. 12 | set({ "n", "x" }, "", function() 13 | mc.lineAddCursor(-1) 14 | end) 15 | set({ "n", "x" }, "", function() 16 | mc.lineAddCursor(1) 17 | end) 18 | set({ "n", "x" }, "", function() 19 | mc.lineSkipCursor(-1) 20 | end) 21 | set({ "n", "x" }, "", function() 22 | mc.lineSkipCursor(1) 23 | end) 24 | 25 | -- Add or skip adding a new cursor by matching word/selection 26 | set({ "n", "x" }, "n", function() 27 | mc.matchAddCursor(1) 28 | end) 29 | set({ "n", "x" }, "s", function() 30 | mc.matchSkipCursor(1) 31 | end) 32 | set({ "n", "x" }, "N", function() 33 | mc.matchAddCursor(-1) 34 | end) 35 | set({ "n", "x" }, "S", function() 36 | mc.matchSkipCursor(-1) 37 | end) 38 | 39 | -- In normal/visual mode, press `mwap` will create a cursor in every match of 40 | -- the word captured by `iw` (or visually selected range) inside the bigger 41 | -- range specified by `ap`. Useful to replace a word inside a function, e.g. mwif. 42 | set({ "n", "x" }, "mw", function() 43 | mc.operator({ motion = "iw", visual = true }) 44 | -- Or you can pass a pattern, press `mwi{` will select every \w, 45 | -- basically every char in a `{ a, b, c, d }`. 46 | -- mc.operator({ pattern = [[\<\w]] }) 47 | end) 48 | 49 | -- Press `mWi"ap` will create a cursor in every match of string captured by `i"` inside range `ap`. 50 | set("n", "mW", mc.operator) 51 | 52 | -- Add all matches in the document 53 | set({ "n", "x" }, "A", mc.matchAllAddCursors) 54 | 55 | -- You can also add cursors with any motion you prefer: 56 | -- set("n", "", function() 57 | -- mc.addCursor("w") 58 | -- end) 59 | -- set("n", "", function() 60 | -- mc.skipCursor("w") 61 | -- end) 62 | 63 | -- Rotate the main cursor. 64 | set({ "n", "x" }, "", mc.nextCursor) 65 | set({ "n", "x" }, "", mc.prevCursor) 66 | 67 | -- Delete the main cursor. 68 | set({ "n", "x" }, "x", mc.deleteCursor) 69 | 70 | -- Add and remove cursors with control + left click. 71 | set("n", "", mc.handleMouse) 72 | set("n", "", mc.handleMouseDrag) 73 | 74 | -- Easy way to add and remove cursors using the main cursor. 75 | set({ "n", "x" }, "", mc.toggleCursor) 76 | 77 | -- Clone every cursor and disable the originals. 78 | set({ "n", "x" }, "", mc.duplicateCursors) 79 | 80 | set("n", "", function() 81 | if not mc.cursorsEnabled() then 82 | mc.enableCursors() 83 | elseif mc.hasCursors() then 84 | mc.clearCursors() 85 | else 86 | -- Default handler. 87 | end 88 | end) 89 | 90 | -- bring back cursors if you accidentally clear them 91 | set("n", "gv", mc.restoreCursors) 92 | 93 | -- Align cursor columns. 94 | set("n", "a", mc.alignCursors) 95 | 96 | -- Split visual selections by regex. 97 | set("x", "S", mc.splitCursors) 98 | 99 | -- Append/insert for each line of visual selections. 100 | set("x", "I", mc.insertVisual) 101 | set("x", "A", mc.appendVisual) 102 | 103 | -- match new cursors within visual selections by regex. 104 | set("x", "M", mc.matchCursors) 105 | 106 | -- Rotate visual selection contents. 107 | set("x", "t", function() 108 | mc.transposeCursors(1) 109 | end) 110 | set("x", "T", function() 111 | mc.transposeCursors(-1) 112 | end) 113 | 114 | -- Jumplist support 115 | set({ "x", "n" }, "", mc.jumpForward) 116 | set({ "x", "n" }, "", mc.jumpBackward) 117 | 118 | -- Customize how cursors look. 119 | local hl = vim.api.nvim_set_hl 120 | hl(0, "MultiCursorCursor", { link = "Cursor" }) 121 | hl(0, "MultiCursorVisual", { link = "Visual" }) 122 | hl(0, "MultiCursorSign", { link = "SignColumn" }) 123 | hl(0, "MultiCursorMatchPreview", { link = "Search" }) 124 | hl(0, "MultiCursorDisabledCursor", { link = "Visual" }) 125 | hl(0, "MultiCursorDisabledVisual", { link = "Visual" }) 126 | hl(0, "MultiCursorDisabledSign", { link = "SignColumn" }) 127 | end, 128 | } 129 | -------------------------------------------------------------------------------- /lua/plugins/noice.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/noice.nvim", 3 | enabled = true, 4 | event = "VeryLazy", 5 | opts = { 6 | lsp = { 7 | -- override markdown rendering so that **cmp** and other plugins use **Treesitter** 8 | override = { 9 | ["vim.lsp.util.convert_input_to_markdown_lines"] = true, 10 | ["vim.lsp.util.stylize_markdown"] = true, 11 | ["cmp.entry.get_documentation"] = true, 12 | }, 13 | signature = { 14 | enabled = false, 15 | }, 16 | hover = { 17 | enabled = false, 18 | }, 19 | }, 20 | routes = { 21 | { 22 | filter = { 23 | event = "msg_show", 24 | any = { 25 | { find = "%d+L, %d+B" }, 26 | { find = "; after #%d+" }, 27 | { find = "; before #%d+" }, 28 | { find = "fewer lines" }, 29 | }, 30 | }, 31 | view = "mini", 32 | }, 33 | { 34 | filter = { 35 | event = "msg_show", 36 | any = { 37 | { find = "Agent service not initialized" }, 38 | }, 39 | }, 40 | opts = { skip = true }, 41 | }, 42 | { 43 | filter = { 44 | event = "notify", 45 | any = { 46 | { find = "No information available" }, 47 | }, 48 | }, 49 | opts = { skip = true }, 50 | }, 51 | }, 52 | views = { 53 | -- Clean cmdline_popup + palette 54 | cmdline_popup = { 55 | position = { 56 | row = 10, 57 | col = "50%", 58 | }, 59 | border = { 60 | style = "single", 61 | }, 62 | size = { 63 | min_width = 60, 64 | width = "auto", 65 | height = "auto", 66 | }, 67 | }, 68 | cmdline_popupmenu = { 69 | relative = "editor", 70 | position = { 71 | row = 13, 72 | col = "50%", 73 | }, 74 | size = { 75 | width = 60, 76 | height = "auto", 77 | max_height = 15, 78 | }, 79 | border = { 80 | style = "none", 81 | padding = { 0, 3 }, 82 | }, 83 | }, 84 | hover = { 85 | border = { 86 | style = "single", 87 | }, 88 | }, 89 | confirm = { 90 | border = { 91 | style = "single", 92 | }, 93 | }, 94 | popup = { 95 | border = { 96 | style = "single", 97 | }, 98 | }, 99 | }, 100 | }, 101 | } 102 | -------------------------------------------------------------------------------- /lua/plugins/obsidian.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "obsidian-nvim/obsidian.nvim", 3 | version = "*", 4 | lazy = false, 5 | opts = { 6 | -- A list of workspace names, paths, and configuration overrides. 7 | -- If you use the Obsidian app, the 'path' of a workspace should generally be 8 | -- your vault root (where the `.obsidian` folder is located). 9 | -- When obsidian.nvim is loaded by your plugin manager, it will automatically set 10 | -- the workspace to the first workspace in the list whose `path` is a parent of the 11 | -- current markdown file being edited. 12 | workspaces = { 13 | { 14 | name = "Notes", 15 | path = "~/Notes", 16 | }, 17 | }, 18 | 19 | -- Optional, set the log level for obsidian.nvim. This is an integer corresponding to one of the log 20 | -- levels defined by "vim.log.levels.*". 21 | log_level = vim.log.levels.INFO, 22 | 23 | daily_notes = { 24 | -- Optional, if you keep daily notes in a separate directory. 25 | folder = "dailies", 26 | -- Optional, if you want to change the date format for the ID of daily notes. 27 | date_format = "%Y-%m-%d-%H:%M", 28 | -- Optional, if you want to change the date format of the default alias of daily notes. 29 | alias_format = "%B %-d, %Y", 30 | -- Optional, default tags to add to each new daily note created. 31 | default_tags = { "daily-notes" }, 32 | -- Optional, if you want to automatically insert a template from your template directory like 'daily.md' 33 | template = nil, 34 | }, 35 | 36 | -- Optional, completion of wiki links, local markdown links, and tags using nvim-cmp. 37 | completion = { 38 | -- Set to false to disable completion. 39 | nvim_cmp = false, 40 | blink = true, 41 | -- Trigger completion at 2 chars. 42 | min_chars = 2, 43 | }, 44 | 45 | -- Optional, configure key mappings. These are the defaults. If you don't want to set any keymappings this 46 | -- way then set 'mappings = {}'. 47 | mappings = { 48 | -- Overrides the 'gf' mapping to work on markdown/wiki links within your vault. 49 | 50 | ["gf"] = { 51 | action = function() 52 | return require("obsidian").util.gf_passthrough() 53 | end, 54 | opts = { noremap = false, expr = true, buffer = true }, 55 | }, 56 | 57 | -- Smart action depending on context, either follow link or toggle checkbox. 58 | [""] = { 59 | action = function() 60 | return require("obsidian").util.smart_action() 61 | end, 62 | opts = { buffer = true, expr = true }, 63 | }, 64 | }, 65 | 66 | -- Where to put new notes. Valid options are 67 | -- * "current_dir" - put new notes in same directory as the current buffer. 68 | -- * "notes_subdir" - put new notes in the default notes subdirectory. 69 | new_notes_location = "notes_subdir", 70 | 71 | -- Optional, customize how note IDs are generated given an optional title. 72 | ---@param title string|? 73 | ---@return string 74 | note_id_func = function(title) 75 | -- Create note IDs in a format with a date and a suffix. 76 | -- In this case a note with the title 'My new note' will be given an ID that looks 77 | -- like '2022-07-24-my-new-note', and therefore the file name '2022-07-24-my-new-note.md' 78 | local suffix = "" 79 | if title ~= nil then 80 | -- If title is given, transform it into valid file name. 81 | suffix = title:gsub(" ", "-"):gsub("[^A-Za-z0-9-]", ""):lower() 82 | else 83 | -- If title is nil, just add 4 random uppercase letters to the suffix. 84 | for _ = 1, 4 do 85 | suffix = suffix .. string.char(math.random(65, 90)) 86 | end 87 | end 88 | -- Get the current date 89 | local date = os.date("*t") 90 | -- Format the date as year-month-day 91 | local date_str = string.format("%02d-%02d-%02d", date.year % 100, date.month, date.day) 92 | return suffix .. "-" .. date_str 93 | end, 94 | 95 | -- Optional, customize how note file names are generated given the ID, target directory, and title. 96 | ---@param spec { id: string, dir: obsidian.Path, title: string|? } 97 | ---@return string|obsidian.Path The full path to the new note. 98 | note_path_func = function(spec) 99 | -- This is equivalent to the default behavior. 100 | local path = spec.dir / tostring(spec.id) 101 | return path:with_suffix(".md") 102 | end, 103 | 104 | -- Optional, customize how wiki links are formatted. You can set this to one of: 105 | -- * "use_alias_only", e.g. '[[Foo Bar]]' 106 | -- * "prepend_note_id", e.g. '[[foo-bar|Foo Bar]]' 107 | -- * "prepend_note_path", e.g. '[[foo-bar.md|Foo Bar]]' 108 | -- * "use_path_only", e.g. '[[foo-bar.md]]' 109 | -- Or you can set it to a function that takes a table of options and returns a string, like this: 110 | wiki_link_func = function(opts) 111 | return require("obsidian.util").wiki_link_id_prefix(opts) 112 | end, 113 | 114 | -- Optional, customize how markdown links are formatted. 115 | markdown_link_func = function(opts) 116 | return require("obsidian.util").markdown_link(opts) 117 | end, 118 | 119 | -- Either 'wiki' or 'markdown'. 120 | preferred_link_style = "wiki", 121 | 122 | -- Optional, customize the default name or prefix when pasting images via `:ObsidianPasteImg`. 123 | ---@return string 124 | image_name_func = function() 125 | -- Prefix image names with timestamp. 126 | return string.format("%s-", os.time()) 127 | end, 128 | 129 | -- Optional, boolean or a function that takes a filename and returns a boolean. 130 | -- `true` indicates that you don't want obsidian.nvim to manage frontmatter. 131 | disable_frontmatter = false, 132 | 133 | -- Optional, alternatively you can customize the frontmatter data. 134 | ---@return table 135 | note_frontmatter_func = function(note) 136 | -- Add the title of the note as an alias. 137 | if note.title then 138 | note:add_alias(note.title) 139 | end 140 | 141 | local out = { id = note.id, aliases = note.aliases, tags = note.tags } 142 | 143 | -- `note.metadata` contains any manually added fields in the frontmatter. 144 | -- So here we just make sure those fields are kept in the frontmatter. 145 | if note.metadata ~= nil and not vim.tbl_isempty(note.metadata) then 146 | for k, v in pairs(note.metadata) do 147 | out[k] = v 148 | end 149 | end 150 | 151 | return out 152 | end, 153 | 154 | -- Optional, for templates (see below). 155 | templates = { 156 | folder = "templates", 157 | date_format = "%Y-%m-%d", 158 | time_format = "%H:%M", 159 | -- A map for custom variables, the key should be the variable and the value a function 160 | substitutions = {}, 161 | }, 162 | 163 | -- Optional, by default when you use `:ObsidianFollowLink` on a link to an external 164 | -- URL it will be ignored but you can customize this behavior here. 165 | ---@param url string 166 | follow_url_func = function(url) 167 | -- Open the URL in the default web browser. 168 | vim.fn.jobstart({ "open", url }) -- Mac OS 169 | -- vim.fn.jobstart({"xdg-open", url}) -- linux 170 | end, 171 | 172 | -- Optional, set to true if you use the Obsidian Advanced URI plugin. 173 | -- https://github.com/Vinzent03/obsidian-advanced-uri 174 | use_advanced_uri = false, 175 | 176 | -- Optional, set to true to force ':ObsidianOpen' to bring the app to the foreground. 177 | open_app_foreground = false, 178 | 179 | picker = { 180 | -- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', or 'mini.pick'. 181 | name = "snacks.pick", 182 | -- Optional, configure key mappings for the picker. These are the defaults. 183 | -- Not all pickers support all mappings. 184 | mappings = { 185 | -- Create a new note from your query. 186 | new = "", 187 | -- Insert a link to the selected note. 188 | insert_link = "", 189 | }, 190 | }, 191 | 192 | -- Optional, sort search results by "path", "modified", "accessed", or "created". 193 | -- The recommend value is "modified" and `true` for `sort_reversed`, which means, for example, 194 | -- that `:ObsidianQuickSwitch` will show the notes sorted by latest modified time 195 | sort_by = "modified", 196 | sort_reversed = true, 197 | 198 | -- Set the maximum number of lines to read from notes on disk when performing certain searches. 199 | search_max_lines = 1000, 200 | 201 | -- Optional, determines how certain commands open notes. The valid options are: 202 | -- 1. "current" (the default) - to always open in the current window 203 | -- 2. "vsplit" - to open in a vertical split if there's not already a vertical split 204 | -- 3. "hsplit" - to open in a horizontal split if there's not already a horizontal split 205 | open_notes_in = "current", 206 | 207 | -- Optional, define your own callbacks to further customize behavior. 208 | callbacks = { 209 | -- Runs at the end of `require("obsidian").setup()`. 210 | ---@param client obsidian.Client 211 | post_setup = function(client) end, 212 | 213 | -- Runs anytime you enter the buffer for a note. 214 | ---@param client obsidian.Client 215 | ---@param note obsidian.Note 216 | enter_note = function(client, note) end, 217 | 218 | -- Runs anytime you leave the buffer for a note. 219 | ---@param client obsidian.Client 220 | ---@param note obsidian.Note 221 | leave_note = function(client, note) end, 222 | 223 | -- Runs right before writing the buffer for a note. 224 | ---@param client obsidian.Client 225 | ---@param note obsidian.Note 226 | pre_write_note = function(client, note) end, 227 | 228 | -- Runs anytime the workspace is set/changed. 229 | ---@param client obsidian.Client 230 | ---@param workspace obsidian.Workspace 231 | post_set_workspace = function(client, workspace) end, 232 | }, 233 | 234 | -- Optional, configure additional syntax highlighting / extmarks. 235 | -- This requires you have `conceallevel` set to 1 or 2. See `:help conceallevel` for more details. 236 | ui = { 237 | enable = true, -- set to false to disable all additional syntax features 238 | update_debounce = 200, -- update delay after a text change (in milliseconds) 239 | max_file_length = 5000, -- disable UI features for files with more than this many lines 240 | -- Define how various check-boxes are displayed 241 | checkboxes = { 242 | -- NOTE: the 'char' value has to be a single character, and the highlight groups are defined below. 243 | [" "] = { char = "󰄱", hl_group = "ObsidianTodo" }, 244 | ["x"] = { char = "", hl_group = "ObsidianDone" }, 245 | [">"] = { char = "", hl_group = "ObsidianRightArrow" }, 246 | ["~"] = { char = "󰰱", hl_group = "ObsidianTilde" }, 247 | ["!"] = { char = "", hl_group = "ObsidianImportant" }, 248 | -- Replace the above with this if you don't have a patched font: 249 | -- [" "] = { char = "☐", hl_group = "ObsidianTodo" }, 250 | -- ["x"] = { char = "✔", hl_group = "ObsidianDone" }, 251 | 252 | -- You can also add more custom ones... 253 | }, 254 | -- Use bullet marks for non-checkbox lists. 255 | bullets = { char = "•", hl_group = "ObsidianBullet" }, 256 | external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" }, 257 | -- Replace the above with this if you don't have a patched font: 258 | -- external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" }, 259 | reference_text = { hl_group = "ObsidianRefText" }, 260 | highlight_text = { hl_group = "ObsidianHighlightText" }, 261 | tags = { hl_group = "ObsidianTag" }, 262 | block_ids = { hl_group = "ObsidianBlockID" }, 263 | hl_groups = { 264 | -- The options are passed directly to `vim.api.nvim_set_hl()`. See `:help nvim_set_hl`. 265 | ObsidianTodo = { bold = true, fg = "#f78c6c" }, 266 | ObsidianDone = { bold = true, fg = "#89ddff" }, 267 | ObsidianRightArrow = { bold = true, fg = "#f78c6c" }, 268 | ObsidianTilde = { bold = true, fg = "#ff5370" }, 269 | ObsidianImportant = { bold = true, fg = "#d73128" }, 270 | ObsidianBullet = { bold = true, fg = "#89ddff" }, 271 | ObsidianRefText = { underline = true, fg = "#c792ea" }, 272 | ObsidianExtLinkIcon = { fg = "#c792ea" }, 273 | ObsidianTag = { italic = true, fg = "#89ddff" }, 274 | ObsidianBlockID = { italic = true, fg = "#89ddff" }, 275 | ObsidianHighlightText = { bg = "#75662e" }, 276 | }, 277 | }, 278 | 279 | -- Specify how to handle attachments. 280 | attachments = { 281 | -- The default folder to place images in via `:ObsidianPasteImg`. 282 | -- If this is a relative path it will be interpreted as relative to the vault root. 283 | -- You can always override this per image by passing a full path to the command instead of just a filename. 284 | img_folder = "assets/imgs", -- This is the default 285 | -- A function that determines the text to insert in the note when pasting an image. 286 | -- It takes two arguments, the `obsidian.Client` and an `obsidian.Path` to the image file. 287 | -- This is the default implementation. 288 | ---@param client obsidian.Client 289 | ---@param path obsidian.Path the absolute path to the image file 290 | ---@return string 291 | img_text_func = function(client, path) 292 | path = client:vault_relative_path(path) or path 293 | return string.format("![%s](%s)", path.name, path) 294 | end, 295 | }, 296 | }, 297 | } 298 | -------------------------------------------------------------------------------- /lua/plugins/rainbow-delimiters.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "HiPhish/rainbow-delimiters.nvim", 3 | enabled = true, 4 | config = function() 5 | -- This module contains a number of default definitions 6 | local rainbow_delimiters = require("rainbow-delimiters") 7 | local colors = dofile(vim.g.base46_cache .. "colors") 8 | 9 | local color_mappings = { 10 | RainbowRed = colors.red, 11 | RainbowYellow = colors.yellow, 12 | RainbowBlue = colors.blue, 13 | RainbowOrange = colors.orange, 14 | RainbowGreen = colors.green, 15 | RainbowViolet = colors.purple, 16 | RainbowCyan = colors.cyan, 17 | RainbowMagenta = colors.magenta, 18 | RainbowPink = colors.pink, 19 | RainbowBrown = colors.brown, 20 | } 21 | 22 | for name, color in pairs(color_mappings) do 23 | vim.api.nvim_set_hl(0, name, { fg = color }) 24 | end 25 | 26 | ---@type rainbow_delimiters.config 27 | vim.g.rainbow_delimiters = { 28 | strategy = { 29 | [""] = rainbow_delimiters.strategy["global"], 30 | vim = rainbow_delimiters.strategy["local"], 31 | }, 32 | query = { 33 | [""] = "rainbow-delimiters", 34 | }, 35 | priority = { 36 | [""] = 110, 37 | lua = 210, 38 | }, 39 | highlight = { 40 | "RainbowRed", 41 | "RainbowYellow", 42 | "RainbowBlue", 43 | -- "RainbowOrange", 44 | "RainbowGreen", 45 | "RainbowViolet", 46 | "RainbowCyan", 47 | "RainbowMagenta", 48 | "RainbowBrown", 49 | }, 50 | } 51 | end, 52 | } 53 | -------------------------------------------------------------------------------- /lua/plugins/snacks.lua: -------------------------------------------------------------------------------- 1 | -- Main configuration table 2 | local opts = {} 3 | 4 | -- =============================== 5 | -- Terminal Configuration 6 | -- =============================== 7 | opts.terminal = { 8 | enabled = false, 9 | win = { 10 | wo = { 11 | winbar = "", 12 | }, 13 | }, 14 | } 15 | 16 | -- =============================== 17 | -- Image Configuration 18 | -- =============================== 19 | ---@class snacks.image.Config 20 | opts.image = { enabled = true, doc = { 21 | inline = false, 22 | } } 23 | 24 | -- =============================== 25 | -- Profiler Configuration 26 | -- =============================== 27 | opts.profiler = { enabled = true } 28 | 29 | -- =============================== 30 | -- Picker Configuration 31 | -- =============================== 32 | ---@class snacks.picker.Config 33 | opts.picker = { 34 | layout = { 35 | layout = { 36 | box = "horizontal", 37 | border = "none", 38 | width = 0.8, 39 | min_width = 120, 40 | height = 0.8, 41 | { 42 | box = "vertical", 43 | border = "single", 44 | title = "{title} {live} {flags}", 45 | { win = "input", height = 1, border = "single" }, 46 | { win = "list", border = "none" }, 47 | }, 48 | { win = "preview", title = "{preview}", border = "single", width = 0.6 }, 49 | }, 50 | }, 51 | } 52 | 53 | -- =============================== 54 | -- Indent Configuration 55 | -- =============================== 56 | ---@class snacks.indent.Config 57 | opts.indent = { 58 | enabled = true, 59 | chunk = { 60 | enabled = true, 61 | -- only show chunk scopes in the current window 62 | only_current = false, 63 | hl = "SnacksIndentChunk", ---@type string|string[] hl group for chunk scopes 64 | char = { 65 | corner_top = "┌", 66 | corner_bottom = "└", 67 | -- corner_top = "╭", 68 | -- corner_bottom = "╰", 69 | horizontal = "─", 70 | vertical = "│", 71 | arrow = "─", 72 | }, 73 | }, 74 | } 75 | 76 | -- =============================== 77 | -- Bigfile Configuration 78 | -- =============================== 79 | ---@class snacks.bigfile.Config 80 | opts.bigfile = { enabled = true } 81 | 82 | -- =============================== 83 | -- Dashboard Configuration 84 | -- =============================== 85 | ---@class snacks.dashboard.Config 86 | opts.dashboard = { 87 | width = 60, 88 | row = nil, -- dashboard position. nil for center 89 | col = nil, -- dashboard position. nil for center 90 | pane_gap = 4, -- empty columns between vertical panes 91 | autokeys = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -- autokey sequence 92 | 93 | -- Preset settings used by some built-in sections 94 | preset = { 95 | pick = nil, 96 | keys = { 97 | { icon = " ", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" }, 98 | { icon = " ", key = "n", desc = "New File", action = ":ene | startinsert" }, 99 | { icon = " ", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" }, 100 | { icon = "", key = "x", desc = "Lazy Extras", action = "LazyExtras" }, 101 | -- { icon = " ", key = "m", desc = "Marks", action = ":lua Snacks.dashboard.pick('marks')" }, 102 | { 103 | icon = " ", 104 | key = "c", 105 | desc = "Config", 106 | action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})", 107 | }, 108 | { icon = " ", key = "s", desc = "Restore Session", section = "session" }, 109 | { icon = "󰒲 ", key = "l", desc = "Lazy", action = ":Lazy", enabled = package.loaded.lazy ~= nil }, 110 | { icon = " ", key = "q", desc = "Quit", action = ":qa" }, 111 | }, 112 | header = [[ 113 | ██████╗ ███████╗ ██████╗ ███╗ ███╗ 114 | ██╔══██╗╚════██║██╔═══██╗████╗ ████║ 115 | ██║ ██║ ██╔╝██║ ██║██╔████╔██║ 116 | ██║ ██║ ██╔╝ ██║ ██║██║╚██╔╝██║ 117 | ██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ██║ 118 | ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 119 | [d7om.dev] 120 | ]], 121 | }, 122 | sections = { 123 | { section = "header" }, 124 | { 125 | pane = 2, 126 | section = "terminal", 127 | -- cmd = "fastfetch --logo none | rg --colors=match:fg:cyan '|||||󰝚|'", 128 | cmd = "pipes.sh -t 1", 129 | height = 8, 130 | padding = 2, 131 | }, 132 | { section = "keys", gap = 1, padding = 1 }, 133 | { pane = 2, icon = "", title = "Recent Files", section = "recent_files", indent = 2, padding = 1 }, 134 | { pane = 2, icon = " ", title = "Projects", section = "projects", indent = 2, padding = 1 }, 135 | { 136 | pane = 2, 137 | icon = " ", 138 | title = "Git Status", 139 | section = "terminal", 140 | enabled = vim.fn.isdirectory(".git") == 1, 141 | cmd = "hub status --short --branch --renames", 142 | height = 5, 143 | padding = 1, 144 | ttl = 5 * 60, 145 | indent = 3, 146 | }, 147 | { section = "startup" }, 148 | }, 149 | } 150 | 151 | -- =============================== 152 | -- Notifier Configuration 153 | -- =============================== 154 | opts.notifier = { 155 | enabled = true, 156 | timeout = 3000, 157 | } 158 | 159 | -- =============================== 160 | -- Quickfile Configuration 161 | -- =============================== 162 | opts.quickfile = { enabled = true } 163 | 164 | -- =============================== 165 | -- Statuscolumn Configuration 166 | -- =============================== 167 | opts.statuscolumn = { enabled = true } 168 | 169 | -- =============================== 170 | -- Words Configuration 171 | -- =============================== 172 | opts.words = { enabled = true } 173 | 174 | -- =============================== 175 | -- Styles Configuration 176 | -- =============================== 177 | opts.styles = { 178 | notification = { 179 | border = "single", 180 | wo = { wrap = false }, -- Wrap notifications 181 | }, 182 | notification_history = { 183 | border = "single", 184 | }, 185 | input = { 186 | backdrop = false, 187 | position = "float", 188 | border = "single", 189 | height = 1, 190 | width = 40, 191 | relative = "cursor", 192 | row = -3, 193 | col = 1, 194 | b = { 195 | completion = false, 196 | }, 197 | }, 198 | } 199 | 200 | -- scroll conf 201 | 202 | -- =============================== 203 | -- Scroll Configuration 204 | -- =============================== 205 | opts.scroll = { 206 | enabled = false, 207 | } 208 | 209 | -- =============================== 210 | -- Keybindings Configuration 211 | -- =============================== 212 | local keys = { 213 | -- { 214 | -- "gB", 215 | -- function() 216 | -- Snacks.gitbrowse() 217 | -- end, 218 | -- desc = "Git Browse", 219 | -- }, 220 | -- { 221 | -- "gg", 222 | -- function() 223 | -- Snacks.lazygit() 224 | -- end, 225 | -- desc = "Lazygit", 226 | -- }, 227 | } 228 | 229 | return { 230 | "folke/snacks.nvim", 231 | priority = 1000, 232 | lazy = false, 233 | opts = opts, 234 | keys = keys, 235 | } 236 | -------------------------------------------------------------------------------- /lua/plugins/tailwind-tools.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "luckasRanarison/tailwind-tools.nvim", 4 | event = "BufRead", 5 | -- enabled = function() 6 | -- return not vim.tbl_contains({ "AvanteInput", "minifiles", "snacks_dashboard", "blade" }, vim.bo.filetype) 7 | -- and vim.bo.buftype ~= "prompt" 8 | -- and vim.b.completion ~= false 9 | -- end, 10 | enabled = false, 11 | name = "tailwind-tools", 12 | build = ":UpdateRemotePlugins", 13 | ft = { "typescriptreact", "astro", "vue" }, 14 | opts = { 15 | server = { 16 | override = true, -- setup the server from the plugin if true 17 | settings = {}, -- shortcut for `settings.tailwindCSS` 18 | }, 19 | document_color = { 20 | enabled = true, -- can be toggled by commands 21 | kind = "background", -- "inline" | "foreground" | "background" 22 | inline_symbol = "󰝤 ", -- only used in inline mode 23 | debounce = 100, -- in milliseconds, only applied in insert mode 24 | }, 25 | conceal = { 26 | enabled = true, -- can be toggled by commands 27 | min_length = 20, -- only conceal classes exceeding the provided length 28 | symbol = "󱏿", -- only a single character is allowed 29 | highlight = { -- extmark highlight options, see :h 'highlight' 30 | fg = "#38BDF8", 31 | }, 32 | }, 33 | cmp = { 34 | highlight = "foreground", -- color preview style, "foreground" | "background" 35 | }, 36 | }, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /lua/plugins/ts.lua: -------------------------------------------------------------------------------- 1 | local map = vim.keymap.set 2 | -- this file will hold ts stuff 3 | return { 4 | { 5 | "davidosomething/format-ts-errors.nvim", 6 | event = "VeryLazy", 7 | config = function() 8 | require("format-ts-errors").setup({ 9 | add_markdown = true, 10 | start_indent_level = 0, 11 | }) 12 | end, 13 | }, 14 | -- LSP 15 | { 16 | "pmizio/typescript-tools.nvim", 17 | enabled = function() 18 | return not (vim.fn.filereadable("src/App.vue") == 1 or vim.fn.filereadable("nuxt.config.ts") == 1) 19 | end, 20 | dependencies = { 21 | "nvim-lua/plenary.nvim", 22 | "neovim/nvim-lspconfig", 23 | }, 24 | ft = { 25 | "typescript", 26 | "typescriptreact", 27 | "javascript", 28 | "javascriptreact", 29 | }, 30 | config = function() 31 | local api = require("typescript-tools.api") 32 | 33 | require("typescript-tools").setup({ 34 | filetypes = { 35 | "javascript", 36 | "javascriptreact", 37 | "typescript", 38 | "typescriptreact", 39 | }, 40 | on_attach = function(client, bufNr) 41 | map("n", "gD", "TSToolsGoToSourceDefinition", { 42 | desc = "Go to source definition", 43 | silent = true, 44 | buffer = bufNr, 45 | }) 46 | -- TSToolsFileReferences 47 | map("n", "gR", "TSToolsFileReferences", { 48 | desc = "File References", 49 | silent = true, 50 | buffer = bufNr, 51 | }) 52 | map( 53 | { "n", "v" }, 54 | "co", 55 | "TSToolsOrganizeImports", 56 | { desc = "Imports Organize", silent = true, buffer = bufNr } 57 | ) 58 | map( 59 | { "n", "v" }, 60 | "cS", 61 | "TSToolsSortImports", 62 | { desc = "Imports Sort", silent = true, buffer = bufNr } 63 | ) 64 | map({ "n", "v" }, "cr", "TSToolsRemoveUnusedImports", { 65 | desc = "Imports remove unused", 66 | silent = true, 67 | buffer = bufNr, 68 | }) 69 | map({ "n", "v" }, "cM", "TSToolsAddMissingImports", { 70 | desc = "Add missing imports", 71 | silent = true, 72 | buffer = bufNr, 73 | }) 74 | map( 75 | { "n", "v" }, 76 | "rF", 77 | "TSToolsRenameFile", 78 | { desc = "Rename File", silent = true, buffer = bufNr } 79 | ) 80 | -- TSToolsFixAll 81 | map({ "n", "v" }, "cD", "TSToolsFixAll", { 82 | desc = "Fix all diagnostics", 83 | silent = true, 84 | buffer = bufNr, 85 | }) 86 | end, 87 | handlers = { 88 | ["textDocument/publishDiagnostics"] = api.filter_diagnostics({ 89 | 80001, -- Ignore this might be converted to a ES export 90 | }), 91 | }, 92 | settings = { 93 | -- For Vue support 94 | -- tsserver_plugins = { 95 | -- "@vue/typescript-plugin", 96 | -- }, 97 | -- Enable all code actions 98 | expose_as_code_action = "all", 99 | complete_function_calls = true, 100 | jsx_close_tag = { 101 | enable = true, 102 | filetypes = { "javascriptreact", "typescriptreact" }, 103 | }, 104 | }, 105 | }) 106 | end, 107 | }, 108 | } 109 | -------------------------------------------------------------------------------- /lua/plugins/ui.lua: -------------------------------------------------------------------------------- 1 | local g = vim.g 2 | 3 | g.toggle_theme_icon = "  " 4 | 5 | local txt = function(str, hl) 6 | str = str or "" 7 | local a = "%#Tb" .. hl .. "#" .. str 8 | return a 9 | end 10 | 11 | local btn = function(str, hl, func, arg) 12 | str = hl and txt(str, hl) or str 13 | arg = arg or "" 14 | return "%" .. arg .. "@Tb" .. func .. "@" .. str .. "%X" 15 | end 16 | 17 | vim.cmd("function! TbToggle_theme(a,b,c,d) \n lua require('base46').toggle_theme() \n endfunction") 18 | vim.cmd("function! TbCloseAllBufs(a,b,c,d) \n lua Utils.close_all_buffers() \n endfunction") 19 | 20 | return { 21 | { 22 | "catppuccin/nvim", 23 | event = "BufRead", 24 | }, 25 | { "tiagovla/scope.nvim", config = true }, 26 | { 27 | "akinsho/bufferline.nvim", 28 | enabled = true, 29 | config = function() 30 | require("bufferline").setup({ 31 | highlights = { 32 | buffer_selected = { 33 | bg = "#1E2122", 34 | }, 35 | duplicate_selected = { 36 | bg = "#1E2122", 37 | bold = true, 38 | }, 39 | duplicate_visible = { 40 | bg = "#1E2122", 41 | bold = false, 42 | italic = false, 43 | }, 44 | duplicate = { 45 | bold = false, 46 | italic = false, 47 | }, 48 | close_button_selected = { 49 | fg = "#CA6169", 50 | bg = "#2D3031", 51 | }, 52 | separator_selected = { 53 | fg = "#1E2122", 54 | bg = "#1E2122", 55 | }, 56 | modified_selected = { 57 | bg = "#2D3031", 58 | }, 59 | indicator_selected = { 60 | bg = "#1E2122", 61 | }, 62 | diagnostic = { 63 | bg = "#1E2122", 64 | }, 65 | diagnostic_selected = { 66 | bg = "#1E2122", 67 | }, 68 | hint_selected = { 69 | bg = "#1E2122", 70 | }, 71 | hint_diagnostic_selected = { 72 | bg = "#1E2122", 73 | }, 74 | info_selected = { 75 | bg = "#1E2122", 76 | }, 77 | info_diagnostic_selected = { 78 | bg = "#1E2122", 79 | }, 80 | warning_selected = { 81 | bg = "#1E2122", 82 | }, 83 | warning_diagnostic_selected = { 84 | bg = "#1E2122", 85 | }, 86 | error_selected = { 87 | bg = "#1E2122", 88 | }, 89 | error_diagnostic_selected = { 90 | bg = "#1E2122", 91 | }, 92 | pick_selected = { 93 | bg = "#1E2122", 94 | }, 95 | }, 96 | 97 | options = { 98 | separator_style = { "", "" }, 99 | buffer_close_icon = " ", 100 | modified_icon = " ", 101 | diagnostics = "nvim_lsp", -- Enable LSP diagnostics 102 | diagnostics_indicator = function(_, _, diagnostics_dict, _) 103 | local s = "" 104 | for e, n in pairs(diagnostics_dict) do 105 | local sym = e == "error" and " " or (e == "warning" and " " or "󱩎 ") 106 | s = s .. sym .. n .. " " 107 | end 108 | return s 109 | end, 110 | custom_areas = { 111 | right = function() 112 | local toggle_theme = { 113 | text = btn(g.toggle_theme_icon, "ThemeToggleBtn", "Toggle_theme"), 114 | } 115 | local close_all_bufs = { 116 | text = btn(" 󰅖 ", "CloseAllBufsBtn", "CloseAllBufs"), 117 | } 118 | if vim.bo.filetype == "snacks_dashboard" then 119 | return {} 120 | else 121 | return { toggle_theme, close_all_bufs } 122 | end 123 | end, 124 | }, 125 | }, 126 | }) 127 | end, 128 | }, 129 | { 130 | "mvllow/modes.nvim", 131 | event = "BufRead", 132 | enabled = true, 133 | config = function() 134 | require("modes").setup({ 135 | line_opacity = 0.2, 136 | set_cursorline = false, 137 | set_number = false, 138 | ignore = { "NvimTree", "TelescopePrompt", "dashboard", "minifiles" }, 139 | }) 140 | end, 141 | }, 142 | { 143 | "rachartier/tiny-inline-diagnostic.nvim", 144 | event = "LspAttach", 145 | enabled = true, 146 | priority = 1000, -- needs to be loaded in first 147 | config = function() 148 | require("tiny-inline-diagnostic").setup({ 149 | preset = "simple", 150 | options = { 151 | show_source = true, 152 | use_icons_from_diagnostic = true, 153 | show_all_diags_on_cursorline = true, 154 | }, 155 | }) 156 | end, 157 | }, 158 | -- { 159 | -- "Bekaboo/dropbar.nvim", 160 | -- event = "BufRead", 161 | -- config = function() 162 | -- local dropbar_api = require("dropbar.api") 163 | -- vim.keymap.set("n", ";", dropbar_api.pick, { desc = "Pick symbols in winbar" }) 164 | -- vim.keymap.set("n", "[;", dropbar_api.goto_context_start, { desc = "Go to start of current context" }) 165 | -- vim.keymap.set("n", "];", dropbar_api.select_next_context, { desc = "Select next context" }) 166 | -- end, 167 | -- }, 168 | { 169 | "rachartier/tiny-glimmer.nvim", 170 | branch = "main", 171 | event = "TextYankPost", 172 | opts = { 173 | default_animation = "fade", 174 | overwrite = { 175 | search = { 176 | enabled = false, 177 | default_animation = "pulse", 178 | next_mapping = "nzzzv", 179 | prev_mapping = "Nzzzv", 180 | }, 181 | paste = { 182 | enabled = true, 183 | default_animation = "reverse_fade", 184 | paste_mapping = "p", 185 | Paste_mapping = "P", 186 | }, 187 | undo = { 188 | enabled = true, 189 | default_animation = { 190 | name = "fade", 191 | }, 192 | undo_mapping = "u", 193 | }, 194 | redo = { 195 | enabled = true, 196 | default_animation = { 197 | name = "reverse_fade", 198 | }, 199 | redo_mapping = "", 200 | }, 201 | }, 202 | }, 203 | }, 204 | { 205 | "https://git.sr.ht/~whynothugo/lsp_lines.nvim", 206 | event = "LspAttach", 207 | enabled = false, 208 | config = function() 209 | vim.diagnostic.config({ virtual_lines = { only_current_line = true } }) 210 | vim.api.nvim_create_autocmd("FileType", { 211 | pattern = { "lazy", "text" }, 212 | callback = function() 213 | vim.diagnostic.config({ virtual_lines = false }) 214 | end, 215 | }) 216 | require("lsp_lines").setup() 217 | end, 218 | }, 219 | } 220 | -------------------------------------------------------------------------------- /lua/plugins/windows.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "d7omdev/windows.nvim", 4 | event = "BufRead", 5 | enabled = false, 6 | dependencies = { "anuvyklack/middleclass", "anuvyklack/animation.nvim" }, 7 | config = function() 8 | vim.o.winwidth = 100 9 | vim.o.winminwidth = 50 10 | vim.o.equalalways = false 11 | require("windows").setup({ 12 | autowidth = { 13 | enable = false, 14 | winwidth = 5, 15 | filetype = { 16 | help = 2, 17 | }, 18 | }, 19 | autoheight = { 20 | enable = false, 21 | winheight = 5, 22 | filetype = { 23 | help = 1, 24 | }, 25 | }, 26 | autoboth = { 27 | enable = true, 28 | }, 29 | }) 30 | end, 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /stylua.toml: -------------------------------------------------------------------------------- 1 | indent_type = "Spaces" 2 | indent_width = 2 3 | column_width = 120 --------------------------------------------------------------------------------