diff --git a/lib/default.nix b/lib/default.nix index 63a31101eee7f..2a5b11e8b6155 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -99,7 +99,7 @@ let length head tail elem elemAt isList; inherit (self.strings) concatStrings concatMapStrings concatImapStrings stringLength substring isString replaceStrings - intersperse concatStringsSep concatMapStringsSep + intersperse concatStringsSep concatMapStringsSep concatMapAttrsStringSep concatImapStringsSep concatLines makeSearchPath makeSearchPathOutput makeLibraryPath makeIncludePath makeBinPath optionalString hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape diff --git a/lib/strings.nix b/lib/strings.nix index aafbdffaa7bc0..a6a1cafe856c1 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -269,6 +269,37 @@ rec { f: list: concatStringsSep sep (lib.imap1 f list); + /** + Like [`concatMapStringsSep`](#function-library-lib.strings.concatMapStringsSep) + but takes an attribute set instead of a list. + + # Type + + ``` + concatMapAttrsStringSep :: String -> (String -> Any -> String) -> AttrSet -> String + ``` + + # Examples + + :::{.example} + ## `lib.strings.concatMapAttrsStringSep` usage example + + ```nix + concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; } + => "a: foo-0.1.0\nb: foo-0.2.0" + ``` + + ::: + */ + concatMapAttrsStringSep = + # Separator to add between items + sep: + # Function that receives the attribute name and the value + f: + # Attribute set to map from + attrs: + concatMapStringsSep sep (name: f name attrs.${name}) (lib.attrNames attrs); + /** Concatenate a list of strings, adding a newline at the end of each one. Defined as `concatMapStrings (s: s + "\n")`. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index d59f5586b82d7..b170b638b6a83 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -39,6 +39,7 @@ let composeManyExtensions concatLines concatMapAttrs + concatMapAttrsStringSep concatMapStrings concatStrings concatStringsSep @@ -330,6 +331,11 @@ runTests { expected = "a,b,c"; }; + testConcatMapAttrsStringSepExamples = { + expr = concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; }; + expected = "a: foo-0.1.0\nb: foo-0.2.0"; + }; + testConcatLines = { expr = concatLines ["a" "b" "c"]; expected = "a\nb\nc\n"; diff --git a/pkgs/applications/virtualization/singularity/generic.nix b/pkgs/applications/virtualization/singularity/generic.nix index 1cac1d4f16c65..9b5edc04fa774 100644 --- a/pkgs/applications/virtualization/singularity/generic.nix +++ b/pkgs/applications/virtualization/singularity/generic.nix @@ -132,10 +132,6 @@ let lib.optional (privileged-un-utils != null) (lib.makeBinPath [ privileged-un-utils ]) ++ args.systemBinPaths or [ "/run/wrappers/bin" ]; - concatMapStringAttrsSep = - sep: f: attrs: - lib.concatMapStringsSep sep (name: f name attrs.${name}) (lib.attrNames attrs); - addShellDoubleQuotes = s: lib.escapeShellArg ''"'' + s + lib.escapeShellArg ''"''; in (buildGoModule { @@ -240,7 +236,7 @@ in patchShebangs --build "$configureScript" makeit e2e scripts mlocal/scripts # Patching the hard-coded defaultPath by prefixing the packages in defaultPathInputs - ${concatMapStringAttrsSep "\n" (fileName: originalDefaultPaths: '' + ${lib.concatMapAttrsStringSep "\n" (fileName: originalDefaultPaths: '' substituteInPlace ${lib.escapeShellArg fileName} \ ${ lib.concatMapStringsSep " \\\n " ( diff --git a/pkgs/test/overriding.nix b/pkgs/test/overriding.nix index e4c1f257c8190..159ed46856d82 100644 --- a/pkgs/test/overriding.nix +++ b/pkgs/test/overriding.nix @@ -58,5 +58,5 @@ stdenvNoCC.mkDerivation { passthru = { inherit tests; }; buildCommand = '' touch $out - '' + lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs (name: t: "([[ ${lib.boolToString t.expr} == ${lib.boolToString t.expected} ]] && echo '${name} success') || (echo '${name} fail' && exit 1)") tests)); + '' + lib.concatMapAttrsStringSep "\n" (name: t: "([[ ${lib.boolToString t.expr} == ${lib.boolToString t.expected} ]] && echo '${name} success') || (echo '${name} fail' && exit 1)") tests; }