├── .github └── workflows │ ├── ci.yml │ └── stale.yml ├── .gitignore ├── .neoconf.json ├── .stylua.toml ├── .typos.toml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── doc ├── api.md └── astrocore.txt ├── lazy.lua ├── lua ├── astrocore │ ├── buffer.lua │ ├── buffer │ │ └── comparator.lua │ ├── config.lua │ ├── health.lua │ ├── init.lua │ ├── rooter.lua │ └── toggles.lua └── resession │ └── extensions │ └── astrocore.lua ├── neovim.yml └── selene.toml /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: AstroNvim 2 | on: 3 | push: 4 | branches: [main] 5 | pull_request: 6 | pull_request_target: 7 | types: [opened, edited, synchronize] 8 | 9 | jobs: 10 | CI: 11 | uses: AstroNvim/.github/.github/workflows/plugin_ci.yml@main 12 | if: ${{ github.event_name != 'pull_request_target' }} 13 | secrets: inherit 14 | with: 15 | plugin_name: ${{ github.event.repository.name }} 16 | is_production: ${{ github.event_name == 'push' }} 17 | PR: 18 | uses: AstroNvim/.github/.github/workflows/validate_pr.yml@main 19 | if: ${{ github.event_name == 'pull_request_target' }} 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues and PRs" 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" # run at 0130 UTC 5 | 6 | jobs: 7 | stale: 8 | uses: AstroNvim/.github/.github/workflows/stale.yml@main 9 | secrets: inherit 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/tags 2 | -------------------------------------------------------------------------------- /.neoconf.json: -------------------------------------------------------------------------------- 1 | { 2 | "neodev": { 3 | "library": { 4 | "enabled": true, 5 | "plugins": ["lazy.nvim", "astroui", "resession.nvim"] 6 | } 7 | }, 8 | "neoconf": { 9 | "plugins": { 10 | "lua_ls": { 11 | "enabled": true 12 | } 13 | } 14 | }, 15 | "lspconfig": { 16 | "lua_ls": { 17 | "Lua.format.enable": false, 18 | "Lua.diagnostics.globals": ["astronvim"] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 120 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferDouble" 6 | call_parentheses = "None" 7 | collapse_simple_statement = "Always" 8 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = ["CHANGELOG.md", "doc/*"] 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.0.5](https://github.com/AstroNvim/astrocore/compare/v2.0.4...v2.0.5) (2025-04-30) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | * **rooter:** improve `exists` function ([1b96f40](https://github.com/AstroNvim/astrocore/commit/1b96f40c76d7ff792515d5d41c8f31081fd3c5b0)) 9 | 10 | ## [2.0.4](https://github.com/AstroNvim/astrocore/compare/v2.0.3...v2.0.4) (2025-04-28) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | * improve rooter docstring ([3c79603](https://github.com/AstroNvim/astrocore/commit/3c7960313120ea6f58196aa27b14760a7c459955)) 16 | 17 | ## [2.0.3](https://github.com/AstroNvim/astrocore/compare/v2.0.2...v2.0.3) (2025-04-23) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | * **buffer:** get the session config directly from the `astrocore` module ([89c080c](https://github.com/AstroNvim/astrocore/commit/89c080ce4e946adacbf5519eda97cd4c0c84a3a6)) 23 | 24 | ## [2.0.2](https://github.com/AstroNvim/astrocore/compare/v2.0.1...v2.0.2) (2025-04-21) 25 | 26 | 27 | ### Reverts 28 | 29 | * remove `vim.lsp.foldexpr` hack ([6a58ab8](https://github.com/AstroNvim/astrocore/commit/6a58ab83503097bc7b3df0517fbc0b9377cc3142)) 30 | 31 | ## [2.0.1](https://github.com/AstroNvim/astrocore/compare/v2.0.0...v2.0.1) (2025-04-09) 32 | 33 | 34 | ### Bug Fixes 35 | 36 | * **resession:** prime `vim.lsp.foldexpr` on session restore ([6e9e51a](https://github.com/AstroNvim/astrocore/commit/6e9e51aa0d06c5a8af72abfa58f25ce80df8a86b)) 37 | 38 | ## [2.0.0](https://github.com/AstroNvim/astrocore/compare/v1.16.0...v2.0.0) (2025-03-26) 39 | 40 | 41 | ### ⚠ BREAKING CHANGES 42 | 43 | * rename `vim.b.cmp_enabled` to `vim.b.completion` 44 | * simplify diagnostic toggling to just enabled/disabled rather than various modes 45 | * allow `rename_file` to be passed in the new filename 46 | * remove `mason` module and use `mason-tools-installer` if available for applying mason updates 47 | * remove `system_open` function as one should use `vim.ui.open` 48 | * require Neovim v0.10 49 | 50 | ### Features 51 | 52 | * add `enabled` function to `large_buf` configuration for fine grain control over what bufers get detected ([396974e](https://github.com/AstroNvim/astrocore/commit/396974ec2a820b72326d4d1c3e9b8c14a285a5e8)) 53 | * add `virtual_text` and `virtual_lines` toggles ([78de20e](https://github.com/AstroNvim/astrocore/commit/78de20e59f6f6cae6cd12c2f2fbab7dc49abac04)) 54 | * allow `large_buf.enabled` function to modify large buffer configuration ([9ac85b7](https://github.com/AstroNvim/astrocore/commit/9ac85b7b2efc96acc4d6484e1b9873bcb3c9d275)) 55 | * allow `rename_file` to be passed in the new filename ([5da4f87](https://github.com/AstroNvim/astrocore/commit/5da4f873fdcf252a38a58d47dc558798a122b909)) 56 | * allow configuration of virtual text and virtual lines on startup ([ea2206c](https://github.com/AstroNvim/astrocore/commit/ea2206c4dbb98b5b1122985570598a6e8e423be6)) 57 | * prompt user to save file before renaming with `rename_file` ([3a75df9](https://github.com/AstroNvim/astrocore/commit/3a75df9979ee24bebc12fb96bf74b0630a39ac38)) 58 | * rename `vim.b.cmp_enabled` to `vim.b.completion` ([499de90](https://github.com/AstroNvim/astrocore/commit/499de90c663fccb7d37d6048c702d205b1104abc)) 59 | * set colorscheme when necessary if AstroUI is available ([c78fa9c](https://github.com/AstroNvim/astrocore/commit/c78fa9cfa72a876aa9a46f01a4dd4b3b47bc499f)) 60 | * simplify diagnostic toggling to just enabled/disabled rather than various modes ([d435d72](https://github.com/AstroNvim/astrocore/commit/d435d72f3e7d329c7e7651954769f9adf846078c)) 61 | 62 | 63 | ### Bug Fixes 64 | 65 | * **config:** normalize mappings when running `setup` ([2d03ccc](https://github.com/AstroNvim/astrocore/commit/2d03ccc038f1fca21057dea43c209830a837ae06)) 66 | * maintain original tab ordering when renaming file ([ba308ba](https://github.com/AstroNvim/astrocore/commit/ba308ba9e5f8fa2ec1021e48961ecd059901c665)) 67 | * rename `overwrite` option to `force` in `rename_file` ([bc7bd35](https://github.com/AstroNvim/astrocore/commit/bc7bd35e7bb1b5a165d7347d6dc9b89e90587579)) 68 | * validate original file exists in `rename_file` ([8295110](https://github.com/AstroNvim/astrocore/commit/8295110fe7962d6153dc9523151cc2e05ffe565b)) 69 | 70 | 71 | ### Code Refactoring 72 | 73 | * remove `mason` module and use `mason-tools-installer` if available for applying mason updates ([88c9e08](https://github.com/AstroNvim/astrocore/commit/88c9e08ce08e725eaa6980364982e76f91b7a8ec)) 74 | * remove `system_open` function as one should use `vim.ui.open` ([2715dbf](https://github.com/AstroNvim/astrocore/commit/2715dbff99bdce60a69feb571194a4cd6997176b)) 75 | * require Neovim v0.10 ([3690cc6](https://github.com/AstroNvim/astrocore/commit/3690cc60e953b4537aa6435ff6ef13162b44e0d1)) 76 | 77 | ## [1.16.0](https://github.com/AstroNvim/astrocore/compare/v1.15.0...v1.16.0) (2025-02-18) 78 | 79 | 80 | ### Features 81 | 82 | * add `set_diagnostics` helper function to easily change diagnostics mode ([a073c79](https://github.com/AstroNvim/astrocore/commit/a073c79e27e3dabf50243daa6b764789b1da76cb)) 83 | 84 | ## [1.15.0](https://github.com/AstroNvim/astrocore/compare/v1.14.0...v1.15.0) (2025-02-17) 85 | 86 | 87 | ### Features 88 | 89 | * add `rename_file` method for prompting the user to rename a file ([633a260](https://github.com/AstroNvim/astrocore/commit/633a2606050f678d0393fc1feb2b9af28fe9a657)) 90 | 91 | ## [1.14.0](https://github.com/AstroNvim/astrocore/compare/v1.13.2...v1.14.0) (2025-02-14) 92 | 93 | 94 | ### Features 95 | 96 | * add support for `snacks.bufdelete` to buffer utilities ([5e26ac1](https://github.com/AstroNvim/astrocore/commit/5e26ac1f45fd2b0307bf6c6c04be1b4d33532505)) 97 | 98 | ## [1.13.2](https://github.com/AstroNvim/astrocore/compare/v1.13.1...v1.13.2) (2025-02-13) 99 | 100 | 101 | ### Bug Fixes 102 | 103 | * **buffer:** improve type safety for `is_large` ([9a6ed00](https://github.com/AstroNvim/astrocore/commit/9a6ed00103ed02ce10c769b104749ff5fba50e52)) 104 | 105 | ## [1.13.1](https://github.com/AstroNvim/astrocore/compare/v1.13.0...v1.13.1) (2025-02-13) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * **large_buf:** no need to pass in `bufnr` data ([ca7c59c](https://github.com/AstroNvim/astrocore/commit/ca7c59ce094b98ab540b3d59ebc0fe80ec374553)) 111 | 112 | ## [1.13.0](https://github.com/AstroNvim/astrocore/compare/v1.12.2...v1.13.0) (2025-02-13) 113 | 114 | 115 | ### Features 116 | 117 | * **large_buf:** improve `is_large` API and add configurable notification on detection ([e3085ab](https://github.com/AstroNvim/astrocore/commit/e3085abb370f3a556676707c103d33223560f084)) 118 | 119 | ## [1.12.2](https://github.com/AstroNvim/astrocore/compare/v1.12.1...v1.12.2) (2025-02-13) 120 | 121 | 122 | ### Bug Fixes 123 | 124 | * incorrect autocommand description ([d356cc5](https://github.com/AstroNvim/astrocore/commit/d356cc5119a5b5f0dc43a6261b4c150af2c9cf2f)) 125 | 126 | ## [1.12.1](https://github.com/AstroNvim/astrocore/compare/v1.12.0...v1.12.1) (2025-02-13) 127 | 128 | 129 | ### Bug Fixes 130 | 131 | * resolve incorrect function location (not considered breaking because bug and new) ([1b72dfe](https://github.com/AstroNvim/astrocore/commit/1b72dfe382d4815aadab6df91d90b1fcf23b4c75)) 132 | 133 | ## [1.12.0](https://github.com/AstroNvim/astrocore/compare/v1.11.0...v1.12.0) (2025-02-12) 134 | 135 | 136 | ### Features 137 | 138 | * add `is_large_buf` to interactively check if buffer is large ([7a80ad7](https://github.com/AstroNvim/astrocore/commit/7a80ad74ee42884cbd3086be02053c773bc36a6e)) 139 | * add `line_length` to large buffer detection ([aa76560](https://github.com/AstroNvim/astrocore/commit/aa76560f144bc0de128d6bd9d5024d335ca51ecc)) 140 | * allow disabling individual large file metrics ([5463a98](https://github.com/AstroNvim/astrocore/commit/5463a98314168116f2d62f15bbd5e8761071f310)) 141 | 142 | 143 | ### Bug Fixes 144 | 145 | * improve typos detection ([025274c](https://github.com/AstroNvim/astrocore/commit/025274c5db248320c6f0d079d15b2e5fe6447b4a)) 146 | 147 | ## [1.11.0](https://github.com/AstroNvim/astrocore/compare/v1.10.0...v1.11.0) (2024-10-28) 148 | 149 | 150 | ### Features 151 | 152 | * **health:** add health check for conflicting mappings ([1040947](https://github.com/AstroNvim/astrocore/commit/1040947440b44d1d79ec575b30ba05c7091d6dff)) 153 | 154 | ## [1.10.0](https://github.com/AstroNvim/astrocore/compare/v1.9.0...v1.10.0) (2024-09-27) 155 | 156 | 157 | ### Features 158 | 159 | * add `with_file` helper to run a function on an opened file ([ca2a852](https://github.com/AstroNvim/astrocore/commit/ca2a852831ad113606b8a16c40ff1ac44644b2a3)) 160 | 161 | ## [1.9.0](https://github.com/AstroNvim/astrocore/compare/v1.8.1...v1.9.0) (2024-09-19) 162 | 163 | 164 | ### Features 165 | 166 | * add `patch_func` to monkey patch into an existing function ([e7d7a35](https://github.com/AstroNvim/astrocore/commit/e7d7a35c490b4e1f15252f36c198d35e21490f4d)) 167 | 168 | ## [1.8.1](https://github.com/AstroNvim/astrocore/compare/v1.8.0...v1.8.1) (2024-09-17) 169 | 170 | 171 | ### Bug Fixes 172 | 173 | * remove non-public facing `json` module as it was merged upstream ([2d19ef3](https://github.com/AstroNvim/astrocore/commit/2d19ef3f8b97418b31bbf665cd6a2f68a4c95782)) 174 | 175 | ## [1.8.0](https://github.com/AstroNvim/astrocore/compare/v1.7.2...v1.8.0) (2024-08-29) 176 | 177 | 178 | ### Features 179 | 180 | * **buffer:** add utility to check if a buffer has a filetype ([a00fa8c](https://github.com/AstroNvim/astrocore/commit/a00fa8c08b534cd3c56a39bc76d64de7d5ae9e64)) 181 | 182 | ## [1.7.2](https://github.com/AstroNvim/astrocore/compare/v1.7.1...v1.7.2) (2024-08-27) 183 | 184 | 185 | ### Bug Fixes 186 | 187 | * **buffer:** make sure previous buffer is valid ([1087dc4](https://github.com/AstroNvim/astrocore/commit/1087dc4645724bc28bb6c82d0a2ac73377e68411)) 188 | 189 | ## [1.7.1](https://github.com/AstroNvim/astrocore/compare/v1.7.0...v1.7.1) (2024-08-08) 190 | 191 | 192 | ### Bug Fixes 193 | 194 | * the right hand side is not mandatory when setting a mapping ([47a7b83](https://github.com/AstroNvim/astrocore/commit/47a7b834c547f4bb84072309f41d11687ccccd20)) 195 | 196 | ## [1.7.0](https://github.com/AstroNvim/astrocore/compare/v1.6.3...v1.7.0) (2024-08-04) 197 | 198 | 199 | ### Features 200 | 201 | * add `json` module for cleaning up json ([ee7b8bd](https://github.com/AstroNvim/astrocore/commit/ee7b8bd1ac1b66949b3edfb95c58db766483d706)) 202 | 203 | ## [1.6.3](https://github.com/AstroNvim/astrocore/compare/v1.6.2...v1.6.3) (2024-07-22) 204 | 205 | 206 | ### Bug Fixes 207 | 208 | * defer clipboard because xsel and pbcopy can be slow ([3bc1868](https://github.com/AstroNvim/astrocore/commit/3bc186846084b42fd76618cd15fbe121ac5c0585)) 209 | 210 | ## [1.6.2](https://github.com/AstroNvim/astrocore/compare/v1.6.1...v1.6.2) (2024-07-12) 211 | 212 | 213 | ### Bug Fixes 214 | 215 | * update to `which-key` v3 ([a7a909b](https://github.com/AstroNvim/astrocore/commit/a7a909bf27f1147e05998af8c00a987ddc25943d)) 216 | 217 | ## [1.6.1](https://github.com/AstroNvim/astrocore/compare/v1.6.0...v1.6.1) (2024-06-20) 218 | 219 | 220 | ### Bug Fixes 221 | 222 | * **rooter:** add LSP client `root_dir` to roots ([c8de780](https://github.com/AstroNvim/astrocore/commit/c8de7803a02cc69f084b23a8c63141b98b70f56a)) 223 | 224 | ## [1.6.0](https://github.com/AstroNvim/astrocore/compare/v1.5.0...v1.6.0) (2024-06-07) 225 | 226 | 227 | ### Features 228 | 229 | * add `unique_list` which gets unique values from list ([70e0682](https://github.com/AstroNvim/astrocore/commit/70e068219c6012e9a2287aa75db906d5c505e998)) 230 | 231 | ## [1.5.0](https://github.com/AstroNvim/astrocore/compare/v1.4.0...v1.5.0) (2024-06-03) 232 | 233 | 234 | ### Features 235 | 236 | * setup `highlighturl` capabilities on setup ([3bf9e36](https://github.com/AstroNvim/astrocore/commit/3bf9e36b71f931646a1d264cf8076d7214fb2f86)) 237 | 238 | 239 | ### Bug Fixes 240 | 241 | * resolve `path` before running `vim.ui.open` ([879b67b](https://github.com/AstroNvim/astrocore/commit/879b67b8f32561419b01d3d9f31ac774b6b741fe)) 242 | 243 | ## [1.4.0](https://github.com/AstroNvim/astrocore/compare/v1.3.3...v1.4.0) (2024-05-24) 244 | 245 | 246 | ### Features 247 | 248 | * **rooter:** allow `rooter.ignore.servers` to be an arbitrary filter function ([0283868](https://github.com/AstroNvim/astrocore/commit/028386800779b29a1cea238897d0ff4b8f45599e)) 249 | * **rooter:** allow passing rooter configurations to rooting functions for API execution ([0707cb4](https://github.com/AstroNvim/astrocore/commit/0707cb4b91d899975d79d0c57ae1feee3c684e00)) 250 | 251 | ## [1.3.3](https://github.com/AstroNvim/astrocore/compare/v1.3.2...v1.3.3) (2024-05-13) 252 | 253 | 254 | ### Bug Fixes 255 | 256 | * **rooter:** detect unique LSP roots in the case of multiple language servers ([c15cfb2](https://github.com/AstroNvim/astrocore/commit/c15cfb23352a0f09b79551286dc8c59cc5876423)) 257 | 258 | ## [1.3.2](https://github.com/AstroNvim/astrocore/compare/v1.3.1...v1.3.2) (2024-05-07) 259 | 260 | 261 | ### Bug Fixes 262 | 263 | * don't schedule functions when loading plugins ([70b9a20](https://github.com/AstroNvim/astrocore/commit/70b9a209bade26bde4256b9d8abfb2a6e67ef723)) 264 | 265 | ## [1.3.1](https://github.com/AstroNvim/astrocore/compare/v1.3.0...v1.3.1) (2024-05-06) 266 | 267 | 268 | ### Bug Fixes 269 | 270 | * don't trim content by default when reading a file ([c637f51](https://github.com/AstroNvim/astrocore/commit/c637f51cb83786fc50d0b8075175e7a3e27db2ef)) 271 | 272 | ## [1.3.0](https://github.com/AstroNvim/astrocore/compare/v1.2.2...v1.3.0) (2024-05-06) 273 | 274 | 275 | ### Features 276 | 277 | * add `read_file` utility ([d9b2a47](https://github.com/AstroNvim/astrocore/commit/d9b2a47fb358e903712e4b94e539dbcf38900629)) 278 | 279 | ## [1.2.2](https://github.com/AstroNvim/astrocore/compare/v1.2.1...v1.2.2) (2024-04-29) 280 | 281 | 282 | ### Bug Fixes 283 | 284 | * **rooter:** normalization of path "/" should be "/" ([60db5cc](https://github.com/AstroNvim/astrocore/commit/60db5cce71685330bb275a89224847d20fffd62f)) 285 | 286 | 287 | ### Reverts 288 | 289 | * use `vim.keymap.set` defaults ([cbd996e](https://github.com/AstroNvim/astrocore/commit/cbd996ef7b1c949bb1b89c3dbfe0857042ef5625)) 290 | 291 | ## [1.2.1](https://github.com/AstroNvim/astrocore/compare/v1.2.0...v1.2.1) (2024-04-22) 292 | 293 | 294 | ### Bug Fixes 295 | 296 | * add check for new `islist` function ([248e38a](https://github.com/AstroNvim/astrocore/commit/248e38a3e2e8d4316705403644dcda8ec63a31f6)) 297 | 298 | ## [1.2.0](https://github.com/AstroNvim/astrocore/compare/v1.1.3...v1.2.0) (2024-04-17) 299 | 300 | 301 | ### Features 302 | 303 | * allow specific window to be provided to `delete_url_match` and `set_url_match` ([2a77fdc](https://github.com/AstroNvim/astrocore/commit/2a77fdc69dc04afe917dd5fac68a01fab1bea806)) 304 | * store current window `highlighturl` state ([abe1ce8](https://github.com/AstroNvim/astrocore/commit/abe1ce821876a836f7576bc75c97f6f6ae8f415f)) 305 | 306 | 307 | ### Bug Fixes 308 | 309 | * **toggles:** toggle all windows when toggling url matching ([417f798](https://github.com/AstroNvim/astrocore/commit/417f79836bb6ae9ae249b7ca11258939a07f598a)) 310 | 311 | ## [1.1.3](https://github.com/AstroNvim/astrocore/compare/v1.1.2...v1.1.3) (2024-04-17) 312 | 313 | 314 | ### Bug Fixes 315 | 316 | * make sure buffers are valid before checking for filetype ([83e5425](https://github.com/AstroNvim/astrocore/commit/83e5425c89887eb616e8dc6530d97f7b9c19e942)) 317 | 318 | ## [1.1.2](https://github.com/AstroNvim/astrocore/compare/v1.1.1...v1.1.2) (2024-04-09) 319 | 320 | 321 | ### Bug Fixes 322 | 323 | * add missing function mapping type ([1d2b396](https://github.com/AstroNvim/astrocore/commit/1d2b396fcf07008b771b923aaca724d0b8dcf8f9)) 324 | 325 | ## [1.1.1](https://github.com/AstroNvim/astrocore/compare/v1.1.0...v1.1.1) (2024-04-05) 326 | 327 | 328 | ### Bug Fixes 329 | 330 | * hide `nvim_exec_autocmds` errors with `pcall` ([1736458](https://github.com/AstroNvim/astrocore/commit/1736458b321c59c6e57c456f0f39c0665b301591)) 331 | 332 | ## [1.1.0](https://github.com/AstroNvim/astrocore/compare/v1.0.1...v1.1.0) (2024-04-05) 333 | 334 | 335 | ### Features 336 | 337 | * add `exec_buffer_autocmds` to execute autocommands in each file buffer ([f2088d2](https://github.com/AstroNvim/astrocore/commit/f2088d2afc5d19e51ca363156bfbbb9f89093fa0)) 338 | 339 | ## [1.0.1](https://github.com/AstroNvim/astrocore/compare/v1.0.0...v1.0.1) (2024-04-02) 340 | 341 | 342 | ### Bug Fixes 343 | 344 | * **resession:** fix restoration of single tabpages ([8de07ce](https://github.com/AstroNvim/astrocore/commit/8de07ce5403d291be4434e7ca333b61cfc9c74f9)) 345 | 346 | ## 1.0.0 (2024-03-20) 347 | 348 | 349 | ### ⚠ BREAKING CHANGES 350 | 351 | * remove `get_hlgroup` now available in AstroUI 352 | * **config:** rename `features.max_file` to `features.large_buf` 353 | * **toggles:** remove indent guide toggle 354 | * move to variable arguments for `list_insert` and `load_plugin_with_func` 355 | * remove `alpha_button` function since alpha provides it's own 356 | * **buffer:** modularize `astrocore.buffer.comparator` 357 | * drop support for Neovim v0.8 358 | * move `astrocore.utils` to root `astrocore` module 359 | * remove astronvim updater and git utilities 360 | * move autocmds,user commands, on_key to configuration table 361 | * icons moved to AstroUI 362 | 363 | ### Features 364 | 365 | * add `on_load` function to execute a function when a plugin loads ([254a94d](https://github.com/AstroNvim/astrocore/commit/254a94d3c188b1fd1a24952cbc61d2799171c6bc)) 366 | * add `silent` to default keymap options ([11af187](https://github.com/AstroNvim/astrocore/commit/11af1879701539badd654206514fd1518ec6336d)) 367 | * add `vim.fn.sign_define` and `vim.diagnostic.config` support ([184bd90](https://github.com/AstroNvim/astrocore/commit/184bd90f63c6ab87ca1f0fdef310608bff6de285)) 368 | * add `wslview` support to `system_open` ([6a79c20](https://github.com/AstroNvim/astrocore/commit/6a79c20b196aefae75ce684b051587b2585a9045)) 369 | * add ability for `on_load` to easily just load another plugin ([ca29e21](https://github.com/AstroNvim/astrocore/commit/ca29e21c1a5ffa210fa39336126f9591f9966c5c)) 370 | * add ability for multiple plugins to be supplied to `on_load` ([720bf6b](https://github.com/AstroNvim/astrocore/commit/720bf6b2a95eaa7433c155b040d0488a9f0bc43c)) 371 | * add ability to configure filetypes with `vim.filetype.add` ([51ac59f](https://github.com/AstroNvim/astrocore/commit/51ac59f6a4e1ec84bfaee07a027495a35e7beaf4)) 372 | * add buffer utilities ([2f74a61](https://github.com/AstroNvim/astrocore/commit/2f74a61db34f6193aa4cc97e6f93682ab4858527)) 373 | * add experimental rooter ([96eb638](https://github.com/AstroNvim/astrocore/commit/96eb6381f64b437d8abf5098e62695f106cd47df)) 374 | * add healthchecks ([7a5b7e7](https://github.com/AstroNvim/astrocore/commit/7a5b7e7c809dc09a0a7f324a2b1571f4a2efcb64)) 375 | * add mapping configuration and autocmds ([a45533b](https://github.com/AstroNvim/astrocore/commit/a45533b22310d2dfe603617875a98dbd7094213e)) 376 | * add Mason utility functions ([92b40bc](https://github.com/AstroNvim/astrocore/commit/92b40bc9a5c390c8323a20862fe4e489d113ad89)) 377 | * add polish function ([485b727](https://github.com/AstroNvim/astrocore/commit/485b72796b460eead192fd09eb8f546fca6a8c80)) 378 | * add resession extension for AstroCore ([5217973](https://github.com/AstroNvim/astrocore/commit/52179734242211c61dbfae0efb8268ed04b535d0)) 379 | * add types for autocompletion with `lua_ls` ([63ed189](https://github.com/AstroNvim/astrocore/commit/63ed18904ff3f0d7a761eba0f5a9da2d49bee95a)) 380 | * add UI/UX toggle utilities ([1878654](https://github.com/AstroNvim/astrocore/commit/1878654739444f81c2e1cb43a381b4975635e0d8)) 381 | * allow `false` to disable autocmds, commands, or on_key functions ([38991f9](https://github.com/AstroNvim/astrocore/commit/38991f940cb40cbd5fe0a3634129f9c7eca6a1a9)) 382 | * allow `large_buf` to be set to `false` to disable detection ([ac0f0bd](https://github.com/AstroNvim/astrocore/commit/ac0f0bddfd06c77345f367e4611461e338365dfb)) 383 | * allow vim options to be configured ([e81ff58](https://github.com/AstroNvim/astrocore/commit/e81ff580c08756f762ff029a3f4fb2bd73c42974)) 384 | * **buffer:** add `wipe` function to fully wipe a buffer ([685da23](https://github.com/AstroNvim/astrocore/commit/685da236d8649fb6c259ec8b49c5f74b84020cc9)) 385 | * **buffer:** add ability for `close_tab` to close a specific tabpage ([1b57b25](https://github.com/AstroNvim/astrocore/commit/1b57b25107be19250aeca9f4bede0764f94c32c9)) 386 | * clean up rooter and add toggle function ([f22dcfe](https://github.com/AstroNvim/astrocore/commit/f22dcfe6134a5cf31f92e1dcd6538010da4ef4b1)) 387 | * **config:** rename `features.max_file` to `features.large_buf` ([e2df9f0](https://github.com/AstroNvim/astrocore/commit/e2df9f0c037f3ccbdd65b2555761f2856ec01064)) 388 | * make `event` function more extendable ([4708247](https://github.com/AstroNvim/astrocore/commit/4708247df2a0a01672081deb48a1b8961225a97f)) 389 | * move astronvim specific features to configuration ([4b1a21a](https://github.com/AstroNvim/astrocore/commit/4b1a21ae4de92f2bf45f8cb506ee13955f382149)) 390 | * move autocmds,user commands, on_key to configuration table ([a2b0564](https://github.com/AstroNvim/astrocore/commit/a2b0564f8060f4d911cc53c1e8731b4cd944e4c4)) 391 | * move git and updater utilities ([8899cc3](https://github.com/AstroNvim/astrocore/commit/8899cc3f8cf4d2701e52c3d3ed0e6b92989964a9)) 392 | * move to variable arguments for `list_insert` and `load_plugin_with_func` ([1c7fcd5](https://github.com/AstroNvim/astrocore/commit/1c7fcd57cbdaef0ad02109e50f6748b051b8b80e)) 393 | * **toggles:** add `buffer_indent_guides` toggle ([515d5f3](https://github.com/AstroNvim/astrocore/commit/515d5f3083e4b350852a54a8581dd736a69c3691)) 394 | * **toggles:** add buffer local cmp toggle ([aa3d013](https://github.com/AstroNvim/astrocore/commit/aa3d013ca06734b1596dd2aa88e91c793bffc01e)) 395 | * use `on_load` to load which-key queue automatically ([be8c860](https://github.com/AstroNvim/astrocore/commit/be8c86010cbe178e42c9efd5f3763fec360f5559)) 396 | * **utils:** add update_packages utility to update lazy and mason ([76eb2f7](https://github.com/AstroNvim/astrocore/commit/76eb2f7d72fed4b06955e5e8a43eff64a2612666)) 397 | 398 | 399 | ### Bug Fixes 400 | 401 | * **buffer:** fix `bd` usage when `bufnr` is 0 ([ec82070](https://github.com/AstroNvim/astrocore/commit/ec82070afdce258cfb52c1e32e40edbacc67dcd9)) 402 | * don't schedule polish ([de74fa4](https://github.com/AstroNvim/astrocore/commit/de74fa40522bf416f0e5912b6e114cd4a0adaa85)) 403 | * extend `on_exit` passed to custom toggle terminal ([08f73ce](https://github.com/AstroNvim/astrocore/commit/08f73cee62e38793085c631f32036ff76e3c9c50)) 404 | * guarantee M.config always exists ([cc33dfc](https://github.com/AstroNvim/astrocore/commit/cc33dfc22ed909534282331136ae87ee0662aaa5)) 405 | * **health:** update healthcheck ([53af950](https://github.com/AstroNvim/astrocore/commit/53af950399a6bc940012613221a849e1f805f99f)) 406 | * incorrect docstring for `rooter` settings ([36aa11d](https://github.com/AstroNvim/astrocore/commit/36aa11d3923bb287ab0e90b702af16ac7c0141ef)) 407 | * localize user terminals to utilities ([4e406cc](https://github.com/AstroNvim/astrocore/commit/4e406cc95e529ddcda8e3ada043c51f288f7671d)) 408 | * protect function lazy loading against asynchronous loops ([7e125ac](https://github.com/AstroNvim/astrocore/commit/7e125acf7bddc981cbd4d0e1f8c1fa08eee50990)) 409 | * **resession:** only change buffers on load if cursor is in a wipe buffer ([1a1bff7](https://github.com/AstroNvim/astrocore/commit/1a1bff7da93497ea9751a4dc71cfadb99ddc4804)) 410 | * **resession:** rename extension to `astrocore` ([771930c](https://github.com/AstroNvim/astrocore/commit/771930c9c16035c0c77ca0dda857fdb3d2826669)) 411 | * **rooter:** allow project root detection for files that do not yet exist ([c691761](https://github.com/AstroNvim/astrocore/commit/c6917610c4065f74519c5dd64782baaa2619ac33)) 412 | * **rooter:** only check patterns for existing paths ([42a9394](https://github.com/AstroNvim/astrocore/commit/42a939433007a891449ef67bce4c0dc3048abe00)) 413 | * **toggles:** immediately refresh `mini.indentscope` ([526cbc3](https://github.com/AstroNvim/astrocore/commit/526cbc3f14b75510d7236bf73557a964fcb6fe91)) 414 | * **toggles:** update semantic_tokens_enabled to just semantic_tokens ([8f6b75f](https://github.com/AstroNvim/astrocore/commit/8f6b75fb916c8a952663112102f72485354c8140)) 415 | * unhide custom toggle terminals by default ([027e12b](https://github.com/AstroNvim/astrocore/commit/027e12b93d70cae4063f97b38d782718b0160c98)) 416 | * update `reload` function for new `options` structure ([b8e8a9b](https://github.com/AstroNvim/astrocore/commit/b8e8a9b031aa2abdb39b7d2ff624b25ca2edd0c7)) 417 | * update reload function with new structure ([7f5df22](https://github.com/AstroNvim/astrocore/commit/7f5df2200898934a2606f35b3d01cd9754a2a09f)) 418 | * use `explorer.exe` instead of `wslview` in WSL ([495f339](https://github.com/AstroNvim/astrocore/commit/495f339b30ba51c282d54fae58a2db0df684a32f)) 419 | * **utils:** reload AstroUI as well as AstroCore ([ad12e9c](https://github.com/AstroNvim/astrocore/commit/ad12e9c3683acf09544acc1cc8d414005df377bd)) 420 | 421 | 422 | ### Performance Improvements 423 | 424 | * optimize `list_insert_unique` ([58b832d](https://github.com/AstroNvim/astrocore/commit/58b832d46a439febd8e808de4731e19b332261a8)) 425 | * remove need to make deep copies ([4e677ff](https://github.com/AstroNvim/astrocore/commit/4e677ff984f099832041feb6b7d304b1388f2ff6)) 426 | 427 | 428 | ### Reverts 429 | 430 | * continue hiding custom toggle terminals by default ([c9d24ce](https://github.com/AstroNvim/astrocore/commit/c9d24ce03e16dc6b542a2fa3203eec43db2ddd5c)) 431 | * move `list_insert_unique` and `load_plugin_with_func` back to taking lists instead of variable arguments ([1f3ae05](https://github.com/AstroNvim/astrocore/commit/1f3ae05f5df572f3674e223a669f9895935c95de)) 432 | 433 | 434 | ### Miscellaneous Chores 435 | 436 | * drop support for Neovim v0.8 ([3213349](https://github.com/AstroNvim/astrocore/commit/3213349bfca03934ba4bc0c33aff6321b0c1e7f2)) 437 | 438 | 439 | ### Code Refactoring 440 | 441 | * **buffer:** modularize `astrocore.buffer.comparator` ([8651582](https://github.com/AstroNvim/astrocore/commit/8651582e7324bb84118444613366829723d0725c)) 442 | * icons moved to AstroUI ([18e9189](https://github.com/AstroNvim/astrocore/commit/18e9189574ecae363074c7d23f9729cdf7f3818f)) 443 | * move `astrocore.utils` to root `astrocore` module ([60d9aaf](https://github.com/AstroNvim/astrocore/commit/60d9aaff0306aab978f31ffb55fc326c724ad254)) 444 | * remove `alpha_button` function since alpha provides it's own ([484de60](https://github.com/AstroNvim/astrocore/commit/484de6051cfd9ffdb53fd967397d80836fcb846e)) 445 | * remove `get_hlgroup` now available in AstroUI ([3ff32fb](https://github.com/AstroNvim/astrocore/commit/3ff32fb1137dd4425713626738ad9ca11a53f0b3)) 446 | * remove astronvim updater and git utilities ([a26729d](https://github.com/AstroNvim/astrocore/commit/a26729d082123c65d4dff4fbe895a1e8cf719d3a)) 447 | * **toggles:** remove indent guide toggle ([a063322](https://github.com/AstroNvim/astrocore/commit/a06332290c833810fd22cacf37837dce5b0a39c3)) 448 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧰 AstroCore 2 | 3 | AstroCore provides the core Lua API that powers [AstroNvim](https://github.com/AstroNvim/AstroNvim). It provides an interface for configuration auto commands, user commands, on_key functions, key mappings, and more as well as a Lua API of common utility functions. 4 | 5 | ## ✨ Features 6 | 7 | - Unified interface for configuring auto commands, user commands, key maps, on key functions 8 | - Easy toggles of UI/UX elements and features 9 | - Universal interface for setting up git worktrees 10 | - Tab local buffer management for a clean `tabline` 11 | - Project root detection with automatic `cd` features 12 | - Session management with [resession.nvim][resession] 13 | 14 | ## ⚡️ Requirements 15 | 16 | - Neovim >= 0.10 17 | - [lazy.nvim](https://github.com/folke/lazy.nvim) 18 | - [resession.nvim][resession] (_optional_) 19 | 20 | ## 📦 Installation 21 | 22 | Install the plugin with the lazy plugin manager: 23 | 24 | ```lua 25 | return { 26 | "AstroNvim/astrocore", 27 | lazy = false, -- disable lazy loading 28 | priority = 10000, -- load AstroCore first 29 | opts = { 30 | -- set configuration options as described below 31 | }, 32 | } 33 | ``` 34 | 35 | > 💡 If you want to enable session management with [resession.nvim][resession], enable it in the setup: 36 | 37 | ```lua 38 | require("resession").setup { 39 | extensions = { 40 | astrocore = {}, 41 | }, 42 | } 43 | ``` 44 | 45 | ## ⚙️ Configuration 46 | 47 | **AstroCore** comes with no defaults, but can be configured fully through the `opts` table in lazy. Here are descriptions of the options and some example usages: 48 | 49 | ```lua 50 | ---@type AstroCoreConfig 51 | local opts = { 52 | -- easily configure auto commands 53 | autocmds = { 54 | -- first key is the `augroup` (:h augroup) 55 | highlighturl = { 56 | -- list of auto commands to set 57 | { 58 | -- events to trigger 59 | event = { "VimEnter", "FileType", "BufEnter", "WinEnter" }, 60 | -- the rest of the autocmd options (:h nvim_create_autocmd) 61 | desc = "URL Highlighting", 62 | callback = function() require("astrocore").set_url_match() end, 63 | }, 64 | }, 65 | }, 66 | -- easily configure user commands 67 | commands = { 68 | -- key is the command name 69 | AstroReload = { 70 | -- first element with no key is the command (string or function) 71 | function() require("astrocore").reload() end, 72 | -- the rest are options for creating user commands (:h nvim_create_user_command) 73 | desc = "Reload AstroNvim (Experimental)", 74 | }, 75 | }, 76 | -- Configure diagnostics options (`:h vim.diagnostic.config()`) 77 | diagnostics = { 78 | update_in_insert = false, 79 | }, 80 | -- passed to `vim.filetype.add` 81 | filetypes = { 82 | -- see `:h vim.filetype.add` for usage 83 | extension = { 84 | foo = "fooscript", 85 | }, 86 | filename = { 87 | [".foorc"] = "fooscript", 88 | }, 89 | pattern = { 90 | [".*/etc/foo/.*"] = "fooscript", 91 | }, 92 | }, 93 | -- Configuration of vim mappings to create 94 | mappings = { 95 | -- map mode (:h map-modes) 96 | n = { 97 | -- use vimscript strings for mappings 98 | [""] = { ":w!", desc = "Save File" }, 99 | -- navigate buffer tabs with `H` and `L` 100 | L = { 101 | function() require("astrocore.buffer").nav(vim.v.count1) end, 102 | desc = "Next buffer", 103 | }, 104 | H = { 105 | function() require("astrocore.buffer").nav(-vim.v.count1) end, 106 | desc = "Previous buffer", 107 | }, 108 | -- tables with just a `desc` key will be registered with which-key if it's installed 109 | -- this is useful for naming menus 110 | ["b"] = { desc = "Buffers" }, 111 | }, 112 | }, 113 | -- easily configure functions on key press 114 | on_keys = { 115 | -- first key is the namespace 116 | auto_hlsearch = { 117 | -- list of functions to execute on key press (:h vim.on_key) 118 | function(char) -- example automatically disables `hlsearch` when not actively searching 119 | if vim.fn.mode() == "n" then 120 | local new_hlsearch = vim.tbl_contains({ "", "n", "N", "*", "#", "?", "/" }, vim.fn.keytrans(char)) 121 | if vim.opt.hlsearch:get() ~= new_hlsearch then vim.opt.hlsearch = new_hlsearch end 122 | end 123 | end, 124 | }, 125 | }, 126 | -- easily configure vim options 127 | options = { 128 | -- first key is the type of option `vim.` 129 | opt = { 130 | relativenumber = true, -- sets `vim.opt.relativenumber` 131 | signcolumn = "auto", -- sets `vim.opt.relativenumber` 132 | }, 133 | g = { 134 | -- set global `vim.g` settings here 135 | }, 136 | }, 137 | -- configure AstroNvim features 138 | features = { 139 | autopairs = true, -- enable or disable autopairs on start 140 | cmp = true, -- enable or disable cmp on start 141 | diagnostics = { virtual_text = true, virtual_lines = false }, -- enable or disable diagnostics features on start 142 | highlighturl = true, -- enable or disable highlighting of urls on start 143 | -- table for defining the size of the max file for all features, above these limits we disable features like treesitter. 144 | large_buf = { 145 | -- whether to enable large file detection for a buffer (must return false to disable) 146 | -- first parameter is the buffer number, the second is the large buffer configuration table 147 | -- return values: 148 | -- - `true` or `nil` to continue and respects all changes made to the large buffer configuration table 149 | -- - `false` to disable large file detection for the buffer 150 | -- - a new table of large buffer options to use instead of the defaults 151 | enabled = function(bufnr, config) end, 152 | notify = true, -- whether or not to display a notification when a large file is detected 153 | size = 1024 * 100, -- max file size (or false to disable check) 154 | lines = 10000, -- max number of lines (or false to disable check) 155 | line_length = 1000, -- average line length (or false to disable check) 156 | }, 157 | notifications = true, -- enable or disable notifications on start 158 | }, 159 | -- Enable git integration for detached worktrees 160 | git_worktrees = { 161 | { toplevel = vim.env.HOME, gitdir = vim.env.HOME .. "/.dotfiles" }, 162 | }, 163 | -- Configure project root detection, check status with `:AstroRootInfo` 164 | rooter = { 165 | -- list of detectors in order of prevalence, elements can be: 166 | -- "lsp" : lsp detection 167 | -- string[] : a list of directory patterns to look for 168 | -- fun(bufnr: integer): string|string[] : a function that takes a buffer number and outputs detected roots 169 | detector = { 170 | "lsp", -- highest priority is getting workspace from running language servers 171 | { ".git", "_darcs", ".hg", ".bzr", ".svn" }, -- next check for a version controlled parent directory 172 | { "lua", "MakeFile", "package.json" }, -- lastly check for known project root files 173 | }, 174 | -- ignore things from root detection 175 | ignore = { 176 | servers = {}, -- list of language server names to ignore (Ex. { "efm" }) 177 | dirs = {}, -- list of directory patterns (Ex. { "~/.cargo/*" }) 178 | }, 179 | -- automatically update working directory (update manually with `:AstroRoot`) 180 | autochdir = false, 181 | -- scope of working directory to change ("global"|"tab"|"win") 182 | scope = "global", 183 | -- show notification on every working directory change 184 | notify = false, 185 | }, 186 | -- Configuration table of session options for AstroNvim's session management powered by Resession 187 | sessions = { 188 | -- Configure auto saving 189 | autosave = { 190 | last = true, -- auto save last session 191 | cwd = true, -- auto save session for each working directory 192 | }, 193 | -- Patterns to ignore when saving sessions 194 | ignore = { 195 | dirs = {}, -- working directories to ignore sessions in 196 | filetypes = { "gitcommit", "gitrebase" }, -- filetypes to ignore sessions 197 | buftypes = {}, -- buffer types to ignore sessions 198 | }, 199 | }, 200 | } 201 | ``` 202 | 203 | ## 📦 API 204 | 205 | **AstroCore** provides a Lua API with utility functions. This can be viewed with `:h astrocore` or in the repository at [doc/api.md](doc/api.md) 206 | 207 | [resession]: https://github.com/stevearc/resession.nvim/ 208 | 209 | ## 🚀 Contributing 210 | 211 | If you plan to contribute, please check the [contribution guidelines](https://github.com/AstroNvim/.github/blob/main/CONTRIBUTING.md) first. 212 | -------------------------------------------------------------------------------- /doc/api.md: -------------------------------------------------------------------------------- 1 | # Lua API 2 | 3 | astrocore API documentation 4 | 5 | ## astrocore 6 | 7 | ### cmd 8 | 9 | 10 | ```lua 11 | function astrocore.cmd(cmd: string|string[], show_error?: boolean) 12 | -> result: string|nil 13 | ``` 14 | 15 | Run a shell command and capture the output and if the command succeeded or failed 16 | 17 | *param* `cmd` — The terminal command to execute 18 | 19 | *param* `show_error` — Whether or not to show an unsuccessful command as an error to the user 20 | 21 | *return* `result` — The result of a successfully executed command or nil 22 | 23 | ### conditional_func 24 | 25 | 26 | ```lua 27 | function astrocore.conditional_func(func: function, condition: boolean, ...any) 28 | -> result: any 29 | ``` 30 | 31 | Call function if a condition is met 32 | 33 | *param* `func` — The function to run 34 | 35 | *param* `condition` — Whether to run the function or not 36 | 37 | *return* `result` — the result of the function running or nil 38 | 39 | ### config 40 | 41 | 42 | ```lua 43 | AstroCoreOpts 44 | ``` 45 | 46 | The configuration as set by the user through the `setup()` function 47 | 48 | ### delete_url_match 49 | 50 | 51 | ```lua 52 | function astrocore.delete_url_match(win?: integer) 53 | ``` 54 | 55 | Delete the syntax matching rules for URLs/URIs if set 56 | 57 | *param* `win` — the window id to remove url highlighting in (default: current window) 58 | 59 | ### empty_map_table 60 | 61 | 62 | ```lua 63 | function astrocore.empty_map_table() 64 | -> mappings: table 65 | ``` 66 | 67 | Get an empty table of mappings with a key for each map mode 68 | 69 | *return* `mappings` — a table with entries for each map mode 70 | 71 | ### event 72 | 73 | 74 | ```lua 75 | function astrocore.event(event: string|vim.api.keyset_exec_autocmds, instant?: boolean) 76 | ``` 77 | 78 | Trigger an AstroNvim user event 79 | 80 | *param* `event` — The event pattern or full autocmd options (pattern always prepended with "Astro") 81 | 82 | *param* `instant` — Whether or not to execute instantly or schedule 83 | 84 | ### exec_buffer_autocmds 85 | 86 | 87 | ```lua 88 | function astrocore.exec_buffer_autocmds(event: string|string[], opts: vim.api.keyset.exec_autocmds) 89 | ``` 90 | 91 | Execute autocommand across all valid buffers 92 | 93 | *param* `event` — the event or events to execute 94 | 95 | *param* `opts` — Dictionary of autocommnd options 96 | 97 | ### extend_tbl 98 | 99 | 100 | ```lua 101 | function astrocore.extend_tbl(default?: table, opts?: table) 102 | -> extended: table 103 | ``` 104 | 105 | Merge extended options with a default table of options 106 | 107 | *param* `default` — The default table that you want to merge into 108 | 109 | *param* `opts` — The new options that should be merged with the default table 110 | 111 | *return* `extended` — The extended table 112 | 113 | ### file_worktree 114 | 115 | 116 | ```lua 117 | function astrocore.file_worktree(file?: string, worktrees?: table[]) 118 | -> worktree: table|nil 119 | ``` 120 | 121 | Get the first worktree that a file belongs to 122 | 123 | *param* `file` — the file to check, defaults to the current file 124 | 125 | *param* `worktrees` — an array like table of worktrees with entries `toplevel` and `gitdir`, default retrieves from `vim.g.git_worktrees` 126 | 127 | *return* `worktree` — a table specifying the `toplevel` and `gitdir` of a worktree or nil if not found 128 | 129 | ### get_plugin 130 | 131 | 132 | ```lua 133 | function astrocore.get_plugin(plugin: string) 134 | -> spec: LazyPlugin? 135 | ``` 136 | 137 | Get a plugin spec from lazy 138 | 139 | *param* `plugin` — The plugin to search for 140 | 141 | *return* `spec` — The found plugin spec from Lazy 142 | 143 | ### is_available 144 | 145 | 146 | ```lua 147 | function astrocore.is_available(plugin: string) 148 | -> available: boolean 149 | ``` 150 | 151 | Check if a plugin is defined in lazy. Useful with lazy loading when a plugin is not necessarily loaded yet 152 | 153 | *param* `plugin` — The plugin to search for 154 | 155 | *return* `available` — Whether the plugin is available 156 | 157 | ### list_insert_unique 158 | 159 | 160 | ```lua 161 | function astrocore.list_insert_unique(dst: any[]|nil, src: any[]) 162 | -> result: any[] 163 | ``` 164 | 165 | Insert one or more values into a list like table and maintain that you do not insert non-unique values (THIS MODIFIES `dst`) 166 | 167 | *param* `dst` — The list like table that you want to insert into 168 | 169 | *param* `src` — Values to be inserted 170 | 171 | *return* `result` — The modified list like table 172 | 173 | ### load_plugin_with_func 174 | 175 | 176 | ```lua 177 | function astrocore.load_plugin_with_func(plugin: string, module: table, funcs: string|string[]) 178 | ``` 179 | 180 | A helper function to wrap a module function to require a plugin before running 181 | 182 | *param* `plugin` — The plugin to call `require("lazy").load` with 183 | 184 | *param* `module` — The system module where the functions live (e.g. `vim.ui`) 185 | 186 | *param* `funcs` — The functions to wrap in the given module (e.g. `"ui", "select"`) 187 | 188 | ### normalize_mappings 189 | 190 | 191 | ```lua 192 | function astrocore.normalize_mappings(mappings?: table?>) 193 | ``` 194 | 195 | Normalize a mappings table to use official keycode casing 196 | 197 | ### notify 198 | 199 | 200 | ```lua 201 | function astrocore.notify(msg: string, type: integer|nil, opts?: table) 202 | ``` 203 | 204 | Serve a notification with a title of AstroNvim 205 | 206 | *param* `msg` — The notification body 207 | 208 | *param* `type` — The type of the notification (:help vim.log.levels) 209 | 210 | *param* `opts` — The nvim-notify options to use (:help notify-options) 211 | 212 | ### on_load 213 | 214 | 215 | ```lua 216 | function astrocore.on_load(plugins: string|string[], load_op: string|fun()|string[]) 217 | ``` 218 | 219 | Execute a function when a specified plugin is loaded with Lazy.nvim, or immediately if already loaded 220 | 221 | *param* `plugins` — the name of the plugin or a list of plugins to defer the function execution on. If a list is provided, only one needs to be loaded to execute the provided function 222 | 223 | *param* `load_op` — the function to execute when the plugin is loaded, a plugin name to load, or a list of plugin names to load 224 | 225 | ### patch_func 226 | 227 | 228 | ```lua 229 | function astrocore.patch_func(orig?: function, override: fun(orig: function, ...any):...unknown) 230 | -> patched: function 231 | ``` 232 | 233 | Monkey patch into an existing function 234 | 235 | Example from `:h vim.paste()` 236 | ```lua 237 | local patch_func = require("astrocore").patch_func 238 | vim.paste = patch_func(vim.paste, function(orig, lines, phase) 239 | for i, line in ipairs(lines) do 240 | -- Scrub ANSI color codes from paste input. 241 | lines[i] = line:gsub('\27%[[0-9;mK]+', '') 242 | end 243 | return orig(lines, phase) 244 | end) 245 | ``` 246 | 247 | *param* `orig` — the original function to override, if `nil` is provided then an empty function is passed 248 | 249 | *param* `override` — the override function 250 | 251 | *return* `patched` — the new function with the patch applied 252 | 253 | ### plugin_opts 254 | 255 | 256 | ```lua 257 | function astrocore.plugin_opts(plugin: string) 258 | -> opts: table 259 | ``` 260 | 261 | Resolve the options table for a given plugin with lazy 262 | 263 | *param* `plugin` — The plugin to search for 264 | 265 | *return* `opts` — The plugin options 266 | 267 | ### read_file 268 | 269 | 270 | ```lua 271 | function astrocore.read_file(path: string) 272 | -> content: string 273 | ``` 274 | 275 | Helper function to read a file and return it's content 276 | 277 | *param* `path` — the path to the file to read 278 | 279 | *return* `content` — the contents of the file 280 | 281 | ### reload 282 | 283 | 284 | ```lua 285 | function astrocore.reload() 286 | ``` 287 | 288 | Partially reload AstroNvim user settings. Includes core vim options, mappings, and highlights. This is an experimental feature and may lead to instabilities until restart. 289 | 290 | ### rename_file 291 | 292 | 293 | ```lua 294 | function astrocore.rename_file(opts?: AstroCoreRenameFileOpts) 295 | ``` 296 | 297 | Prompt the user to rename a file 298 | 299 | *param* `opts` — optional fields for file renaming 300 | 301 | ### set_mappings 302 | 303 | 304 | ```lua 305 | function astrocore.set_mappings(map_table: table?>, base?: vim.keymap.set.Opts) 306 | ``` 307 | 308 | Table based API for setting keybindings 309 | 310 | *param* `map_table` — A nested table where the first key is the vim mode, the second key is the key to map, and the value is the function to set the mapping to 311 | 312 | *param* `base` — A base set of options to set on every keybinding 313 | 314 | ### set_url_match 315 | 316 | 317 | ```lua 318 | function astrocore.set_url_match(win?: integer) 319 | ``` 320 | 321 | Add syntax matching rules for highlighting URLs/URIs 322 | 323 | *param* `win` — the window id to remove url highlighting in (default: current window) 324 | 325 | ### setup 326 | 327 | 328 | ```lua 329 | function astrocore.setup(opts: AstroCoreOpts) 330 | ``` 331 | 332 | Setup and configure AstroCore 333 | See: [astrocore.config](file:///home/runner/work/astrocore/astrocore/lua/astrocore/init.lua#13#0) 334 | 335 | ### toggle_term_cmd 336 | 337 | 338 | ```lua 339 | function astrocore.toggle_term_cmd(opts: string|table) 340 | ``` 341 | 342 | Toggle a user terminal if it exists, if not then create a new one and save it 343 | 344 | *param* `opts` — A terminal command string or a table of options for Terminal:new() (Check toggleterm.nvim documentation for table format) 345 | 346 | ### unique_list 347 | 348 | 349 | ```lua 350 | function astrocore.unique_list(list: any[]) 351 | -> result: any[] 352 | ``` 353 | 354 | Remove duplicate entries from a given list (does not mutate the original list) 355 | 356 | *param* `list` — The list like table that you want to remove duplicates from 357 | 358 | *return* `result` — The list like table of unique values 359 | 360 | ### update_packages 361 | 362 | 363 | ```lua 364 | function astrocore.update_packages() 365 | ``` 366 | 367 | Sync Lazy and then update Mason 368 | 369 | ### url_matcher 370 | 371 | 372 | ```lua 373 | string 374 | ``` 375 | 376 | regex used for matching a valid URL/URI string 377 | 378 | ### user_terminals 379 | 380 | 381 | ```lua 382 | { [string]: table } 383 | ``` 384 | 385 | A table to manage ToggleTerm terminals created by the user, indexed by the command run and then the instance number 386 | 387 | ### which_key_queue 388 | 389 | 390 | ```lua 391 | nil 392 | ``` 393 | 394 | A placeholder variable used to queue section names to be registered by which-key 395 | 396 | ### which_key_register 397 | 398 | 399 | ```lua 400 | function astrocore.which_key_register() 401 | ``` 402 | 403 | Register queued which-key mappings 404 | 405 | ### with_file 406 | 407 | 408 | ```lua 409 | function astrocore.with_file(filename: string, mode?: "a"|"a+"|"a+b"|"ab"|"r"...(+7), callback?: fun(file: file*), on_error?: fun(err: string)) 410 | ``` 411 | 412 | Execute function with open file 413 | 414 | *param* `filename` — path to file to interact with 415 | 416 | *param* `mode` — the mode in which to open the file 417 | 418 | *param* `callback` — the callback to execute with the opened file 419 | 420 | *param* `on_error` — the callback to execute if unable to open the file 421 | 422 | ```lua 423 | mode: 424 | -> "r" -- Read mode. 425 | | "w" -- Write mode. 426 | | "a" -- Append mode. 427 | | "r+" -- Update mode, all previous data is preserved. 428 | | "w+" -- Update mode, all previous data is erased. 429 | | "a+" -- Append update mode, previous data is preserved, writing is only allowed at the end of file. 430 | | "rb" -- Read mode. (in binary mode.) 431 | | "wb" -- Write mode. (in binary mode.) 432 | | "ab" -- Append mode. (in binary mode.) 433 | | "r+b" -- Update mode, all previous data is preserved. (in binary mode.) 434 | | "w+b" -- Update mode, all previous data is erased. (in binary mode.) 435 | | "a+b" -- Append update mode, previous data is preserved, writing is only allowed at the end of file. (in binary mode.) 436 | ``` 437 | 438 | 439 | ## astrocore.buffer 440 | 441 | ### close 442 | 443 | 444 | ```lua 445 | function astrocore.buffer.close(bufnr?: integer, force?: boolean) 446 | ``` 447 | 448 | Close a given buffer 449 | 450 | *param* `bufnr` — The buffer to close or the current buffer if not provided 451 | 452 | *param* `force` — Whether or not to foce close the buffers or confirm changes (default: false) 453 | 454 | ### close_all 455 | 456 | 457 | ```lua 458 | function astrocore.buffer.close_all(keep_current?: boolean, force?: boolean) 459 | ``` 460 | 461 | Close all buffers 462 | 463 | *param* `keep_current` — Whether or not to keep the current buffer (default: false) 464 | 465 | *param* `force` — Whether or not to foce close the buffers or confirm changes (default: false) 466 | 467 | ### close_left 468 | 469 | 470 | ```lua 471 | function astrocore.buffer.close_left(force?: boolean) 472 | ``` 473 | 474 | Close buffers to the left of the current buffer 475 | 476 | *param* `force` — Whether or not to foce close the buffers or confirm changes (default: false) 477 | 478 | ### close_right 479 | 480 | 481 | ```lua 482 | function astrocore.buffer.close_right(force?: boolean) 483 | ``` 484 | 485 | Close buffers to the right of the current buffer 486 | 487 | *param* `force` — Whether or not to foce close the buffers or confirm changes (default: false) 488 | 489 | ### close_tab 490 | 491 | 492 | ```lua 493 | function astrocore.buffer.close_tab(tabpage?: integer) 494 | ``` 495 | 496 | Close a given tab 497 | 498 | *param* `tabpage` — The tabpage to close or the current tab if not provided 499 | 500 | ### current_buf 501 | 502 | 503 | ```lua 504 | nil 505 | ``` 506 | 507 | Placeholders for keeping track of most recent and previous buffer 508 | 509 | ### has_filetype 510 | 511 | 512 | ```lua 513 | function astrocore.buffer.has_filetype(bufnr?: integer) 514 | -> boolean 515 | ``` 516 | 517 | Check if a buffer has a filetype 518 | 519 | *param* `bufnr` — The buffer to check, default to current buffer 520 | 521 | *return* — Whether the buffer has a filetype or not 522 | 523 | ### is_large 524 | 525 | 526 | ```lua 527 | function astrocore.buffer.is_large(bufnr?: integer, large_buf_opts?: AstroCoreMaxFile) 528 | -> is_large: boolean 529 | ``` 530 | 531 | Check if a buffer is a large buffer (always returns false if large buffer detection is disabled) 532 | 533 | *param* `bufnr` — the buffer to check the size of, default to current buffer 534 | 535 | *param* `large_buf_opts` — large buffer parameters, default to AstroCore configuration 536 | 537 | *return* `is_large` — whether the buffer is detected as large or not 538 | 539 | ### is_restorable 540 | 541 | 542 | ```lua 543 | function astrocore.buffer.is_restorable(bufnr: integer) 544 | -> boolean 545 | ``` 546 | 547 | Check if a buffer can be restored 548 | 549 | *param* `bufnr` — The buffer to check 550 | 551 | *return* — Whether the buffer is restorable or not 552 | 553 | ### is_valid 554 | 555 | 556 | ```lua 557 | function astrocore.buffer.is_valid(bufnr?: integer) 558 | -> boolean 559 | ``` 560 | 561 | Check if a buffer is valid 562 | 563 | *param* `bufnr` — The buffer to check, default to current buffer 564 | 565 | *return* — Whether the buffer is valid or not 566 | 567 | ### is_valid_session 568 | 569 | 570 | ```lua 571 | function astrocore.buffer.is_valid_session() 572 | -> boolean 573 | ``` 574 | 575 | Check if the current buffers form a valid session 576 | 577 | *return* — Whether the current session of buffers is a valid session 578 | 579 | ### last_buf 580 | 581 | 582 | ```lua 583 | nil 584 | ``` 585 | 586 | ### move 587 | 588 | 589 | ```lua 590 | function astrocore.buffer.move(n: integer) 591 | ``` 592 | 593 | Move the current buffer tab n places in the bufferline 594 | 595 | *param* `n` — The number of tabs to move the current buffer over by (positive = right, negative = left) 596 | 597 | ### nav 598 | 599 | 600 | ```lua 601 | function astrocore.buffer.nav(n: integer) 602 | ``` 603 | 604 | Navigate left and right by n places in the bufferline 605 | 606 | *param* `n` — The number of tabs to navigate to (positive = right, negative = left) 607 | 608 | ### nav_to 609 | 610 | 611 | ```lua 612 | function astrocore.buffer.nav_to(tabnr: integer) 613 | ``` 614 | 615 | Navigate to a specific buffer by its position in the bufferline 616 | 617 | *param* `tabnr` — The position of the buffer to navigate to 618 | 619 | ### prev 620 | 621 | 622 | ```lua 623 | function astrocore.buffer.prev() 624 | ``` 625 | 626 | Navigate to the previously used buffer 627 | 628 | ### sort 629 | 630 | 631 | ```lua 632 | function astrocore.buffer.sort(compare_func: string|function, skip_autocmd: boolean|nil) 633 | -> boolean 634 | ``` 635 | 636 | Sort a the buffers in the current tab based on some comparator 637 | 638 | *param* `compare_func` — a string of a comparator defined in require("astrocore.buffer.comparator") or a custom comparator function 639 | 640 | *param* `skip_autocmd` — whether or not to skip triggering AstroBufsUpdated autocmd event 641 | 642 | *return* — Whether or not the buffers were sorted 643 | 644 | ### wipe 645 | 646 | 647 | ```lua 648 | function astrocore.buffer.wipe(bufnr?: integer, force?: boolean) 649 | ``` 650 | 651 | Fully wipeout a given buffer 652 | 653 | *param* `bufnr` — The buffer to wipe or the current buffer if not provided 654 | 655 | *param* `force` — Whether or not to foce close the buffers or confirm changes (default: false) 656 | 657 | 658 | ## astrocore.buffer.comparator 659 | 660 | ### bufnr 661 | 662 | 663 | ```lua 664 | function astrocore.buffer.comparator.bufnr(bufnr_a: integer, bufnr_b: integer) 665 | -> comparison: boolean 666 | ``` 667 | 668 | Comparator of two buffer numbers 669 | 670 | *param* `bufnr_a` — buffer number A 671 | 672 | *param* `bufnr_b` — buffer number B 673 | 674 | *return* `comparison` — true if A is sorted before B, false if B should be sorted before A 675 | 676 | ### extension 677 | 678 | 679 | ```lua 680 | function astrocore.buffer.comparator.extension(bufnr_a: integer, bufnr_b: integer) 681 | -> comparison: boolean 682 | ``` 683 | 684 | Comparator of two buffer numbers based on the file extensions 685 | 686 | *param* `bufnr_a` — buffer number A 687 | 688 | *param* `bufnr_b` — buffer number B 689 | 690 | *return* `comparison` — true if A is sorted before B, false if B should be sorted before A 691 | 692 | ### full_path 693 | 694 | 695 | ```lua 696 | function astrocore.buffer.comparator.full_path(bufnr_a: integer, bufnr_b: integer) 697 | -> comparison: boolean 698 | ``` 699 | 700 | Comparator of two buffer numbers based on the full path 701 | 702 | *param* `bufnr_a` — buffer number A 703 | 704 | *param* `bufnr_b` — buffer number B 705 | 706 | *return* `comparison` — true if A is sorted before B, false if B should be sorted before A 707 | 708 | ### modified 709 | 710 | 711 | ```lua 712 | function astrocore.buffer.comparator.modified(bufnr_a: integer, bufnr_b: integer) 713 | -> comparison: boolean 714 | ``` 715 | 716 | Comparator of two buffers based on modification date 717 | 718 | *param* `bufnr_a` — buffer number A 719 | 720 | *param* `bufnr_b` — buffer number B 721 | 722 | *return* `comparison` — true if A is sorted before B, false if B should be sorted before A 723 | 724 | ### unique_path 725 | 726 | 727 | ```lua 728 | function astrocore.buffer.comparator.unique_path(bufnr_a: integer, bufnr_b: integer) 729 | -> comparison: boolean 730 | ``` 731 | 732 | Comparator of two buffers based on their unique path 733 | 734 | *param* `bufnr_a` — buffer number A 735 | 736 | *param* `bufnr_b` — buffer number B 737 | 738 | *return* `comparison` — true if A is sorted before B, false if B should be sorted before A 739 | 740 | 741 | ## astrocore.rooter 742 | 743 | ### bufpath 744 | 745 | 746 | ```lua 747 | function astrocore.rooter.bufpath(bufnr: integer) 748 | -> path: string? 749 | ``` 750 | 751 | Get the real path of a buffer 752 | 753 | *param* `bufnr` — the buffer 754 | 755 | *return* `path` — the real path 756 | 757 | ### detect 758 | 759 | 760 | ```lua 761 | function astrocore.rooter.detect(bufnr?: integer, all?: boolean, config?: AstroCoreRooterOpts) 762 | -> detected: AstroCoreRooterRoot[] 763 | ``` 764 | 765 | Detect roots in a given buffer 766 | 767 | *param* `bufnr` — the buffer to detect 768 | 769 | *param* `all` — whether to return all roots or just one 770 | 771 | *param* `config` — a rooter configuration (defaults to global configuration) 772 | 773 | *return* `detected` — roots 774 | 775 | ### exists 776 | 777 | 778 | ```lua 779 | function astrocore.rooter.exists(path: string) 780 | -> exists: boolean 781 | ``` 782 | 783 | Check if a path exists 784 | 785 | *param* `path` — the path 786 | 787 | *return* `exists` — whether or not the path exists 788 | 789 | ### info 790 | 791 | 792 | ```lua 793 | function astrocore.rooter.info(config?: AstroCoreRooterOpts) 794 | ``` 795 | 796 | Get information information about the current root 797 | 798 | *param* `config` — a rooter configuration (defaults to global configuration) 799 | 800 | ### is_excluded 801 | 802 | 803 | ```lua 804 | function astrocore.rooter.is_excluded(path: string, config?: AstroCoreRooterOpts) 805 | -> excluded: boolean 806 | ``` 807 | 808 | Check if a path is excluded 809 | 810 | *param* `path` — the path 811 | 812 | *param* `config` — a rooter configuration (defaults to global configuration) 813 | 814 | *return* `excluded` — whether or not the path is excluded 815 | 816 | ### normpath 817 | 818 | 819 | ```lua 820 | function astrocore.rooter.normpath(path: string) 821 | -> string 822 | ``` 823 | 824 | Normalize path 825 | 826 | ### realpath 827 | 828 | 829 | ```lua 830 | function astrocore.rooter.realpath(path?: string) 831 | -> the: string? 832 | ``` 833 | 834 | Resolve a given path 835 | 836 | *param* `path` — the path to resolve 837 | 838 | *return* `the` — resolved path 839 | 840 | ### resolve 841 | 842 | 843 | ```lua 844 | function astrocore.rooter.resolve(spec: string|fun(bufnr: integer):string|string[]|nil|string[], config?: AstroCoreRooterOpts) 845 | -> function 846 | ``` 847 | 848 | Resolve the root detection function for a given spec 849 | 850 | *param* `spec` — the root detector specification 851 | 852 | *param* `config` — the root configuration 853 | 854 | ### root 855 | 856 | 857 | ```lua 858 | function astrocore.rooter.root(bufnr?: integer, config?: AstroCoreRooterOpts) 859 | ``` 860 | 861 | Run the root detection and set the current working directory if a new root is detected 862 | 863 | *param* `bufnr` — the buffer to detect 864 | 865 | *param* `config` — a rooter configuration (defaults to global configuration) 866 | 867 | ### set_pwd 868 | 869 | 870 | ```lua 871 | function astrocore.rooter.set_pwd(root: AstroCoreRooterRoot, config?: AstroCoreRooterOpts) 872 | -> success: boolean 873 | ``` 874 | 875 | Set the current directory to a given root 876 | 877 | *param* `root` — the root to set the pwd to 878 | 879 | *param* `config` — a rooter configuration (defaults to global configuration) 880 | 881 | *return* `success` — whether or not the pwd was successfully set 882 | 883 | 884 | ## astrocore.toggles 885 | 886 | ### autochdir 887 | 888 | 889 | ```lua 890 | function astrocore.toggles.autochdir(silent?: boolean) 891 | ``` 892 | 893 | Toggle rooter autochdir 894 | 895 | *param* `silent` — if true then don't sent a notification 896 | 897 | ### autopairs 898 | 899 | 900 | ```lua 901 | function astrocore.toggles.autopairs(silent?: boolean) 902 | ``` 903 | 904 | Toggle autopairs 905 | 906 | *param* `silent` — if true then don't sent a notification 907 | 908 | ### background 909 | 910 | 911 | ```lua 912 | function astrocore.toggles.background(silent?: boolean) 913 | ``` 914 | 915 | Toggle background="dark"|"light" 916 | 917 | *param* `silent` — if true then don't sent a notification 918 | 919 | ### buffer_cmp 920 | 921 | 922 | ```lua 923 | function astrocore.toggles.buffer_cmp(bufnr?: integer, silent?: boolean) 924 | ``` 925 | 926 | Toggle buffer local cmp 927 | 928 | *param* `bufnr` — the buffer to toggle cmp completion on 929 | 930 | *param* `silent` — if true then don't sent a notification 931 | 932 | ### buffer_syntax 933 | 934 | 935 | ```lua 936 | function astrocore.toggles.buffer_syntax(bufnr?: integer, silent?: boolean) 937 | ``` 938 | 939 | Toggle syntax highlighting and treesitter 940 | 941 | *param* `bufnr` — the buffer to toggle syntax on 942 | 943 | *param* `silent` — if true then don't sent a notification 944 | 945 | ### cmp 946 | 947 | 948 | ```lua 949 | function astrocore.toggles.cmp(silent?: boolean) 950 | ``` 951 | 952 | Toggle cmp entrirely 953 | 954 | *param* `silent` — if true then don't sent a notification 955 | 956 | ### conceal 957 | 958 | 959 | ```lua 960 | function astrocore.toggles.conceal(silent?: boolean) 961 | ``` 962 | 963 | Toggle conceal=2|0 964 | 965 | *param* `silent` — if true then don't sent a notification 966 | 967 | ### diagnostics 968 | 969 | 970 | ```lua 971 | function astrocore.toggles.diagnostics(silent?: boolean) 972 | ``` 973 | 974 | Toggle diagnostics 975 | 976 | *param* `silent` — if true then don't sent a notification 977 | 978 | ### foldcolumn 979 | 980 | 981 | ```lua 982 | function astrocore.toggles.foldcolumn(silent?: boolean) 983 | ``` 984 | 985 | Toggle foldcolumn=0|1 986 | 987 | *param* `silent` — if true then don't sent a notification 988 | 989 | ### indent 990 | 991 | 992 | ```lua 993 | function astrocore.toggles.indent(silent?: boolean) 994 | ``` 995 | 996 | Set the indent and tab related numbers 997 | 998 | *param* `silent` — if true then don't sent a notification 999 | 1000 | ### notifications 1001 | 1002 | 1003 | ```lua 1004 | function astrocore.toggles.notifications(silent?: boolean) 1005 | ``` 1006 | 1007 | Toggle notifications for UI toggles 1008 | 1009 | *param* `silent` — if true then don't sent a notification 1010 | 1011 | ### number 1012 | 1013 | 1014 | ```lua 1015 | function astrocore.toggles.number(silent?: boolean) 1016 | ``` 1017 | 1018 | Change the number display modes 1019 | 1020 | *param* `silent` — if true then don't sent a notification 1021 | 1022 | ### paste 1023 | 1024 | 1025 | ```lua 1026 | function astrocore.toggles.paste(silent?: boolean) 1027 | ``` 1028 | 1029 | Toggle paste 1030 | 1031 | *param* `silent` — if true then don't sent a notification 1032 | 1033 | ### signcolumn 1034 | 1035 | 1036 | ```lua 1037 | function astrocore.toggles.signcolumn(silent?: boolean) 1038 | ``` 1039 | 1040 | Toggle signcolumn="auto"|"no" 1041 | 1042 | *param* `silent` — if true then don't sent a notification 1043 | 1044 | ### spell 1045 | 1046 | 1047 | ```lua 1048 | function astrocore.toggles.spell(silent?: boolean) 1049 | ``` 1050 | 1051 | Toggle spell 1052 | 1053 | *param* `silent` — if true then don't sent a notification 1054 | 1055 | ### statusline 1056 | 1057 | 1058 | ```lua 1059 | function astrocore.toggles.statusline(silent?: boolean) 1060 | ``` 1061 | 1062 | Toggle laststatus=3|2|0 1063 | 1064 | *param* `silent` — if true then don't sent a notification 1065 | 1066 | ### tabline 1067 | 1068 | 1069 | ```lua 1070 | function astrocore.toggles.tabline(silent?: boolean) 1071 | ``` 1072 | 1073 | Toggle showtabline=2|0 1074 | 1075 | *param* `silent` — if true then don't sent a notification 1076 | 1077 | ### url_match 1078 | 1079 | 1080 | ```lua 1081 | function astrocore.toggles.url_match(silent?: boolean) 1082 | ``` 1083 | 1084 | Toggle URL/URI syntax highlighting rules 1085 | 1086 | *param* `silent` — if true then don't sent a notification 1087 | 1088 | ### virtual_lines 1089 | 1090 | 1091 | ```lua 1092 | function astrocore.toggles.virtual_lines(silent?: boolean) 1093 | ``` 1094 | 1095 | Toggle diagnostics virtual lines 1096 | 1097 | *param* `silent` — if true then don't sent a notification 1098 | 1099 | ### virtual_text 1100 | 1101 | 1102 | ```lua 1103 | function astrocore.toggles.virtual_text(silent?: boolean) 1104 | ``` 1105 | 1106 | Toggle diagnostics virtual text 1107 | 1108 | *param* `silent` — if true then don't sent a notification 1109 | 1110 | ### wrap 1111 | 1112 | 1113 | ```lua 1114 | function astrocore.toggles.wrap(silent?: boolean) 1115 | ``` 1116 | 1117 | Toggle wrap 1118 | 1119 | *param* `silent` — if true then don't sent a notification 1120 | 1121 | 1122 | -------------------------------------------------------------------------------- /doc/astrocore.txt: -------------------------------------------------------------------------------- 1 | *astrocore.txt* For Neovim >= 0.9.0 Last change: 2025 April 30 2 | 3 | ============================================================================== 4 | Table of Contents *astrocore-table-of-contents* 5 | 6 | 1. AstroCore |astrocore-astrocore| 7 | - Features |astrocore-astrocore-features| 8 | - Requirements |astrocore-astrocore-requirements| 9 | - Installation |astrocore-astrocore-installation| 10 | - Configuration |astrocore-astrocore-configuration| 11 | - API |astrocore-astrocore-api| 12 | - Contributing |astrocore-astrocore-contributing| 13 | 2. Lua API |astrocore-lua-api| 14 | - astrocore |astrocore-lua-api-astrocore| 15 | - astrocore.buffer |astrocore-lua-api-astrocore.buffer| 16 | - astrocore.buffer.comparator|astrocore-lua-api-astrocore.buffer.comparator| 17 | - astrocore.rooter |astrocore-lua-api-astrocore.rooter| 18 | - astrocore.toggles |astrocore-lua-api-astrocore.toggles| 19 | 20 | ============================================================================== 21 | 1. AstroCore *astrocore-astrocore* 22 | 23 | AstroCore provides the core Lua API that powers AstroNvim 24 | . It provides an interface for 25 | configuration auto commands, user commands, on_key functions, key mappings, and 26 | more as well as a Lua API of common utility functions. 27 | 28 | 29 | FEATURES *astrocore-astrocore-features* 30 | 31 | - Unified interface for configuring auto commands, user commands, key maps, on key functions 32 | - Easy toggles of UI/UX elements and features 33 | - Universal interface for setting up git worktrees 34 | - Tab local buffer management for a clean `tabline` 35 | - Project root detection with automatic `cd` features 36 | - Session management with resession.nvim 37 | 38 | 39 | REQUIREMENTS *astrocore-astrocore-requirements* 40 | 41 | - Neovim >= 0.10 42 | - lazy.nvim 43 | - resession.nvim (_optional_) 44 | 45 | 46 | INSTALLATION *astrocore-astrocore-installation* 47 | 48 | Install the plugin with the lazy plugin manager: 49 | 50 | >lua 51 | return { 52 | "AstroNvim/astrocore", 53 | lazy = false, -- disable lazy loading 54 | priority = 10000, -- load AstroCore first 55 | opts = { 56 | -- set configuration options as described below 57 | }, 58 | } 59 | < 60 | 61 | 62 | If you want to enable session management with resession.nvim 63 | , enable it in the setup: 64 | >lua 65 | require("resession").setup { 66 | extensions = { 67 | astrocore = {}, 68 | }, 69 | } 70 | < 71 | 72 | 73 | CONFIGURATION *astrocore-astrocore-configuration* 74 | 75 | **AstroCore** comes with no defaults, but can be configured fully through the 76 | `opts` table in lazy. Here are descriptions of the options and some example 77 | usages: 78 | 79 | >lua 80 | ---@type AstroCoreConfig 81 | local opts = { 82 | -- easily configure auto commands 83 | autocmds = { 84 | -- first key is the `augroup` (:h augroup) 85 | highlighturl = { 86 | -- list of auto commands to set 87 | { 88 | -- events to trigger 89 | event = { "VimEnter", "FileType", "BufEnter", "WinEnter" }, 90 | -- the rest of the autocmd options (:h nvim_create_autocmd) 91 | desc = "URL Highlighting", 92 | callback = function() require("astrocore").set_url_match() end, 93 | }, 94 | }, 95 | }, 96 | -- easily configure user commands 97 | commands = { 98 | -- key is the command name 99 | AstroReload = { 100 | -- first element with no key is the command (string or function) 101 | function() require("astrocore").reload() end, 102 | -- the rest are options for creating user commands (:h nvim_create_user_command) 103 | desc = "Reload AstroNvim (Experimental)", 104 | }, 105 | }, 106 | -- Configure diagnostics options (`:h vim.diagnostic.config()`) 107 | diagnostics = { 108 | update_in_insert = false, 109 | }, 110 | -- passed to `vim.filetype.add` 111 | filetypes = { 112 | -- see `:h vim.filetype.add` for usage 113 | extension = { 114 | foo = "fooscript", 115 | }, 116 | filename = { 117 | [".foorc"] = "fooscript", 118 | }, 119 | pattern = { 120 | [".*/etc/foo/.*"] = "fooscript", 121 | }, 122 | }, 123 | -- Configuration of vim mappings to create 124 | mappings = { 125 | -- map mode (:h map-modes) 126 | n = { 127 | -- use vimscript strings for mappings 128 | [""] = { ":w!", desc = "Save File" }, 129 | -- navigate buffer tabs with `H` and `L` 130 | L = { 131 | function() require("astrocore.buffer").nav(vim.v.count1) end, 132 | desc = "Next buffer", 133 | }, 134 | H = { 135 | function() require("astrocore.buffer").nav(-vim.v.count1) end, 136 | desc = "Previous buffer", 137 | }, 138 | -- tables with just a `desc` key will be registered with which-key if it's installed 139 | -- this is useful for naming menus 140 | ["b"] = { desc = "Buffers" }, 141 | }, 142 | }, 143 | -- easily configure functions on key press 144 | on_keys = { 145 | -- first key is the namespace 146 | auto_hlsearch = { 147 | -- list of functions to execute on key press (:h vim.on_key) 148 | function(char) -- example automatically disables `hlsearch` when not actively searching 149 | if vim.fn.mode() == "n" then 150 | local new_hlsearch = vim.tbl_contains({ "", "n", "N", "*", "#", "?", "/" }, vim.fn.keytrans(char)) 151 | if vim.opt.hlsearch:get() ~= new_hlsearch then vim.opt.hlsearch = new_hlsearch end 152 | end 153 | end, 154 | }, 155 | }, 156 | -- easily configure vim options 157 | options = { 158 | -- first key is the type of option `vim.` 159 | opt = { 160 | relativenumber = true, -- sets `vim.opt.relativenumber` 161 | signcolumn = "auto", -- sets `vim.opt.relativenumber` 162 | }, 163 | g = { 164 | -- set global `vim.g` settings here 165 | }, 166 | }, 167 | -- configure AstroNvim features 168 | features = { 169 | autopairs = true, -- enable or disable autopairs on start 170 | cmp = true, -- enable or disable cmp on start 171 | diagnostics = { virtual_text = true, virtual_lines = false }, -- enable or disable diagnostics features on start 172 | highlighturl = true, -- enable or disable highlighting of urls on start 173 | -- table for defining the size of the max file for all features, above these limits we disable features like treesitter. 174 | large_buf = { 175 | -- whether to enable large file detection for a buffer (must return false to disable) 176 | -- first parameter is the buffer number, the second is the large buffer configuration table 177 | -- return values: 178 | -- - `true` or `nil` to continue and respects all changes made to the large buffer configuration table 179 | -- - `false` to disable large file detection for the buffer 180 | -- - a new table of large buffer options to use instead of the defaults 181 | enabled = function(bufnr, config) end, 182 | notify = true, -- whether or not to display a notification when a large file is detected 183 | size = 1024 * 100, -- max file size (or false to disable check) 184 | lines = 10000, -- max number of lines (or false to disable check) 185 | line_length = 1000, -- average line length (or false to disable check) 186 | }, 187 | notifications = true, -- enable or disable notifications on start 188 | }, 189 | -- Enable git integration for detached worktrees 190 | git_worktrees = { 191 | { toplevel = vim.env.HOME, gitdir = vim.env.HOME .. "/.dotfiles" }, 192 | }, 193 | -- Configure project root detection, check status with `:AstroRootInfo` 194 | rooter = { 195 | -- list of detectors in order of prevalence, elements can be: 196 | -- "lsp" : lsp detection 197 | -- string[] : a list of directory patterns to look for 198 | -- fun(bufnr: integer): string|string[] : a function that takes a buffer number and outputs detected roots 199 | detector = { 200 | "lsp", -- highest priority is getting workspace from running language servers 201 | { ".git", "_darcs", ".hg", ".bzr", ".svn" }, -- next check for a version controlled parent directory 202 | { "lua", "MakeFile", "package.json" }, -- lastly check for known project root files 203 | }, 204 | -- ignore things from root detection 205 | ignore = { 206 | servers = {}, -- list of language server names to ignore (Ex. { "efm" }) 207 | dirs = {}, -- list of directory patterns (Ex. { "~/.cargo/*" }) 208 | }, 209 | -- automatically update working directory (update manually with `:AstroRoot`) 210 | autochdir = false, 211 | -- scope of working directory to change ("global"|"tab"|"win") 212 | scope = "global", 213 | -- show notification on every working directory change 214 | notify = false, 215 | }, 216 | -- Configuration table of session options for AstroNvim's session management powered by Resession 217 | sessions = { 218 | -- Configure auto saving 219 | autosave = { 220 | last = true, -- auto save last session 221 | cwd = true, -- auto save session for each working directory 222 | }, 223 | -- Patterns to ignore when saving sessions 224 | ignore = { 225 | dirs = {}, -- working directories to ignore sessions in 226 | filetypes = { "gitcommit", "gitrebase" }, -- filetypes to ignore sessions 227 | buftypes = {}, -- buffer types to ignore sessions 228 | }, 229 | }, 230 | } 231 | < 232 | 233 | 234 | API *astrocore-astrocore-api* 235 | 236 | **AstroCore** provides a Lua API with utility functions. This can be viewed 237 | with |astrocore| or in the repository at doc/api.md 238 | 239 | 240 | CONTRIBUTING *astrocore-astrocore-contributing* 241 | 242 | If you plan to contribute, please check the contribution guidelines 243 | first. 244 | 245 | 246 | ============================================================================== 247 | 2. Lua API *astrocore-lua-api* 248 | 249 | astrocore API documentation 250 | 251 | 252 | ASTROCORE *astrocore-lua-api-astrocore* 253 | 254 | 255 | CMD ~ 256 | 257 | >lua 258 | function astrocore.cmd(cmd: string|string[], show_error?: boolean) 259 | -> result: string|nil 260 | < 261 | 262 | Run a shell command and capture the output and if the command succeeded or 263 | failed 264 | 265 | _param_ `cmd` — The terminal command to execute 266 | 267 | _param_ `show_error` — Whether or not to show an unsuccessful command as an 268 | error to the user 269 | 270 | _return_ `result` — The result of a successfully executed command or nil 271 | 272 | 273 | CONDITIONAL_FUNC ~ 274 | 275 | >lua 276 | function astrocore.conditional_func(func: function, condition: boolean, ...any) 277 | -> result: any 278 | < 279 | 280 | Call function if a condition is met 281 | 282 | _param_ `func` — The function to run 283 | 284 | _param_ `condition` — Whether to run the function or not 285 | 286 | _return_ `result` — the result of the function running or nil 287 | 288 | 289 | CONFIG ~ 290 | 291 | >lua 292 | AstroCoreOpts 293 | < 294 | 295 | The configuration as set by the user through the `setup()` function 296 | 297 | 298 | DELETE_URL_MATCH ~ 299 | 300 | >lua 301 | function astrocore.delete_url_match(win?: integer) 302 | < 303 | 304 | Delete the syntax matching rules for URLs/URIs if set 305 | 306 | _param_ `win` — the window id to remove url highlighting in (default: current 307 | window) 308 | 309 | 310 | EMPTY_MAP_TABLE ~ 311 | 312 | >lua 313 | function astrocore.empty_map_table() 314 | -> mappings: table 315 | < 316 | 317 | Get an empty table of mappings with a key for each map mode 318 | 319 | _return_ `mappings` — a table with entries for each map mode 320 | 321 | 322 | EVENT ~ 323 | 324 | >lua 325 | function astrocore.event(event: string|vim.api.keyset_exec_autocmds, instant?: boolean) 326 | < 327 | 328 | Trigger an AstroNvim user event 329 | 330 | _param_ `event` — The event pattern or full autocmd options (pattern always 331 | prepended with "Astro") 332 | 333 | _param_ `instant` — Whether or not to execute instantly or schedule 334 | 335 | 336 | EXEC_BUFFER_AUTOCMDS ~ 337 | 338 | >lua 339 | function astrocore.exec_buffer_autocmds(event: string|string[], opts: vim.api.keyset.exec_autocmds) 340 | < 341 | 342 | Execute autocommand across all valid buffers 343 | 344 | _param_ `event` — the event or events to execute 345 | 346 | _param_ `opts` — Dictionary of autocommnd options 347 | 348 | 349 | EXTEND_TBL ~ 350 | 351 | >lua 352 | function astrocore.extend_tbl(default?: table, opts?: table) 353 | -> extended: table 354 | < 355 | 356 | Merge extended options with a default table of options 357 | 358 | _param_ `default` — The default table that you want to merge into 359 | 360 | _param_ `opts` — The new options that should be merged with the default table 361 | 362 | _return_ `extended` — The extended table 363 | 364 | 365 | FILE_WORKTREE ~ 366 | 367 | >lua 368 | function astrocore.file_worktree(file?: string, worktrees?: table[]) 369 | -> worktree: table|nil 370 | < 371 | 372 | Get the first worktree that a file belongs to 373 | 374 | _param_ `file` — the file to check, defaults to the current file 375 | 376 | _param_ `worktrees` — an array like table of worktrees with entries 377 | `toplevel` and `gitdir`, default retrieves from `vim.g.git_worktrees` 378 | 379 | _return_ `worktree` — a table specifying the `toplevel` and `gitdir` of a 380 | worktree or nil if not found 381 | 382 | 383 | GET_PLUGIN ~ 384 | 385 | >lua 386 | function astrocore.get_plugin(plugin: string) 387 | -> spec: LazyPlugin? 388 | < 389 | 390 | Get a plugin spec from lazy 391 | 392 | _param_ `plugin` — The plugin to search for 393 | 394 | _return_ `spec` — The found plugin spec from Lazy 395 | 396 | 397 | IS_AVAILABLE ~ 398 | 399 | >lua 400 | function astrocore.is_available(plugin: string) 401 | -> available: boolean 402 | < 403 | 404 | Check if a plugin is defined in lazy. Useful with lazy loading when a plugin is 405 | not necessarily loaded yet 406 | 407 | _param_ `plugin` — The plugin to search for 408 | 409 | _return_ `available` — Whether the plugin is available 410 | 411 | 412 | LIST_INSERT_UNIQUE ~ 413 | 414 | >lua 415 | function astrocore.list_insert_unique(dst: any[]|nil, src: any[]) 416 | -> result: any[] 417 | < 418 | 419 | Insert one or more values into a list like table and maintain that you do not 420 | insert non-unique values (THIS MODIFIES `dst`) 421 | 422 | _param_ `dst` — The list like table that you want to insert into 423 | 424 | _param_ `src` — Values to be inserted 425 | 426 | _return_ `result` — The modified list like table 427 | 428 | 429 | LOAD_PLUGIN_WITH_FUNC ~ 430 | 431 | >lua 432 | function astrocore.load_plugin_with_func(plugin: string, module: table, funcs: string|string[]) 433 | < 434 | 435 | A helper function to wrap a module function to require a plugin before running 436 | 437 | _param_ `plugin` — The plugin to call `require("lazy").load` with 438 | 439 | _param_ `module` — The system module where the functions live 440 | (e.g. `vim.ui`) 441 | 442 | _param_ `funcs` — The functions to wrap in the given module (e.g. `"ui", 443 | "select"`) 444 | 445 | 446 | NORMALIZE_MAPPINGS ~ 447 | 448 | >lua 449 | function astrocore.normalize_mappings(mappings?: table?>) 450 | < 451 | 452 | Normalize a mappings table to use official keycode casing 453 | 454 | 455 | NOTIFY ~ 456 | 457 | >lua 458 | function astrocore.notify(msg: string, type: integer|nil, opts?: table) 459 | < 460 | 461 | Serve a notification with a title of AstroNvim 462 | 463 | _param_ `msg` — The notification body 464 | 465 | _param_ `type` — The type of the notification (:help vim.log.levels) 466 | 467 | _param_ `opts` — The nvim-notify options to use (:help notify-options) 468 | 469 | 470 | ON_LOAD ~ 471 | 472 | >lua 473 | function astrocore.on_load(plugins: string|string[], load_op: string|fun()|string[]) 474 | < 475 | 476 | Execute a function when a specified plugin is loaded with Lazy.nvim, or 477 | immediately if already loaded 478 | 479 | _param_ `plugins` — the name of the plugin or a list of plugins to defer the 480 | function execution on. If a list is provided, only one needs to be loaded to 481 | execute the provided function 482 | 483 | _param_ `load_op` — the function to execute when the plugin is loaded, a 484 | plugin name to load, or a list of plugin names to load 485 | 486 | 487 | PATCH_FUNC ~ 488 | 489 | >lua 490 | function astrocore.patch_func(orig?: function, override: fun(orig: function, ...any):...unknown) 491 | -> patched: function 492 | < 493 | 494 | Monkey patch into an existing function 495 | 496 | Example from |vim.paste()| `lua local patch_func = 497 | require("astrocore").patch_func vim.paste = patch_func(vim.paste, 498 | function(orig, lines, phase) for i, line in ipairs(lines) do -- Scrub ANSI 499 | color codes from paste input. lines[i] = line:gsub('\27%[[0-9;mK]+', '') end 500 | return orig(lines, phase) end)` 501 | 502 | _param_ `orig` — the original function to override, if `nil` is provided then 503 | an empty function is passed 504 | 505 | _param_ `override` — the override function 506 | 507 | _return_ `patched` — the new function with the patch applied 508 | 509 | 510 | PLUGIN_OPTS ~ 511 | 512 | >lua 513 | function astrocore.plugin_opts(plugin: string) 514 | -> opts: table 515 | < 516 | 517 | Resolve the options table for a given plugin with lazy 518 | 519 | _param_ `plugin` — The plugin to search for 520 | 521 | _return_ `opts` — The plugin options 522 | 523 | 524 | READ_FILE ~ 525 | 526 | >lua 527 | function astrocore.read_file(path: string) 528 | -> content: string 529 | < 530 | 531 | Helper function to read a file and return it’s content 532 | 533 | _param_ `path` — the path to the file to read 534 | 535 | _return_ `content` — the contents of the file 536 | 537 | 538 | RELOAD ~ 539 | 540 | >lua 541 | function astrocore.reload() 542 | < 543 | 544 | Partially reload AstroNvim user settings. Includes core vim options, mappings, 545 | and highlights. This is an experimental feature and may lead to instabilities 546 | until restart. 547 | 548 | 549 | RENAME_FILE ~ 550 | 551 | >lua 552 | function astrocore.rename_file(opts?: AstroCoreRenameFileOpts) 553 | < 554 | 555 | Prompt the user to rename a file 556 | 557 | _param_ `opts` — optional fields for file renaming 558 | 559 | 560 | SET_MAPPINGS ~ 561 | 562 | >lua 563 | function astrocore.set_mappings(map_table: table?>, base?: vim.keymap.set.Opts) 564 | < 565 | 566 | Table based API for setting keybindings 567 | 568 | _param_ `map_table` — A nested table where the first key is the vim mode, the 569 | second key is the key to map, and the value is the function to set the mapping 570 | to 571 | 572 | _param_ `base` — A base set of options to set on every keybinding 573 | 574 | 575 | SET_URL_MATCH ~ 576 | 577 | >lua 578 | function astrocore.set_url_match(win?: integer) 579 | < 580 | 581 | Add syntax matching rules for highlighting URLs/URIs 582 | 583 | _param_ `win` — the window id to remove url highlighting in (default: current 584 | window) 585 | 586 | 587 | SETUP ~ 588 | 589 | >lua 590 | function astrocore.setup(opts: AstroCoreOpts) 591 | < 592 | 593 | Setup and configure AstroCore See: astrocore.config 594 | 595 | 596 | 597 | TOGGLE_TERM_CMD ~ 598 | 599 | >lua 600 | function astrocore.toggle_term_cmd(opts: string|table) 601 | < 602 | 603 | Toggle a user terminal if it exists, if not then create a new one and save it 604 | 605 | _param_ `opts` — A terminal command string or a table of options for 606 | Terminal:new() (Check toggleterm.nvim documentation for table format) 607 | 608 | 609 | UNIQUE_LIST ~ 610 | 611 | >lua 612 | function astrocore.unique_list(list: any[]) 613 | -> result: any[] 614 | < 615 | 616 | Remove duplicate entries from a given list (does not mutate the original list) 617 | 618 | _param_ `list` — The list like table that you want to remove duplicates from 619 | 620 | _return_ `result` — The list like table of unique values 621 | 622 | 623 | UPDATE_PACKAGES ~ 624 | 625 | >lua 626 | function astrocore.update_packages() 627 | < 628 | 629 | Sync Lazy and then update Mason 630 | 631 | 632 | URL_MATCHER ~ 633 | 634 | >lua 635 | string 636 | < 637 | 638 | regex used for matching a valid URL/URI string 639 | 640 | 641 | USER_TERMINALS ~ 642 | 643 | >lua 644 | { [string]: table } 645 | < 646 | 647 | A table to manage ToggleTerm terminals created by the user, indexed by the 648 | command run and then the instance number 649 | 650 | 651 | WHICH_KEY_QUEUE ~ 652 | 653 | >lua 654 | nil 655 | < 656 | 657 | A placeholder variable used to queue section names to be registered by 658 | which-key 659 | 660 | 661 | WHICH_KEY_REGISTER ~ 662 | 663 | >lua 664 | function astrocore.which_key_register() 665 | < 666 | 667 | Register queued which-key mappings 668 | 669 | 670 | WITH_FILE ~ 671 | 672 | >lua 673 | function astrocore.with_file(filename: string, mode?: "a"|"a+"|"a+b"|"ab"|"r"...(+7), callback?: fun(file: file*), on_error?: fun(err: string)) 674 | < 675 | 676 | Execute function with open file 677 | 678 | _param_ `filename` — path to file to interact with 679 | 680 | _param_ `mode` — the mode in which to open the file 681 | 682 | _param_ `callback` — the callback to execute with the opened file 683 | 684 | _param_ `on_error` — the callback to execute if unable to open the file 685 | 686 | >lua 687 | mode: 688 | -> "r" -- Read mode. 689 | | "w" -- Write mode. 690 | | "a" -- Append mode. 691 | | "r+" -- Update mode, all previous data is preserved. 692 | | "w+" -- Update mode, all previous data is erased. 693 | | "a+" -- Append update mode, previous data is preserved, writing is only allowed at the end of file. 694 | | "rb" -- Read mode. (in binary mode.) 695 | | "wb" -- Write mode. (in binary mode.) 696 | | "ab" -- Append mode. (in binary mode.) 697 | | "r+b" -- Update mode, all previous data is preserved. (in binary mode.) 698 | | "w+b" -- Update mode, all previous data is erased. (in binary mode.) 699 | | "a+b" -- Append update mode, previous data is preserved, writing is only allowed at the end of file. (in binary mode.) 700 | < 701 | 702 | 703 | ASTROCORE.BUFFER *astrocore-lua-api-astrocore.buffer* 704 | 705 | 706 | CLOSE ~ 707 | 708 | >lua 709 | function astrocore.buffer.close(bufnr?: integer, force?: boolean) 710 | < 711 | 712 | Close a given buffer 713 | 714 | _param_ `bufnr` — The buffer to close or the current buffer if not provided 715 | 716 | _param_ `force` — Whether or not to foce close the buffers or confirm changes 717 | (default: false) 718 | 719 | 720 | CLOSE_ALL ~ 721 | 722 | >lua 723 | function astrocore.buffer.close_all(keep_current?: boolean, force?: boolean) 724 | < 725 | 726 | Close all buffers 727 | 728 | _param_ `keep_current` — Whether or not to keep the current buffer (default: 729 | false) 730 | 731 | _param_ `force` — Whether or not to foce close the buffers or confirm changes 732 | (default: false) 733 | 734 | 735 | CLOSE_LEFT ~ 736 | 737 | >lua 738 | function astrocore.buffer.close_left(force?: boolean) 739 | < 740 | 741 | Close buffers to the left of the current buffer 742 | 743 | _param_ `force` — Whether or not to foce close the buffers or confirm changes 744 | (default: false) 745 | 746 | 747 | CLOSE_RIGHT ~ 748 | 749 | >lua 750 | function astrocore.buffer.close_right(force?: boolean) 751 | < 752 | 753 | Close buffers to the right of the current buffer 754 | 755 | _param_ `force` — Whether or not to foce close the buffers or confirm changes 756 | (default: false) 757 | 758 | 759 | CLOSE_TAB ~ 760 | 761 | >lua 762 | function astrocore.buffer.close_tab(tabpage?: integer) 763 | < 764 | 765 | Close a given tab 766 | 767 | _param_ `tabpage` — The tabpage to close or the current tab if not provided 768 | 769 | 770 | CURRENT_BUF ~ 771 | 772 | >lua 773 | nil 774 | < 775 | 776 | Placeholders for keeping track of most recent and previous buffer 777 | 778 | 779 | HAS_FILETYPE ~ 780 | 781 | >lua 782 | function astrocore.buffer.has_filetype(bufnr?: integer) 783 | -> boolean 784 | < 785 | 786 | Check if a buffer has a filetype 787 | 788 | _param_ `bufnr` — The buffer to check, default to current buffer 789 | 790 | _return_ — Whether the buffer has a filetype or not 791 | 792 | 793 | IS_LARGE ~ 794 | 795 | >lua 796 | function astrocore.buffer.is_large(bufnr?: integer, large_buf_opts?: AstroCoreMaxFile) 797 | -> is_large: boolean 798 | < 799 | 800 | Check if a buffer is a large buffer (always returns false if large buffer 801 | detection is disabled) 802 | 803 | _param_ `bufnr` — the buffer to check the size of, default to current buffer 804 | 805 | _param_ `large_buf_opts` — large buffer parameters, default to AstroCore 806 | configuration 807 | 808 | _return_ `is_large` — whether the buffer is detected as large or not 809 | 810 | 811 | IS_RESTORABLE ~ 812 | 813 | >lua 814 | function astrocore.buffer.is_restorable(bufnr: integer) 815 | -> boolean 816 | < 817 | 818 | Check if a buffer can be restored 819 | 820 | _param_ `bufnr` — The buffer to check 821 | 822 | _return_ — Whether the buffer is restorable or not 823 | 824 | 825 | IS_VALID ~ 826 | 827 | >lua 828 | function astrocore.buffer.is_valid(bufnr?: integer) 829 | -> boolean 830 | < 831 | 832 | Check if a buffer is valid 833 | 834 | _param_ `bufnr` — The buffer to check, default to current buffer 835 | 836 | _return_ — Whether the buffer is valid or not 837 | 838 | 839 | IS_VALID_SESSION ~ 840 | 841 | >lua 842 | function astrocore.buffer.is_valid_session() 843 | -> boolean 844 | < 845 | 846 | Check if the current buffers form a valid session 847 | 848 | _return_ — Whether the current session of buffers is a valid session 849 | 850 | 851 | LAST_BUF ~ 852 | 853 | >lua 854 | nil 855 | < 856 | 857 | 858 | MOVE ~ 859 | 860 | >lua 861 | function astrocore.buffer.move(n: integer) 862 | < 863 | 864 | Move the current buffer tab n places in the bufferline 865 | 866 | _param_ `n` — The number of tabs to move the current buffer over by (positive 867 | = right, negative = left) 868 | 869 | 870 | NAV ~ 871 | 872 | >lua 873 | function astrocore.buffer.nav(n: integer) 874 | < 875 | 876 | Navigate left and right by n places in the bufferline 877 | 878 | _param_ `n` — The number of tabs to navigate to (positive = right, negative = 879 | left) 880 | 881 | 882 | NAV_TO ~ 883 | 884 | >lua 885 | function astrocore.buffer.nav_to(tabnr: integer) 886 | < 887 | 888 | Navigate to a specific buffer by its position in the bufferline 889 | 890 | _param_ `tabnr` — The position of the buffer to navigate to 891 | 892 | 893 | PREV ~ 894 | 895 | >lua 896 | function astrocore.buffer.prev() 897 | < 898 | 899 | Navigate to the previously used buffer 900 | 901 | 902 | SORT ~ 903 | 904 | >lua 905 | function astrocore.buffer.sort(compare_func: string|function, skip_autocmd: boolean|nil) 906 | -> boolean 907 | < 908 | 909 | Sort a the buffers in the current tab based on some comparator 910 | 911 | _param_ `compare_func` — a string of a comparator defined in 912 | require("astrocore.buffer.comparator") or a custom comparator function 913 | 914 | _param_ `skip_autocmd` — whether or not to skip triggering AstroBufsUpdated 915 | autocmd event 916 | 917 | _return_ — Whether or not the buffers were sorted 918 | 919 | 920 | WIPE ~ 921 | 922 | >lua 923 | function astrocore.buffer.wipe(bufnr?: integer, force?: boolean) 924 | < 925 | 926 | Fully wipeout a given buffer 927 | 928 | _param_ `bufnr` — The buffer to wipe or the current buffer if not provided 929 | 930 | _param_ `force` — Whether or not to foce close the buffers or confirm changes 931 | (default: false) 932 | 933 | 934 | ASTROCORE.BUFFER.COMPARATOR *astrocore-lua-api-astrocore.buffer.comparator* 935 | 936 | 937 | BUFNR ~ 938 | 939 | >lua 940 | function astrocore.buffer.comparator.bufnr(bufnr_a: integer, bufnr_b: integer) 941 | -> comparison: boolean 942 | < 943 | 944 | Comparator of two buffer numbers 945 | 946 | _param_ `bufnr_a` — buffer number A 947 | 948 | _param_ `bufnr_b` — buffer number B 949 | 950 | _return_ `comparison` — true if A is sorted before B, false if B should be 951 | sorted before A 952 | 953 | 954 | EXTENSION ~ 955 | 956 | >lua 957 | function astrocore.buffer.comparator.extension(bufnr_a: integer, bufnr_b: integer) 958 | -> comparison: boolean 959 | < 960 | 961 | Comparator of two buffer numbers based on the file extensions 962 | 963 | _param_ `bufnr_a` — buffer number A 964 | 965 | _param_ `bufnr_b` — buffer number B 966 | 967 | _return_ `comparison` — true if A is sorted before B, false if B should be 968 | sorted before A 969 | 970 | 971 | FULL_PATH ~ 972 | 973 | >lua 974 | function astrocore.buffer.comparator.full_path(bufnr_a: integer, bufnr_b: integer) 975 | -> comparison: boolean 976 | < 977 | 978 | Comparator of two buffer numbers based on the full path 979 | 980 | _param_ `bufnr_a` — buffer number A 981 | 982 | _param_ `bufnr_b` — buffer number B 983 | 984 | _return_ `comparison` — true if A is sorted before B, false if B should be 985 | sorted before A 986 | 987 | 988 | MODIFIED ~ 989 | 990 | >lua 991 | function astrocore.buffer.comparator.modified(bufnr_a: integer, bufnr_b: integer) 992 | -> comparison: boolean 993 | < 994 | 995 | Comparator of two buffers based on modification date 996 | 997 | _param_ `bufnr_a` — buffer number A 998 | 999 | _param_ `bufnr_b` — buffer number B 1000 | 1001 | _return_ `comparison` — true if A is sorted before B, false if B should be 1002 | sorted before A 1003 | 1004 | 1005 | UNIQUE_PATH ~ 1006 | 1007 | >lua 1008 | function astrocore.buffer.comparator.unique_path(bufnr_a: integer, bufnr_b: integer) 1009 | -> comparison: boolean 1010 | < 1011 | 1012 | Comparator of two buffers based on their unique path 1013 | 1014 | _param_ `bufnr_a` — buffer number A 1015 | 1016 | _param_ `bufnr_b` — buffer number B 1017 | 1018 | _return_ `comparison` — true if A is sorted before B, false if B should be 1019 | sorted before A 1020 | 1021 | 1022 | ASTROCORE.ROOTER *astrocore-lua-api-astrocore.rooter* 1023 | 1024 | 1025 | BUFPATH ~ 1026 | 1027 | >lua 1028 | function astrocore.rooter.bufpath(bufnr: integer) 1029 | -> path: string? 1030 | < 1031 | 1032 | Get the real path of a buffer 1033 | 1034 | _param_ `bufnr` — the buffer 1035 | 1036 | _return_ `path` — the real path 1037 | 1038 | 1039 | DETECT ~ 1040 | 1041 | >lua 1042 | function astrocore.rooter.detect(bufnr?: integer, all?: boolean, config?: AstroCoreRooterOpts) 1043 | -> detected: AstroCoreRooterRoot[] 1044 | < 1045 | 1046 | Detect roots in a given buffer 1047 | 1048 | _param_ `bufnr` — the buffer to detect 1049 | 1050 | _param_ `all` — whether to return all roots or just one 1051 | 1052 | _param_ `config` — a rooter configuration (defaults to global configuration) 1053 | 1054 | _return_ `detected` — roots 1055 | 1056 | 1057 | EXISTS ~ 1058 | 1059 | >lua 1060 | function astrocore.rooter.exists(path: string) 1061 | -> exists: boolean 1062 | < 1063 | 1064 | Check if a path exists 1065 | 1066 | _param_ `path` — the path 1067 | 1068 | _return_ `exists` — whether or not the path exists 1069 | 1070 | 1071 | INFO ~ 1072 | 1073 | >lua 1074 | function astrocore.rooter.info(config?: AstroCoreRooterOpts) 1075 | < 1076 | 1077 | Get information information about the current root 1078 | 1079 | _param_ `config` — a rooter configuration (defaults to global configuration) 1080 | 1081 | 1082 | IS_EXCLUDED ~ 1083 | 1084 | >lua 1085 | function astrocore.rooter.is_excluded(path: string, config?: AstroCoreRooterOpts) 1086 | -> excluded: boolean 1087 | < 1088 | 1089 | Check if a path is excluded 1090 | 1091 | _param_ `path` — the path 1092 | 1093 | _param_ `config` — a rooter configuration (defaults to global configuration) 1094 | 1095 | _return_ `excluded` — whether or not the path is excluded 1096 | 1097 | 1098 | NORMPATH ~ 1099 | 1100 | >lua 1101 | function astrocore.rooter.normpath(path: string) 1102 | -> string 1103 | < 1104 | 1105 | Normalize path 1106 | 1107 | 1108 | REALPATH ~ 1109 | 1110 | >lua 1111 | function astrocore.rooter.realpath(path?: string) 1112 | -> the: string? 1113 | < 1114 | 1115 | Resolve a given path 1116 | 1117 | _param_ `path` — the path to resolve 1118 | 1119 | _return_ `the` — resolved path 1120 | 1121 | 1122 | RESOLVE ~ 1123 | 1124 | >lua 1125 | function astrocore.rooter.resolve(spec: string|fun(bufnr: integer):string|string[]|nil|string[], config?: AstroCoreRooterOpts) 1126 | -> function 1127 | < 1128 | 1129 | Resolve the root detection function for a given spec 1130 | 1131 | _param_ `spec` — the root detector specification 1132 | 1133 | _param_ `config` — the root configuration 1134 | 1135 | 1136 | ROOT ~ 1137 | 1138 | >lua 1139 | function astrocore.rooter.root(bufnr?: integer, config?: AstroCoreRooterOpts) 1140 | < 1141 | 1142 | Run the root detection and set the current working directory if a new root is 1143 | detected 1144 | 1145 | _param_ `bufnr` — the buffer to detect 1146 | 1147 | _param_ `config` — a rooter configuration (defaults to global configuration) 1148 | 1149 | 1150 | SET_PWD ~ 1151 | 1152 | >lua 1153 | function astrocore.rooter.set_pwd(root: AstroCoreRooterRoot, config?: AstroCoreRooterOpts) 1154 | -> success: boolean 1155 | < 1156 | 1157 | Set the current directory to a given root 1158 | 1159 | _param_ `root` — the root to set the pwd to 1160 | 1161 | _param_ `config` — a rooter configuration (defaults to global configuration) 1162 | 1163 | _return_ `success` — whether or not the pwd was successfully set 1164 | 1165 | 1166 | ASTROCORE.TOGGLES *astrocore-lua-api-astrocore.toggles* 1167 | 1168 | 1169 | AUTOCHDIR ~ 1170 | 1171 | >lua 1172 | function astrocore.toggles.autochdir(silent?: boolean) 1173 | < 1174 | 1175 | Toggle rooter autochdir 1176 | 1177 | _param_ `silent` — if true then don’t sent a notification 1178 | 1179 | 1180 | AUTOPAIRS ~ 1181 | 1182 | >lua 1183 | function astrocore.toggles.autopairs(silent?: boolean) 1184 | < 1185 | 1186 | Toggle autopairs 1187 | 1188 | _param_ `silent` — if true then don’t sent a notification 1189 | 1190 | 1191 | BACKGROUND ~ 1192 | 1193 | >lua 1194 | function astrocore.toggles.background(silent?: boolean) 1195 | < 1196 | 1197 | Toggle background="dark"|"light" 1198 | 1199 | _param_ `silent` — if true then don’t sent a notification 1200 | 1201 | 1202 | BUFFER_CMP ~ 1203 | 1204 | >lua 1205 | function astrocore.toggles.buffer_cmp(bufnr?: integer, silent?: boolean) 1206 | < 1207 | 1208 | Toggle buffer local cmp 1209 | 1210 | _param_ `bufnr` — the buffer to toggle cmp completion on 1211 | 1212 | _param_ `silent` — if true then don’t sent a notification 1213 | 1214 | 1215 | BUFFER_SYNTAX ~ 1216 | 1217 | >lua 1218 | function astrocore.toggles.buffer_syntax(bufnr?: integer, silent?: boolean) 1219 | < 1220 | 1221 | Toggle syntax highlighting and treesitter 1222 | 1223 | _param_ `bufnr` — the buffer to toggle syntax on 1224 | 1225 | _param_ `silent` — if true then don’t sent a notification 1226 | 1227 | 1228 | CMP ~ 1229 | 1230 | >lua 1231 | function astrocore.toggles.cmp(silent?: boolean) 1232 | < 1233 | 1234 | Toggle cmp entrirely 1235 | 1236 | _param_ `silent` — if true then don’t sent a notification 1237 | 1238 | 1239 | CONCEAL ~ 1240 | 1241 | >lua 1242 | function astrocore.toggles.conceal(silent?: boolean) 1243 | < 1244 | 1245 | Toggle conceal=2|0 1246 | 1247 | _param_ `silent` — if true then don’t sent a notification 1248 | 1249 | 1250 | DIAGNOSTICS ~ 1251 | 1252 | >lua 1253 | function astrocore.toggles.diagnostics(silent?: boolean) 1254 | < 1255 | 1256 | Toggle diagnostics 1257 | 1258 | _param_ `silent` — if true then don’t sent a notification 1259 | 1260 | 1261 | FOLDCOLUMN ~ 1262 | 1263 | >lua 1264 | function astrocore.toggles.foldcolumn(silent?: boolean) 1265 | < 1266 | 1267 | Toggle foldcolumn=0|1 1268 | 1269 | _param_ `silent` — if true then don’t sent a notification 1270 | 1271 | 1272 | INDENT ~ 1273 | 1274 | >lua 1275 | function astrocore.toggles.indent(silent?: boolean) 1276 | < 1277 | 1278 | Set the indent and tab related numbers 1279 | 1280 | _param_ `silent` — if true then don’t sent a notification 1281 | 1282 | 1283 | NOTIFICATIONS ~ 1284 | 1285 | >lua 1286 | function astrocore.toggles.notifications(silent?: boolean) 1287 | < 1288 | 1289 | Toggle notifications for UI toggles 1290 | 1291 | _param_ `silent` — if true then don’t sent a notification 1292 | 1293 | 1294 | NUMBER ~ 1295 | 1296 | >lua 1297 | function astrocore.toggles.number(silent?: boolean) 1298 | < 1299 | 1300 | Change the number display modes 1301 | 1302 | _param_ `silent` — if true then don’t sent a notification 1303 | 1304 | 1305 | PASTE ~ 1306 | 1307 | >lua 1308 | function astrocore.toggles.paste(silent?: boolean) 1309 | < 1310 | 1311 | Toggle paste 1312 | 1313 | _param_ `silent` — if true then don’t sent a notification 1314 | 1315 | 1316 | SIGNCOLUMN ~ 1317 | 1318 | >lua 1319 | function astrocore.toggles.signcolumn(silent?: boolean) 1320 | < 1321 | 1322 | Toggle signcolumn="auto"|"no" 1323 | 1324 | _param_ `silent` — if true then don’t sent a notification 1325 | 1326 | 1327 | SPELL ~ 1328 | 1329 | >lua 1330 | function astrocore.toggles.spell(silent?: boolean) 1331 | < 1332 | 1333 | Toggle spell 1334 | 1335 | _param_ `silent` — if true then don’t sent a notification 1336 | 1337 | 1338 | STATUSLINE ~ 1339 | 1340 | >lua 1341 | function astrocore.toggles.statusline(silent?: boolean) 1342 | < 1343 | 1344 | Toggle laststatus=3|2|0 1345 | 1346 | _param_ `silent` — if true then don’t sent a notification 1347 | 1348 | 1349 | TABLINE ~ 1350 | 1351 | >lua 1352 | function astrocore.toggles.tabline(silent?: boolean) 1353 | < 1354 | 1355 | Toggle showtabline=2|0 1356 | 1357 | _param_ `silent` — if true then don’t sent a notification 1358 | 1359 | 1360 | URL_MATCH ~ 1361 | 1362 | >lua 1363 | function astrocore.toggles.url_match(silent?: boolean) 1364 | < 1365 | 1366 | Toggle URL/URI syntax highlighting rules 1367 | 1368 | _param_ `silent` — if true then don’t sent a notification 1369 | 1370 | 1371 | VIRTUAL_LINES ~ 1372 | 1373 | >lua 1374 | function astrocore.toggles.virtual_lines(silent?: boolean) 1375 | < 1376 | 1377 | Toggle diagnostics virtual lines 1378 | 1379 | _param_ `silent` — if true then don’t sent a notification 1380 | 1381 | 1382 | VIRTUAL_TEXT ~ 1383 | 1384 | >lua 1385 | function astrocore.toggles.virtual_text(silent?: boolean) 1386 | < 1387 | 1388 | Toggle diagnostics virtual text 1389 | 1390 | _param_ `silent` — if true then don’t sent a notification 1391 | 1392 | 1393 | WRAP ~ 1394 | 1395 | >lua 1396 | function astrocore.toggles.wrap(silent?: boolean) 1397 | < 1398 | 1399 | Toggle wrap 1400 | 1401 | _param_ `silent` — if true then don’t sent a notification 1402 | 1403 | Generated by panvimdoc 1404 | 1405 | vim:tw=78:ts=8:noet:ft=help:norl: 1406 | -------------------------------------------------------------------------------- /lazy.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "AstroNvim/astrocore", 3 | opts_extend = { 4 | "rooter.ignore.servers", 5 | "rooter.ignore.dirs", 6 | "sessions.ignore.buftypes", 7 | "sessions.ignore.dirs", 8 | "sessions.ignore.filetypes", 9 | "git_worktrees", 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /lua/astrocore/buffer.lua: -------------------------------------------------------------------------------- 1 | ---AstroNvim Buffer Utilities 2 | --- 3 | ---Buffer management related utility functions 4 | --- 5 | ---This module can be loaded with `local buffer_utils = require "astrocore.buffer"` 6 | --- 7 | ---copyright 2023 8 | ---license GNU General Public License v3.0 9 | ---@class astrocore.buffer 10 | local M = {} 11 | 12 | local astro = require "astrocore" 13 | 14 | --- Placeholders for keeping track of most recent and previous buffer 15 | M.current_buf, M.last_buf = nil, nil 16 | 17 | --- Check if a buffer is valid 18 | ---@param bufnr? integer The buffer to check, default to current buffer 19 | ---@return boolean # Whether the buffer is valid or not 20 | function M.is_valid(bufnr) 21 | if not bufnr then bufnr = 0 end 22 | return vim.api.nvim_buf_is_valid(bufnr) and vim.bo[bufnr].buflisted 23 | end 24 | 25 | local large_buf_cache, buf_size_cache = {}, {} -- cache large buffer detection results and buffer sizes 26 | --- Check if a buffer is a large buffer (always returns false if large buffer detection is disabled) 27 | ---@param bufnr? integer the buffer to check the size of, default to current buffer 28 | ---@param large_buf_opts? AstroCoreMaxFile large buffer parameters, default to AstroCore configuration 29 | ---@return boolean is_large whether the buffer is detected as large or not 30 | function M.is_large(bufnr, large_buf_opts) 31 | if not bufnr then bufnr = vim.api.nvim_get_current_buf() end 32 | local skip_cache = large_buf_opts ~= nil -- skip cache when called manually with custom options 33 | if not large_buf_opts then large_buf_opts = vim.tbl_get(astro.config, "features", "large_buf") end 34 | if large_buf_opts then 35 | if skip_cache or large_buf_cache[bufnr] == nil then 36 | local enabled = vim.tbl_get(large_buf_opts, "enabled") 37 | if type(enabled) == "function" then 38 | large_buf_opts = vim.deepcopy(large_buf_opts) 39 | enabled = enabled(bufnr, large_buf_opts) 40 | if type(enabled) == "table" then large_buf_opts = enabled end 41 | end 42 | local large_buf = false 43 | if vim.F.if_nil(enabled, true) then 44 | if not buf_size_cache[bufnr] then 45 | local ok, stats = pcall(vim.uv.fs_stat, vim.api.nvim_buf_get_name(bufnr)) 46 | buf_size_cache[bufnr] = ok and stats and stats.size or 0 47 | end 48 | local file_size = buf_size_cache[bufnr] 49 | local line_count = vim.api.nvim_buf_line_count(bufnr) 50 | local too_large = large_buf_opts.size and file_size > large_buf_opts.size 51 | local too_long = large_buf_opts.lines and line_count > large_buf_opts.lines 52 | local too_wide = large_buf_opts.line_length and (file_size / line_count) - 1 > large_buf_opts.line_length 53 | large_buf = too_large or too_long or too_wide or false 54 | end 55 | if skip_cache then return large_buf end 56 | large_buf_cache[bufnr] = large_buf 57 | end 58 | return large_buf_cache[bufnr] 59 | end 60 | return false 61 | end 62 | 63 | --- Check if a buffer has a filetype 64 | ---@param bufnr? integer The buffer to check, default to current buffer 65 | ---@return boolean # Whether the buffer has a filetype or not 66 | function M.has_filetype(bufnr) 67 | if not bufnr then bufnr = 0 end 68 | local filetype = vim.bo[bufnr].filetype 69 | return filetype ~= nil and filetype ~= "" 70 | end 71 | 72 | --- Check if a buffer can be restored 73 | ---@param bufnr integer The buffer to check 74 | ---@return boolean # Whether the buffer is restorable or not 75 | function M.is_restorable(bufnr) 76 | if not M.is_valid(bufnr) or vim.bo[bufnr].bufhidden ~= "" then return false end 77 | 78 | if vim.bo[bufnr].buftype == "" then 79 | -- Normal buffer, check if it listed. 80 | if not vim.bo[bufnr].buflisted then return false end 81 | -- Check if it has a filename. 82 | if vim.api.nvim_buf_get_name(bufnr) == "" then return false end 83 | end 84 | 85 | local session_ignore = vim.tbl_get(astro.config, "sessions", "ignore") or {} 86 | if 87 | vim.tbl_contains(vim.tbl_get(session_ignore, "filetypes") or {}, vim.bo[bufnr].filetype) 88 | or vim.tbl_contains(vim.tbl_get(session_ignore, "buftypes") or {}, vim.bo[bufnr].buftype) 89 | then 90 | return false 91 | end 92 | return true 93 | end 94 | 95 | --- Check if the current buffers form a valid session 96 | ---@return boolean # Whether the current session of buffers is a valid session 97 | function M.is_valid_session() 98 | local cwd = vim.fn.getcwd() 99 | for _, dir in ipairs(vim.tbl_get(astro.config, "sessions", "ignore", "dirs") or {}) do 100 | if vim.fn.expand(dir) == cwd then return false end 101 | end 102 | for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do 103 | if M.is_restorable(bufnr) then return true end 104 | end 105 | return false 106 | end 107 | 108 | --- Move the current buffer tab n places in the bufferline 109 | ---@param n integer The number of tabs to move the current buffer over by (positive = right, negative = left) 110 | function M.move(n) 111 | if n == 0 then return end -- if n = 0 then no shifts are needed 112 | local bufs = vim.t.bufs -- make temp variable 113 | for i, bufnr in ipairs(bufs) do -- loop to find current buffer 114 | if bufnr == vim.api.nvim_get_current_buf() then -- found index of current buffer 115 | for _ = 0, (n % #bufs) - 1 do -- calculate number of right shifts 116 | local new_i = i + 1 -- get next i 117 | if i == #bufs then -- if at end, cycle to beginning 118 | new_i = 1 -- next i is actually 1 if at the end 119 | local val = bufs[i] -- save value 120 | table.remove(bufs, i) -- remove from end 121 | table.insert(bufs, new_i, val) -- insert at beginning 122 | else -- if not at the end,then just do an in place swap 123 | bufs[i], bufs[new_i] = bufs[new_i], bufs[i] 124 | end 125 | i = new_i -- iterate i to next value 126 | end 127 | break 128 | end 129 | end 130 | vim.t.bufs = bufs -- set buffers 131 | astro.event "BufsUpdated" 132 | vim.cmd.redrawtabline() -- redraw tabline 133 | end 134 | 135 | --- Navigate left and right by n places in the bufferline 136 | ---@param n integer The number of tabs to navigate to (positive = right, negative = left) 137 | function M.nav(n) 138 | local current = vim.api.nvim_get_current_buf() 139 | for i, v in ipairs(vim.t.bufs) do 140 | if current == v then 141 | local new_buf = vim.t.bufs[(i + n - 1) % #vim.t.bufs + 1] 142 | if new_buf ~= current then vim.api.nvim_set_current_buf(new_buf) end 143 | return 144 | end 145 | end 146 | end 147 | 148 | --- Navigate to a specific buffer by its position in the bufferline 149 | ---@param tabnr integer The position of the buffer to navigate to 150 | function M.nav_to(tabnr) 151 | if tabnr > #vim.t.bufs or tabnr < 1 then 152 | astro.notify(("No tab #%d"):format(tabnr), vim.log.levels.WARN) 153 | else 154 | local new_buf = vim.t.bufs[tabnr] 155 | if vim.api.nvim_get_current_buf() ~= new_buf then vim.api.nvim_set_current_buf(new_buf) end 156 | end 157 | end 158 | 159 | --- Navigate to the previously used buffer 160 | function M.prev() 161 | if vim.api.nvim_get_current_buf() == M.current_buf then 162 | if M.last_buf and M.is_valid(M.last_buf) then 163 | vim.api.nvim_set_current_buf(M.last_buf) 164 | else 165 | astro.notify("Previous buffer not found", vim.log.levels.WARN) 166 | end 167 | else 168 | astro.notify("Must be in a main editor window to switch the window buffer", vim.log.levels.ERROR) 169 | end 170 | end 171 | 172 | --- Helper function to power a save confirmation prompt before `mini.bufremove` 173 | ---@param func fun(bufnr:integer,force:boolean?) The function to execute if confirmation is passed 174 | ---@param bufnr integer The buffer to close or the current buffer if not provided 175 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 176 | local function mini_confirm(func, bufnr, force) 177 | if not force and vim.bo[bufnr].modified then 178 | local bufname = vim.fn.expand "%" 179 | local empty = bufname == "" 180 | if empty then bufname = "Untitled" end 181 | local confirm = vim.fn.confirm(('Save changes to "%s"?'):format(bufname), "&Yes\n&No\n&Cancel", 1, "Question") 182 | if confirm == 1 then 183 | if empty then return end 184 | vim.cmd.write() 185 | elseif confirm == 2 then 186 | force = true 187 | else 188 | return 189 | end 190 | end 191 | func(bufnr, force) 192 | end 193 | 194 | --- Close a given buffer 195 | ---@param bufnr? integer The buffer to close or the current buffer if not provided 196 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 197 | function M.close(bufnr, force) 198 | if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end 199 | if M.is_valid(bufnr) and #vim.t.bufs > 1 then 200 | if astro.is_available "snacks.nvim" then 201 | require("snacks").bufdelete { buf = bufnr, force = force } 202 | return 203 | end 204 | if astro.is_available "mini.bufremove" then 205 | mini_confirm(require("mini.bufremove").delete, bufnr, force) 206 | return 207 | end 208 | end 209 | -- fallback 210 | local buftype = vim.bo[bufnr].buftype 211 | vim.cmd(("silent! %s %d"):format((force or buftype == "terminal") and "bdelete!" or "confirm bdelete", bufnr)) 212 | end 213 | 214 | --- Fully wipeout a given buffer 215 | ---@param bufnr? integer The buffer to wipe or the current buffer if not provided 216 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 217 | function M.wipe(bufnr, force) 218 | if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end 219 | if M.is_valid(bufnr) and #vim.t.bufs > 1 then 220 | if astro.is_available "snacks.nvim" then 221 | return require("snacks").bufdelete { buf = bufnr, force = force, wipe = true } 222 | end 223 | if astro.is_available "mini.bufremove" then return mini_confirm(require("mini.bufremove").wipeout, bufnr, force) end 224 | end 225 | -- fallback 226 | local buftype = vim.bo[bufnr].buftype 227 | vim.cmd(("silent! %s %d"):format((force or buftype == "terminal") and "bwipeout!" or "confirm bwipeout", bufnr)) 228 | end 229 | 230 | --- Close all buffers 231 | ---@param keep_current? boolean Whether or not to keep the current buffer (default: false) 232 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 233 | function M.close_all(keep_current, force) 234 | if keep_current == nil then keep_current = false end 235 | local current = vim.api.nvim_get_current_buf() 236 | for _, bufnr in ipairs(vim.t.bufs) do 237 | if not keep_current or bufnr ~= current then M.close(bufnr, force) end 238 | end 239 | end 240 | 241 | --- Close buffers to the left of the current buffer 242 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 243 | function M.close_left(force) 244 | local current = vim.api.nvim_get_current_buf() 245 | for _, bufnr in ipairs(vim.t.bufs) do 246 | if bufnr == current then break end 247 | M.close(bufnr, force) 248 | end 249 | end 250 | 251 | --- Close buffers to the right of the current buffer 252 | ---@param force? boolean Whether or not to foce close the buffers or confirm changes (default: false) 253 | function M.close_right(force) 254 | local current = vim.api.nvim_get_current_buf() 255 | local after_current = false 256 | for _, bufnr in ipairs(vim.t.bufs) do 257 | if after_current then M.close(bufnr, force) end 258 | if bufnr == current then after_current = true end 259 | end 260 | end 261 | 262 | --- Sort a the buffers in the current tab based on some comparator 263 | ---@param compare_func string|function a string of a comparator defined in require("astrocore.buffer.comparator") or a custom comparator function 264 | ---@param skip_autocmd boolean|nil whether or not to skip triggering AstroBufsUpdated autocmd event 265 | ---@return boolean # Whether or not the buffers were sorted 266 | function M.sort(compare_func, skip_autocmd) 267 | if type(compare_func) == "string" then compare_func = require("astrocore.buffer.comparator")[compare_func] end 268 | if type(compare_func) == "function" then 269 | local bufs = vim.t.bufs 270 | table.sort(bufs, compare_func) 271 | vim.t.bufs = bufs 272 | if not skip_autocmd then astro.event "BufsUpdated" end 273 | vim.cmd.redrawtabline() 274 | return true 275 | end 276 | return false 277 | end 278 | 279 | --- Close a given tab 280 | ---@param tabpage? integer The tabpage to close or the current tab if not provided 281 | function M.close_tab(tabpage) 282 | if #vim.api.nvim_list_tabpages() > 1 then 283 | tabpage = tabpage or vim.api.nvim_get_current_tabpage() 284 | vim.t[tabpage].bufs = nil 285 | astro.event "BufsUpdated" 286 | vim.cmd.tabclose(vim.api.nvim_tabpage_get_number(tabpage)) 287 | end 288 | end 289 | 290 | return M 291 | -------------------------------------------------------------------------------- /lua/astrocore/buffer/comparator.lua: -------------------------------------------------------------------------------- 1 | ---AstroNvim Buffer Comparators 2 | --- 3 | ---Buffer comparator functions for sorting buffers 4 | --- 5 | ---This module can be loaded with `local buffer_comparators = require "astrocore.buffer.comparator"` 6 | --- 7 | ---copyright 2023 8 | ---license GNU General Public License v3.0 9 | ---@class astrocore.buffer.comparator 10 | local M = {} 11 | 12 | local fnamemodify = vim.fn.fnamemodify 13 | local function bufinfo(bufnr) return vim.fn.getbufinfo(bufnr)[1] end 14 | local function unique_path(bufnr) 15 | local status_avail, provider = pcall(require, "astroui.status.provider") 16 | if not status_avail then 17 | vim.notify("AstroUI required for unique path calculation", vim.log.levels.ERROR, { title = "AstroNvim" }) 18 | return "" 19 | end 20 | return provider.unique_path() { bufnr = bufnr } .. fnamemodify(bufinfo(bufnr).name, ":t") 21 | end 22 | 23 | --- Comparator of two buffer numbers 24 | ---@param bufnr_a integer buffer number A 25 | ---@param bufnr_b integer buffer number B 26 | ---@return boolean comparison true if A is sorted before B, false if B should be sorted before A 27 | function M.bufnr(bufnr_a, bufnr_b) return bufnr_a < bufnr_b end 28 | 29 | --- Comparator of two buffer numbers based on the file extensions 30 | ---@param bufnr_a integer buffer number A 31 | ---@param bufnr_b integer buffer number B 32 | ---@return boolean comparison true if A is sorted before B, false if B should be sorted before A 33 | function M.extension(bufnr_a, bufnr_b) 34 | return fnamemodify(bufinfo(bufnr_a).name, ":e") < fnamemodify(bufinfo(bufnr_b).name, ":e") 35 | end 36 | 37 | --- Comparator of two buffer numbers based on the full path 38 | ---@param bufnr_a integer buffer number A 39 | ---@param bufnr_b integer buffer number B 40 | ---@return boolean comparison true if A is sorted before B, false if B should be sorted before A 41 | function M.full_path(bufnr_a, bufnr_b) 42 | return fnamemodify(bufinfo(bufnr_a).name, ":p") < fnamemodify(bufinfo(bufnr_b).name, ":p") 43 | end 44 | 45 | --- Comparator of two buffers based on their unique path 46 | ---@param bufnr_a integer buffer number A 47 | ---@param bufnr_b integer buffer number B 48 | ---@return boolean comparison true if A is sorted before B, false if B should be sorted before A 49 | function M.unique_path(bufnr_a, bufnr_b) return unique_path(bufnr_a) < unique_path(bufnr_b) end 50 | 51 | --- Comparator of two buffers based on modification date 52 | ---@param bufnr_a integer buffer number A 53 | ---@param bufnr_b integer buffer number B 54 | ---@return boolean comparison true if A is sorted before B, false if B should be sorted before A 55 | function M.modified(bufnr_a, bufnr_b) return bufinfo(bufnr_a).lastused > bufinfo(bufnr_b).lastused end 56 | 57 | return M 58 | -------------------------------------------------------------------------------- /lua/astrocore/config.lua: -------------------------------------------------------------------------------- 1 | -- AstroNvim Core Configuration 2 | -- 3 | -- This module simply defines the configuration table structure for `opts` used in: 4 | -- 5 | -- require("astrocore").setup(opts) 6 | -- 7 | -- copyright 2023 8 | -- GNU General Public License v3.0 9 | 10 | ---@alias AstroCoreMappingCmd string|function 11 | 12 | ---@class AstroCoreMapping: vim.api.keyset.keymap 13 | ---@field [1] AstroCoreMappingCmd? rhs of keymap 14 | 15 | ---@alias AstroCoreMappings table?> 16 | 17 | ---@class AstroCoreCommand: vim.api.keyset.user_command 18 | ---@field [1] string|function the command to execute 19 | 20 | ---@class AstroCoreAutocmd: vim.api.keyset.create_autocmd 21 | ---@field event string|string[] Event(s) that will trigger the handler 22 | 23 | ---@alias AstroCoreRooterSpec string|string[]|fun(bufnr: integer): (string|string[]|nil) 24 | 25 | ---@class AstroCoreRooterIgnore 26 | ---@field dirs string[]? a list of patterns that match directories to exclude from root detection 27 | ---@field servers string[]|fun(client:vim.lsp.Client):boolean? a list of language servers to exclude from root detection or a filter function to return if a client should be ignored or not 28 | 29 | ---@class AstroCoreRooterOpts 30 | ---@field detector AstroCoreRooterSpec[]? a list of specifications for the rooter detection 31 | ---@field ignore AstroCoreRooterIgnore? configure things to ignore from root detection 32 | ---@field scope "global"|"tab"|"win"? what scope to change the working directory 33 | ---@field autochdir boolean? whether or not to change working directory automatically 34 | ---@field enabled boolean? whether or not to enable the rooter user command and autocommands 35 | ---@field notify boolean? whether or not to notify on working directory change 36 | 37 | ---@class AstroCoreGitWorktree 38 | ---@field toplevel string the top level directory 39 | ---@field gitdir string the location of the git directory 40 | 41 | ---@class AstroCoreMaxFile 42 | ---@field enabled (boolean|fun(bufnr: integer, config: AstroCoreMaxFile):boolean|AstroCoreMaxFile?)? whether to enable large file detection 43 | ---@field notify boolean? whether or not to display a notification when a large file is detected 44 | ---@field size integer|false? the number of bytes in a file or false to disable check 45 | ---@field lines integer|false? the number of lines in a file or false to disable check 46 | ---@field line_length integer|false? the average line length in a file or false to disable check 47 | 48 | ---@class AstroCoreSessionAutosave 49 | ---@field last boolean? whether or not to save the last session 50 | ---@field cwd boolean? whether or not to save a session for the current working directory 51 | 52 | ---@class AstroCoreSessionIgnore 53 | ---@field dirs string[]? directories to ignore 54 | ---@field filetypes string[]? filetypes to ignore 55 | ---@field buftypes string[]? buffer types to ignore 56 | 57 | -- TODO: remove note about version after dropping support for Neovim v0.10 58 | 59 | ---@class AstroCoreDiagnosticsFeature 60 | ---@field virtual_text boolean? show virtual text on startup 61 | ---@field virtual_lines boolean? show virtual lines on startup (Neovim v0.11+ only) 62 | --- 63 | ---@class AstroCoreSessionOpts 64 | ---Session autosaving options 65 | ---Example: 66 | --- 67 | ---```lua 68 | ---autosave = { 69 | --- last = true, 70 | --- cwd = true, 71 | ---} 72 | ---``` 73 | ---@field autosave AstroCoreSessionAutosave? 74 | ---Patterns to ignore when saving sessions 75 | ---Example: 76 | --- 77 | ---```lua 78 | ---autosave = { 79 | --- dirs = { "/path/to/ignore/sessions/dir" }, 80 | --- filetypes = { "gitcommit", "gitrebase" }, 81 | --- buftypes = { "nofile" } 82 | ---} 83 | ---``` 84 | ---@field ignore AstroCoreSessionIgnore? 85 | 86 | ---@class AstroCoreFeatureOpts 87 | ---@field autopairs boolean? enable or disable autopairs on start (boolean; default = true) 88 | ---@field cmp boolean? enable or disable cmp on start (boolean; default = true) 89 | ---@field diagnostics boolean|AstroCoreDiagnosticsFeature? diagnostic enabled on start 90 | ---@field highlighturl boolean? enable or disable highlighting of urls on start (boolean; default = true) 91 | ---table for defining the size of the max file for all features, above these limits we disable features like treesitter. 92 | ---value can also be `false` to disable large buffer detection. 93 | ---Example: 94 | --- 95 | ---```lua 96 | ---large_buf = { 97 | --- size = 1024 * 100, 98 | --- lines = 10000 99 | ---}, 100 | ---``` 101 | ---@field large_buf AstroCoreMaxFile|false? 102 | ---@field notifications boolean? enable or disable notifications on start (boolean; default = true) 103 | 104 | ---@class AstroCoreOpts 105 | ---Configuration of auto commands 106 | ---The key into the table is the group name for the auto commands (`:h augroup`) and the value 107 | ---is a list of autocmd tables where `event` key is the event(s) that trigger the auto command 108 | ---and the rest are auto command options (`:h nvim_create_autocmd`) 109 | ---Example: 110 | --- 111 | ---```lua 112 | ---autocmds = { 113 | --- -- first key is the `augroup` (:h augroup) 114 | --- highlighturl = { 115 | --- -- list of auto commands to set 116 | --- { 117 | --- -- events to trigger 118 | --- event = { "VimEnter", "FileType", "BufEnter", "WinEnter" }, 119 | --- -- the rest of the autocmd options (:h nvim_create_autocmd) 120 | --- desc = "URL Highlighting", 121 | --- callback = function() require("astrocore").set_url_match() end 122 | --- } 123 | --- } 124 | ---} 125 | ---``` 126 | ---@field autocmds table? 127 | ---Configuration of user commands 128 | ---The key into the table is the name of the user command and the value is a table of command options 129 | ---Example: 130 | --- 131 | ---```lua 132 | ---commands = { 133 | --- -- key is the command name 134 | --- AstroReload = { 135 | --- -- first element with no key is the command (string or function) 136 | --- function() require("astrocore").reload() end, 137 | --- -- the rest are options for creating user commands (:h nvim_create_user_command) 138 | --- desc = "Reload AstroNvim (Experimental)", 139 | --- } 140 | ---} 141 | ---``` 142 | ---@field commands table? 143 | ---Configure diagnostics options (`:h vim.diagnostic.config()`) 144 | ---Example: 145 | -- 146 | ---```lua 147 | ---diagnostics = { update_in_insert = false }, 148 | ---``` 149 | ---@field diagnostics vim.diagnostic.Opts? 150 | ---Configuration of filetypes, simply runs `vim.filetype.add` 151 | --- 152 | ---See `:h vim.filetype.add` for details on usage 153 | --- 154 | ---Example: 155 | --- 156 | ---```lua 157 | ---filetypes = { -- parameter to `vim.filetype.add` 158 | --- extension = { 159 | --- foo = "fooscript" 160 | --- }, 161 | --- filename = { 162 | --- [".foorc"] = "fooscript" 163 | --- }, 164 | --- pattern = { 165 | --- [".*/etc/foo/.*"] = "fooscript", 166 | --- } 167 | ---} 168 | ---``` 169 | ---@field filetypes vim.filetype.add.filetypes? 170 | ---Configuration of vim mappings to create. 171 | ---The first key into the table is the vim map mode (`:h map-modes`), and the value is a table of entries to be passed to `vim.keymap.set` (`:h vim.keymap.set`): 172 | --- - The key is the first parameter or the vim mode (only a single mode supported) and the value is a table of keymaps within that mode: 173 | --- - The first element with no key in the table is the action (the 2nd parameter) and the rest of the keys/value pairs are options for the third parameter. 174 | ---Example: 175 | -- 176 | ---```lua 177 | ---mappings = { 178 | --- -- map mode (:h map-modes) 179 | --- n = { 180 | --- -- use vimscript strings for mappings 181 | --- [""] = { ":w!", desc = "Save File" }, 182 | --- -- navigate buffer tabs with `H` and `L` 183 | --- L = { 184 | --- function() require("astrocore.buffer").nav(vim.v.count1) end, 185 | --- desc = "Next buffer", 186 | --- }, 187 | --- H = { 188 | --- function() require("astrocore.buffer").nav(-vim.v.count1) end, 189 | --- desc = "Previous buffer", 190 | --- }, 191 | --- -- tables with just a `desc` key will be registered with which-key if it's installed 192 | --- -- this is useful for naming menus 193 | --- ["b"] = { desc = "Buffers" }, 194 | --- } 195 | ---} 196 | ---``` 197 | ---@field mappings AstroCoreMappings? 198 | ---@field _map_sections table? 199 | ---Configuration of vim `on_key` functions. 200 | ---The key into the table is the namespace of the function and the value is a list like table of `on_key` functions 201 | ---Example: 202 | --- 203 | ---```lua 204 | ---on_keys = { 205 | --- -- first key is the namespace 206 | --- auto_hlsearch = { 207 | --- -- list of functions to execute on key press (:h vim.on_key) 208 | --- function(char) -- example automatically disables `hlsearch` when not actively searching 209 | --- if vim.fn.mode() == "n" then 210 | --- local new_hlsearch = vim.tbl_contains({ "", "n", "N", "*", "#", "?", "/" }, vim.fn.keytrans(char)) 211 | --- if vim.opt.hlsearch:get() ~= new_hlsearch then vim.opt.hlsearch = new_hlsearch end 212 | --- end 213 | --- end, 214 | --- }, 215 | ---}, 216 | ---``` 217 | ---@field on_keys table? 218 | ---Configuration of `vim` options (`vim.. = value`) 219 | ---The first key into the table is the type of option and the second key is the setting 220 | ---Example: 221 | --- 222 | ---```lua 223 | ---options = { 224 | --- -- first key is the type of option 225 | --- opt = { -- (`vim.opt`) 226 | --- relativenumber = true, -- sets `vim.opt.relativenumber` 227 | --- signcolumn = "auto", -- sets `vim.opt.signcolumn` 228 | --- }, 229 | --- g = { -- (`vim.g`) 230 | --- -- set global `vim.g.` settings here 231 | --- } 232 | ---} 233 | ---``` 234 | ---@field options table>? 235 | ---Configure signs (`:h sign_define()`) 236 | ---Example: 237 | -- 238 | ---```lua 239 | ---signs = { 240 | --- DapBreakPoint" = { text = "", texthl = "DiagnosticInfo" }, 241 | ---}, 242 | ---``` 243 | ---@field signs table? 244 | ---Configuration table of features provided by AstroCore 245 | ---Example: 246 | -- 247 | ---```lua 248 | ---features = { 249 | --- autopairs = true, 250 | --- cmp = true, 251 | --- diagnostics = true, 252 | --- highlighturl = true, 253 | --- notiifcations = true, 254 | --- large_buf = { size = 1024 * 100, lines = 10000 }, 255 | ---} 256 | ---``` 257 | ---@field features AstroCoreFeatureOpts? 258 | ---Enable git integration for detached worktrees 259 | ---Example: 260 | -- 261 | ---```lua 262 | ---git_worktrees = { 263 | --- { toplevel = vim.env.HOME, gitdir=vim.env.HOME .. "/.dotfiles" } 264 | ---} 265 | ---``` 266 | ---@field git_worktrees AstroCoreGitWorktree[]? 267 | ---Enable and configure project root detection 268 | ---Example: 269 | -- 270 | ---```lua 271 | ---rooter = { 272 | --- detector = { 273 | --- "lsp", -- highest priority is getting workspace from running language servers 274 | --- { ".git", "_darcs", ".hg", ".bzr", ".svn" }, -- next check for a version controlled parent directory 275 | --- { "lua", "MakeFile", "package.json" }, -- lastly check for known project root files 276 | --- }, 277 | --- ignore = { 278 | --- servers = {}, -- list of language server names to ignore (Ex. { "efm" }) 279 | --- dirs = {}, -- list of directory patterns (Ex. { "~/.cargo/*" }) 280 | --- }, 281 | --- autochdir = false, -- automatically update working directory 282 | --- scope = "global", -- scope of working directory to change ("global"|"tab"|"win") 283 | --- notify = false, -- show notification on every working directory change 284 | ---} 285 | ---``` 286 | ---@field rooter AstroCoreRooterOpts|false? 287 | ---Configuration table of session options for AstroNvim's session management powered by Resession 288 | ---Example: 289 | -- 290 | ---```lua 291 | ---sessions = { 292 | --- autosave = { 293 | --- last = true, -- auto save last session 294 | --- cwd = true, -- auto save session for each working directory 295 | --- }, 296 | --- ignore = { 297 | --- dirs = {}, -- working directories to ignore sessions in 298 | --- filetypes = { "gitcommit", "gitrebase" }, -- filetypes to ignore sessions 299 | --- buftypes = {}, -- buffer types to ignore sessions 300 | --- }, 301 | ---} 302 | ---``` 303 | ---@field sessions AstroCoreSessionOpts? 304 | 305 | ---@type AstroCoreOpts 306 | local M = { 307 | autocmds = {}, 308 | commands = {}, 309 | diagnostics = {}, 310 | filetypes = {}, 311 | mappings = {}, 312 | on_keys = {}, 313 | options = {}, 314 | signs = {}, 315 | features = { 316 | autopairs = true, 317 | cmp = true, 318 | diagnostics = true, 319 | highlighturl = true, 320 | large_buf = { notify = true, size = 1.5 * 1024 * 1024, lines = 100000, line_length = 1000 }, 321 | notifications = true, 322 | }, 323 | git_worktrees = nil, 324 | rooter = { enabled = true }, 325 | sessions = { 326 | autosave = { last = true, cwd = true }, 327 | ignore = { 328 | dirs = {}, 329 | filetypes = { "gitcommit", "gitrebase" }, 330 | buftypes = {}, 331 | }, 332 | }, 333 | } 334 | 335 | return M 336 | -------------------------------------------------------------------------------- /lua/astrocore/health.lua: -------------------------------------------------------------------------------- 1 | -- ### AstroCore Health Checks 2 | -- 3 | -- use with `:checkhealth astrocore` 4 | -- 5 | -- copyright 2024 6 | -- license GNU General Public License v3.0 7 | 8 | local M = {} 9 | 10 | local astrocore = require "astrocore" 11 | local health = vim.health 12 | 13 | local function check_mapping_conflicts(all_maps) 14 | local set_mappings, any_duplicates = {}, false 15 | for mode, mappings in pairs(all_maps) do 16 | for lhs, rhs in pairs(mappings) do 17 | if rhs then 18 | if not set_mappings[mode] then set_mappings[mode] = {} end 19 | local normalized_lhs = vim.api.nvim_replace_termcodes(lhs, true, true, true) 20 | if set_mappings[mode][normalized_lhs] then 21 | set_mappings[mode][normalized_lhs][lhs] = rhs 22 | set_mappings[mode][normalized_lhs][1] = true 23 | any_duplicates = true 24 | else 25 | set_mappings[mode][normalized_lhs] = { [1] = false, [lhs] = rhs } 26 | end 27 | end 28 | end 29 | end 30 | 31 | if any_duplicates then 32 | local msg = "" 33 | for mode, mappings in pairs(set_mappings) do 34 | local mode_msg 35 | for _, duplicate_mappings in pairs(mappings) do 36 | if duplicate_mappings[1] then 37 | if not mode_msg then 38 | mode_msg = ("Conflicting mappings detected in mode `%s`:\n"):format(mode) 39 | else 40 | mode_msg = mode_msg .. "\n" 41 | end 42 | for lhs, rhs in pairs(duplicate_mappings) do 43 | if type(lhs) == "string" then 44 | mode_msg = mode_msg .. ("- %s: %s\n"):format(lhs, type(rhs) == "table" and (rhs.desc or rhs[1]) or rhs) 45 | end 46 | end 47 | end 48 | end 49 | if mode_msg then msg = msg .. mode_msg end 50 | end 51 | health.warn( 52 | msg, 53 | "Make sure to normalize the left hand side of mappings to what is used in :h keycodes. This includes making sure to capitalize and ." 54 | ) 55 | else 56 | health.ok "No conflicting mappings detected" 57 | end 58 | end 59 | 60 | function M.check() 61 | health.start "Checking for conflicting mappings" 62 | check_mapping_conflicts(astrocore.config.mappings) 63 | end 64 | 65 | return M 66 | -------------------------------------------------------------------------------- /lua/astrocore/init.lua: -------------------------------------------------------------------------------- 1 | ---AstroNvim Core Utilities 2 | --- 3 | ---Various utility functions to use within AstroNvim and user configurations. 4 | --- 5 | ---This module can be loaded with `local astro = require "astrocore"` 6 | --- 7 | ---copyright 2023 8 | ---license GNU General Public License v3.0 9 | ---@class astrocore 10 | local M = {} 11 | 12 | --- The configuration as set by the user through the `setup()` function 13 | M.config = require "astrocore.config" 14 | --- A table to manage ToggleTerm terminals created by the user, indexed by the command run and then the instance number 15 | ---@type table> 16 | M.user_terminals = {} 17 | 18 | --- Merge extended options with a default table of options 19 | ---@param default? table The default table that you want to merge into 20 | ---@param opts? table The new options that should be merged with the default table 21 | ---@return table extended The extended table 22 | function M.extend_tbl(default, opts) 23 | opts = opts or {} 24 | return default and vim.tbl_deep_extend("force", default, opts) or opts 25 | end 26 | 27 | --- Sync Lazy and then update Mason 28 | function M.update_packages() 29 | require("lazy").sync { wait = true } 30 | if vim.fn.exists ":MasonToolsUpdate" > 0 then vim.cmd.MasonToolsUpdate() end 31 | end 32 | 33 | --- Partially reload AstroNvim user settings. Includes core vim options, mappings, and highlights. This is an experimental feature and may lead to instabilities until restart. 34 | function M.reload() 35 | local lazy, was_modifiable = require "lazy", vim.opt.modifiable:get() 36 | if not was_modifiable then vim.opt.modifiable = true end 37 | lazy.reload { plugins = { M.get_plugin "astrocore" } } 38 | if not was_modifiable then vim.opt.modifiable = false end 39 | if M.is_available "astroui" then lazy.reload { plugins = { M.get_plugin "astroui" } } end 40 | vim.cmd.doautocmd "ColorScheme" 41 | end 42 | 43 | --- Insert one or more values into a list like table and maintain that you do not insert non-unique values (THIS MODIFIES `dst`) 44 | ---@param dst any[]|nil The list like table that you want to insert into 45 | ---@param src any[] Values to be inserted 46 | ---@return any[] result The modified list like table 47 | function M.list_insert_unique(dst, src) 48 | if not dst then dst = {} end 49 | assert(vim.islist(dst), "Provided table is not a list like table") 50 | local added = {} 51 | for _, val in ipairs(dst) do 52 | added[val] = true 53 | end 54 | for _, val in ipairs(src) do 55 | if not added[val] then 56 | table.insert(dst, val) 57 | added[val] = true 58 | end 59 | end 60 | return dst 61 | end 62 | 63 | --- Remove duplicate entries from a given list (does not mutate the original list) 64 | ---@param list any[] The list like table that you want to remove duplicates from 65 | ---@return any[] result The list like table of unique values 66 | function M.unique_list(list) 67 | local out, cache = {}, {} 68 | assert(vim.islist(list), "Provided table is not a list like table") 69 | for _, val in ipairs(list) do 70 | if not cache[val] then 71 | table.insert(out, val) 72 | cache[val] = true 73 | end 74 | end 75 | return out 76 | end 77 | 78 | --- Call function if a condition is met 79 | ---@param func function The function to run 80 | ---@param condition boolean # Whether to run the function or not 81 | ---@return any|nil result the result of the function running or nil 82 | function M.conditional_func(func, condition, ...) 83 | -- if the condition is true or no condition is provided, evaluate the function with the rest of the parameters and return the result 84 | if condition and type(func) == "function" then return func(...) end 85 | end 86 | 87 | --- Serve a notification with a title of AstroNvim 88 | ---@param msg string The notification body 89 | ---@param type integer|nil The type of the notification (:help vim.log.levels) 90 | ---@param opts? table The nvim-notify options to use (:help notify-options) 91 | function M.notify(msg, type, opts) 92 | vim.schedule(function() vim.notify(msg, type, M.extend_tbl({ title = "AstroNvim" }, opts)) end) 93 | end 94 | 95 | --- Trigger an AstroNvim user event 96 | ---@param event string|vim.api.keyset_exec_autocmds The event pattern or full autocmd options (pattern always prepended with "Astro") 97 | ---@param instant? boolean Whether or not to execute instantly or schedule 98 | function M.event(event, instant) 99 | if type(event) == "string" then event = { pattern = event } end 100 | event = M.extend_tbl({ modeline = false }, event) 101 | event.pattern = "Astro" .. event.pattern 102 | if instant then 103 | vim.api.nvim_exec_autocmds("User", event) 104 | else 105 | vim.schedule(function() vim.api.nvim_exec_autocmds("User", event) end) 106 | end 107 | end 108 | 109 | --- Execute autocommand across all valid buffers 110 | ---@param event string|string[] the event or events to execute 111 | ---@param opts vim.api.keyset.exec_autocmds Dictionary of autocommnd options 112 | function M.exec_buffer_autocmds(event, opts) 113 | opts = M.extend_tbl(opts, { modeline = false }) 114 | for _, tabpage in ipairs(vim.api.nvim_list_tabpages()) do 115 | for _, bufnr in ipairs(vim.t[tabpage].bufs or {}) do 116 | if vim.api.nvim_buf_is_valid(bufnr) and vim.bo[bufnr].filetype then 117 | opts.buffer = bufnr 118 | pcall(vim.api.nvim_exec_autocmds, event, opts) 119 | end 120 | end 121 | end 122 | end 123 | 124 | --- Helper function to read a file and return it's content 125 | ---@param path string the path to the file to read 126 | ---@return string content the contents of the file 127 | function M.read_file(path) 128 | local fd = assert(vim.uv.fs_open(path, "r", 420)) 129 | local stat = assert(vim.uv.fs_fstat(fd)) 130 | local content = assert(vim.uv.fs_read(fd, stat.size)) 131 | assert(vim.uv.fs_close(fd)) 132 | return content 133 | end 134 | 135 | --- Toggle a user terminal if it exists, if not then create a new one and save it 136 | ---@param opts string|table A terminal command string or a table of options for Terminal:new() (Check toggleterm.nvim documentation for table format) 137 | function M.toggle_term_cmd(opts) 138 | local terms = M.user_terminals 139 | -- if a command string is provided, create a basic table for Terminal:new() options 140 | if type(opts) == "string" then opts = { cmd = opts } end 141 | opts = M.extend_tbl({ hidden = true }, opts) 142 | local num = vim.v.count > 0 and vim.v.count or 1 143 | -- if terminal doesn't exist yet, create it 144 | if not terms[opts.cmd] then terms[opts.cmd] = {} end 145 | if not terms[opts.cmd][num] then 146 | if not opts.count then opts.count = vim.tbl_count(terms) * 100 + num end 147 | local on_exit = opts.on_exit 148 | opts.on_exit = function(...) 149 | terms[opts.cmd][num] = nil 150 | if on_exit then on_exit(...) end 151 | end 152 | terms[opts.cmd][num] = require("toggleterm.terminal").Terminal:new(opts) 153 | end 154 | -- toggle the terminal 155 | terms[opts.cmd][num]:toggle() 156 | end 157 | 158 | --- Get a plugin spec from lazy 159 | ---@param plugin string The plugin to search for 160 | ---@return LazyPlugin? spec The found plugin spec from Lazy 161 | function M.get_plugin(plugin) 162 | local lazy_config_avail, lazy_config = pcall(require, "lazy.core.config") 163 | return lazy_config_avail and lazy_config.spec.plugins[plugin] or nil 164 | end 165 | 166 | --- Check if a plugin is defined in lazy. Useful with lazy loading when a plugin is not necessarily loaded yet 167 | ---@param plugin string The plugin to search for 168 | ---@return boolean available Whether the plugin is available 169 | function M.is_available(plugin) return M.get_plugin(plugin) ~= nil end 170 | 171 | --- Resolve the options table for a given plugin with lazy 172 | ---@param plugin string The plugin to search for 173 | ---@return table opts The plugin options 174 | function M.plugin_opts(plugin) 175 | local spec = M.get_plugin(plugin) 176 | return spec and require("lazy.core.plugin").values(spec, "opts") or {} 177 | end 178 | 179 | --- A helper function to wrap a module function to require a plugin before running 180 | ---@param plugin string The plugin to call `require("lazy").load` with 181 | ---@param module table The system module where the functions live (e.g. `vim.ui`) 182 | ---@param funcs string|string[] The functions to wrap in the given module (e.g. `"ui", "select"`) 183 | function M.load_plugin_with_func(plugin, module, funcs) 184 | if type(funcs) == "string" then funcs = { funcs } end 185 | for _, func in ipairs(funcs) do 186 | local old_func = module[func] 187 | module[func] = function(...) 188 | module[func] = old_func 189 | require("lazy").load { plugins = { plugin } } 190 | module[func](...) 191 | end 192 | end 193 | end 194 | 195 | --- Execute a function when a specified plugin is loaded with Lazy.nvim, or immediately if already loaded 196 | ---@param plugins string|string[] the name of the plugin or a list of plugins to defer the function execution on. If a list is provided, only one needs to be loaded to execute the provided function 197 | ---@param load_op fun()|string|string[] the function to execute when the plugin is loaded, a plugin name to load, or a list of plugin names to load 198 | function M.on_load(plugins, load_op) 199 | local lazy_config_avail, lazy_config = pcall(require, "lazy.core.config") 200 | if lazy_config_avail then 201 | if type(plugins) == "string" then plugins = { plugins } end 202 | if type(load_op) ~= "function" then 203 | local to_load = type(load_op) == "string" and { load_op } or load_op --[=[@as string[]]=] 204 | load_op = function() require("lazy").load { plugins = to_load } end 205 | end 206 | 207 | for _, plugin in ipairs(plugins) do 208 | if vim.tbl_get(lazy_config.plugins, plugin, "_", "loaded") then 209 | vim.schedule(load_op) 210 | return 211 | end 212 | end 213 | vim.api.nvim_create_autocmd("User", { 214 | pattern = "LazyLoad", 215 | desc = ("A function to be ran when one of these plugins runs: %s"):format(vim.inspect(plugins)), 216 | callback = function(args) 217 | if vim.tbl_contains(plugins, args.data) then 218 | load_op() 219 | return true 220 | end 221 | end, 222 | }) 223 | end 224 | end 225 | 226 | --- A placeholder variable used to queue section names to be registered by which-key 227 | ---@type table? 228 | M.which_key_queue = nil 229 | 230 | --- Register queued which-key mappings 231 | function M.which_key_register() 232 | if M.which_key_queue then 233 | local wk_avail, wk = pcall(require, "which-key") 234 | if wk_avail then 235 | wk.add(M.which_key_queue) 236 | M.which_key_queue = nil 237 | end 238 | end 239 | end 240 | 241 | --- Get an empty table of mappings with a key for each map mode 242 | ---@return table mappings a table with entries for each map mode 243 | function M.empty_map_table() 244 | local maps = {} 245 | for _, mode in ipairs { "", "n", "v", "x", "s", "o", "!", "i", "l", "c", "t" } do 246 | maps[mode] = {} 247 | end 248 | if vim.fn.has "nvim-0.10.0" == 1 then 249 | for _, abbr_mode in ipairs { "ia", "ca", "!a" } do 250 | maps[abbr_mode] = {} 251 | end 252 | end 253 | return maps 254 | end 255 | 256 | --- Table based API for setting keybindings 257 | ---@param map_table AstroCoreMappings A nested table where the first key is the vim mode, the second key is the key to map, and the value is the function to set the mapping to 258 | ---@param base? vim.keymap.set.Opts A base set of options to set on every keybinding 259 | function M.set_mappings(map_table, base) 260 | local was_no_which_key_queue = not M.which_key_queue 261 | -- iterate over the first keys for each mode 262 | for mode, maps in pairs(map_table) do 263 | -- iterate over each keybinding set in the current mode 264 | for keymap, options in pairs(maps) do 265 | -- build the options for the command accordingly 266 | if options then 267 | local cmd 268 | local keymap_opts = base or {} 269 | if type(options) == "string" or type(options) == "function" then 270 | cmd = options 271 | else 272 | cmd = options[1] 273 | keymap_opts = vim.tbl_deep_extend("force", keymap_opts, options) 274 | keymap_opts[1] = nil 275 | end 276 | if not cmd then -- if which-key mapping, queue it 277 | ---@cast keymap_opts wk.Spec 278 | keymap_opts[1], keymap_opts.mode = keymap, mode 279 | if not keymap_opts.group then keymap_opts.group = keymap_opts.desc end 280 | if not M.which_key_queue then M.which_key_queue = {} end 281 | table.insert(M.which_key_queue, keymap_opts) 282 | else -- if not which-key mapping, set it 283 | vim.keymap.set(mode, keymap, cmd, keymap_opts) 284 | end 285 | end 286 | end 287 | end 288 | if was_no_which_key_queue and M.which_key_queue then M.on_load("which-key.nvim", M.which_key_register) end 289 | end 290 | 291 | --- regex used for matching a valid URL/URI string 292 | M.url_matcher = 293 | "\\v\\c%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)%([&:#*@~%_\\-=?!+;/0-9a-z]+%(%([.;/?]|[.][.]+)[&:#*@~%_\\-=?!+/0-9a-z]+|:\\d+|,%(%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)@![0-9a-z]+))*|\\([&:#*@~%_\\-=?!+;/.0-9a-z]*\\)|\\[[&:#*@~%_\\-=?!+;/.0-9a-z]*\\]|\\{%([&:#*@~%_\\-=?!+;/.0-9a-z]*|\\{[&:#*@~%_\\-=?!+;/.0-9a-z]*})\\})+" 294 | 295 | --- Delete the syntax matching rules for URLs/URIs if set 296 | ---@param win? integer the window id to remove url highlighting in (default: current window) 297 | function M.delete_url_match(win) 298 | if not win then win = vim.api.nvim_get_current_win() end 299 | for _, match in ipairs(vim.fn.getmatches(win)) do 300 | if match.group == "HighlightURL" then vim.fn.matchdelete(match.id, win) end 301 | end 302 | vim.w[win].highlighturl_enabled = false 303 | end 304 | 305 | --- Add syntax matching rules for highlighting URLs/URIs 306 | ---@param win? integer the window id to remove url highlighting in (default: current window) 307 | function M.set_url_match(win) 308 | if not win then win = vim.api.nvim_get_current_win() end 309 | M.delete_url_match(win) 310 | if M.config.features.highlighturl then 311 | vim.fn.matchadd("HighlightURL", M.url_matcher, 15, -1, { window = win }) 312 | vim.w[win].highlighturl_enabled = true 313 | end 314 | end 315 | 316 | --- Run a shell command and capture the output and if the command succeeded or failed 317 | ---@param cmd string|string[] The terminal command to execute 318 | ---@param show_error? boolean Whether or not to show an unsuccessful command as an error to the user 319 | ---@return string|nil result The result of a successfully executed command or nil 320 | function M.cmd(cmd, show_error) 321 | if type(cmd) == "string" then cmd = { cmd } end 322 | if vim.fn.has "win32" == 1 then cmd = vim.list_extend({ "cmd.exe", "/C" }, cmd) end 323 | local result = vim.fn.system(cmd) 324 | local success = vim.api.nvim_get_vvar "shell_error" == 0 325 | if not success and (show_error == nil or show_error) then 326 | vim.api.nvim_err_writeln(("Error running command %s\nError message:\n%s"):format(table.concat(cmd, " "), result)) 327 | end 328 | return success and assert(result):gsub("[\27\155][][()#;?%d]*[A-PRZcf-ntqry=><~]", "") or nil 329 | end 330 | 331 | --- Get the first worktree that a file belongs to 332 | ---@param file? string the file to check, defaults to the current file 333 | ---@param worktrees table[]? an array like table of worktrees with entries `toplevel` and `gitdir`, default retrieves from `vim.g.git_worktrees` 334 | ---@return table|nil worktree a table specifying the `toplevel` and `gitdir` of a worktree or nil if not found 335 | function M.file_worktree(file, worktrees) 336 | worktrees = worktrees or M.config.git_worktrees 337 | if not worktrees then return end 338 | file = file or vim.fn.expand "%" --[[@as string]] 339 | for _, worktree in ipairs(worktrees) do 340 | if 341 | M.cmd({ 342 | "git", 343 | "--work-tree", 344 | worktree.toplevel, 345 | "--git-dir", 346 | worktree.gitdir, 347 | "ls-files", 348 | "--error-unmatch", 349 | file, 350 | }, false) 351 | then 352 | return worktree 353 | end 354 | end 355 | end 356 | 357 | --- Monkey patch into an existing function 358 | --- 359 | --- Example from `:h vim.paste()` 360 | --- ```lua 361 | --- local patch_func = require("astrocore").patch_func 362 | --- vim.paste = patch_func(vim.paste, function(orig, lines, phase) 363 | --- for i, line in ipairs(lines) do 364 | --- -- Scrub ANSI color codes from paste input. 365 | --- lines[i] = line:gsub('\27%[[0-9;mK]+', '') 366 | --- end 367 | --- return orig(lines, phase) 368 | --- end) 369 | --- ``` 370 | ---@param orig? function the original function to override, if `nil` is provided then an empty function is passed 371 | ---@param override fun(orig:function, ...):... the override function 372 | ---@return function patched the new function with the patch applied 373 | function M.patch_func(orig, override) 374 | if not orig then orig = function() end end 375 | return function(...) return override(orig, ...) end 376 | end 377 | 378 | --- Execute function with open file 379 | ---@param filename string path to file to interact with 380 | ---@param mode? openmode the mode in which to open the file 381 | ---@param callback? fun(file:file*) the callback to execute with the opened file 382 | ---@param on_error? fun(err:string) the callback to execute if unable to open the file 383 | function M.with_file(filename, mode, callback, on_error) 384 | local file, errmsg = io.open(filename, mode) 385 | if file then 386 | if callback then callback(file) end 387 | file:close() 388 | elseif errmsg and on_error then 389 | on_error(errmsg) 390 | end 391 | end 392 | 393 | ---@class AstroCoreRenameFileOpts 394 | ---@field from string? the file to be renamed (defaults to name of current buffer) 395 | ---@field to string? the new filename relative to the original directory (defaults to prompting the user) 396 | ---@field on_rename fun(from: string, to: string, success: boolean)? optional function to execute after the file is renamed 397 | ---@field save boolean? if file to be renamed is open and modified save before renaming or not (default is nil which will prompt the user) 398 | ---@field force boolean? set to true to overwrite existing files 399 | 400 | --- Prompt the user to rename a file 401 | ---@param opts? AstroCoreRenameFileOpts optional fields for file renaming 402 | function M.rename_file(opts) 403 | if not opts then opts = {} end 404 | local from = opts.from 405 | if not from then 406 | if require("astrocore.buffer").is_valid() then 407 | from = vim.api.nvim_buf_get_name(0) 408 | if from == "" then 409 | M.notify("Cannot rename unnamed buffer", vim.log.levels.ERROR) 410 | return 411 | end 412 | else 413 | M.notify("Only renaming real file buffers is supported", vim.log.levels.ERROR) 414 | return 415 | end 416 | end 417 | from = vim.fn.fnamemodify(from, ":p") 418 | 419 | local from_bufnr = vim.fn.bufnr(from) 420 | if from_bufnr >= 0 and vim.bo[from_bufnr].modified then 421 | local write_confirm = opts.save ~= nil and (opts.save and 1 or 2) 422 | or vim.fn.confirm( 423 | ('Save changes to "%s"?'):format(vim.fn.fnamemodify(from, ":.")), 424 | "&Yes\n&No\n&Cancel", 425 | 1, 426 | "Question" 427 | ) 428 | -- write_confirm: 1 saves, 2 doesn't save, anything else aborts 429 | if write_confirm == 1 then 430 | vim.api.nvim_buf_call(from_bufnr, function() vim.cmd.write { mods = { silent = true } } end) 431 | elseif write_confirm ~= 2 then 432 | M.notify(("Renaming cancelled:\n`%s`"):format(vim.fn.fnamemodify(from, ":.")), vim.log.levels.INFO) 433 | return 434 | end 435 | end 436 | 437 | if not vim.uv.fs_stat(from) then 438 | M.notify(("File does not exists:\n`%s`"):format(vim.fn.fnamemodify(from, ":.")), vim.log.levels.ERROR) 439 | return 440 | end 441 | 442 | local _rename_file = function(to) 443 | to = vim.fn.fnamemodify(to, ":p") 444 | if not opts.force and vim.uv.fs_stat(to) then 445 | M.notify(("File already exists:\n`%s`\n\n"):format(vim.fn.fnamemodify(to, ":.")), vim.log.levels.ERROR) 446 | return 447 | end 448 | vim.fn.mkdir(vim.fs.dirname(to), "p") 449 | local rename_data = { from = from, to = to } 450 | M.event({ pattern = "RenameFilePre", data = rename_data }, true) 451 | local success = vim.fn.rename(from, to) == 0 452 | rename_data.success = success 453 | if success then 454 | if from_bufnr >= 0 then 455 | local to_bufnr = vim.fn.bufadd(to) 456 | vim.bo[to_bufnr].buflisted = true 457 | for _, win in ipairs(vim.fn.win_findbuf(from_bufnr)) do 458 | vim.api.nvim_win_call(win, function() vim.cmd.buffer(to_bufnr) end) 459 | end 460 | for _, tabpage in ipairs(vim.api.nvim_list_tabpages()) do 461 | if vim.t[tabpage].bufs then -- rebuild buffer ordering after rename 462 | local bufs = {} 463 | for _, bufnr in ipairs(vim.t[tabpage].bufs) do 464 | if bufnr ~= to_bufnr then table.insert(bufs, bufnr == from_bufnr and to_bufnr or bufnr) end 465 | end 466 | vim.t[tabpage].bufs = bufs 467 | end 468 | end 469 | vim.api.nvim_buf_delete(from_bufnr, { force = true }) 470 | end 471 | else 472 | M.notify(("Error renaming file:\n`%s`"):format(vim.fn.fnamemodify(from, ":.")), vim.log.levels.ERROR) 473 | end 474 | if opts.on_rename then opts.on_rename(from, to, success) end 475 | M.event({ pattern = "RenameFilePost", data = rename_data }, true) 476 | end 477 | 478 | if opts.to then 479 | _rename_file(opts.to) 480 | else 481 | local root = vim.fn.getcwd() 482 | if from:find(root, 1, true) ~= 1 then root = vim.fn.fnamemodify(from, ":p:h") end 483 | local prefix = from:sub(#root + 2) 484 | vim.ui.input({ 485 | prompt = "New File Name: ", 486 | default = prefix, 487 | completion = "file", 488 | }, function(input) 489 | if input and input ~= "" and input ~= prefix then _rename_file(vim.fs.normalize(root .. "/" .. input)) end 490 | end) 491 | end 492 | end 493 | 494 | local key_cache = {} ---@type { [string]: string } 495 | --- Normalize a mappings table to use official keycode casing 496 | ---@param mappings AstroCoreMappings? 497 | function M.normalize_mappings(mappings) 498 | if not mappings then return end 499 | for _, mode_maps in pairs(mappings) do 500 | for key, _ in pairs(mode_maps) do 501 | if not key_cache[key] then 502 | key_cache[key] = vim.fn.keytrans(vim.api.nvim_replace_termcodes(key, true, true, true)) 503 | end 504 | local normkey = key_cache[key] 505 | if key ~= normkey then 506 | mode_maps[normkey], mode_maps[key] = mode_maps[key], nil 507 | end 508 | end 509 | end 510 | end 511 | 512 | --- Setup and configure AstroCore 513 | ---@param opts AstroCoreOpts 514 | ---@see astrocore.config 515 | function M.setup(opts) 516 | M.normalize_mappings(M.config.mappings) 517 | M.normalize_mappings(opts.mappings) 518 | M.config = vim.tbl_deep_extend("force", M.config, opts) 519 | 520 | -- options 521 | if vim.bo.filetype == "lazy" then vim.cmd.bw() end 522 | if vim.tbl_get(M.config, "options", "opt", "clipboard") then 523 | local opt = M.config.options.opt 524 | local lazy_clipboard = opt.clipboard 525 | opt.clipboard = nil 526 | vim.schedule(function() -- defer setting clipboard 527 | opt.clipboard = lazy_clipboard 528 | vim.opt.clipboard = opt.clipboard 529 | end) 530 | end 531 | for scope, settings in pairs(M.config.options) do 532 | for setting, value in pairs(settings) do 533 | vim[scope][setting] = value 534 | end 535 | end 536 | 537 | -- mappings 538 | M.set_mappings(M.config.mappings) 539 | 540 | -- autocmds 541 | for augroup, autocmds in pairs(M.config.autocmds) do 542 | if autocmds then 543 | local augroup_id = vim.api.nvim_create_augroup(augroup, { clear = true }) 544 | for _, autocmd in ipairs(autocmds) do 545 | local event = autocmd.event 546 | autocmd.event = nil 547 | autocmd.group = augroup_id 548 | vim.api.nvim_create_autocmd(event, autocmd) 549 | autocmd.event = event 550 | end 551 | end 552 | end 553 | 554 | -- user commands 555 | for cmd, spec in pairs(M.config.commands) do 556 | if spec then 557 | local action = spec[1] 558 | spec[1] = nil 559 | vim.api.nvim_create_user_command(cmd, action, spec) 560 | spec[1] = action 561 | end 562 | end 563 | 564 | -- vim.filetype 565 | if M.config.filetypes then vim.filetype.add(M.config.filetypes) end 566 | 567 | -- on_key hooks 568 | for namespace, funcs in pairs(M.config.on_keys) do 569 | if funcs then 570 | local ns = vim.api.nvim_create_namespace(namespace) 571 | for _, func in ipairs(funcs) do 572 | vim.on_key(func, ns) 573 | end 574 | end 575 | end 576 | 577 | -- sign definition 578 | for name, dict in pairs(M.config.signs or {}) do 579 | if dict then vim.fn.sign_define(name, dict) end 580 | end 581 | 582 | -- setup diagnostics 583 | vim.diagnostic.config(M.config.diagnostics) 584 | local diagnostic_feature = vim.tbl_get(M.config, "features", "diagnostics") 585 | if diagnostic_feature then 586 | vim.diagnostic.enable(true) 587 | if type(diagnostic_feature) == "table" then 588 | local diagnostic_config = assert(vim.diagnostic.config()) 589 | -- setup startup state of virtual text and virtual_lines 590 | for _, feature in ipairs { "virtual_text", "virtual_lines" } do 591 | if 592 | diagnostic_config[feature] ~= nil 593 | and diagnostic_feature[feature] ~= nil 594 | and (diagnostic_config[feature] ~= false) ~= diagnostic_feature[feature] 595 | then 596 | require("astrocore.toggles")[feature](true) 597 | end 598 | end 599 | end 600 | else 601 | vim.diagnostic.enable(false) 602 | end 603 | 604 | vim.api.nvim_create_autocmd("BufRead", { 605 | group = vim.api.nvim_create_augroup("large_buf_detector", { clear = true }), 606 | desc = "Large buffer detection loading a file into a buffer", 607 | callback = function(args) 608 | if require("astrocore.buffer").is_large(args.buf) then 609 | vim.b[args.buf].large_buf = true 610 | if vim.tbl_get(M.config, "features", "large_buf", "notify") then 611 | M.notify( 612 | ("Large file detected `%s`\nSome Neovim features may be **disabled**"):format( 613 | vim.fn.fnamemodify(vim.api.nvim_buf_get_name(args.buf), ":p:~:.") 614 | ) 615 | ) 616 | end 617 | M.event("LargeBuf", true) 618 | end 619 | end, 620 | }) 621 | 622 | -- set up highlighturl 623 | local highlighturl_group = vim.api.nvim_create_augroup("highlighturl", { clear = true }) 624 | vim.api.nvim_set_hl(0, "HighlightURL", { default = true, underline = true }) 625 | vim.api.nvim_create_autocmd("ColorScheme", { 626 | group = highlighturl_group, 627 | desc = "Set up HighlightURL hlgroup", 628 | callback = function() vim.api.nvim_set_hl(0, "HighlightURL", { default = true, underline = true }) end, 629 | }) 630 | vim.api.nvim_create_autocmd({ "VimEnter", "FileType", "BufEnter", "WinEnter" }, { 631 | group = highlighturl_group, 632 | desc = "Highlight URLs", 633 | callback = function(args) 634 | for _, win in ipairs(vim.api.nvim_list_wins()) do 635 | if 636 | vim.api.nvim_win_get_buf(win) == args.buf 637 | and vim.tbl_get(require "astrocore", "config", "features", "highlighturl") 638 | and not vim.w[win].highlighturl_enabled 639 | then 640 | M.set_url_match(win) 641 | end 642 | end 643 | end, 644 | }) 645 | 646 | -- initialize rooter 647 | if vim.tbl_get(M.config, "rooter", "enabled") then 648 | local root_config = M.config.rooter --[[@as AstroCoreRooterOpts]] 649 | vim.api.nvim_create_user_command( 650 | "AstroRootInfo", 651 | function() require("astrocore.rooter").info() end, 652 | { desc = "Display rooter information" } 653 | ) 654 | vim.api.nvim_create_user_command( 655 | "AstroRoot", 656 | function() require("astrocore.rooter").root() end, 657 | { desc = "Run root detection" } 658 | ) 659 | 660 | local group = vim.api.nvim_create_augroup("rooter", { clear = true }) -- clear the augroup no matter what 661 | vim.api.nvim_create_autocmd({ "VimEnter", "BufEnter" }, { 662 | nested = true, 663 | group = group, 664 | desc = "Root detection when entering a buffer", 665 | callback = function(args) 666 | if root_config.autochdir then require("astrocore.rooter").root(args.buf) end 667 | end, 668 | }) 669 | if vim.tbl_contains(root_config.detector or {}, "lsp") then 670 | vim.api.nvim_create_autocmd("LspAttach", { 671 | nested = true, 672 | group = group, 673 | desc = "Root detection on LSP attach", 674 | callback = function(args) 675 | if root_config.autochdir then 676 | local server = assert(vim.lsp.get_client_by_id(args.data.client_id)).name 677 | if not vim.tbl_contains(vim.tbl_get(root_config, "ignore", "servers") or {}, server) then 678 | require("astrocore.rooter").root(args.buf) 679 | end 680 | end 681 | end, 682 | }) 683 | end 684 | end 685 | 686 | local astroui_avail, astroui = pcall(require, "astroui") 687 | if astroui_avail then astroui.set_colorscheme() end 688 | end 689 | 690 | return M 691 | -------------------------------------------------------------------------------- /lua/astrocore/rooter.lua: -------------------------------------------------------------------------------- 1 | ---AstroNvim Rooter 2 | --- 3 | ---Utilities necessary for automatic root detectoin 4 | --- 5 | ---This module is heavily inspired by LazyVim and project.nvim 6 | ---https://github.com/ahmedkhalf/project.nvim 7 | ---https://github.com/LazyVim/LazyVim/blob/98db7ec0d287adcd8eaf6a93c4a392f588b5615a/lua/lazyvim/util/root.lua 8 | --- 9 | ---This module can be loaded with `local rooter = require "astrocore.rooter"` 10 | --- 11 | ---copyright 2023 12 | ---license GNU General Public License v3.0 13 | ---@class astrocore.rooter 14 | local M = { detectors = {} } 15 | 16 | ---@alias AstroCoreRooterDetectorFunc fun(bufnr: integer,...): string[] 17 | ---@alias AstroCoreRooterDetector fun(config:AstroCoreRooterOpts?):AstroCoreRooterDetectorFunc 18 | 19 | ---@class AstroCoreRooterDetectors 20 | ---@type table 21 | M.detectors = {} 22 | 23 | local vim_autochdir 24 | 25 | local function notify(msg, level) 26 | require("astrocore").notify(msg, level or vim.log.levels.INFO, { title = "AstroNvim Rooter" }) 27 | end 28 | 29 | local function resolve_config() return require("astrocore").config.rooter or {} end 30 | 31 | --- Create a detect workspace folders from active language servers 32 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 33 | ---@return AstroCoreRooterDetectorFunc 34 | function M.detectors.lsp(config) 35 | if not config then config = resolve_config() end 36 | ---@type (string[]|fun(client:vim.lsp.Client):boolean)? 37 | local server_filter = vim.tbl_get(config, "ignore", "servers") 38 | if server_filter and type(server_filter) ~= "function" then 39 | local ignore_servers = server_filter 40 | server_filter = function(lsp_client) return vim.tbl_contains(ignore_servers, lsp_client.name) end 41 | end 42 | return function(bufnr) 43 | local bufpath = M.bufpath(bufnr) 44 | if not bufpath then return {} end 45 | local roots = {} ---@type string[] 46 | for _, client in ipairs(vim.lsp.get_clients { buffer = bufnr }) do 47 | if not server_filter or not server_filter(client) then 48 | if client.root_dir then table.insert(roots, client.root_dir) end 49 | vim.tbl_map( 50 | function(ws) table.insert(roots, vim.uri_to_fname(ws.uri)) end, 51 | client.config.workspace_folders or {} 52 | ) 53 | end 54 | end 55 | local found_lsp_roots = {} 56 | return vim.tbl_filter(function(path) 57 | path = M.normpath(path) 58 | if path and bufpath:find(path, 1, true) == 1 then 59 | if not found_lsp_roots[path] then 60 | found_lsp_roots[path] = true 61 | return true 62 | end 63 | end 64 | return false 65 | end, roots) 66 | end 67 | end 68 | 69 | --- Create a detect folders matching patterns 70 | ---@return AstroCoreRooterDetectorFunc 71 | function M.detectors.pattern() 72 | return function(bufnr, patterns) 73 | if type(patterns) == "string" then patterns = { patterns } end 74 | local path = M.bufpath(bufnr) or vim.loop.cwd() 75 | if not path then return {} end 76 | local pattern = M.exists(path) and vim.fs.find(patterns, { path = path, upward = true })[1] 77 | return pattern and { vim.fs.dirname(pattern) } or {} 78 | end 79 | end 80 | 81 | ---@class AstroCoreRooterRoot 82 | ---@field paths string[] 83 | ---@field spec AstroCoreRooterSpec 84 | 85 | --- Get the real path of a buffer 86 | ---@param bufnr integer the buffer 87 | ---@return string? path the real path 88 | function M.bufpath(bufnr) return M.realpath(vim.api.nvim_buf_get_name(bufnr)) end 89 | 90 | --- Resolve a given path 91 | ---@param path? string the path to resolve 92 | ---@return string? the resolved path 93 | function M.realpath(path) 94 | if not path or path == "" then return nil end 95 | return M.normpath(vim.uv.fs_realpath(path) or path) 96 | end 97 | 98 | --- Check if a path exists 99 | ---@param path string the path 100 | ---@return boolean exists whether or not the path exists 101 | function M.exists(path) return vim.uv.fs_stat(path) ~= nil end 102 | 103 | --- Normalize path 104 | ---@param path string 105 | ---@return string 106 | function M.normpath(path) 107 | if path:sub(1, 1) == "~" then 108 | local home = assert(vim.loop.os_homedir()) 109 | if home:sub(-1) == "\\" or home:sub(-1) == "/" then home = home:sub(1, -2) end 110 | path = home .. path:sub(2) 111 | end 112 | path = path:gsub("\\", "/"):gsub("/+", "/") 113 | return (path:sub(-1) == "/" and path ~= "/") and path:sub(1, -2) or path 114 | end 115 | 116 | --- Resolve the root detection function for a given spec 117 | ---@param spec AstroCoreRooterSpec the root detector specification 118 | ---@param config? AstroCoreRooterOpts the root configuration 119 | ---@return function 120 | function M.resolve(spec, config) 121 | if M.detectors[spec] then 122 | return M.detectors[spec](config) 123 | elseif type(spec) == "function" then 124 | return spec 125 | end 126 | local pattern_detector = M.detectors.pattern(config) 127 | return function(bufnr) return pattern_detector(bufnr, spec) end 128 | end 129 | 130 | --- Detect roots in a given buffer 131 | ---@param bufnr? integer the buffer to detect 132 | ---@param all? boolean whether to return all roots or just one 133 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 134 | ---@return AstroCoreRooterRoot[] detected roots 135 | function M.detect(bufnr, all, config) 136 | if not config then config = resolve_config() end 137 | local ret = {} 138 | if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end 139 | 140 | if not require("astrocore.buffer").is_valid(bufnr) then return ret end 141 | 142 | local path = M.bufpath(bufnr) 143 | if path and M.is_excluded(path) then return ret end 144 | 145 | for _, spec in ipairs(config.detector or {}) do 146 | local paths = M.resolve(spec, config)(bufnr) 147 | if not paths then 148 | paths = {} 149 | elseif type(paths) ~= "table" then 150 | paths = { paths } 151 | end 152 | local roots = {} ---@type string[] 153 | for _, p in ipairs(paths) do 154 | local pp = M.realpath(p) 155 | if pp and not vim.tbl_contains(roots, pp) then roots[#roots + 1] = pp end 156 | end 157 | table.sort(roots, function(a, b) return #a > #b end) 158 | if #roots > 0 then 159 | table.insert(ret, { spec = spec, paths = roots }) 160 | if not all then break end 161 | end 162 | end 163 | return ret 164 | end 165 | 166 | --- Get information information about the current root 167 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 168 | function M.info(config) 169 | if not config then config = resolve_config() end 170 | local lines = {} 171 | if vim_autochdir then 172 | table.insert(lines, "Rooting disabled when `autochdir` is set") 173 | else 174 | local roots = M.detect(0, true, config) 175 | local first = true 176 | for _, root in ipairs(roots) do 177 | for _, path in ipairs(root.paths) do 178 | local surround = first and "**" or "" 179 | table.insert( 180 | lines, 181 | ("%s`%s` *(%s*)%s"):format( 182 | surround, 183 | path, 184 | type(root.spec) == "table" and table.concat(root.spec --[=[@as string[]]=], ", ") or root.spec, 185 | surround 186 | ) 187 | ) 188 | first = false 189 | end 190 | end 191 | table.insert(lines, "```lua") 192 | if config.detector then table.insert(lines, "detector = " .. vim.inspect(config.detector)) end 193 | if config.ignore then 194 | for _, type in ipairs { "dirs", "servers" } do 195 | local spec = config.ignore[type] 196 | if spec then table.insert(lines, "ignore." .. type .. " = " .. vim.inspect(spec)) end 197 | end 198 | end 199 | for _, key in ipairs { "scope", "autochdir", "notify" } do 200 | local setting = config[key] 201 | if setting then table.insert(lines, key .. " = " .. vim.inspect(setting)) end 202 | end 203 | table.insert(lines, "```") 204 | end 205 | notify(table.concat(lines, "\n")) 206 | end 207 | 208 | --- Set the current directory to a given root 209 | ---@param root AstroCoreRooterRoot the root to set the pwd to 210 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 211 | ---@return boolean success whether or not the pwd was successfully set 212 | function M.set_pwd(root, config) 213 | if not config then config = resolve_config() end 214 | local path = root.paths[1] 215 | if path ~= nil then 216 | if vim.fn.has "win32" > 0 then path = path:gsub("\\", "/") end 217 | if vim.fn.getcwd() ~= path then 218 | if config.scope == "global" then 219 | vim.api.nvim_set_current_dir(path) 220 | elseif config.scope == "tab" then 221 | vim.cmd.tchdir(path) 222 | elseif config.scope == "win" then 223 | vim.cmd.lchdir(path) 224 | else 225 | vim.api.nvim_err_writeln(("Unable to parse scope: %s"):format(config.scope)) 226 | end 227 | 228 | if config.notify then notify(("Set CWD to `%s`"):format(path)) end 229 | end 230 | return true 231 | end 232 | 233 | return false 234 | end 235 | 236 | --- Check if a path is excluded 237 | ---@param path string the path 238 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 239 | ---@return boolean excluded whether or not the path is excluded 240 | function M.is_excluded(path, config) 241 | if not config then config = resolve_config() end 242 | for _, path_pattern in ipairs(vim.tbl_get(config, "ignore", "dirs") or {}) do 243 | if path:match(M.normpath(path_pattern)) then return true end 244 | end 245 | return false 246 | end 247 | 248 | --- Run the root detection and set the current working directory if a new root is detected 249 | ---@param bufnr? integer the buffer to detect 250 | ---@param config? AstroCoreRooterOpts a rooter configuration (defaults to global configuration) 251 | function M.root(bufnr, config) 252 | -- add `autochdir` protection 253 | local autochdir = vim.opt.autochdir:get() 254 | if not vim_autochdir and autochdir then 255 | notify("Rooting disabled, unset `autochdir` to re-enable", vim.log.levels.WARN) 256 | vim_autochdir = true 257 | elseif vim_autochdir and not autochdir then 258 | vim_autochdir = false 259 | end 260 | 261 | if vim_autochdir or vim.v.vim_did_enter == 0 then return end 262 | 263 | if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end 264 | if not config then config = resolve_config() end 265 | local root = M.detect(bufnr, false, config)[1] 266 | if root then M.set_pwd(root, config) end 267 | end 268 | 269 | return M 270 | -------------------------------------------------------------------------------- /lua/astrocore/toggles.lua: -------------------------------------------------------------------------------- 1 | ---AstroNvim UI/UX Toggles 2 | --- 3 | --- Utility functions for easy UI toggles. 4 | --- 5 | ---This module can be loaded with `local ui = require("astrocore.toggles")` 6 | --- 7 | ---copyright 2023 8 | ---license GNU General Public License v3.0 9 | ---@class astrocore.toggles 10 | local M = {} 11 | 12 | local function bool2str(bool) return bool and "on" or "off" end 13 | local function ui_notify(silent, ...) return not silent and require("astrocore").notify(...) end 14 | 15 | --- Toggle rooter autochdir 16 | ---@param silent? boolean if true then don't sent a notification 17 | function M.autochdir(silent) 18 | local root_config = require("astrocore").config.rooter 19 | if not root_config then 20 | ui_notify(silent, "Rooter not configured") 21 | else 22 | root_config.autochdir = not root_config.autochdir 23 | ui_notify(silent, ("Rooter autochdir %s"):format(bool2str(root_config.autochdir))) 24 | end 25 | end 26 | 27 | --- Toggle notifications for UI toggles 28 | ---@param silent? boolean if true then don't sent a notification 29 | function M.notifications(silent) 30 | local features = assert(require("astrocore").config.features) 31 | features.notifications = not features.notifications 32 | ui_notify(silent, ("Notifications %s"):format(bool2str(features.notifications))) 33 | end 34 | 35 | --- Toggle autopairs 36 | ---@param silent? boolean if true then don't sent a notification 37 | function M.autopairs(silent) 38 | local ok, autopairs = pcall(require, "nvim-autopairs") 39 | if ok then 40 | if autopairs.state.disabled then 41 | autopairs.enable() 42 | else 43 | autopairs.disable() 44 | end 45 | require("astrocore").config.features.autopairs = autopairs.state.disabled 46 | ui_notify(silent, ("autopairs %s"):format(bool2str(not autopairs.state.disabled))) 47 | else 48 | ui_notify(silent, "autopairs not available") 49 | end 50 | end 51 | 52 | --- Toggle background="dark"|"light" 53 | ---@param silent? boolean if true then don't sent a notification 54 | function M.background(silent) 55 | vim.go.background = vim.go.background == "light" and "dark" or "light" 56 | ui_notify(silent, ("background=%s"):format(vim.go.background)) 57 | end 58 | 59 | --- Toggle cmp entrirely 60 | ---@param silent? boolean if true then don't sent a notification 61 | function M.cmp(silent) 62 | local features = assert(require("astrocore").config.features) 63 | features.cmp = not features.cmp 64 | local ok, _ = pcall(require, "cmp") 65 | ui_notify(silent, ok and ("Global completion %s"):format(bool2str(features.cmp)) or "completion not available") 66 | end 67 | 68 | --- Toggle buffer local cmp 69 | ---@param bufnr? integer the buffer to toggle cmp completion on 70 | ---@param silent? boolean if true then don't sent a notification 71 | function M.buffer_cmp(bufnr, silent) 72 | bufnr = (bufnr and bufnr ~= 0) and bufnr or vim.api.nvim_win_get_buf(0) 73 | if vim.b[bufnr].completion == nil then vim.b[bufnr].completion = require("astrocore").config.features.cmp end 74 | vim.b[bufnr].completion = not vim.b[bufnr].completion 75 | local ok, _ = pcall(require, "cmp") 76 | ui_notify( 77 | silent, 78 | ok and ("Buffer completion %s"):format(bool2str(vim.b[bufnr].completion)) or "completion not available" 79 | ) 80 | end 81 | 82 | --- Toggle showtabline=2|0 83 | ---@param silent? boolean if true then don't sent a notification 84 | function M.tabline(silent) 85 | vim.opt.showtabline = vim.opt.showtabline:get() == 0 and 2 or 0 86 | ui_notify(silent, ("tabline %s"):format(bool2str(vim.opt.showtabline:get() == 2))) 87 | end 88 | 89 | --- Toggle conceal=2|0 90 | ---@param silent? boolean if true then don't sent a notification 91 | function M.conceal(silent) 92 | vim.opt.conceallevel = vim.opt.conceallevel:get() == 0 and 2 or 0 93 | ui_notify(silent, ("conceal %s"):format(bool2str(vim.opt.conceallevel:get() == 2))) 94 | end 95 | 96 | --- Toggle laststatus=3|2|0 97 | ---@param silent? boolean if true then don't sent a notification 98 | function M.statusline(silent) 99 | local laststatus = vim.opt.laststatus:get() 100 | local status 101 | if laststatus == 0 then 102 | vim.opt.laststatus = 2 103 | status = "local" 104 | elseif laststatus == 2 then 105 | vim.opt.laststatus = 3 106 | status = "global" 107 | elseif laststatus == 3 then 108 | vim.opt.laststatus = 0 109 | status = "off" 110 | end 111 | ui_notify(silent, ("statusline %s"):format(status)) 112 | end 113 | 114 | --- Toggle signcolumn="auto"|"no" 115 | ---@param silent? boolean if true then don't sent a notification 116 | function M.signcolumn(silent) 117 | if vim.wo.signcolumn == "no" then 118 | vim.wo.signcolumn = "yes" 119 | elseif vim.wo.signcolumn == "yes" then 120 | vim.wo.signcolumn = "auto" 121 | else 122 | vim.wo.signcolumn = "no" 123 | end 124 | ui_notify(silent, ("signcolumn=%s"):format(vim.wo.signcolumn)) 125 | end 126 | 127 | --- Set the indent and tab related numbers 128 | ---@param silent? boolean if true then don't sent a notification 129 | function M.indent(silent) 130 | local input_avail, input = pcall(vim.fn.input, "Set indent value (>0 expandtab, <=0 noexpandtab): ") 131 | if input_avail then 132 | local indent = tonumber(input) 133 | if not indent or indent == 0 then return end 134 | vim.bo.expandtab = (indent > 0) -- local to buffer 135 | indent = math.abs(indent) 136 | vim.bo.tabstop = indent -- local to buffer 137 | vim.bo.softtabstop = indent -- local to buffer 138 | vim.bo.shiftwidth = indent -- local to buffer 139 | ui_notify(silent, ("indent=%d %s"):format(indent, vim.bo.expandtab and "expandtab" or "noexpandtab")) 140 | end 141 | end 142 | 143 | --- Change the number display modes 144 | ---@param silent? boolean if true then don't sent a notification 145 | function M.number(silent) 146 | local number = vim.wo.number -- local to window 147 | local relativenumber = vim.wo.relativenumber -- local to window 148 | if not number and not relativenumber then 149 | vim.wo.number = true 150 | elseif number and not relativenumber then 151 | vim.wo.relativenumber = true 152 | elseif number and relativenumber then 153 | vim.wo.number = false 154 | else -- not number and relativenumber 155 | vim.wo.relativenumber = false 156 | end 157 | ui_notify(silent, ("number %s, relativenumber %s"):format(bool2str(vim.wo.number), bool2str(vim.wo.relativenumber))) 158 | end 159 | 160 | --- Toggle spell 161 | ---@param silent? boolean if true then don't sent a notification 162 | function M.spell(silent) 163 | vim.wo.spell = not vim.wo.spell -- local to window 164 | ui_notify(silent, ("spell %s"):format(bool2str(vim.wo.spell))) 165 | end 166 | 167 | --- Toggle paste 168 | ---@param silent? boolean if true then don't sent a notification 169 | function M.paste(silent) 170 | local paste = not assert(vim.opt.paste):get() 171 | vim.opt.paste = paste -- local to window 172 | ui_notify(silent, ("paste %s"):format(bool2str(paste))) 173 | end 174 | 175 | --- Toggle wrap 176 | ---@param silent? boolean if true then don't sent a notification 177 | function M.wrap(silent) 178 | vim.wo.wrap = not vim.wo.wrap -- local to window 179 | ui_notify(silent, ("wrap %s"):format(bool2str(vim.wo.wrap))) 180 | end 181 | 182 | --- Toggle syntax highlighting and treesitter 183 | ---@param bufnr? integer the buffer to toggle syntax on 184 | ---@param silent? boolean if true then don't sent a notification 185 | function M.buffer_syntax(bufnr, silent) 186 | -- HACK: this should just be `bufnr = bufnr or 0` but it looks like `vim.treesitter.stop` has a bug with `0` being current 187 | bufnr = (bufnr and bufnr ~= 0) and bufnr or vim.api.nvim_win_get_buf(0) 188 | local ts_avail, parsers = pcall(require, "nvim-treesitter.parsers") 189 | local astrolsp_avail, lsp_toggle = pcall(require, "astrolsp.toggles") 190 | if vim.bo[bufnr].syntax == "off" then 191 | if ts_avail and parsers.has_parser() then vim.treesitter.start(bufnr) end 192 | vim.bo[bufnr].syntax = "on" 193 | if astrolsp_avail and not vim.b[bufnr].semantic_tokens then lsp_toggle.buffer_semantic_tokens(bufnr, true) end 194 | else 195 | if ts_avail and parsers.has_parser() then vim.treesitter.stop(bufnr) end 196 | vim.bo[bufnr].syntax = "off" 197 | if astrolsp_avail and vim.b[bufnr].semantic_tokens then lsp_toggle.buffer_semantic_tokens(bufnr, true) end 198 | end 199 | ui_notify(silent, ("syntax %s"):format(vim.bo[bufnr].syntax)) 200 | end 201 | 202 | --- Toggle URL/URI syntax highlighting rules 203 | ---@param silent? boolean if true then don't sent a notification 204 | function M.url_match(silent) 205 | local features = assert(require("astrocore").config.features) 206 | features.highlighturl = not features.highlighturl 207 | vim.tbl_map(require("astrocore").set_url_match, vim.api.nvim_list_wins()) 208 | ui_notify(silent, ("URL highlighting %s"):format(bool2str(features.highlighturl))) 209 | end 210 | 211 | local last_active_foldcolumn 212 | --- Toggle foldcolumn=0|1 213 | ---@param silent? boolean if true then don't sent a notification 214 | function M.foldcolumn(silent) 215 | local curr_foldcolumn = vim.wo.foldcolumn 216 | if curr_foldcolumn ~= "0" then last_active_foldcolumn = curr_foldcolumn end 217 | vim.wo.foldcolumn = curr_foldcolumn == "0" and (last_active_foldcolumn or "1") or "0" 218 | ui_notify(silent, ("foldcolumn=%s"):format(vim.wo.foldcolumn)) 219 | end 220 | 221 | --- Toggle diagnostics 222 | ---@param silent? boolean if true then don't sent a notification 223 | function M.diagnostics(silent) 224 | vim.diagnostic.enable(not vim.diagnostic.is_enabled()) 225 | ui_notify(silent, ("Diagnostics %s"):format(bool2str(vim.diagnostic.is_enabled()))) 226 | end 227 | 228 | local previous_virtual_text 229 | --- Toggle diagnostics virtual text 230 | ---@param silent? boolean if true then don't sent a notification 231 | function M.virtual_text(silent) 232 | local virtual_text = vim.diagnostic.config().virtual_text 233 | local new_virtual_text = false 234 | if virtual_text then 235 | previous_virtual_text = virtual_text 236 | else 237 | new_virtual_text = previous_virtual_text or true 238 | end 239 | vim.diagnostic.config { virtual_text = new_virtual_text } 240 | ui_notify(silent, ("Virtual text %s"):format(bool2str(new_virtual_text))) 241 | end 242 | 243 | local previous_virtual_lines 244 | --- Toggle diagnostics virtual lines 245 | ---@param silent? boolean if true then don't sent a notification 246 | function M.virtual_lines(silent) 247 | local virtual_lines = vim.diagnostic.config().virtual_lines 248 | -- TODO: remove check when dropping support for Neovim v0.10 249 | if virtual_lines == nil then ui_notify(silent, "Virtual lines not available") end 250 | local new_virtual_lines = false 251 | if virtual_lines then 252 | previous_virtual_lines = virtual_lines 253 | else 254 | new_virtual_lines = previous_virtual_lines or true 255 | end 256 | vim.diagnostic.config { virtual_lines = new_virtual_lines } 257 | ui_notify(silent, ("Virtual lines %s"):format(bool2str(new_virtual_lines))) 258 | end 259 | 260 | return M 261 | -------------------------------------------------------------------------------- /lua/resession/extensions/astrocore.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | ---@param opts resession.Extension.OnSaveOpts 4 | function M.on_save(opts) 5 | -- initiate astronvim data 6 | local data = { bufnrs = {}, tabs = {} } 7 | 8 | local buf_utils = require "astrocore.buffer" 9 | 10 | data.current_buf = buf_utils.current_buf 11 | data.last_buf = buf_utils.last_buf 12 | 13 | -- save tab scoped buffers and buffer numbers from buffer name 14 | for new_tabpage, tabpage in ipairs(vim.api.nvim_list_tabpages()) do 15 | if tabpage == opts.tabpage then data.tabpage = new_tabpage end 16 | data.tabs[new_tabpage] = vim.t[tabpage].bufs 17 | for _, bufnr in ipairs(data.tabs[new_tabpage]) do 18 | data.bufnrs[vim.api.nvim_buf_get_name(bufnr)] = bufnr 19 | end 20 | end 21 | 22 | return data 23 | end 24 | 25 | function M.on_post_load(data) 26 | -- create map from old buffer numbers to new buffer numbers 27 | local new_bufnrs = {} 28 | local new_tabpages = vim.api.nvim_list_tabpages() 29 | for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do 30 | local old_bufnr = data.bufnrs[vim.api.nvim_buf_get_name(bufnr)] 31 | if old_bufnr then new_bufnrs[old_bufnr] = bufnr end 32 | end 33 | -- build new tab scoped buffer lists 34 | if not data.tabpage then 35 | for tabpage, tabs in pairs(data.tabs) do 36 | local bufs = vim.tbl_map(function(bufnr) return new_bufnrs[bufnr] end, tabs) 37 | vim.t[new_tabpages[tabpage]].bufs = bufs 38 | end 39 | else 40 | vim.t.bufs = vim.tbl_map(function(bufnr) return new_bufnrs[bufnr] end, data.tabs[data.tabpage]) 41 | end 42 | 43 | local buf_utils = require "astrocore.buffer" 44 | local current_buf, last_buf = new_bufnrs[data.current_buf], new_bufnrs[data.last_buf] 45 | if current_buf and last_buf then 46 | buf_utils.current_buf = current_buf 47 | buf_utils.last_buf = last_buf 48 | end 49 | 50 | require("astrocore").event "BufsUpdated" 51 | 52 | if current_buf and last_buf then 53 | if vim.opt.bufhidden:get() == "wipe" and vim.fn.bufnr() ~= buf_utils.current_buf then 54 | vim.cmd.b(buf_utils.current_buf) 55 | end 56 | end 57 | end 58 | 59 | return M 60 | -------------------------------------------------------------------------------- /neovim.yml: -------------------------------------------------------------------------------- 1 | --- 2 | base: lua51 3 | 4 | globals: 5 | vim: 6 | any: true 7 | bit: 8 | any: true 9 | -------------------------------------------------------------------------------- /selene.toml: -------------------------------------------------------------------------------- 1 | std = "neovim" 2 | 3 | [rules] 4 | global_usage = "allow" 5 | if_same_then_else = "allow" 6 | incorrect_standard_library_use = "allow" 7 | mixed_table = "allow" 8 | multiple_statements = "allow" 9 | --------------------------------------------------------------------------------