summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthieu Coudron <teto@users.noreply.github.com>2023-05-01 18:53:22 +0200
committerGitHub <noreply@github.com>2023-05-01 18:53:22 +0200
commit8670e496ffd093b60e74e7fa53526aa5920d09eb (patch)
tree80a7e735cc0aaec413752870b4c12055a66a05e9
parent68378870ab44d78e688232c6ecc78febd928cb1f (diff)
parent82e9b3f35800dd0e838b78727b95138d72203dd3 (diff)
Merge pull request #227714 from ony/feature/generateLuarocksConfig-toLua
lua.lib: use toLua in generateLuarocksConfig
-rw-r--r--lib/generators.nix24
-rw-r--r--lib/tests/misc.nix40
-rw-r--r--pkgs/development/lua-modules/lib.nix77
3 files changed, 96 insertions, 45 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index 4ecbdac3c125e..c46ecca58c68f 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 49336b8b96301..ea3548b9514ed 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" ];
diff --git a/pkgs/development/lua-modules/lib.nix b/pkgs/development/lua-modules/lib.nix
index 92d483d7f085d..bdf363fb47999 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));
@@ -88,58 +89,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}'
-    -- 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}
-    }
-  '' + lib.optionalString lua.pkgs.isLuaJIT ''
-    -- Luajit provides some additional functionality built-in; this exposes
-    -- that to luarock's dependency system
+  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.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 = {
-      ${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}
-    }
-  '';
+      jit = "${lua.luaversion}-1";
+      ffi = "${lua.luaversion}-1";
+      luaffi = "${lua.luaversion}-1";
+      bit = "${lua.luaversion}-1";
+    };
+  } // {
+    # 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);
+  });
 }