1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00
home-manager/modules/launchd/types.nix
Austin Horstman 5d13260881 treewide: lnl7 -> nix-darwin
Renamed recently.
2025-05-16 18:47:17 -05:00

150 lines
4.5 KiB
Nix

# launchd option type from nix-darwin
#
# Original code from https://github.com/nix-darwin/nix-darwin/commit/861af0fc94df9454f4e92d6892f75588763164bb
{ lib, ... }:
let
inherit (lib)
imap1
types
mkOption
showOption
mergeDefinitions
;
inherit (builtins)
map
filter
length
deepSeq
throw
toString
concatLists
;
inherit (lib.options) showDefs;
wildcardText = lib.literalMD "`*`";
/*
*
A type of list which does not allow duplicate elements. The base/inner
list type to use (e.g. `types.listOf` or `types.nonEmptyListOf`) is passed
via argument `listType`, which must be the final type and not a function.
NOTE: The extra check for duplicates is quadratic and strict, so use this
type sparingly and only:
* when needed, and
* when the list is expected to be recursively short (e.g. < 10 elements)
and shallow (i.e. strict evaluation of the list won't take too long)
The implementation of this function is similar to that of
`types.nonEmptyListOf`.
*/
types'.uniqueList =
listType:
listType
// {
description = "unique ${types.optionDescriptionPhrase (class: class == "noun") listType}";
substSubModules = m: types'.uniqueList (listType.substSubModules m);
# This has been taken from the implementation of `types.listOf`, but has
# been modified to throw on duplicates. This check cannot be done in the
# `check` fn as this check is deep/strict, and because `check` runs
# prior to merging.
merge =
loc: defs:
let
# Each element of `dupes` is a list. When there are duplicates,
# later lists will be duplicates of earlier lists, so just throw on
# the first set of duplicates found so that we don't have duplicate
# error msgs.
checked = filter (
li:
if length li > 1 then
throw ''
The option `${showOption loc}' contains duplicate entries after merging:
${showDefs li}''
else
false
) dupes;
dupes = map (def: filter (def': def'.value == def.value) merged) merged;
merged = filter (x: x ? value) (
concatLists (
imap1 (
n: def:
imap1 (
m: el:
let
inherit (def) file;
loc' = loc ++ [ "[definition ${toString n}-entry ${toString m}]" ];
in
(mergeDefinitions loc' listType.nestedTypes.elemType [
{
inherit file;
value = el;
}
]).optionalValue
// {
inherit loc' file;
}
) def.value
) defs
)
);
in
deepSeq checked (map (x: x.value) merged);
};
in
{
StartCalendarInterval =
let
CalendarIntervalEntry = types.submodule {
options = {
Minute = mkOption {
type = types.nullOr (types.ints.between 0 59);
default = null;
defaultText = wildcardText;
description = ''
The minute on which this job will be run.
'';
};
Hour = mkOption {
type = types.nullOr (types.ints.between 0 23);
default = null;
defaultText = wildcardText;
description = ''
The hour on which this job will be run.
'';
};
Day = mkOption {
type = types.nullOr (types.ints.between 1 31);
default = null;
defaultText = wildcardText;
description = ''
The day on which this job will be run.
'';
};
Weekday = mkOption {
type = types.nullOr (types.ints.between 0 7);
default = null;
defaultText = wildcardText;
description = ''
The weekday on which this job will be run (0 and 7 are Sunday).
'';
};
Month = mkOption {
type = types.nullOr (types.ints.between 1 12);
default = null;
defaultText = wildcardText;
description = ''
The month on which this job will be run.
'';
};
};
};
in
types.either CalendarIntervalEntry (types'.uniqueList (types.nonEmptyListOf CalendarIntervalEntry));
}