Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions nixos/doc/manual/development/settings-options.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,67 @@ have a predefined type and string generator already declared under
and returning a set with [CDN](https://github.com/dzikoysk/cdn)-specific
attributes `type` and `generate` as specified [below](#pkgs-formats-result).

`pkgs.formats.kdl` { }

: A function taking an empty attribute set (for future extensibility)
and returning a set with [KDL](https://kdl.dev/)-specific attributes `type`,
`lib` and `generate` as specified [below](#pkgs-formats-result).

`lib` is a set containing the functions `node` and `typed`, which are helper
functions indended to facilitate generating the required structure for pkgs.formats.kdl

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
functions indended to facilitate generating the required structure for pkgs.formats.kdl
functions intended to facilitate generating the required structure for pkgs.formats.kdl

in an ergonomic way.

Their signatures are as follows:

`node`:

```nix
name: type: arguments: properties: children: { inherit name type arguments properties children; };
```

`typed`:

```nix
type: value: { inherit type value; };
```

This allows writing the KDL node

```kdl
name "arg1" (special-type)"arg2" prop=1 {
child
}
```

as

```nix
(node "name" null [ "arg1" (typed "special-type" "arg2") ] { prop = 1; } [
(node "child" null [ ] { } [ ])
])
```

instead of

```nix
{
name = "name";
arguments = [
"arg1"
{
type = "special-type";
value = "arg2";
}
];
properties = { prop = 1; };
children = [
{
name = "child";
}
];
}
```

`pkgs.formats.elixirConf { elixir ? pkgs.elixir }`

: A function taking an attribute set with values
Expand Down
26 changes: 26 additions & 0 deletions pkgs/by-name/js/json2kdl/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
lib,
rustPlatform,
fetchFromGitHub,
}:

rustPlatform.buildRustPackage rec {
pname = "json2kdl";
version = "0.2.0";

src = fetchFromGitHub {
owner = "AgathaSorceress";
repo = pname;
rev = "v${version}";
hash = "sha256-NVpIHbv7vbppe+g7YK9OY2oL7axmqG8Kmuv4kO8Jyjs=";
};

cargoHash = "sha256-xlG8p25VBLwUWnyr9JNzSrI0KmwdRpAgL5eckbC/3nk=";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems this tag has changed since:

error: hash mismatch in fixed-output derivation '/nix/store/k0shsqibh29w4v9mx015dlibgx05f8bj-json2kdl-0.2.0-vendor-staging.drv':
        likely URL: (unknown)
         specified: sha256-xlG8p25VBLwUWnyr9JNzSrI0KmwdRpAgL5eckbC/3nk=
            got:    sha256-PK/DduEy0BfHt0asEUR41lvUl++w/UTqZ0HFSuO2OVI=


meta = {
description = "Program that converts JSON files to KDL";
homepage = "https://github.com/AgathaSorceress/json2kdl";
platforms = lib.platforms.all;
maintainers = (with lib.maintainers; [ feathecutie ]);
};
}
134 changes: 134 additions & 0 deletions pkgs/pkgs-lib/formats.nix
Original file line number Diff line number Diff line change
Expand Up @@ -637,4 +637,138 @@ rec {
else
throw "pkgs.formats.xml: Unknown format: ${format}";

# The KDL document language (https://kdl.dev/)
kdl = {}: {

type = (with lib.types; let
# https://github.com/kdl-org/kdl/blob/main/SPEC.md#value
untypedKdlValue = (nullOr (oneOf [ str bool number ])) // { description = "KDL value"; };
kdlValue = either untypedKdlValue ((submodule {
options = {
type = lib.mkOption {
type = nullOr str;
default = null;
description = ''
[Type Annotation](https://github.com/kdl-org/kdl/blob/main/SPEC.md#type-annotation) of the value.
Set to `null` to prevent generating a type annotation.
'';
};
value = lib.mkOption {
type = untypedKdlValue;
description = ''
The actual KDL value.
'';
};
};
}) // { description = "submodule: { type = /* type annotation */; value = /* KDL value */; }"; });
node = submoduleWith {
modules = lib.toList {
options = {
name = lib.mkOption {
type = str;
description = ''
Name of [KDL node](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node).
'';
};
type = lib.mkOption {
type = nullOr str;
default = null;
description = ''
[Type Annotation](https://github.com/kdl-org/kdl/blob/main/SPEC.md#type-annotation) of [KDL node](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node).
Set to `null` to prevent generating a type annotation.
'';
};
arguments = lib.mkOption {
type = listOf kdlValue;
default = [ ];
description = ''
[Arguments](https://github.com/kdl-org/kdl/blob/main/SPEC.md#argument) of [KDL node](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node).
'';
};
properties = lib.mkOption {
type = attrsOf kdlValue;
default = { };
description = ''
[Properties](https://github.com/kdl-org/kdl/blob/main/SPEC.md#property) of [KDL node](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node).
'';
};
children = lib.mkOption {
type = listOf (node // {
# Prevent Nix from trying to recurse into suboptions or submodules, as this leads to a stack overflow
getSubOptions = prefix: {};
getSubModules = null;
});
default = [ ];
description = ''
[Children](https://github.com/kdl-org/kdl/blob/main/SPEC.md#children-block) of [KDL node](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node).
'';
};
};
};
description = "KDL node";
};
valueType = listOf node;
in
valueType);

lib = {
/**
Helper function for generating attrsets expect by pkgs.formats.kdl

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: expected


# Example

```nix
let
settingsFormat = pkgs.formats.kdl { };
inherit (settingsFormat.lib) node;
in
settingsFormat.generate "sample.kdl" [
(node "foo" null [ ] { } [
(node "bar" null [ "baz" ] { a = 1; } [ ])
])
]
```

# Arguments

name
: The name of the node, represented by a string

type
: The type annotation of the node, represented by a string, or null to avoid generating a type annotation

arguments
: The arguments of the node, represented as a list of KDL values

properties
: The properties of the node, represented as an attrset of KDL values

children
: The children of the node, represented as a list of nodes

*/
node = name: type: arguments: properties: children: { inherit name type arguments properties children; };

/**
Helper function for generting the format of a typed value as expected by pkgs.formats.kdl

@KiaraGrouwstra KiaraGrouwstra May 2, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: generating


type
: The type of the value, represented by a string

value
: The value itself
*/
typed = type: value: { inherit type value; };
};

generate = name: value: pkgs.callPackage ({ runCommand, json2kdl }: runCommand name {
nativeBuildInputs = [ json2kdl ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
json2kdl "$valuePath" "$out"
'') {};

};

}