From 25f8a3f2763ac89f5124176627b22181d883a053 Mon Sep 17 00:00:00 2001 From: Mykola Orliuk Date: Sun, 23 Apr 2023 02:43:37 +0200 Subject: [PATCH 1/3] lua.lib: use toLua in generateLuarocksConfig --- pkgs/development/lua-modules/lib.nix | 55 ++++++++++++---------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/pkgs/development/lua-modules/lib.nix b/pkgs/development/lua-modules/lib.nix index 5079a4b25405..467e73c5e7e7 100644 --- a/pkgs/development/lua-modules/lib.nix +++ b/pkgs/development/lua-modules/lib.nix @@ -1,5 +1,6 @@ { pkgs, lib, lua }: let + inherit (lib.generators) toLua; requiredLuaModules = drvs: with lib; let modules = filter hasLuaModule drvs; in unique ([lua] ++ modules ++ concatLists (catAttrs "requiredLuaModules" modules)); @@ -89,58 +90,50 @@ rec { , rocksSubdir }: let rocksTrees = lib.imap0 - (i: dep: "{ name = [[dep-${toString i}]], root = '${dep}', rocks_dir = '${dep}/${dep.rocksSubdir}' }") + (i: dep: { name = "dep-${toString i}"; root = "${dep}"; rocks_dir = "${dep}/${dep.rocksSubdir}"; }) requiredLuaRocks; # Explicitly point luarocks to the relevant locations for multiple-output # derivations that are external dependencies, to work around an issue it has # (https://github.com/luarocks/luarocks/issues/766) - depVariables = lib.concatMap ({name, dep}: [ - "${name}_INCDIR='${lib.getDev dep}/include';" - "${name}_LIBDIR='${lib.getLib dep}/lib';" - "${name}_BINDIR='${lib.getBin dep}/bin';" - ]) externalDeps'; + depVariables = zipAttrsWithLast (lib.lists.map ({name, dep}: { + "${name}_INCDIR" = "${lib.getDev dep}/include"; + "${name}_LIBDIR" = "${lib.getLib dep}/lib"; + "${name}_BINDIR" = "${lib.getBin dep}/bin"; + }) externalDeps'); + zipAttrsWithLast = lib.attrsets.zipAttrsWith (name: lib.lists.last); # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ] externalDeps' = lib.filter (dep: !lib.isDerivation dep) externalDeps; externalDepsDirs = map - (x: "'${builtins.toString x}'") + (x: builtins.toString x) (lib.filter (lib.isDerivation) externalDeps); - - extraVariablesStr = lib.concatStringsSep "\n " - (lib.mapAttrsToList (k: v: "${k}='${v}';") extraVariables); in '' local_cache = "" -- To prevent collisions when creating environments, we install the rock -- files into per-package subdirectories - rocks_subdir = '${rocksSubdir}' + rocks_subdir = ${toLua {} rocksSubdir} -- first tree is the default target where new rocks are installed, -- any other trees in the list are treated as additional sources of installed rocks for matching dependencies. - rocks_trees = { - {name = "current", root = '${placeholder "out"}', rocks_dir = "current" }, - ${lib.concatStringsSep "\n, " rocksTrees} - } + rocks_trees = ${toLua {} ( + [{name = "current"; root = "${placeholder "out"}"; rocks_dir = "current"; }] ++ + rocksTrees + )} '' + lib.optionalString lua.pkgs.isLuaJIT '' -- Luajit provides some additional functionality built-in; this exposes -- that to luarock's dependency system - rocks_provided = { - jit='${lua.luaversion}-1'; - ffi='${lua.luaversion}-1'; - luaffi='${lua.luaversion}-1'; - bit='${lua.luaversion}-1'; - } + rocks_provided = ${toLua {} { + jit = "${lua.luaversion}-1"; + ffi = "${lua.luaversion}-1"; + luaffi = "${lua.luaversion}-1"; + bit = "${lua.luaversion}-1"; + }} '' + '' -- For single-output external dependencies - external_deps_dirs = { - ${lib.concatStringsSep "\n, " externalDepsDirs} - } - variables = { - -- Some needed machinery to handle multiple-output external dependencies, - -- as per https://github.com/luarocks/luarocks/issues/766 - ${lib.optionalString (lib.length depVariables > 0) '' - ${lib.concatStringsSep "\n " depVariables}''} - ${extraVariablesStr} - } + external_deps_dirs = ${toLua {} externalDepsDirs} + -- Some needed machinery to handle multiple-output external dependencies, + -- as per https://github.com/luarocks/luarocks/issues/766 + variables = ${toLua {} (depVariables // extraVariables)} ''; } From 7287c0e076c3fd69d55e96cdc5c46e951bed01d4 Mon Sep 17 00:00:00 2001 From: Mykola Orliuk Date: Sat, 29 Apr 2023 18:35:07 +0200 Subject: [PATCH 2/3] lib.generators.toLua: asBindings option Allows to generate code block for setting of global variables --- lib/generators.nix | 24 +++++++++++++++++++++--- lib/tests/misc.nix | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/lib/generators.nix b/lib/generators.nix index 4ecbdac3c125..c46ecca58c68 100644 --- a/lib/generators.nix +++ b/lib/generators.nix @@ -434,6 +434,7 @@ ${expr "" v} Configuration: * multiline - by default is true which results in indented block-like view. * indent - initial indent. + * asBindings - by default generate single value, but with this use attrset to set global vars. Attention: Regardless of multiline parameter there is no trailing newline. @@ -464,18 +465,35 @@ ${expr "" v} /* If this option is true, the output is indented with newlines for attribute sets and lists */ multiline ? true, /* Initial indentation level */ - indent ? "" + indent ? "", + /* Interpret as variable bindings */ + asBindings ? false, }@args: v: with builtins; let innerIndent = "${indent} "; introSpace = if multiline then "\n${innerIndent}" else " "; outroSpace = if multiline then "\n${indent}" else " "; - innerArgs = args // { indent = innerIndent; }; + innerArgs = args // { + indent = if asBindings then indent else innerIndent; + asBindings = false; + }; concatItems = concatStringsSep ",${introSpace}"; isLuaInline = { _type ? null, ... }: _type == "lua-inline"; + + generatedBindings = + assert lib.assertMsg (badVarNames == []) "Bad Lua var names: ${toPretty {} badVarNames}"; + libStr.concatStrings ( + lib.attrsets.mapAttrsToList (key: value: "${indent}${key} = ${toLua innerArgs value}\n") v + ); + + # https://en.wikibooks.org/wiki/Lua_Programming/variable#Variable_names + matchVarName = match "[[:alpha:]_][[:alnum:]_]*(\\.[[:alpha:]_][[:alnum:]_]*)*"; + badVarNames = filter (name: matchVarName name == null) (attrNames v); in - if v == null then + if asBindings then + generatedBindings + else if v == null then "nil" else if isInt v || isFloat v || isString v || isBool v then builtins.toJSON v diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 49336b8b9630..ea3548b9514e 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -4,6 +4,11 @@ with import ../default.nix; let + testingThrow = expr: { + expr = (builtins.tryEval (builtins.seq expr "didn't throw")); + expected = { success = false; value = false; }; + }; + testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr); testSanitizeDerivationName = { name, expected }: let @@ -962,6 +967,41 @@ runTests { expected = ''{ 41, 43 }''; }; + testToLuaEmptyBindings = { + expr = generators.toLua { asBindings = true; } {}; + expected = ""; + }; + + testToLuaBindings = { + expr = generators.toLua { asBindings = true; } { x1 = 41; _y = { a = 43; }; }; + expected = '' + _y = { + ["a"] = 43 + } + x1 = 41 + ''; + }; + + testToLuaPartialTableBindings = { + expr = generators.toLua { asBindings = true; } { "x.y" = 42; }; + expected = '' + x.y = 42 + ''; + }; + + testToLuaIndentedBindings = { + expr = generators.toLua { asBindings = true; indent = " "; } { x = { y = 42; }; }; + expected = " x = {\n [\"y\"] = 42\n }\n"; + }; + + testToLuaBindingsWithSpace = testingThrow ( + generators.toLua { asBindings = true; } { "with space" = 42; } + ); + + testToLuaBindingsWithLeadingDigit = testingThrow ( + generators.toLua { asBindings = true; } { "11eleven" = 42; } + ); + testToLuaBasicExample = { expr = generators.toLua {} { cmd = [ "typescript-language-server" "--stdio" ]; From 82e9b3f35800dd0e838b78727b95138d72203dd3 Mon Sep 17 00:00:00 2001 From: Mykola Orliuk Date: Sat, 29 Apr 2023 18:37:42 +0200 Subject: [PATCH 3/3] lua.lib: lift toLua to top in generateLuarocksConfig With asBindings option of toLua we can generate whole block of global variables assignments. --- pkgs/development/lua-modules/lib.nix | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pkgs/development/lua-modules/lib.nix b/pkgs/development/lua-modules/lib.nix index 467e73c5e7e7..64a40fa79602 100644 --- a/pkgs/development/lua-modules/lib.nix +++ b/pkgs/development/lua-modules/lib.nix @@ -109,31 +109,31 @@ rec { externalDepsDirs = map (x: builtins.toString x) (lib.filter (lib.isDerivation) externalDeps); - in '' - local_cache = "" - -- To prevent collisions when creating environments, we install the rock - -- files into per-package subdirectories - rocks_subdir = ${toLua {} rocksSubdir} - -- first tree is the default target where new rocks are installed, - -- any other trees in the list are treated as additional sources of installed rocks for matching dependencies. - rocks_trees = ${toLua {} ( + in toLua { asBindings = true; } ({ + local_cache = ""; + # To prevent collisions when creating environments, we install the rock + # files into per-package subdirectories + rocks_subdir = rocksSubdir; + # first tree is the default target where new rocks are installed, + # any other trees in the list are treated as additional sources of installed rocks for matching dependencies. + rocks_trees = ( [{name = "current"; root = "${placeholder "out"}"; rocks_dir = "current"; }] ++ rocksTrees - )} - '' + lib.optionalString lua.pkgs.isLuaJIT '' - -- Luajit provides some additional functionality built-in; this exposes - -- that to luarock's dependency system - rocks_provided = ${toLua {} { + ); + } // lib.optionalAttrs lua.pkgs.isLuaJIT { + # Luajit provides some additional functionality built-in; this exposes + # that to luarock's dependency system + rocks_provided = { jit = "${lua.luaversion}-1"; ffi = "${lua.luaversion}-1"; luaffi = "${lua.luaversion}-1"; bit = "${lua.luaversion}-1"; - }} - '' + '' - -- For single-output external dependencies - external_deps_dirs = ${toLua {} externalDepsDirs} - -- Some needed machinery to handle multiple-output external dependencies, - -- as per https://github.com/luarocks/luarocks/issues/766 - variables = ${toLua {} (depVariables // extraVariables)} - ''; + }; + } // { + # For single-output external dependencies + external_deps_dirs = externalDepsDirs; + # Some needed machinery to handle multiple-output external dependencies, + # as per https://github.com/luarocks/luarocks/issues/766 + variables = (depVariables // extraVariables); + }); }