sloth-flake.nvim/lib/lua.nix

133 lines
3.2 KiB
Nix

{pkgs, ...}: let
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 ", ";
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 = {
render = args: data: let
astType = data.__ast;
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,
name,
args,
...
}: "function ${name}(${commaJoin args})${introSpace}${renderLua innerArgs data}${outroSpace}end";
};
generatedBindings = assert assertMsg (badBindingNames == []) "Bad Lua var names: ${toPretty {} badBindingNames}";
concatStrings (mapAttrsToList (key: value: "${indent}${key} = ${renderLua innerArgs value}\n") v);
concatItems = concatStringsSep ",${introSpace}";
varNameRe = "[[:alpha:]_][[:alnum:]_]*";
matchBindingName = match "${varNameRe}(\\.${varNameRe})*";
badBindingNames = filter (name: matchBindingName name == null) (attrNames v);
luaKey = key:
if match varNameRe key == null
then "[${toJSON key}]"
else key;
withSpaces = val: optionalString (val != "") "${introSpace}${val}${outroSpace}";
mkKV = key: value: "${luaKey key} = ${renderLua innerArgs value}";
in
if asBindings
then generatedBindings
else if isNull v
then "nil"
else if isInt v || isFloat v || isString v || isBool v
then toJSON v
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;};
in
fix (lua: {
inherit renderLua;
writeLua = name: value: pkgs.writeText name (lua.renderLua {} value);
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;};
})