hylonix/modules/home-manager/gecko-browser/gecko-lib/profiles.nix
hylodon 2a5ced3905 Removed pipe operator.
The pipe operator '<|' was added in Nix 2.24 as experimental. In typical
nix community fashion, an eternity has passed, it's still experimental, and
they're still arguing about it. Thus, in order not to burden any users of
this flake, they have been removed.

To get this done quickly a utility function has been added called 'compose'.
It is 'lib.trivial.pipe' written in reverse. This eliminates any bugs and
performance regressions from unnecessary thunk evaluation.
2026-02-23 22:08:18 +00:00

189 lines
4.9 KiB
Nix

{
lib,
pkgs,
sLib,
info,
geckoLib,
...
}@args:
let
# (a -> b -> c) -> [a] -> [b] -> [c]
mapProduct =
f: xs: ys:
builtins.concatMap (y: builtins.concatMap (x: f x y) xs) ys;
# (Lib -> Profile -> c) -> ProfileSettings -> [c]
mapLibAndProfile =
f:
sLib.compose [
(mapProduct f allLibs)
builtins.attrValues
];
allLibs = sLib.compose [
builtins.attrValues
(lib.filterAttrs (k: _: k != "profiles"))
] geckoLib;
allLibs' = allLibs ++ [ geckoLib.profiles ];
submodule =
{ config, name, ... }:
{
options = {
id = lib.mkOption {
type = lib.types.ints.unsigned;
default = 0;
description = "Profile ID";
};
name = lib.mkOption {
type = lib.types.str;
default = name;
description = "Profile name";
};
path = lib.mkOption {
type = lib.types.str;
default = name;
description = "Profile path";
};
isDefault = lib.mkOption {
type = lib.types.bool;
default = config.id == 0;
defaultText = "config.id == 0";
description = "Is profile the default?";
};
languagePacks = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [
"en-GB"
"de"
];
description = "The language packs to install.";
};
}
// builtins.foldl' (x: y: x // y.options) { } allLibs;
};
writeProfilesIni = configPath: profileSettings: {
name = "${configPath}/profiles.ini";
value.text = lib.generators.toINI { } (
lib.mapAttrs' (
_: v:
lib.nameValuePair "Profile${builtins.toString v.id}" {
Name = v.name;
Path = v.path;
IsRelative = 1;
Default = if v.isDefault then 1 else 0;
}
) profileSettings
// {
General = {
StartWithLastProfile = 1;
Version = 2;
};
}
);
};
in
{
options = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule submodule);
default = { };
description = "Sets browser settings on a per-profile basis.";
};
getDefaultProfileName =
profileSettings:
sLib.compose [
builtins.head
(builtins.filter (x: profileSettings.${x}.isDefault))
builtins.attrNames
] profileSettings;
process =
{ languagePacks, ... }:
let
extractVersion = sLib.compose [
(x: if x == [ ] then info.base.version else builtins.head x)
(builtins.match "([^-]*)-.*")
] info.base.version;
in
{
policies.ExtensionSettings = sLib.compose [
builtins.listToAttrs
(builtins.map (lang: {
name = "langpack-${lang}@firefox.mozilla.org";
value = {
installation_mode = "force_installed";
install_url = "https://releases.mozilla.org/pub/firefox/releases/${extractVersion}/linux-x86_64/xpi/${lang}.xpi";
};
}))
] languagePacks;
};
assertions = profiles: [
{
assertion = profiles != { };
message = "No profiles are defined.";
}
{
assertion = sLib.compose [
(x: x == 1)
builtins.length
(builtins.filter (x: profiles.${x}.isDefault))
builtins.attrNames
] profiles;
message = "One, and only one, profile must be marked as 'isDefault'. If you have not set this option on any profile, then one and only one profile must have id '0'.";
}
];
warnings = _: [ ];
evaluateAllProfiles =
profiles:
let
processLevel =
level: userConfig:
sLib.compose [
sLib.recursiveMergeAll
(x: [ userConfig ] ++ x)
(builtins.map (myLib: (myLib.${level} or (_: { })) userConfig))
] allLibs';
# Internal libraries can create their own configuration that needs to be merged
# into the user configuration (the user's takes priority). Generate that config.
finalConfig = builtins.mapAttrs (
_:
sLib.compose [
(processLevel "postprocess")
(processLevel "process")
(processLevel "preprocess")
]
) profiles;
in
{
assertions =
mapLibAndProfile (x: x.assertions or (_: [ ])) finalConfig
++ geckoLib.profiles.assertions finalConfig;
warnings =
mapLibAndProfile (x: x.warnings or (_: [ ])) finalConfig ++ geckoLib.profiles.warnings finalConfig;
profiles = lib.mapAttrs (_: v: {
policies = v.policies;
prefs = v.prefs;
files = builtins.concatMap (x: (x.files or (_: [ ])) v) allLibs';
extFiles = builtins.concatMap (x: (x.extFiles or (_: [ ])) v) allLibs';
}) finalConfig;
files = [
(writeProfilesIni info.configPath finalConfig)
]
++ mapLibAndProfile (x: x.files or (_: [ ])) finalConfig;
};
}