| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | # Nixpkgs/NixOS option handling. | 
					
						
							| 
									
										
										
										
											2017-07-28 20:05:35 -04:00
										 |  |  |  | { lib }: | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-28 20:05:35 -04:00
										 |  |  |  | with lib.trivial; | 
					
						
							|  |  |  |  | with lib.lists; | 
					
						
							|  |  |  |  | with lib.attrsets; | 
					
						
							|  |  |  |  | with lib.strings; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | rec { | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-23 18:20:39 +02:00
										 |  |  |  |   isOption = lib.isType "option"; | 
					
						
							| 
									
										
										
										
											2013-10-30 15:33:20 +01:00
										 |  |  |  |   mkOption = | 
					
						
							|  |  |  |  |     { default ? null # Default value used when no definition is given in the configuration. | 
					
						
							|  |  |  |  |     , defaultText ? null # Textual representation of the default, for in the manual. | 
					
						
							|  |  |  |  |     , example ? null # Example value used in the manual. | 
					
						
							|  |  |  |  |     , description ? null # String describing the option. | 
					
						
							| 
									
										
										
										
											2016-04-20 21:57:33 +00:00
										 |  |  |  |     , relatedPackages ? null # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix). | 
					
						
							| 
									
										
										
										
											2013-10-30 15:33:20 +01:00
										 |  |  |  |     , type ? null # Option type, providing type-checking and value merging. | 
					
						
							|  |  |  |  |     , apply ? null # Function that converts the option value to something else. | 
					
						
							|  |  |  |  |     , internal ? null # Whether the option is for NixOS developers only. | 
					
						
							|  |  |  |  |     , visible ? null # Whether the option shows up in the manual. | 
					
						
							| 
									
										
										
										
											2015-07-30 13:36:57 +02:00
										 |  |  |  |     , readOnly ? null # Whether the option can be set only once | 
					
						
							| 
									
										
										
										
											2013-10-30 15:33:20 +01:00
										 |  |  |  |     , options ? null # Obsolete, used by types.optionSet. | 
					
						
							|  |  |  |  |     } @ attrs: | 
					
						
							|  |  |  |  |     attrs // { _type = "option"; }; | 
					
						
							| 
									
										
										
										
											2009-05-27 20:25:17 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-18 15:13:42 -04:00
										 |  |  |  |   mkEnableOption = name: mkOption { | 
					
						
							|  |  |  |  |     default = false; | 
					
						
							|  |  |  |  |     example = true; | 
					
						
							| 
									
										
										
										
											2013-10-17 14:29:51 +02:00
										 |  |  |  |     description = "Whether to enable ${name}."; | 
					
						
							| 
									
										
										
										
											2013-07-18 15:13:42 -04:00
										 |  |  |  |     type = lib.types.bool; | 
					
						
							|  |  |  |  |   }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-21 14:50:46 +01:00
										 |  |  |  |   # This option accept anything, but it does not produce any result.  This | 
					
						
							|  |  |  |  |   # is useful for sharing a module across different module sets without | 
					
						
							|  |  |  |  |   # having to implement similar features as long as the value of the options | 
					
						
							|  |  |  |  |   # are not expected. | 
					
						
							|  |  |  |  |   mkSinkUndeclaredOptions = attrs: mkOption ({ | 
					
						
							|  |  |  |  |     internal = true; | 
					
						
							|  |  |  |  |     visible = false; | 
					
						
							|  |  |  |  |     default = false; | 
					
						
							|  |  |  |  |     description = "Sink for option definitions."; | 
					
						
							|  |  |  |  |     type = mkOptionType { | 
					
						
							|  |  |  |  |       name = "sink"; | 
					
						
							|  |  |  |  |       check = x: true; | 
					
						
							|  |  |  |  |       merge = loc: defs: false; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  |     apply = x: throw "Option value is not readable because the option is not declared."; | 
					
						
							|  |  |  |  |   } // attrs); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |   mergeDefaultOption = loc: defs: | 
					
						
							|  |  |  |  |     let list = getValues defs; in | 
					
						
							| 
									
										
										
										
											2012-08-13 14:19:31 -04:00
										 |  |  |  |     if length list == 1 then head list | 
					
						
							| 
									
										
										
										
											2013-11-12 13:48:19 +01:00
										 |  |  |  |     else if all isFunction list then x: mergeDefaultOption loc (map (f: f x) list) | 
					
						
							| 
									
										
										
										
											2009-05-19 14:54:41 +00:00
										 |  |  |  |     else if all isList list then concatLists list | 
					
						
							| 
									
										
										
										
											2015-07-23 17:19:21 +02:00
										 |  |  |  |     else if all isAttrs list then foldl' lib.mergeAttrs {} list | 
					
						
							|  |  |  |  |     else if all isBool list then foldl' lib.or false list | 
					
						
							| 
									
										
										
										
											2013-11-12 13:48:19 +01:00
										 |  |  |  |     else if all isString list then lib.concatStrings list | 
					
						
							|  |  |  |  |     else if all isInt list && all (x: x == head list) list then head list | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |     else throw "Cannot merge definitions of `${showOption loc}' given in ${showFiles (getFiles defs)}."; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |   mergeOneOption = loc: defs: | 
					
						
							|  |  |  |  |     if defs == [] then abort "This case should never happen." | 
					
						
							|  |  |  |  |     else if length defs != 1 then | 
					
						
							|  |  |  |  |       throw "The unique option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}." | 
					
						
							|  |  |  |  |     else (head defs).value; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:04:27 +02:00
										 |  |  |  |   /* "Merge" option definitions by checking that they all have the same value. */ | 
					
						
							|  |  |  |  |   mergeEqualOption = loc: defs: | 
					
						
							|  |  |  |  |     if defs == [] then abort "This case should never happen." | 
					
						
							| 
									
										
										
										
											2015-07-23 17:19:21 +02:00
										 |  |  |  |     else foldl' (val: def: | 
					
						
							| 
									
										
										
										
											2015-06-15 18:04:27 +02:00
										 |  |  |  |       if def.value != val then | 
					
						
							|  |  |  |  |         throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}." | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         val) (head defs).value defs; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |   getValues = map (x: x.value); | 
					
						
							|  |  |  |  |   getFiles = map (x: x.file); | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:38 +00:00
										 |  |  |  |   # Generate documentation template from the list of option declaration like | 
					
						
							|  |  |  |  |   # the set generated with filterOptionSets. | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |   optionAttrSetToDocList = optionAttrSetToDocList' []; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   optionAttrSetToDocList' = prefix: options: | 
					
						
							| 
									
										
										
										
											2015-07-23 16:32:52 +02:00
										 |  |  |  |     concatMap (opt: | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |       let | 
					
						
							|  |  |  |  |         docOption = rec { | 
					
						
							| 
									
										
										
										
											2018-02-11 22:04:09 +00:00
										 |  |  |  |           loc = opt.loc; | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |           name = showOption opt.loc; | 
					
						
							|  |  |  |  |           description = opt.description or (throw "Option `${name}' has no description."); | 
					
						
							|  |  |  |  |           declarations = filter (x: x != unknownModule) opt.declarations; | 
					
						
							|  |  |  |  |           internal = opt.internal or false; | 
					
						
							|  |  |  |  |           visible = opt.visible or true; | 
					
						
							| 
									
										
										
										
											2015-07-30 13:36:57 +02:00
										 |  |  |  |           readOnly = opt.readOnly or false; | 
					
						
							| 
									
										
										
										
											2016-09-07 10:03:32 +09:00
										 |  |  |  |           type = opt.type.description or null; | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-20 21:57:33 +00:00
										 |  |  |  |         // optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; } | 
					
						
							|  |  |  |  |         // optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; } | 
					
						
							|  |  |  |  |         // optionalAttrs (opt ? defaultText) { default = opt.defaultText; } | 
					
						
							|  |  |  |  |         // optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) { inherit (opt) relatedPackages; }; | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         subOptions = | 
					
						
							|  |  |  |  |           let ss = opt.type.getSubOptions opt.loc; | 
					
						
							|  |  |  |  |           in if ss != {} then optionAttrSetToDocList' opt.loc ss else []; | 
					
						
							|  |  |  |  |       in | 
					
						
							| 
									
										
										
										
											2015-07-23 16:32:52 +02:00
										 |  |  |  |         [ docOption ] ++ subOptions) (collect isOption options); | 
					
						
							| 
									
										
										
										
											2009-06-11 16:03:38 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 11:07:49 +00:00
										 |  |  |  |   /* This function recursively removes all derivation attributes from
 | 
					
						
							|  |  |  |  |      `x' except for the `name' attribute.  This is to make the | 
					
						
							|  |  |  |  |      generation of `options.xml' much more efficient: the XML | 
					
						
							|  |  |  |  |      representation of derivations is very large (on the order of | 
					
						
							|  |  |  |  |      megabytes) and is not actually used by the manual generator. */ | 
					
						
							| 
									
										
										
										
											2013-10-17 14:29:51 +02:00
										 |  |  |  |   scrubOptionValue = x: | 
					
						
							| 
									
										
										
										
											2013-10-30 16:19:07 +01:00
										 |  |  |  |     if isDerivation x then | 
					
						
							|  |  |  |  |       { type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; } | 
					
						
							| 
									
										
										
										
											2010-05-12 11:07:49 +00:00
										 |  |  |  |     else if isList x then map scrubOptionValue x | 
					
						
							| 
									
										
										
										
											2010-06-01 14:24:16 +00:00
										 |  |  |  |     else if isAttrs x then mapAttrs (n: v: scrubOptionValue v) (removeAttrs x ["_args"]) | 
					
						
							| 
									
										
										
										
											2010-05-12 11:07:49 +00:00
										 |  |  |  |     else x; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 10:14:24 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* For use in the ‘example’ option attribute.  It causes the given
 | 
					
						
							|  |  |  |  |      text to be included verbatim in documentation.  This is necessary | 
					
						
							|  |  |  |  |      for example values that are not simple values, e.g., | 
					
						
							|  |  |  |  |      functions. */ | 
					
						
							|  |  |  |  |   literalExample = text: { _type = "literalExample"; inherit text; }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Helper functions. */ | 
					
						
							| 
									
										
										
										
											2018-03-05 09:54:21 -05:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   # Convert an option, described as a list of the option parts in to a | 
					
						
							|  |  |  |  |   # safe, human readable version. ie: | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   # (showOption ["foo" "bar" "baz"]) == "foo.bar.baz" | 
					
						
							|  |  |  |  |   # (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux" | 
					
						
							|  |  |  |  |   showOption = parts: let | 
					
						
							|  |  |  |  |     escapeOptionPart = part: | 
					
						
							|  |  |  |  |       let | 
					
						
							|  |  |  |  |         escaped = lib.strings.escapeNixString part; | 
					
						
							|  |  |  |  |       in if escaped == "\"${part}\"" | 
					
						
							|  |  |  |  |          then part | 
					
						
							|  |  |  |  |          else escaped; | 
					
						
							|  |  |  |  |     in (concatStringsSep ".") (map escapeOptionPart parts); | 
					
						
							| 
									
										
										
										
											2013-10-28 19:48:30 +01:00
										 |  |  |  |   showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files); | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |   unknownModule = "<unknown-file>"; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:41 +00:00
										 |  |  |  | } |