feat: lua render now handle indentation
parent
1d6bc88719
commit
aff1dbc079
|
|
@ -1,2 +1,3 @@
|
||||||
.direnv
|
.direnv
|
||||||
.envrc
|
.envrc
|
||||||
|
result
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
./dev
|
./dev
|
||||||
./flakeModule.nix
|
./flakeModule.nix
|
||||||
./lib
|
./lib
|
||||||
|
./tests
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
modules = mkOption {
|
modules = mkOption {
|
||||||
description = "modules used to create your neovim package";
|
description = "modules used to create your neovim package";
|
||||||
type = with types; listOf attrs;
|
type = with types; listOf deferredModule;
|
||||||
default = [config.module];
|
default = [config.module];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
inherit (lib.attrsets) attrNames optionalAttrs;
|
inherit (lib.attrsets) attrNames optionalAttrs;
|
||||||
inherit (lib.lists) concatMap;
|
inherit (lib.lists) concatMap;
|
||||||
inherit (lib.strings) fileContents splitString;
|
inherit (lib.strings) fileContents splitString;
|
||||||
lua = callPackage ./lua.nix {};
|
lua = callPackage ./legacyLua.nix {};
|
||||||
callPackage = lib.callPackageWith (pkgs // dependenciesExtraArgs);
|
callPackage = lib.callPackageWith (pkgs // dependenciesExtraArgs);
|
||||||
|
|
||||||
hasMatch = pattern: str: isList (match pattern str);
|
hasMatch = pattern: str: isList (match pattern str);
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
versionLua = version: with lua; nix2lua (return (lambda (return version)));
|
versionLua = version: with lua; nix2lua (return (lambda [] (return version)));
|
||||||
|
|
||||||
textOrContent = content:
|
textOrContent = content:
|
||||||
if isPath content
|
if isPath content
|
||||||
|
|
@ -156,7 +156,7 @@
|
||||||
content = textOrContent plugin.${type};
|
content = textOrContent plugin.${type};
|
||||||
in
|
in
|
||||||
optionalAttrs (! isNull plugin.${type}) {
|
optionalAttrs (! isNull plugin.${type}) {
|
||||||
${type} = with lua; lambda (raw content);
|
${type} = with lua; lambda [] (raw content);
|
||||||
};
|
};
|
||||||
pluginName = plugin:
|
pluginName = plugin:
|
||||||
if plugin ? pname
|
if plugin ? pname
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
{...}: let
|
||||||
|
inherit (builtins) match isNull typeOf concatStringsSep attrNames concatMap;
|
||||||
|
fix = f: let x = f x; in x;
|
||||||
|
|
||||||
|
commaJoin = concatStringsSep ", ";
|
||||||
|
wrapNotNull' = val: value:
|
||||||
|
if isNull val
|
||||||
|
then []
|
||||||
|
else [value];
|
||||||
|
wrapNotNull = val: wrapNotNull' val val;
|
||||||
|
|
||||||
|
toLua = {
|
||||||
|
ast = {
|
||||||
|
raw = {data, ...}: data;
|
||||||
|
return = {data, ...}: "return ${nix2lua data}";
|
||||||
|
fn = {
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
...
|
||||||
|
}: "function ${name}(${commaJoin args})\n${nix2lua data}\nend";
|
||||||
|
};
|
||||||
|
|
||||||
|
type = fix (type: {
|
||||||
|
null = _: "nil";
|
||||||
|
string = data: ''"${data}"'';
|
||||||
|
path = type.string;
|
||||||
|
lambda = data: builtins.trace "Skipping function" null;
|
||||||
|
int = data: toString data;
|
||||||
|
|
||||||
|
bool = data:
|
||||||
|
if data
|
||||||
|
then "true"
|
||||||
|
else "false";
|
||||||
|
|
||||||
|
ast = data: let
|
||||||
|
astType = data.__ast;
|
||||||
|
in
|
||||||
|
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;
|
||||||
|
luaValue = nix2lua value;
|
||||||
|
in
|
||||||
|
wrapNotNull' luaValue ''
|
||||||
|
${luaKey} = ${luaValue},
|
||||||
|
'';
|
||||||
|
attrsContent = concatMap mkKeyValue (attrNames data);
|
||||||
|
in ''
|
||||||
|
{
|
||||||
|
${concatStringsSep "" attrsContent}}
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
newAst = type: set: set // {__ast = type;};
|
||||||
|
|
||||||
|
nix2lua = data: let
|
||||||
|
type = typeOf data;
|
||||||
|
in
|
||||||
|
if data ? __ast
|
||||||
|
then toLua.type.ast data
|
||||||
|
else if toLua.type ? ${type}
|
||||||
|
then toLua.type.${type} data
|
||||||
|
else abort ''Type "${type}"'';
|
||||||
|
in
|
||||||
|
fix (lua: {
|
||||||
|
inherit nix2lua;
|
||||||
|
|
||||||
|
raw = data: newAst "raw" {inherit data;};
|
||||||
|
|
||||||
|
function = name: args: data:
|
||||||
|
newAst "fn" {
|
||||||
|
inherit name data args;
|
||||||
|
};
|
||||||
|
|
||||||
|
lambda = lua.function "";
|
||||||
|
|
||||||
|
return = data: newAst "return" {inherit data;};
|
||||||
|
})
|
||||||
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;};
|
||||||
}
|
})
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
}: let
|
}: let
|
||||||
inherit (builtins) isPath;
|
inherit (builtins) isPath;
|
||||||
inherit (pkgs.lib) fileContents fix literalExample mergeAttrsList mkOption optionalAttrs types;
|
inherit (pkgs.lib) fileContents fix literalExample mergeAttrsList mkOption optionalAttrs types;
|
||||||
lua = import ../../lua.nix {};
|
lua = callModule ../../lua.nix {};
|
||||||
|
|
||||||
modules = {
|
modules = {
|
||||||
keymap = callModule ./keymap.nix {};
|
keymap = callModule ./keymap.nix {};
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
content = textOrContent plugin.${type};
|
content = textOrContent plugin.${type};
|
||||||
in
|
in
|
||||||
optionalAttrs (! isNull plugin.${type}) {
|
optionalAttrs (! isNull plugin.${type}) {
|
||||||
${type} = with lua; lambda (raw content);
|
${type} = with lua; lambda [] (raw content);
|
||||||
};
|
};
|
||||||
name = getPluginName plugin.plugin;
|
name = getPluginName plugin.plugin;
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
sloth,
|
sloth,
|
||||||
|
callModule,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
inherit (pkgs) vimUtils;
|
inherit (pkgs) vimUtils;
|
||||||
inherit (pkgs.lib) fix listToAttrs nameValuePair;
|
inherit (pkgs.lib) fix listToAttrs nameValuePair;
|
||||||
fs = pkgs.lib.fileset;
|
fs = pkgs.lib.fileset;
|
||||||
lua = import ../lua.nix {};
|
lua = callModule ../lua.nix {};
|
||||||
|
|
||||||
versionLua = version: with lua; nix2lua (return (lambda (return version)));
|
versionLua = version: with lua; renderLua {} (return (lambda [] (return version)));
|
||||||
luaDefsToLua = luaDefs: with lua; nix2lua (return luaDefs);
|
luaDefsToLua = luaDefs: with lua; renderLua {} (return luaDefs);
|
||||||
in
|
in
|
||||||
fix (self: {
|
fix (self: {
|
||||||
mkSlothPlugin = luaDefs:
|
mkSlothPlugin = luaDefs:
|
||||||
|
|
|
||||||
|
|
@ -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