├── .github └── workflows │ └── document.yml ├── .gitignore ├── .stylua.toml ├── LICENSE ├── README.md ├── after └── ftplugin │ ├── llvm.vim │ ├── markdown.lua │ ├── mir.vim │ ├── scala.lua │ ├── tablegen.vim │ └── typst.lua ├── bump_treesitter.hs ├── flake-lock └── generated.json ├── flake.lock ├── flake.nix ├── fourmolu.yaml ├── ftdetect ├── inc.vim ├── llvm-lit.vim ├── llvm.vim ├── makepkg.vim ├── mill.vim ├── mlir.vim ├── sail.vim ├── sc.vim └── tablegen.vim ├── indent ├── llvm.vim ├── mlir.vim └── nix.vim ├── init.lua ├── lazy-lock.json ├── lua ├── README.md ├── builder │ └── key-mapper.lua ├── completion │ ├── init.lua │ └── rc.lua ├── core │ ├── autocmd.lua │ ├── init.lua │ └── options.lua ├── git │ ├── gitsigns.lua │ └── init.lua ├── key-mapping.lua ├── lang │ ├── configs.lua │ ├── deno.lua │ ├── init.lua │ ├── on_attach.lua │ └── scala.lua ├── libs │ ├── bigfile.lua │ ├── bufdel.lua │ ├── cache.lua │ ├── find_root.lua │ └── notify.lua ├── pack.lua ├── tools │ └── init.lua ├── treesitter │ ├── config.lua │ └── init.lua └── ui │ ├── indent.lua │ ├── init.lua │ ├── kanagawa.lua │ └── statusline.lua ├── nix ├── mkTreesitter.nix ├── nvfetcher.toml ├── nvim-treesitter-lock-file.nix └── nvim-treesitter-parsers.nix ├── nvfetcher.toml ├── overlay.nix └── syntax ├── llvm.vim ├── machine-ir.vim ├── mir.vim ├── mlir.vim ├── sail.vim └── tablegen.vim /.github/workflows/document.yml: -------------------------------------------------------------------------------- 1 | name: Document build 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'docs/manual' 7 | - '.github/workflows/document.yml' 8 | 9 | jobs: 10 | build-and-deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: Setup mdBook 17 | uses: peaceiris/actions-mdbook@v1 18 | with: 19 | mdbook-version: 'latest' 20 | 21 | - name: Build document 22 | run: cd docs/manual && mdbook build 23 | 24 | - name: Deploy 25 | uses: JamesIves/github-pages-deploy-action@v4 26 | with: 27 | branch: gh-pages 28 | folder: docs/manual/book 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .neovim.lua 2 | result 3 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | column_width = 100 2 | line_endings = "Unix" 3 | indent_type = "Spaces" 4 | indent_width = 2 5 | quote_style = "AutoPreferDouble" 6 | call_parentheses = "Always" 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Neovim Configuration 2 | 3 | This Neovim configuration is built with a focus on a simple, elegant, and 4 | distraction-free user interface. The goal is to enhance coding usability rather 5 | than overwhelm with fancy, unnecessary UI elements. I will consistently add and 6 | test plugins with multiple coding scenario, keep only those are suitable for 7 | daily use. 8 | 9 | - Clean & Minimalist Aesthetic: Enjoy a calm, focused coding environment that 10 | prioritizes what matters most: your code. 11 | - Streamlined Workflow: Optimized for efficiency, allowing you to code faster 12 | and with less friction. 13 | - Essential Tooling: Includes carefully selected plugins and settings that 14 | genuinely improve the coding experience without adding clutter. 15 | - Performance-Oriented: Lightweight and responsive, ensuring a smooth 16 | experience even with larger projects. 17 | - Focus on Readability: UI elements are designed to be clear and unobtrusive, 18 | making your code the star of the show. 19 | - Usability First: Every feature and plugin is chosen with practical coding 20 | benefits in mind, not just for visual appeal. 21 | 22 | ## Getting Start 23 | 24 | This configuration is compatible with neovim 0.10+ version. 25 | 26 | ```bash 27 | git clone --depth=1 https://github.com/Avimitin/nvim.git ~/.config/nvim 28 | ``` 29 | 30 | Finally, input `nvim` to open the editor, and all plugins will be downloaded automatically. 31 | 32 | ```bash 33 | nvim 34 | ``` 35 | 36 | ### Nix nerds 37 | 38 | To use this in your home-manager, you can use the `xdg.configFile` attribute: 39 | 40 | ```nix 41 | { pkgs }: 42 | { 43 | xdg.configFile = { 44 | neovim = { 45 | target = "nvim"; 46 | source = pkgs.fetchFromGitHub { 47 | repo = "nvim"; 48 | owner = "Avimitin"; 49 | rev = "..."; 50 | hash = "..."; 51 | } 52 | }; 53 | }; 54 | } 55 | ``` 56 | 57 | Diagnostic error/warning/hint are highlighted with undercurl, please use 58 | [kitty](https://sw.kovidgoyal.net/kitty/), 59 | [wezterm](https://wezfurlong.org/wezterm/index.html) 60 | or anyother terminal that support undercurl. 61 | 62 | If you are using tmux, to have a correct display, you can try my configuration below: 63 | 64 | ```tmux 65 | # (MUST) Enable 256 color for tmux 66 | set -g default-terminal "tmux-256color" 67 | 68 | # (Optional, choose any of them) 69 | # Enable true color and undercurl for wezterm 70 | set -as terminal-features ",wezterm*:RGB" 71 | set -as terminal-features ",wezterm*:usstyle" 72 | # Same as above, but for kitty. (kitty doesn't support Windows so I have to keep two configuration here) 73 | set -as terminal-features ",kitty*:RGB" 74 | set -as terminal-features ",kitty*:usstyle" 75 | # Same as above, but for SSH. This is useful because I am using `alias ssh="TERM=xterm-256color exec ssh"` 76 | set -as terminal-features ",xterm-256color*:RGB" 77 | set -as terminal-features ",xterm-256color*:usstyle" 78 | set -as terminal-overrides ",xterm*:Tc" 79 | 80 | # (MUST) This hijack the neovim undercurl char sequence, to avoid tmux escape them. 81 | set -as terminal-overrides ',*:Smulx=\E[4::%p1%dm' 82 | ``` 83 | 84 | ## Project Structure 85 | 86 | - `after/ftplugin/.lua`: missing default configuration for filetypes 87 | - `lua`: the configuration core 88 | 89 | * `key-mapping.lua`: my modification to the built-in key mappings 90 | * `pack.lua`: script to download lazy.nvim plugin manager 91 | * `core/`: my modification to the built-in options and auto commands 92 | * `completion/`: plugins and configuration for LSP and vim command completion 93 | * `git/`: plugin and configuration for using git in Neovim 94 | * `lang/`: plugins and configuration for using LSP server and get diagnostic in Neovim 95 | * `libs/`: functions that I don't want to write twice 96 | * `tools/`: miscellaneous plugins that can enhance editing experience 97 | * `treesitter/`: plugins for text object highlight and editing 98 | * `ui/`: plugins for decorating the neovim 99 | 100 | - `ftdetect`: List of script to help neovim identify filetype for some file, not important. 101 | - `indent`: List of script to help neovim properly set indentation, not important. 102 | - `syntax`: Additional syntax detection for some file type, not important. 103 | 104 | 105 | ## Treesitter parsers in nix 106 | 107 | - For normal user: make sure gcc is installed, then run `:TSInstall ` to compile and install corresponding treesitter plugin 108 | - For nix user: you can add this repository as an overlay and use the pre-bundled neovim: 109 | 110 | ```nix 111 | # flake.nix 112 | { 113 | description = "Simple home-manager neovim configuration"; 114 | 115 | inputs = { 116 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 117 | my-neovim.url = "github:Avimitin/nvim"; 118 | home-manager = { 119 | url = "github:nix-community/home-manager"; 120 | inputs.nixpkgs.follows = "nixpkgs"; 121 | }; 122 | }; 123 | 124 | outputs = { self, nixpkgs, flake-utils, home-manager, my-neovim }: { 125 | homeConfiguration = home-manager.lib.homeManagerConfiguration { 126 | # import my overlay, it will add a new `neovim-nightly` derivation into your nixpkgs 127 | pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ my-neovim.overlays.default ]; }; 128 | modules = [ 129 | ({ pkgs }: { 130 | # Then add the pre-bundled neovim into your home configuration 131 | home.packages = [ 132 | pkgs.neovim-nightly 133 | ]; 134 | }) 135 | ]; 136 | }; 137 | }; 138 | } 139 | ``` 140 | 141 | ## License 142 | 143 | This configuration since commit `912416ae9c4b55501b23a91d774b567ba8697dd1` are 144 | licenced under the Apache 2.0 license. 145 | 146 | 另附:禁止在 CSDN,bilibili 等国内平台使用该配置文件进行任何活动。 147 | 你只保有自己修改部分的权利。 148 | 149 | # Additional notes 150 | 151 | ## About treesitter bumping 152 | 153 | - Run `:Lazy sync` 154 | - Remove hash in ./nix/nvim-treesitter-lock-file.nix 155 | - Run `nix build '.#neovim-nightly'` 156 | - Update hash 157 | - Run `./bump_treesitter.hs` 158 | - Run `nix build '.#neovim-nightly'` 159 | -------------------------------------------------------------------------------- /after/ftplugin/llvm.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin file 2 | " Language: LLVM Assembly 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | 5 | if exists("b:did_ftplugin") 6 | finish 7 | endif 8 | let b:did_ftplugin = 1 9 | 10 | setlocal softtabstop=2 shiftwidth=2 11 | setlocal expandtab 12 | setlocal comments+=:; 13 | -------------------------------------------------------------------------------- /after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | if require("libs.cache")["markdown"] then 2 | return 3 | end 4 | 5 | vim.b.table_mode_corner = "|" 6 | vim.opt_local.spell = true 7 | -------------------------------------------------------------------------------- /after/ftplugin/mir.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin file 2 | " Language: LLVM Machine IR 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | 5 | if exists("b:did_ftplugin") 6 | finish 7 | endif 8 | let b:did_ftplugin = 1 9 | 10 | setlocal softtabstop=2 shiftwidth=2 11 | setlocal expandtab 12 | setlocal comments+=:; 13 | 14 | -------------------------------------------------------------------------------- /after/ftplugin/scala.lua: -------------------------------------------------------------------------------- 1 | if require("libs.cache")["scala"] then 2 | return 3 | end 4 | 5 | local scala_config = require("metals").bare_config() 6 | scala_config.settings = { 7 | showImplicitArguments = true, 8 | excludedPackages = { "akka.actor.typed.javadsl", "com.github.swagger.akka.javadsl" }, 9 | } 10 | 11 | local metals_binary = vim.fn.exepath("metals") 12 | if not metals_binary or metals_binary == "" then 13 | vim.notify("metals not found, stop configuring LSP.", vim.log.levels.WARN) 14 | return 15 | end 16 | scala_config.settings.metalsBinaryPath = metals_binary 17 | 18 | local mill_exe = vim.fn.exepath("mill") 19 | if not mill_exe or mill_exe == "" then 20 | vim.notify("mill not found, stop configuring metals.", vim.log.levels.WARN) 21 | return 22 | end 23 | 24 | scala_config.init_options.statusBarProvider = "off" 25 | scala_config.root_patterns = { "build.sbt", "build.sc", "build.gradle", "pom.xml", ".git" } 26 | scala_config.find_root_dir_max_project_nesting = 0 27 | scala_config.settings.millScript = mill_exe 28 | scala_config.capabilities = require("cmp_nvim_lsp").default_capabilities() 29 | scala_config.on_attach = require("lang.on_attach").setup_all 30 | require("metals").initialize_or_attach(scala_config) 31 | 32 | -- nvim-metals will send metals/didFocus protocol to all the buffer, which will cause other LSP to exits. 33 | -- Here I recreate the nvim-metasls-forcus auto commands to force it run on *.scala/*.sc only. 34 | -- Using LspAttach here to delay the erase execution, because the nvim-metals plugin define the 35 | -- auto commands after buffer attached. 36 | vim.api.nvim_create_autocmd("LspAttach", { 37 | pattern = { "*.scala", "*.sc" }, 38 | callback = function() 39 | vim.schedule(function() 40 | vim.api.nvim_clear_autocmds({ group = "nvim-metals-focus" }) 41 | vim.api.nvim_create_autocmd("BufEnter", { 42 | pattern = { "*.scala", "*.sc" }, 43 | callback = function() 44 | require("metals").did_focus() 45 | end, 46 | group = vim.api.nvim_create_augroup("nvim-metals-focus", { clear = true }), 47 | }) 48 | end) 49 | end, 50 | }) 51 | -------------------------------------------------------------------------------- /after/ftplugin/tablegen.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin file 2 | " Language: LLVM TableGen 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | 5 | if exists("b:did_ftplugin") 6 | finish 7 | endif 8 | let b:did_ftplugin = 1 9 | 10 | setlocal matchpairs+=<:> 11 | setlocal softtabstop=2 shiftwidth=2 12 | setlocal expandtab 13 | -------------------------------------------------------------------------------- /after/ftplugin/typst.lua: -------------------------------------------------------------------------------- 1 | if require("libs.cache")["typst"] then 2 | return 3 | end 4 | 5 | vim.opt_local.spell = true 6 | -------------------------------------------------------------------------------- /bump_treesitter.hs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix 2 | #!nix shell .#ghc-for-ts-plugins -c runghc 3 | 4 | {-# LANGUAGE DeriveGeneric #-} 5 | {-# LANGUAGE OverloadedStrings #-} 6 | {-# OPTIONS_GHC -Wall #-} 7 | 8 | import qualified Control.Concurrent.Async 9 | import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan) 10 | import qualified Control.Foldl as Fold 11 | import qualified Data.Aeson as Aeson 12 | import qualified Data.ByteString.Builder 13 | import qualified Data.Text 14 | import qualified Data.Text.Encoding 15 | import qualified Data.Text.IO as TIO 16 | import qualified GHC.Generics 17 | import qualified System.IO 18 | import Turtle 19 | 20 | {- | This wrapped in Maybe because I am using Channel based IO for read and write file. 21 | A `Nothing` constructor could help us exit the dangling updater when finish. 22 | -} 23 | type NewHashInfo = Maybe (Text, Text, Text) 24 | 25 | data DerivationInfo = DerivationInfo 26 | { name :: Text 27 | , url :: Text 28 | , hash :: Text 29 | } 30 | deriving (GHC.Generics.Generic, Show) 31 | 32 | instance Aeson.FromJSON DerivationInfo 33 | 34 | procGetStdout :: Text -> [Text] -> IO Text 35 | procGetStdout cmd args = do 36 | (exitCode, rawOut, rawErr) <- procStrictWithErr cmd args empty 37 | case exitCode of 38 | ExitSuccess -> return $ Data.Text.strip rawOut 39 | ExitFailure code -> 40 | die $ "command " <> cmd <> " fail with exit code " <> repr code <> ", stderr: " <> rawErr 41 | 42 | getSrcInfo :: a -> IO [DerivationInfo] 43 | getSrcInfo _ = do 44 | rawJson <- 45 | procGetStdout 46 | "nix" 47 | [ "eval" 48 | , "--json" 49 | , ".#treesitter-plugin-nightly" 50 | , "--apply" 51 | , "pkg: map (p: { name = p.name; url = p.src.url; hash = p.src.outputHash; }) pkg.plugins" 52 | ] 53 | case Aeson.decode $ 54 | Data.ByteString.Builder.toLazyByteString $ 55 | Data.Text.Encoding.encodeUtf8Builder rawJson of 56 | Just a -> return a 57 | Nothing -> die "fail parsing JSON value, invalid nix output" 58 | 59 | nixPrefetch :: Text -> IO Text 60 | nixPrefetch url = do 61 | TIO.putStrLn $ format ("Exec nix-prefetch-url with url: " % s) url 62 | rawOut <- procGetStdout "nix-prefetch-url" [url, "--print-path", "--type", "sha256"] 63 | return $ last $ Data.Text.lines rawOut 64 | 65 | nixHash :: Text -> IO Text 66 | nixHash filepath = do 67 | TIO.putStrLn $ format ("Exec nix hash with file: " % s) filepath 68 | procGetStdout "nix" ["hash", "file", "--base16", "--type", "sha256", "--sri", filepath] 69 | 70 | updateHash :: Chan NewHashInfo -> Text -> Text -> Text -> IO () 71 | updateHash chan name old new = do 72 | TIO.putStrLn $ format (s % " hash changed from " % s % " to " % s) name old new 73 | liftIO $ writeChan chan $ Just (name, old, new) 74 | 75 | updateHashFromChan :: Chan NewHashInfo -> IO () 76 | updateHashFromChan chan = do 77 | msg <- readChan chan 78 | case msg of 79 | Just (name, old, new) -> do 80 | TIO.putStrLn $ format ("Replacing hash for derivation " % s) name 81 | inplace (text old *> return new) "overlay.nix" 82 | updateHashFromChan chan 83 | Nothing -> do 84 | TIO.putStrLn "Bye!" 85 | return () 86 | 87 | tryUpdateHash :: Chan NewHashInfo -> DerivationInfo -> IO () 88 | tryUpdateHash chan DerivationInfo{name = pname, url = purl, hash = oldHash} = do 89 | filepath <- nixPrefetch purl 90 | newHash <- nixHash filepath 91 | TIO.putStrLn $ format ("Examinate hash for " % s) pname 92 | when (oldHash /= newHash) $ do 93 | updateHash chan pname oldHash newHash 94 | 95 | -- | return a list of async handle for task update 96 | updateOverlayWithAsync :: 97 | Chan NewHashInfo -> [DerivationInfo] -> Shell (Control.Concurrent.Async.Async ()) 98 | updateOverlayWithAsync chan originDrvsInfo = do 99 | drv <- select originDrvsInfo 100 | liftIO $ Control.Concurrent.Async.async $ tryUpdateHash chan drv 101 | 102 | updateOverlay :: [DerivationInfo] -> Shell () 103 | updateOverlay originDrvsInfo = do 104 | chan <- 105 | liftIO 106 | ( do 107 | chan <- newChan :: IO (Chan NewHashInfo) 108 | _ <- Control.Concurrent.Async.async $ updateHashFromChan chan 109 | return chan 110 | ) 111 | asyncHandles <- flip fold Fold.list $ updateOverlayWithAsync chan originDrvsInfo 112 | mapM_ wait asyncHandles 113 | liftIO $ writeChan chan Nothing 114 | 115 | bump :: IO () 116 | bump = do 117 | printf "Start bumping\n" 118 | allInfos <- getSrcInfo () 119 | sh $ updateOverlay allInfos 120 | 121 | main :: IO () 122 | main = do 123 | System.IO.hSetBuffering System.IO.stdout System.IO.LineBuffering 124 | bump 125 | -------------------------------------------------------------------------------- /flake-lock/generated.json: -------------------------------------------------------------------------------- 1 | { 2 | "flake-utils": { 3 | "cargoLocks": null, 4 | "date": "2024-11-13", 5 | "extract": null, 6 | "name": "flake-utils", 7 | "passthru": null, 8 | "pinned": false, 9 | "src": { 10 | "sha256": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 11 | "type": "tarball", 12 | "url": "https://github.com/numtide/flake-utils/archive/11707dc2f618dd54ca8739b309ec4fc024de578b.tar.gz" 13 | }, 14 | "version": "11707dc2f618dd54ca8739b309ec4fc024de578b" 15 | }, 16 | "nixpkgs": { 17 | "cargoLocks": null, 18 | "date": "2025-04-02", 19 | "extract": null, 20 | "name": "nixpkgs", 21 | "passthru": null, 22 | "pinned": false, 23 | "src": { 24 | "sha256": "sha256-ZID5T65E8ruHqWRcdvZLsczWDOAWIE7om+vQOREwiX0=", 25 | "type": "tarball", 26 | "url": "https://github.com/NixOS/nixpkgs/archive/b7ba7f9f45c5cd0d8625e9e217c28f8eb6a19a76.tar.gz" 27 | }, 28 | "version": "b7ba7f9f45c5cd0d8625e9e217c28f8eb6a19a76" 29 | }, 30 | "treefmt-nix": { 31 | "cargoLocks": null, 32 | "date": "2025-04-02", 33 | "extract": null, 34 | "name": "treefmt-nix", 35 | "passthru": null, 36 | "pinned": false, 37 | "src": { 38 | "sha256": "sha256-iBzr7Zb11nQxwX90bO1+Bm1MGlhMSmu4ixgnQFB+j4E=", 39 | "type": "tarball", 40 | "url": "https://github.com/numtide/treefmt-nix/archive/18bed671738e36c5504e188aadc18b7e2a6e408f.tar.gz" 41 | }, 42 | "version": "18bed671738e36c5504e188aadc18b7e2a6e408f" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "root": {} 4 | }, 5 | "root": "root", 6 | "version": 7 7 | } 8 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Flakes for running this configuration"; 3 | 4 | outputs = 5 | _: 6 | let 7 | jsonToSrc = 8 | file: 9 | with builtins; 10 | let 11 | srcDefines = fromJSON (readFile file); 12 | in 13 | mapAttrs ( 14 | name: value: 15 | fetchTarball { 16 | inherit (value.src) url sha256; 17 | } 18 | ) srcDefines; 19 | inputs = jsonToSrc ./flake-lock/generated.json; 20 | overlay = import ./overlay.nix; 21 | in 22 | { 23 | overlays.default = overlay; 24 | neovimConfig = 25 | let 26 | lib = import "${inputs.nixpkgs}/lib"; 27 | in 28 | with lib.fileset; 29 | toSource { 30 | root = ./.; 31 | fileset = unions [ 32 | ./after 33 | ./ftdetect 34 | ./indent 35 | ./lua 36 | ./syntax 37 | ./vsnip 38 | ./init.lua 39 | ./lazy-lock.json 40 | ]; 41 | }; 42 | } 43 | // (import inputs.flake-utils).eachDefaultSystem ( 44 | system: 45 | let 46 | pkgs = import inputs.nixpkgs { 47 | overlays = [ overlay ]; 48 | inherit system; 49 | }; 50 | treefmtEval = (import inputs.treefmt-nix).lib.evalModule pkgs { 51 | projectRootFile = "flake.nix"; 52 | settings.verbose = 1; 53 | programs.nixfmt.enable = true; 54 | }; 55 | in 56 | { 57 | formatter = treefmtEval.config.build.wrapper; 58 | legacyPackages = pkgs; 59 | devShells.default = pkgs.mkShell { 60 | nativeBuildInputs = with pkgs.haskellPackages; [ 61 | pkgs.ghc-for-ts-plugins 62 | fourmolu 63 | haskell-language-server 64 | ]; 65 | }; 66 | } 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /fourmolu.yaml: -------------------------------------------------------------------------------- 1 | # Number of spaces per indentation step 2 | indentation: 4 3 | 4 | # Max line length for automatic line breaking 5 | column-limit: 100 6 | 7 | # Styling of arrows in type signatures (choices: trailing, leading, or leading-args) 8 | function-arrows: trailing 9 | 10 | # How to place commas in multi-line lists, records, etc. (choices: leading or trailing) 11 | comma-style: leading 12 | 13 | # Styling of import/export lists (choices: leading, trailing, or diff-friendly) 14 | import-export-style: diff-friendly 15 | 16 | # Whether to full-indent or half-indent 'where' bindings past the preceding body 17 | indent-wheres: false 18 | 19 | # Whether to leave a space before an opening record brace 20 | record-brace-space: false 21 | 22 | # Number of spaces between top-level declarations 23 | newlines-between-decls: 1 24 | 25 | # How to print Haddock comments (choices: single-line, multi-line, or multi-line-compact) 26 | haddock-style: multi-line 27 | 28 | # How to print module docstring 29 | haddock-style-module: null 30 | 31 | # Styling of let blocks (choices: auto, inline, newline, or mixed) 32 | let-style: auto 33 | 34 | # How to align the 'in' keyword with respect to the 'let' keyword (choices: left-align, right-align, or no-space) 35 | in-style: right-align 36 | 37 | # Whether to put parentheses around a single constraint (choices: auto, always, or never) 38 | single-constraint-parens: always 39 | 40 | # Output Unicode syntax (choices: detect, always, or never) 41 | unicode: never 42 | 43 | # Give the programmer more choice on where to insert blank lines 44 | respectful: true 45 | 46 | # Fixity information for operators 47 | fixities: [] 48 | 49 | # Module reexports Fourmolu should know about 50 | reexports: [] 51 | 52 | -------------------------------------------------------------------------------- /ftdetect/inc.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.cpp.inc set filetype=cpp 2 | au BufRead,BufNewFile *.h.inc set filetype=cpp 3 | -------------------------------------------------------------------------------- /ftdetect/llvm-lit.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile lit.*cfg set filetype=python 2 | -------------------------------------------------------------------------------- /ftdetect/llvm.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.ll set filetype=llvm 2 | -------------------------------------------------------------------------------- /ftdetect/makepkg.vim: -------------------------------------------------------------------------------- 1 | autocmd BufNewFile,BufRead .makepkg.conf set filetype=bash 2 | -------------------------------------------------------------------------------- /ftdetect/mill.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.mill set filetype=scala 2 | -------------------------------------------------------------------------------- /ftdetect/mlir.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.mlir set filetype=mlir 2 | -------------------------------------------------------------------------------- /ftdetect/sail.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.sail set filetype=sail 2 | -------------------------------------------------------------------------------- /ftdetect/sc.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.sc set filetype=scala 2 | -------------------------------------------------------------------------------- /ftdetect/tablegen.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.td set filetype=tablegen 2 | -------------------------------------------------------------------------------- /indent/llvm.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: llvm 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | " What this indent plugin currently does: 5 | " - If no other rule matches copy indent from previous non-empty, 6 | " non-commented line 7 | " - On '}' align the same as the line containing the matching '{' 8 | " - If previous line ends with ':' increase indentation 9 | " - If the current line ends with ':' indent at the same level as the 10 | " enclosing '{'/'}' block 11 | " Stuff that would be nice to add: 12 | " - Continue comments on next line 13 | " - If there is an opening+unclosed parenthesis on previous line indent to that 14 | if exists("b:did_indent") 15 | finish 16 | endif 17 | let b:did_indent = 1 18 | 19 | setlocal shiftwidth=2 expandtab 20 | 21 | setlocal indentkeys=0{,0},<:>,!^F,o,O,e 22 | setlocal indentexpr=GetLLVMIndent() 23 | 24 | if exists("*GetLLVMIndent") 25 | finish 26 | endif 27 | 28 | function! FindOpenBrace(lnum) 29 | call cursor(a:lnum, 1) 30 | return searchpair('{', '', '}', 'bW') 31 | endfun 32 | 33 | function! GetLLVMIndent() 34 | " On '}' align the same as the line containing the matching '{' 35 | let thisline = getline(v:lnum) 36 | if thisline =~ '^\s*}' 37 | call cursor(v:lnum, 1) 38 | silent normal % 39 | let opening_lnum = line('.') 40 | if opening_lnum != v:lnum 41 | return indent(opening_lnum) 42 | endif 43 | endif 44 | 45 | " Indent labels the same as the current opening block 46 | if thisline =~ ':\s*$' 47 | let blockbegin = FindOpenBrace(v:lnum) 48 | if blockbegin > 0 49 | return indent(blockbegin) 50 | endif 51 | endif 52 | 53 | " Find a non-blank not-completely commented line above the current line. 54 | let prev_lnum = prevnonblank(v:lnum - 1) 55 | while prev_lnum > 0 && synIDattr(synID(prev_lnum, indent(prev_lnum)+1, 0), "name") =? "string\|comment" 56 | let prev_lnum = prevnonblank(prev_lnum-1) 57 | endwhile 58 | " Hit the start of the file, use zero indent. 59 | if prev_lnum == 0 60 | return 0 61 | endif 62 | 63 | let ind = indent(prev_lnum) 64 | let prevline = getline(prev_lnum) 65 | 66 | " Add a 'shiftwidth' after lines that start a block or labels 67 | if prevline =~ '{\s*$' || prevline =~ ':\s*$' 68 | let ind = ind + &shiftwidth 69 | endif 70 | 71 | return ind 72 | endfunction 73 | -------------------------------------------------------------------------------- /indent/mlir.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: mlir 3 | " Maintainer: The MLIR team 4 | " Adapted from the LLVM vim indent file 5 | " What this indent plugin currently does: 6 | " - If no other rule matches copy indent from previous non-empty, 7 | " non-commented line. 8 | " - On '}' align the same as the line containing the matching '{'. 9 | " - If previous line starts with a block label, increase indentation. 10 | " - If the current line is a block label and ends with ':' indent at the same 11 | " level as the enclosing '{'/'}' block. 12 | " Stuff that would be nice to add: 13 | " - Continue comments on next line. 14 | " - If there is an opening+unclosed parenthesis on previous line indent to 15 | " that. 16 | if exists("b:did_indent") 17 | finish 18 | endif 19 | let b:did_indent = 1 20 | 21 | setlocal shiftwidth=2 expandtab 22 | 23 | setlocal indentkeys=0{,0},<:>,!^F,o,O,e 24 | setlocal indentexpr=GetMLIRIndent() 25 | 26 | if exists("*GetMLIRIndent") 27 | finish 28 | endif 29 | 30 | function! FindOpenBrace(lnum) 31 | call cursor(a:lnum, 1) 32 | return searchpair('{', '', '}', 'bW') 33 | endfun 34 | 35 | function! GetMLIRIndent() 36 | " On '}' align the same as the line containing the matching '{' 37 | let thisline = getline(v:lnum) 38 | if thisline =~ '^\s*}' 39 | call cursor(v:lnum, 1) 40 | silent normal % 41 | let opening_lnum = line('.') 42 | if opening_lnum != v:lnum 43 | return indent(opening_lnum) 44 | endif 45 | endif 46 | 47 | " Indent labels the same as the current opening block 48 | if thisline =~ '\^\h\+.*:\s*$' 49 | let blockbegin = FindOpenBrace(v:lnum) 50 | if blockbegin > 0 51 | return indent(blockbegin) 52 | endif 53 | endif 54 | 55 | " Find a non-blank not-completely commented line above the current line. 56 | let prev_lnum = prevnonblank(v:lnum - 1) 57 | while prev_lnum > 0 && synIDattr(synID(prev_lnum, 1 + indent(prev_lnum), 0), "name") == "mlirComment" 58 | let prev_lnum = prevnonblank(prev_lnum-1) 59 | endwhile 60 | " Hit the start of the file, use zero indent. 61 | if prev_lnum == 0 62 | return 0 63 | endif 64 | 65 | let ind = indent(prev_lnum) 66 | let prevline = getline(prev_lnum) 67 | 68 | " Add a 'shiftwidth' after lines that start a function, block/labels, or a 69 | " region. 70 | if prevline =~ '{\s*$' || prevline =~ '\^\h\+.*:\s*$' 71 | let ind = ind + &shiftwidth 72 | endif 73 | 74 | return ind 75 | endfunction 76 | -------------------------------------------------------------------------------- /indent/nix.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Language: Nix 3 | " Maintainer: Daiderd Jordan 4 | " URL: https://github.com/LnL7/vim-nix 5 | 6 | if exists("b:did_indent") 7 | finish 8 | endif 9 | let b:did_indent = 1 10 | 11 | setlocal indentexpr=GetNixIndent() 12 | setlocal indentkeys+=0=then,0=else,0=inherit,0=in,* 13 | 14 | if exists("*GetNixIndent") 15 | finish 16 | endif 17 | 18 | let s:cpo_save = &cpo 19 | set cpo&vim 20 | 21 | let s:skip_syntax = '\%(Comment\|String\)$' 22 | let s:binding_open = '\%(\\)' 23 | let s:binding_close = '\%(\\)' 24 | let s:block_open = '\%({\|[\)' 25 | let s:block_close = '\%(}\|]\)' 26 | 27 | function! GetNixIndent() 28 | let lnum = prevnonblank(v:lnum - 1) 29 | let ind = indent(lnum) 30 | 31 | " At the start of the file use zero indent. 32 | if lnum == 0 33 | return 0 34 | endif 35 | 36 | " Skip indentation for single line comments explicitly, in case a 37 | " comment was just inserted (eg. visual block mode) 38 | if getline(v:lnum) =~ '^\s*#' 39 | return indent(v:lnum) 40 | endif 41 | 42 | if synIDattr(synID(v:lnum, 1, 1), "name") !~ s:skip_syntax 43 | let current_line = getline(v:lnum) 44 | let last_line = getline(lnum) 45 | 46 | if current_line =~ '^\s*in\>' 47 | let save_cursor = getcurpos() 48 | normal ^ 49 | let bslnum = searchpair(s:binding_open, '', s:binding_close, 'bnW', 50 | \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "StringSpecial$"') 51 | call setpos('.', save_cursor) 52 | return indent(bslnum) 53 | endif 54 | 55 | if last_line =~ s:block_open . '\s*$' 56 | let ind += &sw 57 | endif 58 | 59 | if current_line =~ '^\s*' . s:block_close 60 | let ind -= &sw 61 | endif 62 | 63 | if last_line =~ '[(=]$' 64 | let ind += &sw 65 | endif 66 | 67 | if last_line =~ '\' 76 | let ind -= &sw 77 | endif 78 | endif 79 | 80 | if synIDattr(synID(v:lnum, 1, 1), "name") =~ '^nixString' 81 | let current_line = getline(v:lnum) 82 | 83 | let ind = indent(v:lnum) 84 | let bslnum = searchpair('''''', '', '''''', 'bnW', 85 | \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "StringSpecial$"') 86 | 87 | if ind <= indent(bslnum) 88 | let ind = indent(bslnum) + &sw 89 | endif 90 | 91 | if current_line =~ '^\s*''''[^''\$]' 92 | let ind = indent(bslnum) 93 | endif 94 | if current_line =~ '^\s*''''$' 95 | let ind = indent(bslnum) 96 | endif 97 | endif 98 | 99 | return ind 100 | endfunction 101 | 102 | let &cpo = s:cpo_save 103 | unlet s:cpo_save 104 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | -- Reject loading plugins when bigfile detect. Default on 1.5M size. 2 | require("libs.bigfile").setup() 3 | 4 | require("core") 5 | require("pack").setup() 6 | require("key-mapping") 7 | 8 | vim.o.background = "dark" 9 | vim.cmd.colorscheme("kanagawa") 10 | -------------------------------------------------------------------------------- /lazy-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, 3 | "buffer_manager.nvim": { "branch": "main", "commit": "d82035f35c3a24aa5b7d13c511890bdcc8c33976" }, 4 | "ccc.nvim": { "branch": "main", "commit": "9d1a256e006decc574789dfc7d628ca11644d4c2" }, 5 | "cmp-cmdline": { "branch": "main", "commit": "d126061b624e0af6c3a556428712dd4d4194ec6d" }, 6 | "cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" }, 7 | "cmp-nvim-lsp-signature-help": { "branch": "main", "commit": "031e6ba70b0ad5eee49fd2120ff7a2e325b17fa7" }, 8 | "cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" }, 9 | "conform.nvim": { "branch": "master", "commit": "6feb2f28f9a9385e401857b21eeac3c1b66dd628" }, 10 | "cybu.nvim": { "branch": "main", "commit": "576712593eb92f8c1d6d4bea9e003be485a64382" }, 11 | "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, 12 | "dropbar.nvim": { "branch": "master", "commit": "f7ecb0c3600ca1dc467c361e9af40f97289d7aad" }, 13 | "fidget.nvim": { "branch": "main", "commit": "d9ba6b7bfe29b3119a610892af67602641da778e" }, 14 | "galaxyline.nvim": { "branch": "global-status-line", "commit": "c4801de4bad71e0a38cab8e5e703524c97496812" }, 15 | "gitsigns.nvim": { "branch": "main", "commit": "8bdaccdb897945a3c99c1ad8df94db0ddf5c8790" }, 16 | "indent-blankline.nvim": { "branch": "master", "commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba" }, 17 | "kanagawa.nvim": { "branch": "master", "commit": "debe91547d7fb1eef34ce26a5106f277fbfdd109" }, 18 | "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, 19 | "leap.nvim": { "branch": "main", "commit": "212429314c5bfa41f4154bfa8805f7227ba6a880" }, 20 | "neoscroll.nvim": { "branch": "master", "commit": "f957373912e88579e26fdaea4735450ff2ef5c9c" }, 21 | "nui.nvim": { "branch": "main", "commit": "7cd18e73cfbd70e1546931b7268b3eebaeff9391" }, 22 | "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, 23 | "nvim-lspconfig": { "branch": "master", "commit": "b8e7957bde4cbb3cb25a13a62548f7c273b026e9" }, 24 | "nvim-metals": { "branch": "main", "commit": "d1639b7fccd845875e33444c7860ad292ab8670d" }, 25 | "nvim-scrollbar": { "branch": "main", "commit": "5b103ef0fd2e8b9b4be3878ed38d224522192c6c" }, 26 | "nvim-surround": { "branch": "main", "commit": "8dd9150ca7eae5683660ea20cec86edcd5ca4046" }, 27 | "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, 28 | "nvim-treesitter-textobjects": { "branch": "master", "commit": "0f051e9813a36481f48ca1f833897210dbcfffde" }, 29 | "nvim-ts-autotag": { "branch": "main", "commit": "a1d526af391f6aebb25a8795cbc05351ed3620b5" }, 30 | "nvim-web-devicons": { "branch": "master", "commit": "1fb58cca9aebbc4fd32b086cb413548ce132c127" }, 31 | "oil.nvim": { "branch": "master", "commit": "685cdb4ffa74473d75a1b97451f8654ceeab0f4a" }, 32 | "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, 33 | "quicker.nvim": { "branch": "master", "commit": "51d3926f183c2d98fbc237cc237ae0926839af3a" }, 34 | "sort.nvim": { "branch": "main", "commit": "c789da6968337d2a61104a929880b5f144e02855" }, 35 | "statuscol.nvim": { "branch": "main", "commit": "a2580e009a3b4c51b5978768d907dafae2c919ac" }, 36 | "telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" }, 37 | "vim-easy-align": { "branch": "master", "commit": "9815a55dbcd817784458df7a18acacc6f82b1241" }, 38 | "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, 39 | "vim-table-mode": { "branch": "master", "commit": "e4365bde024f73e205eefa2fb78e3029ddb92ea9" } 40 | } 41 | -------------------------------------------------------------------------------- /lua/README.md: -------------------------------------------------------------------------------- 1 | ## Components 2 | 3 | - **core**: neovim basic options/key mappings/auto commands 4 | - **completion**: nvim-cmp related configuration 5 | - `init.lua`: package registry 6 | - `rc.lua`: nvim-cmp configuration 7 | - **git**: git related plugins 8 | - `init.lua`: package registry 9 | - `gitsigns.lua`: gitsigns configuration 10 | - **lib**: functions that I don't want to write twice 11 | - **lsp**: LSP protocol related plugins 12 | - `init.lua`: package registry 13 | - `config.lua`: basic settings for lspconfig 14 | - `keymaps.lua`: coding key mappings 15 | - `lspsaga.lua`: configuration for lspsaga 16 | - **note**: Note taking related plugins 17 | - **tools**: Plugins that enhance editing experience 18 | - `init.lua`: package registry 19 | - `nvim_tree.lua`: configuration for nvim tree 20 | - `telescope.lua`: configuration for telescope 21 | - **treesitter**: Treesitter related plugins 22 | - `init.lua`: plugin registry 23 | - `config.lua`: treesitter configuration 24 | - **ui**: UI related plugins 25 | - `init.lua`: plugin registry 26 | - `bufferline.lua`: bufferline configuration 27 | - `indent.lua`: indent guideline configuration 28 | - `kanagawa.lua`: kanagawa colorscheme configuration 29 | - `statusline.lua`: galaxyline configuration 30 | - **pack.lua**: Lazy.nvim configuration 31 | -------------------------------------------------------------------------------- /lua/builder/key-mapper.lua: -------------------------------------------------------------------------------- 1 | -- This file act as an API compatible layer. 2 | -- Here we are using which-key.nvim as plugin, but when one day which-key.nvim 3 | -- is no more under maintain, we can still keep compatibiltity and replace implementation here. 4 | 5 | local export = {} 6 | 7 | local function unwrap_options(original) 8 | local default = { 9 | noremap = true, 10 | silent = true, 11 | desc = "Undocumented", 12 | } 13 | 14 | return vim.tbl_deep_extend("force", default, original) 15 | end 16 | 17 | local function unwrap_keymaps(mappings) 18 | local copy = vim.tbl_deep_extend("force", {}, mappings) 19 | copy[1] = nil 20 | copy[2] = nil 21 | 22 | return mappings[1], mappings[2], unwrap_options(copy) 23 | end 24 | 25 | local function check(mappings) 26 | local warn = function(msg) 27 | vim.notify(msg, vim.log.levels.WARN) 28 | end 29 | if not mappings or #mappings == 0 then 30 | local is_buffer_map = mappings.buffer ~= nil and "true" or "false" 31 | warn("Null mappings given, please check config: is_buffer_map=" .. is_buffer_map) 32 | return false 33 | end 34 | if #mappings < 2 then 35 | warn("Only one key mapping is given: " .. mappings[1]) 36 | return false 37 | end 38 | if #mappings > 2 then 39 | local msg = string.format( 40 | "More than two pair was given, where first item is %s, second item is %s", 41 | mappings[1], 42 | mappings[2] 43 | ) 44 | warn(msg) 45 | return false 46 | end 47 | if type(mappings[1]) ~= "string" then 48 | warn("Mapping pairs must be in string, but lhs is not, it is a " .. type(mappings[1])) 49 | return false 50 | end 51 | if type(mappings[2]) ~= "string" and type(mappings[2]) ~= "function" then 52 | warn( 53 | "Mapping pairs must be in string or function, but rhs is not, it is a " .. type(mappings[2]) 54 | ) 55 | return false 56 | end 57 | 58 | return true 59 | end 60 | 61 | -- Batch set keymappings 62 | -- Allow form: 63 | -- 1. { "lhs", "rhs", option = "foo" } 64 | -- 2. { { "lhs", "rhs", opt = "foo" }, { "lhs", "rhs", opt = "bar" } } 65 | function export.map(modes, mappings) 66 | if type(modes) == "string" then 67 | modes = { modes } 68 | end 69 | 70 | if type(modes) ~= "table" then 71 | vim.notify("Invalid mode set when mapping keys", vim.log.levels.ERROR) 72 | return false 73 | end 74 | 75 | for _, mode in ipairs(modes) do 76 | if type(mappings[1]) == "string" then 77 | if not check(mappings) then 78 | return false 79 | end 80 | 81 | vim.keymap.set(mode, unwrap_keymaps(mappings)) 82 | goto continue 83 | end 84 | 85 | for _, kpair in ipairs(mappings) do 86 | if not check(kpair) then 87 | return false 88 | end 89 | vim.keymap.set(mode, unwrap_keymaps(kpair)) 90 | end 91 | 92 | ::continue:: 93 | end 94 | end 95 | 96 | function export.cmd(cmd) 97 | return "" .. cmd .. "" 98 | end 99 | 100 | function export.bufmap(bufid, modes, mappings) 101 | if type(mappings[1]) == "string" then 102 | mappings["buffer"] = bufid 103 | return export.map(modes, mappings) 104 | end 105 | 106 | for _, kpair in ipairs(mappings) do 107 | kpair["buffer"] = bufid 108 | end 109 | return export.map(modes, mappings) 110 | end 111 | 112 | function export.mk_keymap(keymap_set) 113 | export.map("n", keymap_set.normal) 114 | export.map("x", keymap_set.selection) 115 | export.map("i", keymap_set.insertion) 116 | export.map("t", keymap_set.terminal) 117 | end 118 | 119 | return export 120 | -------------------------------------------------------------------------------- /lua/completion/init.lua: -------------------------------------------------------------------------------- 1 | local register = require("pack").register 2 | 3 | register("hrsh7th/nvim-cmp", { 4 | event = "InsertEnter", 5 | keys = { ":", "/" }, 6 | dependencies = { 7 | -- from lsp 8 | "hrsh7th/cmp-nvim-lsp", 9 | -- for function parameters 10 | "hrsh7th/cmp-nvim-lsp-signature-help", 11 | -- for OS path 12 | "hrsh7th/cmp-path", 13 | -- for vim command line 14 | "hrsh7th/cmp-cmdline", 15 | }, 16 | 17 | config = function() 18 | require("completion.rc") 19 | end, 20 | }) 21 | -------------------------------------------------------------------------------- /lua/completion/rc.lua: -------------------------------------------------------------------------------- 1 | local cmp = require("cmp") 2 | 3 | local keymap = { 4 | scroll_up = "", 5 | scroll_down = "", 6 | abort = "", 7 | confirm = "", 8 | select_next = "", 9 | select_prev = "", 10 | } 11 | 12 | local icons = { 13 | Text = "", 14 | Method = "󰆧", 15 | Function = "󰊕", 16 | Constructor = "", 17 | Field = "", 18 | Variable = "", 19 | Class = "", 20 | Interface = "", 21 | Module = "", 22 | Property = "", 23 | Unit = "", 24 | Value = "", 25 | Enum = "", 26 | Keyword = "", 27 | Snippet = "", 28 | Color = "", 29 | File = "", 30 | Reference = "", 31 | Folder = "", 32 | EnumMember = "", 33 | Constant = "", 34 | Struct = "", 35 | Event = "", 36 | Operator = "", 37 | TypeParameter = "", 38 | Vim = "", 39 | } 40 | 41 | local has_words_before = function() 42 | local line, col = unpack(vim.api.nvim_win_get_cursor(0)) 43 | return col ~= 0 44 | and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil 45 | end 46 | 47 | local feedkey = function(key, mode) 48 | vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true) 49 | end 50 | 51 | cmp.setup({ 52 | view = { 53 | entries = { name = "custom", selection_order = "near_cursor" }, 54 | }, 55 | window = { 56 | documentation = { 57 | winhighlight = "Normal:CmpDocumentation,FloatBorder:CmpDocumentation,Search:None", 58 | side_padding = 1, 59 | }, 60 | }, 61 | formatting = { 62 | fields = { "kind", "abbr", "menu" }, 63 | format = function(entry, item) 64 | -- return special icon for cmdline completion 65 | if entry.source.name == "cmdline" then 66 | item.kind = icons["Vim"] 67 | item.menu = "Vim" 68 | return item 69 | elseif entry.source.name == "nvim_lsp_signature_help" then 70 | item.kind = "Property" 71 | end 72 | item.menu = item.kind 73 | item.kind = icons[item.kind] 74 | return item 75 | end, 76 | }, 77 | mapping = { 78 | [keymap.scroll_up] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 79 | "i", 80 | "c", 81 | }), 82 | [keymap.scroll_down] = cmp.mapping(cmp.mapping.scroll_docs(4), { 83 | "i", 84 | "c", 85 | }), 86 | [keymap.abort] = cmp.mapping({ 87 | i = cmp.mapping.abort(), 88 | c = cmp.mapping.close(), 89 | }), 90 | [keymap.confirm] = cmp.mapping.confirm({ 91 | behavior = cmp.ConfirmBehavior.Replace, 92 | select = false, 93 | }), 94 | [keymap.select_next] = cmp.mapping(function(fallback) 95 | if cmp.visible() then 96 | cmp.select_next_item() 97 | elseif has_words_before() then 98 | cmp.complete() 99 | else 100 | fallback() 101 | end 102 | end, { "i", "s" }), 103 | [keymap.select_prev] = cmp.mapping(function() 104 | if cmp.visible() then 105 | cmp.select_prev_item() 106 | end 107 | end, { "i", "s" }), 108 | }, 109 | sources = { 110 | { name = "nvim_lsp", priority = 99 }, 111 | { name = "nvim_lsp_signature_help" }, 112 | { name = "path" }, 113 | }, 114 | experimental = { 115 | ghost_text = true, 116 | }, 117 | preselect = cmp.PreselectMode.None, 118 | }) 119 | 120 | -- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore). 121 | cmp.setup.cmdline("/", { 122 | mapping = cmp.mapping.preset.cmdline(), 123 | sources = cmp.config.sources({ 124 | { name = "nvim_lsp_document_symbol" }, 125 | }, { 126 | { name = "buffer" }, 127 | }), 128 | }) 129 | 130 | cmp.setup.cmdline(":", { 131 | mapping = cmp.mapping.preset.cmdline(), 132 | sources = cmp.config.sources({ 133 | { name = "path" }, 134 | }, { 135 | { name = "cmdline" }, 136 | }), 137 | }) 138 | -------------------------------------------------------------------------------- /lua/core/autocmd.lua: -------------------------------------------------------------------------------- 1 | local au = vim.api.nvim_create_autocmd 2 | 3 | -- Copy data to system clipboard only when we are pressing 'y'. 'd', 'x' will be filtered out. 4 | -- 5 | -- Credit: https://github.com/ibhagwan/smartyank.nvim 6 | local smart_yank_gid = vim.api.nvim_create_augroup("SmartYank", { clear = true }) 7 | au("TextYankPost", { 8 | group = smart_yank_gid, 9 | desc = "Copy and highlight yanked text to system clipboard", 10 | callback = function() 11 | vim.hl.on_yank({ higroup = "HighLightLineMatches", timeout = 200 }) 12 | 13 | if not vim.fn.has("clipboard") == 1 then 14 | return 15 | end 16 | 17 | local copy_key_is_y = vim.v.operator == "y" 18 | if not copy_key_is_y then 19 | return 20 | end 21 | 22 | local copy = function(str) 23 | local ok, error = pcall(vim.fn.setreg, "+", str) 24 | if not ok then 25 | vim.notify("fail to copy to clipboard: " .. error, vim.log.levels.ERROR) 26 | return 27 | end 28 | end 29 | 30 | local present, yank_data = pcall(vim.fn.getreg, "0") 31 | if not present then 32 | vim.notify("fail to get content from reg 0: " .. yank_data, vim.log.levels.ERROR) 33 | return 34 | end 35 | if #yank_data < 1 then 36 | return 37 | end 38 | 39 | copy(yank_data) 40 | end, 41 | }) 42 | 43 | -- 44 | -- Automatically set PWD to buffer 45 | -- 46 | au({ "VimEnter" }, { 47 | pattern = { "*" }, 48 | callback = function() 49 | local finder = require("libs.find_root") 50 | 51 | local old_cwd = vim.loop.cwd() 52 | finder.set_root({ patterns = { "Cargo.toml", ".git", "flake.nix" } }) 53 | local new_cwd = vim.loop.cwd() 54 | 55 | if not vim.b.current_buf_root_dir and new_cwd ~= old_cwd then 56 | vim.notify("Dir changed to: " .. new_cwd) 57 | end 58 | end, 59 | }) 60 | 61 | au({ "BufWinEnter" }, { 62 | desc = "return cursor to where it was last time closing the file", 63 | group = vim.api.nvim_create_augroup("AutoJump", { clear = true }), 64 | callback = function() 65 | if not vim.tbl_contains({ "", "acwrite" }, vim.bo.buftype) then 66 | return 67 | end 68 | if vim.tbl_contains({ "gitcommit" }, vim.bo.filetype) then 69 | return 70 | end 71 | 72 | vim.cmd('silent! normal! g`"zv') 73 | end, 74 | }) 75 | 76 | -- only highlight when searching 77 | au("CmdlineEnter", { 78 | callback = function() 79 | local cmd = vim.v.event.cmdtype 80 | if cmd == "/" or cmd == "?" then 81 | vim.opt.hlsearch = true 82 | end 83 | end, 84 | }) 85 | au("CmdlineLeave", { 86 | callback = function() 87 | local cmd = vim.v.event.cmdtype 88 | if cmd == "/" or cmd == "?" then 89 | vim.opt.hlsearch = false 90 | end 91 | end, 92 | }) 93 | -------------------------------------------------------------------------------- /lua/core/init.lua: -------------------------------------------------------------------------------- 1 | require("core.options") 2 | require("core.autocmd") 3 | -------------------------------------------------------------------------------- /lua/core/options.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- vim option configuration 3 | -- 4 | 5 | vim.g.mapleader = ";" 6 | 7 | local options = { 8 | completeopt = { "menuone", "noselect", "menu" }, 9 | -- Enables 24-bit RGB color in the TUI 10 | termguicolors = true, 11 | encoding = "utf-8", 12 | -- When file encoding forcely set to UTF-8, some file with non-Unicode 13 | -- encoding will lose information during the encoding conversion. 14 | -- If you have problem with this encoding, set value to empty string "". 15 | fileencoding = "utf-8", 16 | -- enable number 17 | number = true, 18 | -- enable relative number 19 | rnu = true, 20 | -- enable highlightfor current line 21 | cursorline = true, 22 | -- TAB SETTING 23 | -- Use 2 spaces forcely. But don't worry, vim-sleuth will handle the indent 24 | -- gracefully. See for more. 25 | -- 26 | -- Use the appropriate number of spaces to insert a . 27 | expandtab = true, 28 | -- Number of spaces that a in the file counts for. 29 | tabstop = 4, 30 | shiftwidth = 2, 31 | softtabstop = 2, 32 | -- A List is an ordered sequence of items. 33 | list = true, 34 | listchars = { tab = " ", trail = "·" }, 35 | fillchars = { 36 | fold = " ", 37 | foldopen = "", 38 | foldclose = "", 39 | foldsep = " ", 40 | diff = "╱", 41 | eob = " ", 42 | }, 43 | -- Minimal number of screen lines to keep above and below the cursor. 44 | scrolloff = 5, 45 | -- 200 is more appropriate for which-keys. You can quickly input keys without prompting up 46 | -- the which-keys panel, or wait 200ms if you forget keymappings. 47 | timeoutlen = 300, 48 | -- Time in milliseconds to wait for a key code sequence to complete 49 | ttimeoutlen = 200, 50 | -- use timeout for showing which-keys 51 | timeout = true, 52 | -- remember where to recover cursor 53 | viewoptions = { "cursor", "folds", "slash", "unix" }, 54 | -- lines longer than the width of the window will wrap and displaying continues 55 | -- on the next line. 56 | wrap = true, 57 | -- set text width to zero to use the wrap functionality 58 | tw = 0, 59 | cindent = true, 60 | -- set windows split at bottom-right by default 61 | splitright = true, 62 | splitbelow = true, 63 | -- don't show the "--VISUAL--" "--INSERT--" text 64 | showmode = false, 65 | -- show chars, selected block in visual mode 66 | showcmd = false, 67 | -- auto completion on command 68 | wildmenu = true, 69 | -- ignore case when searching and only on searching 70 | ignorecase = true, 71 | smartcase = true, 72 | inccommand = "split", 73 | ttyfast = true, 74 | visualbell = true, 75 | -- affect swap file write and cursorhold. Set it to 5secs to reduce performance impact 76 | updatetime = 5000, 77 | virtualedit = "block", 78 | -- enable all the mouse functionality 79 | mouse = "a", 80 | -- use indent as the fold method 81 | foldcolumn = "1", 82 | foldmethod = "indent", 83 | foldlevel = 99, 84 | foldenable = true, 85 | formatoptions = "qj", 86 | hidden = true, 87 | -- options to truncate hit-enter prompts causesd by file message 88 | -- 1. "a": Use all abbreviations, such as truncate "Modified" to "[+]" 89 | -- 2. "T": Truncate file message in the middle if it is too long 90 | -- 3. "W": Do not show "written" or "[w]" when writing a file 91 | -- 4. "F": Do not show file info when editing a file 92 | shortmess = "aTWF", 93 | -- let status bar (at bottom) be global status bar, don't change with winbar 94 | laststatus = 3, 95 | } 96 | 97 | local function ensure_cache(suffix) 98 | local dir = vim.fn.stdpath("cache") .. "/" .. suffix 99 | -- TODO: Use vim.loop.fs_stat 100 | local resp = vim.fn.mkdir(dir, "p") 101 | if resp == 1 then 102 | return dir 103 | end 104 | 105 | return nil 106 | end 107 | 108 | local backup_dir = ensure_cache("backup") 109 | if backup_dir then 110 | options.backupdir = backup_dir 111 | options.directory = backup_dir 112 | end 113 | 114 | local undo_dir = ensure_cache("undo") 115 | local has_persist = vim.fn.has("persistent_undo") 116 | if has_persist == 1 then 117 | options.undofile = true 118 | options.undodir = undo_dir 119 | end 120 | 121 | for k, v in pairs(options) do 122 | vim.opt[k] = v 123 | end 124 | -- END of vim options configuration 125 | 126 | -- 127 | -- built-in configuration 128 | -- 129 | 130 | -- built-in plugins that really useless 131 | for _, plugin in ipairs({ 132 | "gzip", 133 | "zip", 134 | "zipPlugin", 135 | "tar", 136 | "tarPlugin", 137 | "getscript", 138 | "getscriptPlugin", 139 | "vimball", 140 | "vimballPlugin", 141 | "2html_plugin", 142 | "matchit", 143 | "matchparen", 144 | "logiPat", 145 | "rust_vim", 146 | "rust_vim_plugin_cargo", 147 | "rrhelper", 148 | "netrw", 149 | "netrwPlugin", 150 | "netrwSettings", 151 | "netrwFileHandlers", 152 | }) do 153 | local var = "loaded_" .. plugin 154 | vim.g[var] = 1 155 | end 156 | 157 | -- built-in neovim RPC provider that I never used 158 | for _, provider in ipairs({ 159 | "perl", 160 | "node", 161 | "ruby", 162 | "python", 163 | "python3", 164 | }) do 165 | local var = "loaded_" .. provider .. "_provider" 166 | vim.g[var] = 0 167 | end 168 | -- END of built-in configuration 169 | 170 | -- If anything went wrong, rm -r ~/.cache/nvim/luac 171 | vim.loader.enable() 172 | -------------------------------------------------------------------------------- /lua/git/gitsigns.lua: -------------------------------------------------------------------------------- 1 | require("gitsigns").setup({ 2 | signs = { 3 | add = { 4 | text = "▐", 5 | }, 6 | change = { 7 | text = "▐", 8 | }, 9 | untracked = { 10 | text = "▐", 11 | }, 12 | delete = { 13 | text = "▐", 14 | }, 15 | topdelete = { 16 | text = "󱨉", 17 | }, 18 | changedelete = { 19 | text = "▐", 20 | }, 21 | }, 22 | on_attach = function(bufnr) 23 | local gs = package.loaded.gitsigns 24 | 25 | require("builder.key-mapper").bufmap(bufnr, "n", { 26 | { "gS", gs.stage_buffer, desc = "Stage buffer" }, 27 | { "gu", gs.undo_stage_hunk, desc = "Undo stage hunk" }, 28 | { "gR", gs.reset_buffer, desc = "Reset buffer" }, 29 | { "gp", gs.preview_hunk, desc = "Preview hunk" }, 30 | { "gq", gs.setqflist, desc = "Set qflist for hunk in current buffer" }, 31 | { 32 | "gQ", 33 | function() 34 | gs.setqflist("all") 35 | end, 36 | desc = "Set qflist for all hunk", 37 | }, 38 | { 39 | "gB", 40 | function() 41 | gs.blame_line({ full = true }) 42 | end, 43 | desc = "Open git blame panel", 44 | }, 45 | { "gb", gs.toggle_current_line_blame, desc = "Enter line blame mode" }, 46 | { "gD", gs.diffthis, desc = "Open diff" }, 47 | { "gd", gs.toggle_deleted, desc = "Toggle deleted line" }, 48 | { 49 | "]g", 50 | function() 51 | if vim.wo.diff then 52 | return "]g" 53 | end 54 | vim.schedule(function() 55 | gs.next_hunk() 56 | end) 57 | return "" 58 | end, 59 | expr = true, 60 | desc = "Go to next hunk", 61 | }, 62 | { 63 | "[g", 64 | function() 65 | if vim.wo.diff then 66 | return "[g" 67 | end 68 | vim.schedule(function() 69 | gs.prev_hunk() 70 | end) 71 | return "" 72 | end, 73 | expr = true, 74 | desc = "Go to previous hunk", 75 | }, 76 | }) 77 | 78 | -- Actions 79 | require("builder.key-mapper").bufmap(bufnr, { "n", "v" }, { 80 | { "gs", ":Gitsigns stage_hunk", desc = "Stage hunk" }, 81 | { "gr", ":Gitsigns reset_hunk", desc = "Reset hunk" }, 82 | }) 83 | 84 | -- Text object 85 | require("builder.key-mapper").bufmap( 86 | bufnr, 87 | { "o", "x" }, 88 | { "ih", ":Gitsigns select_hunk", desc = "Select hunk" } 89 | ) 90 | end, 91 | numhl = false, 92 | linehl = false, 93 | watch_gitdir = { interval = 1000, follow_files = true }, 94 | current_line_blame = false, 95 | current_line_blame_opts = { 96 | virt_text = true, 97 | virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align' 98 | delay = 1000, 99 | }, 100 | sign_priority = 2000, 101 | update_debounce = 100, 102 | status_formatter = nil, -- Use default 103 | word_diff = false, 104 | diff_opts = { internal = true }, 105 | }) 106 | -------------------------------------------------------------------------------- /lua/git/init.lua: -------------------------------------------------------------------------------- 1 | local pack = require("pack").register 2 | 3 | pack("lewis6991/gitsigns.nvim", { 4 | config = function() 5 | require("git.gitsigns") 6 | end, 7 | }) 8 | -------------------------------------------------------------------------------- /lua/key-mapping.lua: -------------------------------------------------------------------------------- 1 | -- Here we have built-in re-mapping only, plugins key-mappings goes into different plugin settings. 2 | 3 | local keymapper = require("builder.key-mapper") 4 | 5 | keymapper.mk_keymap({ 6 | normal = { 7 | { "j", "v:count == 0 ? 'gj' : 'j'", desc = "Go display lines downward", expr = true }, 8 | { "k", "v:count == 0 ? 'gk' : 'k'", desc = "Go display lines upward", expr = true }, 9 | { "L", "g_", desc = "Jump to beginning" }, 10 | { "H", "^", desc = "Jump to end" }, 11 | { 12 | "w", 13 | function() 14 | vim.cmd.write({ bang = true }) 15 | end, 16 | desc = "Save buffer", 17 | }, 18 | { "", vim.cmd.noh, desc = "Close search highlight" }, 19 | { 20 | "q", 21 | function() 22 | require("libs.bufdel").delete_buffer_expr("", false) 23 | end, 24 | desc = "Close current buffer", 25 | }, 26 | { "x", vim.cmd.x, desc = "Save and quit" }, 27 | { "", [["+p]], desc = "paste" }, 28 | { "", [["+p]], desc = "paste" }, 29 | }, 30 | selection = { 31 | { "J", ":m '>+1gv=gv" }, 32 | { "K", ":m '<-2gv=gv" }, 33 | { "L", "g_", desc = "Select to beginning" }, 34 | { "H", "^", desc = "Select to end" }, 35 | { "", "", desc = "anti-touch" }, 36 | { "", ">gv", desc = "Increase indent" }, 37 | { "", "", "^i", desc = "Jump to beginning of the line" }, 41 | { "", [["+pi]], desc = "paste" }, 42 | { "", "", desc = "Jump to end of the line" }, 43 | { "", "", desc = "Exit insert mode" }, 44 | { "", "", desc = "Go up one line" }, 45 | { "", "", desc = "Go up one line" }, 46 | { "", "", desc = "Go up one line" }, 47 | { "", "", desc = "Go down one line" }, 48 | { "", "", desc = "anti-touch" }, 49 | }, 50 | terminal = { 51 | { "", "" }, 52 | }, 53 | }) 54 | -------------------------------------------------------------------------------- /lua/lang/configs.lua: -------------------------------------------------------------------------------- 1 | local config = { 2 | -- Told LSP server about the nvim lsp capabilities 3 | capabilities = require("cmp_nvim_lsp").default_capabilities(), 4 | -- Setup keymap on attach 5 | on_attach = require("lang.on_attach").setup_all, 6 | --settings = {}, 7 | } 8 | 9 | local lspconfig = require("lspconfig") 10 | local setup = function(server, settings) 11 | if settings then 12 | config = vim.tbl_deep_extend("force", config, settings) 13 | end 14 | 15 | lspconfig[server].setup(config) 16 | end 17 | 18 | -- C/CPP 19 | setup("ccls", { 20 | root_dir = require("lspconfig").util.root_pattern( 21 | "build", 22 | "compile_commands.json", 23 | ".ccls", 24 | ".git" 25 | ), 26 | init_options = { 27 | compilationDatabaseDirectory = "build", 28 | index = { 29 | threads = 0, 30 | }, 31 | clang = { 32 | excludeArgs = { "-frounding-math" }, 33 | }, 34 | }, 35 | }) 36 | 37 | -- Haskell 38 | setup("hls", { 39 | settings = { 40 | haskell = { 41 | formattingProvider = "fourmolu", 42 | plugin = { 43 | rename = { 44 | config = { 45 | crossModule = true, 46 | }, 47 | }, 48 | }, 49 | }, 50 | }, 51 | }) 52 | 53 | -- JavaScript/TypeScript 54 | setup("ts_ls") 55 | -- I don't use deno for now, but keep config here 56 | -- setup("denols", require("lang.deno")) 57 | 58 | -- Lua 59 | local _lua_config = {} 60 | local _is_nvim_config_dir = (vim.fn.getcwd()):find("nvim") 61 | if _is_nvim_config_dir then 62 | local neovim_setting = { 63 | diagnostics = { 64 | enable = true, 65 | globals = { "vim" }, 66 | }, 67 | runtime = { 68 | version = "LuaJIT", 69 | path = vim.split(package.path, ";"), 70 | }, 71 | workspace = { 72 | library = { 73 | vim.env.VIMRUNTIME, 74 | vim.api.nvim_get_runtime_file("", true), 75 | }, 76 | checkThirdParty = false, 77 | }, 78 | completion = { 79 | callSnippet = "Replace", 80 | }, 81 | } 82 | _lua_config.settings = { 83 | Lua = neovim_setting, 84 | } 85 | end 86 | setup("lua_ls", _lua_config) 87 | 88 | -- Nix 89 | setup("nil_ls") 90 | 91 | -- OCaml 92 | setup("ocamllsp") 93 | 94 | -- Python 95 | setup("pyright") 96 | 97 | -- Rust 98 | setup("rust_analyzer", { 99 | -- Don't know why built-in not working 100 | root_dir = function() 101 | return require("libs.find_root").find_root({ patterns = { "Cargo.toml" } }) 102 | end, 103 | on_init = function(client) 104 | local _, folder = next(client.workspace_folders) 105 | local current_dir = folder.name 106 | 107 | local cfg_file = vim.fs.joinpath(current_dir, ".rust-analyzer.json") 108 | 109 | -- prompt when try to read the file, to avoid security issue 110 | local file = vim.secure.read(cfg_file) 111 | if not file then 112 | return true 113 | end 114 | 115 | local local_settings = { ["rust-analyzer"] = vim.json.decode(file) } 116 | client.config.settings = vim.tbl_deep_extend("force", client.config.settings, local_settings) 117 | client.notify("workspace/didChangeConfiguration", { settings = client.config.settings }) 118 | 119 | vim.notify( 120 | "Using new local settings in " .. vim.fs.normalize(current_dir .. "/.rust-analyzer.json") 121 | ) 122 | 123 | return true 124 | end, 125 | }) 126 | -------------------------------------------------------------------------------- /lua/lang/deno.lua: -------------------------------------------------------------------------------- 1 | local Export = { 2 | settings = { 3 | deno = { 4 | enable = true, 5 | suggest = { 6 | imports = { 7 | hosts = { 8 | ["https://deno.land"] = true, 9 | ["https://crux.land"] = true, 10 | }, 11 | }, 12 | }, 13 | }, 14 | }, 15 | handlers = { 16 | ["deno/registryState"] = function(_, result, ctx) 17 | local client = vim.lsp.get_client_by_id(ctx.client_id) 18 | local config = (client.config.settings.deno.suggest or {}).imports or {} 19 | local hosts = config.hosts or {} 20 | hosts[result.origin] = true 21 | 22 | local new_config = { 23 | deno = { 24 | suggest = { 25 | imports = { 26 | hosts = hosts, 27 | }, 28 | }, 29 | }, 30 | } 31 | client.config.settings = vim.tbl_deep_extend("force", client.config.settings, new_config) 32 | client.notify("workspace/didChangeConfiguration", { 33 | settings = new_config, 34 | }) 35 | end, 36 | }, 37 | } 38 | 39 | -- fix highlight on codefences 40 | vim.g.markdown_fenced_languages = { 41 | "ts=typescript", 42 | } 43 | 44 | local on_attach = function(client, bufnr) 45 | require("lang.on_attach").setup_all(client, bufnr) 46 | 47 | ---@return table|nil 48 | local function get_deno_client() 49 | local clients = vim.lsp.get_active_clients({ 50 | bufnr = bufnr, 51 | name = "denols", 52 | }) 53 | 54 | local _, deno = next(clients) 55 | if deno == nil then 56 | vim.notify("No Deno client found") 57 | return nil 58 | end 59 | 60 | return deno 61 | end 62 | 63 | local cmd = function(...) 64 | vim.api.nvim_buf_create_user_command(bufnr, ...) 65 | end 66 | 67 | cmd("DenoReloadImports", function() 68 | local deno = get_deno_client() 69 | if deno == nil then 70 | return 71 | end 72 | 73 | deno.request("deno/reloadImportRegistries", nil, function() 74 | vim.notify("Registries reloaded") 75 | end) 76 | end, { 77 | desc = "Reload cached response from import registries", 78 | }) 79 | 80 | cmd("DenoCache", function() 81 | local deno = get_deno_client() 82 | if deno == nil then 83 | return 84 | end 85 | 86 | local api = vim.api 87 | local current_window = api.nvim_get_current_win() 88 | local current_buffer = api.nvim_win_get_buf(current_window) 89 | 90 | deno.request( 91 | "deno/cache", 92 | { referrer = { uri = vim.lsp.util.make_text_document_params(current_buffer) }, uris = {} }, 93 | function() 94 | vim.notify("Dependencies cached") 95 | end 96 | ) 97 | 98 | vim.notify("Cache request sent, downloading dependencies...") 99 | end, { 100 | desc = "Cache uncached module", 101 | }) 102 | end 103 | 104 | Export.on_attach = on_attach 105 | 106 | return Export 107 | -------------------------------------------------------------------------------- /lua/lang/init.lua: -------------------------------------------------------------------------------- 1 | local register = require("pack").register 2 | 3 | -- Interact with LSP server 4 | register("neovim/nvim-lspconfig", { 5 | config = function() 6 | require("lang.configs") 7 | end, 8 | }) 9 | 10 | register("numToStr/Comment.nvim", { 11 | config = function() 12 | require("Comment").setup({}) 13 | end, 14 | keys = { 15 | { "gcc", desc = "Toggle line comment" }, 16 | { "gbc", desc = "Toggle block comment" }, 17 | { mode = "x", "gc", desc = "Toggle line comment" }, 18 | { mode = "x", "gb", desc = "Toggle block comment" }, 19 | }, 20 | }) 21 | 22 | register("scalameta/nvim-metals", { 23 | ft = { "scala" }, 24 | config = function() 25 | require("lang.scala") 26 | end, 27 | }) 28 | 29 | register("stevearc/conform.nvim", { 30 | ft = { 31 | "lua", 32 | "javascript", 33 | "typescript", 34 | "javascriptreact", 35 | "typescriptreact", 36 | "json", 37 | "nix", 38 | "haskell", 39 | "python", 40 | "rust", 41 | "scala", 42 | "ocaml", 43 | }, 44 | config = function() 45 | require("conform").setup({ 46 | formatters_by_ft = { 47 | lua = { "stylua" }, 48 | javascript = { "prettierd", "prettier", stop_after_first = true }, 49 | json = { "prettierd", "prettier", stop_after_first = true }, 50 | typescript = { "prettierd", "prettier", stop_after_first = true }, 51 | nix = { "nixfmt" }, 52 | haskell = { "fourmolu" }, 53 | python = { "black" }, 54 | rust = { "rustfmt" }, 55 | ocaml = { "ocamlformat" }, 56 | }, 57 | format_on_save = function(bufnr) 58 | -- Avoid text lock for long time 59 | if vim.api.nvim_buf_line_count(bufnr) >= 5000 then 60 | return 61 | end 62 | 63 | if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then 64 | return 65 | end 66 | 67 | return { timeout_ms = 500, lsp_fallback = true } 68 | end, 69 | }) 70 | 71 | require("builder.key-mapper").map("n", { 72 | "cf", 73 | function() 74 | -- Use LSP client provided formatter when no formatter specify 75 | require("conform").format({ lsp_format = "fallback" }) 76 | end, 77 | desc = "[LSP] Format code", 78 | }) 79 | 80 | vim.api.nvim_create_user_command("FormatDisable", function(args) 81 | if args.bang then 82 | -- FormatDisable! will disable formatting just for this buffer 83 | vim.b.disable_autoformat = true 84 | else 85 | vim.g.disable_autoformat = true 86 | end 87 | end, { 88 | desc = "Disable autoformat-on-save", 89 | bang = true, 90 | }) 91 | vim.api.nvim_create_user_command("FormatEnable", function() 92 | vim.b.disable_autoformat = false 93 | vim.g.disable_autoformat = false 94 | end, { 95 | desc = "Re-enable autoformat-on-save", 96 | }) 97 | end, 98 | }) 99 | -------------------------------------------------------------------------------- /lua/lang/on_attach.lua: -------------------------------------------------------------------------------- 1 | local utils = {} 2 | 3 | utils.setup_keymaps = function(_, bufnr) 4 | local telescope = function(action, args) 5 | return function() 6 | local theme = require("telescope.themes").get_dropdown(args or {}) 7 | local builtins = require("telescope.builtin") 8 | builtins[action](theme) 9 | end 10 | end 11 | 12 | vim.api.nvim_set_option_value("omnifunc", "v:lua.vim.lsp.omnifunc", { buf = bufnr }) 13 | 14 | require("builder.key-mapper").bufmap(bufnr, "n", { 15 | { "K", vim.lsp.buf.hover, desc = "[LSP] Open document" }, 16 | { "R", vim.lsp.buf.rename, desc = "[LSP] Rename symbol" }, 17 | 18 | { "gD", telescope("lsp_definitions"), desc = "[LSP] Search and goto `definitions`" }, 19 | { "gR", telescope("lsp_references"), desc = "[LSP] Search and goto `references`" }, 20 | { "gI", telescope("lsp_implementations"), desc = "[LSP] Search and goto `implementations`" }, 21 | { "gT", telescope("lsp_type_definitions"), desc = "[LSP] Search and goto `type definition`" }, 22 | 23 | -- cf: code format, define in conform.nvim module at lang/init.lua 24 | { "ca", vim.lsp.buf.code_action, desc = "[LSP] Open code actions" }, 25 | { "cr", vim.lsp.codelens.run, desc = "[LSP] Run codelens at current line" }, 26 | 27 | { "do", vim.diagnostic.open_float, desc = "[LSP] Open floating list" }, 28 | { "dq", vim.diagnostic.setqflist, desc = "[LSP] Open quickfix list" }, 29 | 30 | { "[[", vim.diagnostic.goto_prev, desc = "[LSP] Jump to previous error" }, 31 | { "]]", vim.diagnostic.goto_next, desc = "[LSP] Jump to next error" }, 32 | }) 33 | end 34 | 35 | utils.setup_icons = function() 36 | local icons = { 37 | "", 38 | "", 39 | "", 40 | "", 41 | } 42 | 43 | -- Setup diagnostic icons and signs 44 | vim.diagnostic.config({ 45 | virtual_text = { 46 | prefix = function(_) 47 | return "" 48 | end, 49 | spacing = 8, 50 | }, 51 | float = { 52 | prefix = function(diag) 53 | return icons[diag.severity] .. " " 54 | end, 55 | border = "solid", 56 | }, 57 | signs = false, 58 | underline = true, 59 | -- update diagnostic in insert mode will be annoying when the output is too verbose 60 | update_in_insert = false, 61 | }) 62 | end 63 | 64 | -- LSP's on_attach interface accept two arguments client and bufnr. But we don't use client for now, so it is okay to pass nil here. 65 | utils.setup_all = function(client, bufnr) 66 | utils.setup_icons() 67 | utils.setup_keymaps(client, bufnr) 68 | 69 | if client.server_capabilities.inlayHintProvider then 70 | -- Display after attached 71 | vim.defer_fn(function() 72 | if vim.lsp.inlay_hint.is_enabled() then 73 | vim.lsp.inlay_hint.enable(false) 74 | end 75 | end, 1000) 76 | end 77 | 78 | local gid = vim.api.nvim_create_augroup("MyLspAutocmdsSetup" .. bufnr, { clear = true }) 79 | 80 | if client.server_capabilities.documentHighlightProvider then 81 | vim.api.nvim_create_autocmd("CursorHold", { 82 | callback = function() 83 | vim.lsp.buf.document_highlight() 84 | end, 85 | group = gid, 86 | buffer = bufnr, 87 | desc = "Document Highlight", 88 | }) 89 | vim.api.nvim_create_autocmd("CursorMoved", { 90 | callback = function() 91 | vim.lsp.buf.clear_references() 92 | end, 93 | group = gid, 94 | buffer = bufnr, 95 | desc = "Clear All the References", 96 | }) 97 | end 98 | 99 | if client and client.server_capabilities and client.server_capabilities.codeLensProvider then 100 | vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, { 101 | group = gid, 102 | buffer = bufnr, 103 | callback = function() 104 | vim.lsp.codelens.refresh({ bufnr = bufnr }) 105 | end, 106 | }) 107 | end 108 | 109 | -- Clean buffer from client when buffer is deleted 110 | vim.api.nvim_create_autocmd("BufDelete", { 111 | buffer = bufnr, 112 | group = gid, 113 | callback = function() 114 | vim.lsp.inlay_hint.enable(false, { buffer = bufnr }) 115 | vim.lsp.buf_detach_client(bufnr, client.id) 116 | vim.api.nvim_clear_autocmds({ group = gid }) 117 | end, 118 | }) 119 | end 120 | 121 | return utils 122 | -------------------------------------------------------------------------------- /lua/lang/scala.lua: -------------------------------------------------------------------------------- 1 | local scala_config = require("metals").bare_config() 2 | scala_config.settings = { 3 | showImplicitArguments = true, 4 | excludedPackages = { "akka.actor.typed.javadsl", "com.github.swagger.akka.javadsl" }, 5 | } 6 | 7 | local metals_binary = vim.fn.exepath("metals") 8 | if not metals_binary or metals_binary == "" then 9 | vim.notify("metals not found, stop configuring LSP.", vim.log.levels.WARN) 10 | return 11 | end 12 | scala_config.settings.metalsBinaryPath = metals_binary 13 | 14 | local mill_exe = vim.fn.exepath("mill") 15 | if not mill_exe or mill_exe == "" then 16 | vim.notify("mill not found, stop configuring metals.", vim.log.levels.WARN) 17 | return 18 | end 19 | 20 | scala_config.init_options.statusBarProvider = "off" 21 | scala_config.root_patterns = { "build.sbt", "build.sc", "build.gradle", "pom.xml", ".git" } 22 | scala_config.find_root_dir_max_project_nesting = 0 23 | scala_config.settings.millScript = mill_exe 24 | scala_config.capabilities = require("cmp_nvim_lsp").default_capabilities() 25 | scala_config.on_attach = require("lang.on_attach").setup_all 26 | require("metals").initialize_or_attach(scala_config) 27 | 28 | -- nvim-metals will send metals/didFocus protocol to all the buffer, which will cause other LSP to exits. 29 | -- Here I recreate the nvim-metasls-forcus auto commands to force it run on *.scala/*.sc only. 30 | -- Using LspAttach here to delay the erase execution, because the nvim-metals plugin define the 31 | -- auto commands after buffer attached. 32 | vim.api.nvim_create_autocmd("LspAttach", { 33 | pattern = { "*.scala", "*.sc" }, 34 | callback = function() 35 | vim.schedule(function() 36 | vim.api.nvim_clear_autocmds({ group = "nvim-metals-focus" }) 37 | vim.api.nvim_create_autocmd("BufEnter", { 38 | pattern = { "*.scala", "*.sc" }, 39 | callback = function() 40 | require("metals").did_focus() 41 | end, 42 | group = vim.api.nvim_create_augroup("nvim-metals-focus", { clear = true }), 43 | }) 44 | end) 45 | end, 46 | }) 47 | -------------------------------------------------------------------------------- /lua/libs/bigfile.lua: -------------------------------------------------------------------------------- 1 | -- Source: https://github.com/folke/snacks.nvim 2 | -- License: Apache License 2.0 3 | -- w/ modification to integrate in this dotfile 4 | 5 | ---@class snacks.bigfile 6 | local M = {} 7 | 8 | ---@class snacks.bigfile.Config 9 | local defaults = { 10 | notify = true, -- show notification when big file detected 11 | size = 1.5 * 1024 * 1024, -- 1.5MB 12 | -- Enable or disable features when big file detected 13 | ---@param ctx {buf: number, ft:string} 14 | setup = function(ctx) 15 | vim.g.loaded_matchparen = false 16 | vim.wo.foldmethod = "manual" 17 | vim.wo.statuscolumn = "" 18 | vim.wo.conceallevel = 0 19 | vim.b.minianimate_disable = true 20 | vim.schedule(function() 21 | vim.bo[ctx.buf].syntax = ctx.ft 22 | end) 23 | end, 24 | } 25 | 26 | ---@private 27 | function M.setup(user) 28 | local opts = user or defaults 29 | 30 | vim.filetype.add({ 31 | pattern = { 32 | [".*"] = { 33 | function(path, buf) 34 | return vim.bo[buf] 35 | and vim.bo[buf].filetype ~= "bigfile" 36 | and path 37 | and vim.fn.getfsize(path) > opts.size 38 | and "bigfile" 39 | or nil 40 | end, 41 | }, 42 | }, 43 | }) 44 | 45 | vim.api.nvim_create_autocmd({ "FileType" }, { 46 | group = vim.api.nvim_create_augroup("snacks_bigfile", { clear = true }), 47 | pattern = "bigfile", 48 | callback = function(ev) 49 | if opts.notify then 50 | local path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(ev.buf), ":p:~:.") 51 | vim.notify( 52 | ("Big file detected `%s`. Some Neovim features have been **disabled**."):format(path), 53 | vim.log.levels.WARN 54 | ) 55 | end 56 | vim.api.nvim_buf_call(ev.buf, function() 57 | opts.setup({ 58 | buf = ev.buf, 59 | ft = vim.filetype.match({ buf = ev.buf }) or "", 60 | }) 61 | end) 62 | end, 63 | }) 64 | end 65 | 66 | return M 67 | -------------------------------------------------------------------------------- /lua/libs/bufdel.lua: -------------------------------------------------------------------------------- 1 | -- nvim-bufdel 2 | -- By Olivier Roques 3 | -- github.com/ojroques 4 | 5 | local M = {} 6 | 7 | -- Switch to buffer 'buf' on each window from list 'windows' 8 | local function switch_buffer(windows, buf) 9 | local cur_win = vim.fn.winnr() 10 | for _, winid in ipairs(windows) do 11 | vim.cmd(string.format("%d wincmd w", vim.fn.win_id2win(winid))) 12 | vim.cmd(string.format("buffer %d", buf)) 13 | end 14 | vim.cmd(string.format("%d wincmd w", cur_win)) 15 | end 16 | 17 | -- Select the next buffer to display 18 | local function get_next_buf(buf) 19 | -- build table mapping buffers to their actual position 20 | local buffers, buf_index = {}, 1 21 | for i, bufinfo in ipairs(vim.fn.getbufinfo({ buflisted = 1 })) do 22 | if buf == bufinfo.bufnr then 23 | buf_index = i 24 | end 25 | table.insert(buffers, bufinfo.bufnr) 26 | end 27 | -- select next buffer according to user choice 28 | if buf_index == #buffers and #buffers > 1 then 29 | return buffers[#buffers - 1] 30 | end 31 | return buffers[buf_index % #buffers + 1] 32 | end 33 | 34 | -- Delete a buffer, ignoring changes if 'force' is set 35 | local function delete_buffer(buf, force) 36 | if vim.fn.buflisted(buf) == 0 then 37 | return 38 | end 39 | -- retrieve buffer and delete it while preserving window layout 40 | local next_buf = get_next_buf(buf) 41 | local windows = vim.fn.getbufinfo(buf)[1].windows 42 | switch_buffer(windows, next_buf) 43 | -- force deletion of terminal buffers 44 | if force or vim.fn.getbufvar(buf, "&buftype") == "terminal" then 45 | vim.cmd(string.format("bd! %d", buf)) 46 | else 47 | vim.cmd(string.format("silent! confirm bd %d", buf)) 48 | end 49 | -- revert buffer switches if deletion was cancelled 50 | if vim.fn.buflisted(buf) == 1 then 51 | switch_buffer(windows, buf) 52 | end 53 | end 54 | 55 | -- Delete a given buffer, ignoring changes if 'force' is set 56 | function M.delete_buffer_expr(bufexpr, force) 57 | if #vim.fn.getbufinfo({ buflisted = 1 }) < 2 then 58 | -- exit when there is only one buffer left 59 | if force then 60 | vim.cmd("qall!") 61 | else 62 | vim.cmd("confirm qall") 63 | end 64 | return 65 | end 66 | -- retrieve buffer number from buffer expression 67 | if not bufexpr then 68 | delete_buffer(vim.fn.bufnr(), force) 69 | end 70 | if tonumber(bufexpr) then 71 | delete_buffer(tonumber(bufexpr), force) 72 | end 73 | bufexpr = string.gsub(bufexpr, [[^['"]+]], "") -- escape any start quote 74 | bufexpr = string.gsub(bufexpr, [[['"]+$]], "") -- escape any end quote 75 | delete_buffer(vim.fn.bufnr(bufexpr), force) 76 | end 77 | 78 | -- Delete all listed buffers except current, ignoring changes if 'force' is set 79 | function M.delete_buffer_others(force) 80 | for _, bufinfo in ipairs(vim.fn.getbufinfo({ buflisted = 1 })) do 81 | if bufinfo.bufnr ~= vim.fn.bufnr() then 82 | delete_buffer(bufinfo.bufnr, force) 83 | end 84 | end 85 | end 86 | 87 | return M 88 | -------------------------------------------------------------------------------- /lua/libs/cache.lua: -------------------------------------------------------------------------------- 1 | local M = { 2 | __cache = {}, 3 | } 4 | 5 | -- function loaded will insert the given module name into cache when it is not exist. 6 | ---@param mod string A unique module name 7 | ---@return boolean true if the given mod is loaded, false if the given mod is not exist. 8 | function M.loaded(mod) 9 | local key = string.format("%d%s", vim.api.nvim_get_current_buf(), mod) 10 | if M.__cache[key] then 11 | return true 12 | end 13 | 14 | M.__cache[key] = 1 15 | 16 | return false 17 | end 18 | 19 | setmetatable(M, { 20 | __call = function(self, a) 21 | return self.loaded(a) 22 | end, 23 | __index = function(self, a) 24 | return self.loaded(a) 25 | end, 26 | }) 27 | 28 | return M 29 | -------------------------------------------------------------------------------- /lua/libs/find_root.lua: -------------------------------------------------------------------------------- 1 | local export = {} 2 | 3 | function export.find_root(opts) 4 | return vim.fs.root(0, opts.patterns or { ".git", "flake.nix" }) 5 | or vim.fs.dirname(vim.api.nvim_buf_get_name(0)) 6 | end 7 | 8 | function export.set_root(opts) 9 | opts = opts or {} 10 | 11 | if not vim.tbl_contains({ "", "acwrite" }, vim.bo.buftype) then 12 | return 13 | end 14 | 15 | if vim.tbl_contains(opts.exclude_filetype or { "oil" }, vim.bo.filetype) then 16 | return 17 | end 18 | 19 | local root = vim.b.current_buf_root_dir or nil 20 | if root == nil then 21 | root = export.find_root(opts) 22 | vim.b.current_buf_root_dir = root 23 | end 24 | 25 | if root ~= nil then 26 | vim.api.nvim_set_current_dir(root) 27 | end 28 | end 29 | 30 | return export 31 | -------------------------------------------------------------------------------- /lua/libs/notify.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.info(msg) 4 | vim.notify(" => INFO: " .. msg, vim.log.levels.INFO) 5 | end 6 | 7 | function M.error(title, msg) 8 | vim.api.nvim_echo({ { " => ERROR: " .. title, "ErrorMsg" } }, true, {}) 9 | vim.notify(msg, vim.log.levels.ERROR) 10 | end 11 | 12 | return M 13 | -------------------------------------------------------------------------------- /lua/pack.lua: -------------------------------------------------------------------------------- 1 | local notify = require("libs.notify") 2 | 3 | local M = { 4 | repositories = {}, 5 | } 6 | 7 | local function collect_plugins() 8 | local overlays = { 9 | "completion", 10 | "git", 11 | "lang", 12 | "tools", 13 | "treesitter", 14 | "ui", 15 | } 16 | 17 | for _, component in ipairs(overlays) do 18 | local ok, maybe_error = pcall(require, component) 19 | if not ok then 20 | notify.error("fail to load component " .. component, maybe_error) 21 | end 22 | end 23 | end 24 | 25 | function M.setup() 26 | local lazy_nvim_install_path = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 27 | if not vim.loop.fs_stat(lazy_nvim_install_path) then 28 | notify.info("Package manager not found, installing...") 29 | local success, maybe_error = pcall(vim.fn.system, { 30 | "git", 31 | "clone", 32 | "--filter=blob:none", 33 | "https://github.com/folke/lazy.nvim.git", 34 | "--branch=stable", 35 | lazy_nvim_install_path, 36 | }) 37 | 38 | if not success then 39 | notify.error("ERROR: Fail to install plugin manager lazy.nvim", maybe_error) 40 | notify.info("You can cleanup the " .. lazy_nvim_install_path .. " and start again") 41 | return 42 | end 43 | end 44 | 45 | vim.opt.rtp:prepend(lazy_nvim_install_path) 46 | 47 | collect_plugins() 48 | 49 | require("lazy").setup(M.repositories, { 50 | rocks = { enabled = false }, 51 | performance = { 52 | rtp = { 53 | reset = false, 54 | }, 55 | }, 56 | }) 57 | end 58 | 59 | ---@param repo_path string URL to the plugin repositories 60 | ---@param config table? Lazy.nvim plugin spec 61 | function M.register(repo_path, config) 62 | local package = config or {} 63 | 64 | package[1] = repo_path 65 | 66 | table.insert(M.repositories, package) 67 | end 68 | 69 | return M 70 | -------------------------------------------------------------------------------- /lua/tools/init.lua: -------------------------------------------------------------------------------- 1 | local register = require("pack").register 2 | 3 | -- Neovim Library wrapper 4 | register("nvim-lua/plenary.nvim", { 5 | lazy = true, 6 | }) 7 | 8 | -- UI Library 9 | register("MunifTanjim/nui.nvim", { 10 | lazy = true, 11 | }) 12 | 13 | -- Use oil for main file management, use neo-tree for treestyle display only. 14 | register("stevearc/oil.nvim", { 15 | cmd = { "Oil" }, 16 | lazy = false, 17 | keys = { 18 | { 19 | "_", 20 | function() 21 | require("oil").open(vim.fn.getcwd()) 22 | end, 23 | desc = "Open cwd", 24 | }, 25 | { "-", "Oil", { desc = "Open parent directory" } }, 26 | }, 27 | config = function() 28 | require("oil").setup({ 29 | float = { 30 | border = "solid", 31 | max_width = 200, 32 | max_height = 50, 33 | }, 34 | keymaps = { 35 | ["q"] = "actions.close", 36 | }, 37 | view_options = { 38 | show_hidden = true, 39 | }, 40 | }) 41 | end, 42 | }) 43 | 44 | local function my_ivy(opt) 45 | local my_opt = { 46 | borderchars = { 47 | prompt = { " " }, 48 | results = { " " }, 49 | preview = { " " }, 50 | }, 51 | } 52 | local exted = vim.tbl_deep_extend("force", my_opt, opt or {}) 53 | return require("telescope.themes").get_ivy(exted) 54 | end 55 | 56 | -- Fuzzy Picker 57 | register("nvim-telescope/telescope.nvim", { 58 | lazy = true, 59 | config = function() 60 | require("telescope").setup({ 61 | defaults = { 62 | prompt_prefix = "  ", 63 | entry_prefix = " ", 64 | defaults = { 65 | vimgrep_arguments = { 66 | "rg", 67 | "--color=never", 68 | "--no-heading", 69 | "--with-filename", 70 | "--line-number", 71 | "--column", 72 | "--smart-case", 73 | "--trim", -- add this value 74 | }, 75 | }, 76 | }, 77 | pickers = { 78 | find_files = { 79 | -- `hidden = true` will still show the inside of `.git/` as it's not `.gitignore`d. 80 | find_command = { "rg", "--files", "--hidden", "--glob", "!**/.git/*" }, 81 | }, 82 | }, 83 | }) 84 | end, 85 | keys = { 86 | { 87 | "ff", 88 | function() 89 | local function my_find_file(opt) 90 | if not vim.b._is_inside_git_worktree then 91 | vim.fn.system("git rev-parse --is-inside-work-tree") 92 | vim.b._is_inside_git_worktree = vim.v.shell_error == 0 93 | end 94 | if vim.b._is_inside_git_worktree then 95 | return require("telescope.builtin").git_files(opt) 96 | else 97 | return require("telescope.builtin").find_files(opt) 98 | end 99 | end 100 | 101 | my_find_file(my_ivy({ hidden = true })) 102 | end, 103 | desc = "Find file", 104 | }, 105 | { 106 | "fs", 107 | function() 108 | require("telescope.builtin").lsp_dynamic_workspace_symbols(my_ivy()) 109 | end, 110 | desc = "Find symbol", 111 | }, 112 | { 113 | "fg", 114 | function() 115 | require("telescope.builtin").live_grep(my_ivy()) 116 | end, 117 | desc = "Find keyword", 118 | }, 119 | }, 120 | }) 121 | 122 | -- Surround operation 123 | register("kylechui/nvim-surround", { 124 | keys = { 125 | "ys", 126 | "yS", 127 | "cs", 128 | "cS", 129 | "ds", 130 | "dS", 131 | { "gs", mode = { "x" } }, 132 | { "gS", mode = { "x" } }, 133 | { "", mode = "i" }, 134 | }, 135 | config = function() 136 | require("nvim-surround").setup({ 137 | keymaps = { 138 | visual = "gs", 139 | }, 140 | -- add new object "y" for operating on Types. For example: `Vector` 141 | surrounds = { 142 | ["y"] = { 143 | add = function() 144 | local result = require("nvim-surround.config").get_input("Enter the type name: ") 145 | if result then 146 | return { { result .. "<" }, { ">" } } 147 | end 148 | end, 149 | find = function() 150 | return require("nvim-surround.config").get_selection({ 151 | pattern = "[^=%s%(%)]+%b<>", 152 | }) 153 | end, 154 | delete = "^(.-<)().-(>)()$", 155 | change = { 156 | target = "^.-([%w_]+)()<.->()()$", 157 | replacement = function() 158 | local result = 159 | require("nvim-surround.config").get_input("Enter new type replacement: ") 160 | if result then 161 | return { { result }, { "" } } 162 | end 163 | end, 164 | }, 165 | }, 166 | }, 167 | }) 168 | end, 169 | }) 170 | 171 | -- Quick moving by two character searching 172 | register("ggandor/leap.nvim", { 173 | keys = { 174 | { "s", "(leap-forward-to)", mode = { "n", "x", "o" }, desc = "Leap forward to" }, 175 | { "S", "(leap-backward-to)", mode = { "n", "x", "o" }, desc = "Leap backward to" }, 176 | { "x", "(leap-forward-till)", mode = { "x", "o" }, desc = "Leap forward until" }, 177 | { "X", "(leap-backward-till)", mode = { "x", "o" }, desc = "Leap backward until" }, 178 | { "gw", "(leap-from-window)", mode = { "n" }, desc = "Leap from window" }, 179 | { "gW", "(leap-cross-window)", mode = { "n" }, desc = "Leap cross window" }, 180 | }, 181 | }) 182 | 183 | -- sort the number or text 184 | register("sQVe/sort.nvim", { 185 | config = function() 186 | require("sort").setup({}) 187 | end, 188 | cmd = "Sort", 189 | }) 190 | 191 | -- Auto matically setting tab width by projects 192 | register("tpope/vim-sleuth") 193 | 194 | --- Color utils 195 | register("uga-rosa/ccc.nvim", { 196 | config = function() 197 | require("ccc").setup() 198 | end, 199 | cmd = { 200 | "CccPick", 201 | "CccHighlighterEnable", 202 | }, 203 | }) 204 | 205 | -- Easy aligning text 206 | register("junegunn/vim-easy-align", { 207 | cmd = "EasyAlign", 208 | keys = { { "e", ":EasyAlign", mode = "x" } }, 209 | }) 210 | 211 | register("stevearc/quicker.nvim", { 212 | ft = "qf", 213 | config = function() 214 | require("quicker").setup() 215 | require("galaxyline").load_galaxyline() 216 | end, 217 | }) 218 | 219 | -- Open buffer manager 220 | register("j-morano/buffer_manager.nvim", { 221 | lazy = true, 222 | keys = { 223 | -- tools 224 | { 225 | "b", 226 | function() 227 | require("buffer_manager.ui").toggle_quick_menu() 228 | end, 229 | desc = "Toggle buffer manager", 230 | }, 231 | { 232 | "", 233 | function() 234 | require("cybu").autocmd() 235 | require("buffer_manager.ui").nav_next() 236 | end, 237 | desc = "Next buffer", 238 | }, 239 | { 240 | "", 241 | function() 242 | require("cybu").autocmd() 243 | require("buffer_manager.ui").nav_prev() 244 | end, 245 | desc = "Prev buffer", 246 | }, 247 | }, 248 | config = function() 249 | require("buffer_manager").setup({ 250 | -- Defined in kanagawa.nvim 251 | highlight = "Normal:BufferManagerBorder", 252 | }) 253 | end, 254 | }) 255 | 256 | -- Cycle through buffers 257 | register("ghillb/cybu.nvim", { 258 | lazy = true, 259 | config = function() 260 | require("cybu").setup({ 261 | style = { 262 | border = "none", 263 | padding = 5, 264 | hide_buffer_id = true, 265 | }, 266 | display_time = 1500, 267 | exclude = { 268 | "neo-tree", 269 | "qf", 270 | "neo-term", 271 | }, 272 | }) 273 | end, 274 | }) 275 | 276 | register("dhruvasagar/vim-table-mode", { 277 | cmd = "TableModeToggle", 278 | }) 279 | -------------------------------------------------------------------------------- /lua/treesitter/config.lua: -------------------------------------------------------------------------------- 1 | local disable = function(_, buf) 2 | return vim.api.nvim_buf_line_count(buf) >= 5000 3 | end 4 | 5 | require("nvim-treesitter.configs").setup({ 6 | auto_install = false, 7 | incremental_selection = { 8 | enable = true, 9 | keymaps = { 10 | init_selection = false, 11 | node_incremental = false, 12 | scope_incremental = false, 13 | node_decremental = false, 14 | }, 15 | }, 16 | highlight = { 17 | enable = true, 18 | additional_vim_regex_highlighting = { "org" }, 19 | disable = disable, 20 | }, 21 | indent = { 22 | enable = true, 23 | disable = disable, 24 | }, 25 | autotag = { 26 | enable = true, 27 | }, 28 | textobjects = { 29 | select = { 30 | enable = true, 31 | 32 | -- Automatically jump forward to textobj, similar to targets.vim 33 | lookahead = true, 34 | 35 | keymaps = {}, 36 | }, 37 | }, 38 | }) 39 | -------------------------------------------------------------------------------- /lua/treesitter/init.lua: -------------------------------------------------------------------------------- 1 | local register = require("pack").register 2 | 3 | register("nvim-treesitter/nvim-treesitter", { 4 | event = "BufReadPost", 5 | config = function() 6 | vim.schedule(function() 7 | require("treesitter.config") 8 | end) 9 | end, 10 | dependencies = { 11 | "nvim-treesitter/nvim-treesitter-textobjects", 12 | "windwp/nvim-ts-autotag", 13 | }, 14 | }) 15 | -------------------------------------------------------------------------------- /lua/ui/indent.lua: -------------------------------------------------------------------------------- 1 | local hooks = require("ibl.hooks") 2 | hooks.register(hooks.type.ACTIVE, function(bufnr) 3 | return vim.api.nvim_buf_line_count(bufnr) < 5000 4 | end) 5 | 6 | require("ibl").setup({ 7 | indent = { 8 | char = "▏", 9 | }, 10 | scope = { 11 | show_start = false, 12 | show_end = false, 13 | }, 14 | exclude = { 15 | filetypes = { 16 | "help", 17 | "terminal", 18 | "dashboard", 19 | "packer", 20 | "lspinfo", 21 | "TelescopePrompt", 22 | "TelescopeResults", 23 | "startify", 24 | "dashboard", 25 | "dotooagenda", 26 | "log", 27 | "fugitive", 28 | "gitcommit", 29 | "packer", 30 | "vimwiki", 31 | "markdown", 32 | "txt", 33 | "vista", 34 | "help", 35 | "todoist", 36 | "NvimTree", 37 | "peekaboo", 38 | "git", 39 | "TelescopePrompt", 40 | "undotree", 41 | "flutterToolsOutline", 42 | "lsp-installer", 43 | "hydra_hint", 44 | "noice", 45 | "", 46 | }, 47 | }, 48 | }) 49 | -------------------------------------------------------------------------------- /lua/ui/init.lua: -------------------------------------------------------------------------------- 1 | local register = require("pack").register 2 | 3 | -- Deep dark purple colorscheme 4 | register("rebelot/kanagawa.nvim", { 5 | lazy = true, 6 | config = function() 7 | require("ui.kanagawa") 8 | end, 9 | }) 10 | 11 | --- List of nerd-font icons 12 | register("kyazdani42/nvim-web-devicons", { 13 | lazy = true, 14 | config = function() 15 | require("nvim-web-devicons").setup({ 16 | override = { 17 | ml = { 18 | icon = "", 19 | color = "#e37933", 20 | cterm_color = "166", 21 | name = "Ml", 22 | }, 23 | }, 24 | override_by_extension = { 25 | ["mill"] = { 26 | icon = "", 27 | color = "#cc3e44", 28 | cterm_color = "167", 29 | name = "Scala", 30 | }, 31 | ["sc"] = { 32 | icon = "", 33 | color = "#cc3e44", 34 | cterm_color = "167", 35 | name = "Scala", 36 | }, 37 | }, 38 | }) 39 | end, 40 | }) 41 | 42 | -- Status line 43 | register("Avimitin/galaxyline.nvim", { 44 | branch = "global-status-line", 45 | event = { "FileType", "WinEnter", "BufEnter" }, 46 | config = function() 47 | require("ui.statusline") 48 | end, 49 | }) 50 | 51 | -- Indent guide line 52 | register("lukas-reineke/indent-blankline.nvim", { 53 | event = "BufRead", 54 | config = function() 55 | require("ui.indent") 56 | end, 57 | }) 58 | 59 | -- Notification UI 60 | register("j-hui/fidget.nvim", { 61 | config = function() 62 | require("fidget").setup({}) 63 | vim.notify = require("fidget").notify 64 | end, 65 | }) 66 | 67 | -- Scrollbar UI 68 | register("petertriho/nvim-scrollbar", { 69 | lazy = true, 70 | event = "BufReadPost", 71 | config = function() 72 | require("scrollbar").setup({ 73 | marks = { 74 | Search = { text = { "" } }, 75 | }, 76 | excluded_buftypes = { 77 | "terminal", 78 | }, 79 | excluded_filetypes = { 80 | "prompt", 81 | "TelescopePrompt", 82 | "noice", 83 | "Git", 84 | "cmp_menu", 85 | "cmp_docs", 86 | "markdown", 87 | }, 88 | handlers = { 89 | cursor = false, 90 | diagnostic = false, 91 | }, 92 | }) 93 | end, 94 | }) 95 | 96 | -- prettify the input and select ui 97 | register("stevearc/dressing.nvim", { 98 | lazy = true, 99 | init = function() 100 | ---@diagnostic disable-next-line: duplicate-set-field 101 | vim.ui.select = function(...) 102 | require("lazy").load({ plugins = { "dressing.nvim" } }) 103 | require("dressing").setup({ 104 | input = { border = "solid" }, 105 | select = { nui = { border = "solid" } }, 106 | }) 107 | return vim.ui.select(...) 108 | end 109 | ---@diagnostic disable-next-line: duplicate-set-field 110 | vim.ui.input = function(...) 111 | require("lazy").load({ plugins = { "dressing.nvim" } }) 112 | require("dressing").setup({ 113 | input = { border = "solid", prefer_width = 15, min_width = { 10, 0.1 } }, 114 | select = { nui = { border = "solid" } }, 115 | }) 116 | return vim.ui.input(...) 117 | end 118 | end, 119 | }) 120 | 121 | register("luukvbaal/statuscol.nvim", { 122 | event = "VeryLazy", 123 | config = function() 124 | local builtin = require("statuscol.builtin") 125 | require("statuscol").setup({ 126 | relculright = true, 127 | setopt = true, 128 | segments = { 129 | -- one space gap 130 | { text = { " " } }, 131 | -- Show the fold icon 132 | { text = { builtin.foldfunc }, click = "v:lua.ScFa" }, 133 | { text = { " " } }, 134 | -- Show git status 135 | { 136 | sign = { 137 | namespace = { "gitsign" }, 138 | maxwidth = 1, 139 | colwidth = 1, 140 | auto = false, 141 | }, 142 | click = "v:lua.ScSa", 143 | }, 144 | { text = { " " } }, 145 | -- Show the number column 146 | { text = { builtin.lnumfunc }, click = "v:lua.ScLa" }, 147 | -- Padding 148 | { text = { " " } }, 149 | }, 150 | ft_ignore = { 151 | "aerial", 152 | "help", 153 | "vim", 154 | "fugitive", 155 | "alpha", 156 | "dashboard", 157 | "neo-tree", 158 | "Trouble", 159 | "noice", 160 | "lazy", 161 | "toggleterm", 162 | }, 163 | }) 164 | end, 165 | }) 166 | 167 | -- winbar 168 | register("Bekaboo/dropbar.nvim", { 169 | -- lazy loading is done in this plugin 170 | lazy = false, 171 | keys = { 172 | { 173 | "p", 174 | function() 175 | require("dropbar.api").pick() 176 | end, 177 | desc = "Open picker on winbar", 178 | }, 179 | }, 180 | }) 181 | 182 | register("karb94/neoscroll.nvim", { 183 | keys = { 184 | "", 185 | "", 186 | "", 187 | "", 188 | "", 189 | "", 190 | "zt", 191 | "zz", 192 | "zb", 193 | }, 194 | config = function() 195 | require("neoscroll").setup({}) 196 | end, 197 | }) 198 | -------------------------------------------------------------------------------- /lua/ui/kanagawa.lua: -------------------------------------------------------------------------------- 1 | local function override(colors) 2 | local default = colors.palette 3 | -- local theme = colors.theme 4 | 5 | local overrides = { 6 | -- CursorLine = { bg = "#1b1b26" }, 7 | -- 8 | Normal = { bg = default.sumiInk0, fg = default.fujiWhite }, 9 | TelescopeBorder = { fg = default.sumiInk0, bg = default.sumiInk0 }, 10 | NormalFloat = { bg = default.sumiInk1 }, 11 | BufferManagerBorder = { bg = default.sumiInk1, fg = default.sumiInk1 }, 12 | -- FloatTitle = { fg = "#D3C6AA", bg = "#5C3F4F", bold = true }, 13 | -- FloatBorder = { link = "NormalFloat" }, 14 | 15 | -- Pmenu = { bg = default.sumiInk3 }, 16 | CmpDocumentation = { link = "Pmenu" }, 17 | 18 | ["@markup.heading.1"] = { 19 | fg = default.springGreen, 20 | bold = true, 21 | }, 22 | ["@markup.heading.2"] = { 23 | fg = default.waveAqua1, 24 | bold = true, 25 | }, 26 | ["@markup.heading.3"] = { 27 | fg = default.peachRed, 28 | bold = true, 29 | }, 30 | ["@markup.heading"] = { 31 | fg = default.crystalBlue, 32 | bold = true, 33 | }, 34 | ["@text.reference"] = { 35 | fg = default.springBlue, 36 | italic = true, 37 | }, 38 | } 39 | 40 | return overrides 41 | end 42 | 43 | require("kanagawa").setup({ 44 | undercurl = true, -- enable undercurls 45 | overrides = override, 46 | colors = { 47 | theme = { 48 | all = { 49 | ui = { 50 | bg_gutter = "none", 51 | }, 52 | }, 53 | }, 54 | }, 55 | background = { 56 | dark = "wave", 57 | light = "lotus", 58 | }, 59 | }) 60 | -------------------------------------------------------------------------------- /lua/ui/statusline.lua: -------------------------------------------------------------------------------- 1 | local gl = require("galaxyline") 2 | local gls = gl.section 3 | 4 | local colors = { 5 | bg = "#1a1a23", 6 | fg = "#b2b2b9", 7 | black = "#191919", 8 | yellow = "#E5C07B", 9 | cyan = "#70C0BA", 10 | dimblue = "#83A598", 11 | green = "#98C379", 12 | orange = "#FF8800", 13 | purple = "#C678DD", 14 | magenta = "#D27E99", 15 | blue = "#81A1C1", 16 | red = "#D54E53", 17 | lightgrey = "#5a5a72", 18 | } 19 | 20 | local light_colors = { 21 | bg = "#d6d6d6", 22 | fg = "#191919", 23 | black = "#191919", 24 | yellow = "#191919", 25 | cyan = "#191919", 26 | dimblue = "#191919", 27 | green = "#191919", 28 | orange = "#191919", 29 | purple = "#191919", 30 | magenta = "#191919", 31 | blue = "#191919", 32 | red = "#191919", 33 | lightgrey = "#191919", 34 | } 35 | 36 | if vim.o.background == "light" then 37 | colors = vim.tbl_deep_extend("force", colors, light_colors) 38 | end 39 | 40 | --[[ local checkwidth = function() 41 | local squeeze_width = vim.fn.winwidth(0) / 2 42 | if squeeze_width > 30 then 43 | return true 44 | end 45 | return false 46 | end ]] 47 | 48 | --[[ local buffer_not_empty = function() 49 | if vim.fn.empty(vim.fn.expand("%:t")) ~= 1 then 50 | return true 51 | end 52 | return false 53 | end ]] 54 | 55 | -- insert_left insert item at the left panel 56 | local function insert_left(element) 57 | table.insert(gls.left, element) 58 | end 59 | 60 | local function insert_space_on_left() 61 | insert_left({ 62 | SpaceOnLeft = { 63 | provider = function() 64 | return " " 65 | end, 66 | highlight = { colors.bg, colors.bg }, 67 | }, 68 | }) 69 | end 70 | 71 | local function insert_right(element) 72 | table.insert(gls.right, element) 73 | end 74 | 75 | local function insert_space_on_right() 76 | insert_right({ 77 | SpaceOnRight = { 78 | provider = function() 79 | return " " 80 | end, 81 | highlight = { colors.bg, colors.bg }, 82 | }, 83 | }) 84 | end 85 | 86 | ----------------------------------------------------- 87 | ----------------- start insert ---------------------- 88 | ----------------------------------------------------- 89 | -- { mode panel start 90 | local vim_mode = { 91 | alias = { 92 | n = "", 93 | no = "󰌌", 94 | nov = "󰌌", 95 | noV = "󰌌", 96 | i = "󰏫", 97 | c = "", 98 | v = "", 99 | V = "", 100 | [""] = "󰩬", 101 | C = "", 102 | ["r?"] = "?", 103 | rm = "", 104 | R = "", 105 | Rv = "", 106 | s = "󰆽", 107 | S = "󰆽", 108 | ["r"] = "󰌑", 109 | [""] = "󰆽", 110 | t = "", 111 | ["!"] = "", 112 | _LineLeap = "󱕘", 113 | }, 114 | color = { 115 | n = colors.green, 116 | i = colors.yellow, 117 | v = colors.blue, 118 | [""] = colors.blue, 119 | V = colors.blue, 120 | c = colors.magenta, 121 | no = colors.red, 122 | s = colors.orange, 123 | S = colors.orange, 124 | [""] = colors.orange, 125 | ic = colors.yellow, 126 | R = colors.purple, 127 | Rv = colors.purple, 128 | cv = colors.red, 129 | ce = colors.red, 130 | r = colors.cyan, 131 | rm = colors.cyan, 132 | ["r?"] = colors.cyan, 133 | ["!"] = colors.red, 134 | t = colors.red, 135 | _LineLeap = colors.red, 136 | }, 137 | is_line_leap = false, 138 | } 139 | 140 | insert_left({ 141 | ViModeIcon = { 142 | provider = function() 143 | -- auto change color according the vim mode 144 | local mode = vim.fn.mode() 145 | if vim_mode.is_line_leap then 146 | mode = "_LineLeap" 147 | end 148 | vim.api.nvim_set_hl(0, "GalaxyViMode", { bg = vim_mode.color[mode], fg = colors.black }) 149 | return " " .. vim_mode.alias[mode] .. " " 150 | end, 151 | highlight = "GalaxyViMode", 152 | }, 153 | }) 154 | 155 | local gid = vim.api.nvim_create_augroup("LineLeapStatus", { clear = true }) 156 | vim.api.nvim_create_autocmd("User", { 157 | pattern = "LeapEnter", 158 | group = gid, 159 | callback = function() 160 | vim_mode.is_line_leap = true 161 | end, 162 | }) 163 | vim.api.nvim_create_autocmd("User", { 164 | pattern = "LeapLeave", 165 | group = gid, 166 | callback = function() 167 | vim_mode.is_line_leap = false 168 | end, 169 | }) 170 | 171 | insert_space_on_left() 172 | 173 | insert_left({ 174 | DiagnosticError = { 175 | provider = "DiagnosticError", 176 | icon = "  ", 177 | highlight = { colors.red, colors.bg }, 178 | }, 179 | }) 180 | insert_left({ 181 | DiagnosticWarn = { 182 | provider = "DiagnosticWarn", 183 | icon = "  ", 184 | highlight = { colors.yellow, colors.bg }, 185 | }, 186 | }) 187 | insert_left({ 188 | DiagnosticHint = { 189 | provider = "DiagnosticHint", 190 | icon = "  ", 191 | highlight = { colors.dimblue, colors.bg }, 192 | }, 193 | }) 194 | insert_left({ 195 | DiagnosticInfo = { 196 | provider = "DiagnosticInfo", 197 | icon = "  ", 198 | highlight = { colors.dimblue, colors.bg }, 199 | }, 200 | }) 201 | 202 | insert_space_on_left() 203 | 204 | insert_left({ 205 | GetLspClient = { 206 | provider = function() 207 | local ft = vim.opt_local.filetype:get() 208 | local client = require("galaxyline.provider_lsp").get_lsp_client() 209 | if client == "No Active Lsp" then 210 | return ft 211 | end 212 | return ft .. ":(" .. client .. ")" 213 | end, 214 | highlight = { 215 | colors.lightgrey, 216 | colors.bg, 217 | }, 218 | }, 219 | }) 220 | 221 | insert_space_on_right() 222 | 223 | insert_right({ 224 | LineColumn = { 225 | provider = "LineColumn", 226 | highlight = { colors.lightgrey, colors.bg }, 227 | }, 228 | }) 229 | 230 | -- ============================= short line =============================== 231 | 232 | local BufferTypeMap = { 233 | ["DiffviewFiles"] = " Diff View", 234 | ["FTerm"] = "Terminal", 235 | ["Mundo"] = "Mundo History", 236 | ["MundoDiff"] = "Mundo Diff", 237 | ["NeogitCommitMessage"] = " Neogit Commit", 238 | ["NeogitPopup"] = " Neogit Popup", 239 | ["NeogitStatus"] = " Neogit Status", 240 | ["NvimTree"] = " Tree", 241 | ["dap-repl"] = " Dap REPL", 242 | ["dapui_breakpoints"] = " Dap Breakpoints", 243 | ["dapui_scopes"] = "󱄑 Dap Scope", 244 | ["dapui_stacks"] = " Dap Stacks", 245 | ["dapui_watches"] = " Dap Watch", 246 | ["fern"] = " Fern FM", 247 | ["neo-tree"] = "󰙅 NeoTree", 248 | ["fugitive"] = " Fugitive", 249 | ["floggraph"] = " Git Log", 250 | ["fugitiveblame"] = " Fugitive Blame", 251 | ["git"] = " Git", 252 | ["help"] = "󰞋 Help", 253 | ["minimap"] = "Minimap", 254 | ["neoterm"] = " NeoTerm", 255 | ["qf"] = " Quick Fix", 256 | ["quickfix"] = " Quick Fix", 257 | ["tabman"] = "Tab Manager", 258 | ["tagbar"] = "Tagbar", 259 | ["toggleterm"] = " ToggleTerm", 260 | ["Trouble"] = " Diagnostic", 261 | ["neo-term"] = " NeoTerm", 262 | ["noice"] = " noice", 263 | ["TelescopePrompt"] = " Telescope", 264 | } 265 | 266 | gl.short_line_list = vim.tbl_keys(BufferTypeMap) 267 | 268 | require("galaxyline").section.short_line_left = { 269 | { 270 | ShortLineLeftBufferType = { 271 | highlight = { colors.lightgrey, colors.bg }, 272 | provider = function() 273 | local name = BufferTypeMap[vim.bo.filetype] 274 | return string.format("▊ %s", name) 275 | end, 276 | }, 277 | }, 278 | { 279 | WinSeparator = { 280 | highlight = { colors.bg, colors.bg }, 281 | provider = function() 282 | return " " 283 | end, 284 | }, 285 | }, 286 | } 287 | 288 | require("galaxyline").load_galaxyline() 289 | -------------------------------------------------------------------------------- /nix/mkTreesitter.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | nodejs, 5 | tree-sitter, 6 | fetchNvimTsLockFile, 7 | fetchFromGitHub, 8 | runCommand, 9 | fetchurl, 10 | neovim, 11 | }: 12 | 13 | { 14 | name, 15 | hash, 16 | needs_generate ? false, 17 | srcRoot ? null, 18 | }: 19 | let 20 | # Get parser information from nvim-treesitter's lockfile.json 21 | parsers-info = lib.importJSON "${fetchNvimTsLockFile}"; 22 | 23 | url = parsers-info.${name}.url; 24 | rev = parsers-info.${name}.revision; 25 | shortrev = builtins.substring 0 7 rev; 26 | src = fetchurl { 27 | name = "tree-sitter-${name}-${shortrev}-src.tar.gz"; 28 | url = "${url}/archive/${rev}.tar.gz"; 29 | 30 | inherit hash; 31 | }; 32 | version = "unstable-${shortrev}"; 33 | in 34 | stdenv.mkDerivation { 35 | pname = "tree-sitter-${name}"; 36 | inherit src version; 37 | 38 | nativeBuildInputs = lib.optionals needs_generate [ 39 | nodejs 40 | tree-sitter 41 | ]; 42 | 43 | CFLAGS = [ 44 | "-Isrc" 45 | "-O2" 46 | ]; 47 | CXXFLAGS = [ 48 | "-Isrc" 49 | "-O2" 50 | ]; 51 | 52 | stripDebugList = [ "parser" ]; 53 | 54 | configurePhase = 55 | lib.optionalString (srcRoot != null) '' 56 | cd ${srcRoot} 57 | '' 58 | + lib.optionalString needs_generate '' 59 | tree-sitter generate 60 | ''; 61 | 62 | buildPhase = '' 63 | runHook preBuild 64 | if [[ -e src/scanner.cc ]]; then 65 | $CXX -fPIC -c src/scanner.cc -o scanner.o $CXXFLAGS 66 | elif [[ -e src/scanner.c ]]; then 67 | $CC -fPIC -c src/scanner.c -o scanner.o $CFLAGS 68 | fi 69 | $CC -fPIC -c src/parser.c -o parser.o $CFLAGS 70 | rm -rf parser 71 | $CXX -shared -o parser *.o 72 | runHook postBuild 73 | ''; 74 | 75 | installPhase = '' 76 | runHook preInstall 77 | mkdir -p $out/parser 78 | mv parser $out/parser/${name}.so 79 | 80 | mkdir -p $out/dist 81 | echo "parser-rev: ${rev}" > "$out/dist/${name}-version.txt" 82 | runHook postInstall 83 | ''; 84 | } 85 | -------------------------------------------------------------------------------- /nix/nvfetcher.toml: -------------------------------------------------------------------------------- 1 | [neovim-nightly] 2 | # Use the nightly tag of neovim repo 3 | src.cmd = "echo nightly" 4 | # How to fetch source 5 | fetch.github = "neovim/neovim" 6 | # Re-evaluate nix src everytime is required because nvchecker 7 | # will not update src branch when include_regex is unchanged. 8 | # However our source update machanism is tricky: 9 | # it relies on neovim/neovim force pushed nightly tag. 10 | fetch.force = true 11 | -------------------------------------------------------------------------------- /nix/nvim-treesitter-lock-file.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenvNoCC, 3 | fetchFromGitHub, 4 | neovim, 5 | }: 6 | 7 | let 8 | rev = with builtins; (fromJSON (readFile ../lazy-lock.json))."nvim-treesitter".commit; 9 | in 10 | stdenvNoCC.mkDerivation { 11 | name = "nvim-treesitter-lock-file-${rev}"; 12 | 13 | src = fetchFromGitHub { 14 | owner = "nvim-treesitter"; 15 | repo = "nvim-treesitter"; 16 | inherit rev; 17 | hash = "sha256-CVs9FTdg3oKtRjz2YqwkMr0W5qYLGfVyxyhE3qnGYbI="; 18 | }; 19 | 20 | nativeBuildInputs = [ neovim ]; 21 | 22 | buildPhase = '' 23 | cat < $out/${passthru.scriptPath} 20 | ''; 21 | } 22 | -------------------------------------------------------------------------------- /nvfetcher.toml: -------------------------------------------------------------------------------- 1 | [nixpkgs] 2 | src.git = "https://github.com/NixOS/nixpkgs.git" 3 | src.branch = "nixpkgs-unstable" 4 | fetch.tarball = "https://github.com/NixOS/nixpkgs/archive/$ver.tar.gz" 5 | 6 | [flake-utils] 7 | src.git = "https://github.com/numtide/flake-utils" 8 | fetch.tarball = "https://github.com/numtide/flake-utils/archive/$ver.tar.gz" 9 | 10 | [treefmt-nix] 11 | src.git = "https://github.com/numtide/treefmt-nix" 12 | fetch.tarball = "https://github.com/numtide/treefmt-nix/archive/$ver.tar.gz" 13 | -------------------------------------------------------------------------------- /overlay.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | mkTreesitter = final.callPackage ./nix/mkTreesitter.nix { }; 3 | fetchNvimTsLockFile = final.callPackage ./nix/nvim-treesitter-lock-file.nix { }; 4 | generate-nvim-treesitter-parsers = final.callPackage ./nix/nvim-treesitter-parsers.nix { }; 5 | 6 | treesitter-plugin-nightly = final.generate-nvim-treesitter-parsers [ 7 | { 8 | name = "bash"; 9 | hash = "sha256-aYOHtNMKMmctxI1q9CGmid17kUHSWWOActiMlSRVmc0="; 10 | } 11 | { 12 | name = "c"; 13 | hash = "sha256-t5zse6CwEz99H0BjQLKURmr1FMPhoEJVXtDMjVzsXSk="; 14 | } 15 | { 16 | name = "cpp"; 17 | hash = "sha256-gVS1uEK3pB+Izmgxc41nQ69i5MhVmM+dL4A4Tw81a+A="; 18 | } 19 | { 20 | name = "css"; 21 | hash = "sha256-gLLd4X3sGo+dzwa+sMouT4GJIsAv0x4vxxjKQbJQrxs="; 22 | } 23 | { 24 | name = "comment"; 25 | hash = "sha256-XSkreGkg8yhTDPBPU2yZ8apXcEbNJ0csjv5xnp9vvwQ="; 26 | } 27 | { 28 | name = "diff"; 29 | hash = "sha256-Q61DD6CX81M3npBflPE5P3glMdfCNB877juXFgKqu7Q="; 30 | } 31 | { 32 | name = "firrtl"; 33 | hash = "sha256-xrh8XlgcFz+Z1Rh7z1KZWV26RE65hVtIKjw9XPZaXuA="; 34 | } 35 | { 36 | name = "gitcommit"; 37 | hash = "sha256-pthd5ATiFnrSwY7OCgK5SSaj5PII1y+sbq3VL572OZg="; 38 | } 39 | { 40 | name = "haskell"; 41 | hash = "sha256-R9w8P29Heh0JtTT534e++Gpa315XN92hlQw2A8pRTpI="; 42 | } 43 | { 44 | name = "javascript"; 45 | hash = "sha256-SnIKLaKCIflGh4Pie+pMG6CYPxiEe8cu6juMcBhfJpg="; 46 | } 47 | { 48 | name = "typescript"; 49 | hash = "sha256-ls5NG1E3Z9QUvMpAjv2bSYeRYszuzb7XmojorSGE84U="; 50 | srcRoot = "typescript"; 51 | } 52 | { 53 | name = "tsx"; 54 | hash = "sha256-ls5NG1E3Z9QUvMpAjv2bSYeRYszuzb7XmojorSGE84U="; 55 | srcRoot = "tsx"; 56 | } 57 | { 58 | name = "typst"; 59 | hash = "sha256-BnSyu5q5IPf6g/+2pCoyDfFLeD+8fKvSXXFQOGXnzUs="; 60 | } 61 | { 62 | name = "llvm"; 63 | hash = "sha256-3/WPq64L+L0ewbrbvihkeuLOCoS7XhiKQnFIwS3i4HY="; 64 | } 65 | { 66 | name = "lua"; 67 | hash = "sha256-0gK6jswRs0lMIuGGgRwFnQAjZH3xSmATzC1cERLG000="; 68 | } 69 | { 70 | name = "ocaml"; 71 | hash = "sha256-l8k6+QLuXplP09aNzJyzkvdThlduJd7wskGCZ9qN2gs="; 72 | srcRoot = "grammars/ocaml"; 73 | } 74 | { 75 | name = "ocaml_interface"; 76 | hash = "sha256-l8k6+QLuXplP09aNzJyzkvdThlduJd7wskGCZ9qN2gs="; 77 | srcRoot = "grammars/interface"; 78 | } 79 | { 80 | name = "regex"; 81 | hash = "sha256-Os29dXqV12QcgrEjj+to55cprPUmxxYXW0rBjkb2ETw="; 82 | } 83 | { 84 | name = "ruby"; 85 | hash = "sha256-jsEbPD+PIcr281nqxtonYYID/SadnSlARUpbhVy3GAM="; 86 | } 87 | { 88 | name = "python"; 89 | hash = "sha256-MF7HdaUCl2r1gepj/+OeHW8WYXGRMdsSBLtxgto4ZEI="; 90 | } 91 | { 92 | name = "rust"; 93 | hash = "sha256-U2Viwf80W7UeMViQPpr8v16g9JY6N1mP4ezYq0cYpJc="; 94 | } 95 | { 96 | name = "proto"; 97 | hash = "sha256-eDnzT35wGxFzhcvy61d+1VG8ObB999mcakG3NNlrcck="; 98 | } 99 | { 100 | name = "scala"; 101 | hash = "sha256-iDxcht6pRtJc/MTg1CbF5x36pdZVgtZqWQCDigO4ymk="; 102 | } 103 | { 104 | name = "nix"; 105 | hash = "sha256-ZReufsys08Xh7BQFhYOc7FLtz9P1HUcUP5VD4pk5hUM="; 106 | } 107 | { 108 | name = "vimdoc"; 109 | hash = "sha256-zCEusqf9IKsfp1nUSu6CPQEOs+A9bOQk9i++cAiQy8o="; 110 | } 111 | { 112 | name = "query"; 113 | hash = "sha256-ZLbsbuf+8kikkdsiVRmkLBDBKYwLonJtjKtojpAHzRg="; 114 | } 115 | { 116 | name = "markdown"; 117 | hash = "sha256-T6RAgjmBVn0uSG9KG4XBZ4Gt+YPAZqIhac/NcnPGebM="; 118 | srcRoot = "tree-sitter-markdown"; 119 | } 120 | { 121 | name = "markdown_inline"; 122 | hash = "sha256-T6RAgjmBVn0uSG9KG4XBZ4Gt+YPAZqIhac/NcnPGebM="; 123 | srcRoot = "tree-sitter-markdown-inline"; 124 | } 125 | { 126 | name = "mlir"; 127 | hash = "sha256-sXYSc5+yD3odBVJQG0JTK9Nihe13oxSox6kzllq2jss="; 128 | needs_generate = true; 129 | } 130 | { 131 | name = "yaml"; 132 | hash = "sha256-FMTYaOpWez3Tr3ojFsh9XjE62F9h+6TKewnGGd8zv0I="; 133 | } 134 | { 135 | name = "zig"; 136 | hash = "sha256-x69bGpkvyv/fUKEamXT7+PCdIMTZ70IkWskMFS3TqFo="; 137 | } 138 | ]; 139 | 140 | neovim-nightly-bin = final.neovim-unwrapped.overrideAttrs { 141 | # Disable default treesitter plugins, they are outdated 142 | treesitter-parsers = { }; 143 | }; 144 | neovim-nightly = final.wrapNeovim final.neovim-nightly-bin { 145 | extraMakeWrapperArgs = '''--add-flags' '--cmd "set rtp^=${final.treesitter-plugin-nightly}"' ''; 146 | }; 147 | 148 | ghc-for-ts-plugins = final.haskellPackages.ghcWithPackages ( 149 | pkgs: with pkgs; [ 150 | aeson 151 | turtle 152 | ] 153 | ); 154 | } 155 | -------------------------------------------------------------------------------- /syntax/llvm.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: llvm 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | " Version: $Revision$ 5 | 6 | if version < 600 7 | syntax clear 8 | elseif exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | syn case match 13 | 14 | " Types. 15 | " Types also include struct, array, vector, etc. but these don't 16 | " benefit as much from having dedicated highlighting rules. 17 | syn keyword llvmType void half bfloat float double x86_fp80 fp128 ppc_fp128 18 | syn keyword llvmType label metadata x86_mmx x86_amx 19 | syn keyword llvmType type label opaque token ptr 20 | syn match llvmType /\/ 21 | 22 | " Instructions. 23 | " The true and false tokens can be used for comparison opcodes, but it's 24 | " much more common for these tokens to be used for boolean constants. 25 | syn keyword llvmStatement add addrspacecast alloca and arcp ashr atomicrmw 26 | syn keyword llvmStatement bitcast br catchpad catchswitch catchret call callbr 27 | syn keyword llvmStatement cleanuppad cleanupret cmpxchg eq exact extractelement 28 | syn keyword llvmStatement extractvalue fadd fast fcmp fdiv fence fmul fneg fpext 29 | syn keyword llvmStatement fptosi fptoui fptrunc free freeze frem fsub 30 | syn keyword llvmStatement getelementptr icmp inbounds indirectbr insertelement 31 | syn keyword llvmStatement insertvalue inttoptr invoke landingpad load lshr 32 | syn keyword llvmStatement malloc max min mul nand ne ninf nnan nsw nsz nuw oeq 33 | syn keyword llvmStatement oge ogt ole olt one or ord phi ptrtoint resume ret 34 | syn keyword llvmStatement sdiv select sext sge sgt shl shufflevector sitofp 35 | syn keyword llvmStatement sle slt srem store sub switch trunc udiv ueq uge ugt 36 | syn keyword llvmStatement uitofp ule ult umax umin une uno unreachable unwind 37 | syn keyword llvmStatement urem va_arg xchg xor zext 38 | 39 | " Keywords. 40 | syn keyword llvmKeyword 41 | \ acq_rel 42 | \ acquire 43 | \ addrspace 44 | \ alias 45 | \ align 46 | \ alignstack 47 | \ allocsize 48 | \ alwaysinline 49 | \ appending 50 | \ argmemonly 51 | \ arm_aapcs_vfpcc 52 | \ arm_aapcscc 53 | \ arm_apcscc 54 | \ asm 55 | \ atomic 56 | \ available_externally 57 | \ blockaddress 58 | \ builtin 59 | \ byref 60 | \ byval 61 | \ c 62 | \ caller 63 | \ catch 64 | \ cc 65 | \ ccc 66 | \ cleanup 67 | \ cold 68 | \ coldcc 69 | \ comdat 70 | \ common 71 | \ constant 72 | \ convergent 73 | \ datalayout 74 | \ declare 75 | \ default 76 | \ define 77 | \ deplibs 78 | \ dereferenceable 79 | \ dereferenceable_or_null 80 | \ distinct 81 | \ dllexport 82 | \ dllimport 83 | \ dso_local 84 | \ dso_preemptable 85 | \ except 86 | \ extern_weak 87 | \ external 88 | \ externally_initialized 89 | \ fastcc 90 | \ filter 91 | \ from 92 | \ gc 93 | \ global 94 | \ hhvm_ccc 95 | \ hhvmcc 96 | \ hidden 97 | \ hot 98 | \ immarg 99 | \ inaccessiblemem_or_argmemonly 100 | \ inaccessiblememonly 101 | \ inalloca 102 | \ initialexec 103 | \ inlinehint 104 | \ inreg 105 | \ intel_ocl_bicc 106 | \ inteldialect 107 | \ internal 108 | \ jumptable 109 | \ linkonce 110 | \ linkonce_odr 111 | \ local_unnamed_addr 112 | \ localdynamic 113 | \ localexec 114 | \ minsize 115 | \ module 116 | \ monotonic 117 | \ msp430_intrcc 118 | \ mustprogress 119 | \ musttail 120 | \ naked 121 | \ nest 122 | \ noalias 123 | \ nobuiltin 124 | \ nocallback 125 | \ nocapture 126 | \ nocf_check 127 | \ no_cfi 128 | \ noduplicate 129 | \ nofree 130 | \ noimplicitfloat 131 | \ noinline 132 | \ nomerge 133 | \ nonlazybind 134 | \ nonnull 135 | \ noprofile 136 | \ norecurse 137 | \ noredzone 138 | \ noreturn 139 | \ nosync 140 | \ noundef 141 | \ nounwind 142 | \ nosanitize_bounds 143 | \ nosanitize_coverage 144 | \ null_pointer_is_valid 145 | \ optforfuzzing 146 | \ optnone 147 | \ optsize 148 | \ personality 149 | \ preallocated 150 | \ private 151 | \ protected 152 | \ ptx_device 153 | \ ptx_kernel 154 | \ readnone 155 | \ readonly 156 | \ release 157 | \ returned 158 | \ returns_twice 159 | \ safestack 160 | \ sanitize_address 161 | \ sanitize_hwaddress 162 | \ sanitize_memory 163 | \ sanitize_memtag 164 | \ sanitize_thread 165 | \ section 166 | \ seq_cst 167 | \ shadowcallstack 168 | \ sideeffect 169 | \ signext 170 | \ source_filename 171 | \ speculatable 172 | \ speculative_load_hardening 173 | \ spir_func 174 | \ spir_kernel 175 | \ sret 176 | \ ssp 177 | \ sspreq 178 | \ sspstrong 179 | \ strictfp 180 | \ swiftcc 181 | \ swifterror 182 | \ swifttailcc 183 | \ swiftself 184 | \ syncscope 185 | \ tail 186 | \ tailcc 187 | \ target 188 | \ thread_local 189 | \ to 190 | \ triple 191 | \ unnamed_addr 192 | \ unordered 193 | \ uselistorder 194 | \ uselistorder_bb 195 | \ uwtable 196 | \ volatile 197 | \ weak 198 | \ weak_odr 199 | \ willreturn 200 | \ win64cc 201 | \ within 202 | \ writeonly 203 | \ x86_64_sysvcc 204 | \ x86_fastcallcc 205 | \ x86_stdcallcc 206 | \ x86_thiscallcc 207 | \ zeroext 208 | 209 | " Obsolete keywords. 210 | syn keyword llvmError getresult begin end 211 | 212 | " Misc syntax. 213 | syn match llvmNoName /[%@!]\d\+\>/ 214 | syn match llvmNumber /-\?\<\d\+\>/ 215 | syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/ 216 | syn match llvmFloat /\<0x\x\+\>/ 217 | syn keyword llvmBoolean true false 218 | syn keyword llvmConstant zeroinitializer undef null none poison vscale 219 | syn match llvmComment /;.*$/ 220 | syn region llvmString start=/"/ skip=/\\"/ end=/"/ 221 | syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/ 222 | syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/ 223 | 224 | " Named metadata and specialized metadata keywords. 225 | syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/ 226 | syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/ 227 | syn match llvmType /!\zs\a\+\ze\s*(/ 228 | syn match llvmConstant /\/ 229 | syn match llvmConstant /\/ 230 | syn match llvmConstant /\/ 231 | syn match llvmConstant /\/ 232 | syn match llvmConstant /\/ 233 | syn match llvmConstant /\/ 234 | 235 | " Syntax-highlight lit test commands and bug numbers. 236 | syn match llvmSpecialComment /;\s*PR\d*\s*$/ 237 | syn match llvmSpecialComment /;\s*REQUIRES:.*$/ 238 | syn match llvmSpecialComment /;\s*RUN:.*$/ 239 | syn match llvmSpecialComment /;\s*ALLOW_RETRIES:.*$/ 240 | syn match llvmSpecialComment /;\s*CHECK:.*$/ 241 | syn match llvmSpecialComment /;\s*CHECK-EMPTY:\s*$/ 242 | syn match llvmSpecialComment /\v;\s*CHECK-(NEXT|NOT|DAG|SAME|LABEL|COUNT-\d+):.*$/ 243 | syn match llvmSpecialComment /;\s*XFAIL:.*$/ 244 | 245 | if version >= 508 || !exists("did_c_syn_inits") 246 | if version < 508 247 | let did_c_syn_inits = 1 248 | command -nargs=+ HiLink hi link 249 | else 250 | command -nargs=+ HiLink hi def link 251 | endif 252 | 253 | HiLink llvmType Type 254 | HiLink llvmStatement Statement 255 | HiLink llvmNumber Number 256 | HiLink llvmComment Comment 257 | HiLink llvmString String 258 | HiLink llvmLabel Label 259 | HiLink llvmKeyword Keyword 260 | HiLink llvmBoolean Boolean 261 | HiLink llvmFloat Float 262 | HiLink llvmNoName Identifier 263 | HiLink llvmConstant Constant 264 | HiLink llvmSpecialComment SpecialComment 265 | HiLink llvmError Error 266 | HiLink llvmIdentifier Identifier 267 | 268 | delcommand HiLink 269 | endif 270 | 271 | let b:current_syntax = "llvm" 272 | -------------------------------------------------------------------------------- /syntax/machine-ir.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: mir 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | " Version: $Revision$ 5 | 6 | syn case match 7 | 8 | " FIXME: MIR doesn't actually match LLVM IR. Stop including it all as a 9 | " fallback once enough is implemented. 10 | " See the MIR LangRef: https://llvm.org/docs/MIRLangRef.html 11 | unlet b:current_syntax " Unlet so that the LLVM syntax will load 12 | runtime! syntax/llvm.vim 13 | unlet b:current_syntax 14 | 15 | syn match mirType /\<[sp]\d\+\>/ 16 | 17 | " Opcodes. Matching instead of listing them because individual targets can add 18 | " these. FIXME: Maybe use some more context to make this more accurate? 19 | syn match mirStatement /\<[A-Z][A-Za-z0-9_]*\>/ 20 | 21 | syn match mirPReg /$[-a-zA-Z$._][-a-zA-Z$._0-9]*/ 22 | 23 | if version >= 508 || !exists("did_c_syn_inits") 24 | if version < 508 25 | let did_c_syn_inits = 1 26 | command -nargs=+ HiLink hi link 27 | else 28 | command -nargs=+ HiLink hi def link 29 | endif 30 | 31 | HiLink mirType Type 32 | HiLink mirStatement Statement 33 | HiLink mirPReg Identifier 34 | 35 | delcommand HiLink 36 | endif 37 | 38 | let b:current_syntax = "mir" 39 | -------------------------------------------------------------------------------- /syntax/mir.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: mir 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | " Version: $Revision$ 5 | 6 | if version < 600 7 | syntax clear 8 | elseif exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | syn case match 13 | 14 | " MIR is embedded in a yaml container, so we load all of the yaml syntax. 15 | runtime! syntax/yaml.vim 16 | unlet b:current_syntax 17 | 18 | " The first document of a file is allowed to contain an LLVM IR module inside 19 | " a top-level yaml block string. 20 | syntax include @LLVM syntax/llvm.vim 21 | " FIXME: This should only be allowed for the first document of the file 22 | syntax region llvm start=/\(^---\s*|\)\@<=/ end=/\(^\.\.\.\)\@=/ contains=@LLVM 23 | 24 | " The `body:` field of a document contains the MIR dump of the function 25 | syntax include @MIR syntax/machine-ir.vim 26 | syntax region mir start=/\(^body:\s*|\)\@<=/ end=/\(^[^[:space:]]\)\@=/ contains=@MIR 27 | 28 | " Syntax-highlight lit test commands and bug numbers. 29 | syn match mirSpecialComment /#\s*PR\d*\s*$/ 30 | syn match mirSpecialComment /#\s*REQUIRES:.*$/ 31 | syn match mirSpecialComment /#\s*RUN:.*$/ 32 | syn match mirSpecialComment /#\s*ALLOW_RETRIES:.*$/ 33 | syn match mirSpecialComment /#\s*CHECK:.*$/ 34 | syn match mirSpecialComment "\v#\s*CHECK-(NEXT|NOT|DAG|SAME|LABEL):.*$" 35 | syn match mirSpecialComment /#\s*XFAIL:.*$/ 36 | 37 | if version >= 508 || !exists("did_c_syn_inits") 38 | if version < 508 39 | let did_c_syn_inits = 1 40 | command -nargs=+ HiLink hi link 41 | else 42 | command -nargs=+ HiLink hi def link 43 | endif 44 | 45 | HiLink mirSpecialComment SpecialComment 46 | endif 47 | 48 | let b:current_syntax = "mir" 49 | -------------------------------------------------------------------------------- /syntax/mlir.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: mlir 3 | " Maintainer: The MLIR team, http://github.com/tensorflow/mlir/ 4 | " Version: $Revision$ 5 | " Some parts adapted from the LLVM vim syntax file. 6 | 7 | if version < 600 8 | syntax clear 9 | elseif exists("b:current_syntax") 10 | finish 11 | endif 12 | 13 | syn case match 14 | 15 | " Types. 16 | " 17 | syn keyword mlirType index f16 f32 f64 bf16 18 | " Signless integer types. 19 | syn match mlirType /\/ 20 | " Unsigned integer types. 21 | syn match mlirType /\/ 22 | " Signed integer types. 23 | syn match mlirType /\/ 24 | 25 | " Elemental types inside memref, tensor, or vector types. 26 | syn match mlirType /x\s*\zs\(bf16|f16\|f32\|f64\|i\d\+\|ui\d\+\|si\d\+\)/ 27 | 28 | " Shaped types. 29 | syn match mlirType /\/ 30 | syn match mlirType /\/ 31 | syn match mlirType /\/ 32 | 33 | " vector types inside memref or tensor. 34 | syn match mlirType /x\s*\zsvector/ 35 | 36 | " Operations. 37 | " TODO: this list is not exhaustive. 38 | syn keyword mlirOps alloc alloca addf addi and call call_indirect cmpf cmpi 39 | syn keyword mlirOps constant dealloc divf dma_start dma_wait dim exp 40 | syn keyword mlirOps getTensor index_cast load log memref_cast 41 | syn keyword mlirOps memref_shape_cast mulf muli negf powf prefetch rsqrt sitofp 42 | syn keyword mlirOps splat store select sqrt subf subi subview tanh 43 | syn keyword mlirOps view 44 | 45 | " Math ops. 46 | syn match mlirOps /\/ 47 | 48 | " Affine ops. 49 | syn match mlirOps /\/ 50 | syn match mlirOps /\/ 51 | syn match mlirOps /\/ 52 | syn match mlirOps /\/ 53 | syn match mlirOps /\/ 54 | syn match mlirOps /\/ 55 | syn match mlirOps /\/ 56 | syn match mlirOps /\/ 57 | syn match mlirOps /\/ 58 | syn match mlirOps /\/ 59 | syn match mlirOps /\/ 60 | syn match mlirOps /\/ 61 | syn match mlirOps /\/ 62 | 63 | " TODO: dialect name prefixed ops (llvm or std). 64 | 65 | " Keywords. 66 | syn keyword mlirKeyword 67 | \ affine_map 68 | \ affine_set 69 | \ dense 70 | \ else 71 | \ func 72 | \ module 73 | \ return 74 | \ step 75 | \ to 76 | 77 | " Misc syntax. 78 | 79 | syn match mlirNumber /-\?\<\d\+\>/ 80 | " Match numbers even in shaped types. 81 | syn match mlirNumber /-\?\<\d\+\ze\s*x/ 82 | syn match mlirNumber /x\s*\zs-\?\d\+\ze\s*x/ 83 | 84 | syn match mlirFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/ 85 | syn match mlirFloat /\<0x\x\+\>/ 86 | syn keyword mlirBoolean true false 87 | " Spell checking is enabled only in comments by default. 88 | syn match mlirComment /\/\/.*$/ contains=@Spell 89 | syn region mlirString start=/"/ skip=/\\"/ end=/"/ 90 | syn match mlirLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/ 91 | " Prefixed identifiers usually used for ssa values and symbols. 92 | syn match mlirIdentifier /[%@][a-zA-Z$._-][a-zA-Z0-9$._-]*/ 93 | syn match mlirIdentifier /[%@]\d\+\>/ 94 | " Prefixed identifiers usually used for blocks. 95 | syn match mlirBlockIdentifier /\^[a-zA-Z$._-][a-zA-Z0-9$._-]*/ 96 | syn match mlirBlockIdentifier /\^\d\+\>/ 97 | " Prefixed identifiers usually used for types. 98 | syn match mlirTypeIdentifier /![a-zA-Z$._-][a-zA-Z0-9$._-]*/ 99 | syn match mlirTypeIdentifier /!\d\+\>/ 100 | " Prefixed identifiers usually used for attribute aliases and result numbers. 101 | syn match mlirAttrIdentifier /#[a-zA-Z$._-][a-zA-Z0-9$._-]*/ 102 | syn match mlirAttrIdentifier /#\d\+\>/ 103 | 104 | " Syntax-highlight lit test commands and bug numbers. 105 | syn match mlirSpecialComment /\/\/\s*RUN:.*$/ 106 | syn match mlirSpecialComment /\/\/\s*CHECK:.*$/ 107 | syn match mlirSpecialComment "\v\/\/\s*CHECK-(NEXT|NOT|DAG|SAME|LABEL):.*$" 108 | syn match mlirSpecialComment /\/\/\s*expected-error.*$/ 109 | syn match mlirSpecialComment /\/\/\s*expected-remark.*$/ 110 | syn match mlirSpecialComment /;\s*XFAIL:.*$/ 111 | syn match mlirSpecialComment /\/\/\s*PR\d*\s*$/ 112 | syn match mlirSpecialComment /\/\/\s*REQUIRES:.*$/ 113 | 114 | if version >= 508 || !exists("did_c_syn_inits") 115 | if version < 508 116 | let did_c_syn_inits = 1 117 | command -nargs=+ HiLink hi link 118 | else 119 | command -nargs=+ HiLink hi def link 120 | endif 121 | 122 | HiLink mlirType Type 123 | HiLink mlirOps Statement 124 | HiLink mlirNumber Number 125 | HiLink mlirComment Comment 126 | HiLink mlirString String 127 | HiLink mlirLabel Label 128 | HiLink mlirKeyword Keyword 129 | HiLink mlirBoolean Boolean 130 | HiLink mlirFloat Float 131 | HiLink mlirConstant Constant 132 | HiLink mlirSpecialComment SpecialComment 133 | HiLink mlirIdentifier Identifier 134 | HiLink mlirBlockIdentifier Label 135 | HiLink mlirTypeIdentifier Type 136 | HiLink mlirAttrIdentifier PreProc 137 | 138 | delcommand HiLink 139 | endif 140 | 141 | let b:current_syntax = "mlir" 142 | -------------------------------------------------------------------------------- /syntax/sail.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: Sail 3 | " Maintainer: Bill McSpadden (bill@riscv.org) 4 | " Last Update: 5 | " Built on verilog.vim from vim63 6 | 7 | " For version 5.x: Clear all syntax items 8 | " For version 6.x: Quit when a syntax file was already loaded 9 | if version < 600 10 | syntax clear 11 | elseif exists("b:current_syntax") 12 | finish 13 | endif 14 | 15 | " Set the local value of the 'iskeyword' option 16 | if version >= 600 17 | setlocal iskeyword=@,48-57,_,192-255 18 | else 19 | set iskeyword=@,48-57,_,192-255 20 | endif 21 | 22 | " Taken from the "The Sail instruction-set semantics specification language" July 15, 2021 23 | " Using sail-mode.el as a pattern. 24 | "syn keyword sailStatement foreach let val 25 | syntax keyword identifier val function type struct union enum let var if then by 26 | syntax keyword identifier else match in return register ref forall operator effect 27 | syntax keyword identifier overload cast sizeof constant constraint default assert newtype from 28 | syntax keyword identifier pure infixl infixr infix scattered end try catch and to 29 | syntax keyword identifier throw clause as repeat until while do foreach bitfield 30 | syntax keyword identifier mapping where with implicit 31 | 32 | syntax keyword sailKind Int Type Order Bool inc dec 33 | syntax keyword sailKind barr depend rreg wreg rmem rmemt wmv wmvt eamem wmem 34 | syntax keyword sailKind exmem undef unspec nondet escape configuration 35 | 36 | syntax keyword sailType vector bitvector int nat atom range unit bit real list bool string bits option 37 | syntax keyword sailType uint64_t int64_t bv_t mpz_t 38 | 39 | syntax keyword sailSpecial _prove _not_prove create kill convert undefined 40 | 41 | syntax match sailNumber "\<0b[0-1_]\+\>" 42 | syntax match sailNumber "\<0x[0-9a-fA-F_]\+\>" 43 | syntax match sailNumber "\<[-+]\?[0-9]\+\>" 44 | syntax match sailNumber "\<[+-]\=[0-9]\+\(\.[0-9]*\|\)\>" 45 | 46 | syntax region sailComment start="/\*" end="\*/" contains=sailTodo 47 | syntax match sailComment "//.*" contains=sailTodo 48 | syntax keyword sailTodo contained TODO FIXME XXX 49 | 50 | syntax match sailPragma "$[a-zA-Z0-9_]\+\>" 51 | 52 | syntax region sailString start=+"+ skip=+\\"+ end=+"+ contains=sailEscape 53 | syntax match sailEscape +\\[nt"\\]+ contained 54 | syntax match sailEscape "\\\o\o\=\o\=" contained 55 | 56 | syntax match sailConstant "\<[A-Z][A-Z0-9_]\+\>" 57 | 58 | syntax match sailPragma "$include .*" contains=sailFilename 59 | syntax region sailFilename start=+<+ end=+>+ contained 60 | 61 | 62 | if version >= 508 || !exists("did_sail_syn_inits") 63 | if version < 508 64 | let did_sail_syn_inits = 1 65 | command -nargs=+ HiLink hi link 66 | else 67 | command -nargs=+ HiLink hi def link 68 | endif 69 | HiLink sailNumber Number 70 | HiLink sailComment Comment 71 | HiLink sailGlobal Define 72 | HiLink sailPragma PreProc 73 | HiLink sailString String 74 | HiLink sailConstant Constant 75 | HiLink sailTodo Todo 76 | HiLink sailFilename String 77 | HiLink sailKind Type 78 | HiLink sailSpecial PreProc 79 | 80 | endif 81 | 82 | 83 | 84 | 85 | let b:current_syntax = "sail" 86 | 87 | " vim: ts=2 88 | -------------------------------------------------------------------------------- /syntax/tablegen.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: TableGen 3 | " Maintainer: The LLVM team, http://llvm.org/ 4 | " Version: $Revision$ 5 | 6 | if version < 600 7 | syntax clear 8 | elseif exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | " May be changed if you have a really slow machine 13 | syntax sync minlines=100 14 | 15 | syn case match 16 | 17 | syn keyword tgKeyword def let in code dag field include defm foreach defset defvar if then else 18 | syn keyword tgType class int string list bit bits multiclass 19 | 20 | syn match tgNumber /\<\d\+\>/ 21 | syn match tgNumber /\<\d\+\.\d*\>/ 22 | syn match tgNumber /\<0b[01]\+\>/ 23 | syn match tgNumber /\<0x[0-9a-fA-F]\+\>/ 24 | syn region tgString start=/"/ skip=/\\"/ end=/"/ oneline 25 | 26 | syn region tgCode start=/\[{/ end=/}\]/ 27 | 28 | syn keyword tgTodo contained TODO FIXME 29 | syn match tgComment /\/\/.*$/ contains=tgTodo 30 | " Handle correctly imbricated comment 31 | syn region tgComment2 matchgroup=tgComment2 start=+/\*+ end=+\*/+ contains=tgTodo,tgComment2 32 | 33 | if version >= 508 || !exists("did_c_syn_inits") 34 | if version < 508 35 | let did_c_syn_inits = 1 36 | command -nargs=+ HiLink hi link 37 | else 38 | command -nargs=+ HiLink hi def link 39 | endif 40 | 41 | HiLink tgKeyword Statement 42 | HiLink tgType Type 43 | HiLink tgNumber Number 44 | HiLink tgComment Comment 45 | HiLink tgComment2 Comment 46 | HiLink tgString String 47 | " May find a better Hilight group... 48 | HiLink tgCode Special 49 | HiLink tgTodo Todo 50 | 51 | delcommand HiLink 52 | endif 53 | 54 | let b:current_syntax = "tablegen" 55 | --------------------------------------------------------------------------------