# My own module with nicer syntax for impernanence { lib, config, ... }: let cfg = config.satellite.persistence; in { # {{{ Option definition options.satellite.persistence = { enable = lib.mkEnableOption "satellite persistence"; at = lib.mkOption { default = { }; description = "Record of persistent locations (eg: /persist)"; type = lib.types.attrsOf (lib.types.submodule (args: { config = { home = "${args.config.path}${config.home.homeDirectory}"; }; options = { # {{{ Location options path = lib.mkOption { type = lib.types.str; example = "/persist"; description = "The root location to store the home directory for files in this record"; }; home = lib.mkOption { type = lib.types.str; description = "The path to the home directory for files in this record"; }; prefixDirectories = lib.mkOption { type = lib.types.bool; default = true; description = "Whether to enable gnu/stow type prefix directories"; }; # }}} # {{{ Apps apps = lib.mkOption { default = { }; description = "Record of gnu/stow-style apps to be stored in this location"; type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: { options = { name = lib.mkOption { type = lib.types.str; default = name; description = "The gnu/stow-style subdirectory name"; }; files = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; example = [ ".screenrc" ]; description = '' A list of files in your home directory you want to link to persistent storage. Allows both absolute paths and paths relative to the home directory. ''; }; directories = lib.mkOption { default = [ ]; description = '' Modified version of `home.persistence.*.directories` which takes in absolute paths. ''; type = lib.types.listOf (lib.types.either lib.types.str (lib.types.submodule { options = { directory = lib.mkOption { type = lib.types.str; example = "/home/username/.config/nvim"; description = "The directory path to be linked."; }; method = lib.mkOption { type = lib.types.enum [ "bindfs" "symlink" ]; default = "symlink"; description = '' The linking method that should be used for this directory. bindfs is the default and works for most use cases, however some programs may behave better with symlinks. ''; }; }; })); }; }; })); }; # }}} }; })); }; }; # }}} # {{{ Config generation config = let makeLocation = location: let # {{{ Path processing processPath = appName: path: let suffix = "${lib.strings.removePrefix "${config.home.homeDirectory}/" (builtins.toString path)}"; prefix = if location.prefixDirectories then "${appName}/" else ""; in # lib.debug.traceSeq "\nProcessing path at location ${location.path} and app ${appName} from original path ${value} to ${prefix + suffix}" (prefix + suffix); # }}} # {{{ Constructors mkDirectory = appName: directory: if builtins.isAttrs directory then { method = directory.method; directory = processPath appName directory.directory; } else processPath appName directory; mkAppDirectory = app: builtins.map (mkDirectory app.name) app.directories; mkAppFiles = app: builtins.map (processPath app.name) app.files; # }}} in # {{{ Impermanence config generation lib.attrsets.nameValuePair location.home { removePrefixDirectory = location.prefixDirectories; allowOther = true; directories = lib.lists.flatten (lib.attrsets.mapAttrsToList (_: mkAppDirectory) location.apps); files = lib.lists.flatten (lib.attrsets.mapAttrsToList (_: mkAppFiles) location.apps); }; # }}} in lib.mkIf cfg.enable { home.persistence = lib.attrsets.mapAttrs' (_: makeLocation) cfg.at; }; # }}} }