nixpkgs/pkgs/applications/editors/neovim/utils.nix
birdee 600f8504be neovimUtils.grammarToPlugin: improve error message on invalid grammarPlugins
Update pkgs/applications/editors/neovim/utils.nix

Co-authored-by: Perchun Pak <github@perchun.it>

Update pkgs/applications/editors/neovim/utils.nix

Co-authored-by: Austin Horstman <khaneliman12@gmail.com>

Update pkgs/applications/editors/neovim/utils.nix

OH

Co-authored-by: Austin Horstman <khaneliman12@gmail.com>
2024-11-18 12:25:39 -08:00

261 lines
8.1 KiB
Nix

{ lib
, stdenv
, makeSetupHook
, callPackage
, vimUtils
, vimPlugins
, nodejs
, neovim-unwrapped
, bundlerEnv
, ruby
, lua
, python3Packages
, wrapNeovimUnstable
}:
let
inherit (vimUtils) toVimPlugin;
/* transform all plugins into an attrset
{ optional = bool; plugin = package; }
*/
normalizePlugins = plugins:
let
defaultPlugin = {
plugin = null;
config = null;
optional = false;
};
in
map (x: defaultPlugin // (if (x ? plugin) then x else { plugin = x; })) plugins;
/**
accepts a list of normalized plugins and convert them into a vim package
# Type
```
normalizedPluginsToVimPackage :: [AttrSet] -> AttrSet
```
# Examples
:::{.example}
```nix
normalizedPluginsToVimPackage [ { plugin = vim-fugitive; optional = false'} ]
=> { start = [ vim-fugitive ]; opt = []; }
:::
*/
normalizedPluginsToVimPackage = normalizedPlugins:
let
pluginsPartitioned = lib.partition (x: x.optional == true) normalizedPlugins;
in {
start = map (x: x.plugin) pluginsPartitioned.wrong;
opt = map (x: x.plugin) pluginsPartitioned.right;
};
/* returns everything needed for the caller to wrap its own neovim:
- the generated content of the future init.vim
- the arguments to wrap neovim with
The caller is responsible for writing the init.vim and adding it to the wrapped
arguments (["-u" writeText "init.vim" GENERATEDRC)]).
This makes it possible to write the config anywhere: on a per-project basis
.nvimrc or in $XDG_CONFIG_HOME/nvim/init.vim to avoid sideeffects.
Indeed, note that wrapping with `-u init.vim` has sideeffects like .nvimrc wont be loaded
anymore, $MYVIMRC wont be set etc
*/
makeNeovimConfig = {
customRC ? ""
/* the function you would have passed to lua.withPackages */
, extraLuaPackages ? (_: [ ])
, ...}@attrs: let
luaEnv = neovim-unwrapped.lua.withPackages extraLuaPackages;
in attrs // {
neovimRcContent = customRC;
wrapperArgs = lib.optionals (luaEnv != null) [
"--prefix" "LUA_PATH" ";" (neovim-unwrapped.lua.pkgs.luaLib.genLuaPathAbsStr luaEnv)
"--prefix" "LUA_CPATH" ";" (neovim-unwrapped.lua.pkgs.luaLib.genLuaCPathAbsStr luaEnv)
];
};
# to keep backwards compatibility for people using neovim.override
legacyWrapper = neovim: {
extraMakeWrapperArgs ? ""
/* the function you would have passed to python.withPackages */
, extraPythonPackages ? (_: [])
/* the function you would have passed to python.withPackages */
, withPython3 ? true, extraPython3Packages ? (_: [])
/* the function you would have passed to lua.withPackages */
, extraLuaPackages ? (_: [])
, withNodeJs ? false
, withRuby ? true
, vimAlias ? false
, viAlias ? false
, configure ? {}
, extraName ? ""
}:
let
# we convert from the old configure.format to
plugins = if builtins.hasAttr "plug" configure then
throw "The neovim legacy wrapper doesn't support configure.plug anymore, please setup your plugins via 'configure.packages' instead"
else
lib.flatten (lib.mapAttrsToList genPlugin (configure.packages or {}));
genPlugin = packageName: {start ? [], opt ? []}:
start ++ (map (p: { plugin = p; optional = true; }) opt);
res = makeNeovimConfig {
inherit withPython3;
inherit extraPython3Packages;
inherit extraLuaPackages;
inherit withNodeJs withRuby viAlias vimAlias;
customRC = configure.customRC or "";
inherit plugins;
inherit extraName;
};
in
wrapNeovimUnstable neovim (res // {
wrapperArgs = lib.escapeShellArgs res.wrapperArgs + " " + extraMakeWrapperArgs;
wrapRc = (configure != {});
});
/* Generate vim.g.<LANG>_host_prog lua rc to setup host providers
Mapping a boolean argument to a key that tells us whether to add
vim.g.<LANG>_host_prog=$out/bin/nvim-<LANG>
Or this:
let g:loaded_${prog}_provider=0
While the latter tells nvim that this provider is not available */
generateProviderRc = {
withPython3 ? true
, withNodeJs ? false
, withRuby ? true
# perl is problematic https://github.com/NixOS/nixpkgs/issues/132368
, withPerl ? false
# so that we can pass the full neovim config while ignoring it
, ...
}: let
hostprog_check_table = {
node = withNodeJs;
python = false;
python3 = withPython3;
ruby = withRuby;
perl = withPerl;
};
genProviderCommand = prog: withProg:
if withProg then
"vim.g.${prog}_host_prog='${placeholder "out"}/bin/nvim-${prog}'"
else
"vim.g.loaded_${prog}_provider=0";
hostProviderLua = lib.mapAttrsToList genProviderCommand hostprog_check_table;
in
lib.concatStringsSep ";" hostProviderLua;
/* Converts a lua package into a neovim plugin.
Does so by installing the lua package with a flat hierarchy of folders
*/
buildNeovimPlugin = callPackage ./build-neovim-plugin.nix {
inherit (vimUtils) toVimPlugin;
inherit lua;
};
grammarToPlugin = grammar:
let
name = lib.pipe grammar [
lib.getName
# added in buildGrammar
(lib.removeSuffix "-grammar")
# grammars from tree-sitter.builtGrammars
(lib.removePrefix "tree-sitter-")
(lib.replaceStrings [ "-" ] [ "_" ])
];
nvimGrammars = lib.mapAttrsToList (
name: value:
value.origGrammar
or (builtins.throw "additions to `pkgs.vimPlugins.nvim-treesitter.grammarPlugins` set should be passed through `pkgs.neovimUtils.grammarToPlugin` first")
) vimPlugins.nvim-treesitter.grammarPlugins;
isNvimGrammar = x: builtins.elem x nvimGrammars;
toNvimTreesitterGrammar = callPackage ({ }:
makeSetupHook {
name = "to-nvim-treesitter-grammar";
} ./to-nvim-treesitter-grammar.sh) {};
in
(toVimPlugin (stdenv.mkDerivation {
name = "treesitter-grammar-${name}";
origGrammar = grammar;
grammarName = name;
# Queries for nvim-treesitter's (not just tree-sitter's) officially
# supported languages are bundled with nvim-treesitter
# Queries from repositories for such languages are incompatible
# with nvim's implementation of treesitter.
#
# We try our best effort to only include queries for niche languages
# (there are grammars for them in nixpkgs, but they're in
# `tree-sitter-grammars.tree-sitter-*`; `vimPlugins.nvim-treesitter-parsers.*`
# only includes officially supported languages)
#
# To use grammar for a niche language, users usually do:
# packages.all.start = with final.vimPlugins; [
# (pkgs.neovimUtils.grammarToPlugin pkgs.tree-sitter-grammars.tree-sitter-LANG)
# ]
#
# See also https://github.com/NixOS/nixpkgs/pull/344849#issuecomment-2381447839
installQueries = !isNvimGrammar grammar;
dontUnpack = true;
__structuredAttrs = true;
nativeBuildInputs = [ toNvimTreesitterGrammar ];
meta = {
platforms = lib.platforms.all;
} // grammar.meta;
}));
/*
Fork of vimUtils.packDir that additionnally generates a propagated-build-inputs-file that
can be used by the lua hooks to generate a proper LUA_PATH
Generates a packpath folder as expected by vim
Example:
packDir ( {myVimPackage = { start = [ vimPlugins.vim-fugitive ]; opt = []; }; })
=> "/nix/store/xxxxx-pack-dir"
*/
packDir = packages:
let
rawPackDir = vimUtils.packDir packages;
in
rawPackDir.override ({
postBuild = ''
mkdir $out/nix-support
for i in $(find -L $out -name propagated-build-inputs ); do
cat "$i" >> $out/nix-support/propagated-build-inputs
done
'';});
in
{
inherit makeNeovimConfig;
inherit generateProviderRc;
inherit legacyWrapper;
inherit grammarToPlugin;
inherit packDir;
inherit normalizePlugins normalizedPluginsToVimPackage;
inherit buildNeovimPlugin;
buildNeovimPluginFrom2Nix = lib.warn "buildNeovimPluginFrom2Nix was renamed to buildNeovimPlugin" buildNeovimPlugin;
}