nixpkgs/pkgs/pkgs-lib/formats.nix
Ben Wolsieffer 98336c223b pkgs-lib: allow paths in TOML, YAML and JSON
Paths get automatically added to the store. The INI generator currently chokes
on paths, so it is not supported for now.
2021-06-28 11:59:03 -04:00

133 lines
3.2 KiB
Nix

{ lib, pkgs }:
rec {
/*
Every following entry represents a format for program configuration files
used for `settings`-style options (see https://github.com/NixOS/rfcs/pull/42).
Each entry should look as follows:
<format> = <parameters>: {
# ^^ Parameters for controlling the format
# The module system type most suitable for representing such a format
# The description needs to be overwritten for recursive types
type = ...;
# generate :: Name -> Value -> Path
# A function for generating a file with a value of such a type
generate = ...;
});
*/
json = {}: {
type = with lib.types; let
valueType = nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
]) // {
description = "JSON value";
};
in valueType;
generate = name: value: pkgs.runCommandNoCC name {
nativeBuildInputs = [ pkgs.jq ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
jq . "$valuePath"> $out
'';
};
# YAML has been a strict superset of JSON since 1.2
yaml = {}:
let jsonSet = json {};
in jsonSet // {
type = jsonSet.type // {
description = "YAML value";
};
};
ini = {
# Represents lists as duplicate keys
listsAsDuplicateKeys ? false,
# Alternative to listsAsDuplicateKeys, converts list to non-list
# listToValue :: [IniAtom] -> IniAtom
listToValue ? null,
...
}@args:
assert !listsAsDuplicateKeys || listToValue == null;
{
type = with lib.types; let
singleIniAtom = nullOr (oneOf [
bool
int
float
str
]) // {
description = "INI atom (null, bool, int, float or string)";
};
iniAtom =
if listsAsDuplicateKeys then
coercedTo singleIniAtom lib.singleton (listOf singleIniAtom) // {
description = singleIniAtom.description + " or a list of them for duplicate keys";
}
else if listToValue != null then
coercedTo singleIniAtom lib.singleton (nonEmptyListOf singleIniAtom) // {
description = singleIniAtom.description + " or a non-empty list of them";
}
else
singleIniAtom;
in attrsOf (attrsOf iniAtom);
generate = name: value:
let
transformedValue =
if listToValue != null
then
lib.mapAttrs (section: lib.mapAttrs (key: val:
if lib.isList val then listToValue val else val
)) value
else value;
in pkgs.writeText name (lib.generators.toINI (removeAttrs args ["listToValue"]) transformedValue);
};
toml = {}: json {} // {
type = with lib.types; let
valueType = oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
] // {
description = "TOML value";
};
in valueType;
generate = name: value: pkgs.runCommandNoCC name {
nativeBuildInputs = [ pkgs.remarshal ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
json2toml "$valuePath" "$out"
'';
};
}