{ pkgs, lib, config, ... }: let inherit (lib) types; inherit (lib.options) mkEnableOption mkOption; cfg = config.services.smooooth; in { options.services.smooooth = { enable = mkEnableOption "the smooooth nixos hot reloader"; blockers = mkOption { description = "names of processes that may block reloading by holding a flake (sub)path open. default state is \"stop\""; default = [ "nano" "nvim" "vim" "vi" "hx" ]; example = '' [ "hx" { nano = "die"; nvim = "stop"; } { fish = "die"; } ] ''; type = with types; listOf ( either str ( attrsOf (enum [ "stop" "die" ]) ) ); }; path = mkOption { description = "path to the root of your flake."; type = types.str; }; nixPackage = mkOption { description = "preferred package providing a `nix` executable."; default = pkgs.nix; type = types.package; }; package = mkOption { description = "smooooth package"; type = types.package; }; }; config = lib.mkIf cfg.enable { environment.etc."smooooth.json".text = builtins.toJSON { inherit (cfg) path; blockers = let withDefaults = map ( b: if builtins.typeOf b == "string" then { "${b}" = "stop"; } else b ) cfg.blockers; merged = lib.mergeAttrsList withDefaults; # FIXME clumsy, could do better transformed = lib.mapAttrsToList (n: v: { name = n; cond = [ (lib.toSentenceCase v) ]; }) merged; in transformed; }; systemd.user = { services.smooooth = { enable = true; path = [ cfg.package ]; wantedBy = [ "graphical-session.target" ]; after = [ "graphical-session.target" ]; serviceConfig = { Restart = "always"; Type = "notify"; ExecStart = "${lib.getExe cfg.package}"; }; }; }; }; }