From 2c9631997f376f5c80fe8b7da5fc25ffdb97b279 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 30 Dec 2020 01:05:51 +0000 Subject: [PATCH] Initial commit --- LICENSE | 8 ++ README.md | 58 ++++++++++++ example.nix | 76 ++++++++++++++++ flake.lock | 146 ++++++++++++++++++++++++++++++ flake.nix | 44 +++++++++ nixvim.nix | 105 +++++++++++++++++++++ plugins/colorschemes/gruvbox.nix | 18 ++++ plugins/default.nix | 6 ++ plugins/statuslines/lightline.nix | 29 ++++++ 9 files changed, 490 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 example.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nixvim.nix create mode 100644 plugins/colorschemes/gruvbox.nix create mode 100644 plugins/default.nix create mode 100644 plugins/statuslines/lightline.nix diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..2790f38b --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright 2020 Pedro Alves + +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 00000000..b09a2de4 --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# NixVim - A Neovim configuration system for nix +## What is it? +NixVim is a [Neovim](https://neovim.io) distribution built around +[Nix](https://nixos.org) modules. It is distributed as a Nix flake, and +configured through Nix, all while leaving room for your plugins and your vimrc. + +## What does it look like? +Here is a simple config that uses gruvbox as the colorscheme and uses the +lightline plugin: + +```nix +{ + programs.nixvim = { + enable = true; + + colorschemes.gruvbox.enable = true; + + plugins.lightline.enable = true; + }; +} +``` + +When we do this, lightline will be set up to a sensible default, and will use +gruvbox as the colorscheme, no extra configuration required! + +## Instalation +Right now, NixVim is only distributed as a Nix flake, which means you must +enable Nix flakes in order to use it. + +It is fairly easy to enable flakes globally, just put this in +`/etc/nixos/configuration.nix` + +```nix +{ pkgs, lib, ... }: +{ + nix = { + package = pkgs.nixFlakes; + extraOptions = lib.optionalString (config.nix.package == pkgs.nixFlakes) + "experimental-features = nix-command flakes"; + }; +} +``` + +Then, you need to import the module. Information on how to do this will be added +soon. + +## How does it work? +When you build the module (probably using home-manager), it will install all +your plugins and generate a lua config for NeoVim with all the options +specified. Because it uses lua, this ensures that your configuration will load +as fast as possible. + +Since everything is disabled by default, it will be as snappy as you want it to +be. + +## Plugins +NixVim provides a plugin system using Nix modules, allowing you to configure vim +similar to how you would configure NixOS services. diff --git a/example.nix b/example.nix new file mode 100644 index 00000000..319178de --- /dev/null +++ b/example.nix @@ -0,0 +1,76 @@ +{...}: +{ + programs.nixvim = { + # This just enables NixVim. + # If all you have is this, then there will be little visible difference + # when compared to just installing NeoVim. + enable = true; + + maps.normal = { + # Equivalent to nnoremap ; : + ";" = ":"; + # Equivalent to nmap gg Man + "gg" = { silent = true; buffer = true; remap = false; action = "Man" + # Etc... + }; + + # We can set the leader key: + leader = ","; + + # We can create maps for every mode! + # There is .normal, .insert, .visual and .operator + # These are aliased to .n, .i, .v and .o + + # We can also set options: + options = { + tabstop = 4; + shiftwidth = 4; + noexpandtab = true; + + mouse = "a"; + + # etc... + } + + # Of course, we can still use comfy vimscript: + extraConfigVim = builtins.readFile ./init.vim; + # Or lua! + extraConfigLua = builtins.readFile ./init.lua; + + # One of the big advantages of NixVim is how it provides modules for + # popular vim plugins + # Enabling a plugin this way skips all the boring configuration that + # some plugins tend to require. + plugins = { + lightline = { + enable = true; + + # This is optional - it will default to your enabled colorscheme + colorscheme = "wombat"; + + # This is one of lightline's example configurations + active = { + left = [ + [ "mode", "paste" ] + [ "redaonly", "filename", "modified", "helloworld" ] + ]; + }; + + component = { + helloworld = "Hello, world!"; + }; + }; + + # Of course, there are a lot more plugins available. + # You can find an up-to-date list here: + # https://nixvim.pta2002.com/plugins + }; + + # There is a separate namespace for colorschemes: + colorschemes.gruvbox.enable = true; + + # What about plugins not available as a module? + # Use extraPlugins: + extraPlugins = with pkgs.vimPlugins; [ vim-toml ]; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..320e6882 --- /dev/null +++ b/flake.lock @@ -0,0 +1,146 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1606424373, + "narHash": "sha256-oq8d4//CJOrVj+EcOaSXvMebvuTkmBJuT5tzlfewUnQ=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "99f1c2157fba4bfe6211a321fd0ee43199025dbf", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1605370193, + "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5021eac20303a61fafe17224c087f5519baed54d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "flake": false, + "locked": { + "lastModified": 1594969032, + "narHash": "sha256-nbZfz02QoVe1yYK7EtCV7wMi4VdHzZEoPg20ZSDo9to=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "c4662e662462e7bf3c2a968483478a665d00e717", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "neovim-nightly": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "neovim-nightly": "neovim-nightly_2", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1609229781, + "narHash": "sha256-hLTWHQYkpUVcLCCtuBQ+pWwB+cgNQR3i8V2jkkBhb/Y=", + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "rev": "b56f54f82db2d3d7bd358f6610aa783e3474af9a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "type": "github" + } + }, + "neovim-nightly_2": { + "flake": false, + "locked": { + "lastModified": 1609210020, + "narHash": "sha256-vXoaqhbnfv34P0E2CIEMWD+0o9jUDu95Vjl33DIGxGw=", + "owner": "neovim", + "repo": "neovim", + "rev": "28a0f6b17ddb51f605abfcd9d48b8084545d5901", + "type": "github" + }, + "original": { + "owner": "neovim", + "repo": "neovim", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1609214493, + "narHash": "sha256-lz8ROoxchhjoBd5phaM8t6EFAmRf+dU6clod2mdHOAg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ea3638a3fb262d3634be7e4c2aa3d4e9474ae157", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1609079092, + "narHash": "sha256-KhyKfxBHtZlAgudpZ0EJVzeuqROjKfVOwj8j0cuhU50=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2f47650c2f28d87f86ab807b8a339c684d91ec56", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "flake": false, + "locked": { + "lastModified": 1608206889, + "narHash": "sha256-DSgtmqIzGFNbDXnuEUiQWVOuKCyUnyFJxXMG/P3YFLA=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "d16e007e6bd263ba5899a9a425d76a78906570cd", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "neovim-nightly": "neovim-nightly", + "nixpkgs": "nixpkgs_2" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..cd59532f --- /dev/null +++ b/flake.nix @@ -0,0 +1,44 @@ +{ + description = "A neovim configuration system for NixOS"; + + inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable; + inputs.neovim-nightly.url = github:nix-community/neovim-nightly-overlay; + + outputs = { self, nixpkgs, ... }@inputs: rec { + overlays = [ + inputs.neovim-nightly.overlay + ]; + + nixosModules.nixvim = import ./nixvim.nix; + + # This is a simple container for testing + nixosConfigurations.container = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ({ pkgs, ... }: { + boot.isContainer = true; + system.configurationRevision = nixpkgs.lib.mkIf (self ? rev) self.rev; + + users.users.test = { + isNormalUser = true; + password = ""; + }; + + imports = [ + nixosModules.nixvim + ]; + + nixpkgs.overlays = [ inputs.neovim-nightly.overlay ]; + + programs.nixvim = { + enable = true; + package = pkgs.neovim-nightly; + colorschemes.gruvbox.enable = true; + + plugins.lightline.enable = true; + }; + }) + ]; + }; + }; +} diff --git a/nixvim.nix b/nixvim.nix new file mode 100644 index 00000000..e75b5f7a --- /dev/null +++ b/nixvim.nix @@ -0,0 +1,105 @@ +{ pkgs, lib, config, ... }: +with lib; +let + cfg = config.programs.nixvim; + + pluginWithConfigType = types.submodule { + options = { + config = mkOption { + type = types.lines; + description = "vimscript for this plugin to be placed in init.vim"; + default = ""; + }; + + optional = mkEnableOption "optional" // { + description = "Don't load by default (load with :packadd)"; + }; + + plugin = mkOption { + type = types.package; + description = "vim plugin"; + }; + }; + }; +in +{ + options = { + programs.nixvim = { + enable = mkEnableOption "enable NixVim"; + + package = mkOption { + type = types.package; + default = pkgs.neovim; + description = "The package to use for neovim."; + }; + + extraPlugins = mkOption { + type = with types; listOf (either package pluginWithConfigType); + default = [ ]; + description = "List of vim plugins to install."; + }; + + colorscheme = mkOption { + type = types.str; + description = "The name of the colorscheme"; + }; + + extraConfigLua = mkOption { + type = types.lines; + default = ""; + description = "Extra contents for init.lua"; + }; + + extraConfigVim = mkOption { + type = types.lines; + default = ""; + description = "Extra contents for init.vim"; + }; + + configure = mkOption { + type = types.attrsOf types.anything; + default = { }; + }; + }; + }; + + imports = [ + ./plugins + ]; + + config = let + neovimConfig = pkgs.neovimUtils.makeNeovimConfig { + configure = cfg.configure; + plugins = cfg.extraPlugins; + + withPython2 = false; + withPython3 = false; + withNodeJs = false; + withRuby = false; + }; + + wrappedNeovim = pkgs.wrapNeovimUnstable cfg.package (neovimConfig // { + wrapperArgs = lib.escapeShellArgs neovimConfig.wrapperArgs; + }); + in mkIf cfg.enable { + environment.systemPackages = [ wrappedNeovim ]; + programs.nixvim = { + configure = { + customRC = cfg.extraConfigVim + (optionalString (cfg.colorscheme != "") '' + + colorscheme ${cfg.colorscheme} + ''); + packages.nixvim = { + start = filter (f: f != null) (map (x: + if x ? plugin && x.optional == true then null else (x.plugin or x)) + cfg.extraPlugins); + opt = filter (f: f!= null) + (map (x: if x ? plugin && x.optional == true then x.plugin else null) + cfg.extraPlugins); + }; + }; + }; + + environment.etc."xdg/nvim/sysinit.vim".text = neovimConfig.neovimRcContent; + }; +} diff --git a/plugins/colorschemes/gruvbox.nix b/plugins/colorschemes/gruvbox.nix new file mode 100644 index 00000000..5531381f --- /dev/null +++ b/plugins/colorschemes/gruvbox.nix @@ -0,0 +1,18 @@ +{ pkgs, config, lib, ... }: +with lib; +let + cfg = config.programs.nixvim.colorschemes.gruvbox; +in { + options = { + programs.nixvim.colorschemes.gruvbox = { + enable = mkEnableOption "Enable gruvbox"; + }; + }; + + config = mkIf cfg.enable { + programs.nixvim = { + colorscheme = "gruvbox"; + extraPlugins = [ pkgs.vimPlugins.gruvbox ]; + }; + }; +} diff --git a/plugins/default.nix b/plugins/default.nix new file mode 100644 index 00000000..3a4b1c4e --- /dev/null +++ b/plugins/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./statuslines/lightline.nix + ./colorschemes/gruvbox.nix + ]; +} diff --git a/plugins/statuslines/lightline.nix b/plugins/statuslines/lightline.nix new file mode 100644 index 00000000..7639c471 --- /dev/null +++ b/plugins/statuslines/lightline.nix @@ -0,0 +1,29 @@ +{ pkgs, config, lib, ... }: +with lib; +let + cfg = config.programs.nixvim.plugins.lightline; +in { + options = { + programs.nixvim.plugins.lightline = { + enable = mkEnableOption "Enable lightline"; + + colorscheme = mkOption { + type = types.str; + default = config.programs.nixvim.colorscheme; + description = "The colorscheme to use for lightline. Defaults to .colorscheme."; + example = "gruvbox"; + }; + }; + }; + + config = mkIf cfg.enable { + programs.nixvim = { + extraPlugins = [ pkgs.vimPlugins.lightline-vim ]; + extraConfigVim = '' + """ lightline {{{ + let g:lightline = { 'colorscheme': '${cfg.colorscheme}' } + """ }}} + ''; + }; + }; +}