diff --git a/modules/launchd/default.nix b/modules/launchd/default.nix
index dccddd0..8ff6933 100644
--- a/modules/launchd/default.nix
+++ b/modules/launchd/default.nix
@@ -35,56 +35,7 @@ let
config = {
serviceConfig.Label = mkDefault "org.nixos.${name}";
- plist = pkgs.writeText "${config.serviceConfig.Label}.plist" (''
-
-
-
-
- '' + xmlMapAttr xmlString "Label" config.serviceConfig.Label
- + xmlMapAttr xmlBool "Disabled" config.serviceConfig.Disabled
- + xmlMapAttr xmlString "UserName" config.serviceConfig.UserName
- + xmlMapAttr xmlString "GroupName" config.serviceConfig.GroupName
- + xmlMapAttr (xmlMapAttrs xmlBool) "inetdCompatibility" config.serviceConfig.inetdCompatibility
- + xmlMapAttr (xmlMap xmlString) "LimitLoadToHosts" config.serviceConfig.LimitLoadToHosts
- + xmlMapAttr (xmlMap xmlString) "LimitLoadFromHosts" config.serviceConfig.LimitLoadFromHosts
- + xmlMapAttr xmlString "LimitLoadToSessionType" config.serviceConfig.LimitLoadToSessionType
- + xmlMapAttr xmlString "Program" config.serviceConfig.Program
- + xmlMapAttr (xmlMap xmlString) "ProgramArguments" config.serviceConfig.ProgramArguments
- + xmlMapAttr xmlBool "EnableGlobbing" config.serviceConfig.EnableGlobbing
- + xmlMapAttr xmlBool "EnableTransactions" config.serviceConfig.EnableTransactions
- + xmlMapAttr xmlBool "OnDemand" config.serviceConfig.OnDemand
- + xmlMapAttr xmlBool "KeepAlive" config.serviceConfig.KeepAlive
- + xmlMapAttr xmlBool "RunAtLoad" config.serviceConfig.RunAtLoad
- + xmlMapAttr xmlString "RootDirectory" config.serviceConfig.RootDirectory
- + xmlMapAttr xmlString "WorkingDirectory" config.serviceConfig.WorkingDirectory
- + xmlMapAttr (xmlMapAttrs xmlString) "EnvironmentVariables" config.serviceConfig.EnvironmentVariables
- + xmlMapAttr xmlInt "Umask" config.serviceConfig.Umask
- + xmlMapAttr xmlInt "TimeOut" config.serviceConfig.TimeOut
- + xmlMapAttr xmlInt "ExitTimeOut" config.serviceConfig.ExitTimeOut
- + xmlMapAttr xmlInt "ThrottleInterval" config.serviceConfig.ThrottleInterval
- + xmlMapAttr xmlBool "InitGroups" config.serviceConfig.InitGroups
- + xmlMapAttr (xmlMap xmlString) "WatchPaths" config.serviceConfig.WatchPaths
- + xmlMapAttr (xmlMap xmlString) "QueueDirectories" config.serviceConfig.QueueDirectories
- + xmlMapAttr xmlBool "StartOnMount" config.serviceConfig.StartOnMount
- + xmlMapAttr xmlInt "StartInterval" config.serviceConfig.StartInterval
- + xmlMapAttr (xmlMapAttrs xmlInt) "StartCalendarInterval" config.serviceConfig.StartCalendarInterval
- + xmlMapAttr xmlString "StandardInPath" config.serviceConfig.StandardInPath
- + xmlMapAttr xmlString "StandardOutPath" config.serviceConfig.StandardOutPath
- + xmlMapAttr xmlString "StandardErrorPath" config.serviceConfig.StandardErrorPath
- + xmlMapAttr xmlBool "Debug" config.serviceConfig.Debug
- + xmlMapAttr xmlBool "WaitForDebugger" config.serviceConfig.WaitForDebugger
- + xmlMapAttr (xmlMapAttrs xmlInt) "SoftResourceLimits" config.serviceConfig.SoftResourceLimits
- + xmlMapAttr (xmlMapAttrs xmlInt) "HardResourceLimits" config.serviceConfig.HardResourceLimits
- + xmlMapAttr xmlInt "Nice" config.serviceConfig.Nice
- + xmlMapAttr xmlString "ProcessType" config.serviceConfig.ProcessType
- + xmlMapAttr xmlBool "AbandonProcessGroup" config.serviceConfig.AbandonProcessGroup
- + xmlMapAttr xmlBool "LowPriorityIO" config.serviceConfig.LowPriorityIO
- + xmlMapAttr xmlBool "LaunchOnlyOnce" config.serviceConfig.LaunchOnlyOnce
- + xmlMapAttr (xmlMapAttrs xmlBool) "MachServices" config.serviceConfig.MachServices
- + ''
-
-
- '');
+ plist = pkgs.writeText "${config.serviceConfig.Label}.plist" (toPLIST config.serviceConfig);
};
};
diff --git a/modules/launchd/lib.nix b/modules/launchd/lib.nix
index 483a0d1..65fc036 100644
--- a/modules/launchd/lib.nix
+++ b/modules/launchd/lib.nix
@@ -2,27 +2,56 @@
with lib;
+let
+
+ attrFilter = name: value: name != "_module" && value != null;
+
+in
+
rec {
- xmlMap = f: xs: ''
-
- ${concatMapStringsSep "\n" f xs}
-
- '';
+ toPLIST = x: ''
+
+
+
+ '' + pprExpr "" x
+ + "\n";
- xmlMapAttrs = f: attr: ''
-
- ${concatStringsSep "\n" (mapAttrsFlatten (xmlMapAttr f) attr)}
-
- '';
+ pprExpr = ind: x:
+ if isNull x then "" else
+ if isBool x then pprBool ind x else
+ if isInt x then pprInt ind x else
+ if isString x then pprStr ind x else
+ if isList x then pprList ind x else
+ if isAttrs x then pprAttrs ind x else
+ throw "invalid plist type";
- xmlMapAttr = f: n: v: optionalString (v != null) ''
- ${n}
- ${f v}
- '';
+ pprLiteral = ind: x: ind + x;
- xmlBool = x: if x then "" else "";
- xmlInt = x: "${toString x}";
- xmlString = x: "${x}";
+ pprBool = ind: x: pprLiteral ind (if x then "" else "");
+ pprInt = ind: x: pprLiteral ind "${toString x}";
+ pprStr = ind: x: pprLiteral ind "${x}";
+ pprKey = ind: x: pprLiteral ind "${x}";
+
+ pprIndent = ind: (pprExpr "\t${ind}");
+
+ pprItem = ind: concatMapStringsSep "\n" (pprIndent ind);
+
+ pprList = ind: x: concatStringsSep "\n" [
+ (pprLiteral ind "")
+ (pprItem ind x)
+ (pprLiteral ind "")
+ ];
+
+ pprAttrs = ind: x: concatStringsSep "\n" [
+ (pprLiteral ind "")
+ (pprAttr ind x)
+ (pprLiteral ind "")
+ ];
+
+ pprAttr = ind: x: concatStringsSep "\n" (flatten (mapAttrsToList (name: value: optional (attrFilter name value) [
+ (pprKey "\t${ind}" name)
+ (pprExpr "\t${ind}" value)
+ ]) x));
}