flake: { config, pkgs, lib, system, ... }: let cfg = config.programs.packer; templatePath = "${config.home.homeDirectory}/.config/packer/template.clj"; app = pkgs.runCommand "packer" {buildInputs = [pkgs.makeWrapper];} '' makeWrapper ${flake.outputs.packages.${system}.packer}/bin/packer $out/bin/packer --set PACKER_TEMPLATE_FILE "${templatePath}" ''; in { options.programs.packer = with lib; { enable = mkEnableOption "Packer application"; templateFile = mkOption { type = types.nullOr types.path; description = "The path to template file. If provided, the 'template' option will be ignored."; default = null; example = "./packer.template.clj"; }; template = mkOption { type = types.str; description = "The content of the template file written in Clojure language."; default = '' (use 'packer.model) (require 'packer.util) ; Define some useful function ; to provide a constant number of items. (defn x [n] (fn [_] n)) ; Define a store - the single source ; of truth of all items from which ; we are going to choose what we want to pack. ; The items are grouped by categories. (def store { :cloths [ (->Item :t-shirt #(/ % 4)) ] :electronics [ (->Item :smartphone (x 1)) (->Item :tablet (x 1)) (->Item :laptop (x 1)) ] }) ; Define the display names for each ; item, category and question. (def i18n { :nights? "How many nights?" :tablet? "Do you need your tablet there?" :laptop? "Do you need your laptop there?" :electronics "Electronics" :cloths "Cloths" :t-shirt "T-shirt" :smartphone "Smartphone" :tablet "Tablet" :laptop "Laptop" }) ; Define some utility function ; to generate preset basing on some question (defn preset [question items seq] (if (packer.util/ask-bool (get i18n question)) (concat seq items) seq)) ; Define profile - a function which takes ; a number of provided nights and produces ; the sequence of all items which should ; be in the target list. If the sequence is empty ; no item will be produced on the target list. (defn profile [nights] (->> [:smartphone :t-shirt] (preset :tablet? [:tablet]) (preset :laptop? [:laptop]))) ; Wrap it up together. It should be ; the last expression in the file. (->Template store i18n profile) ''; }; }; config = lib.mkIf cfg.enable { home.packages = [app]; home.file.${templatePath} = if (cfg.templateFile != null) then { source = cfg.templateFile; } else { text = cfg.template; }; }; }