├── .gitignore ├── .luarc.json ├── .masonrc.json ├── LICENSE ├── README.md ├── docs └── readme │ ├── masonrc.png │ ├── preview1.png │ └── preview2.png ├── ftdetect └── init.lua ├── ftplugin ├── java.lua └── rust.lua ├── init.lua ├── lua ├── config │ ├── buffer-closer.lua │ ├── bufferline.lua │ ├── cmp │ │ ├── LuaSnip.lua │ │ └── init.lua │ ├── comment │ │ ├── Comment.lua │ │ └── todo-comments.lua │ ├── conform.lua │ ├── copilot.lua │ ├── dap │ │ ├── dap-virtual-text.lua │ │ ├── dapui.lua │ │ └── init.lua │ ├── flutter-tools.lua │ ├── git │ │ ├── git-conflict.lua │ │ └── gitsigns.lua │ ├── highlight-colors.lua │ ├── indent-blankline.lua │ ├── lazy-nvim.lua │ ├── lsp │ │ ├── default.lua │ │ ├── lspconfig.lua │ │ └── lspsaga.lua │ ├── lualine │ │ ├── components │ │ │ ├── copilot.lua │ │ │ ├── diagnostics.lua │ │ │ ├── encoding.lua │ │ │ ├── file.lua │ │ │ ├── git.lua │ │ │ ├── indent.lua │ │ │ ├── location.lua │ │ │ ├── lsp_servers.lua │ │ │ ├── mode.lua │ │ │ └── time.lua │ │ ├── init.lua │ │ └── seps.lua │ ├── mason.lua │ ├── nvim-autopairs.lua │ ├── nvim-tree.lua │ ├── nvim-treesitter.lua │ ├── nvim-ufo.lua │ ├── stcursorword.lua │ ├── sttusline │ │ └── init.lua │ ├── telescope │ │ └── init.lua │ ├── toggleterm.lua │ ├── tokyonight.lua │ ├── url-open.lua │ ├── whichkey.lua │ ├── wilder.lua │ └── witch.lua ├── core │ ├── autocmd.lua │ ├── bootstrap.lua │ ├── command.lua │ ├── nvimmap.lua │ ├── option.lua │ └── plugmap.lua ├── extension │ ├── copilot.lua │ ├── git-conflict.lua │ ├── lualine.lua │ └── mason.lua ├── language │ └── vietnamese.lua ├── plugins │ └── init.lua ├── ui │ ├── border.lua │ ├── colors.lua │ └── icons │ │ ├── init.lua │ │ └── lspkind.lua └── utils │ ├── init.lua │ ├── mapper.lua │ ├── notify.lua │ ├── plug-extension.lua │ ├── reloader.lua │ └── tbl.lua ├── stylua.toml └── templates └── plug_autocmd.txt /.gitignore: -------------------------------------------------------------------------------- 1 | test.txt 2 | lazy-lock.json 3 | directory-structure.md 4 | -------------------------------------------------------------------------------- /.luarc.json: -------------------------------------------------------------------------------- 1 | { 2 | "diagnostics.disable": ["undefined-field", "different-requires"] 3 | } 4 | -------------------------------------------------------------------------------- /.masonrc.json: -------------------------------------------------------------------------------- 1 | [ 2 | "lua-language-server", 3 | "stylua", 4 | "bash-language-server", 5 | "shfmt", 6 | "shellcheck", 7 | "taplo", 8 | "clangd", 9 | "clang-format", 10 | "cmake-language-server", 11 | "codelldb", 12 | "pyright", 13 | "autopep8", 14 | "codespell", 15 | "prettierd", 16 | "eslint-lsp", 17 | "css-lsp", 18 | "html-lsp", 19 | "typescript-language-server", 20 | "emmet-ls", 21 | "json-lsp", 22 | "tailwindcss-language-server", 23 | "google-java-format", 24 | "java-debug-adapter", 25 | "jdtls" 26 | ] 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Tran Vo Son Tung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is the distro neovim for fullstack development. 2 | 3 | 🚀 Performance for time startup: 24ms - 50ms(about 50 plugins) 4 | 5 | ## Features 6 | 7 | | Plugin | Description | 8 | | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | 9 | | [lazy](https://github.com/folke/lazy.nvim) | A plugin manager that loads plugins lazily to ensure fast startup times. | 10 | | [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) | Support default lsp for (lua, python, web development, java, bash, c-c++ ) | 11 | | [mason](https://github.com/williamboman/mason.nvim) | Automatically installs LSP servers, formatters, linters, and debug adapters | 12 | | [conform](https://github.com/stevearc/conform.nvim) | Fast formatter | 13 | | [nvim-cmp](https://github.com/hrsh7th/nvim-cmp) | A lightweight completion plugin | 14 | | [witch](https://github.com/sontungexpt/witch) | Main theme | 15 | | [url-open](https://github.com/sontungexpt/url-open) | Great plugin to open the url under cursor | 16 | | [stcursorword](https://github.com/sontungexpt/stcursorword) | Highlight all words similar to the word under the cursor | 17 | | [buffer-closer](https://github.com/sontungexpt/buffer-closer) | Automatic close unused buffers | 18 | | [nvim-tree](https://github.com/nvim-tree/nvim-tree.lua) | A fast and lightweight file explorer | 19 | | [toggleterm](https://github.com/akinsho/toggleterm.nvim) | Includes a terminal using toggleterm | 20 | | [gitsigns](https://github.com/lewis6991/gitsigns.nvim), [git-conflict](https://github.com/akinsho/git-conflict.nvim) | Integrates Git functionality with gitsigns and git-conflict plugins for a seamless Git experience. | 21 | | [comment](https://github.com/numToStr/Comment.nvim) | A plugin for easily generating comments. | 22 | | [dap](https://github.com/mfussenegger/nvim-dap), [dapui](https://github.com/rcarriga/nvim-dap-ui) | Offers debugging capabilities with dap and dapui plugins. | 23 | | [treesitter](https://github.com/nvim-treesitter/nvim-treesitter) | Provides syntax highlighting | 24 | | [autopairs](https://github.com/windwp/nvim-autopairs) | Auto generate pairs | 25 | | [rainbow-delimiters](https://github.com/HiPhish/rainbow-delimiters.nvim) | Beautiful bracket highlighting | 26 | | [ccc](https://github.com/uga-rosa/ccc.nvim) | A color picker using ccc | 27 | | [sttusline](https://github.com/sontungexpt/sttusline) | A very lightweight, super fast and lazyloading statusline plugin for neovim written in lua | 28 | | [telescope](https://github.com/nvim-telescope/telescope.nvim) | Provides a file finder using telescope, a fuzzy finder plugin for files, buffers, and more. | 29 | 30 | And many more plugins that you can see in [plugins/init.lua](./lua/plugins/init.lua) 31 | 32 | 33 | 34 | ## Preview 35 | 36 | ![preview1](./docs/readme/preview1.png) 37 | 38 | ![preview2](./docs/readme/preview2.png) 39 | 40 | ## How to add more key map 41 | 42 | - We provide you two files for keymap. 43 | 44 | - One for plugin key map (~/.config/nvim/lua/core/plugmap.lua).(This file will 45 | be load on startup) 46 | 47 | - One for some custom default nvim map (~/.config/nvim/lua/core/nvimmap.lua). 48 | In this file if any keymap you want it run on startup please put your map 49 | function in map_on_startup function 50 | 51 | - We provide you a function to map 52 | 53 | ```lua 54 | ---@tparam table|string mode : Table mode used for applying the key map if only one mode you can use string 55 | ---@tparam string key : The key you wish to map. 56 | ---@tparam function|string map_to : The key or function to be executed by the keymap. 57 | ---@tparam table|number opts : Options to be applied in vim.keymap.set. 58 | --- - Default opts = 1. 59 | --- - opts = 1 for noremap and silent and nowait. 60 | --- - opts = 2 for not noremap and silent. 61 | --- - opts = 3 for noremap and not silent. 62 | --- - opts = 4 for not noremap and not silent. 63 | --- - opts = 5 for expr and noremap and silent. 64 | --- - opts = 6 for noremap and silent and wait. 65 | --- - opts = 7 for noremap and silent and nowait and expr. 66 | ---@tparam table extend_opts: Extension or overriding of opts if opts is a number. 67 | require("utils.mapper").map(mode, key, map_to, opts, extend_opts) 68 | 69 | --- Examples: 70 | require("utils.mapper").map({ "n", "v" }, "gx", ":URLOpenUnderCursor", { desc = "Open URL under cursor" }) 71 | require("utils.mapper").map("n" }, "gx", ":URLOpenUnderCursor", 2, { desc = "Open URL under cursor" }) 72 | ``` 73 | 74 | ## Install LSP, debugger 75 | 76 | - We use mason plugin to automatically install lsps, debuggers, linters 77 | - To ensure a package is automatically synced on startup, you can create a `.masonrc.json` file in the project's root directory or add 78 | packages to ensured_installed in ~/.config/nvim/lua/plugins/configs/mason.lua 79 | - If you want disable automatically synced mason packages on startup, you can change 80 | `auto_sync = false` in ~/.config/nvim/lua/plugins/configs/mason.lua 81 | - Additionally, you can manually sync the package by using the command `:MasonSyncPackages` in your neovim 82 | 83 | - Example .masonrc.json 84 | ![.masonrc.json](./docs/readme/masonrc.png) 85 | 86 | ## Requirements 87 | 88 | - xclip (for clipboard support) 89 | - fd (for telescope) 90 | - ripgrep (for telescope) 91 | - Nerdfonts (for icons) (I use Hack Nerd Font) 92 | - Neovim 0.5 or higher 93 | 94 | Arch Linux: 95 | 96 | ```bash 97 | sudo pacman -S xclip fd ripgrep 98 | ``` 99 | 100 | ```bash 101 | yay -S ttf-hack-nerd 102 | ``` 103 | 104 | ## Installation 105 | 106 | Clone this repository into your Neovim configuration directory. 107 | 108 | Linux and MacOS: 109 | 110 | SSH method (recommended) 111 | 112 | ```bash 113 | [ -d ~/.config/nvim ] && mv ~/.config/nvim ~/.config/nvim.bak ; git clone git@github.com:sontungexpt/stinvim.git ~/.config/nvim --depth 1 114 | ``` 115 | 116 | ```bash 117 | [ -d ~/.config/nvim ] && mv ~/.config/nvim ~/.config/nvim.bak ; git clone https://github.com/sontungexpt/stinvim.git ~/.config/nvim --depth 1 118 | ``` 119 | 120 | Windows (git bash) 121 | 122 | ```bash 123 | [ -d %USERPROFILE%/Local/nvim ] && mv %USERPROFILE%\AppData\Local\nvim %USERPROFILE%\AppData\Local\nvim.bak ; git clone https://github.com/sontungexpt/stinvim.git %USERPROFILE%\AppData\Local\nvim --depth 1 124 | ``` 125 | 126 | You will also need to install the plugins. This configuration uses the lazy.nvim plugin manager to manage plugins. You can install the plugins by opening Neovim and running `:Lazy sync` 127 | 128 | In this distro we enable two providers: nodejs and python so please install it or you can disable it in file ~/.config/nvim/lua/core/provider.lua 129 | 130 | ```bash 131 | # for nodejs 132 | npm install -g neovim 133 | 134 | # for ruby 135 | # gem install neovim 136 | 137 | # for python 138 | python3 -m venv .venv 139 | source .venv/bin/activate 140 | pip install --upgrade pip 141 | pip install neovim 142 | ``` 143 | 144 | ```vim 145 | :Lazy sync 146 | ``` 147 | 148 | ## Inspiration 149 | 150 | - [neovim-config](https://github.com/sontungexpt/neovim-config) 151 | 152 | ## Configuration 153 | 154 | This configuration is highly customizable and easy to configure. 155 | 156 | ## Contributions 157 | 158 | If you find any issues with this configuration or would like to contribute, please feel free to submit a pull request or open an issue. 159 | 160 | ## License 161 | 162 | This configuration is licensed under the MIT license - see the [LICENSE](LICENSE) file for details. 163 | -------------------------------------------------------------------------------- /docs/readme/masonrc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sontungexpt/stinvim/99a280bbd06104793b880b5a654ec8a03f5ab78d/docs/readme/masonrc.png -------------------------------------------------------------------------------- /docs/readme/preview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sontungexpt/stinvim/99a280bbd06104793b880b5a654ec8a03f5ab78d/docs/readme/preview1.png -------------------------------------------------------------------------------- /docs/readme/preview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sontungexpt/stinvim/99a280bbd06104793b880b5a654ec8a03f5ab78d/docs/readme/preview2.png -------------------------------------------------------------------------------- /ftdetect/init.lua: -------------------------------------------------------------------------------- 1 | -- https://neovim.io/doc/user/lua.html#vim.filetype.add() 2 | vim.filetype.add { 3 | extension = { 4 | json = "jsonc", 5 | rasi = "rasi", 6 | html = "html", 7 | zsh = "sh", 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /ftplugin/java.lua: -------------------------------------------------------------------------------- 1 | local ok, jdtls = pcall(require, "jdtls") 2 | if not ok then return end 3 | 4 | local vim = vim 5 | local fn, fs = vim.fn, vim.fs 6 | local mason_registry_get_package = require("mason-registry").get_package 7 | 8 | local jdtls_path = mason_registry_get_package("jdtls"):get_install_path() 9 | 10 | local jar_path = fn.glob(jdtls_path .. "/plugins/org.eclipse.equinox.launcher_*.jar", true, true)[1] 11 | if not jar_path then 12 | require("utils.notify").error("JDTLS not found") 13 | return 14 | end 15 | 16 | local jdebug_path = mason_registry_get_package("java-debug-adapter"):get_install_path() 17 | local jtest_path = mason_registry_get_package("java-test"):get_install_path() 18 | 19 | local uname = (vim.uv or vim.loop).os_uname().sysname 20 | uname = uname == "Linux" and "linux" or uname == "Darwin" and "mac" or "win" 21 | 22 | local root_dir = fs.root(0, { ".git", "pom.xml", "build.gradle" }) 23 | if not root_dir then return end 24 | 25 | local project_name = fs.basename(root_dir) 26 | 27 | local workspace_dir = fn.stdpath("cache") .. "/site/java/workspace-root/" .. project_name 28 | if fn.isdirectory(workspace_dir) == 0 then fn.mkdir(workspace_dir, "p") end 29 | 30 | local function find_java() 31 | local java_priority_paths = { 32 | "/usr/lib/jvm/java-17-openjdk/bin/java", 33 | "/usr/lib/jvm/java-11-openjdk/bin/java", 34 | "/usr/lib/jvm/java-8-openjdk/bin/java", 35 | } 36 | for i, path in ipairs(java_priority_paths) do 37 | if fn.filereadable(path) == 1 then return path, { 38 | name = i, 39 | path = path, 40 | } end 41 | end 42 | local java = fn.exepath("java") 43 | if java ~= "" then return java, { 44 | name = 1, 45 | path = java, 46 | } end 47 | return nil, nil 48 | end 49 | 50 | local java_path, runtime_paths = find_java() 51 | if not java_path then 52 | require("utils.notify").error("Java not found") 53 | return 54 | end 55 | 56 | local extendedClientCapabilities = jdtls.extendedClientCapabilities 57 | extendedClientCapabilities.resolveAdditionalTextEditsSupport = true 58 | 59 | local bundles = {} 60 | if jdebug_path ~= "" then 61 | vim.list_extend( 62 | bundles, 63 | fn.glob(jdebug_path .. "/extension/server/com.microsoft.java.debug.plugin-*.jar", true, true) 64 | ) 65 | end 66 | if jtest_path ~= "" then vim.list_extend(bundles, fn.glob(jtest_path .. "/extension/server/*.jar", true, true)) end 67 | 68 | local config = { 69 | cmd = { 70 | java_path, 71 | "-Declipse.application=org.eclipse.jdt.ls.core.id1", 72 | "-Dosgi.bundles.defaultStartLevel=4", 73 | "-Declipse.product=org.eclipse.jdt.ls.core.product", 74 | "-Dlog.protocol=true", 75 | "-Dlog.level=ALL", 76 | "-javaagent:" .. jdtls_path .. "/lombok.jar", 77 | "-Xmx1g", 78 | "--add-modules=ALL-SYSTEM", 79 | "--add-opens", 80 | "java.base/java.util=ALL-UNNAMED", 81 | "--add-opens", 82 | "java.base/java.lang=ALL-UNNAMED", 83 | "-jar", 84 | jar_path, 85 | "-configuration", 86 | jdtls_path .. "/config_" .. uname, 87 | "-data", 88 | workspace_dir, 89 | }, 90 | capabilities = require("config.lsp.default").capabilities, 91 | on_attach = function(client, bufnr) 92 | jdtls.setup_dap { hotcodereplace = "auto" } 93 | require("jdtls.dap").setup_dap_main_class_configs() 94 | 95 | require("jdtls.setup").add_commands() 96 | require("config.lsp.default").on_attach(client, bufnr) 97 | end, 98 | root_dir = root_dir, 99 | init_options = { -- dap 100 | extendedClientCapabilities = extendedClientCapabilities, 101 | bundles = bundles, 102 | }, 103 | settings = { 104 | java = { 105 | eclipse = { 106 | downloadSources = true, 107 | }, 108 | maven = { 109 | downloadSources = true, 110 | }, 111 | implementationsCodeLens = { 112 | enabled = true, 113 | }, 114 | referencesCodeLens = { 115 | enabled = true, 116 | }, 117 | references = { 118 | includeDecompiledSources = true, 119 | }, 120 | signatureHelp = { 121 | enabled = true, 122 | }, 123 | contentProvider = { 124 | preferred = "fernflower", 125 | }, 126 | format = { 127 | enabled = true, 128 | settings = { 129 | url = fn.stdpath("config") .. "/lang-servers/intellij-java-google-style.xml", 130 | profile = "GoogleStyle", 131 | }, 132 | }, 133 | completion = { 134 | favoriteStaticMembers = { 135 | "org.hamcrest.MatcherAssert.assertThat", 136 | "org.hamcrest.Matchers.*", 137 | "org.hamcrest.CoreMatchers.*", 138 | "org.junit.jupiter.api.Assertions.*", 139 | "java.util.Objects.requireNonNull", 140 | "java.util.Objects.requireNonNullElse", 141 | "org.mockito.Mockito.*", 142 | }, 143 | filteredTypes = { 144 | "com.sun.*", 145 | "io.micrometer.shaded.*", 146 | "java.awt.*", 147 | "jdk.*", 148 | "sun.*", 149 | }, 150 | importOrder = { 151 | "java", 152 | "javax", 153 | "com", 154 | "org", 155 | }, 156 | }, 157 | sources = { 158 | organizeImports = { 159 | starThreshold = 9999, 160 | staticStarThreshold = 9999, 161 | }, 162 | }, 163 | codeGeneration = { 164 | toString = { 165 | template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}", 166 | }, 167 | hashCodeEquals = { 168 | useJava7Objects = true, 169 | }, 170 | useBlocks = true, 171 | }, 172 | configuration = { 173 | runtimes = runtime_paths, 174 | -- runtimes = { 175 | -- -- { 176 | -- -- name = "JavaSE-11", 177 | -- -- path = "/usr/lib/jvm/java-11-openjdk/", 178 | -- -- }, 179 | -- { 180 | -- name = "JavaSE-17", 181 | -- path = "/usr/lib/jvm/java-17-openjdk/", 182 | -- }, 183 | -- }, 184 | }, 185 | }, 186 | flags = { 187 | debounce_text_changes = 150, 188 | allow_incremental_sync = true, 189 | }, 190 | }, 191 | } 192 | 193 | jdtls.start_or_attach(config) 194 | -------------------------------------------------------------------------------- /ftplugin/rust.lua: -------------------------------------------------------------------------------- 1 | -- https://github.com/mrcjkb/rustaceanvim/blob/master/lua/rustaceanvim/config/internal.lua 2 | -- 3 | local executors = require("rustaceanvim.executors") 4 | vim.g.rustaceanvim = { 5 | -- Plugin configuration 6 | -- tools = {}, 7 | -- 8 | -- LSP configuration 9 | server = { 10 | on_attach = function(client, bufnr) 11 | require("config.lsp.default").on_attach(client, bufnr) 12 | -- you can also put keymaps in here 13 | end, 14 | -- default_settings = { 15 | -- -- rust-analyzer language server configuration 16 | -- ["rust-analyzer"] = {}, 17 | -- }, 18 | }, 19 | 20 | tools = { 21 | --- how to execute terminal commands 22 | --- options right now: termopen / quickfix / toggleterm / vimux 23 | executor = executors.toggleterm, 24 | hover_actions = { 25 | --- whether to replace Neovim's built-in `vim.lsp.buf.hover`. 26 | ---@type boolean 27 | replace_builtin_hover = false, 28 | }, 29 | }, 30 | -- DAP configuration 31 | -- dap = {}, 32 | } 33 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | local require = require 2 | 3 | -- core module 4 | require("core.option") 5 | require("core.autocmd") 6 | require("core.nvimmap") 7 | require("core.plugmap") 8 | 9 | -- Install lazy neovim if not installed 10 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 11 | 12 | if not vim.loop.fs_stat(lazypath) then 13 | require("core.bootstrap").lazy(lazypath) 14 | else 15 | require("core.bootstrap").boot(lazypath) 16 | end 17 | -------------------------------------------------------------------------------- /lua/config/buffer-closer.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | min_remaining_buffers = 2, -- can not be less than 1 3 | retirement_minutes = 5, -- can not be less than 1 4 | 5 | -- close the buffer when the given events are triggered (see :h autocmd-events) 6 | -- if the value is "default", the plugin will use the default events 7 | -- if the value is "disabled", the plugin will not use any events 8 | -- if the value is a table, the plugin will use the given events 9 | events = "default", -- (table, "default", "disabled"): 10 | 11 | timed_check = { 12 | enabled = false, 13 | interval_minutes = 1, -- can not be less than 1 14 | }, 15 | 16 | excluded = { 17 | filetypes = { "lazy", "NvimTree", "mason" }, 18 | buftypes = { "terminal", "nofile", "quickfix", "prompt", "help" }, 19 | filenames = {}, 20 | }, 21 | 22 | -- it means that a buffer will not be closed if it is opened in a window 23 | ignore_working_windows = true, 24 | } 25 | 26 | return options 27 | -------------------------------------------------------------------------------- /lua/config/bufferline.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | 3 | local options = { 4 | options = { 5 | -- set to "tabs" to only show tabpages instead 6 | mode = "buffers", 7 | -- | "ordinal" | "buffer_id" | "both" | function({ ordinal, id, lower, raise }): string, 8 | numbers = "none", 9 | close_command = "bdelete %d", 10 | right_mouse_command = function(bufnr) 11 | vim.api.nvim_command("vsplit") 12 | vim.api.nvim_command("buffer " .. bufnr) 13 | end, 14 | left_mouse_command = "buffer %d", 15 | middle_mouse_command = "bdelete %d", 16 | indicator = { 17 | -- icon = "▍", 18 | icon = " ", 19 | style = "icon", 20 | }, 21 | icon_close_tab = "", 22 | icon_close_tab_modified = "●", 23 | icon_pinned = "車", 24 | close_icon = "", 25 | buffer_close_icon = "", 26 | modified_icon = "● ", 27 | left_trunc_marker = "", 28 | right_trunc_marker = "", 29 | truncate_names = true, -- whether or not tab names should be truncated 30 | max_name_length = 30, 31 | max_prefix_length = 13, 32 | tab_size = 23, 33 | diagnostics = "nvim_lsp", 34 | diagnostics_update_in_insert = true, 35 | -- The diagnostics indicator can be set to nil to keep the buffer name highlight but delete the highlighting 36 | -- diagnostics_indicator = function(count, level, diagnostics_dict, context) 37 | -- if context.buffer:current() then 38 | -- return '' 39 | -- end 40 | -- return '' 41 | -- end, 42 | diagnostics_indicator = function(count) return "(" .. count .. ")" end, 43 | offsets = { 44 | { 45 | filetype = "NvimTree", 46 | -- text = "File Explorer", 47 | text = "", 48 | text_align = "center", --"left" | "center" | "right", 49 | padding = 1, 50 | -- highlight = "Normal", 51 | highlight = "TabLine", 52 | separator = false, 53 | }, 54 | }, 55 | show_buffer_icons = true, 56 | show_buffer_close_icons = true, 57 | show_close_icon = false, 58 | show_tab_indicators = true, 59 | persist_buffer_sort = true, -- whether or not custom sorted buffers should persist 60 | -- separator_style = "thin", -- | "thick" | "thin" | { 'any', 'any' }, 61 | separator_style = { "│", "│" }, -- | "thick" | "thin" | { 'any', 'any' }, 62 | show_current_context = true, 63 | enforce_regular_tabs = true, 64 | always_show_bufferline = true, 65 | hover = { 66 | enabled = true, 67 | delay = 0, 68 | reveal = { "close" }, 69 | }, 70 | sort_by = "insert_after_current", 71 | }, 72 | highlights = { 73 | fill = { 74 | fg = { attribute = "fg", highlight = "TabLine" }, 75 | bg = { attribute = "bg", highlight = "TabLine" }, 76 | }, 77 | background = { 78 | fg = colors.gray, 79 | -- fg = { attribute = "fg", highlight = "TabLine" }, 80 | bg = { attribute = "bg", highlight = "TabLine" }, 81 | }, 82 | buffer_visible = { 83 | fg = { attribute = "fg", highlight = "TabLine" }, 84 | bg = { attribute = "bg", highlight = "TabLine" }, 85 | }, 86 | buffer_selected = { 87 | fg = { attribute = "fg", highlight = "Normal" }, 88 | bg = { attribute = "bg", highlight = "Normal" }, 89 | bold = true, 90 | italic = true, 91 | }, 92 | close_button = { 93 | fg = { attribute = "fg", highlight = "TabLine" }, 94 | bg = { attribute = "bg", highlight = "TabLine" }, 95 | }, 96 | close_button_visible = { 97 | fg = { attribute = "fg", highlight = "TabLine" }, 98 | bg = { attribute = "bg", highlight = "TabLine" }, 99 | }, 100 | close_button_selected = { 101 | fg = { attribute = "fg", highlight = "Normal" }, 102 | bg = { attribute = "bg", highlight = "Normal" }, 103 | }, 104 | tab = { 105 | fg = { attribute = "fg", highlight = "TabLine" }, 106 | bg = { attribute = "bg", highlight = "TabLine" }, 107 | }, 108 | tab_close = { 109 | fg = { attribute = "fg", highlight = "LspDiagnosticsDefaultError" }, 110 | bg = { attribute = "bg", highlight = "Normal" }, 111 | }, 112 | tab_selected = { 113 | fg = { attribute = "fg", highlight = "TabLine" }, 114 | bg = { attribute = "bg", highlight = "TabLine" }, 115 | }, 116 | duplicate_selected = { 117 | fg = { attribute = "fg", highlight = "TabLine" }, 118 | bg = { attribute = "bg", highlight = "TabLine" }, 119 | bold = true, 120 | italic = true, 121 | }, 122 | duplicate_visible = { 123 | fg = { attribute = "fg", highlight = "TabLine" }, 124 | bg = { attribute = "bg", highlight = "TabLine" }, 125 | bold = true, 126 | italic = true, 127 | }, 128 | duplicate = { 129 | fg = { attribute = "fg", highlight = "TabLine" }, 130 | bg = { attribute = "bg", highlight = "TabLine" }, 131 | bold = true, 132 | italic = true, 133 | }, 134 | modified = { 135 | fg = { attribute = "fg", highlight = "TabLine" }, 136 | bg = { attribute = "bg", highlight = "TabLine" }, 137 | }, 138 | modified_selected = { 139 | fg = { attribute = "fg", highlight = "Normal" }, 140 | bg = { attribute = "bg", highlight = "Normal" }, 141 | }, 142 | modified_visible = { 143 | fg = { attribute = "fg", highlight = "TabLine" }, 144 | bg = { attribute = "bg", highlight = "TabLine" }, 145 | }, 146 | separator = { 147 | fg = { attribute = "fg", highlight = "TabLine" }, 148 | bg = { attribute = "bg", highlight = "TabLine" }, 149 | }, 150 | separator_selected = { 151 | fg = { attribute = "fg", highlight = "TabLine" }, 152 | bg = { attribute = "bg", highlight = "TabLine" }, 153 | }, 154 | separator_visible = { 155 | fg = { attribute = "fg", highlight = "TabLine" }, 156 | bg = { attribute = "bg", highlight = "TabLine" }, 157 | }, 158 | indicator_selected = { 159 | fg = { attribute = "fg", highlight = "LspDiagnosticsDefaultHint" }, 160 | bg = { attribute = "bg", highlight = "Normal" }, 161 | }, 162 | numbers = { 163 | fg = { attribute = "fg", highlight = "TabLine" }, 164 | bg = { attribute = "bg", highlight = "TabLine" }, 165 | }, 166 | numbers_visible = { 167 | fg = { attribute = "fg", highlight = "TabLine" }, 168 | bg = { attribute = "bg", highlight = "TabLine" }, 169 | }, 170 | 171 | numbers_selected = { 172 | fg = { attribute = "fg", highlight = "Normal" }, 173 | bg = { attribute = "bg", highlight = "Normal" }, 174 | bold = true, 175 | italic = true, 176 | }, 177 | diagnostic = { 178 | fg = { attribute = "fg", highlight = "TabLine" }, 179 | bg = { attribute = "bg", highlight = "TabLine" }, 180 | }, 181 | diagnostic_visible = { 182 | fg = { attribute = "fg", highlight = "TabLine" }, 183 | bg = { attribute = "bg", highlight = "TabLine" }, 184 | }, 185 | diagnostic_selected = { 186 | fg = { attribute = "fg", highlight = "Normal" }, 187 | bg = { attribute = "bg", highlight = "Normal" }, 188 | bold = true, 189 | italic = true, 190 | }, 191 | hint = { 192 | fg = { attribute = "fg", highlight = "TabLine" }, 193 | bg = { attribute = "bg", highlight = "TabLine" }, 194 | }, 195 | hint_visible = { 196 | fg = { attribute = "fg", highlight = "TabLine" }, 197 | bg = { attribute = "bg", highlight = "TabLine" }, 198 | }, 199 | hint_selected = { 200 | fg = colors.cyan, 201 | bg = { attribute = "bg", highlight = "Normal" }, 202 | bold = true, 203 | italic = true, 204 | }, 205 | hint_diagnostic = { 206 | fg = colors.cyan, 207 | bg = { attribute = "bg", highlight = "TabLine" }, 208 | }, 209 | hint_diagnostic_visible = { 210 | fg = colors.cyan, 211 | bg = { attribute = "bg", highlight = "TabLine" }, 212 | }, 213 | hint_diagnostic_selected = { 214 | fg = colors.cyan, 215 | bg = { attribute = "bg", highlight = "Normal" }, 216 | bold = true, 217 | italic = true, 218 | }, 219 | info = { 220 | fg = { attribute = "fg", highlight = "TabLine" }, 221 | bg = { attribute = "bg", highlight = "TabLine" }, 222 | }, 223 | info_visible = { 224 | fg = { attribute = "fg", highlight = "TabLine" }, 225 | bg = { attribute = "bg", highlight = "TabLine" }, 226 | }, 227 | info_selected = { 228 | fg = colors.blue, 229 | bg = { attribute = "bg", highlight = "Normal" }, 230 | bold = true, 231 | italic = true, 232 | }, 233 | info_diagnostic = { 234 | fg = colors.blue, 235 | bg = { attribute = "bg", highlight = "TabLine" }, 236 | }, 237 | info_diagnostic_visible = { 238 | fg = colors.blue, 239 | bg = { attribute = "bg", highlight = "TabLine" }, 240 | }, 241 | info_diagnostic_selected = { 242 | fg = colors.blue, 243 | bg = { attribute = "bg", highlight = "Normal" }, 244 | bold = true, 245 | italic = true, 246 | }, 247 | warning = { 248 | fg = { attribute = "fg", highlight = "TabLine" }, 249 | bg = { attribute = "bg", highlight = "TabLine" }, 250 | }, 251 | warning_visible = { 252 | fg = { attribute = "fg", highlight = "TabLine" }, 253 | bg = { attribute = "bg", highlight = "TabLine" }, 254 | }, 255 | warning_selected = { 256 | fg = colors.yellow, 257 | bg = { attribute = "bg", highlight = "Normal" }, 258 | bold = true, 259 | italic = true, 260 | }, 261 | warning_diagnostic = { 262 | fg = colors.yellow, 263 | bg = { attribute = "bg", highlight = "TabLine" }, 264 | }, 265 | warning_diagnostic_visible = { 266 | fg = colors.yellow, 267 | bg = { attribute = "bg", highlight = "TabLine" }, 268 | }, 269 | warning_diagnostic_selected = { 270 | fg = colors.yellow, 271 | bg = { attribute = "bg", highlight = "Normal" }, 272 | bold = true, 273 | italic = true, 274 | }, 275 | error = { 276 | fg = { attribute = "fg", highlight = "TabLine" }, 277 | bg = { attribute = "bg", highlight = "TabLine" }, 278 | }, 279 | error_visible = { 280 | fg = { attribute = "fg", highlight = "TabLine" }, 281 | bg = { attribute = "bg", highlight = "TabLine" }, 282 | }, 283 | error_selected = { 284 | fg = colors.red, 285 | bg = { attribute = "bg", highlight = "Normal" }, 286 | bold = true, 287 | italic = true, 288 | }, 289 | error_diagnostic = { 290 | fg = colors.red, 291 | bg = { attribute = "bg", highlight = "TabLine" }, 292 | }, 293 | error_diagnostic_visible = { 294 | fg = colors.red, 295 | bg = { attribute = "bg", highlight = "TabLine" }, 296 | }, 297 | error_diagnostic_selected = { 298 | fg = colors.red, 299 | bg = { attribute = "bg", highlight = "Normal" }, 300 | bold = true, 301 | italic = true, 302 | }, 303 | pick = { 304 | fg = { attribute = "fg", highlight = "TabLine" }, 305 | bg = { attribute = "bg", highlight = "TabLine" }, 306 | bold = true, 307 | italic = true, 308 | }, 309 | pick_selected = { 310 | fg = { attribute = "fg", highlight = "Normal" }, 311 | bg = { attribute = "bg", highlight = "Normal" }, 312 | bold = true, 313 | italic = true, 314 | }, 315 | pick_visible = { 316 | fg = { attribute = "fg", highlight = "TabLine" }, 317 | bg = { attribute = "bg", highlight = "TabLine" }, 318 | bold = true, 319 | italic = true, 320 | }, 321 | trunc_marker = { 322 | fg = colors.violet, 323 | bg = { attribute = "bg", highlight = "Normal" }, 324 | bold = true, 325 | }, 326 | }, 327 | } 328 | 329 | return options 330 | -------------------------------------------------------------------------------- /lua/config/cmp/LuaSnip.lua: -------------------------------------------------------------------------------- 1 | local opts = { 2 | history = true, 3 | updateevents = "TextChanged,TextChangedI", 4 | } 5 | 6 | require("luasnip").config.set_config(opts) 7 | 8 | -- vscode format 9 | require("luasnip.loaders.from_vscode").lazy_load() 10 | require("luasnip.loaders.from_vscode").lazy_load { paths = vim.g.vscode_snippets_path or "" } 11 | 12 | -- snipmate format 13 | require("luasnip.loaders.from_snipmate").load() 14 | require("luasnip.loaders.from_snipmate").lazy_load { paths = vim.g.snipmate_snippets_path or "" } 15 | 16 | -- lua format 17 | require("luasnip.loaders.from_lua").load() 18 | require("luasnip.loaders.from_lua").lazy_load { paths = vim.g.lua_snippets_path or "" } 19 | 20 | vim.api.nvim_create_autocmd("InsertLeave", { 21 | callback = function() 22 | if 23 | require("luasnip").session.current_nodes[vim.api.nvim_get_current_buf()] 24 | and not require("luasnip").session.jump_active 25 | then 26 | require("luasnip").unlink_current() 27 | end 28 | end, 29 | }) 30 | -------------------------------------------------------------------------------- /lua/config/cmp/init.lua: -------------------------------------------------------------------------------- 1 | local cmp_status_ok, cmp = pcall(require, "cmp") 2 | if not cmp_status_ok then return end 3 | 4 | local snip_status_ok, luasnip = pcall(require, "luasnip") 5 | if not snip_status_ok then return end 6 | 7 | cmp.setup { 8 | snippet = { 9 | expand = function(args) 10 | luasnip.lsp_expand(args.body) -- For `luasnip` users. 11 | end, 12 | }, 13 | sources = { 14 | { name = "nvim_lsp" }, 15 | { name = "luasnip", keyword_length = 4 }, 16 | { name = "path", keyword_length = 3 }, 17 | { name = "buffer", keyword_length = 3 }, 18 | { name = "copilot", keyword_length = 3 }, 19 | { name = "emoji", keyword_length = 3 }, 20 | { name = "dotenv", keyword_length = 3 }, 21 | { name = "nvim_lua", keyword_length = 3 }, 22 | }, 23 | window = { 24 | documentation = cmp.config.window.bordered(), 25 | -- completion = cmp.config.window.bordered(), 26 | }, 27 | formatting = { 28 | fields = { "kind", "abbr", "menu" }, 29 | format = function(entry, vim_item) 30 | vim_item.kind = require("ui.icons.lspkind")[vim_item.kind] 31 | local color_item = require("nvim-highlight-colors").format(entry, { kind = vim_item.kind }) 32 | if color_item.abbr_hl_group then 33 | vim_item.kind_hl_group = color_item.abbr_hl_group 34 | vim_item.kind = color_item.abbr 35 | end 36 | vim_item.menu = ({ 37 | nvim_lsp = "λ ", 38 | luasnip = " ", 39 | buffer = "Ω ", 40 | path = "󱘎 ", 41 | nvim_lua = " ", 42 | copilot = " ", 43 | Copilot = " ", 44 | })[entry.source.name] 45 | return vim_item 46 | end, 47 | }, 48 | confirm_opts = { 49 | behavior = cmp.ConfirmBehavior.Selected, 50 | select = false, 51 | }, 52 | experimental = { 53 | ghost_text = false, 54 | native_menu = false, 55 | }, 56 | mapping = { 57 | [""] = cmp.mapping.complete(), 58 | [""] = cmp.mapping.select_prev_item(), 59 | [""] = cmp.mapping.select_next_item(), 60 | [""] = cmp.mapping.select_prev_item(), 61 | [""] = cmp.mapping.select_next_item(), 62 | [""] = cmp.mapping.scroll_docs(-4), 63 | [""] = cmp.mapping.scroll_docs(4), 64 | [""] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Insert, select = true }, 65 | [""] = cmp.mapping(function(fallback) 66 | if cmp.visible() then 67 | cmp.select_next_item() 68 | elseif luasnip.expand_or_jumpable() then 69 | luasnip.expand_or_jump() 70 | else 71 | fallback() 72 | end 73 | end, { "i", "s" }), 74 | [""] = cmp.mapping(function(fallback) 75 | if cmp.visible() then 76 | cmp.select_prev_item() 77 | elseif luasnip.jumpable(-1) then 78 | luasnip.jump(-1) 79 | else 80 | fallback() 81 | end 82 | end, { "i", "s" }), 83 | }, 84 | sorting = { 85 | priority_weight = 2, 86 | }, 87 | } 88 | -------------------------------------------------------------------------------- /lua/config/comment/Comment.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | padding = true, ---Add a space b/w comment and the line 3 | ignore = "^$", 4 | toggler = { 5 | line = "gcc", 6 | block = "gbc", 7 | }, 8 | opleader = { 9 | line = "gc", 10 | block = "gb", 11 | }, 12 | extra = { 13 | above = "gcO", 14 | below = "gco", 15 | eol = "gcA", 16 | }, 17 | mappings = { 18 | basic = true, 19 | extra = true, 20 | }, 21 | pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(), 22 | } 23 | 24 | return options 25 | -------------------------------------------------------------------------------- /lua/config/comment/todo-comments.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | -- show icons in the signs column 3 | signs = true, 4 | -- sign priority 5 | sign_priority = 8, 6 | -- keywords recognized as todo comments 7 | highlight = { 8 | before = "", -- "fg" or "bg" or empty 9 | keyword = "wide", -- "fg", "bg", "wide", "wide_bg", "wide_fg" or empty. (wide and wide_bg is the same as bg, but will also highlight surrounding characters, wide_fg acts accordingly but with fg) 10 | after = "fg", -- "fg" or "bg" or empty 11 | pattern = [[.*<(KEYWORDS)\s*:]], -- pattern or table of patterns, used for highlighting (vim regex) 12 | comments_only = true, -- uses treesitter to match keywords in comments only 13 | exclude = {}, -- list of file types to exclude highlighting 14 | }, 15 | } 16 | 17 | return options 18 | -------------------------------------------------------------------------------- /lua/config/conform.lua: -------------------------------------------------------------------------------- 1 | ---@param bufnr integer 2 | ---@param ... string 3 | ---@return string 4 | ---@diagnostic disable: unused-local 5 | ---@diagnostic disable-next-line: unused-function 6 | local function first(bufnr, ...) 7 | local conform = require("conform") 8 | for i = 1, select("#", ...) do 9 | local formatter = select(i, ...) 10 | if conform.get_formatter_info(formatter, bufnr).available then return formatter end 11 | end 12 | return select(1, ...) 13 | end 14 | 15 | local biome_prettier = { "biome", "prettierd", "prettier", stop_after_first = true } 16 | 17 | local prettier = { "prettierd", "prettier", stop_after_first = true } 18 | 19 | local slow_format_filetypes = {} 20 | 21 | local options = { 22 | formatters_by_ft = { 23 | lua = { "stylua" }, 24 | 25 | python = { "ruff_format", "autopep8", stop_after_first = true }, 26 | 27 | xml = { "xmlformat" }, 28 | 29 | go = { "goimports", "gofumpt" }, 30 | 31 | -- webdev 32 | javascript = biome_prettier, 33 | typescript = biome_prettier, 34 | javascriptreact = biome_prettier, 35 | typescriptreact = biome_prettier, 36 | json = biome_prettier, 37 | jsonc = biome_prettier, 38 | css = prettier, 39 | html = prettier, 40 | markdown = prettier, 41 | yaml = prettier, 42 | 43 | -- ["*"] = { "codespell" }, 44 | c = { "clang_format" }, 45 | cpp = { "clang_format" }, 46 | rust = { "rustfmt", "leptosfmt" }, 47 | zig = { "zigfmt" }, 48 | 49 | sh = { "shfmt", "shellcheck" }, 50 | 51 | toml = { "taplo" }, 52 | 53 | java = { "google-java-format" }, 54 | 55 | -- dart = { "dcm_format" }, 56 | }, 57 | 58 | default_format_opts = { 59 | lsp_format = "fallback", 60 | }, 61 | format_on_save = function(bufnr) 62 | if slow_format_filetypes[vim.bo[bufnr].filetype] then return end 63 | local function on_format(err) 64 | if err and err:match("timeout$") then slow_format_filetypes[vim.bo[bufnr].filetype] = true end 65 | end 66 | return { timeout_ms = 500, lsp_format = "fallback" }, on_format 67 | end, 68 | format_after_save = function(bufnr) 69 | if not slow_format_filetypes[vim.bo[bufnr].filetype] then return end 70 | return { lsp_format = "fallback" } 71 | end, 72 | } 73 | 74 | return options 75 | -------------------------------------------------------------------------------- /lua/config/copilot.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | panel = { 3 | enabled = true, 4 | auto_refresh = true, 5 | keymap = { 6 | jump_prev = "", 7 | jump_next = "", 8 | accept = "", 9 | refresh = "R", 10 | open = "", 11 | }, 12 | layout = { 13 | position = "right", -- | top | left | right 14 | ratio = 0.5, 15 | }, 16 | }, 17 | suggestion = { 18 | enabled = true, 19 | auto_trigger = true, 20 | debounce = 75, 21 | keymap = { 22 | accept = "", 23 | accept_word = false, 24 | accept_line = false, 25 | next = "", 26 | prev = "", 27 | dismiss = "", 28 | }, 29 | }, 30 | filetypes = { 31 | yaml = true, 32 | markdown = true, 33 | help = false, 34 | gitcommit = false, 35 | gitrebase = false, 36 | hgcommit = false, 37 | svn = false, 38 | cvs = false, 39 | sh = true, 40 | }, 41 | copilot_node_command = "node", -- Node.js version must be > 16.x 42 | server_opts_overrides = {}, 43 | } 44 | 45 | return options 46 | -------------------------------------------------------------------------------- /lua/config/dap/dap-virtual-text.lua: -------------------------------------------------------------------------------- 1 | local status_ok, nvim_dap_virtual_text = pcall(require, "nvim-dap-virtual-text") 2 | if not status_ok then return end 3 | 4 | nvim_dap_virtual_text.setup { 5 | enabled = true, -- enable this plugin (the default) 6 | enabled_commands = true, -- create commands DapVirtualTextEnable, DapVirtualTextDisable, DapVirtualTextToggle, (DapVirtualTextForceRefresh for refreshing when debug adapter did not notify its termination) 7 | highlight_changed_variables = true, -- highlight changed values with NvimDapVirtualTextChanged, else always NvimDapVirtualText 8 | highlight_new_as_changed = false, -- highlight new variables in the same way as changed variables (if highlight_changed_variables) 9 | show_stop_reason = true, -- show stop reason when stopped for exceptions 10 | commented = false, -- prefix virtual text with comment string 11 | only_first_definition = true, -- only show virtual text at first definition (if there are multiple) 12 | all_references = false, -- show virtual text on all all references of the variable (not only definitions) 13 | clear_on_continue = false, -- clear virtual text on "continue" (might cause flickering when stepping) 14 | display_callback = function(variable, buf, stackframe, node, options) 15 | if options.virt_text_pos == "inline" then 16 | return " = " .. variable.value 17 | else 18 | return variable.name .. " = " .. variable.value 19 | end 20 | end, 21 | -- position of virtual text, see `:h nvim_buf_set_extmark()`, default tries to inline the virtual text. Use 'eol' to set to end of line 22 | virt_text_pos = vim.fn.has("nvim-0.10") == 1 and "inline" or "eol", 23 | 24 | all_frames = false, -- show virtual text for all stack frames not only current. Only works for debugpy on my machine. 25 | virt_lines = false, -- show virtual lines instead of virtual text (will flicker!) 26 | virt_text_win_col = nil, -- position the virtual text at a fixed window column (starting from the first text column) , 27 | } 28 | -------------------------------------------------------------------------------- /lua/config/dap/dapui.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | icons = { 3 | expanded = "▾", 4 | collapsed = "▸", 5 | }, 6 | mappings = { 7 | -- Use a table to apply multiple mappings 8 | expand = { "", "<2-LeftMouse>" }, 9 | open = "o", 10 | remove = "d", 11 | edit = "e", 12 | repl = "r", 13 | toggle = "t", 14 | }, 15 | floating = { 16 | max_height = 0.8, 17 | max_width = 0.8, 18 | border = "single", -- "single", "double" or "rounded" 19 | mappings = { 20 | close = { "q", "" }, 21 | }, 22 | }, 23 | windows = { 24 | indent = 1, 25 | }, 26 | } 27 | 28 | return options 29 | -------------------------------------------------------------------------------- /lua/config/dap/init.lua: -------------------------------------------------------------------------------- 1 | local fn = vim.fn 2 | 3 | local dap = require("dap") 4 | 5 | local icons = require("ui.icons") 6 | 7 | fn.sign_define("DapBreakpoint", { 8 | text = icons.DapBreakpoint, 9 | numhl = "DapBreakpoint", 10 | texthl = "DapBreakpoint", 11 | }) 12 | 13 | fn.sign_define("DapStopped", { 14 | text = icons.DapStopped, 15 | numhl = "DapStopped", 16 | texthl = "DapStopped", 17 | }) 18 | 19 | local ok, dapui = pcall(require, "dapui") 20 | if ok then 21 | dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end 22 | dap.listeners.after.disconnect["dapui_config"] = function() 23 | require("dap.repl").close() 24 | dapui.close() 25 | end 26 | dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end 27 | dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end 28 | end 29 | 30 | local function get_bin_path(adapter_name, custom_path) 31 | return require("mason-registry").get_package(adapter_name):get_install_path() .. "/" .. (custom_path or adapter_name) 32 | end 33 | 34 | dap.adapters.codelldb = { 35 | type = "server", 36 | host = "127.0.0.1", 37 | port = 13000, 38 | executable = { 39 | -- CHANGE THIS to your path! 40 | command = get_bin_path("codelldb"), 41 | args = { "--port", 13000 }, 42 | }, 43 | } 44 | 45 | dap.configurations.cpp = { 46 | { 47 | name = "Launch file", 48 | type = "codelldb", 49 | request = "launch", 50 | program = function() return fn.input("path to executable: ", fn.getcwd() .. "/bin/program", "file") end, 51 | cwd = "${workspaceFolder}", 52 | stopOnEntry = false, 53 | args = {}, 54 | }, 55 | } 56 | dap.configurations.c = dap.configurations.cpp 57 | -------------------------------------------------------------------------------- /lua/config/flutter-tools.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | ui = { 3 | -- the border type to use for all floating windows, the same options/formats 4 | -- used for ":h nvim_open_win" e.g. "single" | "shadow" | {} 5 | border = "single", 6 | -- This determines whether notifications are show with `vim.notify` or with the plugin's custom UI 7 | -- please note that this option is eventually going to be deprecated and users will need to 8 | -- depend on plugins like `nvim-notify` instead. 9 | -- notification_style = "native" | "plugin", 10 | }, 11 | -- decorations = { 12 | -- statusline = { 13 | -- -- set to true to be able use the 'flutter_tools_decorations.app_version' in your statusline 14 | -- -- this will show the current version of the flutter app from the pubspec.yaml file 15 | -- app_version = false, 16 | -- -- set to true to be able use the 'flutter_tools_decorations.device' in your statusline 17 | -- -- this will show the currently running device if an application was started with a specific 18 | -- -- device 19 | -- device = false, 20 | -- -- set to true to be able use the 'flutter_tools_decorations.project_config' in your statusline 21 | -- -- this will show the currently selected project configuration 22 | -- project_config = false, 23 | -- }, 24 | -- }, 25 | -- debugger = { -- integrate with nvim dap + install dart code debugger 26 | -- enabled = false, 27 | -- run_via_dap = false, -- use dap instead of a plenary job to run flutter apps 28 | -- -- if empty dap will not stop on any exceptions, otherwise it will stop on those specified 29 | -- -- see |:help dap.set_exception_breakpoints()| for more info 30 | -- exception_breakpoints = {}, 31 | -- register_configurations = function(paths) 32 | -- -- require("dap").configurations.dart = { 33 | -- -- 34 | -- -- } 35 | -- end, 36 | -- }, 37 | -- flutter_path = "", -- <-- this takes priority over the lookup 38 | -- flutter_lookup_cmd = nil, -- example "dirname $(which flutter)" or "asdf where flutter" 39 | -- root_patterns = { ".git", "pubspec.yaml" }, -- patterns to find the root of your flutter project 40 | -- fvm = false, -- takes priority over path, uses /.fvm/flutter_sdk if enabled 41 | -- widget_guides = { 42 | -- enabled = false, 43 | -- }, 44 | -- closing_tags = { 45 | -- highlight = "ErrorMsg", -- highlight for the closing tag 46 | -- prefix = ">", -- character to use for close tag e.g. > Widget 47 | -- enabled = true, -- set to false to disable 48 | -- }, 49 | -- dev_log = { 50 | -- enabled = true, 51 | -- notify_errors = false, -- if there is an error whilst running then notify the user 52 | -- open_cmd = "tabedit", -- command to use to open the log buffer 53 | -- }, 54 | -- dev_tools = { 55 | -- autostart = false, -- autostart devtools server if not detected 56 | -- auto_open_browser = false, -- Automatically opens devtools in the browser 57 | -- }, 58 | -- outline = { 59 | -- open_cmd = "30vnew", -- command to use to open the outline buffer 60 | -- auto_open = false, -- if true this will open the outline automatically when it is first populated 61 | -- }, 62 | -- lsp = { 63 | -- color = { -- show the derived colours for dart variables 64 | -- enabled = false, -- whether or not to highlight color variables at all, only supported on flutter >= 2.10 65 | -- background = false, -- highlight the background 66 | -- background_color = nil, -- required, when background is transparent (i.e. background_color = { r = 19, g = 17, b = 24},) 67 | -- foreground = false, -- highlight the foreground 68 | -- virtual_text = true, -- show the highlight using virtual text 69 | -- virtual_text_str = "■", -- the virtual text character to highlight 70 | -- }, 71 | -- -- on_attach = my_custom_on_attach, 72 | -- -- capabilities = my_custom_capabilities -- e.g. lsp_status capabilities 73 | -- --- OR you can specify a function to deactivate or change or control how the config is created 74 | -- capabilities = function(config) 75 | -- config.specificThingIDontWant = false 76 | -- return config 77 | -- end, 78 | -- -- see the link below for details on each option: 79 | -- -- https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md#client-workspace-configuration 80 | -- settings = { 81 | -- showTodos = true, 82 | -- completeFunctionCalls = true, 83 | -- analysisExcludedFolders = { "" }, 84 | -- renameFilesWithClasses = "prompt", -- "always" 85 | -- enableSnippets = true, 86 | -- updateImportsOnRename = true, -- Whether to update imports and other directives when files are renamed. Required for `FlutterRename` command. 87 | -- }, 88 | -- }, 89 | } 90 | 91 | return options 92 | -------------------------------------------------------------------------------- /lua/config/git/git-conflict.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | default_mappings = { 3 | ours = "o", 4 | theirs = "t", 5 | none = "0", 6 | both = "b", 7 | next = "]c", 8 | prev = "[c", 9 | }, 10 | default_commands = true, -- disable commands created by this plugin 11 | disable_diagnostics = true, -- This will disable the diagnostics in a buffer whilst it is conflicted 12 | highlights = { 13 | -- They must have background color, otherwise the default color will be used 14 | incoming = "DiffText", 15 | current = "DiffAdd", 16 | }, 17 | } 18 | 19 | return options 20 | -------------------------------------------------------------------------------- /lua/config/git/gitsigns.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | signs = { 3 | add = { text = "+" }, 4 | change = { text = "│" }, 5 | delete = { text = "_" }, 6 | topdelete = { text = "‾" }, 7 | changedelete = { text = "~" }, 8 | untracked = { text = "┆" }, 9 | }, 10 | preview_config = { 11 | border = "single", -- Options passed to nvim_open_win 12 | style = "minimal", 13 | relative = "cursor", 14 | row = 0, 15 | col = 1, 16 | }, 17 | current_line_blame_opts = { 18 | virt_text = true, 19 | virt_text_pos = "right_align", -- 'eol' | 'overlay' | 'right_align' 20 | delay = 500, 21 | ignore_whitespace = false, 22 | }, 23 | current_line_blame = true, -- Toggle with `:Gitsigns toggle_current_line_blame` 24 | current_line_blame_formatter = ", - ", 25 | on_attach = require("core.plugmap").gitsigns, 26 | } 27 | 28 | return options 29 | -------------------------------------------------------------------------------- /lua/config/highlight-colors.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | render = "background", -- or 'foreground' or 'virtual' 3 | enable_tailwind = true, 4 | exclude_filetypes = {}, 5 | exclude_buftypes = { 6 | "nofile", 7 | }, 8 | } 9 | 10 | return options 11 | -------------------------------------------------------------------------------- /lua/config/indent-blankline.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | indent = { 3 | char = "│", 4 | }, 5 | scope = { 6 | show_start = false, 7 | }, 8 | exclude = { 9 | filetypes = { "alpha", "dashboard", "Trouble", "lazy", "NvimTree", "mason" }, 10 | }, 11 | } 12 | 13 | return options 14 | -------------------------------------------------------------------------------- /lua/config/lazy-nvim.lua: -------------------------------------------------------------------------------- 1 | return { 2 | defaults = { lazy = true }, 3 | ui = { 4 | -- a number <1 is a percentage., >1 is a fixed size 5 | size = { width = 0.8, height = 0.8 }, 6 | -- wrap the lines in the ui 7 | wrap = true, 8 | -- Accepts same border values as |nvim_open_win()|. 9 | border = "single", 10 | -- If you want to use a specific browser, you can define it here 11 | browser = nil, ---@type string? 12 | }, 13 | performance = { 14 | rtp = { 15 | disabled_plugins = { 16 | "2html_plugin", 17 | "tohtml", 18 | "getscript", 19 | "getscriptPlugin", 20 | "gzip", 21 | "logipat", 22 | "netrw", 23 | "netrwPlugin", 24 | "netrwSettings", 25 | "netrwFileHandlers", 26 | "matchit", 27 | "tar", 28 | "tarPlugin", 29 | "rrhelper", 30 | "spellfile_plugin", 31 | "vimball", 32 | "vimballPlugin", 33 | "zip", 34 | "zipPlugin", 35 | "tutor", 36 | "rplugin", 37 | "syntax", 38 | "synmenu", 39 | "optwin", 40 | "compiler", 41 | "bugreport", 42 | "ftplugin", 43 | }, 44 | }, 45 | }, 46 | } 47 | -------------------------------------------------------------------------------- /lua/config/lsp/default.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local lsp = vim.lsp 4 | local handlers = lsp.handlers 5 | 6 | local signs_hl = { 7 | "DiagnosticSignError", 8 | "DiagnosticSignWarn", 9 | "DiagnosticSignHint", 10 | "DiagnosticSignInfo", 11 | } 12 | 13 | vim.diagnostic.config { 14 | signs = { 15 | text = require("ui.icons").DiagnosticSign, 16 | numhl = signs_hl, 17 | texthl = signs_hl, 18 | }, 19 | underline = true, 20 | severity_sort = true, 21 | update_in_insert = true, 22 | virtual_text = false, 23 | float = { 24 | source = "if_many", 25 | }, 26 | } 27 | 28 | handlers["textDocument/signatureHelp"] = lsp.with(handlers.signature_help, { 29 | border = "single", 30 | focusable = false, 31 | relative = "cursor", 32 | }) 33 | 34 | handlers["textDocument/hover"] = lsp.with(handlers.hover, { 35 | border = "single", 36 | }) 37 | 38 | local capabilities = lsp.protocol.make_client_capabilities() 39 | or require("lspconfig").util.default_config.capabilities 40 | or require("cmp_nvim_lsp").default_capabilities() 41 | 42 | capabilities.textDocument.completion.completionItem = { 43 | snippetSupport = true, 44 | preselectSupport = true, 45 | insertReplaceSupport = true, 46 | labelDetailsSupport = true, 47 | deprecatedSupport = true, 48 | commitCharactersSupport = true, 49 | documentationFormat = { 50 | "markdown", 51 | "plaintext", 52 | }, 53 | tagSupport = { 54 | valueSet = { 1 }, 55 | }, 56 | resolveSupport = { 57 | properties = { 58 | "documentation", 59 | "detail", 60 | "additionalTextEdits", 61 | }, 62 | }, 63 | } 64 | 65 | -- for nvim-ufo 66 | capabilities.textDocument.foldingRange = { 67 | dynamicRegistration = false, 68 | lineFoldingOnly = true, 69 | } 70 | 71 | M.on_attach = function(client, bufnr) 72 | require("better-diagnostic-virtual-text").setup_buf(bufnr, nil) 73 | -- Other client setup 74 | end 75 | M.capabilities = capabilities 76 | 77 | return M 78 | -------------------------------------------------------------------------------- /lua/config/lsp/lspconfig.lua: -------------------------------------------------------------------------------- 1 | local lspconfig = require("lspconfig") 2 | local on_attach = require("config.lsp.default").on_attach 3 | local capabilities = require("config.lsp.default").capabilities 4 | 5 | local lsp_servers = { 6 | 7 | -- python 8 | { 9 | name = "pyright", 10 | }, 11 | 12 | -- bash 13 | { 14 | name = "bashls", 15 | }, 16 | 17 | -- cpp 18 | { 19 | name = "clangd", 20 | }, 21 | { 22 | name = "cmake", 23 | }, 24 | 25 | -- dev 26 | { 27 | name = "cssls", 28 | }, 29 | { 30 | name = "eslint", 31 | }, 32 | { 33 | name = "html", 34 | }, 35 | { 36 | name = "jsonls", 37 | }, 38 | { 39 | name = "tailwindcss", 40 | }, 41 | { 42 | name = "tsserver", 43 | }, 44 | { 45 | name = "emmet_ls", 46 | config = { 47 | filetypes = { 48 | "html", 49 | "css", 50 | "sass", 51 | "scss", 52 | "less", 53 | "javascript", 54 | "typescript", 55 | "jsx", 56 | "tsx", 57 | "typescriptreact", 58 | "javascriptreact", 59 | "vue", 60 | "vue-html", 61 | }, 62 | }, 63 | }, 64 | 65 | -- lua 66 | { 67 | name = "lua_ls", 68 | config = { 69 | settings = { 70 | Lua = { 71 | diagnostics = { 72 | globals = { "vim" }, 73 | }, 74 | workspace = { 75 | library = { 76 | [vim.fn.expand("$VIMRUNTIME/lua")] = true, 77 | [vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true, 78 | [vim.fn.stdpath("data") .. "/lazy/lazy.nvim/lua/lazy"] = true, 79 | }, 80 | maxPreload = 100000, 81 | preloadFileSize = 10000, 82 | }, 83 | }, 84 | }, 85 | }, 86 | }, 87 | } 88 | 89 | for _, server in ipairs(lsp_servers) do 90 | local config = server.config or {} 91 | config.on_attach = config.on_attach or on_attach 92 | config.capabilities = config.capabilities or capabilities 93 | lspconfig[server.name].setup(config) 94 | end 95 | -------------------------------------------------------------------------------- /lua/config/lsp/lspsaga.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | rename = { 3 | -- https://nvimdev.github.io/lspsaga/rename/ 4 | -- 5 | -- Default is true. Whether the name is selected when the float opens 6 | -- In some situation, just like want to change one or less characters, in_select is not so useful. You can tell the Lspsaga to start in normal mode using an extra argument like :Lspsaga lsp_rename mode=n 7 | -- in_select = true 8 | -- 9 | -- Auto save file when the rename is done 10 | -- auto_save = false 11 | -- 12 | -- Width for the project_replace float window 13 | -- project_max_width = 0.5 14 | -- 15 | -- Height for the project_replace float window 16 | -- project_max_height = 0.5 17 | keys = { 18 | quit = { "", "", "" }, 19 | }, 20 | }, 21 | scroll_preview = { 22 | scroll_down = "", 23 | scroll_up = "", 24 | }, 25 | finder = { 26 | -- https://nvimdev.github.io/lspsaga/finder/ 27 | max_height = 0.5, 28 | left_width = 0.4, 29 | right_width = 0.4, 30 | keys = { 31 | toggle_or_open = "o", 32 | vsplit = "", 33 | split = "", 34 | -- tabe = "t", 35 | -- tabnew = "r", 36 | quit = { "q", "" }, 37 | }, 38 | }, 39 | definition = { 40 | -- https://nvimdev.github.io/lspsaga/definition/ 41 | width = 0.85, -- defines float window width 42 | height = 0.6, -- defines float window height 43 | keys = { 44 | edit = "o", 45 | vsplit = "", 46 | split = "", 47 | quit = { "q", "" }, 48 | }, 49 | }, 50 | code_action = { 51 | -- https://nvimdev.github.io/lspsaga/codeaction/ 52 | -- whether number shortcut for code actions are enabled 53 | -- num_shortcut = true, 54 | -- 55 | show_server_name = true, 56 | extend_gitsigns = true, 57 | keys = { 58 | quit = { "q", "" }, 59 | exec = { "", "o" }, 60 | }, 61 | }, 62 | lightbulb = { 63 | enable = false, 64 | -- show sign in status column 65 | -- sign = true, 66 | -- 67 | -- show virtual text at the end of line 68 | -- virtual_text = true, 69 | -- 70 | -- timer debounce 71 | -- debounce = 10, 72 | -- 73 | -- sign_priority = 40, 74 | }, 75 | hover = { 76 | -- https://nvimdev.github.io/lspsaga/hover/ 77 | max_width = 0.9, 78 | max_height = 0.8, 79 | }, 80 | diagnostic = { 81 | -- https://nvimdev.github.io/lspsaga/diagnostic/ 82 | -- show_code_action = true,-- default 83 | -- jump_num_shortcut = true, -- default 84 | max_width = 0.7, 85 | max_height = 0.6, 86 | -- text_hl_follow = true, -- default 87 | -- border_follow = true, -- default 88 | -- extend_relatedInformation = false, -- default 89 | -- show_layout = 'float' -- default 90 | -- max_show_width = 0.9, 91 | -- max_show_height = 0.6, 92 | -- diagnostic_only_current = false -- default 93 | 94 | -- keys = { 95 | -- exec_action = "o", 96 | -- quit = "q", 97 | -- toggle_or_jump = "", 98 | -- quit_in_show = { "q", "" }, 99 | -- }, 100 | }, 101 | outline = { 102 | -- win_position = 'right' 103 | -- win_width = 30 104 | -- 105 | -- auto preview when cursor moved in outline window 106 | -- auto_preview = true 107 | -- 108 | -- detail = true 109 | -- 110 | -- auto close itself when outline window is last window 111 | -- auto_close = true 112 | -- 113 | -- close_after_jump = false -- close after jump 114 | -- 115 | -- layout = 'normal' -- float or normal 116 | -- 117 | -- max_height = 0.5 118 | -- left_width = 0.3 119 | -- 120 | -- keys = { 121 | -- toggle_or_jump = 'o' -- toggle or jump 122 | -- quit = 'q' -- quit outline window 123 | -- jump = 'e' -- jump to pos even on a expand/collapse node 124 | -- }, 125 | }, 126 | callhierarchy = { 127 | -- layout = 'float', -- normal or float 128 | keys = { 129 | edit = "o", --edit (open) file 130 | vsplit = "", -- vsplit 131 | split = "", -- split" 132 | quit = { "q", "" }, -- quit layout 133 | -- tabe = 't', open in new tab 134 | -- shuttle = '[w', shuttle bettween the layout left and right 135 | -- toggle_or_req = 'u', toggle or do request 136 | }, 137 | }, 138 | symbol_in_winbar = { 139 | enable = false, 140 | -- enable = true 141 | -- 142 | -- Separator symbol 143 | -- separator = "  ", 144 | -- 145 | -- When true some symbols like if and for will be ignored (need treesitter) 146 | -- hide_keyword = true, 147 | -- 148 | -- Show file name before symbols 149 | -- show_file = true 150 | -- 151 | -- Show how many folder layers before the file name 152 | -- folder_level = 2, 153 | -- 154 | -- true mean the symbol name and icon have same color. Otherwise, symbol name is light-white 155 | -- color_mode = true, 156 | -- 157 | -- Dynamic render delay 158 | -- delay = 300, 159 | }, 160 | beacon = { 161 | enable = true, 162 | frequency = 7, 163 | }, 164 | ui = { 165 | -- Border type, see :help nvim_open_win 166 | border = "single", 167 | -- 168 | -- Whether to use nvim-web-devicons 169 | -- devicon = true, 170 | -- 171 | -- Show title in some float window 172 | -- title = false, 173 | -- 174 | -- Expand icon 175 | -- expand = "", 176 | expand = "", 177 | -- Collapse icon 178 | collapse = "", 179 | -- Code action icon 180 | -- code_action = "💡", 181 | -- 182 | -- Action fix icon 183 | -- actionfix = ' ', 184 | -- 185 | -- Symbols used in virtual text connect 186 | -- lines = { '┗', '┣', '┃', '━', '┏' }, 187 | -- 188 | -- LSP kind custom table 189 | -- kind = {}, 190 | -- 191 | -- Implement icon 192 | -- imp_sign = '󰳛 ', 193 | }, 194 | } 195 | 196 | return options 197 | -------------------------------------------------------------------------------- /lua/config/lualine/components/copilot.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | local no_seps = require("configs.lualine.seps").no_seps 3 | 4 | return { 5 | function() return package.loaded["copilot_status"] and require("copilot_status").status_string() or "" end, 6 | cnd = function() return package.loaded["copilot_status"] and require("copilot_status").enabled() end, 7 | separator = no_seps, 8 | color = { bg = colors.lualine_bg, fg = colors.fg }, 9 | } 10 | -------------------------------------------------------------------------------- /lua/config/lualine/components/diagnostics.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | 3 | return { 4 | "diagnostics", 5 | sources = { "nvim_diagnostic" }, 6 | symbols = { 7 | error = " ", 8 | warn = " ", 9 | hint = "󰌵 ", 10 | info = " ", 11 | }, 12 | colored = true, 13 | diagnostics_color = { 14 | color_error = { fg = colors.red }, 15 | color_warn = { fg = colors.yellow }, 16 | color_info = { fg = colors.blue }, 17 | color_hint = { fg = colors.green }, 18 | }, 19 | always_visible = false, 20 | update_in_insert = true, 21 | } 22 | -------------------------------------------------------------------------------- /lua/config/lualine/components/encoding.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | local no_seps = require("configs.lualine.seps").no_seps 3 | 4 | -- https://www.nerdfonts.com/cheat-sheet 5 | local icons = { 6 | ["utf-8"] = "󰉿", 7 | ["utf-16"] = "", 8 | ["utf-32"] = "", 9 | ["utf-8mb4"] = "", 10 | ["utf-16le"] = "", 11 | ["utf-16be"] = "", 12 | } 13 | 14 | local encoding = function() 15 | local enc = vim.bo.fenc ~= "" and vim.bo.fenc or vim.o.enc 16 | return icons[enc] or enc 17 | end 18 | 19 | return { 20 | encoding, 21 | separator = no_seps, 22 | padding = 1, 23 | color = { bg = colors.yellow, fg = colors.black }, 24 | } 25 | -------------------------------------------------------------------------------- /lua/config/lualine/components/file.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | local no_seps = require("configs.lualine.seps").no_seps 3 | local M = {} 4 | 5 | M.type = { 6 | "filetype", 7 | icon_only = true, 8 | colored = true, 9 | padding = { left = 2, right = 1 }, 10 | color = { bg = colors.lualine_bg }, 11 | } 12 | 13 | M.name = { 14 | "filename", 15 | padding = { right = 2 }, 16 | separator = no_seps, 17 | color = { bg = colors.lualine_bg, fg = colors.orange, gui = "bold" }, 18 | file_status = true, 19 | newfile_status = false, 20 | path = 0, 21 | symbols = { 22 | modified = "●", 23 | readonly = " ", 24 | unnamed = "", 25 | newfile = " [New]", 26 | }, 27 | } 28 | 29 | return M 30 | -------------------------------------------------------------------------------- /lua/config/lualine/components/git.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | 3 | local M = {} 4 | 5 | M.branch = { 6 | "branch", 7 | icon = " ", 8 | color = { fg = colors.pink, bg = colors.lualine_bg }, 9 | padding = { left = 1, right = 1 }, 10 | } 11 | 12 | M.diff = { 13 | "diff", 14 | colored = true, 15 | diff_color = { 16 | added = "DiagnosticSignInfo", -- Changes the diff's added color 17 | modified = "DiagnosticSignWarn", -- Changes the diff's modified color 18 | removed = "DiagnosticSignError", -- Changes the diff's removed color you 19 | }, 20 | symbols = { added = " ", modified = " ", removed = " " }, 21 | color = { bg = colors.lualine_bg }, 22 | } 23 | 24 | return M 25 | -------------------------------------------------------------------------------- /lua/config/lualine/components/indent.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | local no_seps = require("configs.lualine.seps").no_seps 3 | 4 | local M = {} 5 | 6 | M.value = { 7 | function() 8 | if vim.o.columns > 70 then return "" .. vim.api.nvim_buf_get_option(0, "shiftwidth") end 9 | return "" 10 | end, 11 | padding = 1, 12 | separator = no_seps, 13 | color = { bg = colors.lualine_bg, fg = colors.fg }, 14 | } 15 | 16 | M.icon = { 17 | function() 18 | if vim.o.columns > 70 then return "Tab" .. "" end 19 | return "" 20 | end, 21 | 22 | padding = 1, 23 | separator = no_seps, 24 | color = { bg = colors.blue, fg = colors.black }, 25 | } 26 | 27 | return M 28 | -------------------------------------------------------------------------------- /lua/config/lualine/components/location.lua: -------------------------------------------------------------------------------- 1 | local no_seps = require("configs.lualine.seps").no_seps 2 | local colors = require("ui.colors") 3 | 4 | local M = {} 5 | M.value = { 6 | "location", 7 | padding = 1, 8 | separator = no_seps, 9 | color = { bg = colors.lualine_bg, fg = colors.fg }, 10 | } 11 | 12 | M.progress = { 13 | function() 14 | local current_line = vim.fn.line(".") 15 | local total_lines = vim.fn.line("$") 16 | local chars = { "_", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" } 17 | local line_ratio = current_line / total_lines 18 | local index = math.ceil(line_ratio * #chars) 19 | return chars[index] 20 | end, 21 | padding = 0, 22 | color = { bg = colors.lualine_bg, fg = colors.orange }, 23 | } 24 | 25 | return M 26 | -------------------------------------------------------------------------------- /lua/config/lualine/components/lsp_servers.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | 3 | local lsp_servers = function() 4 | if vim.o.columns > 70 then 5 | local buf_clients = vim.lsp.buf_get_clients() 6 | 7 | if not buf_clients or #buf_clients == 0 then return "NO LSP  " end 8 | 9 | local server_names = {} 10 | 11 | for _, client in pairs(buf_clients) do 12 | local client_name = client.name 13 | if client_name ~= "null-ls" and client_name ~= "copilot" then 14 | table.insert(server_names, client_name) 15 | end 16 | end 17 | 18 | if package.loaded["null-ls"] then 19 | local has_null_ls, null_ls = pcall(require, "null-ls") 20 | 21 | if has_null_ls then 22 | local buf_ft = vim.api.nvim_buf_get_option(0, "filetype") 23 | local null_ls_methods = { 24 | null_ls.methods.DIAGNOSTICS, 25 | null_ls.methods.DIAGNOSTICS_ON_OPEN, 26 | null_ls.methods.DIAGNOSTICS_ON_SAVE, 27 | null_ls.methods.FORMATTING, 28 | } 29 | 30 | local get_null_ls_sources = function(methods, name_only) 31 | local sources = require("null-ls.sources") 32 | local available_sources = sources.get_available(buf_ft) 33 | 34 | methods = type(methods) == "table" and methods or { methods } 35 | 36 | -- methods = nil or {} 37 | if #methods == 0 then 38 | if name_only then 39 | return vim.tbl_map(function(source) return source.name end, available_sources) 40 | end 41 | return available_sources 42 | end 43 | 44 | local source_results = {} 45 | 46 | for _, source in ipairs(available_sources) do 47 | for _, method in ipairs(methods) do 48 | if source.methods[method] then 49 | if name_only then 50 | table.insert(source_results, source.name) 51 | else 52 | table.insert(source_results, source) 53 | end 54 | break 55 | end 56 | end 57 | end 58 | 59 | return source_results 60 | end 61 | 62 | local null_ls_builtins = get_null_ls_sources(null_ls_methods, true) 63 | vim.list_extend(server_names, null_ls_builtins) 64 | end 65 | end 66 | 67 | if package.loaded["conform"] then 68 | local has_conform, conform = pcall(require, "conform") 69 | vim.list_extend( 70 | server_names, 71 | vim.tbl_map(function(formatter) return formatter.name end, conform.list_formatters(0)) 72 | ) 73 | end 74 | 75 | return table.concat(vim.fn.uniq(server_names), ", ") 76 | end 77 | return "" 78 | end 79 | 80 | return { 81 | lsp_servers, 82 | color = { fg = colors.magenta }, 83 | } 84 | -------------------------------------------------------------------------------- /lua/config/lualine/components/mode.lua: -------------------------------------------------------------------------------- 1 | local colors = require("ui.colors") 2 | local no_seps = require("configs.lualine.seps").no_seps 3 | 4 | return { 5 | "mode", 6 | separator = no_seps, 7 | icons_enabled = true, 8 | cond = function() return vim.o.columns > 70 end, 9 | } 10 | -------------------------------------------------------------------------------- /lua/config/lualine/components/time.lua: -------------------------------------------------------------------------------- 1 | local time = function() return vim.fn.strftime("%H:%M:%S") end 2 | 3 | return { 4 | time, 5 | } 6 | -------------------------------------------------------------------------------- /lua/config/lualine/init.lua: -------------------------------------------------------------------------------- 1 | local no_seps = require("configs.lualine.seps").no_seps 2 | 3 | -- Components 4 | local file = require("plugins.configs.lualine.components.file") 5 | local mode = require("plugins.configs.lualine.components.mode") 6 | local indent = require("plugins.configs.lualine.components.indent") 7 | local copilot = require("plugins.configs.lualine.components.copilot") 8 | local location = require("plugins.configs.lualine.components.location") 9 | local lsp_servers = require("plugins.configs.lualine.components.lsp_servers") 10 | local encoding = require("plugins.configs.lualine.components.encoding") 11 | local diagnostics = require("plugins.configs.lualine.components.diagnostics") 12 | local git = require("plugins.configs.lualine.components.git") 13 | 14 | local configs = { 15 | options = { 16 | theme = "tokyonight", 17 | globalstatus = true, 18 | icons_enabled = true, 19 | component_separators = no_seps, 20 | section_separators = no_seps, 21 | disabled_filetypes = { 22 | "lazy", 23 | "NvimTree", 24 | "mason", 25 | "toggleterm", 26 | "help", 27 | "TelescopePrompt", 28 | }, 29 | always_divide_middle = true, 30 | }, 31 | sections = { 32 | lualine_a = { 33 | mode, 34 | }, 35 | lualine_b = { 36 | file.type, 37 | file.name, 38 | }, 39 | lualine_c = { 40 | git.branch, 41 | git.diff, 42 | }, 43 | lualine_x = { 44 | diagnostics, 45 | lsp_servers, 46 | copilot, 47 | indent.icon, 48 | indent.value, 49 | }, 50 | lualine_y = { 51 | encoding, 52 | }, 53 | lualine_z = { 54 | location.value, 55 | location.progress, 56 | }, 57 | }, 58 | } 59 | 60 | return configs 61 | -------------------------------------------------------------------------------- /lua/config/lualine/seps.lua: -------------------------------------------------------------------------------- 1 | return { 2 | rounded_seps = { left = "", right = "" }, 3 | no_seps = { "", "" }, 4 | } 5 | -------------------------------------------------------------------------------- /lua/config/mason.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | -- auto sync the installed packages with ensure_installed when open nvim 3 | auto_sync = true, 4 | ui = { 5 | check_outdated_packages_on_open = true, 6 | border = "single", -- Accepts same border values as |nvim_open_win()|. 7 | width = 0.8, 8 | height = 0.9, 9 | icons = { 10 | package_pending = " ", 11 | package_installed = " ", 12 | package_uninstalled = " ", 13 | }, 14 | }, 15 | max_concurrent_installers = 10, 16 | } 17 | 18 | return options 19 | -------------------------------------------------------------------------------- /lua/config/nvim-autopairs.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | check_ts = true, 3 | ts_config = { 4 | lua = { "string", "source" }, 5 | javascript = { "string", "template_string" }, 6 | java = false, 7 | }, 8 | disable_filetype = { "TelescopePrompt", "NvimTree", "spectre_panel", "dashboard" }, 9 | fast_wrap = { 10 | map = "", 11 | chars = { "{", "[", "(", '"', "'" }, 12 | pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""), 13 | offset = 0, -- Offset from pattern match 14 | end_key = "$", 15 | keys = "qwertyuiopzxcvbnmasdfghjkl", 16 | check_comma = true, 17 | highlight = "PmenuSel", 18 | highlight_grey = "LineNr", 19 | }, 20 | } 21 | 22 | return options 23 | -------------------------------------------------------------------------------- /lua/config/nvim-tree.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local on_attach = function(bufnr) 4 | local api = require("nvim-tree.api") 5 | api.events.subscribe(api.events.Event.TreeOpen, function() vim.wo.statusline = " " end) 6 | 7 | local map = vim.keymap.set 8 | local function opts(desc) 9 | return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } 10 | end 11 | 12 | map("n", "", api.node.open.edit, opts("Open")) 13 | map("n", "o", api.node.open.edit, opts("Open")) 14 | map("n", "cd", api.tree.change_root_to_node, opts("CD")) 15 | map("n", "v", api.node.open.vertical, opts("Open: Vertical Split")) 16 | map("n", "s", api.node.open.horizontal, opts("Open: Horizontal Split")) 17 | map("n", "", api.node.open.tab, opts("Open: New Tab")) 18 | map("n", "P", api.node.navigate.parent, opts("Parent Directory")) 19 | map("n", "", api.node.navigate.parent_close, opts("Close Directory")) 20 | map("n", "", api.node.open.preview, opts("Open Preview")) 21 | map("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) 22 | map("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) 23 | map("n", "C", api.tree.toggle_git_clean_filter, opts("Toggle Git Clean")) 24 | map("n", "I", api.tree.toggle_gitignore_filter, opts("Toggle Git Ignore")) 25 | map("n", "R", api.tree.reload, opts("Refresh")) 26 | map("n", "a", api.fs.create, opts("Create")) 27 | map("n", "D", api.fs.remove, opts("Delete")) 28 | map("n", "dd", api.fs.trash, opts("Trash")) 29 | map("n", "r", api.fs.rename, opts("Rename")) 30 | map("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) 31 | map("n", "x", api.fs.cut, opts("Cut")) 32 | map("n", "yy", api.fs.copy.node, opts("Copy")) 33 | map("n", "yn", api.fs.copy.filename, opts("Copy Name")) 34 | map("n", "yt", api.fs.copy.relative_path, opts("Copy Relative Path")) 35 | map("n", "yp", api.fs.copy.absolute_path, opts("Copy Absolute Path")) 36 | map("n", "p", api.fs.paste, opts("Paste")) 37 | map("n", "-", api.tree.change_root_to_parent, opts("Up")) 38 | map("n", "O", api.node.run.system, opts("Run System")) 39 | map("n", "f", api.live_filter.start, opts("Filter")) 40 | map("n", "F", api.live_filter.clear, opts("Clean Filter")) 41 | map("n", "q", api.tree.close, opts("Close")) 42 | map("n", "W", api.tree.collapse_all, opts("Collapse")) 43 | map("n", "", api.tree.search_node, opts("Search")) 44 | map("n", "", api.node.show_info_popup, opts("Info")) 45 | map("n", "?", api.tree.toggle_help, opts("Help")) 46 | map("n", " ", api.marks.toggle, opts("Toggle Bookmark")) 47 | end 48 | 49 | local options = { 50 | disable_netrw = true, 51 | hijack_cursor = false, -- Keeps the cursor on the first letter of the filename when moving in the tree. 52 | hijack_unnamed_buffer_when_opening = true, 53 | sync_root_with_cwd = true, 54 | reload_on_bufenter = true, 55 | respect_buf_cwd = true, 56 | on_attach = on_attach, 57 | select_prompts = false, 58 | view = { 59 | cursorline = true, 60 | width = 28, 61 | side = "left", 62 | adaptive_size = false, 63 | number = false, 64 | relativenumber = false, 65 | signcolumn = "yes", 66 | }, 67 | renderer = { 68 | special_files = {}, -- add highlight if is special file 69 | }, 70 | update_focused_file = { 71 | enable = true, 72 | update_root = true, 73 | ignore_list = {}, 74 | }, 75 | filters = { 76 | dotfiles = false, 77 | git_clean = false, 78 | no_buffer = false, 79 | custom = { 80 | "zsh_history_fix", 81 | "node_modules", 82 | ".husky", 83 | "*.ppt", 84 | "*.exe", 85 | ".rbenv", 86 | "yay", 87 | }, 88 | exclude = {}, 89 | }, 90 | filesystem_watchers = { 91 | enable = true, 92 | debounce_delay = 50, 93 | ignore_dirs = { "node_modules", ".git", ".cache", "target", "dist" }, 94 | }, 95 | git = { 96 | enable = true, 97 | ignore = false, 98 | show_on_dirs = true, 99 | show_on_open_dirs = true, 100 | timeout = 400, 101 | }, 102 | modified = { 103 | enable = false, 104 | show_on_dirs = true, 105 | show_on_open_dirs = true, 106 | }, 107 | actions = { 108 | file_popup = { 109 | open_win_config = { 110 | col = 1, 111 | row = 1, 112 | relative = "cursor", 113 | border = "single", -- shadow, single, double, rounded 114 | style = "minimal", 115 | }, 116 | }, 117 | open_file = { 118 | window_picker = { 119 | enable = false, 120 | }, 121 | }, 122 | }, 123 | -- trash = { 124 | -- cmd = "trash-put", 125 | -- }, 126 | ui = { 127 | confirm = { 128 | remove = true, 129 | trash = true, 130 | }, 131 | }, 132 | } 133 | 134 | return options 135 | -------------------------------------------------------------------------------- /lua/config/nvim-treesitter.lua: -------------------------------------------------------------------------------- 1 | -- Check if android or iphone device 2 | local is_mobile = vim.fn.isdirectory("/system") == 1 or vim.fn.isdirectory("/var/mobile") 3 | 4 | local options = { 5 | ensure_installed = not is_mobile and "all", 6 | ignore_install = { 7 | "comment", -- i don't need comment url highlight because i use url-open plugin 8 | }, 9 | highlight = { 10 | enable = true, 11 | use_languagetree = true, 12 | additional_vim_regex_highlighting = false, 13 | --disable ={"html","css"} 14 | }, 15 | indent = { 16 | enable = true, 17 | }, 18 | additional_vim_regex_highlighting = false, 19 | autotag = { 20 | enable = true, 21 | filetypes = { 22 | "html", 23 | "xml", 24 | "jsx", 25 | "tsx", 26 | "javascript", 27 | "javascriptreact", 28 | "typescript", 29 | "typescriptreact", 30 | }, 31 | }, 32 | autopairs = { 33 | enable = true, 34 | }, 35 | } 36 | 37 | return options 38 | -------------------------------------------------------------------------------- /lua/config/nvim-ufo.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | -- open_fold_hl_timeout = 400, 3 | close_fold_kinds_for_ft = { 4 | default = { "imports", "comment" }, 5 | json = { "array" }, 6 | c = { "comment", "region" }, 7 | }, 8 | preview = { 9 | win_config = { 10 | border = "single", 11 | winhighlight = "Normal:NormalFloat", 12 | -- winhighlight = "Normal:Folded", 13 | winblend = 0, 14 | }, 15 | mappings = { 16 | scrollE = "", 17 | scrollY = "", 18 | scrollU = "", 19 | scrollD = "", 20 | jumpTop = "gg", 21 | jumpBot = "G", 22 | }, 23 | }, 24 | provider_selector = function(_, filetype, buftype) 25 | -- only use indent until a file is opened 26 | if filetype == "" or buftype == "nofile" then return "indent" end 27 | 28 | return function(bufnr) 29 | local ufo = require("ufo") 30 | local function handleFallbackException(err, providerName) 31 | if type(err) == "string" and err:match("UfoFallbackException") then 32 | return ufo.getFolds(bufnr, providerName) 33 | else 34 | return require("promise").reject(err) 35 | end 36 | end 37 | return ufo 38 | .getFolds(bufnr, "lsp") 39 | :catch(function(err) return handleFallbackException(err, "treesitter") end) 40 | :catch(function(err) return handleFallbackException(err, "indent") end) 41 | end 42 | end, 43 | fold_virt_text_handler = function(virtText, lnum, endLnum, width, truncate) 44 | local suffix = ("  %d "):format(endLnum - lnum) 45 | local sufWidth = vim.fn.strdisplaywidth(suffix) 46 | local targetWidth = width - sufWidth 47 | local newVirtText = {} 48 | local curWidth = 0 49 | for _, chunk in ipairs(virtText) do 50 | local chunkText = chunk[1] 51 | local chunkWidth = vim.fn.strdisplaywidth(chunkText) 52 | 53 | if targetWidth > curWidth + chunkWidth then 54 | -- The chunk fits within the target width, so add it to the new table. 55 | table.insert(newVirtText, chunk) 56 | curWidth = curWidth + chunkWidth 57 | else 58 | chunkText = truncate(chunkText, targetWidth - curWidth) 59 | table.insert(newVirtText, { chunkText, chunk[2] }) 60 | curWidth = curWidth + vim.fn.strdisplaywidth(chunkText) 61 | if curWidth < targetWidth then string.insert(suffix, " ", suffix:len() + 1) end 62 | break 63 | end 64 | end 65 | table.insert(newVirtText, { suffix, "MoreMsg" }) 66 | return newVirtText 67 | end, 68 | } 69 | 70 | return options 71 | -------------------------------------------------------------------------------- /lua/config/stcursorword.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | max_word_length = 100, -- if cursorword length > max_word_length then not highlight 3 | min_word_length = 2, -- if cursorword length < min_word_length then not highlight 4 | excluded = { 5 | filetypes = {}, 6 | buftypes = { 7 | "terminal", 8 | }, 9 | file_patterns = {}, 10 | }, 11 | highlight = { 12 | underline = true, 13 | fg = nil, 14 | bg = nil, 15 | }, 16 | } 17 | 18 | return options 19 | -------------------------------------------------------------------------------- /lua/config/sttusline/init.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | -- 0 | 1 | 2 | 3 3 | -- recommended: 3 4 | -- laststatus = 3, 5 | -- disabled = { 6 | -- filetypes = { 7 | -- -- "NvimTree", 8 | -- -- "lazy", 9 | -- }, 10 | -- buftypes = { 11 | -- "terminal", 12 | -- }, 13 | -- }, 14 | -- components = { 15 | -- "mode", 16 | -- "filename", 17 | -- "git-diff", 18 | -- "diagnostics", 19 | -- "%=", 20 | -- "lsps-formatters", 21 | -- "indent", 22 | -- "encoding", 23 | -- "pos-cursor", 24 | -- "pos-cursor-progress", 25 | -- }, 26 | } 27 | return options 28 | -------------------------------------------------------------------------------- /lua/config/telescope/init.lua: -------------------------------------------------------------------------------- 1 | -- local no_actions = function(prompt_bufnr) print("No actions available!") end 2 | 3 | local actions = require("telescope.actions") 4 | -- local sorters, previewers, actions = 5 | -- require("telescope.sorters"), require("telescope.previewers"), require("telescope.actions") 6 | 7 | local options = { 8 | extension_list = { 9 | -- "fzf", 10 | -- "media_files", 11 | -- "projects", 12 | -- "zoxide", 13 | -- "neoclip", 14 | }, 15 | defaults = { 16 | layout_config = { 17 | horizontal = { 18 | prompt_position = "top", 19 | preview_width = 0.55, 20 | results_width = 0.8, 21 | }, 22 | vertical = { 23 | mirror = false, 24 | }, 25 | width = 0.87, 26 | height = 0.9, 27 | preview_cutoff = 120, 28 | }, 29 | prompt_prefix = " ", 30 | selection_caret = " ", 31 | -- entry_prefix = " ", -- default 32 | -- initial_mode = "insert", -- default 33 | -- selection_strategy = "reset", -- default 34 | -- layout_strategy = "horizontal", -- default 35 | sorting_strategy = "ascending", 36 | mappings = { 37 | i = { 38 | [""] = actions.close, 39 | [""] = actions.close, -- support to toggle telescope 40 | [""] = actions.close, 41 | [""] = actions.close, 42 | 43 | [""] = actions.move_selection_next, 44 | [""] = actions.move_selection_previous, 45 | 46 | [""] = actions.move_selection_next, 47 | [""] = actions.move_selection_previous, 48 | 49 | [""] = actions.results_scrolling_up, 50 | [""] = actions.results_scrolling_down, 51 | 52 | [""] = actions.preview_scrolling_up, 53 | [""] = actions.preview_scrolling_down, 54 | 55 | [""] = actions.select_vertical, 56 | [""] = actions.select_horizontal, 57 | }, 58 | n = { 59 | ["q"] = actions.close, 60 | [""] = actions.close, 61 | [""] = actions.close, -- support to toggle telescope 62 | [""] = actions.close, 63 | [""] = actions.close, 64 | 65 | [""] = actions.preview_scrolling_up, 66 | [""] = actions.preview_scrolling_down, 67 | 68 | [""] = actions.results_scrolling_up, 69 | [""] = actions.results_scrolling_down, 70 | 71 | [""] = actions.move_selection_next, 72 | [""] = actions.move_selection_previous, 73 | 74 | [""] = actions.select_vertical, 75 | [""] = actions.select_horizontal, 76 | }, 77 | }, 78 | file_ignore_patterns = { 79 | "^.git/", 80 | "^./.git/", 81 | "^node_modules/", 82 | "^build/", 83 | "^dist/", 84 | "^target/", 85 | "^vendor/", 86 | "^lazy%-lock%.json$", 87 | "^package%-lock%.json$", 88 | }, 89 | path_display = { "smart" }, 90 | -- border = true, -- default 91 | -- color_devicons = true, 92 | borderchars = { "─", "│", "─", "│", "┌", "┐", "┘", "└" }, 93 | set_env = { COLORTERM = "truecolor" }, -- default = nil, 94 | -- file_sorter = sorters.get_fuzzy_file, 95 | -- generic_sorter = sorters.get_generic_fuzzy_sorter, 96 | -- file_previewer = previewers.vim_buffer_cat.new, 97 | -- grep_previewer = previewers.vim_buffer_vimgrep.new, 98 | -- qflist_previewer = previewers.vim_buffer_qflist.new, 99 | -- buffer_previewer_maker = previewers.buffer_previewer_maker, 100 | }, 101 | pickers = { 102 | planets = { 103 | show_pluto = true, 104 | }, 105 | find_files = { 106 | hidden = true, 107 | }, 108 | }, 109 | extensions = { 110 | fzf = { 111 | -- NOTE: uncomment any option to override the default options 112 | -- fuzzy = true, -- false will only do exact matching 113 | -- override_generic_sorter = true, -- override the generic sorter 114 | -- override_file_sorter = true, -- override the file sorter 115 | -- case_mode = "smart_case", -- or "ignore_case" or "respect_case" 116 | }, 117 | media_files = { 118 | filetypes = { "png", "webp", "jpg", "jpeg", "webm", "pdf", "mp4" }, 119 | find_cmd = "rg", 120 | }, 121 | }, 122 | } 123 | 124 | return options 125 | -------------------------------------------------------------------------------- /lua/config/toggleterm.lua: -------------------------------------------------------------------------------- 1 | local options 2 | 3 | options = { 4 | size = function(term) ---@type number|function 5 | if term.direction == "horizontal" then 6 | return 15 7 | elseif term.direction == "vertical" then 8 | return vim.o.columns * 0.4 9 | end 10 | end, 11 | open_mapping = [[]], 12 | on_create = function(term) 13 | local map = require("utils.mapper").map 14 | local api = vim.api 15 | 16 | local term_id = term.id 17 | local bufnr = term.bufnr 18 | 19 | local map1 = function(mode, key, map_to, expr) map(mode, key, map_to, { buffer = bufnr, expr = expr }) end 20 | 21 | local new_term_id = term_id 22 | local pressed_time = 0 23 | 24 | map1({ "n", "t" }, options.open_mapping, function() 25 | if new_term_id ~= term_id and (vim.uv or vim.loop).now() - pressed_time < 1500 then 26 | vim.defer_fn(function() 27 | api.nvim_command(new_term_id .. "ToggleTerm") 28 | new_term_id = term_id 29 | end, 20) 30 | api.nvim_input("") 31 | else 32 | new_term_id = term_id 33 | api.nvim_command(term_id .. "ToggleTerm") 34 | end 35 | end) 36 | 37 | for i = 1, 9, 1 do 38 | local istr = tostring(i) 39 | map1({ "n", "t" }, istr, function() 40 | pressed_time = (vim.uv or vim.loop).now() 41 | new_term_id = i 42 | return istr 43 | end, true) 44 | end 45 | end, 46 | on_open = function(term) 47 | vim.api.nvim_command("startinsert") 48 | vim.defer_fn( 49 | function() vim.notify("Terminal " .. term.id .. " opened", vim.log.levels.INFO, { title = "ToggleTerm" }) end, 50 | 100 51 | ) 52 | end, 53 | on_close = function(term) vim.api.nvim_command("stopinsert") end, 54 | hide_numbers = true, 55 | autochdir = true, 56 | shade_filetypes = {}, 57 | shade_terminals = false, 58 | -- the degree by which to darken to terminal colour, 59 | -- default: 1 for dark backgrounds, 3 for light 60 | shading_factor = 1, 61 | start_in_insert = true, 62 | insert_mappings = true, -- whether or not the open mapping applies in insert mode 63 | persist_size = true, 64 | direction = "horizontal", -- | 'horizontal' | 'horizontal' | 'tab' | 'float',, 65 | close_on_exit = true, -- close the terminal window when the process exits 66 | shell = vim.o.shell, -- change the default shell 67 | auto_scroll = true, 68 | float_opts = { 69 | border = "single", -- single/double/shadow/curved 70 | width = math.floor(0.9 * vim.o.columns), 71 | height = math.floor(0.85 * vim.o.lines), 72 | winblend = 3, 73 | }, 74 | winbar = { 75 | enabled = false, 76 | name_formatter = function(term) return "" end, 77 | }, 78 | } 79 | 80 | return options 81 | -------------------------------------------------------------------------------- /lua/config/tokyonight.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | -- style = "storm", -- `storm`, `moon`, a darker variant `night` and `day` 3 | style = "moon", -- `storm`, `moon`, a darker variant `night` and `day` 4 | light_style = "day", 5 | transparent = false, 6 | terminal_colors = true, 7 | styles = { 8 | comments = { italic = true }, 9 | keywords = { italic = true }, 10 | functions = {}, 11 | variables = {}, 12 | -- Background styles. Can be "dark", "transparent" or "normal" 13 | sidebars = "dark", -- "dark", "transparent" or "normal" 14 | floats = "dark", -- "dark", "transparent" or "normal" 15 | }, 16 | sidebars = { "qf", "help" }, 17 | day_brightness = 0.4, 18 | hide_inactive_statusline = false, 19 | dim_inactive = false, -- dims inactive windows 20 | lualine_bold = false, -- When `true`, section headers in the lualine theme will be bold 21 | } 22 | 23 | return options 24 | -------------------------------------------------------------------------------- /lua/config/url-open.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | open_app = "default", 3 | open_only_when_cursor_on_url = false, 4 | highlight_url = { 5 | all_urls = { 6 | enabled = true, 7 | fg = "#19ddff", -- "text" or "#rrggbb" 8 | bg = nil, -- nil or "#rrggbb" 9 | underline = true, 10 | }, 11 | cursor_move = { 12 | enabled = true, 13 | fg = "#199eff", -- "text" or "#rrggbb" 14 | bg = nil, -- nil or "#rrggbb" 15 | underline = true, 16 | }, 17 | }, 18 | deep_pattern = false, 19 | extra_patterns = {}, 20 | } 21 | 22 | return options 23 | -------------------------------------------------------------------------------- /lua/config/whichkey.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | win= { 3 | border = "single", -- none/single/double/shadow 4 | }, 5 | } 6 | 7 | return options 8 | -------------------------------------------------------------------------------- /lua/config/wilder.lua: -------------------------------------------------------------------------------- 1 | local status_ok, wilder = pcall(require, "wilder") 2 | if not status_ok then return end 3 | 4 | local colors = require("ui.colors") 5 | 6 | wilder.setup { 7 | modes = { ":", "/", "?" }, 8 | next_key = "", 9 | previous_key = "", 10 | enable_cmdline_enter = 1, 11 | } 12 | 13 | local set_option = wilder.set_option 14 | local popupmenu_devicons = wilder.popupmenu_devicons 15 | local popupmenu_renderer = wilder.popupmenu_renderer 16 | local popupmenu_palette_theme = wilder.popupmenu_palette_theme 17 | 18 | set_option("use_python_remote_plugin", 0) 19 | set_option("pipeline", { 20 | wilder.branch( 21 | wilder.cmdline_pipeline { 22 | fuzzy = 1, 23 | fuzzy_filter = wilder.lua_fzy_filter(), 24 | }, 25 | wilder.vim_search_pipeline() 26 | ), 27 | }) 28 | 29 | local general_style = { 30 | border = "single", -- 'single' | 'double' | 'rounded' | 'solid' 31 | max_height = "80%", 32 | min_height = 0, -- set to the same as 'max_height' for a fixed height window 33 | prompt_position = "top", -- 'top' or 'bottom' 34 | reverse = 0, -- 1 to reverse 35 | left = { " ", popupmenu_devicons() }, 36 | highlighter = { wilder.lua_fzy_highlighter() }, 37 | highlights = { 38 | accent = wilder.make_hl("WilderAccent", "Pmenu", { 39 | { a = 1 }, 40 | { a = 1 }, 41 | { foreground = colors.pink }, 42 | }), 43 | }, 44 | } 45 | 46 | local change_left_icons = function(styles, left) 47 | styles.left = left 48 | return styles 49 | end 50 | 51 | set_option( 52 | "renderer", 53 | wilder.renderer_mux { 54 | [":"] = popupmenu_renderer( 55 | popupmenu_palette_theme(change_left_icons(general_style, { " ", " ", popupmenu_devicons() })) 56 | ), 57 | ["/"] = popupmenu_renderer( 58 | popupmenu_palette_theme(change_left_icons(general_style, { " ", " ", popupmenu_devicons() })) 59 | ), 60 | ["?"] = popupmenu_renderer( 61 | popupmenu_palette_theme(change_left_icons(general_style, { " ", " ", popupmenu_devicons() })) 62 | ), 63 | } 64 | ) 65 | -------------------------------------------------------------------------------- /lua/config/witch.lua: -------------------------------------------------------------------------------- 1 | local options = { 2 | theme = { 3 | -- if you disable the theme, no default highlight styles will be set by default 4 | -- you must to add a customs module or extras module to set the highlight styles 5 | enabled = true, 6 | 7 | -- default style of the theme 8 | -- "dark", "light" 9 | style = "dark", 10 | 11 | -- more module that you want it should be loaded 12 | extras = { 13 | -- bracket = true, 14 | -- dashboard = true, 15 | -- diffview = true, 16 | -- explorer = true, 17 | -- indentline = true, 18 | 19 | -- you can disable startup module by setting enabled to false 20 | -- then you can add the startup module by yourself like extras module like above 21 | -- ["startup."] = true, 22 | }, 23 | 24 | -- custome your highlight module 25 | -- see: witch.theme.example 26 | customs = { 27 | -- require("witch.theme.example"), 28 | }, 29 | 30 | -- This function is called when witch starts highlighting. 31 | -- It provides a unique opportunity to modify the default highlight groups. 32 | -- If you wish to customize the default highlight groups, you can do so here. 33 | -- This function is invoked after loading all colors and highlight options 34 | -- but before applying the highlights, allowing users to adjust undesired highlights. 35 | -- you can do something like this 36 | -- 37 | -- on_highlight = function(style, colors, highlight) 38 | -- if style == "dark" then 39 | -- -- change the default background of witch 40 | -- colors.bg = "#000000" 41 | 42 | -- -- change the Normal highlight group of witch 43 | -- highlight.Normal = { fg = "#ffffff", bg = "#000000" } 44 | -- elseif style == "light" then 45 | -- -- change the default background of witch 46 | -- colors.bg = "#ffffff" 47 | 48 | -- -- change the Normal highlight group of witch 49 | -- highlight.Normal = { fg = "#000000", bg = "#ffffff" } 50 | -- end 51 | -- end, 52 | 53 | --- @param style string : the current style of the theme 54 | --- @param colors table : the current colors of the theme 55 | --- @param highlight table : the current highlights of the theme 56 | on_highlight = function(style, colors, highlight) end, 57 | }, 58 | 59 | -- dims inactive windows 60 | dim_inactive = { 61 | enabled = true, 62 | -- from 0 to 1 63 | -- as nearer to 1 the dimming will be lighter 64 | level = 0.48, 65 | 66 | -- Prevent dimming the last active window when switching to a window 67 | -- with specific filetypes or buftypes listed in the excluded table. 68 | -- 69 | -- The idea of this option is when change to a window like NvimTree, Telescope, ... 70 | -- where these windows are considered auxiliary tools. 71 | -- the last active window retains its status as the main window 72 | -- and should not be dimmed upon switching. 73 | excluded = { 74 | filetypes = { 75 | NvimTree = true, 76 | }, 77 | buftypes = { 78 | nofile = true, 79 | prompt = true, 80 | terminal = true, 81 | }, 82 | }, 83 | }, 84 | 85 | -- true if you want to use command StinvimUISwitch 86 | switcher = true, 87 | 88 | -- add your custom themes here 89 | more_themes = { 90 | 91 | -- the key is the name of the theme must be in PascalCase 92 | -- the value is the table of colors to be passed to the theme 93 | -- with following format in witch.colors.example 94 | -- Custom1 = {}, 95 | -- Custom2 = {}, 96 | }, 97 | } 98 | 99 | return options 100 | -------------------------------------------------------------------------------- /lua/core/autocmd.lua: -------------------------------------------------------------------------------- 1 | local api, type = vim.api, type 2 | local cmd, autocmd = api.nvim_command, api.nvim_create_autocmd 3 | 4 | local group = api.nvim_create_augroup("STINVIM_CORE_AUTOCMD", { clear = true }) 5 | 6 | autocmd({ "VimEnter", "VimLeave" }, { 7 | group = group, 8 | command = "runtime! plugin/rplugin.vim | silent! UpdateRemotePlugins", 9 | desc = "Update remote plugins", 10 | }) 11 | 12 | autocmd("BufWritePre", { 13 | group = group, 14 | command = "silent! %s/\\s\\+$//e | silent! call mkdir(expand('%:p:h'), 'p')", 15 | desc = "Remove trailing whitespace and create parent directory if not exists", 16 | }) 17 | 18 | autocmd("BufEnter", { 19 | group = group, 20 | desc = "Do filetype specific work", 21 | callback = function(args) 22 | vim.defer_fn(function() 23 | local bufnr = api.nvim_get_current_buf() 24 | local work = ({ 25 | help = "wincmd L", -- Open help in vertical split 26 | qf = "set nobuflisted", -- Don't show quickfix in buffer list 27 | sh = function() 28 | if args.file:match("%.env$") then vim.diagnostic.enable(false, { bufnr = bufnr }) end 29 | end, -- Disable diagnostic for .env files 30 | })[vim.bo[bufnr].filetype] 31 | 32 | if type(work) == "string" then 33 | cmd(work) 34 | elseif type(work) == "function" then 35 | work() 36 | end 37 | end, 3) 38 | end, 39 | }) 40 | 41 | autocmd({ "WinLeave", "WinEnter" }, { 42 | group = group, 43 | desc = "Highlight current line and column", 44 | callback = function(args) 45 | cmd(({ 46 | WinLeave = "setlocal nocursorline nocursorcolumn", 47 | WinEnter = "if &buflisted | setlocal cursorline cursorcolumn | else | setlocal cursorline | endif", 48 | })[args.event]) 49 | end, 50 | }) 51 | 52 | autocmd("TextYankPost", { 53 | group = group, 54 | command = "silent! lua vim.highlight.on_yank({higroup='IncSearch', timeout=120})", 55 | desc = "Highlight yanked text", 56 | }) 57 | 58 | autocmd("ModeChanged", { 59 | group = group, 60 | desc = "Move to relative line number when in visual mode", 61 | callback = function(args) 62 | local newmode = args.match:match(":(.*)") 63 | local visual_modes = { 64 | ["v"] = true, 65 | ["V"] = true, 66 | [""] = true, 67 | } 68 | if visual_modes[newmode] then 69 | cmd("set relativenumber") 70 | else 71 | cmd("set norelativenumber") 72 | end 73 | end, 74 | }) 75 | 76 | autocmd("MenuPopup", { 77 | group = group, 78 | once = true, 79 | desc = "Customize right click contextual menu.", 80 | callback = function() 81 | -- Disable right click message 82 | cmd([[aunmenu PopUp.How-to\ disable\ mouse]]) 83 | -- cmd([[aunmenu PopUp.-1-]]) -- You can remode a separator like this. 84 | cmd([[menu PopUp.󰏘\ Inspect\ Color :Inspect]]) 85 | cmd([[menu PopUp.\ Start\ \Debugger :DapContinue]]) 86 | cmd([[menu PopUp.\ Toggle\ \Breakpoint :lua require('dap').toggle_breakpoint()]]) 87 | end, 88 | }) 89 | 90 | autocmd({ "InsertEnter", "InsertLeave", "TermEnter", "TermLeave" }, { 91 | group = group, 92 | desc = "Auto change search highlight color", 93 | callback = function(args) 94 | cmd(({ 95 | InsertEnter = "set nohlsearch", 96 | InsertLeave = "set hlsearch", 97 | TermEnter = "set nohlsearch", 98 | TermLeave = "set hlsearch", 99 | })[args.event]) 100 | end, 101 | }) 102 | 103 | -- https://unix.stackexchange.com/questions/149209/refresh-changed-content-of-file-opened-in-vim/383044#383044 104 | -- https://vi.stackexchange.com/questions/13692/prevent-focusgained-autocmd-running-in-command-line-editing-mode 105 | autocmd({ "FocusGained", "TermResponse", "TermLeave" }, { 106 | group = group, 107 | command = [[silent! if mode() != 'c' && !bufexists("[Command Line]") | checktime | endif | lua if package.loaded['nvim-tree'] then vim.api.nvim_command('NvimTreeRefresh') end]], 108 | desc = "Reload file if changed outside of nvim", 109 | }) 110 | 111 | autocmd("BufHidden", { 112 | desc = "Delete [No Name] buffer when it's hidden", 113 | group = group, 114 | callback = function(event) 115 | if event.file == "" and vim.bo[event.buf].buftype == "" and not vim.bo[event.buf].modified then 116 | api.nvim_buf_delete(event.buf, { force = true }) 117 | end 118 | end, 119 | }) 120 | 121 | do 122 | local vim_resized_trigger = false 123 | autocmd({ "VimResized", "WinScrolled" }, { 124 | group = group, 125 | desc = "Preserve window ratios on VimResized", 126 | callback = function(args) 127 | vim.schedule(function() 128 | local win_ids = api.nvim_tabpage_list_wins(0) 129 | local num_wins = #win_ids 130 | 131 | if num_wins > 1 then 132 | local curr_vim_width = vim.o.columns 133 | local curr_vim_height = vim.o.lines 134 | - vim.o.cmdheight 135 | - (vim.o.laststatus ~= 0 and 1 or 0) 136 | - (vim.o.showtabline ~= 0 and #api.nvim_list_tabpages() > 1 and 1 or 0) 137 | 138 | if args.event == "VimResized" then 139 | vim_resized_trigger = true 140 | for i = 1, num_wins, 1 do 141 | local id = win_ids[i] 142 | local last_widths, last_heights = vim.w[id].last_widths, vim.w[id].last_heights 143 | local ceil_or_floor = i % 2 == 1 and math.ceil or math.floor 144 | if type(last_widths) == "table" then 145 | api.nvim_win_set_width(id, ceil_or_floor(curr_vim_width / last_widths[2] * last_widths[1])) 146 | end 147 | if type(last_heights) == "table" then 148 | api.nvim_win_set_height(id, ceil_or_floor(curr_vim_height / last_heights[2] * last_heights[1])) 149 | end 150 | end 151 | elseif not vim_resized_trigger then 152 | for i = 1, num_wins, 1 do 153 | local id = win_ids[i] 154 | api.nvim_win_set_var(id, "last_widths", { api.nvim_win_get_width(id), curr_vim_width }) 155 | api.nvim_win_set_var(id, "last_heights", { api.nvim_win_get_height(id), curr_vim_height }) 156 | end 157 | else 158 | vim_resized_trigger = false 159 | end 160 | end 161 | end) 162 | end, 163 | }) 164 | end 165 | -------------------------------------------------------------------------------- /lua/core/bootstrap.lua: -------------------------------------------------------------------------------- 1 | local vim = vim 2 | local api, fn = vim.api, vim.fn 3 | 4 | if vim.version().minor < 10 then 5 | api.nvim_err_writeln("Error: Bootstrap requires at least nvim 0.10") 6 | return 7 | end 8 | 9 | local M = {} 10 | 11 | local function echo(str) 12 | vim.cmd.redraw() 13 | api.nvim_echo({ { str, "Bold" } }, true, {}) 14 | end 15 | 16 | function M.lazy(install_path) 17 | --------- lazy.nvim --------------- 18 | echo(" Installing lazy.nvim and plugins ...") 19 | 20 | local repo = "https://github.com/folke/lazy.nvim.git" 21 | 22 | vim.system({ "git", "clone", "--filter=blob:none", "--branch=stable", repo, install_path }, nil, function(out) 23 | vim.schedule(function() 24 | if out.code == 0 then 25 | api.nvim_create_autocmd("User", { 26 | once = true, 27 | pattern = "LazyDone", 28 | callback = function() 29 | echo("󰏔 Plugins installed successfully!") 30 | require("utils").close_buffers_matching("lazy", "filetype") 31 | end, 32 | }) 33 | 34 | echo(" lazy.nvim installed successfully!. Loading plugins ...") 35 | M.boot(install_path) 36 | else 37 | api.nvim_err_writeln("Error: Unable to install lazy.nvim and plugins") 38 | end 39 | end) 40 | end) 41 | end 42 | 43 | M.load_plugin_extensions = function() 44 | local plug_extension_dir = vim.g.stinvim_plugin_extension_dir or fn.stdpath("config") .. "/lua/extension" 45 | 46 | local files = fn.glob(plug_extension_dir .. "/*.lua", true, true) 47 | 48 | for _, file in ipairs(files) do 49 | local module = dofile(file) 50 | if module.enabled ~= false and type(module.entry) == "function" then module.entry() end 51 | end 52 | end 53 | 54 | function M.boot(install_path) 55 | local autocmd, augroup, schedule = api.nvim_create_autocmd, api.nvim_create_augroup, vim.schedule 56 | 57 | autocmd("CmdlineEnter", { 58 | once = true, 59 | callback = function() require("core.command") end, 60 | }) 61 | 62 | autocmd({ "UIEnter", "BufEnter", "BufNewFile" }, { 63 | group = augroup("StinvimLazyEvents", {}), 64 | callback = function(args) 65 | if args.event == "UIEnter" then vim.g.ui_entered = true end 66 | 67 | if 68 | vim.g.ui_entered 69 | and args.file ~= "" 70 | and api.nvim_get_option_value("buftype", { buf = args.buf }) ~= "nofile" 71 | then 72 | api.nvim_del_augroup_by_name("StinvimLazyEvents") 73 | schedule(function() 74 | api.nvim_exec_autocmds("User", { pattern = "FilePostLazyLoaded" }) 75 | schedule(function() api.nvim_exec_autocmds("Filetype", { buffer = args.buf }) end) 76 | end) 77 | end 78 | end, 79 | }) 80 | 81 | autocmd("BufEnter", { 82 | group = augroup("StinvimGitLazyLoad", {}), 83 | callback = function(args) 84 | if args.file ~= "" and api.nvim_get_option_value("buftype", { buf = args.buf }) ~= "nofile" then 85 | api.nvim_del_augroup_by_name("StinvimGitLazyLoad") 86 | vim.system({ "git", "-C", vim.fs.dirname(args.file), "rev-parse" }, nil, function(out) 87 | if out.code == 0 then 88 | schedule(function() api.nvim_exec_autocmds("User", { pattern = "GitLazyLoaded" }) end) 89 | end 90 | end) 91 | end 92 | end, 93 | }) 94 | 95 | vim.opt.rtp:prepend(install_path) 96 | 97 | M.load_plugin_extensions() 98 | 99 | require("plugins") 100 | end 101 | 102 | return M 103 | -------------------------------------------------------------------------------- /lua/core/command.lua: -------------------------------------------------------------------------------- 1 | local new_cmd = vim.api.nvim_create_user_command 2 | 3 | new_cmd("NvimHotReload", require("utils.reloader").hot_reload, { nargs = 0 }) 4 | new_cmd("NvimTouchPlugExtension", require("utils.plug-extension").touch_plug_extension, { nargs = 0 }) 5 | -------------------------------------------------------------------------------- /lua/core/nvimmap.lua: -------------------------------------------------------------------------------- 1 | local autocmd = vim.api.nvim_create_autocmd 2 | 3 | vim.schedule(function() -- any maps should work after neovim open 4 | local uv = vim.uv or vim.loop 5 | local api = vim.api 6 | local map = require("utils.mapper").map 7 | 8 | -- Remap for dealing with word wrap 9 | map({ "n", "x" }, "k", 'v:count || mode(1)[0:1] == "no" ? "k" : "gk"', 7) 10 | map({ "n", "x" }, "j", 'v:count || mode(1)[0:1] == "no" ? "j" : "gj"', 7) 11 | map({ "n", "v" }, "", 'v:count || mode(1)[0:1] == "no" ? "k" : "gk"', 7) 12 | map({ "n", "v" }, "", 'v:count || mode(1)[0:1] == "no" ? "j" : "gj"', 7) 13 | 14 | -- When you press i, automatically indent to the appropriate position 15 | -- map("n", "i", [[strlen(getline('.')) == 0 ? '_cc' : 'i']], 7) 16 | map("n", "i", function() 17 | if not api.nvim_get_option_value("buftype", { buf = 0 }) and api.nvim_get_current_line() == "" then 18 | local modified = api.nvim_get_option_value("modified", { buf = 0 }) 19 | api.nvim_input(api.nvim_replace_termcodes("_cc", true, true, true)) 20 | if not modified then vim.defer_fn(function() api.nvim_set_option_value("modified", false, { buf = 0 }) end, 1) end 21 | else 22 | api.nvim_command("startinsert") 23 | end 24 | end) 25 | 26 | -- Delete empty lines without writing to registers 27 | map("n", "dd", [[match(getline('.'), '^\s*$') != -1 ? '"_dd' : "dd"]], 7) 28 | map("n", "dx", "x") 29 | 30 | -- inspect colors 31 | map("n", "", "Inspect") 32 | 33 | -- Delete empty lines without writing to registers 34 | map("n", "x", [[col('.') == 1 && match(getline('.'), '^\s*$') != -1 ? '"_dd$' : '"_x']], 7) 35 | map("n", "X", [[col('.') == 1 && match(getline('.'), '^\s*$') != -1 ? '"_dd$' : '"_X']], 7) 36 | 37 | map("x", "P", "p") 38 | map("x", "p", 'p:let @+=@0:let @"=@0') 39 | 40 | -- Indent lines with tab in visual mode 41 | map("x", "", ">gv|") 42 | map("x", "", "", ">>_") 44 | map("n", "", "<<_") 45 | 46 | -- Better escape by jj 47 | do 48 | local waiting = false 49 | local first_pressed_time = 0 50 | local modified = false 51 | 52 | map({ "i", "c", "t" }, "j", function() 53 | local mode = api.nvim_get_mode().mode 54 | local now = uv.now() 55 | if not waiting then 56 | waiting = true 57 | first_pressed_time = now 58 | elseif now - first_pressed_time < vim.o.timeoutlen then -- waiting 59 | waiting = false 60 | if mode == "c" then 61 | api.nvim_input("") 62 | return "" 63 | elseif mode == "t" then 64 | return [[]] 65 | end 66 | api.nvim_feedkeys(api.nvim_replace_termcodes("", true, true, true), "n", false) 67 | if not modified then 68 | vim.defer_fn(function() api.nvim_set_option_value("modified", false, { buf = 0 }) end, 1) 69 | end 70 | return "" 71 | else -- waiting 72 | first_pressed_time = now -- new waiting 73 | end 74 | 75 | if mode == "c" then 76 | api.nvim_feedkeys("j", "n", true) 77 | return "" 78 | end 79 | 80 | modified = api.nvim_get_option_value("modified", { buf = 0 }) 81 | return "j" 82 | end, 7) 83 | end 84 | 85 | --Save file as the traditional way 86 | map({ "n", "i", "v", "c" }, "", "w", 2) 87 | 88 | --ctrl a to selected all text in file 89 | map({ "n", "i", "v" }, "", "normal! ggVG") 90 | 91 | --The arrow keys in the insert mode 92 | map("i", "", "") 93 | map("i", "", "") 94 | map("i", "", "") 95 | map("i", "", "") 96 | 97 | --Change the buffer 98 | map("n", "]b", "bnext") 99 | map("n", "[b", "bNext") 100 | 101 | --Go to the current path 102 | map({ "n", "v" }, "cd", "cd %:p:h:pwd", 3) 103 | 104 | --Close Buffer 105 | map({ "n", "v" }, "Q", function() 106 | local buf = api.nvim_get_current_buf() 107 | if api.nvim_buf_is_valid(buf) and api.nvim_get_option_value("modified", { buf = buf }) then 108 | require("utils.notify").warn("Buffer is modified, please save it first.") 109 | else 110 | api.nvim_buf_delete(buf, {}) 111 | end 112 | end) 113 | 114 | --Clean searching 115 | map({ "n", "v" }, "C", "noh:set ignorecase") 116 | 117 | --Resize Buffer 118 | map("n", "", function() require("smart-resizing").adjust_current_win_width(1, 2) end) 119 | map("n", "", function() require("smart-resizing").adjust_current_win_width(1, 1) end) 120 | 121 | map("n", "", function() require("smart-resizing").adjust_current_win_height(1, 2) end) 122 | map("n", "", function() require("smart-resizing").adjust_current_win_height(1, 1) end) 123 | 124 | --Make all windows (almost) equally high and wide 125 | map("n", "=", "=") 126 | 127 | --Change the layout to horizontal 128 | map("n", "gv", "tH", "Change the layout to vertical") 129 | 130 | --Change the layout to vertical 131 | map("n", "gh", "tK", "Change the layout to horizontally") 132 | 133 | -- Split horizontally 134 | map("n", "", "split") 135 | 136 | -- Split vertically 137 | map("n", "", "vsplit") 138 | 139 | --Move between windows 140 | map("n", "", "h") 141 | map("n", "", "j") 142 | map("n", "", "k") 143 | map("n", "", "l") 144 | 145 | --Swap up one row 146 | map("n", "", "m .-2==") 147 | map("v", "", "m '<-2gv=gv") 148 | 149 | --Swap down one row 150 | map("n", "", "m .+1==") 151 | map("v", "", "m '>+1gv=gv") 152 | 153 | autocmd("TermOpen", { 154 | callback = function(args) 155 | local bufnr = args.buf 156 | 157 | -- local map = require("utils.mapper").map 158 | local close_buf = function() api.nvim_buf_delete(bufnr, { force = true }) end 159 | local map1 = function(mode, key, map_to) map(mode, key, map_to, { buffer = bufnr }) end 160 | 161 | map1("n", "q", close_buf) 162 | map1("n", "Q", close_buf) 163 | map1({ "n", "t" }, "", close_buf) 164 | map1({ "n", "t" }, "", close_buf) 165 | 166 | map1("n", "i", "startinsert") 167 | 168 | map1("t", "", [[]]) 169 | 170 | map1("t", "", [[wincmd h]]) 171 | map1("t", "", [[wincmd j]]) 172 | map1("t", "", [[wincmd k]]) 173 | map1("t", "", [[wincmd l]]) 174 | map1("t", "", [[]]) 175 | end, 176 | }) 177 | 178 | autocmd("CmdlineEnter", { 179 | once = true, 180 | desc = "Make autoclose brackets, quotes in command mode", 181 | callback = function() 182 | -- local map = require("utils.mapper").map 183 | local bracket_pairs = { 184 | { "(", ")" }, 185 | { "[", "]" }, 186 | { "{", "}" }, 187 | { "<", ">" }, 188 | { "'", "'" }, 189 | { '"', '"' }, 190 | { "`", "`" }, 191 | } 192 | 193 | local feedks = api.nvim_feedkeys 194 | local replace_termcodes = api.nvim_replace_termcodes 195 | 196 | for _, pair in ipairs(bracket_pairs) do 197 | map( 198 | "c", 199 | pair[1], 200 | function() feedks(replace_termcodes(pair[1] .. pair[2] .. "", true, true, true), "n", true) end, 201 | 7 202 | ) 203 | end 204 | end, 205 | }) 206 | end) 207 | 208 | autocmd({ "BufWinEnter", "CmdwinEnter" }, { 209 | desc = "Make q close special buffers", 210 | callback = function(args) 211 | local buftype = vim.api.nvim_get_option_value("buftype", { buf = args.buf }) 212 | if args.event == "BufWinEnter" and not vim.list_contains({ "help", "nofile", "quickfix" }, buftype) then return end 213 | require("utils.mapper").map("n", "q", "close", { buffer = args.buf }) 214 | end, 215 | }) 216 | -------------------------------------------------------------------------------- /lua/core/option.lua: -------------------------------------------------------------------------------- 1 | local vim = vim 2 | local opt, o, g, fn = vim.opt, vim.o, vim.g, vim.fn 3 | 4 | -- Disable all providers by default, If we need a provider we can enable it by comment the line 5 | g.loaded_node_provider = 0 6 | g.loaded_perl_provider = 0 7 | g.loaded_python3_provider = 0 8 | g.loaded_ruby_provider = 0 9 | 10 | -- Uncomment the following lines to use a ruby and python provider 11 | -- g.ruby_host_prog = "~/.rbenv/versions/3.2.2/bin/neovim-ruby-host" 12 | -- g.python3_host_prog = "~/.venv/bin/python3" 13 | 14 | -- add binaries installed by mason.nvim to path 15 | vim.env.PATH = fn.stdpath("data") .. "/mason/bin" .. (fn.has("win32") ~= 0 and ";" or ":") .. vim.env.PATH 16 | 17 | -- File to identify project root 18 | g.stinvim_root_markers = { 19 | ".git", 20 | "package.json", -- npm 21 | "Cargo.toml", -- rust 22 | "stylua.toml", -- lua 23 | "lazy-lock.json", -- nvim config 24 | "build.zig", -- zig 25 | "gradlew", -- java 26 | "mvnw", -- java 27 | } 28 | 29 | g.stinvim_plugin_extension_dir = fn.stdpath("config") .. "/lua/extension" 30 | 31 | -- disable netrw for nvimtree 32 | g.loaded_netrw = 1 33 | g.loaded_netrwPlugin = 1 34 | 35 | g.skip_ts_context_commentstring_module = true 36 | 37 | -- cmp 38 | o.completeopt = "menu,menuone,noselect" 39 | 40 | -- disable nvim intro 41 | opt.shortmess:append("I") 42 | 43 | -- Don't show mode since we have a statusline 44 | o.showmode = false 45 | o.laststatus = 3 46 | 47 | -- fold 48 | o.foldenable = false -- Don't fold by default 49 | o.foldcolumn = "0" 50 | o.foldlevel = 99 51 | o.foldlevelstart = 99 52 | o.fillchars = "eob: ,fold: ,foldopen:,foldsep: ,foldclose:" 53 | 54 | -- Text width and wrap 55 | o.wrap = false 56 | opt.whichwrap:append("<>[]hl") 57 | o.linebreak = true 58 | o.formatexpr = "v:lua.require'conform'.formatexpr()" 59 | o.textwidth = 100 60 | 61 | --Line number 62 | o.number = true 63 | o.relativenumber = false 64 | -- o.numberwidth = 2 65 | -- o.cmdheight = 1 -- default 66 | 67 | --Encoding 68 | o.encoding = "utf-8" 69 | o.mouse = fn.isdirectory("/system") == 1 and "v" or "a" -- Enable mouse support on android system 70 | o.mousemoveevent = true 71 | 72 | -- o.incsearch = true -- default 73 | -- o.hlsearch = true -- default 74 | 75 | --Tabs & indentation 76 | o.tabstop = 2 77 | o.softtabstop = 2 78 | o.shiftwidth = 2 79 | o.expandtab = true 80 | -- o.autoindent = true -- default 81 | o.smartindent = true 82 | -- o.smarttab = true -- default 83 | -- o.backspace = "indent,eol,start" -- default 84 | 85 | --Undo file 86 | o.undofile = true 87 | 88 | --Update time 89 | o.updatetime = 300 --default 4000ms 90 | o.timeoutlen = 500 --default 1000ms (Shorten key timeout length a little bit for which-key) 91 | 92 | --No backup files 93 | o.swapfile = false 94 | o.backup = false 95 | o.writebackup = false 96 | 97 | --Search settings 98 | o.ignorecase = true 99 | --o.smartcase = true 100 | 101 | --Cursor line 102 | o.cursorline = true 103 | o.cursorcolumn = true 104 | 105 | --Appearance 106 | o.termguicolors = true 107 | -- o.background = "dark" -- default 108 | o.signcolumn = "yes" 109 | 110 | --List 111 | o.list = true 112 | -- tab = "▸ ", 113 | o.listchars = "tab: ,trail:·" 114 | 115 | --Clipboard 116 | o.clipboard = "unnamedplus" 117 | 118 | --Split window 119 | o.splitbelow = true 120 | o.splitright = true 121 | o.winminwidth = 5 122 | 123 | o.wildignore = 124 | "*.pyc,*.o,*.class,*.obj,*.svn,*.swp,*.swo,*.exe,*.dll,*.so,*.dylib,*.jar,*.zip,*.tar.gz,*.tar.bz2,*.rar,*.tar.xz,*.tar.zst,*.tar.lz,*.hg,*.DS_Store,*.min.*,node_modules" 125 | -------------------------------------------------------------------------------- /lua/core/plugmap.lua: -------------------------------------------------------------------------------- 1 | local api = vim.api 2 | local autocmd, augroup = api.nvim_create_autocmd, api.nvim_create_augroup 3 | local M = {} 4 | 5 | vim.schedule(function() 6 | local map = require("utils.mapper").map 7 | local load_mod = require("utils").load_mod 8 | 9 | ------------------------------ url-open ------------------------------ 10 | map({ "n", "v" }, "gx", "URLOpenUnderCursor", "Open URL under cursor") 11 | 12 | ------------------------------ nvimtree ------------------------------ 13 | map({ "n", "i", "v", "c" }, "", function() 14 | local filetype = api.nvim_get_option_value("filetype", { buf = 0 }) 15 | -- local buftype = api.nvim_buf_get_option(0, "buftype") 16 | if vim.tbl_contains({ "TelescopePrompt", "lazy", "mason" }, filetype) then 17 | vim.cmd.normal { "", bang = true } 18 | else 19 | pcall(api.nvim_command, "NvimTreeToggle") 20 | end 21 | end) 22 | 23 | ------------------------------ Telescope ------------------------------ 24 | map({ "n", "i", "v" }, "", "Telescope find_files") 25 | map("n", "fb", "Telescope buffers") 26 | map("n", "fh", "Telescope help_tags") 27 | 28 | map("n", "fg", "Telescope live_grep", "Telescope find string") 29 | map("n", "", "Telescope live_grep", "Telescope find string") 30 | map("n", "fw", "Telescope grep_string", "Find word under cursor") 31 | 32 | ------------------------------ Todo-comments ------------------------------ 33 | map("n", "ft", "TodoTelescope", "Telescope find todo comments") 34 | 35 | map("n", "fd", "Telescope diagnostics") 36 | map("n", "fc", "Telescope command_history", "Find command history") 37 | 38 | ------------------------------ Todo-comments ------------------------------ 39 | map("n", "ft", "TodoTelescope", "Find todo comments") 40 | 41 | ------------------------------ Git conflict ------------------------------ 42 | map("n", "qfc", "GitConflictListQf", "Git conflict quickfix") 43 | 44 | map("n", "[t", function() 45 | load_mod("todo-comments", function(todo_comments) todo_comments.jump_prev() end) 46 | end, "Todo comment prev") 47 | 48 | map("n", "]t", function() 49 | load_mod("todo-comments", function(todo_comments) todo_comments.jump_next() end) 50 | end, "Todo comment next") 51 | 52 | map("n", "[T", function() 53 | load_mod("todo-comments", function(todo_comments) todo_comments.jump_prev { keywords = { "ERROR", "WARNING" } } end) 54 | end, "Todo comment prev error or warning") 55 | 56 | map("n", "]T", function() 57 | load_mod("todo-comments", function(todo_comments) todo_comments.jump_next { keywords = { "ERROR", "WARNING" } } end) 58 | end, "Todo comment next error or warning") 59 | 60 | ------------------------------ ccc ------------------------------ 61 | map({ "n", "i", "v" }, "", "CccPick", "Color picker") 62 | 63 | ------------------------------ ufo ------------------------------ 64 | map("n", "zR", "lua require('ufo').openAllFolds()", "Open all folds") 65 | map("n", "zr", "lua require('ufo').openFoldsExceptKinds()", "Open folds except kind") 66 | map("n", "zM", "lua require('ufo').closeAllFolds()", "Close all folds") 67 | map("n", "zm", "lua require('ufo').closeFoldsWith()", "Close folds with kind") 68 | 69 | ------------------------------ Bufferline ------------------------------ 70 | -- map("n", "", "exe 'BufferLineGoToBuffer ' . v:count1") 71 | 72 | ------------------------------ Markdown preview ------------------------------ 73 | map("n", "pm", "MarkdownPreviewToggle", "Toggle markdown preview") 74 | 75 | ------------------------------ wilder ------------------------------ 76 | -- map("c", "", "has('wilder') && wilder#in_context() ? wilder#next() : ''", 6) 77 | -- map("c", "", "has('wilder') && wilder#in_context() ? wilder#previous() : ''", 6) 78 | -- 79 | 80 | --------------------------------------- dap --------------------------------------- 81 | map("n", "du", function() 82 | load_mod("dapui", function(dapui) dapui.toggle() end) 83 | end, "Toggle DAP UI") 84 | map("n", "db", function() 85 | load_mod("dap", function(dap) dap.toggle_breakpoint() end) 86 | end, "Toggle breakpoint") 87 | map("n", "di", function() 88 | load_mod("dap", function(dap) dap.step_into() end) 89 | end, "Step into") 90 | map("n", "do", function() 91 | load_mod("dap", function(dap) dap.step_over() end) 92 | end, "Step over") 93 | map("n", "dc", function() 94 | load_mod("dap", function(dap) dap.continue() end) 95 | end, "Continue or start debugging") 96 | map("n", "dd", function() 97 | load_mod("dap", function(dap) 98 | dap.disconnect() 99 | dap.close() 100 | end) 101 | end, "Disconnect from debugger") 102 | map("n", "", function() 103 | load_mod("dap", function(dap) dap.step_into() end) 104 | end, "Step into") 105 | map("n", "", function() 106 | load_mod("dap", function(dap) dap.step_over() end) 107 | end, "Step over") 108 | map("n", "", function() 109 | load_mod("dap", function(dap) dap.continue() end) 110 | end, "Continue or start debugging") 111 | map("n", "", function() 112 | load_mod("dap", function(dap) 113 | dap.disconnect() 114 | dap.close() 115 | end) 116 | end, "Disconnect from debugger") 117 | map("n", "dr", function() 118 | load_mod("dap", function(dap) dap.repl.open() end) 119 | end, "Open REPL") 120 | map("n", "dl", function() 121 | load_mod("dap", function(dap) dap.run_last() end) 122 | end, "Run last") 123 | 124 | map({ "n", "v" }, "dh", function() 125 | load_mod("dap.ui.widgets", function(widgets) widgets.hover() end) 126 | end, "Hover widgets") 127 | map({ "n", "v" }, "dp", function() 128 | load_mod("dap.ui.widgets", function(widgets) widgets.preview() end) 129 | end, "Preview widgets") 130 | map("n", "df", function() 131 | load_mod("dap.ui.widgets", function(widgets) widgets.centered_float(widgets.frames) end) 132 | end, "Frames") 133 | map("n", "ds", function() 134 | load_mod("dap.ui.widgets", function(widgets) widgets.centered_float(widgets.scopes) end) 135 | end, "Scopes") 136 | end) 137 | 138 | autocmd("LspAttach", { 139 | group = augroup("Lspsaga-mappings", { clear = true }), 140 | desc = "Lspsaga actions", 141 | once = true, 142 | callback = function() 143 | local map = require("utils.mapper").map 144 | local load_mod = require("utils").load_mod 145 | 146 | map("n", "gf", "Lspsaga finder") 147 | 148 | map({ "n", "v" }, "sa", "Lspsaga code_action") 149 | 150 | map("n", "gr", "Lspsaga rename") 151 | 152 | -- map("n", "gr", "Lspsaga rename ++project") 153 | 154 | map("n", "gp", "Lspsaga peek_definition") 155 | 156 | map("n", "gd", "Lspsaga goto_definition") 157 | 158 | map("n", "gt", "Lspsaga peek_type_definition") 159 | 160 | map("n", "K", function() 161 | local status_ok, ufo = pcall(require, "ufo") 162 | local winid = status_ok and ufo.peekFoldedLinesUnderCursor() or nil 163 | if not winid then api.nvim_command("Lspsaga hover_doc") end 164 | end) 165 | 166 | map("n", "gl", "Lspsaga show_line_diagnostics ++unfocus") 167 | 168 | map("n", "sb", "Lspsaga show_buf_diagnostics") 169 | 170 | map("n", "sw", "Lspsaga show_workspace_diagnostics") 171 | 172 | map("n", "sc", "Lspsaga show_cursor_diagnostics") 173 | 174 | map("n", "[d", "Lspsaga diagnostic_jump_prev") 175 | map("n", "]d", "Lspsaga diagnostic_jump_next") 176 | 177 | map("n", "[e", function() 178 | load_mod("lspsaga.diagnostic", function(diagnostic) diagnostic:goto_prev { severity = 1 } end) 179 | end, "Lspsaga diagnostic_jump_prev error") 180 | map("n", "]e", function() 181 | load_mod("lspsaga.diagnostic", function(diagnostic) diagnostic:goto_next { severity = 1 } end) 182 | end, "Lspsaga diagnostic_jump_next error") 183 | 184 | map("n", "so", "Lspsaga outline") 185 | 186 | -- -- Call hierarchy 187 | -- map("n", "ci", "Lspsaga incoming_calls") 188 | -- map("n", "co", "Lspsaga outgoing_calls") 189 | end, 190 | }) 191 | 192 | M.gitsigns = function(bufnr) 193 | local map = require("utils.mapper").map 194 | local gs = require("gitsigns") 195 | 196 | local map1 = function(mode, key, map_to, desc) map(mode, key, map_to, { buffer = bufnr, desc = desc }) end 197 | 198 | -- Navigation 199 | map1("n", "]g", function() 200 | if vim.wo.diff then 201 | vim.cmd.normal { "]g", bang = true } 202 | else 203 | gs.nav_hunk("next") 204 | end 205 | end, "Gitsigns next hunk") 206 | map("n", "[g", function() 207 | if vim.wo.diff then 208 | vim.cmd.normal { "[g", bang = true } 209 | else 210 | gs.nav_hunk("prev") 211 | end 212 | end, "Gitsigns previous hunk") 213 | 214 | map1("n", "gs", gs.stage_hunk, "Gitsigns stage hunk") 215 | map1("v", "gs", function() gs.stage_hunk { vim.fn.line("."), vim.fn.line("v") } end, "Gitsigns stage hunk") 216 | map1("n", "gr", gs.reset_hunk, "Reset hunk") 217 | map1("v", "gr", function() gs.reset_hunk { vim.fn.line("."), vim.fn.line("v") } end, "Gitsigns reset hunk") 218 | map1("n", "gu", gs.undo_stage_hunk, "Gitsigns undo stage hunk") 219 | map1("n", "gR", gs.reset_buffer, "Gitsigns reset buffer") 220 | map1("n", "gp", gs.preview_hunk, "Gitsigns preview hunk") 221 | map1("n", "gb", gs.toggle_current_line_blame, "Gitsigns blame line") 222 | map1("n", "gd", gs.diffthis, "Gitsigns diff this") 223 | map1("n", "gD", function() gs.diffthis("~") end, "Gitsigns diff this") 224 | end 225 | 226 | return M 227 | -------------------------------------------------------------------------------- /lua/extension/copilot.lua: -------------------------------------------------------------------------------- 1 | local M = { 2 | enabled = true, 3 | } 4 | 5 | local is_authenticated = function() 6 | return vim.fn.filereadable(vim.fn.expand("$HOME") .. "/.config/github-copilot/hosts.json") == 1 7 | end 8 | 9 | M.entry = function() 10 | local id 11 | id = vim.api.nvim_create_autocmd("User", { 12 | pattern = "LazyLoad", 13 | desc = "Automatic auth for copilot", 14 | callback = function(args) 15 | if args.data == "copilot.lua" then 16 | vim.api.nvim_del_autocmd(id) 17 | vim.schedule(function() 18 | if not is_authenticated() then vim.api.nvim_command("Copilot auth") end 19 | end) 20 | end 21 | end, 22 | }) 23 | end 24 | 25 | return M 26 | -------------------------------------------------------------------------------- /lua/extension/git-conflict.lua: -------------------------------------------------------------------------------- 1 | local M = { 2 | enabled = true, 3 | } 4 | 5 | M.entry = function() 6 | vim.api.nvim_create_autocmd("User", { 7 | pattern = "GitConflictDetected", 8 | callback = function() 9 | require("utils.notify").warn("Conflict detected in " .. vim.fn.expand("")) 10 | end, 11 | }) 12 | end 13 | 14 | return M 15 | -------------------------------------------------------------------------------- /lua/extension/lualine.lua: -------------------------------------------------------------------------------- 1 | local M = { 2 | enabled = false, 3 | } 4 | 5 | M.entry = function() 6 | local id 7 | id = vim.api.nvim_create_autocmd("User", { 8 | desc = "Auto enable showmode if the window is small", 9 | pattern = "LazyLoad", 10 | callback = function(args) 11 | if args.data == "lualine.nvim" then 12 | vim.api.nvim_del_autocmd(id) 13 | if vim.o.columns > 70 then 14 | vim.opt.showmode = false 15 | else 16 | vim.opt.showmode = true 17 | end 18 | end 19 | end, 20 | }) 21 | end 22 | 23 | return M 24 | -------------------------------------------------------------------------------- /lua/extension/mason.lua: -------------------------------------------------------------------------------- 1 | local vim, require = vim, require 2 | local api, fn, schedule = vim.api, vim.fn, vim.schedule 3 | 4 | local MASONRC_FILE = fn.stdpath("config") .. "/.masonrc.json" 5 | local PACKAGE_DIR = fn.stdpath("data") .. "/mason/packages" 6 | 7 | local M = { 8 | enabled = true, 9 | } 10 | 11 | local get_ensured_packages = function() 12 | local rcfile = io.open(MASONRC_FILE, "r") 13 | if rcfile then 14 | local json = rcfile:read("*all") 15 | rcfile:close() 16 | return vim.json.decode(json) 17 | end 18 | local ensure_installed = require("mason.settings").current.ensure_installed 19 | return type(ensure_installed) == "table" and ensure_installed or {} 20 | end 21 | 22 | local get_installed_packages = function() 23 | local installed_packages = {} 24 | 25 | local package_paths = fn.glob( 26 | ( 27 | fn.isdirectory(PACKAGE_DIR) == 1 and PACKAGE_DIR 28 | or require("mason.settings").current.install_root_dir .. "/packages" 29 | ) .. "/*", 30 | true, 31 | true 32 | ) 33 | 34 | for i, path in ipairs(package_paths) do 35 | installed_packages[i] = fn.fnamemodify(path, ":t") 36 | end 37 | return installed_packages 38 | end 39 | 40 | local caculate_pkgs = function() 41 | local ensure_pkgs = get_ensured_packages() 42 | local installed_pkgs = get_installed_packages() 43 | 44 | local ensure_pkgs_size = #ensure_pkgs 45 | local installed_pkgs_size = #installed_pkgs 46 | 47 | if ensure_pkgs_size == 0 or installed_pkgs_size == 0 then 48 | return installed_pkgs, installed_pkgs_size, ensure_pkgs, ensure_pkgs_size 49 | end 50 | 51 | local ensure_pkgs_map = {} 52 | for i = 1, ensure_pkgs_size do 53 | ensure_pkgs_map[ensure_pkgs[i]] = true 54 | end 55 | 56 | local pkgs_to_remove = {} 57 | local pkgs_to_remove_size = 0 58 | 59 | for i = 1, installed_pkgs_size do 60 | local pkg = installed_pkgs[i] 61 | if not ensure_pkgs_map[pkg] then 62 | pkgs_to_remove_size = pkgs_to_remove_size + 1 63 | pkgs_to_remove[pkgs_to_remove_size] = pkg 64 | else 65 | ensure_pkgs_map[pkg] = nil 66 | end 67 | end 68 | 69 | local pkgs_to_install = {} 70 | local pkgs_to_install_size = 0 71 | 72 | for pkg, _ in pairs(ensure_pkgs_map) do 73 | pkgs_to_install_size = pkgs_to_install_size + 1 74 | pkgs_to_install[pkgs_to_install_size] = pkg 75 | end 76 | 77 | return pkgs_to_remove, pkgs_to_remove_size, pkgs_to_install, pkgs_to_install_size 78 | end 79 | 80 | --- Update all packages 81 | --- @param exclued ? table packages to be excluded from updating process. Key is package name and value is true 82 | --- @param ui ? boolean open ui when updating packages 83 | local update_pkgs = function(exclued, ui) 84 | schedule(function() 85 | require("utils").load_mod("mason-registry", function(registry) 86 | registry.update(vim.schedule_wrap(function(success, _) 87 | local installed_pkgs = registry.get_installed_packages() 88 | if success then 89 | if ui then require("mason.ui").open() end 90 | for _, pkg in ipairs(installed_pkgs) do 91 | local pkg_name = pkg.name 92 | if not exclued or not exclued[pkg_name] then 93 | pkg:check_new_version(function(update_available, version) 94 | if update_available then 95 | local latest_version = version.latest_version 96 | require("utils.notify").info("Updating " .. pkg_name .. "to" .. latest_version, { title = "Mason" }) 97 | pkg:install():on( 98 | "install:success", 99 | function() 100 | require("utils.notify").info( 101 | "Mason: Update package " .. pkg_name .. "to version " .. latest_version .. " completed", 102 | { title = "Mason" } 103 | ) 104 | end 105 | ) 106 | return 107 | end 108 | end) 109 | end 110 | end 111 | else 112 | require("utils.notify").error("Failed to update registries", { title = "Mason" }) 113 | end 114 | end)) 115 | end) 116 | end) 117 | end 118 | 119 | --- @param package_names string[] 120 | --- @return string[] valid package names 121 | --- @return number size of valid packages 122 | local filter_valid_packages = function(package_names) 123 | local registry = require("mason-registry") 124 | local Func = require("mason-core.functional") 125 | local Package = require("mason-core.package") 126 | 127 | local size = 0 128 | 129 | return Func.filter(function(pkg_specifier) 130 | local package_name = Package.Parse(pkg_specifier) 131 | local ok = pcall(registry.get_package, package_name) 132 | if ok then 133 | size = size + 1 134 | return true 135 | end 136 | require("utils.notify").error("Mason: " .. pkg_specifier .. " is not a valid package.", { title = "Mason" }) 137 | return false 138 | end)(package_names), 139 | size 140 | end 141 | 142 | --- Install packagges without any ui open 143 | --- @param package_names string[] packages to be installed 144 | --- @param cb ? function Args: name, all_completed The callback function will be called when each package is installed successfully 145 | --- @param ui ? boolean open ui when installing packages 146 | local MasonInstall = function(package_names, cb, ui) 147 | return require("utils").load_mod("mason-registry", function(registry) 148 | if ui then require("mason.ui").open() end 149 | local Func = require("mason-core.functional") 150 | local Package = require("mason-core.package") 151 | 152 | local valid_packages, valid_packages_size 153 | 154 | registry:on("package:install:success", function(pkg) 155 | local pkg_name = pkg.name 156 | require("utils.notify").info("Mason: Install package " .. pkg_name .. " completed", { title = "Mason" }) 157 | valid_packages_size = valid_packages_size - 1 158 | if type(cb) == "function" then cb(pkg_name, valid_packages_size == 0) end 159 | end) 160 | 161 | registry.refresh(function() 162 | local install_packages = Func.map(function(pkg_specifier) 163 | local package_name, version = Package.Parse(pkg_specifier) 164 | local pkg = registry.get_package(package_name) 165 | return pkg:install { 166 | version = version, 167 | force = true, 168 | strict = true, 169 | debug = false, 170 | } 171 | end) 172 | valid_packages, valid_packages_size = filter_valid_packages(package_names) 173 | install_packages(valid_packages) 174 | end) 175 | end) 176 | end 177 | 178 | --- Uninstall packagges without any ui open 179 | --- @param package_names string[] packages to be uninstalled 180 | --- @param cb ? function Args: name, all_completed The callback function will be called when each package is uninstalled 181 | --- @param ui ? boolean open ui when installing packages 182 | local function MasonUninstall(package_names, cb, ui) 183 | return require("utils").load_mod("mason-registry", function(registry) 184 | local Func = require("mason-core.functional") 185 | local valid_packages, valid_packages_size = filter_valid_packages(package_names) 186 | if valid_packages_size > 0 then 187 | registry:on("package:uninstall:success", function(pkg) 188 | local pkg_name = pkg.name 189 | vim.defer_fn( 190 | function() 191 | require("utils.notify").info("Mason: Uninstall package " .. pkg_name .. " completed", { title = "Mason" }) 192 | end, 193 | valid_packages_size * 500 194 | ) 195 | valid_packages_size = valid_packages_size - 1 196 | if type(cb) == "function" then cb(pkg_name, valid_packages_size == 0) end 197 | end) 198 | 199 | Func.each(function(package_name) 200 | local pkg = registry.get_package(package_name) 201 | pkg:uninstall() 202 | end, valid_packages) 203 | if ui then require("mason.ui").open() end 204 | end 205 | end) 206 | end 207 | 208 | local clean_pkgs = function(ui) 209 | schedule(function() 210 | MasonUninstall( 211 | require("utils.tbl").find_unique_array_items(get_installed_packages(), get_ensured_packages()), 212 | function(_, all_completed) 213 | if all_completed then require("utils.notify").info("Mason: Cleaned packages", { title = "Mason" }) end 214 | end, 215 | ui ~= false 216 | ) 217 | end) 218 | end 219 | 220 | local sync_pkgs = function(ui) 221 | schedule(function() 222 | local pkgs_to_remove, pkgs_to_remove_size, pkgs_to_install, pkgs_to_install_size = caculate_pkgs() 223 | if pkgs_to_remove_size == 0 and pkgs_to_install_size == 0 then return end 224 | 225 | if require("mason.settings").current.auto_sync then MasonUninstall(pkgs_to_remove, nil, ui ~= false) end 226 | schedule(function() 227 | local exclued_update_pkgs = {} 228 | MasonInstall(pkgs_to_install, function(pkg_name, all_completed) 229 | exclued_update_pkgs[pkg_name] = true 230 | if all_completed then update_pkgs(exclued_update_pkgs) end 231 | end, ui ~= false) 232 | end) 233 | end) 234 | end 235 | 236 | -------------------- Auto commands -------------------- 237 | M.entry = function() 238 | api.nvim_create_autocmd("User", { 239 | once = true, 240 | pattern = { "VeryLazy", "LazyVimStarted" }, 241 | callback = function() sync_pkgs(false) end, 242 | }) 243 | api.nvim_create_user_command("MasonSyncPackages", sync_pkgs, { nargs = 0 }) 244 | api.nvim_create_user_command("MasonUpdatePackages", update_pkgs, { nargs = 0 }) 245 | api.nvim_create_user_command("MasonCleanPackages", clean_pkgs, { nargs = 0 }) 246 | end 247 | 248 | return M 249 | -------------------------------------------------------------------------------- /lua/language/vietnamese.lua: -------------------------------------------------------------------------------- 1 | -- local maps = { 2 | 3 | -- } 4 | -------------------------------------------------------------------------------- /lua/plugins/init.lua: -------------------------------------------------------------------------------- 1 | local require = require 2 | 3 | local plugins = { 4 | --------------------------------------------------- Theme --------------------------------------------------- 5 | --- 6 | { 7 | "sontungexpt/witch", 8 | priority = 1000, 9 | lazy = false, 10 | -- opts = require("config.witch"), 11 | opts = {}, 12 | }, 13 | 14 | { 15 | "sontungexpt/sttusline", 16 | branch = "develop", 17 | dependencies = { 18 | "nvim-tree/nvim-web-devicons", 19 | }, 20 | event = "User FilePostLazyLoaded", 21 | opts = {}, 22 | }, 23 | 24 | { 25 | "sontungexpt/smart-resizing", 26 | }, 27 | 28 | -- { 29 | -- "akinsho/bufferline.nvim", 30 | -- dependencies = { 31 | -- "nvim-tree/nvim-web-devicons", 32 | -- }, 33 | -- event = "User FilePostLazyLoaded", 34 | -- opts = require("config.bufferline"), 35 | -- config = function(_, opts) require("bufferline").setup(opts) end, 36 | -- }, 37 | 38 | --------------------------------------------------- Syntax --------------------------------------------------- 39 | { 40 | "nvim-treesitter/nvim-treesitter", 41 | dependencies = { 42 | "HiPhish/rainbow-delimiters.nvim", 43 | }, 44 | event = { 45 | "CursorHold", 46 | "CursorMoved", 47 | "User FilePostLazyLoaded", 48 | }, 49 | cmd = { 50 | "TSInstall", 51 | "TSBufEnable", 52 | "TSEnable", 53 | "TSBufDisable", 54 | "TSModuleInfo", 55 | "TSInstallFromGrammar", 56 | }, 57 | build = ":TSUpdate", 58 | main = "nvim-treesitter.configs", 59 | opts = function() return require("config.nvim-treesitter") end, 60 | }, 61 | 62 | -- { 63 | -- "windwp/nvim-ts-autotag", 64 | -- dependencies = { 65 | -- "nvim-treesitter/nvim-treesitter", 66 | -- }, 67 | -- ft = { 68 | -- "html", 69 | -- "vue", 70 | -- "tsx", 71 | -- "jsx", 72 | -- "svelte", 73 | -- "javascript", 74 | -- "typescript", 75 | -- "javascriptreact", 76 | -- "typescriptreact", 77 | -- }, 78 | -- }, 79 | 80 | -- { 81 | -- "VebbNix/lf-vim", 82 | -- ft = "lf", 83 | -- }, 84 | 85 | ------------------------------------ Editor ------------------------------------ 86 | { 87 | "sontungexpt/stcursorword", 88 | event = { "CursorHold", "CursorMoved" }, 89 | main = "stcursorword", 90 | opts = {}, 91 | }, 92 | 93 | { 94 | "sontungexpt/url-open", 95 | branch = "mini", 96 | cmd = "URLOpenUnderCursor", 97 | event = { "CursorHold", "CursorMoved" }, 98 | main = "url-open", 99 | opts = {}, 100 | }, 101 | 102 | -- { 103 | -- "sontungexpt/buffer-closer", 104 | -- cmd = "BufferCloserRetire", 105 | -- event = { "BufAdd", "FocusLost", "FocusGained" }, 106 | -- config = function(_, opts) require("buffer-closer").setup {} end, 107 | -- }, 108 | 109 | { 110 | "akinsho/toggleterm.nvim", 111 | cmd = { "ToggleTerm", "ToggleTermToggleAll", "TermExec" }, 112 | keys = "", 113 | main = "toggleterm", 114 | opts = function() return require("config.toggleterm") end, 115 | }, 116 | 117 | { 118 | "kylechui/nvim-surround", 119 | keys = { "ys", "ds", "cs" }, 120 | opts = {}, 121 | }, 122 | 123 | { 124 | "windwp/nvim-autopairs", 125 | event = "InsertEnter", 126 | -- opts = function() return require("config.nvim-autopairs") end, 127 | config = function(_, opts) 128 | require("nvim-autopairs").setup(opts) 129 | local cmp_status_ok, cmp = pcall(require, "cmp") 130 | local cmp_autopairs_status_ok, cmp_autopairs = pcall(require, "nvim-autopairs.completion.cmp") 131 | if cmp_status_ok and cmp_autopairs_status_ok then 132 | cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done { map_char = { tex = "" } }) 133 | end 134 | end, 135 | }, 136 | 137 | -- { 138 | -- "gelguy/wilder.nvim", 139 | -- dependencies = { 140 | -- "romgrk/fzy-lua-native", 141 | -- }, 142 | -- build = ":UpdateRemotePlugins", 143 | -- event = "CmdlineEnter", 144 | -- config = function() require("config.wilder") end, 145 | -- }, 146 | 147 | { 148 | "lukas-reineke/indent-blankline.nvim", 149 | main = "ibl", 150 | event = { "CursorHold", "CursorMoved" }, 151 | dependencies = { 152 | "HiPhish/rainbow-delimiters.nvim", 153 | }, 154 | opts = { 155 | indent = { 156 | char = "│", 157 | }, 158 | scope = { 159 | highlight = { 160 | "RainbowDelimiterRed", 161 | "RainbowDelimiterYellow", 162 | "RainbowDelimiterBlue", 163 | "RainbowDelimiterOrange", 164 | "RainbowDelimiterGreen", 165 | "RainbowDelimiterViolet", 166 | "RainbowDelimiterCyan", 167 | }, 168 | char = "│", 169 | }, 170 | }, 171 | config = function(_, opts) 172 | local hooks = require("ibl.hooks") 173 | hooks.register(hooks.type.SCOPE_HIGHLIGHT, hooks.builtin.scope_highlight_from_extmark) 174 | require("ibl").setup(opts) 175 | end, 176 | }, 177 | 178 | { 179 | "brenoprata10/nvim-highlight-colors", 180 | cmd = "HighlightColors", 181 | event = { "CursorHold", "CursorMoved" }, 182 | opts = function() return require("config.highlight-colors") end, 183 | config = function(_, opts) 184 | require("nvim-highlight-colors").setup(opts) 185 | vim.api.nvim_command("HighlightColors On") 186 | end, 187 | }, 188 | 189 | { 190 | "uga-rosa/ccc.nvim", 191 | cmd = "CccPick", 192 | main = "ccc", 193 | opts = {}, 194 | }, 195 | 196 | { 197 | "iamcco/markdown-preview.nvim", 198 | cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" }, 199 | ft = { "markdown" }, 200 | build = function() 201 | require("lazy").load { plugins = { "markdown-preview.nvim" } } 202 | vim.fn["mkdp#util#install"]() 203 | end, 204 | config = function() vim.g.mkdp_auto_close = 1 end, 205 | }, 206 | 207 | { 208 | "folke/which-key.nvim", 209 | keys = { "", "[", "]", '"', "'", "c", "v", "g", "d", "z" }, 210 | main = "which-key", 211 | opts = function() return require("config.whichkey") end, 212 | }, 213 | 214 | { 215 | "kevinhwang91/nvim-ufo", 216 | keys = { 217 | { "zc", mode = "n", desc = "Fold current line" }, 218 | { "zo", mode = "n", desc = "Unfold current line" }, 219 | { "za", mode = "n", desc = "Toggle fold current line" }, 220 | { "zA", mode = "n", desc = "Toggle fold all lines" }, 221 | { "zr", mode = "n", desc = "Unfold all lines" }, 222 | { "zR", mode = "n", desc = "Fold all lines" }, 223 | }, 224 | dependencies = "kevinhwang91/promise-async", 225 | opts = function() 226 | vim.o.foldenable = true -- enable folding when plugin is loaded 227 | return require("config.nvim-ufo") 228 | end, 229 | }, 230 | 231 | -- { 232 | -- "zbirenbaum/copilot.lua", 233 | -- cmd = "Copilot", 234 | -- event = "InsertEnter", 235 | -- opts = function() return require("config.copilot") end, 236 | -- config = function(_, opts) require("copilot").setup(opts) end, 237 | -- }, 238 | 239 | { 240 | "Exafunction/codeium.vim", 241 | keys = "", 242 | event = "InsertEnter", 243 | cmd = "Codeium", 244 | config = function() 245 | if vim.fn.filereadable(vim.fn.expand("$HOME") .. "/.codeium/config.json") == 0 then 246 | vim.api.nvim_command("Codeium Auth") 247 | end 248 | 249 | vim.g.codeium_no_map_tab = true 250 | local map = require("utils.mapper").map 251 | map("i", "", "codeium#Accept()", 7) 252 | map({ "n", "i" }, "", "codeium#Chat()", 7) 253 | end, 254 | }, 255 | 256 | --------------------------------------------------- File Explorer --------------------------------------------------- 257 | { 258 | "nvim-tree/nvim-tree.lua", 259 | dependencies = { 260 | "nvim-tree/nvim-web-devicons", 261 | }, 262 | cmd = { 263 | "NvimTreeToggle", 264 | "NvimTreeFocus", 265 | "NvimTreeOpen", 266 | }, 267 | opts = function() return require("config.nvim-tree") end, 268 | config = function(_, opts) require("nvim-tree").setup(opts) end, 269 | }, 270 | 271 | { 272 | "nvim-telescope/telescope.nvim", 273 | cmd = "Telescope", 274 | dependencies = { 275 | "nvim-tree/nvim-web-devicons", 276 | "nvim-lua/plenary.nvim", 277 | 278 | -- extensions 279 | -- "nvim-telescope/telescope-media-files.nvim", 280 | }, 281 | opts = function() return require("config.telescope") end, 282 | config = function(_, opts) 283 | local telescope = require("telescope") 284 | telescope.setup(opts) 285 | for _, ext in ipairs(opts.extension_list) do 286 | telescope.load_extension(ext) 287 | end 288 | end, 289 | }, 290 | 291 | --------------------------------------------------- Comments --------------------------------------------------- 292 | { 293 | "numToStr/Comment.nvim", 294 | dependencies = { 295 | { 296 | "JoosepAlviste/nvim-ts-context-commentstring", 297 | dependencies = { 298 | "nvim-treesitter/nvim-treesitter", 299 | }, 300 | opts = { 301 | enable_autocmd = false, 302 | }, 303 | config = function(_, opts) require("ts_context_commentstring").setup(opts) end, 304 | }, 305 | }, 306 | keys = { 307 | { "gcc", mode = "n", desc = "Comment toggle current line" }, 308 | { "gc", mode = { "n", "o" }, desc = "Comment toggle linewise" }, 309 | { "gc", mode = "x", desc = "Comment toggle linewise (visual)" }, 310 | { "gbc", mode = "n", desc = "Comment toggle current block" }, 311 | { "gb", mode = { "n", "o" }, desc = "Comment toggle blockwise" }, 312 | { "gb", mode = "x", desc = "Comment toggle blockwise (visual)" }, 313 | }, 314 | -- because prehook is call so it need to return from a function 315 | main = "Comment", 316 | opts = function() return require("config.comment.Comment") end, 317 | }, 318 | 319 | { 320 | "folke/todo-comments.nvim", 321 | cmd = { "TodoQuickFix", "TodoTelescope" }, 322 | dependencies = { 323 | "nvim-lua/plenary.nvim", 324 | }, 325 | event = { "CursorHold", "CmdlineEnter", "CursorMoved" }, 326 | -- opts = require("config.comment.todo-comments"), 327 | main = "todo-comments", 328 | opts = {}, 329 | }, 330 | 331 | --------------------------------------------------- Git supporter --------------------------------------------------- 332 | { 333 | "lewis6991/gitsigns.nvim", 334 | event = "User GitLazyLoaded", 335 | main = "gitsigns", 336 | opts = function() return require("config.git.gitsigns") end, 337 | }, 338 | 339 | { 340 | "akinsho/git-conflict.nvim", 341 | event = "User GitLazyLoaded", 342 | main = "git-conflict", 343 | opts = function() return require("config.git.git-conflict") end, 344 | }, 345 | 346 | --------------------------------------------------- LSP --------------------------------------------------- 347 | { 348 | "neovim/nvim-lspconfig", 349 | event = "User FilePostLazyLoaded", 350 | config = function() require("config.lsp.lspconfig") end, 351 | }, 352 | 353 | { 354 | "sontungexpt/better-diagnostic-virtual-text", 355 | }, 356 | 357 | { 358 | "mfussenegger/nvim-jdtls", 359 | ft = "java", 360 | -- config is in ftplugin/java.lua 361 | }, 362 | 363 | { 364 | "mrcjkb/rustaceanvim", 365 | ft = "rust", 366 | -- config is in ftplugin/rust.lua 367 | }, 368 | 369 | { 370 | "akinsho/flutter-tools.nvim", 371 | ft = "dart", 372 | event = "BufReadPost */pubspec.yaml", 373 | dependencies = { 374 | "nvim-lua/plenary.nvim", 375 | "stevearc/dressing.nvim", -- optional for vim.ui.select 376 | }, 377 | main = "flutter-tools", 378 | opts = function() return require("config.flutter-tools") end, 379 | }, 380 | 381 | { 382 | "glepnir/lspsaga.nvim", 383 | cmd = "Lspsaga", 384 | dependencies = { 385 | "neovim/nvim-lspconfig", 386 | "nvim-tree/nvim-web-devicons", 387 | 388 | --Please make sure you install markdown and markdown_inline parser 389 | "nvim-treesitter/nvim-treesitter", 390 | }, 391 | main = "lspsaga", 392 | opts = function() return require("config.lsp.lspsaga") end, 393 | }, 394 | 395 | { 396 | "williamboman/mason.nvim", 397 | build = ":MasonUpdate", 398 | cmd = { 399 | "Mason", 400 | "MasonLog", 401 | "MasonUpdate", 402 | "MasonInstall", 403 | "MasonUninstall", 404 | "MasonUninstallAll", 405 | }, 406 | main = "mason", 407 | opts = function() return require("config.mason") end, 408 | }, 409 | 410 | { 411 | "hrsh7th/nvim-cmp", 412 | event = "InsertEnter", 413 | dependencies = { 414 | { 415 | -- snippet plugin 416 | "L3MON4D3/LuaSnip", 417 | build = "make install_jsregexp", 418 | dependencies = "rafamadriz/friendly-snippets", 419 | config = function() require("config.cmp.LuaSnip") end, 420 | }, 421 | 422 | -- cmp sources plugins 423 | { 424 | "hrsh7th/cmp-path", 425 | "hrsh7th/cmp-buffer", 426 | "hrsh7th/cmp-nvim-lsp", 427 | "hrsh7th/cmp-nvim-lua", 428 | "saadparwaiz1/cmp_luasnip", 429 | }, 430 | }, 431 | config = function() require("config.cmp") end, 432 | }, 433 | 434 | { 435 | "stevearc/conform.nvim", 436 | cmd = "ConformInfo", 437 | event = "BufWritePre", 438 | main = "conform", 439 | opts = function() return require("config.conform") end, 440 | }, 441 | 442 | --------------------------------------------------- Debugger --------------------------------------------------- 443 | { 444 | "rcarriga/nvim-dap-ui", 445 | dependencies = { 446 | { 447 | "mfussenegger/nvim-dap", 448 | config = function() require("config.dap") end, 449 | }, 450 | "theHamsta/nvim-dap-virtual-text", 451 | "nvim-neotest/nvim-nio", 452 | }, 453 | main = "dapui", 454 | opts = function() require("config.dap.dapui") end, 455 | }, 456 | } 457 | 458 | require("lazy").setup(plugins, require("config.lazy-nvim")) 459 | -------------------------------------------------------------------------------- /lua/ui/border.lua: -------------------------------------------------------------------------------- 1 | return { 2 | rounded = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, 3 | single = { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, 4 | } 5 | -------------------------------------------------------------------------------- /lua/ui/colors.lua: -------------------------------------------------------------------------------- 1 | local colors = { 2 | bg = "#202328", 3 | fg = "#bbc2cf", 4 | yellow = "#ffc021", 5 | light_yellow = "#ffdf80", 6 | cyan = "#008080", 7 | darkblue = "#081633", 8 | black = "#000000", 9 | white = "#ffffff", 10 | green = "#67bf70", 11 | light_green = "#47d864", 12 | orange = "#FF8800", 13 | violet = "#a9a1e1", 14 | magenta = "#c678dd", 15 | blue = "#51afef", 16 | weight_blue = "#2f86eb", 17 | red = "#ee2c4a", 18 | light_red = "#ff6c6b", 19 | gray = "#5c6370", 20 | purple = "#c688eb", 21 | pink = "#eb7fdc", 22 | } 23 | 24 | return colors 25 | -------------------------------------------------------------------------------- /lua/ui/icons/init.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- diagnostics 3 | DiagnosticSign = { 4 | Error = "", 5 | Warn = "", 6 | Hint = "󰌵", 7 | Info = "", 8 | "", 9 | "", 10 | "󰌵", 11 | "", 12 | }, 13 | 14 | -- dap 15 | DapStopped = "󱞪 ", 16 | DapBreakpoint = " ", 17 | } 18 | -------------------------------------------------------------------------------- /lua/ui/icons/lspkind.lua: -------------------------------------------------------------------------------- 1 | return { 2 | Namespace = "󰌗", 3 | Text = "󰉿", 4 | Method = "󰆧", 5 | Function = "󰆧", 6 | Constructor = "", 7 | Field = "󰜢", 8 | Variable = "󰀫", 9 | Class = "󰠱", 10 | Interface = "", 11 | Module = "", 12 | Property = "󰜢", 13 | Unit = "󰑭", 14 | Value = "󰎠", 15 | Enum = "", 16 | Keyword = "󰌋", 17 | Snippet = "", 18 | Color = "󰏘", 19 | File = "󰈚", 20 | Reference = "󰈇", 21 | Folder = "󰉋", 22 | EnumMember = "", 23 | Constant = "󰏿", 24 | Struct = "󰙅", 25 | Event = "", 26 | Operator = "󰆕", 27 | TypeParameter = "󰊄", 28 | Table = "", 29 | Object = "󰅩", 30 | Tag = "", 31 | Array = "[]", 32 | Boolean = "", 33 | Number = "", 34 | Null = "󰟢", 35 | String = "󰉿", 36 | Calendar = "", 37 | Watch = "󰥔", 38 | Package = "", 39 | Copilot = "", 40 | Codeium = "", 41 | TabNine = "", 42 | } 43 | -------------------------------------------------------------------------------- /lua/utils/init.lua: -------------------------------------------------------------------------------- 1 | local api, fn, pcall = vim.api, vim.fn, pcall 2 | 3 | local M = {} 4 | 5 | --- Get the root directory of the project. 6 | --- 7 | --- @param source string|integer Buffer number (0 for current buffer) or file path to begin the search from 8 | --- @return string|nil: The root directory path of the project 9 | M.find_root = function(source, markers) 10 | return vim.fs.root(source or 0, markers or vim.g.stinvim_root_markers or { 11 | ".git", 12 | "package.json", -- npm 13 | "Cargo.toml", -- rust 14 | "build.zig", -- zig 15 | "stylua.toml", -- lua 16 | "lazy-lock.json", -- nvim config 17 | "gradlew", -- java 18 | "mvnw", -- java 19 | }) 20 | end 21 | 22 | --- Executes a specified command using vim.api.nvim_command 23 | --- and optionally displays success or error messages. 24 | --- 25 | --- @param command string The command to execute 26 | --- @param msg table|nil The message to print on success or error 27 | --- @param quiet boolean|nil Whether to display success or error messages 28 | --- @return boolean True if the command was executed successfully, false otherwise. 29 | M.exec_cmd = function(command, msg, quiet) 30 | local success, error_message = pcall(api.nvim_command, command) 31 | if not quiet then 32 | if success then 33 | require("utils.notify").info(msg and msg.success or command .. " execute success") 34 | else 35 | require("utils.notify").error((msg and msg.error or "Error") .. ": " .. error_message) 36 | end 37 | end 38 | return success 39 | end 40 | 41 | --- Checks if a given plugin is installed in the specified directory. 42 | --- 43 | --- @param plugin_name string The name of the plugin to check. 44 | --- @param custom_dir string The custom installation directory for plugins. 45 | --- @return boolean True if the plugin is installed, false otherwise. 46 | M.is_plug_installed = function(plugin_name, custom_dir) 47 | custom_dir = custom_dir or "/lazy/" 48 | if not vim.startswith(custom_dir, "/") then custom_dir = "/" .. custom_dir end 49 | if not vim.endswith(custom_dir, "/") then custom_dir = custom_dir .. "/" end 50 | 51 | return fn.isdirectory(fn.stdpath("data") .. custom_dir .. plugin_name) == 1 52 | end 53 | 54 | --- Attempts to load a module and calls a provided callback function with the loaded module if successful. 55 | --- 56 | --- @param name string The name of the module to load. 57 | --- @param cb function A function to be executed with the loaded module as an argument. 58 | M.load_mod = function(name, cb) 59 | local status_ok, module = pcall(require, name) 60 | if status_ok then 61 | return cb(module) 62 | else 63 | require("utils.notify").error("Module " .. name .. " not found") 64 | end 65 | end 66 | 67 | --- Attempts to load multiple modules and calls a provided callback function with the loaded modules if successful. If a module fails to load, an error message is printed, and the function returns nil. 68 | --- 69 | --- @param cb function A function to be executed with the loaded module as an argument. 70 | --- @param ... string The names of the modules to load. 71 | M.load_mods = function(cb, ...) 72 | local modules = { ... } 73 | for i, name in ipairs(modules) do 74 | local status_ok, module = pcall(require, name) 75 | if status_ok then 76 | modules[i] = module 77 | else 78 | require("utils.notify").error("Module " .. name .. " not found") 79 | return 80 | end 81 | end 82 | return cb(unpack(modules)) 83 | end 84 | 85 | --- Close a buffer matching the specified filetypes or buftypes. 86 | --- 87 | --- @param bufnr number The buffer number to close. 88 | --- @param matches string|table The filetypes or buffer types to close. 89 | --- @param condition_name string|nil Can be "filetype" or "buftype" (default: "filetype"). 90 | M.close_buffer_matching = function(bufnr, matches, condition_name) 91 | vim.schedule(function() 92 | local condition = api.nvim_get_option_value(condition_name or "filetype", { buf = bufnr }) 93 | if type(matches) == "string" and condition == matches then 94 | api.nvim_buf_delete(bufnr, { force = true }) 95 | elseif type(matches) == "table" then 96 | for _, match in ipairs(matches) do 97 | if type(match) == "string" and condition == match then 98 | api.nvim_buf_delete(bufnr, { force = true }) 99 | return 100 | end 101 | end 102 | end 103 | end) 104 | end 105 | 106 | --- Close all buffers matching the specified filetypes or buffer types. 107 | --- 108 | --- @param matches string|table The filetypes or buffer types to close. 109 | --- @param condition_name string Can be "filetype" or "buftype". 110 | M.close_buffers_matching = function(matches, condition_name) 111 | for _, buf in ipairs(api.nvim_list_bufs()) do 112 | if api.nvim_buf_is_valid(buf) then M.close_buffer_matching(buf, matches, condition_name) end 113 | end 114 | end 115 | 116 | --- Fast close all buffers matching the specified filetypes or buffer types. 117 | --- 118 | --- @param matches string|table The filetypes or buffer types to close. 119 | --- @param condition_name string Can be "filetype" or "buftype". 120 | M.close_buffers_matching_in_visible_windows = function(matches, condition_name) 121 | local wins = api.nvim_list_wins() 122 | for _, win in ipairs(wins) do 123 | M.close_buffer_matching(api.nvim_win_get_buf(win), matches, condition_name) 124 | end 125 | end 126 | 127 | --- Close buffers specified by buffer numbers or filetypes/buftypes. 128 | --- 129 | --- @param matches number|table The buffer numbers or table with filetypes/buftypes. 130 | M.close_buffers = function(matches) 131 | if type(matches) == "number" and api.nvim_buf_is_valid(matches) then 132 | vim.schedule(function() api.nvim_buf_delete(matches, { force = true }) end) 133 | elseif type(matches) == "table" then 134 | for _, buf in ipairs(matches) do 135 | if type(buf) == "number" and api.nvim_buf_is_valid(buf) then 136 | vim.schedule(function() api.nvim_buf_delete(buf, { force = true }) end) 137 | end 138 | end 139 | for _, buf in ipairs(api.nvim_list_bufs()) do 140 | if api.nvim_buf_is_valid(buf) then 141 | M.close_buffer_matching(buf, matches, "filetype") 142 | M.close_buffer_matching(buf, matches, "buftype") 143 | end 144 | end 145 | end 146 | end 147 | 148 | return setmetatable(M, { 149 | __index = function(_, key) return require("utils." .. key) end, 150 | }) 151 | -------------------------------------------------------------------------------- /lua/utils/mapper.lua: -------------------------------------------------------------------------------- 1 | local set_keymap, extend = vim.keymap.set, require("utils.tbl").extend 2 | 3 | local M = {} 4 | 5 | --- @class MapperOpts 6 | --- @see vim.keymap.set.Opts 7 | local OPTIONS = { 8 | { noremap = true, silent = true, nowait = true }, 9 | { noremap = false, silent = true }, 10 | { noremap = true, silent = false }, 11 | { noremap = false, silent = false }, 12 | { noremap = true, silent = true, nowait = false }, 13 | { noremap = true, silent = true, expr = true }, 14 | { noremap = true, silent = true, expr = true, nowait = true }, 15 | } 16 | 17 | --- Set a key mapping in Vim. 18 | --- @param mode table|string: The mode used for applying the key map. 19 | --- @param key string: The key you wish to map. 20 | --- @param map_to function|string: The key or function to be executed by the key map. 21 | --- @param opts ? table|number|string: If opts is a string, it will be used as the description, else if number it will be used as the default keymap options provided by stinvim else if opts is a table it will be used as vim.keymap.set.Opts 22 | --- @param extend_opts ? table|string: Extension or overriding of opts if opts is a number, If opts is a string, it will be used as the description, 23 | --- @see MapperOpts 24 | --- opts: Can be a number or a `vim.keymap.set.Opts` 25 | M.map = function(mode, key, map_to, opts, extend_opts) 26 | local opts_type = type(opts) 27 | local options 28 | if opts_type == "string" then 29 | options = OPTIONS[1] 30 | options.desc = opts 31 | else 32 | options = opts_type == "table" and extend(OPTIONS[1], opts, true) or OPTIONS[opts or 1] or OPTIONS[1] 33 | if extend_opts then 34 | local extend_opts_type = type(extend_opts) 35 | if extend_opts_type == "string" then 36 | options.desc = extend_opts 37 | elseif extend_opts_type == "table" then 38 | options = extend(options, extend_opts, true) 39 | end 40 | end 41 | end 42 | set_keymap(mode, key, map_to, options) 43 | options.desc = nil 44 | end 45 | 46 | return M 47 | -------------------------------------------------------------------------------- /lua/utils/notify.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local levels, notify, schedule = vim.log.levels, vim.notify, vim.schedule 4 | 5 | M.info = function(msg, opts) 6 | schedule(function() 7 | vim.cmd("redraw") 8 | notify(msg, levels.INFO, opts or { title = "Information" }) 9 | end) 10 | end 11 | 12 | M.warn = function(msg, opts) 13 | schedule(function() 14 | vim.cmd("redraw") 15 | notify(msg, levels.WARN, opts or { title = "Warning" }) 16 | end) 17 | end 18 | 19 | M.error = function(msg, opts) 20 | schedule(function() 21 | vim.cmd("redraw") 22 | notify(msg, levels.ERROR, opts or { title = "Error" }) 23 | end) 24 | end 25 | 26 | M.debug = function(msg, opts) 27 | schedule(function() 28 | vim.cmd("redraw") 29 | notify(msg, levels.DEBUG, opts or { title = "Debug" }) 30 | end) 31 | end 32 | 33 | M.trace = function(msg, opts) 34 | schedule(function() 35 | vim.cmd("redraw") 36 | notify(msg, levels.TRACE, opts or { title = "Trace" }) 37 | end) 38 | end 39 | 40 | M.off = function(msg, opts) 41 | schedule(function() 42 | vim.cmd("redraw") 43 | notify(msg, levels.OFF, opts or { title = "Off" }) 44 | end) 45 | end 46 | 47 | return M 48 | -------------------------------------------------------------------------------- /lua/utils/plug-extension.lua: -------------------------------------------------------------------------------- 1 | local fn = vim.fn 2 | 3 | local M = {} 4 | 5 | local copy_file_content = function(source, target) 6 | local source_file = io.open(source, "r") 7 | if source_file then 8 | local content = source_file:read("*all") 9 | source_file:close() 10 | 11 | local target_file = io.open(target, "w") 12 | if target_file then 13 | target_file:write(content) 14 | target_file:close() 15 | return true 16 | else 17 | return false 18 | end 19 | end 20 | end 21 | 22 | M.touch_plug_extension = function(filename) 23 | if type(filename) ~= "string" then filename = fn.input("Enter the filename: ", "", "file") end 24 | 25 | if filename == "" then 26 | require("utils.notify").warn("No filename given") 27 | return 28 | elseif not filename:match("%.lua$") then 29 | filename = fn.fnamemodify(filename, ":r") .. ".lua" 30 | end 31 | 32 | local new_file_path = (vim.g.stinvim_plugin_extension_dir or vim.fn.stdpath("config") .. "/lua/extension") 33 | .. "/" 34 | .. filename 35 | 36 | if fn.filereadable(new_file_path) == 1 then 37 | require("utils.notify").warn("File already exists: " .. filename) 38 | return 39 | end 40 | 41 | local status_ok = copy_file_content(vim.fn.stdpath("config") .. "/templates/plug_autocmd.txt", new_file_path) 42 | if status_ok then 43 | require("utils.notify").info("Created file: " .. filename) 44 | else 45 | require("utils.notify").error("Unable to create file: " .. filename) 46 | end 47 | end 48 | 49 | return M 50 | -------------------------------------------------------------------------------- /lua/utils/reloader.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.hot_reload = function(quiet) 4 | -- Reload options, mappings 5 | local core_modules = { 6 | "core.command", 7 | "core.option", 8 | "core.nvimmap", 9 | "core.autocmd", 10 | "core.plugmap", 11 | } 12 | 13 | local failed_modules = {} 14 | for _, module in ipairs(core_modules) do 15 | package.loaded[module] = nil 16 | local status_ok, m = pcall(require, module) 17 | if not status_ok then 18 | table.insert(failed_modules, m) 19 | elseif module == "core.plugmap" then 20 | for _, func in pairs(m) do 21 | if type(func) == "function" then func() end 22 | end 23 | end 24 | end 25 | 26 | vim.api.nvim_exec_autocmds("ColorScheme", {}) 27 | 28 | if not quiet then -- if not quiet, then notify of result. 29 | if #failed_modules == 0 then 30 | require("utils.notify").info("Reloaded options and nvimmap successfully") 31 | else 32 | require("utils.notify").error("Error while reloading core modules: " .. table.concat(failed_modules, "\n")) 33 | end 34 | end 35 | end 36 | 37 | return M 38 | -------------------------------------------------------------------------------- /lua/utils/tbl.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | --- 4 | --- Creates a shallow clone of a table. 5 | --- Copies all key-value pairs from the input table `tbl` to a new table. 6 | --- If `tbl` contains nested tables, they are shallow cloned recursively. 7 | --- @param tbl table The table to clone. 8 | --- @return table A new table containing shallow copies of all key-value pairs from `tbl`. 9 | function M.clone(tbl) 10 | local clone_tbl = {} 11 | if type(tbl) == "table" then 12 | for k, v in pairs(tbl) do 13 | clone_tbl[k] = M.clone(v) 14 | end 15 | else 16 | clone_tbl = tbl -- des[k] = v 17 | end 18 | return clone_tbl 19 | end 20 | 21 | --- 22 | --- Creates a deep clone of a table. 23 | --- Copies all key-value pairs from the input table `tbl` to a new table. 24 | --- If `tbl` contains nested tables, they are deep cloned recursively. 25 | --- Also copies the metatable of `tbl` to the cloned table, if it exists. 26 | --- @param tbl table The table to deep clone. 27 | --- @return table A new table containing deep copies of all key-value pairs from `tbl`. 28 | function M.deep_clone(tbl) 29 | local clone_tbl = {} 30 | if type(tbl) == "table" then 31 | local mt = getmetatable(tbl) 32 | if mt then 33 | local new_mt = M.clone(mt) 34 | setmetatable(clone_tbl, new_mt) 35 | end 36 | for k, v in pairs(tbl) do 37 | clone_tbl[k] = M.clone(v) 38 | end 39 | else 40 | clone_tbl = tbl -- des[k] = v 41 | end 42 | return clone_tbl 43 | end 44 | 45 | --- 46 | --- Merges two tables recursively, copying key-value pairs from `t2` into `t1`. 47 | --- If both `t1` and `t2` have tables as values for the same key, they are merged recursively. 48 | --- If `force` is `true`, `t1` is overwritten with `t2` even if `t1` is not `nil`. 49 | --- @param t1 table The destination table to merge into. 50 | --- @param t2 table The source table to merge from. 51 | --- @param force boolean Optional. If `true`, overwrites `t1` with `t2` even if `t1` is not `nil`. 52 | --- @return table The merged table `t1`. 53 | M.merge = function(t1, t2, force) 54 | if type(t1) == "table" then 55 | for k, v in pairs(t2) do 56 | t1[k] = M.merge(t1[k], v, force) 57 | end 58 | elseif force or t1 == nil then 59 | t1 = t2 60 | end 61 | return t1 62 | end 63 | 64 | --- 65 | --- Deep merges two tables recursively, copying key-value pairs from `t2` into `t1`. 66 | --- If both `t1` and `t2` have tables as values for the same key, they are deep merged recursively. 67 | --- If `force` is `true`, `t1` is overwritten with `t2` even if `t1` is not `nil`. 68 | --- Preserves metatables from both `t1` and `t2` during the merge. 69 | --- @param t1 table The destination table to merge into. 70 | --- @param t2 table The source table to merge from. 71 | --- @param force boolean Optional. If `true`, overwrites `t1` with `t2` even if `t1` is not `nil`. 72 | --- @return table The merged table `t1`. 73 | M.deep_merge = function(t1, t2, force) 74 | if type(t1) == "table" then 75 | local mt2 = getmetatable(t2) 76 | if mt2 then 77 | local mt1 = getmetatable(t1) 78 | if mt1 then 79 | setmetatable(t1, M.merge(M.clone(mt1), mt2, force)) 80 | else 81 | setmetatable(t1, mt2) 82 | end 83 | end 84 | 85 | for k, v in pairs(t2) do 86 | t1[k] = M.merge(t1[k], v, force) 87 | end 88 | elseif force or t1 == nil then 89 | t1 = t2 90 | end 91 | return t1 92 | end 93 | 94 | --- 95 | --- Shallowly extends a table by copying key-value pairs from `tb2` into a clone of `tb1`. 96 | --- Uses shallow merge, which means that nested tables are not merged but overwritten. 97 | --- If `force` is `true`, values from `tb2` will overwrite existing values in the clone of `tb1`. 98 | --- @param tb1 table The base table to clone and extend. 99 | --- @param tb2 table The table with values to copy into the clone of `tb1`. 100 | --- @param force boolean Optional. If `true`, values from `tb2` overwrite existing values in the clone of `tb1`. 101 | --- @return table A new table that is a shallowly extended clone of `tb1`. 102 | function M.extend(tb1, tb2, force) 103 | local newtbl1 = M.clone(tb1) 104 | return M.merge(newtbl1, tb2, force) 105 | end 106 | 107 | --- 108 | --- Deeply extends a table by copying key-value pairs from `tb2` into a deep clone of `tb1`. 109 | --- Uses deep merge, which means that nested tables are recursively merged. 110 | --- Preserves metatables from both `tb1` and `tb2` during the merge. 111 | --- If `force` is `true`, values from `tb2` will overwrite existing values in the deep clone of `tb1`. 112 | --- @param tb1 table The base table to deep clone and extend. 113 | --- @param tb2 table The table with values to copy into the deep clone of `tb1`. 114 | --- @param force boolean Optional. If `true`, values from `tb2` overwrite existing values in the deep clone of `tb1`. 115 | --- @return table A new table that is a deeply extended clone of `tb1`. 116 | function M.deep_extend(tb1, tb2, force) 117 | local newtbl1 = M.deep_clone(tb1) 118 | return M.deep_merge(newtbl1, tb2, force) 119 | end 120 | 121 | --- Extends multiple tables by copying key-value pairs from all provided tables into a shallow clone of the first table. 122 | --- If `force` is `true`, values from subsequent tables will overwrite existing values in the clone of the first table. 123 | --- @param force boolean If `true`, values from subsequent tables overwrite existing values in the deep clone of the first table. 124 | --- @param ... table The tables to be deep merged. 125 | --- @return table A new table that is a deeply extended clone of the first table. 126 | function M.extend_multitables(force, ...) 127 | local tables = { ... } 128 | local len = #tables 129 | if len > 1 then 130 | local result = M.clone(tables[1]) 131 | for i = 2, len do 132 | result = M.merge(result, tables[i], force) 133 | end 134 | return result 135 | end 136 | return len > 0 and M.clone(tables[1]) or {} 137 | end 138 | 139 | --- 140 | --- Deeply extends multiple tables by copying key-value pairs from all provided tables into a deep clone of the first table. 141 | --- Uses deep merge, which means that nested tables are recursively merged. 142 | --- Preserves metatables from all tables during the merge. 143 | --- If `force` is `true`, values from subsequent tables will overwrite existing values in the deep clone of the first table. 144 | --- @param force boolean If `true`, values from subsequent tables overwrite existing values in the deep clone of the first table. 145 | --- @param ... table The tables to be deep merged. 146 | --- @return table A new table that is a deeply extended clone of the first table. 147 | function M.deep_extend_multitables(force, ...) 148 | local tables = { ... } 149 | local len = #tables 150 | if len > 1 then 151 | local result = M.deep_clone(tables[1]) 152 | for i = 2, len do 153 | result = M.deep_merge(result, tables[i], force) 154 | end 155 | return result 156 | end 157 | return len > 0 and M.deep_clone(tables[1]) or {} 158 | end 159 | 160 | --- Check if two tables contain the same items, regardless of order and duplicates. 161 | --- 162 | --- @param table1 table The first table to compare 163 | --- @param table2 table The second table to compare 164 | --- @return boolean: Whether the two tables are contain the same items 165 | M.same_set = function(table1, table2) -- O(n) 166 | local tbl1_hash = {} -- to check that all elements are in table2 167 | local tbl2_hash = {} -- to check for duplicates in table2 168 | 169 | for _, value in ipairs(table1) do 170 | tbl1_hash[value] = true 171 | end 172 | 173 | for _, value in ipairs(table2) do 174 | if not tbl1_hash[value] and not tbl2_hash[value] then return false end 175 | tbl1_hash[value] = nil 176 | tbl2_hash[value] = true 177 | end 178 | 179 | return next(tbl1_hash) == nil -- check if all elements in table1 are in table2 180 | end 181 | 182 | --- Check if two tables contain the same items, regardless of order. 183 | --- 184 | --- @param table1 table The first table to compare 185 | --- @param table2 table The second table to compare 186 | --- @return boolean: Whether the two tables are contain the same items 187 | M.same_array = function(table1, table2) -- O(n) 188 | local len1 = #table1 189 | local len2 = #table2 190 | if len1 ~= len2 then return false end 191 | 192 | local counts = {} 193 | 194 | for i = 1, len1, 1 do 195 | local v = table1[i] 196 | counts[v] = (counts[v] or 0) + 1 197 | end 198 | 199 | for i = 1, len2, 1 do 200 | local v = table2[i] 201 | local count = counts[v] 202 | if not count or count == 0 then return false end 203 | counts[v] = count - 1 204 | end 205 | 206 | return true 207 | end 208 | 209 | --- Finds the items in the source table that are not present in the target table. 210 | --- 211 | --- @param source table The source table to find unique items that are not in target table 212 | --- @param target table The target table to compare with the source table 213 | --- @return table The unique items in source table that are not in target table 214 | M.find_unique_array_items = function(source, target) 215 | if next(source) == nil then return target end 216 | 217 | local founds = {} 218 | local unique_items = {} 219 | 220 | for _, value in ipairs(target) do 221 | founds[value] = true 222 | end 223 | 224 | local index = 0 225 | for _, value in ipairs(source) do 226 | if not founds[value] then 227 | index = index + 1 228 | unique_items[index] = value 229 | end 230 | end 231 | 232 | return unique_items 233 | end 234 | 235 | return M 236 | -------------------------------------------------------------------------------- /stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | indent_type = "Tabs" 3 | indent_width = 2 4 | quote_style = "AutoPreferDouble" 5 | call_parentheses = "NoSingleTable" 6 | collapse_simple_statement = "Always" 7 | -------------------------------------------------------------------------------- /templates/plug_autocmd.txt: -------------------------------------------------------------------------------- 1 | local utils = require("utils") 2 | local api = vim.api 3 | 4 | local M = { 5 | enabled = true 6 | } 7 | 8 | M.entry = function() 9 | api.nvim_create_autocmd({ "" }, { 10 | pattern = "", 11 | desc = "", 12 | callback = function() 13 | if not utils.is_plug_installed("") then return end 14 | end, 15 | }) 16 | end 17 | 18 | return M 19 | 20 | --------------------------------------------------------------------------------