From 53d0836347ea262884658036f97bf19ecbdc5c26 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 4 Apr 2023 22:57:11 -0400 Subject: [PATCH] Assemble experimental feature docs outside of Nix itself Instead of constructing a markdown list in C++ (which involved all sorts of nasty string literals), export some JSON and assemble it with the manual build system. Besides following the precedent set with other dumped data, this is a better separate of content and presentation; if we decide for example we want to display this information in a different way, or in a different section of the manual, it will become much easier to do so. --- .gitignore | 2 ++ doc/manual/generate-xp-features.nix | 11 ++++++++++ doc/manual/local.mk | 13 +++++++++-- doc/manual/utils.nix | 6 +++--- src/libutil/config.hh | 17 +++++++++++++-- src/libutil/experimental-features.cc | 32 ++++++---------------------- src/libutil/experimental-features.hh | 6 ++---- src/nix/main.cc | 5 +++++ 8 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 doc/manual/generate-xp-features.nix diff --git a/.gitignore b/.gitignore index e326966d6..53442751f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,11 @@ perl/Makefile.config /doc/manual/nix.json /doc/manual/conf-file.json /doc/manual/builtins.json +/doc/manual/xp-features.json /doc/manual/src/SUMMARY.md /doc/manual/src/command-ref/new-cli /doc/manual/src/command-ref/conf-file.md +/doc/manual/src/command-ref/experimental-features.md /doc/manual/src/language/builtins.md # /scripts/ diff --git a/doc/manual/generate-xp-features.nix b/doc/manual/generate-xp-features.nix new file mode 100644 index 000000000..db1ba6092 --- /dev/null +++ b/doc/manual/generate-xp-features.nix @@ -0,0 +1,11 @@ +with builtins; +with import ./utils.nix; + +let + showExperimentalFeature = name: doc: + squash '' + - [`${name}`](#xp-feature-${name}) + + ${indent " " doc} + ''; +in xps: indent " " (concatStringsSep "\n" (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/local.mk b/doc/manual/local.mk index df941d460..0d4b9d640 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -88,12 +88,12 @@ $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli @cp $< $@ @$(call process-includes,$@,$@) -$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix +$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(bindir)/nix @rm -rf $@ $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix (builtins.readFile $<)' @mv $@.tmp $@ -$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix +$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/src/command-ref/conf-file-prefix.md $(d)/src/command-ref/experimental-features.md $(bindir)/nix @cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp $(trace-gen) $(nix-eval) --expr '(import doc/manual/utils.nix).showSettings { useAnchors = true; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; @mv $@.tmp $@ @@ -106,6 +106,15 @@ $(d)/conf-file.json: $(bindir)/nix $(trace-gen) $(dummy-env) $(bindir)/nix show-config --json --experimental-features nix-command > $@.tmp @mv $@.tmp $@ +$(d)/src/command-ref/experimental-features.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(bindir)/nix + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' + @mv $@.tmp $@ + +$(d)/xp-features.json: $(bindir)/nix + $(trace-gen) $(dummy-env) NIX_PATH=nix/corepkgs=corepkgs $(bindir)/nix __dump-xp-features > $@.tmp + @mv $@.tmp $@ + $(d)/src/language/builtins.md: $(d)/builtins.json $(d)/generate-builtins.nix $(d)/src/language/builtins-prefix.md $(bindir)/nix @cat doc/manual/src/language/builtins-prefix.md > $@.tmp $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; diff --git a/doc/manual/utils.nix b/doc/manual/utils.nix index 5eacce0dd..f78e6bb02 100644 --- a/doc/manual/utils.nix +++ b/doc/manual/utils.nix @@ -74,10 +74,10 @@ rec { if aliases == [] then "" else "**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}"; - indent = prefix: s: - concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); - in result; + indent = prefix: s: + concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); + showSettings = args: settingsInfo: concatStrings (attrValues (mapAttrs (showSetting args) settingsInfo)); } diff --git a/src/libutil/config.hh b/src/libutil/config.hh index a001056f7..8b0fe6555 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -371,8 +371,21 @@ extern GlobalConfig globalConfig; struct ExperimentalFeatureSettings : Config { - Setting> experimentalFeatures{this, {}, "experimental-features", - getExperimentalFeaturesList()}; + Setting> experimentalFeatures{ + this, {}, "experimental-features", + R"( + Experimental features that are enabled. + + Example: + + ``` + experimental-features = nix-command flakes + ``` + + Experimental features available: + + {{#include experimental-features.md}} + )"}; /** * Check whether the given experimental feature is enabled. diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index a64e9715a..010ab1d68 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -140,32 +140,12 @@ std::string_view showExperimentalFeature(const ExperimentalFeature tag) return xpFeatureDetails[(size_t)tag].name; } -std::string getExperimentalFeaturesList() { - std::string experimentalFeaturesList = R"( - Experimental features that can be enabled. - - Example: - - ``` - experimental-features = nix-command flakes - - Experimental features available: - -)"; - - for (auto & xpFeature : xpFeatureDetails) { - experimentalFeaturesList += std::string {} - /* length of this first string must be 12, matching the indent of - the descriptions in the xpFeatureDetails literal. FIXME compute - markdown in a less hacky way. */ - + " - " - + "`" + xpFeature.name + "`" - + "\n" - + xpFeature.description - + "\n\n"; - } - - return experimentalFeaturesList; +nlohmann::json documentExperimentalFeatures() { + StringMap res; + for (auto & xpFeature : xpFeatureDetails) + res[std::string { xpFeature.name }] = + trim(stripIndentation(xpFeature.description)); + return (nlohmann::json) res; } std::set parseFeatures(const std::set & rawFeatures) diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index 3c479dbd9..8ef66263a 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -51,11 +51,9 @@ std::string_view showExperimentalFeature(const ExperimentalFeature); /** * Compute the documentation of all experimental features. * - * This a markdown bulleted list where each item is first (a) the - * experimental feature flag name in backticks, and then (b) the - * description of the experimental feature. + * See `doc/manual` for how this information is used. */ -std::string getExperimentalFeaturesList(); +nlohmann::json documentExperimentalFeatures(); /** * Shorthand for `str << showExperimentalFeature(feature)`. diff --git a/src/nix/main.cc b/src/nix/main.cc index 4d4164333..62b1f98d1 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -374,6 +374,11 @@ void mainWrapped(int argc, char * * argv) return; } + if (argc == 2 && std::string(argv[1]) == "__dump-xp-features") { + logger->cout(documentExperimentalFeatures().dump()); + return; + } + Finally printCompletions([&]() { if (completions) {