# Function for creating a Neovim derivation { pkgs, lib, stdenv, # Set by the overlay to ensure we use a compatible version of `wrapNeovimUnstable` pkgs-wrapNeovim ? pkgs, }: with lib; { # NVIM_APPNAME - Defaults to 'nvim' if not set. # If set to something else, this will also rename the binary. appName ? null, # The Neovim package to wrap neovim-unwrapped ? pkgs-wrapNeovim.neovim-unwrapped, plugins ? [], # List of plugins # List of dev plugins (will be bootstrapped) - useful for plugin developers # { name = ; url = ; } devPlugins ? [], # Regexes for config files to ignore, relative to the nvim directory. # e.g. [ "^plugin/neogit.lua" "^ftplugin/.*.lua" ] ignoreConfigRegexes ? [], extraPackages ? [], # Extra runtime dependencies (e.g. ripgrep, ...) # The below arguments can typically be left as their defaults # Additional lua packages (not plugins), e.g. from luarocks.org. # e.g. p: [p.jsregexp] extraLuaPackages ? p: [], extraPython3Packages ? p: [], # Additional python 3 packages withPython3 ? false, # Build Neovim with Python 3 support? withRuby ? false, # Build Neovim with Ruby support? withNodeJs ? false, # Build Neovim with NodeJS support? withSqlite ? true, # Add sqlite? This is a dependency for some plugins # You probably don't want to create vi or vim aliases # if the appName is something different than "nvim" viAlias ? appName == "nvim", # Add a "vi" binary to the build output as an alias? vimAlias ? appName == "nvim", # Add a "vim" binary to the build output as an alias? }: let # This is the structure of a plugin definition. # Each plugin in the `plugins` argument list can also be defined as this attrset defaultPlugin = { plugin = null; # e.g. nvim-lspconfig config = null; # plugin config # If `optional` is set to `false`, the plugin is installed in the 'start' packpath # set to `true`, it is installed in the 'opt' packpath, and can be lazy loaded with # ':packadd! {plugin-name} optional = false; runtime = {}; }; externalPackages = extraPackages ++ (optionals withSqlite [pkgs.sqlite]); # Map all plugins to an attrset { plugin = ; config = ; optional = ; ... } normalizedPlugins = map (x: defaultPlugin // ( if x ? plugin then x else {plugin = x;} )) plugins; # This nixpkgs util function creates an attrset # that pkgs.wrapNeovimUnstable uses to configure the Neovim build. neovimConfig = pkgs-wrapNeovim.neovimUtils.makeNeovimConfig { inherit extraPython3Packages withPython3 withRuby withNodeJs viAlias vimAlias; plugins = normalizedPlugins; }; # This uses the ignoreConfigRegexes list to filter # the nvim directory nvimRtpSrc = let src = ../nvim; in lib.cleanSourceWith { inherit src; name = "nvim-rtp-src"; filter = path: tyoe: let srcPrefix = toString src + "/"; relPath = lib.removePrefix srcPrefix (toString path); in lib.all (regex: builtins.match regex relPath == null) ignoreConfigRegexes; }; # Split runtimepath into 3 directories: # - lua, to be prepended to the rtp at the beginning of init.lua # - nvim, containing plugin, ftplugin, ... subdirectories # - after, to be sourced last in the startup initialization # See also: https://neovim.io/doc/user/starting.html nvimRtp = stdenv.mkDerivation { name = "nvim-rtp"; src = nvimRtpSrc; buildPhase = '' mkdir -p $out/lua mkdir -p $out/ftplugin ''; installPhase = '' cp -r lua $out/ rm -r lua cp -r ftplugin $out/ rm -r ftplugin ''; }; # The final init.lua content that we pass to the Neovim wrapper. # It wraps the user init.lua, prepends the lua lib directory to the RTP # and prepends the nvim and after directory to the RTP initLua = '' vim.opt.rtp:prepend('${nvimRtp}') LAZY_OPTS = { performance = { reset_packpath = false, rtp = { reset = false, disabled_plugins = { "netrwPlugin", "tutor", }, }, }, dev = { path = "${pkgs.neovimUtils.packDir neovimConfig.packpathDirs}/pack/myNeovimPackages/start", patterns = {""}, }, checker = { enabled = false, }, install = { missing = false, }, spec = {{ import = "plugins" }}, } '' + (builtins.readFile ../nvim/init.lua); # Add arguments to the Neovim wrapper script extraMakeWrapperArgs = builtins.concatStringsSep " " ( # Set the NVIM_APPNAME environment variable (optional (appName != "nvim" && appName != null && appName != "") ''--set NVIM_APPNAME "${appName}"'') # Add external packages to the PATH ++ (optional (externalPackages != []) ''--prefix PATH : "${makeBinPath externalPackages}"'') # Set the LIBSQLITE_CLIB_PATH if sqlite is enabled ++ (optional withSqlite ''--set LIBSQLITE_CLIB_PATH "${pkgs.sqlite.out}/lib/libsqlite3.so"'') # Set the LIBSQLITE environment variable if sqlite is enabled ++ (optional withSqlite ''--set LIBSQLITE "${pkgs.sqlite.out}/lib/libsqlite3.so"'') ); luaPackages = neovim-unwrapped.lua.pkgs; resolvedExtraLuaPackages = extraLuaPackages luaPackages; # Native Lua libraries extraMakeWrapperLuaCArgs = optionalString (resolvedExtraLuaPackages != []) ''--suffix LUA_CPATH ";" "${concatMapStringsSep ";" luaPackages.getLuaCPath resolvedExtraLuaPackages}"''; # Lua libraries extraMakeWrapperLuaArgs = optionalString (resolvedExtraLuaPackages != []) ''--suffix LUA_PATH ";" "${concatMapStringsSep ";" luaPackages.getLuaPath resolvedExtraLuaPackages}"''; # wrapNeovimUnstable is the nixpkgs utility function for building a Neovim derivation. neovim-wrapped = pkgs-wrapNeovim.wrapNeovimUnstable neovim-unwrapped (neovimConfig // { luaRcContent = initLua; wrapperArgs = escapeShellArgs neovimConfig.wrapperArgs + " " + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " + extraMakeWrapperLuaArgs; wrapRc = true; }); isCustomAppName = appName != null && appName != "nvim"; in neovim-wrapped.overrideAttrs (oa: { buildPhase = oa.buildPhase # If a custom NVIM_APPNAME has been set, rename the `nvim` binary + lib.optionalString isCustomAppName '' mv $out/bin/nvim $out/bin/${lib.escapeShellArg appName} ''; })