about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2021-12-08 21:27:02 +0100
committerGitHub <noreply@github.com>2021-12-08 21:27:02 +0100
commit15c41e1d54fca9ba6f3c7fbaf294b8af139fbca2 (patch)
tree21a29d4eb2ee33c357a04a939ef68f861cea0b31 /nixos
parent0d85aadbf639e143421ed461ab0a9c42f5f99781 (diff)
parent027f7e1b7f4552c9c9f0ff909a6863d5bf347a72 (diff)
Merge pull request #147265 from pennae/option-docs-build
put all option docs build flavors on equal footing
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/default.nix2
-rw-r--r--nixos/lib/make-options-doc/default.nix129
-rw-r--r--nixos/lib/make-options-doc/generateAsciiDoc.py37
-rw-r--r--nixos/lib/make-options-doc/generateCommonMark.py27
-rw-r--r--nixos/lib/make-options-doc/options-to-docbook.xsl2
-rw-r--r--nixos/lib/make-options-doc/optionsJSONtoXML.nix6
-rw-r--r--nixos/lib/make-options-doc/sortXML.py1
7 files changed, 110 insertions, 94 deletions
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 151743d9fb580..31b6da01c6bd0 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -161,7 +161,7 @@ let
 in rec {
   inherit generatedSources;
 
-  inherit (optionsDoc) optionsJSON optionsXML optionsDocBook;
+  inherit (optionsDoc) optionsJSON optionsDocBook;
 
   # Generate the NixOS manual.
   manualHTML = runCommand "nixos-manual-html"
diff --git a/nixos/lib/make-options-doc/default.nix b/nixos/lib/make-options-doc/default.nix
index e058e70f3888e..493006c92e7f3 100644
--- a/nixos/lib/make-options-doc/default.nix
+++ b/nixos/lib/make-options-doc/default.nix
@@ -24,18 +24,25 @@
 }:
 
 let
-  # Replace functions by the string <function>
-  substFunction = x:
-    if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
-    else if builtins.isList x then map substFunction x
+  # Make a value safe for JSON. Functions are replaced by the string "<function>",
+  # derivations are replaced with an attrset
+  # { _type = "derivation"; name = <name of that derivation>; }.
+  # We need to handle derivations specially because consumers want to know about them,
+  # but we can't easily use the type,name subset of keys (since type is often used as
+  # a module option and might cause confusion). Use _type,name instead to the same
+  # effect, since _type is already used by the module system.
+  substSpecial = x:
+    if lib.isDerivation x then { _type = "derivation"; name = x.name; }
+    else if builtins.isAttrs x then lib.mapAttrs (name: substSpecial) x
+    else if builtins.isList x then map substSpecial x
     else if lib.isFunction x then "<function>"
     else x;
 
-  optionsListDesc = lib.flip map optionsListVisible
+  optionsList = lib.flip map optionsListVisible
    (opt: transformOptions opt
-    // lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
-    // lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
-    // lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
+    // lib.optionalAttrs (opt ? example) { example = substSpecial opt.example; }
+    // lib.optionalAttrs (opt ? default) { default = substSpecial opt.default; }
+    // lib.optionalAttrs (opt ? type) { type = substSpecial opt.type; }
     // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
    );
 
@@ -69,96 +76,25 @@ let
         + "</listitem>";
     in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
 
-  # Custom "less" that pushes up all the things ending in ".enable*"
-  # and ".package*"
-  optionLess = a: b:
-    let
-      ise = lib.hasPrefix "enable";
-      isp = lib.hasPrefix "package";
-      cmp = lib.splitByAndCompare ise lib.compare
-                                 (lib.splitByAndCompare isp lib.compare lib.compare);
-    in lib.compareLists cmp a.loc b.loc < 0;
-
   # Remove invisible and internal options.
   optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
 
-  # Customly sort option list for the man page.
-  # Always ensure that the sort order matches sortXML.py!
-  optionsList = lib.sort optionLess optionsListDesc;
-
-  # Convert the list of options into an XML file.
-  # This file is *not* sorted sorted to save on eval time, since the docbook XML
-  # and the manpage depend on it and thus we evaluate this on every system rebuild.
-  optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsListDesc);
-
   optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
 
-  # TODO: declarations: link to github
-  singleAsciiDoc = name: value: ''
-    == ${name}
-
-    ${value.description}
-
-    [discrete]
-    === details
-
-    Type:: ${value.type}
-    ${ if lib.hasAttr "default" value
-       then ''
-        Default::
-        +
-        ----
-        ${builtins.toJSON value.default}
-        ----
-      ''
-      else "No Default:: {blank}"
-    }
-    ${ if value.readOnly
-       then "Read Only:: {blank}"
-      else ""
-    }
-    ${ if lib.hasAttr "example" value
-       then ''
-        Example::
-        +
-        ----
-        ${builtins.toJSON value.example}
-        ----
-      ''
-      else "No Example:: {blank}"
-    }
-  '';
-
-  singleMDDoc = name: value: ''
-    ## ${lib.escape [ "<" ">" ] name}
-    ${value.description}
-
-    ${lib.optionalString (value ? type) ''
-      *_Type_*:
-      ${value.type}
-    ''}
-
-    ${lib.optionalString (value ? default) ''
-      *_Default_*
-      ```
-      ${builtins.toJSON value.default}
-      ```
-    ''}
-
-    ${lib.optionalString (value ? example) ''
-      *_Example_*
-      ```
-      ${builtins.toJSON value.example}
-      ```
-    ''}
-  '';
-
-in {
+in rec {
   inherit optionsNix;
 
-  optionsAsciiDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleAsciiDoc optionsNix);
+  optionsAsciiDoc = pkgs.runCommand "options.adoc" {} ''
+    ${pkgs.python3Minimal}/bin/python ${./generateAsciiDoc.py} \
+      < ${optionsJSON}/share/doc/nixos/options.json \
+      > $out
+  '';
 
-  optionsMDDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleMDDoc optionsNix);
+  optionsCommonMark = pkgs.runCommand "options.md" {} ''
+    ${pkgs.python3Minimal}/bin/python ${./generateCommonMark.py} \
+      < ${optionsJSON}/share/doc/nixos/options.json \
+      > $out
+  '';
 
   optionsJSON = pkgs.runCommand "options.json"
     { meta.description = "List of NixOS options in JSON format";
@@ -176,7 +112,18 @@ in {
       mkdir -p $out/nix-support
       echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
       echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
-    ''; # */
+    '';
+
+  # Convert options.json into an XML file.
+  # The actual generation of the xml file is done in nix purely for the convenience
+  # of not having to generate the xml some other way
+  optionsXML = pkgs.runCommand "options.xml" {} ''
+    ${pkgs.nix}/bin/nix-instantiate \
+      --store dummy:// \
+      --eval --xml --strict ${./optionsJSONtoXML.nix} \
+      --argstr file ${optionsJSON}/share/doc/nixos/options.json \
+      > "$out"
+  '';
 
   optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
     optionsXML=${optionsXML}
diff --git a/nixos/lib/make-options-doc/generateAsciiDoc.py b/nixos/lib/make-options-doc/generateAsciiDoc.py
new file mode 100644
index 0000000000000..48eadd248c5a0
--- /dev/null
+++ b/nixos/lib/make-options-doc/generateAsciiDoc.py
@@ -0,0 +1,37 @@
+import json
+import sys
+
+options = json.load(sys.stdin)
+# TODO: declarations: link to github
+for (name, value) in options.items():
+    print(f'== {name}')
+    print()
+    print(value['description'])
+    print()
+    print('[discrete]')
+    print('=== details')
+    print()
+    print(f'Type:: {value["type"]}')
+    if 'default' in value:
+        print('Default::')
+        print('+')
+        print('----')
+        print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
+        print('----')
+        print()
+    else:
+        print('No Default:: {blank}')
+    if value['readOnly']:
+        print('Read Only:: {blank}')
+    else:
+        print()
+    if 'example' in value:
+        print('Example::')
+        print('+')
+        print('----')
+        print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
+        print('----')
+        print()
+    else:
+        print('No Example:: {blank}')
+    print()
diff --git a/nixos/lib/make-options-doc/generateCommonMark.py b/nixos/lib/make-options-doc/generateCommonMark.py
new file mode 100644
index 0000000000000..404e53b0df9c2
--- /dev/null
+++ b/nixos/lib/make-options-doc/generateCommonMark.py
@@ -0,0 +1,27 @@
+import json
+import sys
+
+options = json.load(sys.stdin)
+for (name, value) in options.items():
+    print('##', name.replace('<', '\\<').replace('>', '\\>'))
+    print(value['description'])
+    print()
+    if 'type' in value:
+        print('*_Type_*:')
+        print(value['type'])
+        print()
+    print()
+    if 'default' in value:
+        print('*_Default_*')
+        print('```')
+        print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
+        print('```')
+    print()
+    print()
+    if 'example' in value:
+        print('*_Example_*')
+        print('```')
+        print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
+        print('```')
+    print()
+    print()
diff --git a/nixos/lib/make-options-doc/options-to-docbook.xsl b/nixos/lib/make-options-doc/options-to-docbook.xsl
index da4cd164bf206..b9ac264505147 100644
--- a/nixos/lib/make-options-doc/options-to-docbook.xsl
+++ b/nixos/lib/make-options-doc/options-to-docbook.xsl
@@ -189,7 +189,7 @@
   </xsl:template>
 
 
-  <xsl:template match="derivation">
+  <xsl:template match="attrs[attr[@name = '_type' and string[@value = 'derivation']]]">
     <replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
   </xsl:template>
 
diff --git a/nixos/lib/make-options-doc/optionsJSONtoXML.nix b/nixos/lib/make-options-doc/optionsJSONtoXML.nix
new file mode 100644
index 0000000000000..ba50c5f898b5a
--- /dev/null
+++ b/nixos/lib/make-options-doc/optionsJSONtoXML.nix
@@ -0,0 +1,6 @@
+{ file }:
+
+builtins.attrValues
+  (builtins.mapAttrs
+    (name: def: def // { inherit name; })
+    (builtins.fromJSON (builtins.readFile file)))
diff --git a/nixos/lib/make-options-doc/sortXML.py b/nixos/lib/make-options-doc/sortXML.py
index 717820788c944..e63ff3538b3fe 100644
--- a/nixos/lib/make-options-doc/sortXML.py
+++ b/nixos/lib/make-options-doc/sortXML.py
@@ -19,7 +19,6 @@ def sortKey(opt):
         for p in opt.findall('attr[@name="loc"]/list/string')
     ]
 
-# always ensure that the sort order matches the order used in the nix expression!
 options.sort(key=sortKey)
 
 doc = ET.Element("expr")