diff --git a/.envrc b/.envrc deleted file mode 100644 index 1d953f4b..00000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use nix diff --git a/.envrc.developer.template b/.envrc.developer.template new file mode 100644 index 00000000..e8e67adb --- /dev/null +++ b/.envrc.developer.template @@ -0,0 +1 @@ +use flake . --override-input neovim-src /path/to/neovim diff --git a/.envrc.minimal.template b/.envrc.minimal.template new file mode 100644 index 00000000..5f0fc3f2 --- /dev/null +++ b/.envrc.minimal.template @@ -0,0 +1 @@ +use flake .#minimal diff --git a/.gitignore b/.gitignore index 45f52016..9f0ce67a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ -# nix +# direnv +/.direnv +/.envrc + +# neovim-developer +/runtime/ +# nix result result-* .pre-commit-config.yaml diff --git a/flake-compat.nix b/flake-compat.nix index 873ece49..0205bc89 100644 --- a/flake-compat.nix +++ b/flake-compat.nix @@ -3,11 +3,12 @@ let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } ) { src = ./.; - }).defaultNix + }) +.defaultNix diff --git a/flake.lock b/flake.lock index c241cb71..097e1cb0 100644 --- a/flake.lock +++ b/flake.lock @@ -16,6 +16,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -23,11 +39,11 @@ ] }, "locked": { - "lastModified": 1714641030, - "narHash": "sha256-yzcRNDoyVP7+SCNX0wmuDju1NUCt8Dz9+lyUXEI0dbI=", + "lastModified": 1715865404, + "narHash": "sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "e5d10a24b66c3ea8f150e47dfdb0416ab7c3390e", + "rev": "8dc45382d5206bd292f9c2768b8058a8fd8311d9", "type": "github" }, "original": { @@ -56,21 +72,24 @@ "type": "indirect" } }, - "flake-utils": { + "gitignore": { "inputs": { - "systems": "systems" + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, @@ -95,24 +114,17 @@ "type": "github" } }, - "neovim-flake": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] - }, + "neovim-src": { + "flake": false, "locked": { - "dir": "contrib", - "lastModified": 1715815279, - "narHash": "sha256-Pf7ZlqPnr195NZb5ADzMVsXurPMjRZ+JMXf6JxvXArE=", + "lastModified": 1716501420, + "narHash": "sha256-VO9RCUNwiU627oVjR5gfsyz8z6VHkuW2VFT53xth1ig=", "owner": "neovim", "repo": "neovim", - "rev": "9ca81b025990911c2a0dbda92af39ba84983bac3", + "rev": "e7859d2ad504a3e3cae1d540d5fd4f9b560d154a", "type": "github" }, "original": { - "dir": "contrib", "owner": "neovim", "repo": "neovim", "type": "github" @@ -120,43 +132,54 @@ }, "nixpkgs": { "locked": { - "lastModified": 1715774670, - "narHash": "sha256-iJYnKMtLi5u6hZhJm94cRNSDG5Rz6ZzIkGbhPFtDRm0=", + "lastModified": 1716451822, + "narHash": "sha256-0lT5RVelqN+dgXWWneXvV5ufSksW0r0TDQi8O6U2+o8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b3fcfcfabd01b947a1e4f36622bbffa3985bdac6", + "rev": "3305b2b25e4ae4baee872346eae133cf6f611783", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "3305b2b25e4ae4baee872346eae133cf6f611783", "type": "github" } }, - "root": { + "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat", - "flake-parts": "flake-parts", - "hercules-ci-effects": "hercules-ci-effects", - "neovim-flake": "neovim-flake", - "nixpkgs": "nixpkgs" - } - }, - "systems": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs" + ] + }, "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "lastModified": 1716213921, + "narHash": "sha256-xrsYFST8ij4QWaV6HEokCUNIZLjjLP1bYC60K8XiBVA=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "0e8fcc54b842ad8428c9e705cb5994eaf05c26a0", "type": "github" }, "original": { - "owner": "nix-systems", - "repo": "default", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", "type": "github" } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", + "hercules-ci-effects": "hercules-ci-effects", + "neovim-src": "neovim-src", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 62191a4a..c3f2a702 100644 --- a/flake.nix +++ b/flake.nix @@ -2,15 +2,34 @@ description = "Neovim flake"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs-lib.follows = "nixpkgs"; }; - hercules-ci-effects = { url = "github:hercules-ci/hercules-ci-effects"; inputs.nixpkgs.follows = "nixpkgs"; }; - flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; - neovim-flake = { url = "github:neovim/neovim?dir=contrib"; inputs.nixpkgs.follows = "nixpkgs"; }; + nixpkgs.url = "github:NixOS/nixpkgs/3305b2b25e4ae4baee872346eae133cf6f611783"; + flake-parts = { + url = "github:hercules-ci/flake-parts"; + inputs.nixpkgs-lib.follows = "nixpkgs"; + }; + hercules-ci-effects = { + url = "github:hercules-ci/hercules-ci-effects"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + neovim-src = { + url = "github:neovim/neovim"; + flake = false; + }; + pre-commit-hooks = { + url = "github:cachix/pre-commit-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.nixpkgs-stable.follows = "nixpkgs"; + }; }; outputs = inputs: - inputs.flake-parts.lib.mkFlake { inherit inputs; } ({ config, ... }: { + inputs.flake-parts.lib.mkFlake + {inherit inputs;} + ({config, ...}: { systems = [ "x86_64-linux" "x86_64-darwin" @@ -19,33 +38,7 @@ ]; imports = [ - inputs.flake-parts.flakeModules.easyOverlay - inputs.hercules-ci-effects.flakeModule + ./flake ]; - - perSystem = { inputs', system, config, lib, pkgs, ... }: { - packages = { - neovim = inputs'.neovim-flake.packages.neovim // (lib.optionalAttrs pkgs.stdenv.isDarwin { ignoreFailure = true; }); - default = config.packages.neovim; - }; - overlayAttrs = lib.genAttrs [ "neovim-unwrapped" "neovim-nightly" ] (_: config.packages.neovim); - }; - - flake = { - defaultPackage = inputs.nixpkgs.lib.genAttrs config.systems (system: inputs.self.packages.${system}.default); - overlay = inputs.self.overlays.default; - }; - - hercules-ci.flake-update = { - enable = true; - baseMerge.enable = true; - baseMerge.method = "rebase"; - autoMergeMethod = "rebase"; - # Update everynight at midnight - when = { - hour = [ 0 ]; - minute = 0; - }; - }; }); } diff --git a/flake/checks.nix b/flake/checks.nix new file mode 100644 index 00000000..6023d84a --- /dev/null +++ b/flake/checks.nix @@ -0,0 +1,22 @@ +{inputs, ...}: { + perSystem = { + pkgs, + config, + ... + }: { + checks = { + # TODO: not working: remove ? + # shlint = pkgs.runCommand "shlint" { + # nativeBuildInputs = [pkgs.shellcheck]; + # preferLocalBuild = true; + # } "make -C ${inputs.neovim-src} shlint > $out"; + + inherit + (config.packages) + neovim + neovim-debug + neovim-developer + ; + }; + }; +} diff --git a/flake/ci.nix b/flake/ci.nix new file mode 100644 index 00000000..cd96ce32 --- /dev/null +++ b/flake/ci.nix @@ -0,0 +1,17 @@ +{inputs, ...}: { + imports = [ + inputs.hercules-ci-effects.flakeModule + ]; + + hercules-ci.flake-update = { + enable = true; + baseMerge.enable = true; + baseMerge.method = "rebase"; + autoMergeMethod = "rebase"; + # Update everynight at midnight + when = { + hour = [0]; + minute = 0; + }; + }; +} diff --git a/flake/default.nix b/flake/default.nix new file mode 100644 index 00000000..8def5657 --- /dev/null +++ b/flake/default.nix @@ -0,0 +1,20 @@ +{inputs, ...}: { + imports = [ + ./checks.nix + ./ci.nix + ./devshells.nix + ./overlays.nix + ./packages + inputs.pre-commit-hooks.flakeModule + ]; + + perSystem = {pkgs, ...}: { + formatter = pkgs.alejandra; + pre-commit.settings.hooks.alejandra.enable = true; + + # Neovim uses lua 5.1 as it is the version which supports JIT + _module.args = { + lua = pkgs.lua5_1; + }; + }; +} diff --git a/flake/devshells.nix b/flake/devshells.nix new file mode 100644 index 00000000..d89da48e --- /dev/null +++ b/flake/devshells.nix @@ -0,0 +1,50 @@ +{ + perSystem = { + pkgs, + config, + lua, + ... + }: { + devShells = { + default = pkgs.mkShell { + name = "neovim-developer-shell"; + inputsFrom = [ + config.devShells.minimal + config.packages.neovim-developer + ]; + shellHook = '' + ${config.packages.neovim-developer.shellHook or ""} + export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_18}/bin/llvm-symbolizer + export NVIM_PYTHON_LOG_LEVEL=DEBUG + export NVIM_LOG_FILE=/tmp/nvim.log + + # ASAN_OPTIONS=detect_leaks=1 + export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1" + + # for treesitter functionaltests + mkdir -p runtime/parser + cp -f ${pkgs.vimPlugins.nvim-treesitter.builtGrammars.c}/parser runtime/parser/c.so + ''; + }; + + # Provide a devshell that can be used strictly for developing this flake. + minimal = pkgs.mkShell.override {inherit (pkgs.llvmPackages_latest) stdenv;} { + name = "neovim-minimal-shell"; + inputsFrom = [ + config.packages.default + ]; + packages = with pkgs; [ + (python3.withPackages (ps: [ps.msgpack])) + include-what-you-use + jq + lua-language-server + lua.pkgs.luacheck + shellcheck + ]; + shellHook = '' + export VIMRUNTIME= + ''; + }; + }; + }; +} diff --git a/flake/overlays.nix b/flake/overlays.nix new file mode 100644 index 00000000..83b70105 --- /dev/null +++ b/flake/overlays.nix @@ -0,0 +1,23 @@ +{inputs, ...}: { + imports = [ + inputs.flake-parts.flakeModules.easyOverlay + ]; + + perSystem = { + inputs', + system, + config, + lib, + pkgs, + ... + }: { + overlayAttrs = { + inherit + (config.packages) + neovim + neovim-debug + neovim-developer + ; + }; + }; +} diff --git a/flake/packages/default.nix b/flake/packages/default.nix new file mode 100644 index 00000000..992864ad --- /dev/null +++ b/flake/packages/default.nix @@ -0,0 +1,31 @@ +{inputs, ...}: { + perSystem = { + inputs', + system, + config, + lib, + pkgs, + lua, + ... + }: { + packages = { + default = config.packages.neovim; + + neovim = import ./neovim.nix { + inherit (inputs) neovim-src; + inherit lib pkgs; + }; + + neovim-debug = import ./neovim-debug.nix { + inherit (config.packages) neovim; + inherit pkgs; + }; + + neovim-developer = import ./neovim-developer.nix { + inherit (config.packages) neovim-debug; + inherit (inputs) neovim-src; + inherit lib pkgs lua; + }; + }; + }; +} diff --git a/flake/packages/neovim-debug.nix b/flake/packages/neovim-debug.nix new file mode 100644 index 00000000..f3fb0aab --- /dev/null +++ b/flake/packages/neovim-debug.nix @@ -0,0 +1,20 @@ +{ + neovim, + pkgs, + ... +}: +(neovim.override { + stdenv = + if pkgs.stdenv.isLinux + then pkgs.llvmPackages_latest.stdenv + else pkgs.stdenv; + lua = pkgs.luajit; +}) +.overrideAttrs ( + oa: { + dontStrip = true; + NIX_CFLAGES_COMPILE = " -ggdb -Og"; + cmakeBuildType = "Debug"; + disallowedReferences = []; + } +) diff --git a/flake/packages/neovim-developer.nix b/flake/packages/neovim-developer.nix new file mode 100644 index 00000000..a10bf5be --- /dev/null +++ b/flake/packages/neovim-developer.nix @@ -0,0 +1,25 @@ +{ + neovim-debug, + pkgs, + lua, + lib, + neovim-src, + ... +}: +neovim-debug.overrideAttrs (oa: { + cmakeFlagsArray = + oa.cmakeFlagsArray + ++ [ + "-DLUACHECK_PRG=${lua.pkgs.luacheck}/bin/luacheck" + "-DENABLE_LTO=OFF" + ] + ++ lib.optionals pkgs.stdenv.isLinux [ + # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags + # https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports + "-DENABLE_ASAN_UBSAN=ON" + ]; + doCheck = pkgs.stdenv.isLinux; + shellHook = '' + export VIMRUNTIME=${neovim-src}/runtime + ''; +}) diff --git a/flake/packages/neovim.nix b/flake/packages/neovim.nix new file mode 100644 index 00000000..20040aef --- /dev/null +++ b/flake/packages/neovim.nix @@ -0,0 +1,91 @@ +{ + neovim-src, + lib, + pkgs, + ... +}: let + src = pkgs.fetchFromGitHub { + owner = "neovim"; + repo = "neovim"; + inherit (neovim-src) rev; + hash = neovim-src.narHash; + }; + + deps = lib.pipe "${src}/cmake.deps/deps.txt" [ + builtins.readFile + (lib.splitString "\n") + (map (builtins.match "([A-Z0-0_]+)_(URL|SHA256)[[:space:]]+([^[:space:]]+)[[:space:]]*")) + (lib.remove null) + (lib.flip builtins.foldl' {} + (acc: matches: let + name = lib.toLower (builtins.elemAt matches 0); + key = lib.toLower (builtins.elemAt matches 1); + value = lib.toLower (builtins.elemAt matches 2); + in + acc + // { + ${name} = + acc.${name} + or {} + // { + ${key} = value; + }; + })) + (builtins.mapAttrs (lib.const pkgs.fetchurl)) + ]; +in + (pkgs.neovim-unwrapped.override { + gettext = pkgs.gettext.overrideAttrs (_: { + src = deps.gettext; + }); + libiconv = pkgs.libiconv.overrideAttrs (_: { + src = deps.libiconv; + }); + libuv = pkgs.libuv.overrideAttrs (_: { + src = deps.libuv; + }); + libvterm-neovim = pkgs.libvterm-neovim.overrideAttrs (_: { + src = deps.libvterm; + }); + msgpack-c = pkgs.msgpack-c.overrideAttrs (_: { + src = deps.msgpack; + }); + tree-sitter = pkgs.tree-sitter.override (_: { + rustPlatform = + pkgs.rustPlatform + // { + buildRustPackage = args: + pkgs.rustPlatform.buildRustPackage (args + // { + src = deps.treesitter; + cargoHash = "sha256-U2YXpNwtaSSEftswI0p0+npDJqOq5GqxEUlOPRlJGmQ="; + }); + }; + }); + treesitter-parsers = let + grammars = lib.filterAttrs (name: _: lib.hasPrefix "treesitter_" name) deps; + parsers = + lib.mapAttrs' + (name: value: lib.nameValuePair (lib.removePrefix "treesitter_" name) {src = value;}) + grammars; + in + parsers + // { + markdown = parsers.markdown // {location = "tree-sitter-markdown";}; + # TODO useless at some point (has been fixed in nixpkgs master) + markdown_inline = + parsers.markdown + // { + language = "markdown_inline"; + location = "tree-sitter-markdown-inline"; + }; + }; + }) + .overrideAttrs (oa: { + version = "nightly"; + inherit src; + preConfigure = '' + ${oa.preConfigure} + sed -i cmake.config/versiondef.h.in -e 's/@NVIM_VERSION_PRERELEASE@/-dev+${neovim-src.shortRev or "dirty"}/' + ''; + })