1
0
Fork 0
mirror of https://github.com/NotAShelf/neovim-flake.git synced 2024-12-23 02:49:47 +01:00

dev: rebase on a less personalized neovim flake

This commit is contained in:
NotAShelf 2023-02-01 22:11:37 +03:00
commit 9c00808863
No known key found for this signature in database
GPG key ID: 5B5C8895F28445F1
70 changed files with 4910 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

17
.github/workflows/check.yml vendored Normal file
View file

@ -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

34
.github/workflows/manual.yml vendored Normal file
View file

@ -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

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
result
.config

21
LICENSE Normal file
View file

@ -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.

30
README.md Normal file
View file

@ -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)

42
docs/custom-configs.adoc Normal file
View file

@ -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;
};
}
----

36
docs/default-configs.adoc Normal file
View file

@ -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 <<sec-default-nix,Nix>> 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.
====

54
docs/default.nix Normal file
View file

@ -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 = ''
<toc>
<d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-neovim-flake-manual">
<?dbhtml filename="index.html"?>
<d:tocentry linkend="ch-options">
<?dbhtml filename="options.html"?>
</d:tocentry>
<d:tocentry linkend="ch-release-notes">
<?dbhtml filename="release-notes.html"?>
</d:tocentry>
</d:tocentry>
</toc>
'';
};
in {
options.json = nvimModuleDocs.json.override {path = "share/doc/neovim-flake/options.json";};
manPages = docs.manPages;
manual = {inherit (docs) html htmlOpenTool;};
}

71
docs/languages.adoc Normal file
View file

@ -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-plugins-rust,here>>
[[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-plugins-sql,here>>
[[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-plugins-markdown,here>>
[[sec-languages-html]]
=== HTML
*Plugins*: See <<sec-plugins-html,here>>

View file

@ -0,0 +1,42 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>neovim-flake configuration</refentrytitle>
<manvolnum>5</manvolnum>
<refmiscinfo class="source">neovim-flake</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname>neovim configuration</refname>
<refpurpose>neovim-flake configuration specification</refpurpose>
</refnamediv>
<refsection>
<title>Description</title>
<para>
Custom configuration is done with the neovim-flake.lib.neovimConfiguration function. It takes in the configuration as a module.
<programlisting>
neovim-flake.lib.neovimConfiguration {
inherit pkgs;
modules = [{config = xxx;}];
};
</programlisting>
The output of the configuration function is an attrset.
</para>
<programlisting>
{
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";
}
</programlisting>
</refsection>
<refsection>
<title>Options</title>
<para>
You can use the following options in your neovim configuration.
</para>
<xi:include href="./nmd-result/neovim-flake-options.xml"/>
</refsection>
</refentry>

13
docs/man-pages.xml Normal file
View file

@ -0,0 +1,13 @@
<reference xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>neovim-flake Reference Pages</title>
<info>
<author><personname>neovim-flake contributors</personname></author>
<copyright>
<year>20212022</year>
<holder>neovim-flake contributors</holder>
</copyright>
</info>
<xi:include href="man-configuration.xml" />
</reference>

27
docs/manual.xml Normal file
View file

@ -0,0 +1,27 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="book-neovim-flake-manual">
<info>
<title>neovim-flake Manual</title>
</info>
<preface>
<title>Preface</title>
<para>
If you encounter problems or want to discuss neovim-flake then join the Matrix room
<link xlink:href="https://matrix.to/#/%23neovim-flake:matrix.org">#neovim-flake:matrix.org</link>.
If your problem is caused by a bug in neovim-flake then it should be reported on the
<link xlink:href="https://github.com/jordanisaacs/neovim-flake/issues">neovim-flake issue tracker</link>.
</para>
</preface>
<xi:include href="default-configs.xml"/>
<xi:include href="custom-configs.xml"/>
<xi:include href="languages.xml"/>
<xi:include href="plugins.xml"/>
<appendix xml:id="ch-options">
<title>Configuration Options</title>
<xi:include href="./nmd-result/neovim-flake-options.xml" />
</appendix>
<xi:include href="./release-notes/release-notes.xml" />
</book>

111
docs/plugins.adoc Normal file
View file

@ -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

View file

@ -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[]

View file

@ -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.
* <<opt-vim.startPlugins>> & <<opt-vim.optPlugins>> 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 <<opt-vim.treesitter.grammars>>. 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.
* <<opt-vim.configRC>> and <<opt-vim.luaConfigRC>> 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 <<opt-vim.theme.style>> and lualine theme <<opt-vim.statusline.lualine.theme>>.

1022
flake.lock Normal file

File diff suppressed because it is too large Load diff

421
flake.nix Normal file
View file

@ -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 {}
);
}));
}

View file

@ -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,
})
''}
'';
};
}

225
modules/basic/default.nix Normal file
View file

@ -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 {
"<up>" = "<nop>";
"<down>" = "<nop>";
"<left>" = "<nop>";
"<right>" = "<nop>";
};
vim.imap = mkIf cfg.disableArrows {
"<up>" = "<nop>";
"<down>" = "<nop>";
"<left>" = "<nop>";
"<right>" = "<nop>";
};
vim.nnoremap = mkIf cfg.mapLeaderSpace {"<space>" = "<nop>";};
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
''}
'';
};
}

View file

@ -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 = {
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c'}),
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c'}),
['<C-y>'] = cmp.config.disable,
['<C-e>'] = cmp.mapping({
i = cmp.mapping.abort(),
c = cmp.mapping.close(),
}),
['<CR>'] = cmp.mapping.confirm({
select = true,
}),
['<Tab>'] = cmp.mapping(function (fallback)
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function (fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(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;
};
}

225
modules/core/default.nix Normal file
View file

@ -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 "<C-${toUpper (head groups)}>${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;
};
};
}

72
modules/default.nix Normal file
View file

@ -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;
}

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./nvimtreelua.nix
];
}

View file

@ -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 = {
"<C-n>" = ":NvimTreeToggle<CR>";
"<leader>tr" = ":NvimTreeRefresh<CR>";
"<leader>tg" = ":NvimTreeFindFile<CR>";
"<leader>tf" = ":NvimTreeFocus<CR>";
};
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)}
},
},
})
'';
};
}

14
modules/git/config.nix Normal file
View file

@ -0,0 +1,14 @@
{
pkgs,
config,
lib,
...
}:
with lib; {
config = {
vim.git = {
enable = mkDefault false;
gitsigns.enable = mkDefault false;
};
};
}

11
modules/git/default.nix Normal file
View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./config.nix
./git.nix
];
}

69
modules/git/git.nix Normal file
View file

@ -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 <leader>gn'] = { expr = true, "&diff ? \'\' : '<cmd>Gitsigns next_hunk<CR>'"},
['n <leader>gp'] = { expr = true, "&diff ? \'\' : '<cmd>Gitsigns prev_hunk<CR>'"},
['n <leader>gs'] = '<cmd>Gitsigns stage_hunk<CR>',
['v <leader>gs'] = ':Gitsigns stage_hunk<CR>',
['n <leader>gu'] = '<cmd>Gitsigns undo_stage_hunk<CR>',
['n <leader>gr'] = '<cmd>Gitsigns reset_hunk<CR>',
['v <leader>gr'] = ':Gitsigns reset_hunk<CR>',
['n <leader>gR'] = '<cmd>Gitsigns reset_buffer<CR>',
['n <leader>gp'] = '<cmd>Gitsigns preview_hunk<CR>',
['n <leader>gb'] = '<cmd>lua require"gitsigns".blame_line{full=true}<CR>',
['n <leader>gS'] = '<cmd>Gitsigns stage_buffer<CR>',
['n <leader>gU'] = '<cmd>Gitsigns reset_buffer_index<CR>',
['n <leader>gts'] = ':Gitsigns toggle_signs<CR>',
['n <leader>gtn'] = ':Gitsigns toggle_numhl<CR>',
['n <leader>gtl'] = ':Gitsigns toggle_linehl<CR>',
['n <leader>gtw'] = ':Gitsigns toggle_word_diff<CR>',
-- Text objects
['o ih'] = ':<C-U>Gitsigns select_hunk<CR>',
['x ih'] = ':<C-U>Gitsigns select_hunk<CR>'
},
}
'');
}
);
}

6
modules/keys/default.nix Normal file
View file

@ -0,0 +1,6 @@
{
config,
lib,
pkgs,
...
}: {imports = [./which-key.nix];}

View file

@ -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 {}'';
};
}

9
modules/lib/booleans.nix Normal file
View file

@ -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";
}

105
modules/lib/dag.nix Normal file
View file

@ -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
# `<nixpkgs/lib/lists.nix>` 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 [];
}

5
modules/lib/default.nix Normal file
View file

@ -0,0 +1,5 @@
{lib}: {
dag = import ./dag.nix {inherit lib;};
booleans = import ./booleans.nix {inherit lib;};
types = import ./types.nix {inherit lib;};
}

View file

@ -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;
})

68
modules/lib/types-dag.nix Normal file
View file

@ -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 ++ ["<name>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: dagOf (elemType.substSubModules m);
functor = (defaultFunctor name) // {wrapped = elemType;};
nestedTypes.elemType = elemType;
};
}

View file

@ -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;
};
}

7
modules/lib/types.nix Normal file
View file

@ -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;
}

15
modules/lsp/default.nix Normal file
View file

@ -0,0 +1,15 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./lsp.nix
./lspsaga.nix
./nvim-code-action-menu.nix
./trouble.nix
./lsp-signature.nix
./lightbulb.nix
];
}

29
modules/lsp/lightbulb.nix Normal file
View file

@ -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()
'';
};
}

View file

@ -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()
'';
};
}

405
modules/lsp/lsp.nix Normal file
View file

@ -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', '<leader>lgD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgt', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgn', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lgp', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lwl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>lh', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ls', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ln', '<cmd>lua vim.lsp.buf.rename()<CR>', 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", "<leader>ris", rt.inlay_hints.set, opts)
vim.keymap.set("n", "<leader>riu", rt.inlay_hints.unset, opts)
vim.keymap.set("n", "<leader>rr", rt.runnables.runnables, opts)
vim.keymap.set("n", "<leader>rp", rt.parent_module.parent_module, opts)
vim.keymap.set("n", "<leader>rm", rt.expand_macro.expand_macro, opts)
vim.keymap.set("n", "<leader>rc", rt.open_cargo_toml.open_cargo_toml, opts)
vim.keymap.set("n", "<leader>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" }
}
''}
'';
}
);
}

54
modules/lsp/lspsaga.nix Normal file
View file

@ -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 = {
"<silent><leader>ca" = ":<C-U>lua require('lspsaga.codeaction').range_code_action()<CR>";
};
vim.nnoremap =
{
"<silent><leader>lf" = "<cmd>lua require'lspsaga.provider'.lsp_finder()<CR>";
"<silent><leader>lh" = "<cmd>lua require('lspsaga.hover').render_hover_doc()<CR>";
"<silent><C-f>" = "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>";
"<silent><C-b>" = "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>";
"<silent><leader>lr" = "<cmd>lua require'lspsaga.rename'.rename()<CR>";
"<silent><leader>ld" = "<cmd>lua require'lspsaga.provider'.preview_definition()<CR>";
"<silent><leader>ll" = "<cmd>lua require'lspsaga.diagnostic'.show_line_diagnostics()<CR>";
"<silent><leader>lc" = "<cmd>lua require'lspsaga.diagnostic'.show_cursor_diagnostics()<CR>";
"<silent><leader>lp" = "<cmd>lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_prev()<CR>";
"<silent><leader>ln" = "<cmd>lua require'lspsaga.diagnostic'.lsp_jump_diagnostic_next()<CR>";
}
// (
if (!cfg.nvimCodeActionMenu.enable)
then {
"<silent><leader>ca" = "<cmd>lua require('lspsaga.codeaction').code_action()<CR>";
}
else {}
)
// (
if (!cfg.lspSignature.enable)
then {
"<silent><leader>ls" = "<cmd>lua require('lspsaga.signaturehelp').signature_help()<CR>";
}
else {}
);
vim.luaConfigRC.lspsage = nvim.dag.entryAnywhere ''
-- Enable lspsaga
local saga = require 'lspsaga'
saga.init_lsp_saga()
'';
};
}

View file

@ -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 = {
"<silent><leader>ca" = ":CodeActionMenu<CR>";
};
};
}

34
modules/lsp/trouble.nix Normal file
View file

@ -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 = {
"<leader>xx" = "<cmd>TroubleToggle<CR>";
"<leader>lwd" = "<cmd>TroubleToggle workspace_diagnostics<CR>";
"<leader>ld" = "<cmd>TroubleToggle document_diagnostics<CR>";
"<leader>lr" = "<cmd>TroubleToggle lsp_references<CR>";
"<leader>xq" = "<cmd>TroubleToggle quickfix<CR>";
"<leader>xl" = "<cmd>TroubleToggle loclist<CR>";
};
vim.luaConfigRC.trouble = nvim.dag.entryAnywhere ''
-- Enable trouble diagnostics viewer
require("trouble").setup {}
'';
};
}

View file

@ -0,0 +1,14 @@
{
pkgs,
config,
lib,
...
}:
with lib; {
config = {
vim.markdown = {
enable = mkDefault false;
glow.enable = mkDefault false;
};
};
}

View file

@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./config.nix
./glow.nix
];
}

38
modules/markdown/glow.nix Normal file
View file

@ -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 <leader>p :Glow<CR>
'');
};
}

35
modules/modules.nix Normal file
View file

@ -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]

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./vsnip.nix
];
}

View file

@ -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"];
};
}

View file

@ -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 "{}";
};
};
};
}

View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./lualine.nix
./config.nix
];
}

View file

@ -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 ""
}},
}
'';
};
}

View file

@ -0,0 +1,5 @@
[
"tokyonight"
"onedark"
"catppuccin"
]

View file

@ -0,0 +1,10 @@
{
pkgs,
lib,
config,
...
}: {
imports = [
./nvim-bufferline.nix
];
}

View file

@ -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 = {
"<silent><leader>bn" = ":BufferLineCycleNext<CR>";
"<silent><leader>bp" = ":BufferLineCyclePrev<CR>";
"<silent><leader>bc" = ":BufferLinePick<CR>";
"<silent><leader>bse" = ":BufferLineSortByExtension<CR>";
"<silent><leader>bsd" = ":BufferLineSortByDirectory<CR>";
"<silent><leader>bsi" = ":lua require'bufferline'.sort_buffers_by(function (buf_a, buf_b) return buf_a.id < buf_b.id end)<CR>";
"<silent><leader>bmn" = ":BufferLineMoveNext<CR>";
"<silent><leader>bmp" = ":BufferLineMovePrev<CR>";
"<silent><leader>b1" = "<Cmd>BufferLineGoToBuffer 1<CR>";
"<silent><leader>b2" = "<Cmd>BufferLineGoToBuffer 2<CR>";
"<silent><leader>b3" = "<Cmd>BufferLineGoToBuffer 3<CR>";
"<silent><leader>b4" = "<Cmd>BufferLineGoToBuffer 4<CR>";
"<silent><leader>b5" = "<Cmd>BufferLineGoToBuffer 5<CR>";
"<silent><leader>b6" = "<Cmd>BufferLineGoToBuffer 6<CR>";
"<silent><leader>b7" = "<Cmd>BufferLineGoToBuffer 7<CR>";
"<silent><leader>b8" = "<Cmd>BufferLineGoToBuffer 8<CR>";
"<silent><leader>b9" = "<Cmd>BufferLineGoToBuffer 9<CR>";
};
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,
}
}
'';
}
);
}

View file

@ -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 =
{
"<leader>ff" = "<cmd> Telescope find_files<CR>";
"<leader>fg" = "<cmd> Telescope live_grep<CR>";
"<leader>fb" = "<cmd> Telescope buffers<CR>";
"<leader>fh" = "<cmd> Telescope help_tags<CR>";
"<leader>ft" = "<cmd> Telescope<CR>";
"<leader>fvcw" = "<cmd> Telescope git_commits<CR>";
"<leader>fvcb" = "<cmd> Telescope git_bcommits<CR>";
"<leader>fvb" = "<cmd> Telescope git_branches<CR>";
"<leader>fvs" = "<cmd> Telescope git_status<CR>";
"<leader>fvx" = "<cmd> Telescope git_stash<CR>";
}
// (
if config.vim.lsp.enable
then {
"<leader>flsb" = "<cmd> Telescope lsp_document_symbols<CR>";
"<leader>flsw" = "<cmd> Telescope lsp_workspace_symbols<CR>";
"<leader>flr" = "<cmd> Telescope lsp_references<CR>";
"<leader>fli" = "<cmd> Telescope lsp_implementations<CR>";
"<leader>flD" = "<cmd> Telescope lsp_definitions<CR>";
"<leader>flt" = "<cmd> Telescope lsp_type_definitions<CR>";
"<leader>fld" = "<cmd> Telescope diagnostics<CR>";
}
else {}
)
// (
if config.vim.treesitter.enable
then {
"<leader>fs" = "<cmd> Telescope treesitter<CR>";
}
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",
},
},
}
}
'';
};
}

11
modules/theme/config.nix Normal file
View file

@ -0,0 +1,11 @@
{ pkgs, config, lib, ... }:
with lib; {
config = {
vim.theme = {
enable = mkDefault false;
name = mkDefault "onedark";
style = mkDefault "darker";
extraConfig = mkDefault "";
};
};
}

11
modules/theme/default.nix Normal file
View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./theme.nix
./config.nix
];
}

View file

@ -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" ];
};
}

40
modules/theme/theme.nix Normal file
View file

@ -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;};
};
}

View file

@ -0,0 +1,6 @@
{
config,
lib,
pkgs,
...
}: {imports = [./tidal.nix];}

39
modules/tidal/tidal.nix Normal file
View file

@ -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;
};
};
}

View file

@ -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
}
'';
};
}

View file

@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}: {
imports = [
./treesitter.nix
./context.nix
];
}

View file

@ -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,
},
''}
}
'';
}
);
}

View file

@ -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;
};
};
};
}

View file

@ -0,0 +1,11 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
./config.nix
./visuals.nix
];
}

135
modules/visuals/visuals.nix Normal file
View file

@ -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 ""
}
'';
};
}

BIN
screenshot.png Normal file

Binary file not shown.

After

(image error) Size: 204 KiB