Compare commits
14 Commits
99b4355a1a
...
ceeb4c53ef
| Author | SHA1 | Date |
|---|---|---|
|
|
ceeb4c53ef | |
|
|
a842362876 | |
|
|
2761e11d62 | |
|
|
43d374b618 | |
|
|
cf660fa367 | |
|
|
c00555d6d8 | |
|
|
2816b256d4 | |
|
|
aff1dbc079 | |
|
|
1d6bc88719 | |
|
|
44bfef1f1c | |
|
|
bf329e5f42 | |
|
|
c12a87bfa1 | |
|
|
fabe787feb | |
|
|
27c8d275c5 |
|
|
@ -1,2 +1,3 @@
|
||||||
.direnv
|
.direnv
|
||||||
.envrc
|
.envrc
|
||||||
|
result
|
||||||
|
|
|
||||||
36
flake.lock
36
flake.lock
|
|
@ -49,44 +49,10 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1660438583,
|
|
||||||
"narHash": "sha256-rJUTYxFKlWUJI3njAwEc1pKAVooAViZGJvsgqfh/q/E=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"rev": "bbd8f7cd87d0b29294ef3072ffdbd61d60f05da4",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs"
|
||||||
"yants": "yants"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yants": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1686863218,
|
|
||||||
"narHash": "sha256-kooxYm3/3ornWtVBNHM3Zh020gACUyFX2G0VQXnB+mk=",
|
|
||||||
"owner": "divnix",
|
|
||||||
"repo": "yants",
|
|
||||||
"rev": "8f0da0dba57149676aa4817ec0c880fbde7a648d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "divnix",
|
|
||||||
"repo": "yants",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
11
flake.nix
11
flake.nix
|
|
@ -1,19 +1,20 @@
|
||||||
{
|
{
|
||||||
description = "My neovim configuration";
|
description = "Sloth-flake - a nix power neovim plugin manager";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
yants.url = "github:divnix/yants";
|
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {flake-parts, ...} @ inputs: let
|
outputs = {flake-parts, ...} @ inputs: (flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
in (flake-parts.lib.mkFlake {inherit inputs;} {
|
|
||||||
systems = ["x86_64-linux"];
|
systems = ["x86_64-linux"];
|
||||||
|
|
||||||
imports = [
|
imports = with flake-parts.flakeModules; [
|
||||||
|
flakeModules
|
||||||
./dev
|
./dev
|
||||||
|
./flakeModule.nix
|
||||||
./lib
|
./lib
|
||||||
|
./tests
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
{config, ...}: {
|
||||||
|
config.flake.flakeModules.default = {
|
||||||
|
lib,
|
||||||
|
flake-parts-lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) attrsToList listToAttrs mkOption types;
|
||||||
|
inherit (flake-parts-lib) mkPerSystemOption;
|
||||||
|
topConfig = config;
|
||||||
|
in {
|
||||||
|
options.perSystem = mkPerSystemOption ({
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.sloth;
|
||||||
|
sLib = cfg.lib;
|
||||||
|
|
||||||
|
packageModule = types.submodule ({config, ...}: {
|
||||||
|
options = {
|
||||||
|
module = mkOption {
|
||||||
|
description = "module used to create your neovim package";
|
||||||
|
type = types.deferredModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
modules = mkOption {
|
||||||
|
description = "modules used to create your neovim package";
|
||||||
|
type = with types; listOf deferredModule;
|
||||||
|
default = [config.module];
|
||||||
|
};
|
||||||
|
|
||||||
|
specialArgs = mkOption {
|
||||||
|
description = "specialArgs to follow to your modules";
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
buildPackage = {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: {
|
||||||
|
inherit name;
|
||||||
|
value = sLib.mkNeovimPkg {inherit (value) modules specialArgs;};
|
||||||
|
};
|
||||||
|
packagesList = map buildPackage (attrsToList cfg.packages);
|
||||||
|
in {
|
||||||
|
options.sloth = {
|
||||||
|
lib = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
description = "sloth’s lib";
|
||||||
|
default = topConfig.flake.mkLib {inherit pkgs;};
|
||||||
|
defaultText = "mkLib {inherit pkgs;}";
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = mkOption {
|
||||||
|
description = "neovim package to create with sloth";
|
||||||
|
default = {};
|
||||||
|
type = with types; attrsOf packageModule;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.packages = listToAttrs packagesList;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,11 @@
|
||||||
{
|
{self, ...}: let
|
||||||
self,
|
|
||||||
inputs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (builtins) readFile replaceStrings;
|
inherit (builtins) readFile replaceStrings;
|
||||||
versionFile = replaceStrings ["\n"] [""] (readFile ../VERSION);
|
versionFile = replaceStrings ["\n"] [""] (readFile ../VERSION);
|
||||||
version =
|
dirty =
|
||||||
if self.sourceInfo ? dirtyShortRev
|
if self.sourceInfo ? dirtyShortRev
|
||||||
then "${versionFile}-${self.sourceInfo.dirtyShortRev}"
|
then "-${self.sourceInfo.dirtyShortRev}"
|
||||||
else versionFile;
|
else "";
|
||||||
|
version = "${versionFile}${dirty}";
|
||||||
types = import ./types.nix {inherit (inputs) yants;};
|
|
||||||
in {
|
in {
|
||||||
flake.lib = {
|
flake.mkLib = import ./lib.nix {inherit version;};
|
||||||
mkNeovimPkg = import ./mkNeovimPkg.nix {inherit version types;};
|
|
||||||
mkPluginsFromInputs = import ./mkPluginsFromInputs.nix;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
200
lib/deps.nix
200
lib/deps.nix
|
|
@ -1,200 +0,0 @@
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
vimUtils,
|
|
||||||
dependenciesExtraArgs,
|
|
||||||
types,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (builtins) foldl' isPath isList isString mapAttrs match elemAt;
|
|
||||||
inherit (lib.attrsets) attrNames optionalAttrs;
|
|
||||||
inherit (lib.lists) concatMap;
|
|
||||||
inherit (lib.strings) fileContents splitString;
|
|
||||||
lua = callPackage ./lua.nix {};
|
|
||||||
callPackage = lib.callPackageWith (pkgs // dependenciesExtraArgs);
|
|
||||||
|
|
||||||
hasMatch = pattern: str: isList (match pattern str);
|
|
||||||
wrapArray = value:
|
|
||||||
if isList value
|
|
||||||
then value
|
|
||||||
else [value];
|
|
||||||
|
|
||||||
defaultPlugin = {
|
|
||||||
enabled = true;
|
|
||||||
init = null;
|
|
||||||
config = null;
|
|
||||||
dependencies = [];
|
|
||||||
lazy = false;
|
|
||||||
cmd = [];
|
|
||||||
ft = [];
|
|
||||||
events = [];
|
|
||||||
keymaps = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
remotePluginToNeovimPlugin = p:
|
|
||||||
vimUtils.buildVimPlugin rec {
|
|
||||||
inherit (p) src name;
|
|
||||||
pname = name;
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultKeymap = {mode = "n";};
|
|
||||||
normalizeKeymap = keymap: let
|
|
||||||
value = (
|
|
||||||
if isString keymap
|
|
||||||
then {mapping = keymap;}
|
|
||||||
else keymap
|
|
||||||
);
|
|
||||||
in
|
|
||||||
mapAttrs (_: wrapArray) (defaultKeymap // value);
|
|
||||||
normalizeKeymaps = keymaps:
|
|
||||||
if isList keymaps
|
|
||||||
then map normalizeKeymap keymaps
|
|
||||||
else [(normalizeKeymap keymaps)];
|
|
||||||
|
|
||||||
normalizeEvent = event: let
|
|
||||||
value =
|
|
||||||
if ! isString event
|
|
||||||
then event
|
|
||||||
else if ! hasMatch ".* .*" event
|
|
||||||
then {name = event;}
|
|
||||||
else let
|
|
||||||
part = elemAt (splitString " " event);
|
|
||||||
in {
|
|
||||||
name = part 0;
|
|
||||||
pattern = part 1;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
mapAttrs (_: wrapArray) value;
|
|
||||||
normalizeEvents = events:
|
|
||||||
if isList events
|
|
||||||
then map normalizeEvent events
|
|
||||||
else [(normalizeEvent events)];
|
|
||||||
|
|
||||||
withPluginDefaults = dep: defaultPlugin // dep;
|
|
||||||
normalizePlugin = d: let
|
|
||||||
dep = types.dependency d;
|
|
||||||
plugin =
|
|
||||||
if ! dep ? plugin
|
|
||||||
then {plugin = dep;}
|
|
||||||
else let
|
|
||||||
inherit (dep) plugin;
|
|
||||||
in
|
|
||||||
if attrNames plugin == ["name" "src"]
|
|
||||||
then dep // {plugin = remotePluginToNeovimPlugin plugin;}
|
|
||||||
else dep;
|
|
||||||
p = withPluginDefaults plugin;
|
|
||||||
in
|
|
||||||
p
|
|
||||||
// rec {
|
|
||||||
hasCommands = p.cmd != [];
|
|
||||||
hasFileTypes = p.ft != [];
|
|
||||||
keymaps = normalizeKeymaps p.keymaps;
|
|
||||||
hasKeymaps = p.keymaps != [];
|
|
||||||
events = normalizeEvents p.events;
|
|
||||||
hasEvents = p.events != [];
|
|
||||||
lazy = p.lazy || hasCommands || hasFileTypes || hasEvents || hasKeymaps;
|
|
||||||
optional = lazy || p.init != null;
|
|
||||||
};
|
|
||||||
|
|
||||||
normalizeOrImportPlugin = dep:
|
|
||||||
if isPath dep
|
|
||||||
then normalizePlugins (callPackage dep {})
|
|
||||||
else [(normalizePlugin dep)];
|
|
||||||
normalizePlugins = concatMap normalizeOrImportPlugin;
|
|
||||||
|
|
||||||
mkRuntimePlugin = {
|
|
||||||
src,
|
|
||||||
version,
|
|
||||||
...
|
|
||||||
}@opts:
|
|
||||||
vimUtils.buildVimPlugin ({
|
|
||||||
inherit src;
|
|
||||||
}
|
|
||||||
// (optionalAttrs (opts ? nvimRequireCheck) {
|
|
||||||
inherit (opts) nvimRequireCheck;
|
|
||||||
})
|
|
||||||
// (optionalAttrs (isNull version) {
|
|
||||||
name = "runtime";
|
|
||||||
})
|
|
||||||
// (optionalAttrs (! isNull version) {
|
|
||||||
inherit version;
|
|
||||||
pname = "runtime";
|
|
||||||
}));
|
|
||||||
|
|
||||||
mkSlothFlakePlugin = version: plugins:
|
|
||||||
vimUtils.buildVimPlugin {
|
|
||||||
inherit version;
|
|
||||||
pname = "sloth-flake";
|
|
||||||
src = with lib.fileset;
|
|
||||||
toSource {
|
|
||||||
root = ../.;
|
|
||||||
fileset = ../lua/sloth-flake;
|
|
||||||
};
|
|
||||||
nvimRequireCheck = "sloth-flake";
|
|
||||||
buildPhase = ''
|
|
||||||
dir=lua/sloth-flake
|
|
||||||
|
|
||||||
cat <<'LUA' > $dir/dependencies.lua
|
|
||||||
${pluginsLuaDef plugins}
|
|
||||||
LUA
|
|
||||||
|
|
||||||
cat <<'LUA' > $dir/version.lua
|
|
||||||
${versionLua version}
|
|
||||||
LUA
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
versionLua = version: with lua; nix2lua (return (lambda (return version)));
|
|
||||||
|
|
||||||
textOrContent = content:
|
|
||||||
if isPath content
|
|
||||||
then fileContents content
|
|
||||||
else content;
|
|
||||||
|
|
||||||
pluginLuaDef = memo: plugin: let
|
|
||||||
mkTypeFn = type: let
|
|
||||||
content = textOrContent plugin.${type};
|
|
||||||
in
|
|
||||||
optionalAttrs (! isNull plugin.${type}) {
|
|
||||||
${type} = with lua; lambda (raw content);
|
|
||||||
};
|
|
||||||
pluginName = plugin:
|
|
||||||
if plugin ? pname
|
|
||||||
then plugin.pname
|
|
||||||
else plugin.name;
|
|
||||||
name = pluginName plugin.plugin;
|
|
||||||
in
|
|
||||||
memo
|
|
||||||
// {
|
|
||||||
${name} =
|
|
||||||
{
|
|
||||||
name = pluginName plugin.plugin;
|
|
||||||
dependencies = map pluginName plugin.dependencies;
|
|
||||||
}
|
|
||||||
// (mkTypeFn "init")
|
|
||||||
// (mkTypeFn "config")
|
|
||||||
// (optionalAttrs plugin.lazy {
|
|
||||||
lazy = true;
|
|
||||||
})
|
|
||||||
// (optionalAttrs plugin.hasCommands {
|
|
||||||
inherit (plugin) cmd;
|
|
||||||
})
|
|
||||||
// (optionalAttrs plugin.hasFileTypes {
|
|
||||||
inherit (plugin) ft;
|
|
||||||
})
|
|
||||||
// (optionalAttrs plugin.hasEvents {
|
|
||||||
inherit (plugin) events;
|
|
||||||
})
|
|
||||||
// (optionalAttrs plugin.hasKeymaps {
|
|
||||||
inherit (plugin) keymaps;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
pluginsLuaDef = plugins:
|
|
||||||
with lua; nix2lua (return (foldl' pluginLuaDef {} plugins));
|
|
||||||
in {
|
|
||||||
inherit normalizePlugin;
|
|
||||||
inherit normalizePlugins;
|
|
||||||
inherit mkSlothFlakePlugin;
|
|
||||||
inherit mkRuntimePlugin;
|
|
||||||
inherit textOrContent;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
sloth,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (pkgs.lib) evalModules;
|
||||||
|
sLib = sloth.lib;
|
||||||
|
in {
|
||||||
|
evalSlothModules = {
|
||||||
|
modules ? [],
|
||||||
|
specialArgs ? {},
|
||||||
|
}: let
|
||||||
|
moduleConfig = evalModules {
|
||||||
|
specialArgs = specialArgs // {inherit pkgs;};
|
||||||
|
modules = modules ++ [sLib.defaultModule];
|
||||||
|
class = "sloth";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
moduleConfig.config;
|
||||||
|
|
||||||
|
mkNeovimPkg = {
|
||||||
|
modules ? [],
|
||||||
|
specialArgs ? {},
|
||||||
|
}:
|
||||||
|
(sLib.evalSlothModules {inherit modules specialArgs;}).neovimPackage;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{version, ...}: {pkgs, ...}:
|
||||||
|
pkgs.lib.fix (lib: let
|
||||||
|
inherit (pkgs.lib) callPackageWith mergeAttrsList;
|
||||||
|
|
||||||
|
callModule = callPackageWith {
|
||||||
|
inherit pkgs callModule;
|
||||||
|
sloth = {inherit lib version;};
|
||||||
|
};
|
||||||
|
|
||||||
|
callModules = modules: mergeAttrsList (map (path: callModule path {}) modules);
|
||||||
|
in
|
||||||
|
callModules [
|
||||||
|
./evalModules.nix
|
||||||
|
./mkPluginsFromInputs.nix
|
||||||
|
./modules
|
||||||
|
])
|
||||||
178
lib/lua.nix
178
lib/lua.nix
|
|
@ -1,92 +1,132 @@
|
||||||
{...}: let
|
{pkgs, ...}: let
|
||||||
inherit (builtins) match isNull typeOf concatStringsSep attrNames concatMap;
|
inherit
|
||||||
|
(builtins)
|
||||||
|
attrNames
|
||||||
|
concatStringsSep
|
||||||
|
filter
|
||||||
|
isAttrs
|
||||||
|
isBool
|
||||||
|
isFloat
|
||||||
|
isInt
|
||||||
|
isList
|
||||||
|
isPath
|
||||||
|
isNull
|
||||||
|
isString
|
||||||
|
match
|
||||||
|
toJSON
|
||||||
|
typeOf
|
||||||
|
;
|
||||||
|
inherit
|
||||||
|
(pkgs.lib)
|
||||||
|
assertMsg
|
||||||
|
concatStrings
|
||||||
|
fix
|
||||||
|
imap0
|
||||||
|
isDerivation
|
||||||
|
mapAttrsToList
|
||||||
|
optionalString
|
||||||
|
splitString
|
||||||
|
toPretty
|
||||||
|
;
|
||||||
|
|
||||||
commaJoin = concatStringsSep ", ";
|
commaJoin = concatStringsSep ", ";
|
||||||
wrapNotNull' = val: value:
|
|
||||||
if isNull val
|
|
||||||
then []
|
|
||||||
else [value];
|
|
||||||
wrapNotNull = val: wrapNotNull' val val;
|
|
||||||
|
|
||||||
toLua = {
|
renderLua = {
|
||||||
|
multiline ? true,
|
||||||
|
indent ? "",
|
||||||
|
asBindings ? false,
|
||||||
|
} @ args: v: let
|
||||||
|
innerIndent = "${indent} ";
|
||||||
|
introSpace =
|
||||||
|
if multiline
|
||||||
|
then "\n${innerIndent}"
|
||||||
|
else " ";
|
||||||
|
outroSpace =
|
||||||
|
if multiline
|
||||||
|
then "\n${indent}"
|
||||||
|
else " ";
|
||||||
|
innerArgs =
|
||||||
|
args
|
||||||
|
// {
|
||||||
|
indent =
|
||||||
|
if asBindings
|
||||||
|
then indent
|
||||||
|
else innerIndent;
|
||||||
|
asBindings = false;
|
||||||
|
};
|
||||||
|
|
||||||
ast = {
|
ast = {
|
||||||
raw = {data, ...}: data;
|
render = args: data: let
|
||||||
return = {data, ...}: "return ${nix2lua data}";
|
astType = data.__ast;
|
||||||
fn = {
|
in
|
||||||
|
if ast ? ${astType}
|
||||||
|
then ast.${astType} args data
|
||||||
|
else abort ''Unknown ast type ${astType}'';
|
||||||
|
raw = args: {
|
||||||
|
data,
|
||||||
|
__no_indent ? false,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
content =
|
||||||
|
if __no_indent
|
||||||
|
then data
|
||||||
|
else concatStringsSep "\n" (imap0 (idx: line: "${optionalString (idx != 0) args.indent}${line}") (splitString "\n" data));
|
||||||
|
in
|
||||||
|
content;
|
||||||
|
return = args: {data, ...}: "return ${renderLua args data}";
|
||||||
|
fn = args: {
|
||||||
data,
|
data,
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
...
|
...
|
||||||
}: "function ${name}(${commaJoin args})\n${nix2lua data}\nend";
|
}: "function ${name}(${commaJoin args})${introSpace}${renderLua innerArgs data}${outroSpace}end";
|
||||||
};
|
};
|
||||||
|
|
||||||
type = rec {
|
generatedBindings = assert assertMsg (badBindingNames == []) "Bad Lua var names: ${toPretty {} badBindingNames}";
|
||||||
null = _: "nil";
|
concatStrings (mapAttrsToList (key: value: "${indent}${key} = ${renderLua innerArgs value}\n") v);
|
||||||
string = data: ''"${data}"'';
|
|
||||||
path = string;
|
|
||||||
lambda = data: builtins.trace "Skipping function" null;
|
|
||||||
int = data: toString data;
|
|
||||||
|
|
||||||
bool = data:
|
concatItems = concatStringsSep ",${introSpace}";
|
||||||
if data
|
varNameRe = "[[:alpha:]_][[:alnum:]_]*";
|
||||||
then "true"
|
matchBindingName = match "${varNameRe}(\\.${varNameRe})*";
|
||||||
else "false";
|
badBindingNames = filter (name: matchBindingName name == null) (attrNames v);
|
||||||
|
|
||||||
ast = data: let
|
luaKey = key:
|
||||||
astType = data.__ast;
|
if match varNameRe key == null
|
||||||
in
|
then "[${toJSON key}]"
|
||||||
if toLua.ast ? ${astType}
|
|
||||||
then toLua.ast.${astType} data
|
|
||||||
else abort ''Unknown ast type ${astType}'';
|
|
||||||
|
|
||||||
list = data: let
|
|
||||||
nix2luaList = val: wrapNotNull (nix2lua val);
|
|
||||||
listContent = commaJoin (concatMap nix2luaList data);
|
|
||||||
in "{ ${listContent} }";
|
|
||||||
|
|
||||||
set = data: let
|
|
||||||
mkKeyValue = key: let
|
|
||||||
value = data.${key};
|
|
||||||
luaKey =
|
|
||||||
if isNull (match "[a-zA-Z_][a-zA-Z_0-9]+" key)
|
|
||||||
then ''["${key}"]''
|
|
||||||
else key;
|
else key;
|
||||||
luaValue = nix2lua value;
|
|
||||||
|
withSpaces = val: optionalString (val != "") "${introSpace}${val}${outroSpace}";
|
||||||
|
|
||||||
|
mkKV = key: value: "${luaKey key} = ${renderLua innerArgs value}";
|
||||||
in
|
in
|
||||||
wrapNotNull' luaValue ''
|
if asBindings
|
||||||
${luaKey} = ${luaValue},
|
then generatedBindings
|
||||||
'';
|
else if isNull v
|
||||||
attrsContent = concatMap mkKeyValue (attrNames data);
|
then "nil"
|
||||||
in ''
|
else if isInt v || isFloat v || isString v || isBool v
|
||||||
{
|
then toJSON v
|
||||||
${concatStringsSep "" attrsContent}}
|
else if isPath v || isDerivation v
|
||||||
'';
|
then toJSON "${v}"
|
||||||
};
|
else if isList v
|
||||||
};
|
then "{${withSpaces (concatItems (map (renderLua innerArgs) v))}}"
|
||||||
|
else if v ? __ast
|
||||||
|
then ast.render args v
|
||||||
|
else if isAttrs v
|
||||||
|
then "{${withSpaces (concatItems (mapAttrsToList mkKV v))}}"
|
||||||
|
else abort "generators.renderLua: type ${typeOf v} is unsupported";
|
||||||
|
|
||||||
newAst = type: set: set // {__ast = type;};
|
newAst = type: set: set // {__ast = type;};
|
||||||
|
|
||||||
nix2lua = data: let
|
|
||||||
type = typeOf data;
|
|
||||||
in
|
in
|
||||||
if data ? __ast
|
fix (lua: {
|
||||||
then toLua.type.ast data
|
inherit renderLua;
|
||||||
else if toLua.type ? ${type}
|
|
||||||
then toLua.type.${type} data
|
writeLua = name: value: pkgs.writeText name (lua.renderLua {} value);
|
||||||
else abort ''Type "${type}"'';
|
|
||||||
in rec {
|
|
||||||
inherit nix2lua;
|
|
||||||
|
|
||||||
raw = data: newAst "raw" {inherit data;};
|
raw = data: newAst "raw" {inherit data;};
|
||||||
|
|
||||||
functionWithArgs = name: args: data:
|
function = name: args: data: newAst "fn" {inherit name data args;};
|
||||||
newAst "fn" {
|
|
||||||
inherit name data args;
|
|
||||||
};
|
|
||||||
|
|
||||||
function = name: data: functionWithArgs name [] data;
|
lambda = lua.function "";
|
||||||
|
|
||||||
lambda = function "";
|
|
||||||
|
|
||||||
return = data: newAst "return" {inherit data;};
|
return = data: newAst "return" {inherit data;};
|
||||||
}
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
{
|
|
||||||
version,
|
|
||||||
types,
|
|
||||||
}: {
|
|
||||||
pkgs,
|
|
||||||
package ? pkgs.neovim-unwrapped,
|
|
||||||
dependencies ? [],
|
|
||||||
dependenciesExtraArgs ? {},
|
|
||||||
extraLuaPackages ? (_: []),
|
|
||||||
runtime ? null,
|
|
||||||
init ? null,
|
|
||||||
viAlias ? false,
|
|
||||||
vimAlias ? false,
|
|
||||||
vimdiffAlias ? false,
|
|
||||||
nvimdiffAlias ? false,
|
|
||||||
...
|
|
||||||
} @ config: let
|
|
||||||
inherit (builtins) isString isPath map;
|
|
||||||
inherit (pkgs) callPackage bash lib;
|
|
||||||
inherit (lib.strings) optionalString;
|
|
||||||
inherit (lib.lists) concatMap optional;
|
|
||||||
inherit (lib.trivial) flip;
|
|
||||||
inherit (lib.attrsets) optionalAttrs;
|
|
||||||
|
|
||||||
deps = callPackage ./deps.nix {inherit dependenciesExtraArgs types;};
|
|
||||||
|
|
||||||
normalizedPlugins = deps.normalizePlugins dependencies;
|
|
||||||
sloth-flake = deps.mkSlothFlakePlugin version normalizedPlugins;
|
|
||||||
runtimePlugin = deps.mkRuntimePlugin runtime;
|
|
||||||
plugins =
|
|
||||||
normalizedPlugins
|
|
||||||
++ (
|
|
||||||
deps.normalizePlugins
|
|
||||||
([sloth-flake] ++ (optional (runtime != null) runtimePlugin))
|
|
||||||
);
|
|
||||||
|
|
||||||
extractPlugin = p: {inherit (p) optional plugin;};
|
|
||||||
extractPlugins = map extractPlugin;
|
|
||||||
|
|
||||||
extractLuaPackageFn = plugin:
|
|
||||||
optional (plugin ? extraLuaPackages) plugin.extraLuaPackages;
|
|
||||||
extractLuaPackagesFn = plugins: let
|
|
||||||
fnList = concatMap extractLuaPackageFn plugins;
|
|
||||||
concatPackages = ps: fn: fn ps;
|
|
||||||
in
|
|
||||||
ps: concatMap (concatPackages ps) fnList;
|
|
||||||
|
|
||||||
buildInit = {
|
|
||||||
init ? null,
|
|
||||||
postInit ? null,
|
|
||||||
config ? null,
|
|
||||||
}: let
|
|
||||||
initStr = optionalString (! isNull init) ''
|
|
||||||
(function()
|
|
||||||
${deps.textOrContent init}
|
|
||||||
end)();
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
slothCall =
|
|
||||||
if isNull postInit
|
|
||||||
then "require('sloth-flake').setup {}"
|
|
||||||
else ''
|
|
||||||
require('sloth-flake').setup {
|
|
||||||
post_init = function()
|
|
||||||
${deps.textOrContent postInit}
|
|
||||||
end,
|
|
||||||
};
|
|
||||||
'';
|
|
||||||
|
|
||||||
configStr = optionalString (! isNull config) ''
|
|
||||||
|
|
||||||
(function()
|
|
||||||
${deps.textOrContent config}
|
|
||||||
end)()
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
-- Generated by sloth-flake
|
|
||||||
${initStr}
|
|
||||||
${slothCall}
|
|
||||||
${configStr}
|
|
||||||
'';
|
|
||||||
|
|
||||||
customRC =
|
|
||||||
if isString init || isPath init
|
|
||||||
then deps.textOrContent init
|
|
||||||
else buildInit (optionalAttrs (! isNull init) init);
|
|
||||||
|
|
||||||
neovimConfig =
|
|
||||||
pkgs.neovimUtils.makeNeovimConfig {
|
|
||||||
inherit customRC;
|
|
||||||
plugins = extractPlugins plugins;
|
|
||||||
extraLuaPackages = ps:
|
|
||||||
(extractLuaPackagesFn plugins ps) ++ (extraLuaPackages ps);
|
|
||||||
}
|
|
||||||
// {luaRcContent = customRC;};
|
|
||||||
params =
|
|
||||||
removeAttrs neovimConfig ["manifestRc" "neovimRcContent"]
|
|
||||||
// {inherit viAlias vimAlias;};
|
|
||||||
pkg = pkgs.wrapNeovimUnstable package params;
|
|
||||||
mkDiffAlias = name:
|
|
||||||
(flip optionalString) ''
|
|
||||||
cat <<SH > $out/bin/${name}
|
|
||||||
#!${bash}/bin/bash
|
|
||||||
exec $out/bin/nvim -d "\''${@}"
|
|
||||||
SH
|
|
||||||
chmod 555 $out/bin/${name}
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
builtins.seq (types.mkNeovimPkgOptions config) (pkg.overrideAttrs (final: super: {
|
|
||||||
postBuild =
|
|
||||||
super.postBuild
|
|
||||||
+ (mkDiffAlias "vimdiff" vimdiffAlias)
|
|
||||||
+ (mkDiffAlias "nvimdiff" nvimdiffAlias);
|
|
||||||
}))
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{pkgs, ...}: let
|
||||||
pkgs,
|
inherit (builtins) attrNames filter foldl' mapAttrs;
|
||||||
|
in {
|
||||||
|
mkPluginsFromInputs = {
|
||||||
inputs,
|
inputs,
|
||||||
predicate ? pkgs.lib.strings.hasPrefix "plugin-",
|
predicate ? pkgs.lib.strings.hasPrefix "plugin-",
|
||||||
nameMap ? builtins.substring 7 (-1),
|
nameMap ? builtins.substring 7 (-1),
|
||||||
buildVimPlugin ? pkgs.vimUtils.buildVimPlugin,
|
buildVimPlugin ? pkgs.vimUtils.buildVimPlugin,
|
||||||
}: let
|
}: let
|
||||||
inherit (builtins) attrNames filter foldl' mapAttrs;
|
|
||||||
names = filter predicate (attrNames inputs);
|
names = filter predicate (attrNames inputs);
|
||||||
mkPlugin = m: k: let
|
mkPlugin = m: k: let
|
||||||
name = nameMap k;
|
name = nameMap k;
|
||||||
|
|
@ -17,4 +18,5 @@
|
||||||
m // {${name} = pluginDef;};
|
m // {${name} = pluginDef;};
|
||||||
plugins = foldl' mkPlugin {} names;
|
plugins = foldl' mkPlugin {} names;
|
||||||
in
|
in
|
||||||
mapAttrs (_: buildVimPlugin) plugins
|
mapAttrs (_: buildVimPlugin) plugins;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
callModule,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) concatLists;
|
||||||
|
inherit (pkgs) bash lib;
|
||||||
|
inherit
|
||||||
|
(lib)
|
||||||
|
concatMap
|
||||||
|
flip
|
||||||
|
literalExample
|
||||||
|
mkEnableOption
|
||||||
|
mkOption
|
||||||
|
mkPackageOption
|
||||||
|
optional
|
||||||
|
optionalString
|
||||||
|
types
|
||||||
|
;
|
||||||
|
|
||||||
|
modules = {
|
||||||
|
init = callModule ./init.nix {};
|
||||||
|
plugin = callModule ./plugin {};
|
||||||
|
runtime = callModule ./runtime.nix {};
|
||||||
|
sloth = callModule ./sloth.nix {};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraLuaPackagesType =
|
||||||
|
(with types; functionTo (listOf package))
|
||||||
|
// {
|
||||||
|
merge = loc: defs: let
|
||||||
|
fnList = map (def: def.value) defs;
|
||||||
|
concatPackages = ps: fn: fn ps;
|
||||||
|
in
|
||||||
|
ps: concatMap (concatPackages ps) fnList;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkDiffAlias = name:
|
||||||
|
(flip optionalString) ''
|
||||||
|
cat <<SH > $out/bin/${name}
|
||||||
|
#!${bash}/bin/bash
|
||||||
|
exec $out/bin/nvim -d "\''${@}"
|
||||||
|
SH
|
||||||
|
chmod 555 $out/bin/${name}
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
defaultModule = {
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
pkg = pkgs.wrapNeovimUnstable config.package config.neovimOptions;
|
||||||
|
|
||||||
|
neovimOptions = pkgs.neovimUtils.makeNeovimConfig rec {
|
||||||
|
inherit (config) extraLuaPackages viAlias vimAlias;
|
||||||
|
|
||||||
|
customLuaRC = config.init.finalContent;
|
||||||
|
wrapRc = customLuaRC != null;
|
||||||
|
|
||||||
|
plugins = concatLists [
|
||||||
|
(map modules.plugin.extract config.plugins)
|
||||||
|
(optional (! isNull config.runtime) config.runtime.package)
|
||||||
|
[config.slothPlugin]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
neovimPackage = pkg.overrideAttrs (final: super: {
|
||||||
|
postBuild =
|
||||||
|
super.postBuild
|
||||||
|
+ (mkDiffAlias "vimdiff" config.vimdiffAlias)
|
||||||
|
+ (mkDiffAlias "nvimdiff" config.nvimdiffAlias);
|
||||||
|
});
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
package = mkPackageOption pkgs "neovim-unwrapped" {};
|
||||||
|
|
||||||
|
extraLuaPackages = mkOption {
|
||||||
|
description = ''
|
||||||
|
function to define extra lua packages that should be included in
|
||||||
|
neovim environment.
|
||||||
|
'';
|
||||||
|
type = extraLuaPackagesType;
|
||||||
|
example = literalExample "p: [p.nvim-nio]";
|
||||||
|
defaultText = literalExample "_: []";
|
||||||
|
default = _: [];
|
||||||
|
};
|
||||||
|
|
||||||
|
init = modules.init.option;
|
||||||
|
runtime = modules.runtime.option;
|
||||||
|
plugins = modules.plugin.option;
|
||||||
|
|
||||||
|
viAlias = mkEnableOption "creation on `vi` alias";
|
||||||
|
vimAlias = mkEnableOption "creation on `vim` alias";
|
||||||
|
vimdiffAlias = mkEnableOption "creation on `vimdiff` alias";
|
||||||
|
nvimdiffAlias = mkEnableOption "creation on `nvimdiff` alias";
|
||||||
|
|
||||||
|
pluginLuaDefinitions = mkOption {
|
||||||
|
description = ''
|
||||||
|
All lua definitions of plugins. Used by sloth vim plugin
|
||||||
|
'';
|
||||||
|
type = with types; attrsOf anything;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
default = modules.sloth.mkPluginLuaDefinitions config.plugins;
|
||||||
|
};
|
||||||
|
|
||||||
|
slothPlugin = mkOption {
|
||||||
|
description = ''
|
||||||
|
The resulted sloth plugin
|
||||||
|
'';
|
||||||
|
type = types.package;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
default = modules.sloth.mkSlothPlugin config.pluginLuaDefinitions;
|
||||||
|
};
|
||||||
|
|
||||||
|
neovimOptions = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
readOnly = true;
|
||||||
|
description = "The resulting configuration passed to `pkgs.wrapNeovimUnstable`";
|
||||||
|
default = neovimOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
neovimPackage = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
description = "The neovim package generated from your configuration.";
|
||||||
|
readOnly = true;
|
||||||
|
# defaultText = lib.literalExpression "pkgs.hello";
|
||||||
|
default = neovimPackage;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
callModule,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) isAttrs isPath isString readFile;
|
||||||
|
inherit (pkgs.lib) fileContents fix mkOption optionalAttrs optionalString types;
|
||||||
|
|
||||||
|
lua = callModule ../lua.nix {};
|
||||||
|
|
||||||
|
coerceToModule = value:
|
||||||
|
if isAttrs value
|
||||||
|
then value
|
||||||
|
else {finalContent = textOrContent value;};
|
||||||
|
|
||||||
|
textOrContent = content:
|
||||||
|
if isPath content
|
||||||
|
then fileContents content
|
||||||
|
else content;
|
||||||
|
|
||||||
|
buildInit = {
|
||||||
|
init ? null,
|
||||||
|
postInit ? null,
|
||||||
|
config ? null,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
initStr = optionalString (! isNull init) ''
|
||||||
|
(function()
|
||||||
|
${textOrContent init}
|
||||||
|
end)();
|
||||||
|
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInitContent = optionalAttrs (! isNull postInit) {
|
||||||
|
post_init = lua.lambda [] (lua.raw (textOrContent postInit));
|
||||||
|
};
|
||||||
|
|
||||||
|
slothCall = "require('sloth-flake').setup ${lua.renderLua {} postInitContent};";
|
||||||
|
|
||||||
|
configStr = optionalString (! isNull config) ''
|
||||||
|
|
||||||
|
(function()
|
||||||
|
${textOrContent config}
|
||||||
|
end)()
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
-- Generated by sloth-flake
|
||||||
|
${initStr}
|
||||||
|
${slothCall}
|
||||||
|
${configStr}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
module = types.submodule ({config, ...}: {
|
||||||
|
options = {
|
||||||
|
init = mkOption {
|
||||||
|
type = with types; nullOr (either path str);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Lua code to call before plugins loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
postInit = mkOption {
|
||||||
|
type = with types; nullOr (either path str);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Lua code called after init but before import
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = with types; nullOr (either path str);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Lua code called after all plugins are loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
finalContent = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = self.mkCustomLuaRc config;
|
||||||
|
description = ''
|
||||||
|
The resulted init package.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
option = mkOption {
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
init.lua configuration
|
||||||
|
'';
|
||||||
|
type = with types; coercedTo (nullOr (oneOf [path str])) coerceToModule self.module;
|
||||||
|
example = ./init.lua;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkCustomLuaRc = init:
|
||||||
|
if isString init
|
||||||
|
then init
|
||||||
|
else if isPath init
|
||||||
|
then readFile init
|
||||||
|
else if isAttrs init
|
||||||
|
then buildInit init
|
||||||
|
else null;
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
callModule,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) isPath;
|
||||||
|
inherit (pkgs.lib) fileContents fix literalExample mergeAttrsList mkOption optionalAttrs types;
|
||||||
|
lua = callModule ../../lua.nix {};
|
||||||
|
|
||||||
|
modules = {
|
||||||
|
keymap = callModule ./keymap.nix {};
|
||||||
|
event = callModule ./event.nix {};
|
||||||
|
};
|
||||||
|
|
||||||
|
coercePkgToPlugin = pkg: {
|
||||||
|
plugin = pkg;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkROBoolOption = default: description:
|
||||||
|
mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
inherit default;
|
||||||
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
Wether this plugin has ${description}.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
textOrContent = content:
|
||||||
|
if isPath content
|
||||||
|
then fileContents content
|
||||||
|
else content;
|
||||||
|
|
||||||
|
getPluginName = plugin: plugin.pname or plugin.name;
|
||||||
|
mkLuaDefinition = plugin: let
|
||||||
|
mkTypeFn = type: let
|
||||||
|
content = textOrContent plugin.${type};
|
||||||
|
in
|
||||||
|
optionalAttrs (! isNull plugin.${type}) {
|
||||||
|
${type} = with lua; lambda [] (raw content);
|
||||||
|
};
|
||||||
|
name = getPluginName plugin.plugin;
|
||||||
|
in
|
||||||
|
mergeAttrsList ([
|
||||||
|
{
|
||||||
|
inherit name;
|
||||||
|
dependencies = map getPluginName plugin.dependencies;
|
||||||
|
}
|
||||||
|
(mkTypeFn "init")
|
||||||
|
(mkTypeFn "config")
|
||||||
|
]
|
||||||
|
++ (with plugin; [
|
||||||
|
(optionalAttrs lazy {lazy = true;})
|
||||||
|
(optionalAttrs hasCommands {inherit cmd;})
|
||||||
|
(optionalAttrs hasFileTypes {inherit ft;})
|
||||||
|
(optionalAttrs hasEvents {inherit events;})
|
||||||
|
(optionalAttrs hasKeymaps {inherit keymaps;})
|
||||||
|
]));
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
module = types.submodule ({config, ...}: {
|
||||||
|
options = {
|
||||||
|
init = mkOption {
|
||||||
|
type = with types; nullOr (either path str);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The init configuration of your plugin.
|
||||||
|
This will be called before loading your plugin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = with types; nullOr (either path str);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The configuration of your plugin.
|
||||||
|
This will be called after loading your plugin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
optional = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = config.lazy || config.init != null;
|
||||||
|
example = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin = mkOption {
|
||||||
|
# TODO Type should allow old `basicPluginType` ({name:<str>, src:<source>})?
|
||||||
|
type = with types; nullOr package;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Ensure thoses plugins are loaded before the current one
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dependencies = mkOption {
|
||||||
|
type = with types; listOf package;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Ensure thoses plugins are loaded before the current one
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraLuaPackages = mkOption {
|
||||||
|
type = with types; functionTo (listOf package);
|
||||||
|
example = literalExample "p: [p.nvim-nio]";
|
||||||
|
defaultText = literalExample "_: []";
|
||||||
|
default = _: [];
|
||||||
|
description = ''
|
||||||
|
Ensure those packages are available
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
cmd = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
List of commands on which the plugin should be loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
ft = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
List of filetypes on which the plugin should be loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
keymaps = modules.keymap.option;
|
||||||
|
events = modules.event.option;
|
||||||
|
|
||||||
|
hasCommands = mkROBoolOption (config.cmd != []) "declared commands";
|
||||||
|
hasFileTypes = mkROBoolOption (config.ft != []) "file types";
|
||||||
|
hasKeymaps = mkROBoolOption (config.keymaps != []) "keymaps";
|
||||||
|
hasEvents = mkROBoolOption (config.events != []) "events";
|
||||||
|
|
||||||
|
lazy = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = with config; hasCommands || hasFileTypes || hasEvents || hasKeymaps;
|
||||||
|
example = true;
|
||||||
|
description = ''
|
||||||
|
Whether to enable loading lazily the plugin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
pluginName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
default = getPluginName config.plugin;
|
||||||
|
description = ''
|
||||||
|
Name of the plugin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
luaDefinition = mkOption {
|
||||||
|
type = with types; attrsOf anything;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
default = mkLuaDefinition config;
|
||||||
|
description = ''
|
||||||
|
Lua definition of the plugin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# priority = mkOption {
|
||||||
|
# type = types.int;
|
||||||
|
# default = [];
|
||||||
|
# description = ''
|
||||||
|
# Priority of the module. Influence the order of loading plugins.
|
||||||
|
# Highest values get loaded before.
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
option = mkOption {
|
||||||
|
description = ''
|
||||||
|
List of plugins to enable in this installation
|
||||||
|
'';
|
||||||
|
type = with types; listOf (coercedTo package coercePkgToPlugin self.module);
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
extract = plugin: {
|
||||||
|
inherit (plugin) plugin optional;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
{pkgs, ...}: let
|
||||||
|
inherit (builtins) elemAt isList isString mapAttrs match ;
|
||||||
|
inherit (pkgs.lib) fix mkOption splitString types ;
|
||||||
|
|
||||||
|
wrapArray = value:
|
||||||
|
if isList value
|
||||||
|
then value
|
||||||
|
else [value];
|
||||||
|
|
||||||
|
hasMatch = pattern: str: isList (match pattern str);
|
||||||
|
coerceToEvent = event: let
|
||||||
|
part = elemAt (splitString " " event);
|
||||||
|
value =
|
||||||
|
if ! isString event
|
||||||
|
then event
|
||||||
|
else if ! hasMatch ".* .*" event
|
||||||
|
then {name = event;}
|
||||||
|
else {
|
||||||
|
name = part 0;
|
||||||
|
pattern = part 1;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mapAttrs (_: wrapArray) value;
|
||||||
|
coerceToListOfEvent = events:
|
||||||
|
if isList events
|
||||||
|
then map coerceToEvent events
|
||||||
|
else [(coerceToEvent events)];
|
||||||
|
|
||||||
|
typeOrListOf = t: with types; coercedTo t (e: [e]) (listOf t);
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
module = types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = typeOrListOf types.str;
|
||||||
|
default = "n";
|
||||||
|
example = "v";
|
||||||
|
description = ''
|
||||||
|
The name of the event
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
pattern = mkOption {
|
||||||
|
type = typeOrListOf types.str;
|
||||||
|
example = "<C-n>";
|
||||||
|
description = ''
|
||||||
|
The pattern of the event
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
option = mkOption {
|
||||||
|
type = with types; coercedTo (either str (listOf str)) coerceToListOfEvent (listOf self.module);
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
List of events on which the plugin should be loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
{pkgs, ...}: let
|
||||||
|
inherit (pkgs.lib) fix mkOption types;
|
||||||
|
|
||||||
|
coerceStrToKeymap = mapping: {
|
||||||
|
inherit mapping;
|
||||||
|
mode = ["n"];
|
||||||
|
};
|
||||||
|
|
||||||
|
typeOrListOf = t: with types; coercedTo t (e: [e]) (listOf t);
|
||||||
|
|
||||||
|
modeType = types.enum ["n" "v" "s" "i" "o" "x"];
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
module = types.submodule {
|
||||||
|
options = {
|
||||||
|
mode = mkOption {
|
||||||
|
type = typeOrListOf modeType;
|
||||||
|
default = "n";
|
||||||
|
example = "v";
|
||||||
|
description = ''
|
||||||
|
The mode of the keymap.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mapping = mkOption {
|
||||||
|
type = typeOrListOf types.str;
|
||||||
|
example = "<C-n>";
|
||||||
|
description = ''
|
||||||
|
The actual keymap
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
option = mkOption {
|
||||||
|
type = with types; listOf (coercedTo str coerceStrToKeymap self.module);
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
List of keystrokes on which the plugin should be loaded
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
{pkgs, ...}: let
|
||||||
|
inherit (pkgs) vimUtils;
|
||||||
|
inherit (pkgs.lib) fix mkOption types;
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
module = types.submodule ({config, ...}: {
|
||||||
|
options = {
|
||||||
|
src = mkOption {
|
||||||
|
type = with types; either path attrs;
|
||||||
|
description = "Files to include in your runtime";
|
||||||
|
example = ./my-runtime;
|
||||||
|
};
|
||||||
|
|
||||||
|
version = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
description = "Optional version of your runtime";
|
||||||
|
default = null;
|
||||||
|
example = "2025.10.16";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = mkOption {
|
||||||
|
type = with types; attrsOf anything;
|
||||||
|
description = "Extra options to pass to `vimUtils.buildVimPlugin`";
|
||||||
|
default = {};
|
||||||
|
example.nvimRequireCheck = ["my-module.my-submodule"];
|
||||||
|
};
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
description = "The resulted runtime package";
|
||||||
|
readOnly = true;
|
||||||
|
default = self.mkPlugin config;
|
||||||
|
example.nvimRequireCheck = ["my-module.my-submodule"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
option = mkOption {
|
||||||
|
type = types.nullOr self.module;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Your runtime submodule. You can configure what files should be
|
||||||
|
indluded in your runtime
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mkPlugin = opts: let
|
||||||
|
inherit (opts) src version extraOptions;
|
||||||
|
in
|
||||||
|
vimUtils.buildVimPlugin (
|
||||||
|
extraOptions
|
||||||
|
// {inherit src;}
|
||||||
|
// (
|
||||||
|
if isNull version
|
||||||
|
then {name = "runtime";}
|
||||||
|
else {
|
||||||
|
pname = "runtime";
|
||||||
|
inherit version;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
sloth,
|
||||||
|
callModule,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (pkgs) vimUtils;
|
||||||
|
inherit (pkgs.lib) fix listToAttrs nameValuePair;
|
||||||
|
fs = pkgs.lib.fileset;
|
||||||
|
lua = callModule ../lua.nix {};
|
||||||
|
|
||||||
|
defsFile = luaDefs: with lua; writeLua "sloth-plugins-definitions.lua" (return luaDefs);
|
||||||
|
versionFile = with lua; writeLua "sloth-version.lua" (return (lambda [] (return sloth.version)));
|
||||||
|
in
|
||||||
|
fix (self: {
|
||||||
|
mkSlothPlugin = luaDefs:
|
||||||
|
vimUtils.buildVimPlugin {
|
||||||
|
inherit (sloth) version;
|
||||||
|
pname = "sloth-flake";
|
||||||
|
src = fs.toSource {
|
||||||
|
root = ../..;
|
||||||
|
fileset = ../../lua/sloth-flake;
|
||||||
|
};
|
||||||
|
nvimRequireCheck = "sloth-flake";
|
||||||
|
buildPhase = ''
|
||||||
|
dir=lua/sloth-flake
|
||||||
|
ln -s ${defsFile luaDefs} $dir/dependencies.lua
|
||||||
|
ln -s ${versionFile} $dir/version.lua
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mkPluginLuaDefinitions = plugins: let
|
||||||
|
extractDef = plugin: nameValuePair plugin.pluginName plugin.luaDefinition;
|
||||||
|
in
|
||||||
|
listToAttrs (map extractDef plugins);
|
||||||
|
})
|
||||||
138
lib/types.nix
138
lib/types.nix
|
|
@ -1,138 +0,0 @@
|
||||||
{yants, ...}: let
|
|
||||||
stringList = with yants; list string;
|
|
||||||
stringOrStringList = with yants; either string stringList;
|
|
||||||
stringOrStringListOr = type:
|
|
||||||
with yants;
|
|
||||||
option (eitherN [string type (list (either string type))]);
|
|
||||||
in rec {
|
|
||||||
# The runtime object
|
|
||||||
runtimeType = with yants;
|
|
||||||
openStruct "runtime" {
|
|
||||||
# The version of the runtime
|
|
||||||
version = option string;
|
|
||||||
|
|
||||||
# The content of the runtime directory
|
|
||||||
src = any;
|
|
||||||
};
|
|
||||||
|
|
||||||
neovimInitType = with yants;
|
|
||||||
struct "neovimInit" {
|
|
||||||
# Lua code to call before plugins loaded
|
|
||||||
init = option (either string path);
|
|
||||||
# Lua code called after init but before import
|
|
||||||
postInit = option (either string path);
|
|
||||||
# Lua code called after all plugins are loaded
|
|
||||||
config = option (either string path);
|
|
||||||
};
|
|
||||||
|
|
||||||
# As simple remote plugin definition
|
|
||||||
basicPluginType = with yants;
|
|
||||||
struct "basicPlugin" {
|
|
||||||
# The name of your plugin.
|
|
||||||
name = string;
|
|
||||||
# The sources of your plugin
|
|
||||||
# TODO What is the type of a source ?
|
|
||||||
src = any;
|
|
||||||
};
|
|
||||||
|
|
||||||
eventType = with yants;
|
|
||||||
struct "event" {
|
|
||||||
# The name of the event
|
|
||||||
name = stringOrStringList;
|
|
||||||
# The pattern of the event
|
|
||||||
pattern = stringOrStringList;
|
|
||||||
};
|
|
||||||
|
|
||||||
keymapType = with yants;
|
|
||||||
struct "keymap" {
|
|
||||||
# The mode of the keymap
|
|
||||||
mode = option stringOrStringList;
|
|
||||||
# The mapping of the keymap
|
|
||||||
mapping = stringOrStringList;
|
|
||||||
};
|
|
||||||
|
|
||||||
# The plugin type of dependencies
|
|
||||||
pluginType = with yants;
|
|
||||||
struct "plugin" {
|
|
||||||
# Whether this plugin should be enabled. This option allows specific
|
|
||||||
# plugins to be disabled.
|
|
||||||
# enable = option bool;
|
|
||||||
|
|
||||||
# The init configuration of your plugin.
|
|
||||||
# This should be called before loading your plugin.
|
|
||||||
init = option (either path string);
|
|
||||||
|
|
||||||
# The configuration of your plugin.
|
|
||||||
# This should be called after loading your plugin.
|
|
||||||
config = option (either path string);
|
|
||||||
|
|
||||||
# Ensure thoses plugins are loaded before the current one
|
|
||||||
plugin = either drv basicPluginType;
|
|
||||||
|
|
||||||
# Ensure thoses plugins are loaded before the current one
|
|
||||||
dependencies = option (list drv);
|
|
||||||
|
|
||||||
# Ensure those packages are available
|
|
||||||
extraLuaPackages = option function;
|
|
||||||
|
|
||||||
# Should this plugin be load lazily ?
|
|
||||||
lazy = option bool;
|
|
||||||
|
|
||||||
# List of events on which the plugin should be loaded
|
|
||||||
events = option (stringOrStringListOr eventType);
|
|
||||||
|
|
||||||
# List of commands on which the plugin should be loaded
|
|
||||||
cmd = option stringList;
|
|
||||||
|
|
||||||
# List of filetypes on which the plugin should be loaded
|
|
||||||
ft = option stringList;
|
|
||||||
|
|
||||||
# List of keystrokes on which the plugin should be loaded
|
|
||||||
keymaps = option (stringOrStringListOr keymapType);
|
|
||||||
|
|
||||||
# Priority of the module. Influence the order of loading plugins.
|
|
||||||
# Highest values get loaded before.
|
|
||||||
# priority = option int;
|
|
||||||
};
|
|
||||||
|
|
||||||
# A dependency.
|
|
||||||
# TODO Complete doc
|
|
||||||
dependency = with yants; eitherN [path drv pluginType];
|
|
||||||
|
|
||||||
mkNeovimPkgOptions = with yants;
|
|
||||||
struct "mkNeovimPkgOptions" {
|
|
||||||
# The configuration of mkNeovimPkg
|
|
||||||
pkgs = attrs any;
|
|
||||||
|
|
||||||
# The neovim package to wrap with your conifguration.
|
|
||||||
# Default is pkgs.neovim-unwrapped
|
|
||||||
package = option drv;
|
|
||||||
|
|
||||||
# init.lua configuration
|
|
||||||
init = option (eitherN [string path neovimInitType]);
|
|
||||||
|
|
||||||
# An array of dependencies.
|
|
||||||
dependencies = option (list dependency);
|
|
||||||
|
|
||||||
# Extra argument to pass to dependencies files
|
|
||||||
dependenciesExtraArgs = option (attrs any);
|
|
||||||
|
|
||||||
# Ensure those packages are available
|
|
||||||
extraLuaPackages = option function;
|
|
||||||
|
|
||||||
# Runtime configuration
|
|
||||||
runtime = option runtimeType;
|
|
||||||
|
|
||||||
# Create a vi alias
|
|
||||||
viAlias = option bool;
|
|
||||||
|
|
||||||
# Create a vim alias
|
|
||||||
vimAlias = option bool;
|
|
||||||
|
|
||||||
# Create a vimdiff alias to run neovim in diff mode
|
|
||||||
vimdiffAlias = option bool;
|
|
||||||
|
|
||||||
# Create a nvimdiff alias to run neovim in diff mode
|
|
||||||
nvimdiffAlias = option bool;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
perSystem = {pkgs, ...}: let
|
||||||
|
lua = import ../lib/lua.nix {inherit pkgs;};
|
||||||
|
|
||||||
|
diffFiles = actual: expected:
|
||||||
|
pkgs.runCommandWith {
|
||||||
|
name = "diffFiles";
|
||||||
|
derivationArgs.nativeBuildInputs = [pkgs.diffutils];
|
||||||
|
}
|
||||||
|
''
|
||||||
|
diff -u ${expected} ${actual}
|
||||||
|
echo "Comparaison successful."
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
checks.luaRender =
|
||||||
|
diffFiles ./luaRender.lua
|
||||||
|
<| lua.writeLua "debug.lua" {
|
||||||
|
a.b.c = 42;
|
||||||
|
list = [42 4.2 true false null];
|
||||||
|
fn = lua.lambda [] <| lua.raw "print('hello world')";
|
||||||
|
math.succ = lua.function "" ["n"] <| lua.return <| lua.raw "n + 1";
|
||||||
|
non-var-name = 42;
|
||||||
|
multilineFunc =
|
||||||
|
lua.function "" []
|
||||||
|
<| lua.raw ''
|
||||||
|
print("hello world")
|
||||||
|
print("goodbye world")
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
a = {
|
||||||
|
b = {
|
||||||
|
c = 42
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fn = function ()
|
||||||
|
print('hello world')
|
||||||
|
end,
|
||||||
|
list = {
|
||||||
|
42,
|
||||||
|
4.2,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
nil
|
||||||
|
},
|
||||||
|
math = {
|
||||||
|
succ = function (n)
|
||||||
|
return n + 1
|
||||||
|
end
|
||||||
|
},
|
||||||
|
multilineFunc = function ()
|
||||||
|
print("hello world")
|
||||||
|
print("goodbye world")
|
||||||
|
|
||||||
|
end,
|
||||||
|
["non-var-name"] = 42
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue