Files
komorebi/nix/tests/default.nix
T
LGUG2Z 21017b573f feat(wm): initial window placement rules
A window that opens goes after the focused container. A workspace can now say
another place for its windows: the primary or the secondary tile, before or
after the focused container, the end of the list, or a place by number, counting
from 1. The place is for every window, or for the windows that match a rule on
their program, app id, title or path; the rules are the conditions the ignore
and manage rules are made of, and the first that matches in key order decides. A
place that does not exist, such as the secondary tile of a workspace with one
container, is the default place.

A place is read from a name, a number or text that is a number. The
documentation of the setting shows a number and a map's keys can only be text,
and komorebi for Windows (83c4e11d) reads only text, so the form its own page
shows is refused there.

A place that was reserved with preselect-direction is used before the rules are
asked, and a locked container keeps its index. A workspace whose
window_container_behaviour is Append puts a window in the focused container, and
the rules are not used.

A workspace takes the rules from the key initial_window_placement_rules of its
entry in komorebi.json. The key is in schema.json and so in the typed config
option of the module, and the page docs/initial-window-placement-rules.md says
how to write it. vm-placement opens windows in a headless KWin and checks where
they go, by program, app id and title.

The schema that schemars derives for a place is an object with a Placement or an
Index key, which is not what is read or written, so a check against it refuses a
file that the daemon reads. The schema of PlacementTarget is written by hand
instead: a name, a number, or text that is a number. A file with a place of each
form is checked against schema.json, and the module's config option takes them.
2026-10-28 07:20:57 -07:00

138 lines
4.4 KiB
Nix

# `nix-options-validation`: the options `just nixgen` makes from `schema.json`, evaluated against
# the example configuration, whose JSON is checked against the schema, and against the example
# file of the docs, and against the places a workspace can give the windows that open, in every
# form komorebi reads. Run with `nix build -f nix/tests/default.nix`, or as a check of the flake.
{
pkgs ? import <nixpkgs> { },
}:
let
lib = pkgs.lib;
# the Nix module system uses null for an optional field that is not set, and the schema wants
# the field to be absent
filterNulls =
value:
if value == null then
null
else if builtins.isList value then
map filterNulls (builtins.filter (x: x != null) value)
else if builtins.isAttrs value then
lib.filterAttrs (_n: v: v != null) (builtins.mapAttrs (_n: v: filterNulls v) value)
else
value;
evaluated =
(lib.evalModules {
modules = [
(import ../komorebi-options.nix)
(import ./komorebi-example.nix)
];
}).config.komorebi;
evaluatedJson = pkgs.writeText "komorebi-example-from-nix.json" (
builtins.toJSON (filterNulls evaluated)
);
# where a workspace puts the windows that open, in each form komorebi reads: a name, a number,
# text that is a number, and a map of places to rules (whose keys are text)
placements =
(lib.evalModules {
modules = [
(import ../komorebi-options.nix)
{
komorebi.monitors = [
{
workspaces = [
{
name = "name";
initial_window_placement_rules = "Primary";
}
{
name = "number";
initial_window_placement_rules = 3;
}
{
name = "text";
initial_window_placement_rules = "3";
}
{
name = "map";
initial_window_placement_rules = {
Primary = {
kind = "Exe";
id = "firefox";
matching_strategy = "Equals";
};
"2" = [
{
kind = "Title";
id = "notes";
matching_strategy = "StartsWith";
}
];
};
}
];
}
];
}
];
}).config.komorebi;
placementsJson = pkgs.writeText "komorebi-placements.json" (
builtins.toJSON (filterNulls placements)
);
# a place that is neither a name nor a number
nowhereJson = pkgs.writeText "komorebi-nowhere.json" (
builtins.toJSON {
monitors = [
{
workspaces = [
{
name = "x";
initial_window_placement_rules = "Nowhere";
}
];
}
];
}
);
# the file has comment lines (komorebi reads them), which the schema checker does not
exampleJson = pkgs.runCommand "komorebi.example.json" { } ''
grep -v '^\s*//' ${../../docs/komorebi.example.json} > $out
'';
schema = ../../schema.json;
in
pkgs.runCommand "nix-options-validation"
{
nativeBuildInputs = [
pkgs.check-jsonschema
pkgs.jq
];
}
''
echo "Validating the example, written in Nix, against the schema..."
check-jsonschema --schemafile ${schema} ${evaluatedJson}
echo "Validating the example file of the docs against the schema..."
check-jsonschema --schemafile ${schema} ${exampleJson}
echo "Checking that the two examples say the same..."
jq -e --slurpfile example ${exampleJson} 'contains($example[0])' ${evaluatedJson} > /dev/null
echo "Validating the places a workspace can give a new window, in every form, against the schema..."
check-jsonschema --schemafile ${schema} ${placementsJson}
jq -e '[.monitors[0].workspaces[].initial_window_placement_rules | type] == ["string", "number", "string", "object"]' ${placementsJson} > /dev/null
echo "Checking that the schema refuses a place that is neither a name nor a number..."
if check-jsonschema --schemafile ${schema} ${nowhereJson} > /dev/null 2>&1; then
echo "the schema accepts a place that komorebi cannot read" >&2
exit 1
fi
echo "All validations passed!"
touch $out
''