From e72edae19fc13ae14fc575888f0195f58bc9f8fb Mon Sep 17 00:00:00 2001 From: Heitor Augusto Date: Thu, 15 Aug 2024 19:01:27 -0300 Subject: [PATCH] feat: add home manager module --- extractor/extractor.py | 2 +- flake.nix | 2 + modules/default.nix | 7 +++ modules/firefox.nix | 44 ++++++++++++++ modules/librewolf.nix | 44 ++++++++++++++ modules/smoothfox.nix | 44 ++++++++++++++ modules/types.nix | 132 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 modules/default.nix create mode 100644 modules/firefox.nix create mode 100644 modules/librewolf.nix create mode 100644 modules/smoothfox.nix create mode 100644 modules/types.nix diff --git a/extractor/extractor.py b/extractor/extractor.py index 88c096d..d88b389 100644 --- a/extractor/extractor.py +++ b/extractor/extractor.py @@ -75,7 +75,7 @@ def extract(self) -> dict: pref_name, pref_value_raw = pref_match.groups() pref_value = self.parse_value(pref_value_raw) self.current_subsection["settings"].append( - {"name": pref_name, "value": pref_value} + {"enabled": True, "name": pref_name, "value": pref_value} ) return self.sections diff --git a/flake.nix b/flake.nix index 52329be..1d43c4c 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,8 @@ formatter = forAllSystems (pkgs: pkgs.alejandra); + homeManagerModules.betterfox = import ./modules; + packages = forAllSystems (pkgs: let betterfox-extractor = pkgs.callPackage ./extractor {}; in { diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..f319355 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./firefox.nix + ./librewolf.nix + ./smoothfox.nix + ]; +} diff --git a/modules/firefox.nix b/modules/firefox.nix new file mode 100644 index 0000000..e382df0 --- /dev/null +++ b/modules/firefox.nix @@ -0,0 +1,44 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.firefox; + version = + if (config.programs.firefox.package != null) + then "${config.programs.firefox.package.version}" + else "unknown"; + ext = (import ../autogen/firefox).${cfg.betterfox.version}; +in { + options.programs.firefox = { + betterfox = { + enable = lib.mkEnableOption "betterfox support in profiles"; + version = lib.mkOption { + description = "The version of betterfox user.js used"; + type = lib.types.enum (builtins.attrNames (import ../autogen/firefox)); + default = "main"; + }; + }; + profiles = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { + options.betterfox = lib.mkOption { + description = "Setup betterfox user.js in profile"; + type = import ./types.nix { + extracted = ext; + inherit lib; + }; + default = {}; + }; + config = lib.mkIf cfg.betterfox.enable { + settings = config.betterfox.flatSettings; + }; + })); + }; + }; + + config = lib.mkIf (cfg.enable && cfg.betterfox.enable && !(lib.hasPrefix cfg.betterfox.version version)) { + warnings = [ + "Betterfox version ${cfg.betterfox.version} does not match Firefox's (${version})" + ]; + }; +} diff --git a/modules/librewolf.nix b/modules/librewolf.nix new file mode 100644 index 0000000..dd74b22 --- /dev/null +++ b/modules/librewolf.nix @@ -0,0 +1,44 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.librewolf; + version = + if (config.programs.librewolf.package != null) + then "${config.programs.librewolf.package.version}" + else "unknown"; + ext = (import ../autogen/librewolf).${cfg.betterfox.version}; +in { + options.programs.librewolf = { + betterfox = { + enable = lib.mkEnableOption "betterfox support in profiles"; + version = lib.mkOption { + description = "The version of betterfox user.js used"; + type = lib.types.enum (builtins.attrNames (import ../autogen/librewolf)); + default = "main"; + }; + }; + settings = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { + options.betterfox = lib.mkOption { + description = "Setup betterfox user.js in settings"; + type = import ./types.nix { + extracted = ext; + inherit lib; + }; + default = {}; + }; + config = lib.mkIf cfg.betterfox.enable { + settings = config.betterfox.flatSettings; + }; + })); + }; + }; + + config = lib.mkIf (cfg.enable && cfg.betterfox.enable && !(lib.hasPrefix cfg.betterfox.version version)) { + warnings = [ + "Betterfox version ${cfg.betterfox.version} does not match Librewolf's (${version})" + ]; + }; +} diff --git a/modules/smoothfox.nix b/modules/smoothfox.nix new file mode 100644 index 0000000..5429664 --- /dev/null +++ b/modules/smoothfox.nix @@ -0,0 +1,44 @@ +{ + config, + lib, + ... +}: let + cfg = config.programs.firefox; + ext = (import ../autogen/smoothfox).${cfg.betterfox.version}; +in { + options.programs.firefox = { + profiles = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { + options.betterfox.smoothfox = lib.mkOption { + description = "Setup betterfox (Smoothfox) user.js in profile"; + type = import ./types.nix { + extracted = ext; + inherit lib; + }; + default = {}; + }; + config = lib.mkIf cfg.betterfox.enable { + settings = config.betterfox.flatSettings; + }; + })); + }; + }; + + options.programs.librewolf = { + profiles = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { + options.betterfox.smoothfox = lib.mkOption { + description = "Setup betterfox (Smoothfox) user.js in profile"; + type = import ./types.nix { + extracted = ext; + inherit lib; + }; + default = {}; + }; + config = lib.mkIf cfg.betterfox.enable { + settings = config.betterfox.flatSettings; + }; + })); + }; + }; +} diff --git a/modules/types.nix b/modules/types.nix new file mode 100644 index 0000000..0065116 --- /dev/null +++ b/modules/types.nix @@ -0,0 +1,132 @@ +{ + lib, + extracted, + ... +}: let + mapListToAttrs = f: lst: + builtins.listToAttrs (map f lst); + + settingType = setting: + lib.types.submodule ({config, ...}: { + options = { + enable = lib.mkOption { + type = lib.types.bool; + default = setting.enabled; + description = "Enable the ${setting.name} setting"; + }; + value = lib.mkOption { + type = lib.types.anything; + default = setting.enabled; + description = "The value of the ${setting.name} setting"; + }; + flat = lib.mkOption { + type = lib.types.attrsOf lib.types.anything; + description = "Empty attrset in enable=false, the setting and its value otherwise"; + readOnly = true; + }; + }; + config = { + flat = + if config.enable + then {"${setting.name}" = config.value;} + else {}; + }; + }); + + settingOption = setting: + lib.nameValuePair setting.name + (lib.mkOption { + description = "Control the ${setting.name} setting"; + type = settingType setting; + default = {}; + }); + + subsectionType = name: sub: + lib.types.submodule ({config, ...}: { + options = + { + enable = lib.mkEnableOption "settings for ${name}"; + flatSettings = lib.mkOption { + description = "Flat attrset of all settings in subsection ${name} enabled"; + type = lib.types.attrsOf lib.types.anything; + readOnly = true; + }; + } + // mapListToAttrs settingOption sub.settings; + config = { + enable = lib.mkDefault true; + flatSettings = + if config.enable + then + builtins.foldl' (x: y: x // y) {} + (map (setting: config.${setting.name}.flat) sub.settings) + else {}; + }; + }); + subsectionOption = name: sub: + lib.mkOption { + description = "${name}: ${sub.meta.title}"; + type = subsectionType name sub; + default = {}; + }; + + sectionType = name: section: let + subsections = builtins.removeAttrs section ["meta"]; + in + lib.types.submodule ({config, ...}: { + options = + { + enable = lib.mkOption { + description = "setting for ${name}"; + type = lib.types.bool; + }; + flatSettings = lib.mkOption { + description = "Flat attrset of all settings in section ${name} enabled"; + type = lib.types.attrsOf lib.types.anything; + readOnly = true; + }; + } + // lib.mapAttrs subsectionOption subsections; + config = { + flatSettings = + if config.enable + then + builtins.foldl' (x: y: x // y) {} + (lib.mapAttrsToList (name: _: config.${name}.flatSettings) subsections) + else {}; + }; + }); + sectionOption = name: section: + lib.mkOption { + description = "${name}: ${section.meta.title}"; + type = sectionType name section; + default = {}; + }; + enableSection = name: _: {config, ...}: { + "${name}".enable = lib.mkDefault config.enableAllSections; + }; + + type = lib.types.submodule ({config, ...}: { + options = + { + enable = lib.mkEnableOption "Betterfox settings"; + enableAllSections = lib.mkEnableOption "Enable all sections by default"; + flatSettings = lib.mkOption { + description = "Flat attrset of all settings enabled"; + type = lib.types.attrsOf lib.types.anything; + readOnly = true; + }; + } + // lib.mapAttrs sectionOption extracted; + config = { + flatSettings = + if config.enable + then + builtins.foldl' (x: y: x // y) {} + (lib.mapAttrsToList (name: _: config.${name}.flatSettings) extracted) + else {}; + }; + imports = lib.mapAttrsToList enableSection extracted; + }); +in + type