commit 9c008088630b547e35acae5e678456d5f0447c24 Author: NotAShelf Date: Wed Feb 1 22:11:37 2023 +0300 dev: rebase on a less personalized neovim flake diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..4dd7870 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,17 @@ +name: "Pull request" +on: + pull_request: + push: + branches: + - main + workflow_dispatch: +jobs: + nix-flake-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v18 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + - run: nix flake check diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 0000000..ff3153c --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,34 @@ +name: Github Pages docs +on: + push: + branches: + - main + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: write + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Nix + uses: cachix/install-nix-action@v18 + - name: Build + run: | + nix build '.#docs-html' + cp -r result/share/doc/neovim-flake public + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./public diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..121ea04 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +.config diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9f3cbc3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b249b31 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# neovim-flake + +A highly configurable nix flake for neovim. + +Come join the Matrix room if you have any questions or need help: [#neovim-flake:matrix.org](https://matrix.to/#/#neovim-flake:matrix.org) + +## Documentation + +See the [neovim-flake Manual](https://jordanisaacs.github.io/neovim-flake/) for documentation, available options, and release notes. + +If you want to dive right into trying neovim-flake you can get a fully featured configuration with `nix` language support by running: + +``` +nix run github:jordanisaacs/neovim-flake +``` + +## Screenshot + +![screenshot](./screenshot.png) + +## Philosophy + +The philosophy behind this flake configuration is to allow for easily configurable and reproducible neovim environments. Enter a directory and have a ready to go neovim configuration that is the same on every machine. Whether you are a developer, writer, or live coder (see tidal cycles below!), quickly craft a config that suits every project's need. Think of it like a distribution of Neovim that takes advantage of pinning vim plugins and third party dependencies (such as tree-sitter grammars, language servers, and more). + +As a result, one should never get a broken config when setting options. If setting multiple options results in a broken neovim, file an issue! Each plugin knows when another plugin which allows for smart configuration of keybindings and automatic setup of things like completion sources and languages. + + +## Credit + +Originally based on Wil Taylor's amazing [neovim-flake](https://github.com/wiltaylor/neovim-flake) diff --git a/docs/custom-configs.adoc b/docs/custom-configs.adoc new file mode 100644 index 0000000..17994f7 --- /dev/null +++ b/docs/custom-configs.adoc @@ -0,0 +1,42 @@ +[[ch-custom-configuration]] +== Custom Configuration + +Custom configuration is done with the `neovimConfiguration` function. It takes in the configuration as a module. The output of the configuration function is an attrset. + +[source,nix] +---- +{ + options = "The options that were available to configure"; + config = "The outputted configuration"; + pkgs = "The package set used to evaluate the module"; + neovim = "The built neovim package"; +} +---- + +The following is an example of a barebones vim configuration with the default theme enabled. + +[source,nix] +---- +{ + inputs.neovim-flake.url = "github:jordanisaacs/neovim-flake"; + + outputs = {nixpkgs, neovim-flake, ...}: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + configModule = { + # Add any custom options (and feel free to upstream them!) + # options = ... + + config.vim.theme.enable = true; + }; + + customNeovim = neovim-flake.lib.neovimConfiguration { + modules = [configModule]; + inherit pkgs; + }; + in { + packages.${system}.neovim = customNeovim.neovim; + }; +} +---- + diff --git a/docs/default-configs.adoc b/docs/default-configs.adoc new file mode 100644 index 0000000..1a8f0f6 --- /dev/null +++ b/docs/default-configs.adoc @@ -0,0 +1,36 @@ +[[ch-default-configs]] +== Default Configs + +While you can configure neovim-flake yourself using the builder, here are a few default configurations you can use. + +[[sec-default-tidal]] +=== Tidal Cycles + +[source,console] +$ nix run github:jordanisaacs/neovim-flake#tidal file.tidal + +Utilizing https://github.com/tidalcycles/vim-tidal[vim-tidal] and mitchmindtree's fantastic https://github.com/mitchmindtree/tidalcycles.nix[tidalcycles.nix] start playing with tidal cycles in a single command. + +In your tidal file, type a cycle e.g. `d1 $ s "drum"` and then press _ctrl+enter_. Super collider with superdirt, and a modified GHCI with tidal will start up and begin playing. Note, you need jack enabled on your system. If you are using pipewire, its as easy as setting `services.pipewire.jack.enable = true`. + + +[[sec-default-nix]] +=== Nix + +[source,console] +$ nix run github:jordanisaacs/neovim-flake#nix test.nix + +Enables all the of neovim plugins, with language support for specifically Nix. This lets you see what a fully configured neovim setup looks like without downloading a whole bunch of language servers and associated tools. + +[[sec-default-maximal]] +=== Maximal + +[source,console] +$ nix shell github:jordanisaacs/neovim-flake#maximal test.nix + +It is the same fully configured neovim as with the <> config, but with every supported language enabled. + +[NOTE] +==== +Running the maximal config will download *a lot* of packages as it is downloading language servers, formatters, and more. +==== diff --git a/docs/default.nix b/docs/default.nix new file mode 100644 index 0000000..3b04302 --- /dev/null +++ b/docs/default.nix @@ -0,0 +1,54 @@ +{ + pkgs, + lib ? import ../modules/lib/stdlib-extended.nix pkgs.lib, + nmdSrc, +}: let + nmd = import nmdSrc {inherit lib pkgs;}; + scrubbedPkgsModule = { + imports = [ + { + _module.args = { + pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs); + }; + } + ]; + }; + + nvimModuleDocs = nmd.buildModulesDocs { + modules = + import ../modules/modules.nix { + inherit pkgs lib; + check = false; + } + ++ [scrubbedPkgsModule]; + moduleRootPaths = [./..]; + mkModuleUrl = path: "https://github.com/jordanisaacs/neovim-flake/blob/main/${path}#blob-path"; + channelName = "neovim-flake"; + docBook.id = "neovim-flake-options"; + }; + + docs = nmd.buildDocBookDocs { + pathName = "neovim-flake"; + projectName = "neovim-flake"; + modulesDocs = [nvimModuleDocs]; + documentsDirectory = ./.; + documentType = "book"; + chunkToc = '' + + + + + + + + + + + + ''; + }; +in { + options.json = nvimModuleDocs.json.override {path = "share/doc/neovim-flake/options.json";}; + manPages = docs.manPages; + manual = {inherit (docs) html htmlOpenTool;}; +} diff --git a/docs/languages.adoc b/docs/languages.adoc new file mode 100644 index 0000000..a14e35f --- /dev/null +++ b/docs/languages.adoc @@ -0,0 +1,71 @@ +[[ch-languages]] +== Language Support + +Language specific support combines some combination of language specific plugins, `treesitter` support, `nvim-lspconfig` langauge servers, and `null-ls` integration. This gets you capabilities ranging from autocompletion to formatting to diagnostics. The following languages have support beyond just `treesitter` highlighting. + +[[sec-languages-rust]] +=== Rust + +*LSP Server*: https://github.com/rust-analyzer/rust-analyzer[rust-analyzer] + +*Formatting*: Built into LSP, uses https://github.com/rust-lang/rustfmt[rustfmt] + +*Plugins*: See <> + +[[sec-languages-nix]] +=== Nix + +*LSP Server*: Choice between https://github.com/oxalica/nil[nil] and https://github.com/nix-community/rnix-lsp[rnix-lsp] + +*Formatting*: Choice between https://github.com/kamadorueda/alejandra[alejandra] and https://github.com/nix-community/nixpkgs-fmt[nixpkgs-fmt] + +[[sec-languages-sql]] +=== SQL + +*LSP Server*: https://github.com/lighttiger2505/sqls[sqls] + +*Formatting*: Disabled LSP formatting, instead using https://github.com/sqlfluff/sqlfluff[sqlfluff] + +*Linting*: https://github.com/sqlfluff/sqlfluff[sqlfluff] + +*Plugins*: See <> + +[[sec-languages-clang]] +=== C/C++ + +*LSP Server*: https://github.com/MaskRay/ccls[ccls] + +*Formatting*: Built into language server + +[[sec-languages-typescript]] +=== Typescript + +*LSP Server*: https://github.com/typescript-language-server/typescript-language-server[typescript-language-server] + +*Formatting*: Disabled LSP formatting, instead using https://github.com/prettier/prettier[prettier] + +*Linting*: https://github.com/prettier/prettier[eslint] + +[[sec-languages-python]] +=== Python + +*LSP Server*: https://github.com/microsoft/pyright[pyright] + +*Formatting*: https://github.com/psf/black[black] + +[[sec-languages-zig]] +=== Zig + +*LSP Server*: https://github.com/zigtools/zls[zls] + +*Formatting*: Built into LSP, uses `zig fmt`. + +[[sec-languages-markdown]] +=== Markdown + +*Plugins*: See <> + +[[sec-languages-html]] +=== HTML + +*Plugins*: See <> diff --git a/docs/man-configuration.xml b/docs/man-configuration.xml new file mode 100644 index 0000000..498c0a0 --- /dev/null +++ b/docs/man-configuration.xml @@ -0,0 +1,42 @@ + + + neovim-flake configuration + 5 + neovim-flake + + + + neovim configuration + neovim-flake configuration specification + + + Description + + Custom configuration is done with the neovim-flake.lib.neovimConfiguration function. It takes in the configuration as a module. + + neovim-flake.lib.neovimConfiguration { + inherit pkgs; + modules = [{config = xxx;}]; + }; + + The output of the configuration function is an attrset. + + + { + options = "The options that were available to configure"; + config = "The outputted configuration"; + pkgs = "The package set used to evaluate the module"; + neovim = "The built neovim package"; + } + + + + Options + + You can use the following options in your neovim configuration. + + + + diff --git a/docs/man-pages.xml b/docs/man-pages.xml new file mode 100644 index 0000000..669652e --- /dev/null +++ b/docs/man-pages.xml @@ -0,0 +1,13 @@ + + neovim-flake Reference Pages + + neovim-flake contributors + + 2021–2022 + neovim-flake contributors + + + + diff --git a/docs/manual.xml b/docs/manual.xml new file mode 100644 index 0000000..e961e1e --- /dev/null +++ b/docs/manual.xml @@ -0,0 +1,27 @@ + + + neovim-flake Manual + + + Preface + + If you encounter problems or want to discuss neovim-flake then join the Matrix room + #neovim-flake:matrix.org. + If your problem is caused by a bug in neovim-flake then it should be reported on the + neovim-flake issue tracker. + + + + + + + + Configuration Options + + + + diff --git a/docs/plugins.adoc b/docs/plugins.adoc new file mode 100644 index 0000000..b3a4839 --- /dev/null +++ b/docs/plugins.adoc @@ -0,0 +1,111 @@ +[[ch-plugins]] +== Plugins + +The following are the neovim plugins used within neovim-flake. Some plugins are explicitly enabled by the user, while others are enabled implicitly. + +[[sec-plugins-server]] +=== Language Server + +* https://github.com/neovim/nvim-lspconfig[nvim-lspconfig] common configurations for built-in language server +* https://github.com/jose-elias-alvarez/null-ls.nvim[null-ls.nvim] neovim as a language server to inject LSP diagnostics, code actions, etc. +* https://github.com/glepnir/lspsaga.nvim[lspsaga.nvim] useful UI and tools for lsp +* https://github.com/folke/trouble.nvim[trouble.nvim] pretty list of lsp data +* https://github.com/weilbith/nvim-code-action-menu[nvim-code-action-menu] a better code action menu with diff support +* https://github.com/ray-x/lsp_signature.nvim[lsp-signature] show function signatures as you type +* https://github.com/onsails/lspkind-nvim[lspkind-nvim] for pictograms in lsp (with support for nvim-cmp) + +[[sec-plugins-buffer]] +=== Buffers + +* https://github.com/akinsho/bufferline.nvim[nvim-bufferline-lua] a buffer line with tab integration +* https://github.com/famiu/bufdelete.nvim[bufdelete-nvim] delete buffers without losing window layout + +[[sec-plugins-statuslines]] +=== Statuslines + +* https://github.com/hoob3rt/lualine.nvim[lualine.nvim] statusline written in lua. + +[[sec-plugins-filetrees]] +=== Filetrees + +* https://github.com/kyazdani42/nvim-tree.lua[nvim-tree-lua] a file explorer tree written in lua. Using + +[[sec-plugins-git]] +=== Git + +* https://github.com/lewis6991/gitsigns.nvim[gitsigns.nvim] a variety of git decorations + +[[sec-plugins-treesitter]] +=== Treesitter + +* https://github.com/romgrk/nvim-treesitter-context[nvim-treesitter-context] a context bar using tree-sitter + +[[sec-plugins-visuals]] +=== Visuals + +* https://github.com/lukas-reineke/indent-blankline.nvim[indent-blankline] for indentation guides +* https://github.com/kyazdani42/nvim-web-devicons[nvim-web-devicons] Plugins and colors for icons. Requires patched font + +[[sec-plugins-utilities]] +=== Utilities + +* https://github.com/nvim-telescope/telescope.nvim[telescope] an extendable fuzzy finder of lists. Working ripgrep and fd +* https://github.com/folke/which-key.nvim[which-key] a popup that displays possible keybindings of command being typed + +[[sec-plugins-completions]] +=== Completions + +* https://github.com/hrsh7th/nvim-cmp[nvim-cmp] a completion engine that utilizes sources +** https://github.com/hrsh7th/cmp-buffer[cmp-buffer] a source for buffer words +** https://github.com/hrsh7th/cmp-nvim-lsp[cmp-nvim-lsp] a source for builtin LSP client +** https://github.com/hrsh7th/cmp-vsnip[cmp-vsnip] a source for vim-vsnip autocomplete +** https://github.com/hrsh7th/cmp-path[cmp-path] a source for path autocomplete +** https://github.com/ray-x/cmp-treesitter[cmp-treesitter] treesitter nodes autcomplete + +[[sec-plugins-snippets]] +=== Snippets + +* https://github.com/hrsh7th/vim-vsnip[vim-vsnip] a snippet plugin that supports LSP/VSCode's snippet format + +[[sec-plugins-autopairs]] +=== Autopairs + +* https://github.com/windwp/nvim-autopairs[nvim-autopairs] an autopair plugin for neovim + +[[sec-plugins-themes]] +=== Themes + +* https://github.com/navarasu/onedark.nvim[onedark] a dark colorscheme with multiple options +* https://github.com/folke/tokyonight.nvim[tokyonight-nvim] a neovim theme with multiple color options +* https://github.com/catppuccin/nvim[catppuccin] a pastel theme with 4 color options + +[[sec-plugins-markdown]] +=== Markdown + +* https://github.com/ellisonleao/glow.nvim[glow.nvim] a markdown preview directly in neovim using glow + +[[sec-plugins-rust]] +=== Rust + +* https://github.com/simrat39/rust-tools.nvim[rust-tools] provides tools for rust +* https://github.com/Saecki/crates.nvim[crates.nvim] provides tools for working with `cargo.toml` + +[[sec-plugins-tidalcycles]] +=== Tidal Cycles + +* https://github.com/tidalcycles/vim-tidal[vim-tidal] for tidal cycles integration into vim + +[[sec-plugins-sql]] +=== SQL + +* https://github.com/nanotee/sqls.nvim[sqls.nvim] for useful actions that leverage `sqls` LSP + +[[sec-plugins-html]] +=== HTML + +* https://github.com/windwp/nvim-ts-autotag[nvim-ts-autotag] uses treesitter to autoclose/rename html tags + +[[sec-plugins-dependencies]] +=== Dependencies + +* https://github.com/nvim-lua/plenary.nvim[plenary] which is a dependency of some plugins, installed automatically if needed diff --git a/docs/release-notes/release-notes.adoc b/docs/release-notes/release-notes.adoc new file mode 100644 index 0000000..0bac3ac --- /dev/null +++ b/docs/release-notes/release-notes.adoc @@ -0,0 +1,9 @@ +[[ch-release-notes]] +[appendix] +== Release Notes + +This section lists the release notes for tagged version of neovim-flake and current main. + +:leveloffset: 1 + +include::rl-0.1.adoc[] diff --git a/docs/release-notes/rl-0.1.adoc b/docs/release-notes/rl-0.1.adoc new file mode 100644 index 0000000..0ab1a25 --- /dev/null +++ b/docs/release-notes/rl-0.1.adoc @@ -0,0 +1,32 @@ +[[sec-release-0.1]] +== Release 0.1 + +This is the current master branch and information here is not final. These are changes from the v0.01 tag. + +Special thanks to https://github.com/nix-community/home-manager/[home-manager] for this release. Docs/manual generation, the new module evaluation system, and DAG implementation are from them. + +[[sec-release-0.1-changelog]] +=== Changelog + +https://github.com/jordanisaacs[jordanisaacs]: + +* Removed hare language support (lsp/tree-sitter/etc). `vim.lsp.hare` is no longer defined. If you use hare and would like it added back, please file an issue. + +* <> & <> are now an enum of `string` for options sourced from the flake inputs. Users can still provide vim plugin packages. ++ +If you are contributing and adding a new plugin, add the plugin name to `availablePlugins` in https://github.com/jordanisaacs/neovim-flake/blob/20cec032bd74bc3d20ac17ce36cd84786a04fd3e/modules/lib/types-plugin.nix[types-plugin.nix]. + +* `neovimBuilder` has been removed for configuration. Using an overlay is no longer required. See the manual for the new way to configuration. + +* Treesitter grammars are now configurable with <>. Utilizes the nixpkgs `nvim-treesitter` plugin rather than a custom input in order to take advantage of build support of pinned versions. See https://discourse.nixos.org/t/psa-if-you-are-on-unstable-try-out-nvim-treesitter-withallgrammars/23321?u=snowytrees[discourse] for more information. Packages can be found under the `vimPlugins.nvim-treesitter.builtGrammars` namespace. + +* <> and <> are now of type DAG lines. This allows for ordering of the config. Usage is the same is in home-manager's `home.activation` option. ++ +[source,nix] +---- +vim.luaConfigRC = lib.nvim.dag.entryAnywhere "config here" +---- + +https://github.com/MoritzBoehme[MoritzBoehme]: + +* `catppuccin` theme is now available as a neovim theme <> and lualine theme <>. diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bbe41c0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,1022 @@ +{ + "nodes": { + "bufdelete-nvim": { + "flake": false, + "locked": { + "lastModified": 1649744299, + "narHash": "sha256-0Igk8iPt4UQQTJRBPzTASzNOqY4zlaMiE1PQiBc/KGc=", + "owner": "famiu", + "repo": "bufdelete.nvim", + "rev": "96454aedf95f52393a28cfcfc76482895de014ee", + "type": "github" + }, + "original": { + "owner": "famiu", + "repo": "bufdelete.nvim", + "type": "github" + } + }, + "catppuccin": { + "flake": false, + "locked": { + "lastModified": 1670687538, + "narHash": "sha256-BRQLNMYbOINJXQkKFz2SpXQoaynzcauWSwNfTChaLdc=", + "owner": "catppuccin", + "repo": "nvim", + "rev": "1d22da687d36c37133b13f2b41658c1c989e77e0", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nvim", + "type": "github" + } + }, + "cmp-buffer": { + "flake": false, + "locked": { + "lastModified": 1645413199, + "narHash": "sha256-itDEtoRvZn1mtLhT9WtqKVXoMRe5Qw0/QUf+TFzGNVk=", + "owner": "hrsh7th", + "repo": "cmp-buffer", + "rev": "d66c4c2d376e5be99db68d2362cd94d250987525", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-buffer", + "type": "github" + } + }, + "cmp-nvim-lsp": { + "flake": false, + "locked": { + "lastModified": 1665863036, + "narHash": "sha256-4pppdlVJdn75/faaP3N+o7HgEHxyR1nvkHncnFXGDFA=", + "owner": "hrsh7th", + "repo": "cmp-nvim-lsp", + "rev": "3cf38d9c957e95c397b66f91967758b31be4abe6", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-nvim-lsp", + "type": "github" + } + }, + "cmp-path": { + "flake": false, + "locked": { + "lastModified": 1643823794, + "narHash": "sha256-xYzTpqVKpBBnajqqRRzAXlHAC13VGK1D9mFr3bntepY=", + "owner": "hrsh7th", + "repo": "cmp-path", + "rev": "466b6b8270f7ba89abd59f402c73f63c7331ff6e", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-path", + "type": "github" + } + }, + "cmp-treesitter": { + "flake": false, + "locked": { + "lastModified": 1650880862, + "narHash": "sha256-ZQ2VSrXcUEcy+1lbdvK/pnz3Ppp1lDr38g/z7OvhH8o=", + "owner": "ray-x", + "repo": "cmp-treesitter", + "rev": "c5187c31abd081ecef8b41e5eb476b7340442310", + "type": "github" + }, + "original": { + "owner": "ray-x", + "repo": "cmp-treesitter", + "type": "github" + } + }, + "cmp-vsnip": { + "flake": false, + "locked": { + "lastModified": 1636543683, + "narHash": "sha256-7K3shsiGK7ISFXj9D9MPK7yRqIxeCrbj1IsggToWHO4=", + "owner": "hrsh7th", + "repo": "cmp-vsnip", + "rev": "0abfa1860f5e095a07c477da940cfcb0d273b700", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-vsnip", + "type": "github" + } + }, + "crates-nvim": { + "flake": false, + "locked": { + "lastModified": 1668709750, + "narHash": "sha256-MdmZrZu877P0l4yeJNI6muiYmwVlsvFHJCEBrrhR1Zc=", + "owner": "Saecki", + "repo": "crates.nvim", + "rev": "e11e27864428a68b25e43b833e9081e350a38d96", + "type": "github" + }, + "original": { + "owner": "Saecki", + "repo": "crates.nvim", + "type": "github" + } + }, + "dirt-samples-src": { + "flake": false, + "locked": { + "lastModified": 1588278411, + "narHash": "sha256-h8vQxRym6QzNLOTZU7A43VCHuG0H77l+BFwXnC0L1CE=", + "owner": "tidalcycles", + "repo": "dirt-samples", + "rev": "66d432418c9a7d82cf049d9246adfa62f46df2a6", + "type": "github" + }, + "original": { + "owner": "tidalcycles", + "ref": "master", + "repo": "dirt-samples", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitsigns-nvim": { + "flake": false, + "locked": { + "lastModified": 1666700386, + "narHash": "sha256-pSYXCENFw/z7xppenPehniX8+INkrl+l1LgKKGlfrjQ=", + "owner": "lewis6991", + "repo": "gitsigns.nvim", + "rev": "851cd32caaea84f303c4fdf51d72dfa5fcd795bb", + "type": "github" + }, + "original": { + "owner": "lewis6991", + "repo": "gitsigns.nvim", + "type": "github" + } + }, + "glow-nvim": { + "flake": false, + "locked": { + "lastModified": 1649861698, + "narHash": "sha256-c2HrVLCyekw9b8FxxVMUkBkUitGDX1AyslmM1kZQeCQ=", + "owner": "ellisonleao", + "repo": "glow.nvim", + "rev": "0c76518e440f2ea4dbadd87beec8eea4ce030f17", + "type": "github" + }, + "original": { + "owner": "ellisonleao", + "repo": "glow.nvim", + "type": "github" + } + }, + "indent-blankline": { + "flake": false, + "locked": { + "lastModified": 1649991995, + "narHash": "sha256-pMVby6w7UTR2f1Nxp0ZPlV+KrdXNJ+jEQeQe30Pfs3M=", + "owner": "lukas-reineke", + "repo": "indent-blankline.nvim", + "rev": "045d9582094b27f5ae04d8b635c6da8e97e53f1d", + "type": "github" + }, + "original": { + "owner": "lukas-reineke", + "repo": "indent-blankline.nvim", + "type": "github" + } + }, + "kommentary": { + "flake": false, + "locked": { + "lastModified": 1644888740, + "narHash": "sha256-6YNKYMxaKi02TLa+ebt97XGREnmTjdJAA3bSHFC4yX0=", + "owner": "b3nj5m1n", + "repo": "kommentary", + "rev": "12ecde4ed3ecb39964000a5fd034ae4c1d307388", + "type": "github" + }, + "original": { + "owner": "b3nj5m1n", + "repo": "kommentary", + "type": "github" + } + }, + "lsp-signature": { + "flake": false, + "locked": { + "lastModified": 1651382786, + "narHash": "sha256-owtDWZXZZH6z0m5oHfm/QUjRoWKH4LY6UUOZq8JPckI=", + "owner": "ray-x", + "repo": "lsp_signature.nvim", + "rev": "6d160406f948a810c40304224a1255c8bba5a415", + "type": "github" + }, + "original": { + "owner": "ray-x", + "repo": "lsp_signature.nvim", + "type": "github" + } + }, + "lspkind": { + "flake": false, + "locked": { + "lastModified": 1650298271, + "narHash": "sha256-0103K5lnzWCyuT/qwiBUo5PJ7lUX7fo+zNeEnQClI7A=", + "owner": "onsails", + "repo": "lspkind-nvim", + "rev": "57e5b5dfbe991151b07d272a06e365a77cc3d0e7", + "type": "github" + }, + "original": { + "owner": "onsails", + "repo": "lspkind-nvim", + "type": "github" + } + }, + "lspsaga": { + "flake": false, + "locked": { + "lastModified": 1647219889, + "narHash": "sha256-utb2Rp6RdYWZzVt4W7B7RHOk4Xq1Lli4RcHxZLa8dHc=", + "owner": "tami5", + "repo": "lspsaga.nvim", + "rev": "5309d75bd90ce5b1708331df3af1e971fa83a2b9", + "type": "github" + }, + "original": { + "owner": "tami5", + "repo": "lspsaga.nvim", + "type": "github" + } + }, + "lualine": { + "flake": false, + "locked": { + "lastModified": 1651457787, + "narHash": "sha256-TaRC7Pj9g0nD+kk7VrySulR20GolXtR/roUnA3FM144=", + "owner": "hoob3rt", + "repo": "lualine.nvim", + "rev": "45d07fc026400c211337a7ce1cb90e7b7a397e31", + "type": "github" + }, + "original": { + "owner": "hoob3rt", + "repo": "lualine.nvim", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "rnix-lsp", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655042882, + "narHash": "sha256-9BX8Fuez5YJlN7cdPO63InoyBy7dm3VlJkkmTt6fS1A=", + "owner": "nix-community", + "repo": "naersk", + "rev": "cddffb5aa211f50c4b8750adbec0bbbdfb26bb9f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "nil": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1669568240, + "narHash": "sha256-xarHQnV7XCvioDxoAhOI+KsDzPNeWZ3F1OCPJVWS5S4=", + "owner": "oxalica", + "repo": "nil", + "rev": "8f8a5d2cffb1a92b1b4b5001239ca9138675c3f4", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "nil", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1669809720, + "narHash": "sha256-RMT77f6CPOYtLLQ2esj+EJ1BPVWxf4RDidjrSvA5OhI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "227de2b3bbec142f912c09d5e8a1b4e778aa54fb", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1656753965, + "narHash": "sha256-BCrB3l0qpJokOnIVc3g2lHiGhnjUi0MoXiw6t1o8H1E=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0ea7a8f1b939d74e5df8af9a8f7342097cdf69eb", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1655400192, + "narHash": "sha256-49OBVVRgb9H/PSmNT9W61+NRdDbuSJVuDDflwXlaUKU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3d7435c638baffaa826b85459df0fff47f12317d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nmd": { + "flake": false, + "locked": { + "lastModified": 1666190571, + "narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=", + "owner": "rycee", + "repo": "nmd", + "rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169", + "type": "gitlab" + }, + "original": { + "owner": "rycee", + "repo": "nmd", + "type": "gitlab" + } + }, + "null-ls": { + "flake": false, + "locked": { + "lastModified": 1669991088, + "narHash": "sha256-DZgonVEzkgayvLY9jkEH1O/Xny6LQktyi8rTNbQlkMk=", + "owner": "jose-elias-alvarez", + "repo": "null-ls.nvim", + "rev": "a67897283fdb0051ad5c72e840e1845e195b979b", + "type": "github" + }, + "original": { + "owner": "jose-elias-alvarez", + "repo": "null-ls.nvim", + "type": "github" + } + }, + "nvim-autopairs": { + "flake": false, + "locked": { + "lastModified": 1651184422, + "narHash": "sha256-voiBJw752//W5oAGQ3wFl4XOUE5PGc/ddchXpWUfgFE=", + "owner": "windwp", + "repo": "nvim-autopairs", + "rev": "63779ea99ed43ab22660ac6ae5b506a40bf41aeb", + "type": "github" + }, + "original": { + "owner": "windwp", + "repo": "nvim-autopairs", + "type": "github" + } + }, + "nvim-bufferline-lua": { + "flake": false, + "locked": { + "lastModified": 1666171880, + "narHash": "sha256-hueIGT7KOhca0kP0M1nUYzBrzMz+DpuZSOt5iyuEa40=", + "owner": "akinsho", + "repo": "nvim-bufferline.lua", + "rev": "e70be6232f632d16d2412b1faf85554285036278", + "type": "github" + }, + "original": { + "owner": "akinsho", + "ref": "v3.0.1", + "repo": "nvim-bufferline.lua", + "type": "github" + } + }, + "nvim-cmp": { + "flake": false, + "locked": { + "lastModified": 1666412792, + "narHash": "sha256-ErdM+ETpkgBtAvA/RedqN+DXvunQ4OYl58HpfZQkz/s=", + "owner": "hrsh7th", + "repo": "nvim-cmp", + "rev": "cdb77665bbf23bd2717d424ddf4bf98057c30bb3", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "nvim-cmp", + "type": "github" + } + }, + "nvim-code-action-menu": { + "flake": false, + "locked": { + "lastModified": 1647509555, + "narHash": "sha256-fD9luuZe5mVkJTTtngH0jnwtqljhSZp0OFobBa4uqZI=", + "owner": "weilbith", + "repo": "nvim-code-action-menu", + "rev": "a864a79c8e024d4f5d95915210188c9c3430b160", + "type": "github" + }, + "original": { + "owner": "weilbith", + "repo": "nvim-code-action-menu", + "type": "github" + } + }, + "nvim-compe": { + "flake": false, + "locked": { + "lastModified": 1633188506, + "narHash": "sha256-Y2oqvsuAKM3qjmmtJVD9z34682eCRF25kPL+rxhhg7I=", + "owner": "hrsh7th", + "repo": "nvim-compe", + "rev": "d186d739c54823e0b010feb205c6f97792322c08", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "nvim-compe", + "type": "github" + } + }, + "nvim-cursorline": { + "flake": false, + "locked": { + "lastModified": 1650034925, + "narHash": "sha256-Uhw65p1KBjs8KsVOmTzuiu3XKclxBob8AVdWEt30C/8=", + "owner": "yamatsum", + "repo": "nvim-cursorline", + "rev": "804f0023692653b2b2368462d67d2a87056947f9", + "type": "github" + }, + "original": { + "owner": "yamatsum", + "repo": "nvim-cursorline", + "type": "github" + } + }, + "nvim-lightbulb": { + "flake": false, + "locked": { + "lastModified": 1645713830, + "narHash": "sha256-LxGA2LX9CASodJnZYXGZfGPOeW38MW7z54gYQSDmhRE=", + "owner": "kosayoda", + "repo": "nvim-lightbulb", + "rev": "29ca81408119ba809d1f922edc941868af97ee86", + "type": "github" + }, + "original": { + "owner": "kosayoda", + "repo": "nvim-lightbulb", + "type": "github" + } + }, + "nvim-lspconfig": { + "flake": false, + "locked": { + "lastModified": 1669809489, + "narHash": "sha256-fMDR3sYmVu6cDSU8T75S/ppGYXo9+LPqseAd2n0HW6w=", + "owner": "neovim", + "repo": "nvim-lspconfig", + "rev": "d346335af862ede0cece75739d789cfdc46c4454", + "type": "github" + }, + "original": { + "owner": "neovim", + "repo": "nvim-lspconfig", + "type": "github" + } + }, + "nvim-neoclip": { + "flake": false, + "locked": { + "lastModified": 1651221055, + "narHash": "sha256-JO5tOk+Sv0YNjk1pHKfzXian7trFrEh/+iwH2ZxO0Ss=", + "owner": "AckslD", + "repo": "nvim-neoclip.lua", + "rev": "f3ff1645de5d2fd46ac8ffe86e440b7f3ae1fd11", + "type": "github" + }, + "original": { + "owner": "AckslD", + "repo": "nvim-neoclip.lua", + "type": "github" + } + }, + "nvim-tree-lua": { + "flake": false, + "locked": { + "lastModified": 1662860472, + "narHash": "sha256-3aB1xDU0cylHfZ5yzxMQKf07qrJ1pwHEl+QV42k0CpQ=", + "owner": "kyazdani42", + "repo": "nvim-tree.lua", + "rev": "fb8735e96cecf004fbefb086ce85371d003c5129", + "type": "github" + }, + "original": { + "owner": "kyazdani42", + "repo": "nvim-tree.lua", + "type": "github" + } + }, + "nvim-treesitter-context": { + "flake": false, + "locked": { + "lastModified": 1650876005, + "narHash": "sha256-qsfPqC6wpvM/fvGBtfKY7CjdgjGa6JsyOrI7ZWC7jyM=", + "owner": "lewis6991", + "repo": "nvim-treesitter-context", + "rev": "28fd8fea0d056333dcd3cd5abcb1256e3e526417", + "type": "github" + }, + "original": { + "owner": "lewis6991", + "repo": "nvim-treesitter-context", + "type": "github" + } + }, + "nvim-ts-autotag": { + "flake": false, + "locked": { + "lastModified": 1650591994, + "narHash": "sha256-YsqWrmsbp0NhCrnJQo8Df6yQr4f0shS6GdcEQaHdJDE=", + "owner": "windwp", + "repo": "nvim-ts-autotag", + "rev": "044a05c4c51051326900a53ba98fddacd15fea22", + "type": "github" + }, + "original": { + "owner": "windwp", + "repo": "nvim-ts-autotag", + "type": "github" + } + }, + "nvim-web-devicons": { + "flake": false, + "locked": { + "lastModified": 1651408174, + "narHash": "sha256-hYFDefTMcdtoQLhwUaamyGuid69kUo+95P1wjoS2dmo=", + "owner": "kyazdani42", + "repo": "nvim-web-devicons", + "rev": "bdd43421437f2ef037e0dafeaaaa62b31d35ef2f", + "type": "github" + }, + "original": { + "owner": "kyazdani42", + "repo": "nvim-web-devicons", + "type": "github" + } + }, + "onedark": { + "flake": false, + "locked": { + "lastModified": 1666430920, + "narHash": "sha256-pacwQrYPRp2ZFe5ClVYQz2yFxiBmKZdqKQ/I2FdCRYM=", + "owner": "navarasu", + "repo": "onedark.nvim", + "rev": "7aeca4713a922139b5e14c037b5faf34dc41c8d2", + "type": "github" + }, + "original": { + "owner": "navarasu", + "repo": "onedark.nvim", + "type": "github" + } + }, + "plenary-nvim": { + "flake": false, + "locked": { + "lastModified": 1650205145, + "narHash": "sha256-QKVFz95XaJrwkFaWqUHBirMFagellRn2YpNYnBeI/10=", + "owner": "nvim-lua", + "repo": "plenary.nvim", + "rev": "9069d14a120cadb4f6825f76821533f2babcab92", + "type": "github" + }, + "original": { + "owner": "nvim-lua", + "repo": "plenary.nvim", + "type": "github" + } + }, + "registers": { + "flake": false, + "locked": { + "lastModified": 1650186703, + "narHash": "sha256-kqAcuO/tPO0GHBUwpwQYz7QJCyeTE93CbXnVFK7S8qU=", + "owner": "tversteeg", + "repo": "registers.nvim", + "rev": "dfcf0962ce88b52e00dd96dfaabc9997a18f4efe", + "type": "github" + }, + "original": { + "owner": "tversteeg", + "repo": "registers.nvim", + "type": "github" + } + }, + "rnix-lsp": { + "inputs": { + "naersk": "naersk", + "nixpkgs": "nixpkgs_2", + "utils": "utils" + }, + "locked": { + "lastModified": 1669555118, + "narHash": "sha256-F0s0m62S5bHNVWNHLZD6SeHiLrsDx98VQbRjDyIu+qQ=", + "owner": "nix-community", + "repo": "rnix-lsp", + "rev": "95d40673fe43642e2e1144341e86d0036abd95d9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "rnix-lsp", + "type": "github" + } + }, + "root": { + "inputs": { + "bufdelete-nvim": "bufdelete-nvim", + "catppuccin": "catppuccin", + "cmp-buffer": "cmp-buffer", + "cmp-nvim-lsp": "cmp-nvim-lsp", + "cmp-path": "cmp-path", + "cmp-treesitter": "cmp-treesitter", + "cmp-vsnip": "cmp-vsnip", + "crates-nvim": "crates-nvim", + "flake-utils": "flake-utils", + "gitsigns-nvim": "gitsigns-nvim", + "glow-nvim": "glow-nvim", + "indent-blankline": "indent-blankline", + "kommentary": "kommentary", + "lsp-signature": "lsp-signature", + "lspkind": "lspkind", + "lspsaga": "lspsaga", + "lualine": "lualine", + "nil": "nil", + "nixpkgs": "nixpkgs", + "nmd": "nmd", + "null-ls": "null-ls", + "nvim-autopairs": "nvim-autopairs", + "nvim-bufferline-lua": "nvim-bufferline-lua", + "nvim-cmp": "nvim-cmp", + "nvim-code-action-menu": "nvim-code-action-menu", + "nvim-compe": "nvim-compe", + "nvim-cursorline": "nvim-cursorline", + "nvim-lightbulb": "nvim-lightbulb", + "nvim-lspconfig": "nvim-lspconfig", + "nvim-neoclip": "nvim-neoclip", + "nvim-tree-lua": "nvim-tree-lua", + "nvim-treesitter-context": "nvim-treesitter-context", + "nvim-ts-autotag": "nvim-ts-autotag", + "nvim-web-devicons": "nvim-web-devicons", + "onedark": "onedark", + "plenary-nvim": "plenary-nvim", + "registers": "registers", + "rnix-lsp": "rnix-lsp", + "rust-tools": "rust-tools", + "sqls-nvim": "sqls-nvim", + "telescope": "telescope", + "tidalcycles": "tidalcycles", + "todo-comments": "todo-comments", + "tokyonight": "tokyonight", + "trouble": "trouble", + "vim-vsnip": "vim-vsnip", + "which-key": "which-key" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "nil", + "flake-utils" + ], + "nixpkgs": [ + "nil", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1669170936, + "narHash": "sha256-TKPH4Pzkjw5gAPo9hejs3O4mWJW6V/RSiOj8UuSFRTs=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "c90c223c4aef334356029b89c72bb65e26f7efe6", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-tools": { + "flake": false, + "locked": { + "lastModified": 1673136837, + "narHash": "sha256-+/kK6MU2EiSBFbfqQJwLkJICXZpf8oiShbcvsls3V8A=", + "owner": "simrat39", + "repo": "rust-tools.nvim", + "rev": "df584e84393ef255f5b8cbd709677d6a3a5bf42f", + "type": "github" + }, + "original": { + "owner": "simrat39", + "repo": "rust-tools.nvim", + "type": "github" + } + }, + "sqls-nvim": { + "flake": false, + "locked": { + "lastModified": 1651347942, + "narHash": "sha256-ewCkqU5Kj1MQAjRRzOWalLcv/uOLEbtK1jFrySvZ8Y8=", + "owner": "nanotee", + "repo": "sqls.nvim", + "rev": "c52945aacf30247a3b82c586681c414dcd2359bd", + "type": "github" + }, + "original": { + "owner": "nanotee", + "repo": "sqls.nvim", + "type": "github" + } + }, + "superdirt-src": { + "flake": false, + "locked": { + "lastModified": 1611740180, + "narHash": "sha256-GtnqZeMFqFkVhgx2Exu0wY687cHa7mNnVCgjQd6fiIA=", + "owner": "musikinformatik", + "repo": "superdirt", + "rev": "7abb62e89649daa1232b9cbd6427241868abd30e", + "type": "github" + }, + "original": { + "owner": "musikinformatik", + "ref": "master", + "repo": "superdirt", + "type": "github" + } + }, + "telescope": { + "flake": false, + "locked": { + "lastModified": 1651391210, + "narHash": "sha256-aEY/4ra7qyaXQg3H++b0JUbF7G2nI4m5Ow9daZO/duE=", + "owner": "nvim-telescope", + "repo": "telescope.nvim", + "rev": "544c5ee40752ac5552595da86a62abaa39e2dfa9", + "type": "github" + }, + "original": { + "owner": "nvim-telescope", + "repo": "telescope.nvim", + "type": "github" + } + }, + "tidal-src": { + "flake": false, + "locked": { + "lastModified": 1654350756, + "narHash": "sha256-tONM5SYYBca0orTLH1EUOilSC1FCluWrFt8AetUx+YQ=", + "owner": "tidalcycles", + "repo": "tidal", + "rev": "fda9c1ecb3722698935245e5409ef8ccdfca16c8", + "type": "github" + }, + "original": { + "owner": "tidalcycles", + "ref": "main", + "repo": "tidal", + "type": "github" + } + }, + "tidalcycles": { + "inputs": { + "dirt-samples-src": "dirt-samples-src", + "nixpkgs": "nixpkgs_3", + "superdirt-src": "superdirt-src", + "tidal-src": "tidal-src", + "utils": "utils_2", + "vim-tidal-src": "vim-tidal-src", + "vowel-src": "vowel-src" + }, + "locked": { + "lastModified": 1661670241, + "narHash": "sha256-+5C83z+Sd8ugvMshrXqpca4vv3tQ2D4tYEJ3QY6JVsg=", + "owner": "mitchmindtree", + "repo": "tidalcycles.nix", + "rev": "fefe3d586511e1cfaac79bb83ec0b278bb1b6bad", + "type": "github" + }, + "original": { + "owner": "mitchmindtree", + "repo": "tidalcycles.nix", + "type": "github" + } + }, + "todo-comments": { + "flake": false, + "locked": { + "lastModified": 1642601933, + "narHash": "sha256-8uj5TxO9XZlSCB4lVRbKRc1IlUEKcBf/4bDviwuxEgs=", + "owner": "folke", + "repo": "todo-comments.nvim", + "rev": "98b1ebf198836bdc226c0562b9f906584e6c400e", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "todo-comments.nvim", + "type": "github" + } + }, + "tokyonight": { + "flake": false, + "locked": { + "lastModified": 1666558747, + "narHash": "sha256-hZufHQkI2M0I4mEqV9qs6PkL74aqScKJ3RA5QOulX+0=", + "owner": "folke", + "repo": "tokyonight.nvim", + "rev": "16a294bea92dc8f16ad205c71ce61bf05e79deb3", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "tokyonight.nvim", + "type": "github" + } + }, + "trouble": { + "flake": false, + "locked": { + "lastModified": 1647585739, + "narHash": "sha256-oUf8YbJ9HmSLN8o2c7CXzCYPu7PwKzvVKNiM9HtHQbQ=", + "owner": "folke", + "repo": "trouble.nvim", + "rev": "691d490cc4eadc430d226fa7d77aaa84e2e0a125", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "trouble.nvim", + "type": "github" + } + }, + "utils": { + "locked": { + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "vim-tidal-src": { + "flake": false, + "locked": { + "lastModified": 1664758630, + "narHash": "sha256-fLaBMm6jSLHytIH5IUQtUfi3kaPLdruO3cxv4UcjEO4=", + "owner": "tidalcycles", + "repo": "vim-tidal", + "rev": "f15f14b12176d8f1028d0596b031c3d6e1201c3b", + "type": "github" + }, + "original": { + "owner": "mitchmindtree", + "ref": "mitchmindtree", + "repo": "vim-tidal", + "type": "github" + } + }, + "vim-vsnip": { + "flake": false, + "locked": { + "lastModified": 1650631622, + "narHash": "sha256-USltEc6QGHwMqx7E9wo9qZmq+pm9FLj0CUcKoE7KPLU=", + "owner": "hrsh7th", + "repo": "vim-vsnip", + "rev": "8f199ef690ed26dcbb8973d9a6760d1332449ac9", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "vim-vsnip", + "type": "github" + } + }, + "vowel-src": { + "flake": false, + "locked": { + "lastModified": 1641306144, + "narHash": "sha256-zfF6cvAGDNYWYsE8dOIo38b+dIymd17Pexg0HiPFbxM=", + "owner": "supercollider-quarks", + "repo": "vowel", + "rev": "ab59caa870201ecf2604b3efdd2196e21a8b5446", + "type": "github" + }, + "original": { + "owner": "supercollider-quarks", + "ref": "master", + "repo": "vowel", + "type": "github" + } + }, + "which-key": { + "flake": false, + "locked": { + "lastModified": 1666956294, + "narHash": "sha256-IbJP6j+M+POPhX4YbewTJiSoELvDo6y+vF0RREqqm4c=", + "owner": "folke", + "repo": "which-key.nvim", + "rev": "61553aeb3d5ca8c11eea8be6eadf478062982ac9", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "which-key.nvim", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..1ed33b5 --- /dev/null +++ b/flake.nix @@ -0,0 +1,421 @@ +{ + description = "Jordan's Neovim Configuration"; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + # For generating documentation website + nmd = { + url = "gitlab:rycee/nmd"; + flake = false; + }; + + # LSP plugins + nvim-lspconfig = { + # url = "github:neovim/nvim-lspconfig?ref=v0.1.3"; + # Use master for nil_ls + url = "github:neovim/nvim-lspconfig"; + flake = false; + }; + lspsaga = { + url = "github:tami5/lspsaga.nvim"; + flake = false; + }; + lspkind = { + url = "github:onsails/lspkind-nvim"; + flake = false; + }; + trouble = { + url = "github:folke/trouble.nvim"; + flake = false; + }; + nvim-treesitter-context = { + url = "github:lewis6991/nvim-treesitter-context"; + flake = false; + }; + nvim-lightbulb = { + url = "github:kosayoda/nvim-lightbulb"; + flake = false; + }; + + nvim-code-action-menu = { + url = "github:weilbith/nvim-code-action-menu"; + flake = false; + }; + lsp-signature = { + url = "github:ray-x/lsp_signature.nvim"; + flake = false; + }; + null-ls = { + url = "github:jose-elias-alvarez/null-ls.nvim"; + flake = false; + }; + sqls-nvim = { + url = "github:nanotee/sqls.nvim"; + flake = false; + }; + rust-tools = { + url = "github:simrat39/rust-tools.nvim"; + flake = false; + }; + + # Copying/Registers + registers = { + url = "github:tversteeg/registers.nvim"; + flake = false; + }; + nvim-neoclip = { + url = "github:AckslD/nvim-neoclip.lua"; + flake = false; + }; + + # Telescope + telescope = { + url = "github:nvim-telescope/telescope.nvim"; + flake = false; + }; + + # Langauge server (use master instead of nixpkgs) + rnix-lsp.url = "github:nix-community/rnix-lsp"; + nil = { + url = "github:oxalica/nil"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + + # Filetrees + nvim-tree-lua = { + url = "github:kyazdani42/nvim-tree.lua"; + flake = false; + }; + + # Tablines + nvim-bufferline-lua = { + url = "github:akinsho/nvim-bufferline.lua?ref=v3.0.1"; + flake = false; + }; + + # Statuslines + lualine = { + url = "github:hoob3rt/lualine.nvim"; + flake = false; + }; + + # Autocompletes + nvim-compe = { + url = "github:hrsh7th/nvim-compe"; + flake = false; + }; + nvim-cmp = { + url = "github:hrsh7th/nvim-cmp"; + flake = false; + }; + cmp-buffer = { + url = "github:hrsh7th/cmp-buffer"; + flake = false; + }; + cmp-nvim-lsp = { + url = "github:hrsh7th/cmp-nvim-lsp"; + flake = false; + }; + cmp-vsnip = { + url = "github:hrsh7th/cmp-vsnip"; + flake = false; + }; + cmp-path = { + url = "github:hrsh7th/cmp-path"; + flake = false; + }; + cmp-treesitter = { + url = "github:ray-x/cmp-treesitter"; + flake = false; + }; + + # snippets + vim-vsnip = { + url = "github:hrsh7th/vim-vsnip"; + flake = false; + }; + + # Autopairs + nvim-autopairs = { + url = "github:windwp/nvim-autopairs"; + flake = false; + }; + nvim-ts-autotag = { + url = "github:windwp/nvim-ts-autotag"; + flake = false; + }; + + # Commenting + kommentary = { + url = "github:b3nj5m1n/kommentary"; + flake = false; + }; + todo-comments = { + url = "github:folke/todo-comments.nvim"; + flake = false; + }; + + # Buffer tools + bufdelete-nvim = { + url = "github:famiu/bufdelete.nvim"; + flake = false; + }; + + # Themes + tokyonight = { + url = "github:folke/tokyonight.nvim"; + flake = false; + }; + + onedark = { + url = "github:navarasu/onedark.nvim"; + flake = false; + }; + + catppuccin = { + url = "github:catppuccin/nvim"; + flake = false; + }; + + # Rust crates + crates-nvim = { + url = "github:Saecki/crates.nvim"; + flake = false; + }; + + # Visuals + nvim-cursorline = { + url = "github:yamatsum/nvim-cursorline"; + flake = false; + }; + indent-blankline = { + url = "github:lukas-reineke/indent-blankline.nvim"; + flake = false; + }; + nvim-web-devicons = { + url = "github:kyazdani42/nvim-web-devicons"; + flake = false; + }; + gitsigns-nvim = { + url = "github:lewis6991/gitsigns.nvim"; + flake = false; + }; + + # Key binding help + which-key = { + url = "github:folke/which-key.nvim"; + flake = false; + }; + + # Markdown + glow-nvim = { + url = "github:ellisonleao/glow.nvim"; + flake = false; + }; + + # Tidal cycles + tidalcycles = { + url = "github:mitchmindtree/tidalcycles.nix"; + inputs.vim-tidal-src.url = "github:tidalcycles/vim-tidal"; + }; + + # Plenary (required by crates-nvim) + plenary-nvim = { + url = "github:nvim-lua/plenary.nvim"; + flake = false; + }; + }; + + outputs = { + nixpkgs, + flake-utils, + ... + } @ inputs: let + modulesWithInputs = import ./modules {inherit inputs;}; + + neovimConfiguration = { + modules ? [], + pkgs, + lib ? pkgs.lib, + check ? true, + extraSpecialArgs ? {}, + }: + modulesWithInputs { + inherit pkgs lib check extraSpecialArgs; + configuration = {...}: { + imports = modules; + }; + }; + + nvimBin = pkg: "${pkg}/bin/nvim"; + + buildPkg = pkgs: modules: + (neovimConfiguration { + inherit pkgs modules; + }) + .neovim; + + tidalConfig = { + config = { + vim.tidal.enable = true; + }; + }; + + mainConfig = isMaximal: { + config = { + vim.viAlias = false; + vim.vimAlias = true; + vim.lsp = { + enable = true; + formatOnSave = true; + lightbulb.enable = true; + lspsaga.enable = false; + nvimCodeActionMenu.enable = true; + trouble.enable = true; + lspSignature.enable = true; + nix = { + enable = true; + formatter = "alejandra"; + }; + rust.enable = isMaximal; + python = isMaximal; + clang.enable = isMaximal; + sql = isMaximal; + ts = isMaximal; + go = isMaximal; + zig.enable = isMaximal; + }; + vim.visuals = { + enable = true; + nvimWebDevicons.enable = true; + lspkind.enable = true; + indentBlankline = { + enable = true; + fillChar = ""; + eolChar = ""; + showCurrContext = true; + }; + cursorWordline = { + enable = true; + lineTimeout = 0; + }; + }; + vim.statusline.lualine = { + enable = true; + theme = "catppuccin"; + }; + vim.theme = { + enable = true; + name = "catppuccin"; + style = "mocha"; + }; + vim.autopairs.enable = true; + vim.autocomplete = { + enable = true; + type = "nvim-cmp"; + }; + vim.filetree.nvimTreeLua.enable = true; + vim.tabline.nvimBufferline.enable = true; + vim.treesitter = { + enable = true; + context.enable = true; + }; + vim.keys = { + enable = true; + whichKey.enable = true; + }; + vim.telescope = { + enable = true; + }; + vim.markdown = { + enable = true; + glow.enable = true; + }; + vim.git = { + enable = true; + gitsigns.enable = true; + }; + }; + }; + + nixConfig = mainConfig false; + maximalConfig = mainConfig true; + in + { + lib = { + nvim = (import ./modules/lib/stdlib-extended.nix nixpkgs.lib).nvim; + inherit neovimConfiguration; + }; + + overlays.default = final: prev: { + inherit neovimConfiguration; + neovim-nix = buildPkg prev [nixConfig]; + neovim-maximal = buildPkg prev [maximalConfig]; + neovim-tidal = buildPkg prev [tidalConfig]; + }; + } + // (flake-utils.lib.eachDefaultSystem (system: let + pkgs = import nixpkgs { + inherit system; + overlays = [ + inputs.tidalcycles.overlays.default + (final: prev: { + rnix-lsp = inputs.rnix-lsp.defaultPackage.${system}; + nil = inputs.nil.packages.${system}.default; + }) + ]; + }; + + docs = import ./docs { + inherit pkgs; + nmdSrc = inputs.nmd; + }; + + tidalPkg = buildPkg pkgs [tidalConfig]; + nixPkg = buildPkg pkgs [nixConfig]; + maximalPkg = buildPkg pkgs [maximalConfig]; + in { + apps = + rec { + nix = { + type = "app"; + program = nvimBin nixPkg; + }; + maximal = { + type = "app"; + program = nvimBin maximalPkg; + }; + default = nix; + } + // ( + if !(builtins.elem system ["aarch64-darwin" "x86_64-darwin"]) + then { + tidal = { + type = "app"; + program = nvimBin tidalPkg; + }; + } + else {} + ); + + devShells.default = pkgs.mkShell {nativeBuildInputs = [nixPkg];}; + + packages = + { + docs-html = docs.manual.html; + docs-manpages = docs.manPages; + docs-json = docs.options.json; + default = nixPkg; + nix = nixPkg; + maximal = maximalPkg; + } + // ( + if !(builtins.elem system ["aarch64-darwin" "x86_64-darwin"]) + then { + tidal = tidalPkg; + } + else {} + ); + })); +} diff --git a/modules/autopairs/default.nix b/modules/autopairs/default.nix new file mode 100644 index 0000000..3e85003 --- /dev/null +++ b/modules/autopairs/default.nix @@ -0,0 +1,43 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; +with builtins; let + cfg = config.vim.autopairs; +in { + options.vim = { + autopairs = { + enable = mkOption { + type = types.bool; + default = false; + description = "enable autopairs"; + }; + + type = mkOption { + type = types.enum ["nvim-autopairs"]; + default = "nvim-autopairs"; + description = "Set the autopairs type. Options: nvim-autopairs [nvim-autopairs]"; + }; + }; + }; + + config = + mkIf cfg.enable + { + vim.startPlugins = ["nvim-autopairs"]; + + vim.luaConfigRC.autopairs = nvim.dag.entryAnywhere '' + require("nvim-autopairs").setup{} + ${optionalString (config.vim.autocomplete.type == "nvim-compe") '' + require('nvim-autopairs.completion.compe').setup({ + map_cr = true, + map_complete = true, + auto_select = false, + }) + ''} + ''; + }; +} diff --git a/modules/basic/default.nix b/modules/basic/default.nix new file mode 100644 index 0000000..f020608 --- /dev/null +++ b/modules/basic/default.nix @@ -0,0 +1,225 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; +with builtins; let + cfg = config.vim; +in { + options.vim = { + colourTerm = mkOption { + type = types.bool; + default = true; + description = "Set terminal up for 256 colours"; + }; + + disableArrows = mkOption { + type = types.bool; + default = false; + description = "Set to prevent arrow keys from moving cursor"; + }; + + hideSearchHighlight = mkOption { + type = types.bool; + default = false; + description = "Hide search highlight so it doesn't stay highlighted"; + }; + + scrollOffset = mkOption { + type = types.int; + default = 8; + description = "Start scrolling this number of lines from the top or bottom of the page."; + }; + + wordWrap = mkOption { + type = types.bool; + default = true; + description = "Enable word wrapping."; + }; + + syntaxHighlighting = mkOption { + type = types.bool; + default = true; + description = "Enable syntax highlighting"; + }; + + mapLeaderSpace = mkOption { + type = types.bool; + default = true; + description = "Map the space key to leader key"; + }; + + useSystemClipboard = mkOption { + type = types.bool; + default = true; + description = "Make use of the clipboard for default yank and paste operations. Don't use * and +"; + }; + + mouseSupport = mkOption { + type = with types; enum ["a" "n" "v" "i" "c"]; + default = "a"; + description = "Set modes for mouse support. a - all, n - normal, v - visual, i - insert, c - command"; + }; + + lineNumberMode = mkOption { + type = with types; enum ["relative" "number" "relNumber" "none"]; + default = "relNumber"; + description = "How line numbers are displayed. none, relative, number, relNumber"; + }; + + preventJunkFiles = mkOption { + type = types.bool; + default = false; + description = "Prevent swapfile, backupfile from being created"; + }; + + tabWidth = mkOption { + type = types.int; + default = 4; + description = "Set the width of tabs"; + }; + + autoIndent = mkOption { + type = types.bool; + default = true; + description = "Enable auto indent"; + }; + + cmdHeight = mkOption { + type = types.int; + default = 1; + description = "Height of the command pane"; + }; + + updateTime = mkOption { + type = types.int; + default = 300; + description = "The number of milliseconds till Cursor Hold event is fired"; + }; + + showSignColumn = mkOption { + type = types.bool; + default = true; + description = "Show the sign column"; + }; + + bell = mkOption { + type = types.enum ["none" "visual" "on"]; + default = "none"; + description = "Set how bells are handled. Options: on, visual or none"; + }; + + mapTimeout = mkOption { + type = types.int; + default = 500; + description = "Timeout in ms that neovim will wait for mapped action to complete"; + }; + + splitBelow = mkOption { + type = types.bool; + default = true; + description = "New splits will open below instead of on top"; + }; + + splitRight = mkOption { + type = types.bool; + default = true; + description = "New splits will open to the right"; + }; + }; + + config = { + vim.startPlugins = ["plenary-nvim"]; + + vim.nmap = mkIf cfg.disableArrows { + "" = ""; + "" = ""; + "" = ""; + "" = ""; + }; + + vim.imap = mkIf cfg.disableArrows { + "" = ""; + "" = ""; + "" = ""; + "" = ""; + }; + + vim.nnoremap = mkIf cfg.mapLeaderSpace {"" = "";}; + + vim.configRC.basic = nvim.dag.entryAfter ["globalsScript"] '' + " Settings that are set for everything + set encoding=utf-8 + set mouse=${cfg.mouseSupport} + set tabstop=${toString cfg.tabWidth} + set shiftwidth=${toString cfg.tabWidth} + set softtabstop=${toString cfg.tabWidth} + set expandtab + set cmdheight=${toString cfg.cmdHeight} + set updatetime=${toString cfg.updateTime} + set shortmess+=c + set tm=${toString cfg.mapTimeout} + set hidden + ${optionalString cfg.splitBelow '' + set splitbelow + ''} + ${optionalString cfg.splitRight '' + set splitright + ''} + ${optionalString cfg.showSignColumn '' + set signcolumn=yes + ''} + ${optionalString cfg.autoIndent '' + set autoindent + ''} + + ${optionalString cfg.preventJunkFiles '' + set noswapfile + set nobackup + set nowritebackup + ''} + ${optionalString (cfg.bell == "none") '' + set noerrorbells + set novisualbell + ''} + ${optionalString (cfg.bell == "on") '' + set novisualbell + ''} + ${optionalString (cfg.bell == "visual") '' + set noerrorbells + ''} + ${optionalString (cfg.lineNumberMode == "relative") '' + set relativenumber + ''} + ${optionalString (cfg.lineNumberMode == "number") '' + set number + ''} + ${optionalString (cfg.lineNumberMode == "relNumber") '' + set number relativenumber + ''} + ${optionalString cfg.useSystemClipboard '' + set clipboard+=unnamedplus + ''} + ${optionalString cfg.mapLeaderSpace '' + let mapleader=" " + let maplocalleader=" " + ''} + ${optionalString cfg.syntaxHighlighting '' + syntax on + ''} + ${optionalString (!cfg.wordWrap) '' + set nowrap + ''} + ${optionalString cfg.hideSearchHighlight '' + set nohlsearch + set incsearch + ''} + ${optionalString cfg.colourTerm '' + set termguicolors + set t_Co=256 + ''} + ''; + }; +} diff --git a/modules/completion/default.nix b/modules/completion/default.nix new file mode 100644 index 0000000..bddc13b --- /dev/null +++ b/modules/completion/default.nix @@ -0,0 +1,126 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; +with builtins; let + cfg = config.vim.autocomplete; +in { + options.vim = { + autocomplete = { + enable = mkOption { + type = types.bool; + default = false; + description = "enable autocomplete"; + }; + + type = mkOption { + type = types.enum ["nvim-cmp"]; + default = "nvim-cmp"; + description = "Set the autocomplete plugin. Options: [nvim-cmp]"; + }; + }; + }; + + config = mkIf cfg.enable { + vim.startPlugins = [ + "nvim-cmp" + "cmp-buffer" + "cmp-vsnip" + "cmp-path" + "cmp-treesitter" + ]; + + vim.luaConfigRC.completion = mkIf (cfg.type == "nvim-cmp") (nvim.dag.entryAnywhere '' + local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + + local feedkey = function(key, mode) + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true) + end + + local cmp = require'cmp' + cmp.setup({ + snippet = { + expand = function(args) + vim.fn["vsnip#anonymous"](args.body) + end, + }, + sources = { + ${optionalString (config.vim.lsp.enable) "{ name = 'nvim_lsp' },"} + ${optionalString (config.vim.lsp.rust.enable) "{ name = 'crates' },"} + { name = 'vsnip' }, + { name = 'treesitter' }, + { name = 'path' }, + { name = 'buffer' }, + }, + mapping = { + [''] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }), + [''] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c'}), + [''] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c'}), + [''] = cmp.config.disable, + [''] = cmp.mapping({ + i = cmp.mapping.abort(), + c = cmp.mapping.close(), + }), + [''] = cmp.mapping.confirm({ + select = true, + }), + [''] = cmp.mapping(function (fallback) + if cmp.visible() then + cmp.select_next_item() + elseif vim.fn['vsnip#available'](1) == 1 then + feedkey("(vsnip-expand-or-jump)", "") + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function (fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif vim.fn['vsnip#available'](-1) == 1 then + feedkeys("(vsnip-jump-prev)", "") + end + end, { 'i', 's' }) + }, + completion = { + completeopt = 'menu,menuone,noinsert', + }, + formatting = { + format = function(entry, vim_item) + -- type of kind + vim_item.kind = ${ + optionalString (config.vim.visuals.lspkind.enable) + "require('lspkind').presets.default[vim_item.kind] .. ' ' .." + } vim_item.kind + + -- name for each source + vim_item.menu = ({ + buffer = "[Buffer]", + nvim_lsp = "[LSP]", + vsnip = "[VSnip]", + crates = "[Crates]", + path = "[Path]", + })[entry.source.name] + return vim_item + end, + } + }) + ${optionalString (config.vim.autopairs.enable && config.vim.autopairs.type == "nvim-autopairs") '' + local cmp_autopairs = require('nvim-autopairs.completion.cmp') + cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done({ map_char = { text = ""} })) + ''} + ''); + + vim.snippets.vsnip.enable = + if (cfg.type == "nvim-cmp") + then true + else config.vim.snippets.vsnip.enable; + }; +} diff --git a/modules/core/default.nix b/modules/core/default.nix new file mode 100644 index 0000000..0580cbe --- /dev/null +++ b/modules/core/default.nix @@ -0,0 +1,225 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; +with builtins; let + cfg = config.vim; + + wrapLuaConfig = luaConfig: '' + lua << EOF + ${luaConfig} + EOF + ''; + + mkMappingOption = it: + mkOption ({ + default = {}; + type = with types; attrsOf (nullOr str); + } + // it); +in { + options.vim = { + viAlias = mkOption { + description = "Enable vi alias"; + type = types.bool; + default = true; + }; + + vimAlias = mkOption { + description = "Enable vim alias"; + type = types.bool; + default = true; + }; + + configRC = mkOption { + description = "vimrc contents"; + type = nvim.types.dagOf types.lines; + default = {}; + }; + + luaConfigRC = mkOption { + description = "vim lua config"; + type = nvim.types.dagOf types.lines; + default = {}; + }; + + builtConfigRC = mkOption { + internal = true; + type = types.lines; + description = "The built config for neovim after resolving the DAG"; + }; + + startPlugins = nvim.types.pluginsOpt { + default = []; + description = "List of plugins to startup."; + }; + + optPlugins = nvim.types.pluginsOpt { + default = []; + description = "List of plugins to optionally load"; + }; + + globals = mkOption { + default = {}; + description = "Set containing global variable values"; + type = types.attrs; + }; + + nnoremap = + mkMappingOption {description = "Defines 'Normal mode' mappings";}; + + inoremap = mkMappingOption { + description = "Defines 'Insert and Replace mode' mappings"; + }; + + vnoremap = mkMappingOption { + description = "Defines 'Visual and Select mode' mappings"; + }; + + xnoremap = + mkMappingOption {description = "Defines 'Visual mode' mappings";}; + + snoremap = + mkMappingOption {description = "Defines 'Select mode' mappings";}; + + cnoremap = + mkMappingOption {description = "Defines 'Command-line mode' mappings";}; + + onoremap = mkMappingOption { + description = "Defines 'Operator pending mode' mappings"; + }; + + tnoremap = + mkMappingOption {description = "Defines 'Terminal mode' mappings";}; + + nmap = mkMappingOption {description = "Defines 'Normal mode' mappings";}; + + imap = mkMappingOption { + description = "Defines 'Insert and Replace mode' mappings"; + }; + + vmap = mkMappingOption { + description = "Defines 'Visual and Select mode' mappings"; + }; + + xmap = mkMappingOption {description = "Defines 'Visual mode' mappings";}; + + smap = mkMappingOption {description = "Defines 'Select mode' mappings";}; + + cmap = + mkMappingOption {description = "Defines 'Command-line mode' mappings";}; + + omap = mkMappingOption { + description = "Defines 'Operator pending mode' mappings"; + }; + + tmap = + mkMappingOption {description = "Defines 'Terminal mode' mappings";}; + }; + + config = let + mkVimBool = val: + if val + then "1" + else "0"; + valToVim = val: + if (isInt val) + then (builtins.toString val) + else + ( + if (isBool val) + then (mkVimBool val) + else (toJSON val) + ); + + filterNonNull = mappings: filterAttrs (name: value: value != null) mappings; + globalsScript = + mapAttrsFlatten (name: value: "let g:${name}=${valToVim value}") + (filterNonNull cfg.globals); + + matchCtrl = it: match "Ctrl-(.)(.*)" it; + mapKeyBinding = it: let + groups = matchCtrl it; + in + if groups == null + then it + else "${head (tail groups)}"; + mapVimBinding = prefix: mappings: + mapAttrsFlatten (name: value: "${prefix} ${mapKeyBinding name} ${value}") + (filterNonNull mappings); + + nmap = mapVimBinding "nmap" config.vim.nmap; + imap = mapVimBinding "imap" config.vim.imap; + vmap = mapVimBinding "vmap" config.vim.vmap; + xmap = mapVimBinding "xmap" config.vim.xmap; + smap = mapVimBinding "smap" config.vim.smap; + cmap = mapVimBinding "cmap" config.vim.cmap; + omap = mapVimBinding "omap" config.vim.omap; + tmap = mapVimBinding "tmap" config.vim.tmap; + + nnoremap = mapVimBinding "nnoremap" config.vim.nnoremap; + inoremap = mapVimBinding "inoremap" config.vim.inoremap; + vnoremap = mapVimBinding "vnoremap" config.vim.vnoremap; + xnoremap = mapVimBinding "xnoremap" config.vim.xnoremap; + snoremap = mapVimBinding "snoremap" config.vim.snoremap; + cnoremap = mapVimBinding "cnoremap" config.vim.cnoremap; + onoremap = mapVimBinding "onoremap" config.vim.onoremap; + tnoremap = mapVimBinding "tnoremap" config.vim.tnoremap; + + resolveDag = { + name, + dag, + mapResult, + }: let + sortedDag = nvim.dag.topoSort dag; + result = + if sortedDag ? result + then mapResult sortedDag.result + else abort ("Dependency cycle in ${name}: " + toJSON sortedConfig); + in + result; + in { + vim = { + configRC = { + globalsScript = nvim.dag.entryAnywhere (concatStringsSep "\n" globalsScript); + + luaScript = let + mkSection = r: '' + -- SECTION: ${r.name} + ${r.data} + ''; + mapResult = r: (wrapLuaConfig (concatStringsSep "\n" (map mkSection r))); + luaConfig = resolveDag { + name = "lua config script"; + dag = cfg.luaConfigRC; + inherit mapResult; + }; + in + nvim.dag.entryAfter ["globalsScript"] luaConfig; + + mappings = let + maps = [nmap imap vmap xmap smap cmap omap tmap nnoremap inoremap vnoremap xnoremap snoremap cnoremap onoremap tnoremap]; + mapConfig = concatStringsSep "\n" (map (v: concatStringsSep "\n" v) maps); + in + nvim.dag.entryAfter ["globalsScript"] mapConfig; + }; + + builtConfigRC = let + mkSection = r: '' + " SECTION: ${r.name} + ${r.data} + ''; + mapResult = r: (concatStringsSep "\n" (map mkSection r)); + vimConfig = resolveDag { + name = "vim config script"; + dag = cfg.configRC; + inherit mapResult; + }; + in + vimConfig; + }; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..5c1e08c --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,72 @@ +{inputs}: { + configuration, + pkgs, + lib ? pkgs.lib, + check ? true, + extraSpecialArgs ? {}, +}: let + inherit (pkgs) neovim-unwrapped wrapNeovim vimPlugins; + inherit (builtins) map filter isString toString getAttr hasAttr attrNames; + inherit (pkgs.vimUtils) buildVimPluginFrom2Nix; + + extendedLib = import ./lib/stdlib-extended.nix lib; + + nvimModules = import ./modules.nix { + inherit check pkgs; + lib = extendedLib; + }; + + module = extendedLib.evalModules { + modules = [configuration] ++ nvimModules; + specialArgs = + { + modulesPath = toString ./.; + } + // extraSpecialArgs; + }; + + buildPlug = name: + buildVimPluginFrom2Nix rec { + pname = name; + version = "master"; + src = assert lib.asserts.assertMsg (name != "nvim-treesitter") "Use buildTreesitterPlug for building nvim-treesitter."; + getAttr pname inputs; + }; + + buildTreesitterPlug = grammars: vimPlugins.nvim-treesitter.withPlugins (_: grammars); + + vimOptions = module.config.vim; + + buildConfigPlugins = plugins: + map + (plug: ( + if (isString plug) + then + ( + if (plug == "nvim-treesitter") + then (buildTreesitterPlug vimOptions.treesitter.grammars) + else (buildPlug plug) + ) + else plug + )) + (filter + (f: f != null) + plugins); + + neovim = wrapNeovim neovim-unwrapped { + viAlias = vimOptions.viAlias; + vimAlias = vimOptions.vimAlias; + configure = { + customRC = vimOptions.builtConfigRC; + + packages.myVimPackage = { + start = buildConfigPlugins vimOptions.startPlugins; + opt = buildConfigPlugins vimOptions.optPlugins; + }; + }; + }; +in { + inherit (module) options config; + inherit (module._module.args) pkgs; + inherit neovim; +} diff --git a/modules/filetree/default.nix b/modules/filetree/default.nix new file mode 100644 index 0000000..18441b5 --- /dev/null +++ b/modules/filetree/default.nix @@ -0,0 +1,10 @@ +{ + pkgs, + lib, + config, + ... +}: { + imports = [ + ./nvimtreelua.nix + ]; +} diff --git a/modules/filetree/nvimtreelua.nix b/modules/filetree/nvimtreelua.nix new file mode 100644 index 0000000..cb6f9bf --- /dev/null +++ b/modules/filetree/nvimtreelua.nix @@ -0,0 +1,186 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.filetree.nvimTreeLua; +in { + options.vim.filetree.nvimTreeLua = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable nvim-tree-lua"; + }; + + treeSide = mkOption { + default = "left"; + description = "Side the tree will appear on left or right"; + type = types.enum ["left" "right"]; + }; + + treeWidth = mkOption { + default = 25; + description = "Width of the tree in charecters"; + type = types.int; + }; + + hideFiles = mkOption { + default = [".git" "node_modules" ".cache"]; + description = "Files to hide in the file view by default."; + type = with types; listOf str; + }; + + hideIgnoredGitFiles = mkOption { + default = false; + description = "Hide files ignored by git"; + type = types.bool; + }; + + openOnSetup = mkOption { + default = true; + description = "Open when vim is started on a directory"; + type = types.bool; + }; + + closeOnLastWindow = mkOption { + default = true; + description = "Close when tree is last window open"; + type = types.bool; + }; + + ignoreFileTypes = mkOption { + default = []; + description = "Ignore file types"; + type = with types; listOf str; + }; + + closeOnFileOpen = mkOption { + default = false; + description = "Closes the tree when a file is opened."; + type = types.bool; + }; + + resizeOnFileOpen = mkOption { + default = false; + description = "Resizes the tree when opening a file."; + type = types.bool; + }; + + followBufferFile = mkOption { + default = true; + description = "Follow file that is in current buffer on tree"; + type = types.bool; + }; + + indentMarkers = mkOption { + default = true; + description = "Show indent markers"; + type = types.bool; + }; + + hideDotFiles = mkOption { + default = false; + description = "Hide dotfiles"; + type = types.bool; + }; + + openTreeOnNewTab = mkOption { + default = false; + description = "Opens the tree view when opening a new tab"; + type = types.bool; + }; + + disableNetRW = mkOption { + default = false; + description = "Disables netrw and replaces it with tree"; + type = types.bool; + }; + + hijackNetRW = mkOption { + default = true; + description = "Prevents netrw from automatically opening when opening directories"; + type = types.bool; + }; + + trailingSlash = mkOption { + default = true; + description = "Add a trailing slash to all folders"; + type = types.bool; + }; + + groupEmptyFolders = mkOption { + default = true; + description = "Compact empty folders trees into a single item"; + type = types.bool; + }; + + lspDiagnostics = mkOption { + default = true; + description = "Shows lsp diagnostics in the tree"; + type = types.bool; + }; + + systemOpenCmd = mkOption { + default = "${pkgs.xdg-utils}/bin/xdg-open"; + description = "The command used to open a file with the associated default program"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + vim.startPlugins = ["nvim-tree-lua"]; + + vim.nnoremap = { + "" = ":NvimTreeToggle"; + "tr" = ":NvimTreeRefresh"; + "tg" = ":NvimTreeFindFile"; + "tf" = ":NvimTreeFocus"; + }; + + vim.luaConfigRC.nvimtreelua = nvim.dag.entryAnywhere '' + require'nvim-tree'.setup({ + disable_netrw = ${boolToString cfg.disableNetRW}, + hijack_netrw = ${boolToString cfg.hijackNetRW}, + open_on_tab = ${boolToString cfg.openTreeOnNewTab}, + open_on_setup = ${boolToString cfg.openOnSetup}, + open_on_setup_file = ${boolToString cfg.openOnSetup}, + system_open = { + cmd = ${"'" + cfg.systemOpenCmd + "'"}, + }, + diagnostics = { + enable = ${boolToString cfg.lspDiagnostics}, + }, + view = { + width = ${toString cfg.treeWidth}, + side = ${"'" + cfg.treeSide + "'"}, + }, + renderer = { + indent_markers = { + enable = ${boolToString cfg.indentMarkers}, + }, + add_trailing = ${boolToString cfg.trailingSlash}, + group_empty = ${boolToString cfg.groupEmptyFolders}, + }, + actions = { + open_file = { + quit_on_open = ${boolToString cfg.closeOnFileOpen}, + resize_window = ${boolToString cfg.resizeOnFileOpen}, + }, + }, + git = { + enable = true, + ignore = ${boolToString cfg.hideIgnoredGitFiles}, + }, + filters = { + dotfiles = ${boolToString cfg.hideDotFiles}, + custom = { + ${builtins.concatStringsSep "\n" (builtins.map (s: "\"" + s + "\",") cfg.hideFiles)} + }, + }, + }) + ''; + }; +} diff --git a/modules/git/config.nix b/modules/git/config.nix new file mode 100644 index 0000000..7e12f2f --- /dev/null +++ b/modules/git/config.nix @@ -0,0 +1,14 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; { + config = { + vim.git = { + enable = mkDefault false; + gitsigns.enable = mkDefault false; + }; + }; +} diff --git a/modules/git/default.nix b/modules/git/default.nix new file mode 100644 index 0000000..cb09d72 --- /dev/null +++ b/modules/git/default.nix @@ -0,0 +1,11 @@ +{ + pkgs, + config, + lib, + ... +}: { + imports = [ + ./config.nix + ./git.nix + ]; +} diff --git a/modules/git/git.nix b/modules/git/git.nix new file mode 100644 index 0000000..07060bd --- /dev/null +++ b/modules/git/git.nix @@ -0,0 +1,69 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.git; +in { + options.vim.git = { + enable = mkOption { + type = types.bool; + description = "Enable git plugins"; + }; + + gitsigns.enable = mkOption { + type = types.bool; + description = "Enable git options"; + }; + }; + + config = + mkIf cfg.enable + ( + let + mkVimBool = val: + if val + then "1" + else "0"; + in { + vim.startPlugins = + if (cfg.gitsigns.enable) + then ["gitsigns-nvim"] + else []; + + vim.luaConfigRC.gitsigns = mkIf (cfg.gitsigns.enable) (nvim.dag.entryAnywhere '' + -- GitSigns setup + require('gitsigns').setup { + keymaps = { + noremap = true, + + ['n gn'] = { expr = true, "&diff ? \'\' : 'Gitsigns next_hunk'"}, + ['n gp'] = { expr = true, "&diff ? \'\' : 'Gitsigns prev_hunk'"}, + + ['n gs'] = 'Gitsigns stage_hunk', + ['v gs'] = ':Gitsigns stage_hunk', + ['n gu'] = 'Gitsigns undo_stage_hunk', + ['n gr'] = 'Gitsigns reset_hunk', + ['v gr'] = ':Gitsigns reset_hunk', + ['n gR'] = 'Gitsigns reset_buffer', + ['n gp'] = 'Gitsigns preview_hunk', + ['n gb'] = 'lua require"gitsigns".blame_line{full=true}', + ['n gS'] = 'Gitsigns stage_buffer', + ['n gU'] = 'Gitsigns reset_buffer_index', + ['n gts'] = ':Gitsigns toggle_signs', + ['n gtn'] = ':Gitsigns toggle_numhl', + ['n gtl'] = ':Gitsigns toggle_linehl', + ['n gtw'] = ':Gitsigns toggle_word_diff', + + -- Text objects + ['o ih'] = ':Gitsigns select_hunk', + ['x ih'] = ':Gitsigns select_hunk' + }, + } + ''); + } + ); +} diff --git a/modules/keys/default.nix b/modules/keys/default.nix new file mode 100644 index 0000000..5f5b71a --- /dev/null +++ b/modules/keys/default.nix @@ -0,0 +1,6 @@ +{ + config, + lib, + pkgs, + ... +}: {imports = [./which-key.nix];} diff --git a/modules/keys/which-key.nix b/modules/keys/which-key.nix new file mode 100644 index 0000000..0a8d145 --- /dev/null +++ b/modules/keys/which-key.nix @@ -0,0 +1,24 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.keys; +in { + options.vim.keys = { + enable = mkEnableOption "key binding plugins"; + + whichKey = { + enable = mkEnableOption "which-key menu"; + }; + }; + + config = mkIf (cfg.enable && cfg.whichKey.enable) { + vim.startPlugins = ["which-key"]; + + vim.luaConfigRC.whichkey = nvim.dag.entryAnywhere ''local wk = require("which-key").setup {}''; + }; +} diff --git a/modules/lib/booleans.nix b/modules/lib/booleans.nix new file mode 100644 index 0000000..277dd18 --- /dev/null +++ b/modules/lib/booleans.nix @@ -0,0 +1,9 @@ +# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/booleans.nix +{lib}: { + # Converts a boolean to a yes/no string. This is used in lots of + # configuration formats. + yesNo = value: + if value + then "yes" + else "no"; +} diff --git a/modules/lib/dag.nix b/modules/lib/dag.nix new file mode 100644 index 0000000..d6cc871 --- /dev/null +++ b/modules/lib/dag.nix @@ -0,0 +1,105 @@ +# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/dag.nix +# A generalization of Nixpkgs's `strings-with-deps.nix`. +# +# The main differences from the Nixpkgs version are +# +# - not specific to strings, i.e., any payload is OK, +# +# - the addition of the function `entryBefore` indicating a "wanted +# by" relationship. +{lib}: let + inherit (lib) all filterAttrs nvim mapAttrs toposort; +in { + empty = {}; + + isEntry = e: e ? data && e ? after && e ? before; + isDag = dag: + builtins.isAttrs dag && all nvim.dag.isEntry (builtins.attrValues dag); + + # Takes an attribute set containing entries built by entryAnywhere, + # entryAfter, and entryBefore to a topologically sorted list of + # entries. + # + # Internally this function uses the `toposort` function in + # `` and its value is accordingly. + # + # Specifically, the result on success is + # + # { result = [ { name = ?; data = ?; } … ] } + # + # For example + # + # nix-repl> topoSort { + # a = entryAnywhere "1"; + # b = entryAfter [ "a" "c" ] "2"; + # c = entryBefore [ "d" ] "3"; + # d = entryBefore [ "e" ] "4"; + # e = entryAnywhere "5"; + # } == { + # result = [ + # { data = "1"; name = "a"; } + # { data = "3"; name = "c"; } + # { data = "2"; name = "b"; } + # { data = "4"; name = "d"; } + # { data = "5"; name = "e"; } + # ]; + # } + # true + # + # And the result on error is + # + # { + # cycle = [ { after = ?; name = ?; data = ? } … ]; + # loops = [ { after = ?; name = ?; data = ? } … ]; + # } + # + # For example + # + # nix-repl> topoSort { + # a = entryAnywhere "1"; + # b = entryAfter [ "a" "c" ] "2"; + # c = entryAfter [ "d" ] "3"; + # d = entryAfter [ "b" ] "4"; + # e = entryAnywhere "5"; + # } == { + # cycle = [ + # { after = [ "a" "c" ]; data = "2"; name = "b"; } + # { after = [ "d" ]; data = "3"; name = "c"; } + # { after = [ "b" ]; data = "4"; name = "d"; } + # ]; + # loops = [ + # { after = [ "a" "c" ]; data = "2"; name = "b"; } + # ]; + # } + # true + topoSort = dag: let + dagBefore = dag: name: + builtins.attrNames + (filterAttrs (n: v: builtins.elem name v.before) dag); + normalizedDag = + mapAttrs (n: v: { + name = n; + data = v.data; + after = v.after ++ dagBefore dag n; + }) + dag; + before = a: b: builtins.elem a.name b.after; + sorted = toposort before (builtins.attrValues normalizedDag); + in + if sorted ? result + then { + result = map (v: {inherit (v) name data;}) sorted.result; + } + else sorted; + + # Applies a function to each element of the given DAG. + map = f: mapAttrs (n: v: v // {data = f n v.data;}); + + entryBetween = before: after: data: {inherit data before after;}; + + # Create a DAG entry with no particular dependency information. + entryAnywhere = nvim.dag.entryBetween [] []; + + entryAfter = nvim.dag.entryBetween []; + entryBefore = before: nvim.dag.entryBetween before []; +} diff --git a/modules/lib/default.nix b/modules/lib/default.nix new file mode 100644 index 0000000..bb4a271 --- /dev/null +++ b/modules/lib/default.nix @@ -0,0 +1,5 @@ +{lib}: { + dag = import ./dag.nix {inherit lib;}; + booleans = import ./booleans.nix {inherit lib;}; + types = import ./types.nix {inherit lib;}; +} diff --git a/modules/lib/stdlib-extended.nix b/modules/lib/stdlib-extended.nix new file mode 100644 index 0000000..f43bc15 --- /dev/null +++ b/modules/lib/stdlib-extended.nix @@ -0,0 +1,13 @@ +# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/stdlib-extended.nix +# Just a convenience function that returns the given Nixpkgs standard +# library extended with the HM library. +nixpkgsLib: let + mkNvimLib = import ./.; +in + nixpkgsLib.extend (self: super: { + nvim = mkNvimLib {lib = self;}; + + # For forward compatibility. + literalExpression = super.literalExpression or super.literalExample; + literalDocBook = super.literalDocBook or super.literalExample; + }) diff --git a/modules/lib/types-dag.nix b/modules/lib/types-dag.nix new file mode 100644 index 0000000..439c09d --- /dev/null +++ b/modules/lib/types-dag.nix @@ -0,0 +1,68 @@ +# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/types-dag.nix +# Used for ordering config text. +{lib}: let + inherit + (lib) + defaultFunctor + nvim + mkIf + mkOrder + mkOption + mkOptionType + types + ; + + dagEntryOf = elemType: let + submoduleType = types.submodule ({name, ...}: { + options = { + data = mkOption {type = elemType;}; + after = mkOption {type = with types; listOf str;}; + before = mkOption {type = with types; listOf str;}; + }; + config = mkIf (elemType.name == "submodule") { + data._module.args.dagName = name; + }; + }); + maybeConvert = def: + if nvim.dag.isEntry def.value + then def.value + else + nvim.dag.entryAnywhere ( + if def ? priority + then mkOrder def.priority def.value + else def.value + ); + in + mkOptionType { + name = "dagEntryOf"; + description = "DAG entry of ${elemType.description}"; + # leave the checking to the submodule type + merge = loc: defs: + submoduleType.merge loc (map (def: { + inherit (def) file; + value = maybeConvert def; + }) + defs); + }; +in rec { + # A directed acyclic graph of some inner type. + # + # Note, if the element type is a submodule then the `name` argument + # will always be set to the string "data" since it picks up the + # internal structure of the DAG values. To give access to the + # "actual" attribute name a new submodule argument is provided with + # the name `dagName`. + dagOf = elemType: let + attrEquivalent = types.attrsOf (dagEntryOf elemType); + in + mkOptionType rec { + name = "dagOf"; + description = "DAG of ${elemType.description}"; + inherit (attrEquivalent) check merge emptyValue; + getSubOptions = prefix: elemType.getSubOptions (prefix ++ [""]); + getSubModules = elemType.getSubModules; + substSubModules = m: dagOf (elemType.substSubModules m); + functor = (defaultFunctor name) // {wrapped = elemType;}; + nestedTypes.elemType = elemType; + }; +} diff --git a/modules/lib/types-plugin.nix b/modules/lib/types-plugin.nix new file mode 100644 index 0000000..3cdca58 --- /dev/null +++ b/modules/lib/types-plugin.nix @@ -0,0 +1,55 @@ +{lib}: +with lib; let + # Plugin must be same as input name + availablePlugins = [ + "nvim-treesitter-context" + "gitsigns-nvim" + "plenary-nvim" + "nvim-lspconfig" + "nvim-treesitter" + "lspsaga" + "lspkind" + "nvim-lightbulb" + "lsp-signature" + "nvim-tree-lua" + "nvim-bufferline-lua" + "lualine" + "nvim-compe" + "nvim-autopairs" + "nvim-ts-autotag" + "nvim-web-devicons" + "tokyonight" + "bufdelete-nvim" + "nvim-cmp" + "cmp-nvim-lsp" + "cmp-buffer" + "cmp-vsnip" + "cmp-path" + "cmp-treesitter" + "crates-nvim" + "vim-vsnip" + "nvim-code-action-menu" + "trouble" + "null-ls" + "which-key" + "indent-blankline" + "nvim-cursorline" + "sqls-nvim" + "glow-nvim" + "telescope" + "rust-tools" + "onedark" + "catppuccin" + ]; + + pluginsType = with types; listOf (nullOr (either (enum availablePlugins) package)); +in { + pluginsOpt = { + description, + default ? [], + }: + mkOption { + inherit description default; + type = pluginsType; + }; +} diff --git a/modules/lib/types.nix b/modules/lib/types.nix new file mode 100644 index 0000000..8625f18 --- /dev/null +++ b/modules/lib/types.nix @@ -0,0 +1,7 @@ +{lib}: let + typesDag = import ./types-dag.nix {inherit lib;}; + typesPlugin = import ./types-plugin.nix {inherit lib;}; +in { + inherit (typesDag) dagOf; + inherit (typesPlugin) pluginsOpt; +} diff --git a/modules/lsp/default.nix b/modules/lsp/default.nix new file mode 100644 index 0000000..00c751d --- /dev/null +++ b/modules/lsp/default.nix @@ -0,0 +1,15 @@ +{ + config, + lib, + pkgs, + ... +}: { + imports = [ + ./lsp.nix + ./lspsaga.nix + ./nvim-code-action-menu.nix + ./trouble.nix + ./lsp-signature.nix + ./lightbulb.nix + ]; +} diff --git a/modules/lsp/lightbulb.nix b/modules/lsp/lightbulb.nix new file mode 100644 index 0000000..cbd7622 --- /dev/null +++ b/modules/lsp/lightbulb.nix @@ -0,0 +1,29 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = { + lightbulb = { + enable = mkEnableOption "lightbulb for code actions. Requires emoji font"; + }; + }; + + config = mkIf (cfg.enable && cfg.lightbulb.enable) { + vim.startPlugins = ["nvim-lightbulb"]; + + vim.configRC.lightbulb = nvim.dag.entryAnywhere '' + autocmd CursorHold,CursorHoldI * lua require'nvim-lightbulb'.update_lightbulb() + ''; + + vim.luaConfigRC.lightbulb = nvim.dag.entryAnywhere '' + -- Enable trouble diagnostics viewer + require'nvim-lightbulb'.setup() + ''; + }; +} diff --git a/modules/lsp/lsp-signature.nix b/modules/lsp/lsp-signature.nix new file mode 100644 index 0000000..1d77040 --- /dev/null +++ b/modules/lsp/lsp-signature.nix @@ -0,0 +1,25 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = { + lspSignature = { + enable = mkEnableOption "lsp signature viewer"; + }; + }; + + config = mkIf (cfg.enable && cfg.lspSignature.enable) { + vim.startPlugins = ["lsp-signature"]; + + vim.luaConfigRC.lsp-signature = nvim.dag.entryAnywhere '' + -- Enable lsp signature viewer + require("lsp_signature").setup() + ''; + }; +} diff --git a/modules/lsp/lsp.nix b/modules/lsp/lsp.nix new file mode 100644 index 0000000..5435cc5 --- /dev/null +++ b/modules/lsp/lsp.nix @@ -0,0 +1,405 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = { + enable = mkEnableOption "neovim lsp support"; + formatOnSave = mkEnableOption "Format on save"; + nix = { + enable = mkEnableOption "Nix LSP"; + server = mkOption { + type = with types; enum ["rnix" "nil"]; + default = "nil"; + description = "Which LSP to use"; + }; + + pkg = mkOption { + type = types.package; + default = + if (cfg.nix.server == "rnix") + then pkgs.rnix-lsp + else pkgs.nil; + description = "The LSP package to use"; + }; + + formatter = mkOption { + type = with types; enum ["nixpkgs-fmt" "alejandra"]; + default = "alejandra"; + description = "Which nix formatter to use"; + }; + }; + rust = { + enable = mkEnableOption "Rust LSP"; + rustAnalyzerOpts = mkOption { + type = types.str; + default = '' + ["rust-analyzer"] = { + experimental = { + procAttrMacros = true, + }, + }, + ''; + description = "options to pass to rust analyzer"; + }; + }; + python = mkEnableOption "Python LSP"; + clang = { + enable = mkEnableOption "C language LSP"; + c_header = mkEnableOption "C syntax header files"; + cclsOpts = mkOption { + type = types.str; + default = ""; + }; + }; + sql = mkEnableOption "SQL Language LSP"; + go = mkEnableOption "Go language LSP"; + ts = mkEnableOption "TS language LSP"; + zig.enable = mkEnableOption "Zig language LSP"; + }; + + config = mkIf cfg.enable ( + let + writeIf = cond: msg: + if cond + then msg + else ""; + in { + vim.startPlugins = + [ + "nvim-lspconfig" + "null-ls" + ( + if (config.vim.autocomplete.enable && (config.vim.autocomplete.type == "nvim-cmp")) + then "cmp-nvim-lsp" + else null + ) + ( + if cfg.sql + then "sqls-nvim" + else null + ) + ] + ++ ( + if cfg.rust.enable + then [ + "crates-nvim" + "rust-tools" + ] + else [] + ); + + vim.configRC.lsp = nvim.dag.entryAnywhere '' + ${ + if cfg.nix.enable + then '' + autocmd filetype nix setlocal tabstop=2 shiftwidth=2 softtabstop=2 + '' + else "" + } + + ${ + if cfg.clang.c_header + then '' + " c syntax for header (otherwise breaks treesitter highlighting) + " https://www.reddit.com/r/neovim/comments/orfpcd/question_does_the_c_parser_from_nvimtreesitter/ + let g:c_syntax_for_h = 1 + '' + else "" + } + ''; + vim.luaConfigRC.lsp = nvim.dag.entryAnywhere '' + + local attach_keymaps = function(client, bufnr) + local opts = { noremap=true, silent=true } + + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lgD', 'lua vim.lsp.buf.declaration()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lgd', 'lua vim.lsp.buf.definition()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lgt', 'lua vim.lsp.buf.type_definition()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lgn', 'lua vim.diagnostic.goto_next()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lgp', 'lua vim.diagnostic.goto_prev()', opts) + + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lwa', 'lua vim.lsp.buf.add_workspace_folder()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lwr', 'lua vim.lsp.buf.remove_workspace_folder()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lwl', 'lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))', opts) + + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'lh', 'lua vim.lsp.buf.hover()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'ls', 'lua vim.lsp.buf.signature_help()', opts) + vim.api.nvim_buf_set_keymap(bufnr, 'n', 'ln', 'lua vim.lsp.buf.rename()', opts) + end + + local null_ls = require("null-ls") + local null_helpers = require("null-ls.helpers") + local null_methods = require("null-ls.methods") + + local ls_sources = { + ${writeIf cfg.python + '' + null_ls.builtins.formatting.black.with({ + command = "${pkgs.black}/bin/black", + }), + ''} + + -- Commented out for now + --${writeIf (config.vim.git.enable && config.vim.git.gitsigns.enable) '' + -- null_ls.builtins.code_actions.gitsigns, + --''} + + ${writeIf cfg.sql + '' + null_helpers.make_builtin({ + method = null_methods.internal.FORMATTING, + filetypes = { "sql" }, + generator_opts = { + to_stdin = true, + ignore_stderr = true, + suppress_errors = true, + command = "${pkgs.sqlfluff}/bin/sqlfluff", + args = { + "fix", + "-", + }, + }, + factory = null_helpers.formatter_factory, + }), + + null_ls.builtins.diagnostics.sqlfluff.with({ + command = "${pkgs.sqlfluff}/bin/sqlfluff", + extra_args = {"--dialect", "postgres"} + }), + ''} + + ${writeIf + (cfg.nix.enable + && cfg.nix.server == "rnix" + && cfg.nix.formatter == "alejandra") + '' + null_ls.builtins.formatting.alejandra.with({ + command = "${pkgs.alejandra}/bin/alejandra" + }), + ''} + + ${writeIf cfg.ts + '' + null_ls.builtins.diagnostics.eslint, + null_ls.builtins.formatting.prettier, + ''} + } + + vim.g.formatsave = ${ + if cfg.formatOnSave + then "true" + else "false" + }; + + -- Enable formatting + format_callback = function(client, bufnr) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + if vim.g.formatsave then + local params = require'vim.lsp.util'.make_formatting_params({}) + client.request('textDocument/formatting', params, nil, bufnr) + end + end + }) + end + + default_on_attach = function(client, bufnr) + attach_keymaps(client, bufnr) + format_callback(client, bufnr) + end + + -- Enable null-ls + require('null-ls').setup({ + diagnostics_format = "[#{m}] #{s} (#{c})", + debounce = 250, + default_timeout = 5000, + sources = ls_sources, + on_attach=default_on_attach + }) + + -- Enable lspconfig + local lspconfig = require('lspconfig') + + local capabilities = vim.lsp.protocol.make_client_capabilities() + ${ + let + cfg = config.vim.autocomplete; + in + writeIf cfg.enable ( + if cfg.type == "nvim-cmp" + then '' + capabilities = require('cmp_nvim_lsp').default_capabilities() + '' + else "" + ) + } + + ${writeIf cfg.rust.enable '' + -- Rust config + local rt = require('rust-tools') + + rust_on_attach = function(client, bufnr) + default_on_attach(client, bufnr) + local opts = { noremap=true, silent=true, buffer = bufnr } + vim.keymap.set("n", "ris", rt.inlay_hints.set, opts) + vim.keymap.set("n", "riu", rt.inlay_hints.unset, opts) + vim.keymap.set("n", "rr", rt.runnables.runnables, opts) + vim.keymap.set("n", "rp", rt.parent_module.parent_module, opts) + vim.keymap.set("n", "rm", rt.expand_macro.expand_macro, opts) + vim.keymap.set("n", "rc", rt.open_cargo_toml.open_cargo_toml, opts) + vim.keymap.set("n", "rg", function() rt.crate_graph.view_crate_graph("x11", nil) end, opts) + end + + local rustopts = { + tools = { + autoSetHints = true, + hover_with_actions = false, + inlay_hints = { + only_current_line = false, + } + }, + server = { + capabilities = capabilities, + on_attach = rust_on_attach, + cmd = {"${pkgs.rust-analyzer}/bin/rust-analyzer"}, + settings = { + ${cfg.rust.rustAnalyzerOpts} + } + } + } + + require('crates').setup { + null_ls = { + enabled = true, + name = "crates.nvim", + } + } + rt.setup(rustopts) + ''} + + ${optionalString cfg.zig.enable '' + -- Zig config + lspconfig.zls.setup { + capabilities = capabilities, + on_attach=default_on_attach, + cmd = {"${pkgs.zls}/bin/zls"}, + settings = { + ["zls"] = { + zig_exe_path = "${pkgs.zig}/bin/zig", + zig_lib_path = "${pkgs.zig}/lib/zig", + } + } + } + ''} + + ${writeIf cfg.python '' + -- Python config + lspconfig.pyright.setup{ + capabilities = capabilities; + on_attach=default_on_attach; + cmd = {"${pkgs.nodePackages.pyright}/bin/pyright-langserver", "--stdio"} + } + ''} + + ${writeIf cfg.nix.enable ( + (writeIf (cfg.nix.server == "rnix") '' + -- Nix (rnix) config + lspconfig.rnix.setup{ + capabilities = capabilities, + ${writeIf (cfg.nix.formatter == "alejandra") + '' + on_attach = function(client, bufnr) + attach_keymaps(client, bufnr) + end, + ''} + ${writeIf (cfg.nix.formatter == "nixpkgs-fmt") + '' + on_attach = default_on_attach, + ''} + cmd = {"${cfg.nix.pkg}/bin/rnix-lsp"}, + } + '') + + (writeIf (cfg.nix.server == "nil") '' + -- Nix (nil) config + lspconfig.nil_ls.setup{ + capabilities = capabilities, + on_attach=default_on_attach, + cmd = {"${cfg.nix.pkg}/bin/nil"}, + settings = { + ["nil"] = { + ${writeIf (cfg.nix.formatter == "alejandra") + '' + formatting = { + command = {"${pkgs.alejandra}/bin/alejandra", "--quiet"}, + }, + ''} + ${writeIf (cfg.nix.formatter == "nixpkgs-fmt") + '' + formatting = { + command = {"${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt"}, + }, + ''} + }, + }; + } + '') + )} + + + ${writeIf cfg.clang.enable '' + -- CCLS (clang) config + lspconfig.ccls.setup{ + capabilities = capabilities; + on_attach=default_on_attach; + cmd = {"${pkgs.ccls}/bin/ccls"}; + ${ + if cfg.clang.cclsOpts == "" + then "" + else "init_options = ${cfg.clang.cclsOpts}" + } + } + ''} + + ${writeIf cfg.sql '' + -- SQLS config + lspconfig.sqls.setup { + on_attach = function(client) + client.server_capabilities.execute_command = true + on_attach_keymaps(client, bufnr) + require'sqls'.setup{} + end, + cmd = {"${pkgs.sqls}/bin/sqls", "-config", string.format("%s/config.yml", vim.fn.getcwd()) } + } + ''} + + ${writeIf cfg.go '' + -- Go config + lspconfig.gopls.setup { + capabilities = capabilities; + on_attach = default_on_attach; + cmd = {"${pkgs.gopls}/bin/gopls", "serve"}, + } + ''} + + ${writeIf cfg.ts '' + -- TS config + lspconfig.tsserver.setup { + capabilities = capabilities; + on_attach = function(client, bufnr) + attach_keymaps(client, bufnr) + end, + cmd = { "${pkgs.nodePackages.typescript-language-server}/bin/typescript-language-server", "--stdio" } + } + ''} + ''; + } + ); +} diff --git a/modules/lsp/lspsaga.nix b/modules/lsp/lspsaga.nix new file mode 100644 index 0000000..d244594 --- /dev/null +++ b/modules/lsp/lspsaga.nix @@ -0,0 +1,54 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = {lspsaga = {enable = mkEnableOption "LSP Saga";};}; + + config = mkIf (cfg.enable && cfg.lspsaga.enable) { + vim.startPlugins = ["lspsaga"]; + + vim.vnoremap = { + "ca" = ":lua require('lspsaga.codeaction').range_code_action()"; + }; + + vim.nnoremap = + { + "lf" = "lua require'lspsaga.provider'.lsp_finder()"; + "lh" = "lua require('lspsaga.hover').render_hover_doc()"; + "" = "lua require('lspsaga.action').smart_scroll_with_saga(1)"; + "" = "lua require('lspsaga.action').smart_scroll_with_saga(-1)"; + "lr" = "lua require'lspsaga.rename'.rename()"; + "ld" = "lua require'lspsaga.provider'.preview_definition()"; + "ll" = "lua require'lspsaga.diagnostic'.show_line_diagnostics()"; + "lc" = "lua require'lspsaga.diagnostic'.show_cursor_diagnostics()"; + "lp" = "lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_prev()"; + "ln" = "lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_next()"; + } + // ( + if (!cfg.nvimCodeActionMenu.enable) + then { + "ca" = "lua require('lspsaga.codeaction').code_action()"; + } + else {} + ) + // ( + if (!cfg.lspSignature.enable) + then { + "ls" = "lua require('lspsaga.signaturehelp').signature_help()"; + } + else {} + ); + + vim.luaConfigRC.lspsage = nvim.dag.entryAnywhere '' + -- Enable lspsaga + local saga = require 'lspsaga' + saga.init_lsp_saga() + ''; + }; +} diff --git a/modules/lsp/nvim-code-action-menu.nix b/modules/lsp/nvim-code-action-menu.nix new file mode 100644 index 0000000..ac8b8d6 --- /dev/null +++ b/modules/lsp/nvim-code-action-menu.nix @@ -0,0 +1,24 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = { + nvimCodeActionMenu = { + enable = mkEnableOption "nvim code action menu"; + }; + }; + + config = mkIf (cfg.enable && cfg.nvimCodeActionMenu.enable) { + vim.startPlugins = ["nvim-code-action-menu"]; + + vim.nnoremap = { + "ca" = ":CodeActionMenu"; + }; + }; +} diff --git a/modules/lsp/trouble.nix b/modules/lsp/trouble.nix new file mode 100644 index 0000000..a96ce5d --- /dev/null +++ b/modules/lsp/trouble.nix @@ -0,0 +1,34 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.lsp; +in { + options.vim.lsp = { + trouble = { + enable = mkEnableOption "trouble diagnostics viewer"; + }; + }; + + config = mkIf (cfg.enable && cfg.trouble.enable) { + vim.startPlugins = ["trouble"]; + + vim.nnoremap = { + "xx" = "TroubleToggle"; + "lwd" = "TroubleToggle workspace_diagnostics"; + "ld" = "TroubleToggle document_diagnostics"; + "lr" = "TroubleToggle lsp_references"; + "xq" = "TroubleToggle quickfix"; + "xl" = "TroubleToggle loclist"; + }; + + vim.luaConfigRC.trouble = nvim.dag.entryAnywhere '' + -- Enable trouble diagnostics viewer + require("trouble").setup {} + ''; + }; +} diff --git a/modules/markdown/config.nix b/modules/markdown/config.nix new file mode 100644 index 0000000..72b0007 --- /dev/null +++ b/modules/markdown/config.nix @@ -0,0 +1,14 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; { + config = { + vim.markdown = { + enable = mkDefault false; + glow.enable = mkDefault false; + }; + }; +} diff --git a/modules/markdown/default.nix b/modules/markdown/default.nix new file mode 100644 index 0000000..b039f6e --- /dev/null +++ b/modules/markdown/default.nix @@ -0,0 +1,11 @@ +{ + config, + lib, + pkgs, + ... +}: { + imports = [ + ./config.nix + ./glow.nix + ]; +} diff --git a/modules/markdown/glow.nix b/modules/markdown/glow.nix new file mode 100644 index 0000000..e658446 --- /dev/null +++ b/modules/markdown/glow.nix @@ -0,0 +1,38 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.markdown; +in { + options.vim.markdown = { + enable = mkEnableOption "markdown tools and plugins"; + + glow.enable = mkOption { + type = types.bool; + default = true; + description = "Enable markdown preview in neovim with glow"; + }; + }; + + config = mkIf (cfg.enable) { + vim.startPlugins = [ + ( + if cfg.glow.enable + then "glow-nvim" + else null + ) + ]; + + vim.globals = mkIf (cfg.glow.enable) { + "glow_binary_path" = "${pkgs.glow}/bin"; + }; + + vim.configRC.glow = mkIf (cfg.glow.enable) (nvim.dag.entryAnywhere '' + autocmd FileType markdown noremap p :Glow + ''); + }; +} diff --git a/modules/modules.nix b/modules/modules.nix new file mode 100644 index 0000000..ab682b6 --- /dev/null +++ b/modules/modules.nix @@ -0,0 +1,35 @@ +{ + pkgs, + lib, + check ? true, +}: let + modules = [ + ./completion + ./theme + ./core + ./basic + ./statusline + ./tabline + ./filetree + ./visuals + ./lsp + ./treesitter + ./tidal + ./autopairs + ./snippets + ./keys + ./markdown + ./telescope + ./git + ]; + + pkgsModule = {config, ...}: { + config = { + _module.args.baseModules = modules; + _module.args.pkgsPath = lib.mkDefault pkgs.path; + _module.args.pkgs = lib.mkDefault pkgs; + _module.check = check; + }; + }; +in + modules ++ [pkgsModule] diff --git a/modules/snippets/default.nix b/modules/snippets/default.nix new file mode 100644 index 0000000..dd88e3c --- /dev/null +++ b/modules/snippets/default.nix @@ -0,0 +1,10 @@ +{ + pkgs, + lib, + config, + ... +}: { + imports = [ + ./vsnip.nix + ]; +} diff --git a/modules/snippets/vsnip.nix b/modules/snippets/vsnip.nix new file mode 100644 index 0000000..671671c --- /dev/null +++ b/modules/snippets/vsnip.nix @@ -0,0 +1,18 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.snippets.vsnip; +in { + options.vim.snippets.vsnip = { + enable = mkEnableOption "Enable vim-vsnip"; + }; + + config = mkIf cfg.enable { + vim.startPlugins = ["vim-vsnip"]; + }; +} diff --git a/modules/statusline/config.nix b/modules/statusline/config.nix new file mode 100644 index 0000000..6503543 --- /dev/null +++ b/modules/statusline/config.nix @@ -0,0 +1,65 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; { + config = { + vim.statusline.lualine = { + enable = mkDefault false; + + icons = mkDefault true; + theme = mkDefault "auto"; + sectionSeparator = { + left = mkDefault ""; + right = mkDefault ""; + }; + + componentSeparator = { + left = mkDefault "⏽"; + right = mkDefault "⏽"; + }; + + activeSection = { + a = mkDefault "{'mode'}"; + b = '' + { + { + "branch", + separator = '', + }, + "diff", + } + ''; + c = mkDefault "{'filename'}"; + x = mkDefault '' + { + { + "diagnostics", + sources = {'nvim_lsp'}, + separator = '', + symbols = {error = '', warn = '', info = '', hint = ''}, + }, + { + "filetype", + }, + "fileformat", + "encoding", + } + ''; + y = mkDefault "{'progress'}"; + z = mkDefault "{'location'}"; + }; + + inactiveSection = { + a = mkDefault "{}"; + b = mkDefault "{}"; + c = mkDefault "{'filename'}"; + x = mkDefault "{'location'}"; + y = mkDefault "{}"; + z = mkDefault "{}"; + }; + }; + }; +} diff --git a/modules/statusline/default.nix b/modules/statusline/default.nix new file mode 100644 index 0000000..5d638c9 --- /dev/null +++ b/modules/statusline/default.nix @@ -0,0 +1,11 @@ +{ + pkgs, + config, + lib, + ... +}: { + imports = [ + ./lualine.nix + ./config.nix + ]; +} diff --git a/modules/statusline/lualine.nix b/modules/statusline/lualine.nix new file mode 100644 index 0000000..aba8466 --- /dev/null +++ b/modules/statusline/lualine.nix @@ -0,0 +1,205 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.statusline.lualine; + supported_themes = import ./supported_lualine_themes.nix; +in { + options.vim.statusline.lualine = { + enable = mkOption { + type = types.bool; + description = "Enable lualine"; + }; + + icons = mkOption { + type = types.bool; + description = "Enable icons for lualine"; + }; + + theme = mkOption { + type = types.enum ( + [ + "auto" + "16color" + "gruvbox" + "ayu_dark" + "ayu_light" + "ayu_mirage" + "codedark" + "dracula" + "everforest" + "gruvbox" + "gruvbox_light" + "gruvbox_material" + "horizon" + "iceberg_dark" + "iceberg_light" + "jellybeans" + "material" + "modus_vivendi" + "molokai" + "nightfly" + "nord" + "oceanicnext" + "onelight" + "palenight" + "papercolor_dark" + "papercolor_light" + "powerline" + "seoul256" + "solarized_dark" + "tomorrow" + "wombat" + ] + ++ ( + if elem config.vim.theme.name supported_themes + then [config.vim.theme.name] + else [] + ) + ); + description = "Theme for lualine"; + }; + + sectionSeparator = { + left = mkOption { + type = types.str; + description = "Section separator for left side"; + }; + + right = mkOption { + type = types.str; + description = "Section separator for right side"; + }; + }; + + componentSeparator = { + left = mkOption { + type = types.str; + description = "Component separator for left side"; + }; + + right = mkOption { + type = types.str; + description = "Component separator for right side"; + }; + }; + + activeSection = { + a = mkOption { + type = types.str; + description = "active config for: | (A) | B | C X | Y | Z |"; + }; + + b = mkOption { + type = types.str; + description = "active config for: | A | (B) | C X | Y | Z |"; + }; + + c = mkOption { + type = types.str; + description = "active config for: | A | B | (C) X | Y | Z |"; + }; + + x = mkOption { + type = types.str; + description = "active config for: | A | B | C (X) | Y | Z |"; + }; + + y = mkOption { + type = types.str; + description = "active config for: | A | B | C X | (Y) | Z |"; + }; + + z = mkOption { + type = types.str; + description = "active config for: | A | B | C X | Y | (Z) |"; + }; + }; + + inactiveSection = { + a = mkOption { + type = types.str; + description = "inactive config for: | (A) | B | C X | Y | Z |"; + }; + + b = mkOption { + type = types.str; + description = "inactive config for: | A | (B) | C X | Y | Z |"; + }; + + c = mkOption { + type = types.str; + description = "inactive config for: | A | B | (C) X | Y | Z |"; + }; + + x = mkOption { + type = types.str; + description = "inactive config for: | A | B | C (X) | Y | Z |"; + }; + + y = mkOption { + type = types.str; + description = "inactive config for: | A | B | C X | (Y) | Z |"; + }; + + z = mkOption { + type = types.str; + description = "inactive config for: | A | B | C X | Y | (Z) |"; + }; + }; + }; + + config = + mkIf cfg.enable + { + #assertions = [ + # ({ + # assertion = if cfg.icons then (config.vim.visuals.enable && config.vim.visuals.nvimWebDevicons.enable) else true; + # message = "Must enable config.vim.visual.nvimWebDevicons if using config.vim.visuals.lualine.icons"; + # }) + #]; + + vim.startPlugins = ["lualine"]; + vim.luaConfigRC.lualine = nvim.dag.entryAnywhere '' + require'lualine'.setup { + options = { + icons_enabled = ${ + if cfg.icons + then "true" + else "false" + }, + theme = "${cfg.theme}", + component_separators = {"${cfg.componentSeparator.left}","${cfg.componentSeparator.right}"}, + section_separators = {"${cfg.sectionSeparator.left}","${cfg.sectionSeparator.right}"}, + disabled_filetypes = {}, + }, + sections = { + lualine_a = ${cfg.activeSection.a}, + lualine_b = ${cfg.activeSection.b}, + lualine_c = ${cfg.activeSection.c}, + lualine_x = ${cfg.activeSection.x}, + lualine_y = ${cfg.activeSection.y}, + lualine_z = ${cfg.activeSection.z}, + }, + inactive_sections = { + lualine_a = ${cfg.inactiveSection.a}, + lualine_b = ${cfg.inactiveSection.b}, + lualine_c = ${cfg.inactiveSection.c}, + lualine_x = ${cfg.inactiveSection.x}, + lualine_y = ${cfg.inactiveSection.y}, + lualine_z = ${cfg.inactiveSection.z}, + }, + tabline = {}, + extensions = {${ + if config.vim.filetree.nvimTreeLua.enable + then "\"nvim-tree\"" + else "" + }}, + } + ''; + }; +} diff --git a/modules/statusline/supported_lualine_themes.nix b/modules/statusline/supported_lualine_themes.nix new file mode 100644 index 0000000..e5de3f6 --- /dev/null +++ b/modules/statusline/supported_lualine_themes.nix @@ -0,0 +1,5 @@ +[ + "tokyonight" + "onedark" + "catppuccin" +] diff --git a/modules/tabline/default.nix b/modules/tabline/default.nix new file mode 100644 index 0000000..4d16dfb --- /dev/null +++ b/modules/tabline/default.nix @@ -0,0 +1,10 @@ +{ + pkgs, + lib, + config, + ... +}: { + imports = [ + ./nvim-bufferline.nix + ]; +} diff --git a/modules/tabline/nvim-bufferline.nix b/modules/tabline/nvim-bufferline.nix new file mode 100644 index 0000000..fca433f --- /dev/null +++ b/modules/tabline/nvim-bufferline.nix @@ -0,0 +1,100 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.tabline.nvimBufferline; +in { + options.vim.tabline.nvimBufferline = { + enable = mkEnableOption "nvim-bufferline-lua"; + }; + + config = mkIf cfg.enable ( + let + mouse = { + right = "'vertical sbuffer %d'"; + close = '' + function(bufnum) + require("bufdelete").bufdelete(bufnum, false) + end + ''; + }; + in { + vim.startPlugins = [ + (assert config.vim.visuals.nvimWebDevicons.enable == true; "nvim-bufferline-lua") + "bufdelete-nvim" + ]; + + vim.nnoremap = { + "bn" = ":BufferLineCycleNext"; + "bp" = ":BufferLineCyclePrev"; + "bc" = ":BufferLinePick"; + "bse" = ":BufferLineSortByExtension"; + "bsd" = ":BufferLineSortByDirectory"; + "bsi" = ":lua require'bufferline'.sort_buffers_by(function (buf_a, buf_b) return buf_a.id < buf_b.id end)"; + "bmn" = ":BufferLineMoveNext"; + "bmp" = ":BufferLineMovePrev"; + "b1" = "BufferLineGoToBuffer 1"; + "b2" = "BufferLineGoToBuffer 2"; + "b3" = "BufferLineGoToBuffer 3"; + "b4" = "BufferLineGoToBuffer 4"; + "b5" = "BufferLineGoToBuffer 5"; + "b6" = "BufferLineGoToBuffer 6"; + "b7" = "BufferLineGoToBuffer 7"; + "b8" = "BufferLineGoToBuffer 8"; + "b9" = "BufferLineGoToBuffer 9"; + }; + + vim.luaConfigRC.nvimBufferline = nvim.dag.entryAnywhere '' + require("bufferline").setup{ + options = { + numbers = "both", + close_command = ${mouse.close}, + right_mouse_command = ${mouse.right}, + indicator = { + indicator_icon = '▎', + style = 'icon', + }, + buffer_close_icon = '', + modified_icon = '●', + close_icon = '', + left_trunc_marker = '', + right_trunc_marker = '', + separator_style = "thin", + max_name_length = 18, + max_prefix_length = 15, + tab_size = 18, + show_buffer_icons = true, + show_buffer_close_icons = true, + show_close_icon = true, + show_tab_indicators = true, + persist_buffer_sort = true, + enforce_regular_tabs = false, + always_show_bufferline = true, + offsets = {{filetype = "NvimTree", text = "File Explorer", text_align = "left"}}, + sort_by = 'extension', + diagnostics = "nvim_lsp", + diagnostics_update_in_insert = true, + diagnostics_indicator = function(count, level, diagnostics_dict, context) + local s = "" + for e, n in pairs(diagnostics_dict) do + local sym = e == "error" and "" + or (e == "warning" and "" or "" ) + if(sym ~= "") then + s = s .. " " .. n .. sym + end + end + return s + end, + numbers = function(opts) + return string.format('%s·%s', opts.raise(opts.id), opts.lower(opts.ordinal)) + end, + } + } + ''; + } + ); +} diff --git a/modules/telescope/default.nix b/modules/telescope/default.nix new file mode 100644 index 0000000..67bde16 --- /dev/null +++ b/modules/telescope/default.nix @@ -0,0 +1,77 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.telescope; +in { + options.vim.telescope = { + enable = mkEnableOption "enable telescope"; + }; + + config = mkIf (cfg.enable) { + vim.startPlugins = [ + "telescope" + ]; + + vim.nnoremap = + { + "ff" = " Telescope find_files"; + "fg" = " Telescope live_grep"; + "fb" = " Telescope buffers"; + "fh" = " Telescope help_tags"; + "ft" = " Telescope"; + + "fvcw" = " Telescope git_commits"; + "fvcb" = " Telescope git_bcommits"; + "fvb" = " Telescope git_branches"; + "fvs" = " Telescope git_status"; + "fvx" = " Telescope git_stash"; + } + // ( + if config.vim.lsp.enable + then { + "flsb" = " Telescope lsp_document_symbols"; + "flsw" = " Telescope lsp_workspace_symbols"; + + "flr" = " Telescope lsp_references"; + "fli" = " Telescope lsp_implementations"; + "flD" = " Telescope lsp_definitions"; + "flt" = " Telescope lsp_type_definitions"; + "fld" = " Telescope diagnostics"; + } + else {} + ) + // ( + if config.vim.treesitter.enable + then { + "fs" = " Telescope treesitter"; + } + else {} + ); + + vim.luaConfigRC.telescope = nvim.dag.entryAnywhere '' + require("telescope").setup { + defaults = { + vimgrep_arguments = { + "${pkgs.ripgrep}/bin/rg", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--smart-case" + }, + pickers = { + find_command = { + "${pkgs.fd}/bin/fd", + }, + }, + } + } + ''; + }; +} diff --git a/modules/theme/config.nix b/modules/theme/config.nix new file mode 100644 index 0000000..bbe6d28 --- /dev/null +++ b/modules/theme/config.nix @@ -0,0 +1,11 @@ +{ pkgs, config, lib, ... }: +with lib; { + config = { + vim.theme = { + enable = mkDefault false; + name = mkDefault "onedark"; + style = mkDefault "darker"; + extraConfig = mkDefault ""; + }; + }; +} diff --git a/modules/theme/default.nix b/modules/theme/default.nix new file mode 100644 index 0000000..d511fc4 --- /dev/null +++ b/modules/theme/default.nix @@ -0,0 +1,11 @@ +{ + pkgs, + config, + lib, + ... +}: { + imports = [ + ./theme.nix + ./config.nix + ]; +} diff --git a/modules/theme/supported_themes.nix b/modules/theme/supported_themes.nix new file mode 100644 index 0000000..31fc86f --- /dev/null +++ b/modules/theme/supported_themes.nix @@ -0,0 +1,33 @@ +{ + onedark = { + setup = { style ? "dark" }: '' + -- OneDark theme + require('onedark').setup { + style = "${style}" + } + require('onedark').load() + ''; + styles = [ "dark" "darker" "cool" "deep" "warm" "warmer" ]; + }; + + tokyonight = { + setup = { style ? "night" }: '' + -- need to set style before colorscheme to apply + vim.g.tokyonight_style = '${style}' + vim.cmd[[colorscheme tokyonight]] + ''; + styles = [ "day" "night" "storm" ]; + }; + + catppuccin = { + setup = { style ? "mocha" }: '' + -- Catppuccin theme + require('catppuccin').setup { + flavour = "${style}" + } + -- setup must be called before loading + vim.cmd.colorscheme "catppuccin" + ''; + styles = [ "latte" "frappe" "macchiato" "mocha" ]; + }; +} diff --git a/modules/theme/theme.nix b/modules/theme/theme.nix new file mode 100644 index 0000000..1246b90 --- /dev/null +++ b/modules/theme/theme.nix @@ -0,0 +1,40 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with lib.attrsets; +with builtins; let + cfg = config.vim.theme; + supported_themes = import ./supported_themes.nix; +in { + options.vim.theme = { + enable = mkOption { + type = types.bool; + description = "Enable Theme"; + }; + + name = mkOption { + type = types.enum (attrNames supported_themes); + description = "Supported themes can be found in `supported_themes.nix`"; + }; + + style = mkOption { + type = with types; enum supported_themes.${cfg.name}.styles; + description = "Specific style for theme if it supports it"; + }; + + extraConfig = mkOption { + type = with types; lines; + description = "Additional lua configuration to add before setup"; + }; + }; + + config = mkIf cfg.enable { + vim.startPlugins = [cfg.name]; + vim.luaConfigRC.themeSetup = nvim.dag.entryBefore ["theme"] cfg.extraConfig; + vim.luaConfigRC.theme = supported_themes.${cfg.name}.setup {style = cfg.style;}; + }; +} diff --git a/modules/tidal/default.nix b/modules/tidal/default.nix new file mode 100644 index 0000000..bb19046 --- /dev/null +++ b/modules/tidal/default.nix @@ -0,0 +1,6 @@ +{ + config, + lib, + pkgs, + ... +}: {imports = [./tidal.nix];} diff --git a/modules/tidal/tidal.nix b/modules/tidal/tidal.nix new file mode 100644 index 0000000..6b6c27e --- /dev/null +++ b/modules/tidal/tidal.nix @@ -0,0 +1,39 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.tidal; +in { + options.vim.tidal = { + enable = mkEnableOption "tidal tools and plugins"; + + flash = mkOption { + description = ''When sending a paragraph or a single line, vim-tidal will "flash" the selection for some milliseconds''; + type = types.int; + default = 150; + }; + + openSC = mkOption { + description = "Automatically run the supercollider CLI, sclang, alongside the Tidal GHCI terminal."; + type = types.bool; + default = true; + }; + }; + + config = mkIf (cfg.enable) { + vim.startPlugins = [ + # From tidalcycles flake + pkgs.vimPlugins.vim-tidal + ]; + + vim.globals = { + "tidal_target" = "terminal"; + "tidal_flash_duration" = 150; + "tidal_sc_enable" = cfg.openSC; + }; + }; +} diff --git a/modules/treesitter/context.nix b/modules/treesitter/context.nix new file mode 100644 index 0000000..64e421e --- /dev/null +++ b/modules/treesitter/context.nix @@ -0,0 +1,31 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.treesitter; +in { + options.vim.treesitter.context.enable = mkOption { + type = types.bool; + default = false; + description = "enable function context [nvim-treesitter-context]"; + }; + + config = mkIf (cfg.enable && cfg.context.enable) { + vim.startPlugins = [ + "nvim-treesitter-context" + ]; + + vim.luaConfigRC.treesitter-context = nvim.dag.entryAnywhere '' + -- Treesitter Context config + require'treesitter-context'.setup { + enable = true, + throttle = true, + max_lines = 0 + } + ''; + }; +} diff --git a/modules/treesitter/default.nix b/modules/treesitter/default.nix new file mode 100644 index 0000000..5f52900 --- /dev/null +++ b/modules/treesitter/default.nix @@ -0,0 +1,11 @@ +{ + config, + lib, + pkgs, + ... +}: { + imports = [ + ./treesitter.nix + ./context.nix + ]; +} diff --git a/modules/treesitter/treesitter.nix b/modules/treesitter/treesitter.nix new file mode 100644 index 0000000..8ed5154 --- /dev/null +++ b/modules/treesitter/treesitter.nix @@ -0,0 +1,111 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.treesitter; +in { + options.vim.treesitter = { + enable = mkOption { + default = false; + type = types.bool; + description = "enable tree-sitter [nvim-treesitter]"; + }; + + fold = mkOption { + default = false; + type = types.bool; + description = "enable fold with tree-sitter"; + }; + + autotagHtml = mkOption { + default = false; + type = types.bool; + description = "enable autoclose and rename html tag [nvim-ts-autotag]"; + }; + + grammars = mkOption { + type = with types; listOf package; + default = with (pkgs.vimPlugins.nvim-treesitter.builtGrammars); [ + c + cpp + nix + python + rust + markdown + comment + toml + make + tsx + html + javascript + css + graphql + json + zig + ]; + description = '' + List of treesitter grammars to install. + When enabling a language, its treesitter grammar is added for you. + ''; + }; + }; + + config = mkIf cfg.enable ( + let + writeIf = cond: msg: + if cond + then msg + else ""; + in { + vim.startPlugins = [ + "nvim-treesitter" + ( + if cfg.autotagHtml + then "nvim-ts-autotag" + else null + ) + ]; + + # For some reason treesitter highlighting does not work on start if this is set before syntax on + vim.configRC.treesitter = writeIf cfg.fold (nvim.dag.entryBefore ["basic"] '' + " Tree-sitter based folding + set foldmethod=expr + set foldexpr=nvim_treesitter#foldexpr() + set nofoldenable + ''); + + vim.luaConfigRC.treesitter = nvim.dag.entryAnywhere '' + -- Treesitter config + require'nvim-treesitter.configs'.setup { + highlight = { + enable = true, + disable = {}, + }, + + auto_install = false, + ensure_installed = {}, + + incremental_selection = { + enable = true, + keymaps = { + init_selection = "gnn", + node_incremental = "grn", + scope_incremental = "grc", + node_decremental = "grm", + }, + }, + + ${writeIf cfg.autotagHtml '' + autotag = { + enable = true, + }, + ''} + } + ''; + } + ); +} diff --git a/modules/visuals/config.nix b/modules/visuals/config.nix new file mode 100644 index 0000000..11d580d --- /dev/null +++ b/modules/visuals/config.nix @@ -0,0 +1,28 @@ +{ pkgs +, config +, lib +, ... +}: +with lib; { + config = { + vim.visuals = { + enable = mkDefault false; + + nvimWebDevicons.enable = mkDefault false; + lspkind.enable = mkDefault false; + + cursorWordline = { + enable = mkDefault false; + lineTimeout = mkDefault 500; + }; + + indentBlankline = { + enable = mkDefault false; + listChar = mkDefault "│"; + fillChar = mkDefault "⋅"; + eolChar = mkDefault "↴"; + showCurrContext = mkDefault true; + }; + }; + }; +} diff --git a/modules/visuals/default.nix b/modules/visuals/default.nix new file mode 100644 index 0000000..59a3e54 --- /dev/null +++ b/modules/visuals/default.nix @@ -0,0 +1,11 @@ +{ + pkgs, + config, + lib, + ... +}: { + imports = [ + ./config.nix + ./visuals.nix + ]; +} diff --git a/modules/visuals/visuals.nix b/modules/visuals/visuals.nix new file mode 100644 index 0000000..7008c68 --- /dev/null +++ b/modules/visuals/visuals.nix @@ -0,0 +1,135 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; +with builtins; let + cfg = config.vim.visuals; +in { + options.vim.visuals = { + enable = mkOption { + type = types.bool; + description = "visual enhancements"; + }; + + nvimWebDevicons.enable = mkOption { + type = types.bool; + description = "enable dev icons. required for certain plugins [nvim-web-devicons]"; + }; + + lspkind.enable = mkOption { + type = types.bool; + description = "enable vscode-like pictograms for lsp [lspkind]"; + }; + + cursorWordline = { + enable = mkOption { + type = types.bool; + description = "enable word and delayed line highlight [nvim-cursorline]"; + }; + + lineTimeout = mkOption { + type = types.int; + description = "time in milliseconds for cursorline to appear"; + }; + }; + + indentBlankline = { + enable = mkOption { + type = types.bool; + description = "enable indentation guides [indent-blankline]"; + }; + + listChar = mkOption { + type = types.str; + description = "Character for indentation line"; + }; + + fillChar = mkOption { + type = types.str; + description = "Character to fill indents"; + }; + + eolChar = mkOption { + type = types.str; + description = "Character at end of line"; + }; + + showCurrContext = mkOption { + type = types.bool; + description = "Highlight current context from treesitter"; + }; + }; + }; + + config = + mkIf cfg.enable + { + vim.startPlugins = [ + ( + if cfg.nvimWebDevicons.enable + then "nvim-web-devicons" + else null + ) + ( + if cfg.lspkind.enable + then "lspkind" + else null + ) + ( + if cfg.cursorWordline.enable + then "nvim-cursorline" + else null + ) + ( + if cfg.indentBlankline.enable + then "indent-blankline" + else null + ) + ]; + + vim.luaConfigRC.visuals = nvim.dag.entryAnywhere '' + ${ + if cfg.lspkind.enable + then "require'lspkind'.init()" + else "" + } + ${ + if cfg.indentBlankline.enable + then '' + -- highlight error: https://github.com/lukas-reineke/indent-blankline.nvim/issues/59 + vim.wo.colorcolumn = "99999" + vim.opt.list = true + + + ${ + if cfg.indentBlankline.eolChar == "" + then "" + else ''vim.opt.listchars:append({ eol = "${cfg.indentBlankline.eolChar}" })'' + } + + ${ + if cfg.indentBlankline.fillChar == "" + then "" + else ''vim.opt.listchars:append({ space = "${cfg.indentBlankline.fillChar}"})'' + } + + require("indent_blankline").setup { + char = "${cfg.indentBlankline.listChar}", + show_current_context = ${boolToString cfg.indentBlankline.showCurrContext}, + show_end_of_line = true, + } + '' + else "" + } + + ${ + if cfg.cursorWordline.enable + then "vim.g.cursorline_timeout = ${toString cfg.cursorWordline.lineTimeout}" + else "" + } + ''; + }; +} diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..48ca7d2 Binary files /dev/null and b/screenshot.png differ