mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-12-01 18:16:14 +02:00
51a12b38bd
On some systems, previous usage of `match` may cause a stackoverflow (presumably due to the large size of the match result). Avoid this by (ab)using `replaceStrings` to test for containment without using regexes, thereby avoiding the issue. The causal configuration seems to be the stack size hard limit, which e.g. Amazon Linux sets, whereas most Linux distros leave unlimited. Match the fn name to similar fn in nixpkgs.lib, but different implementation that does not use `match`. This impl gives perhaps unexpected results when the needle is `""`, but the scope of this is narrow and that case is a bit odd anyway. This makes for some duplication-of-work as we do a different `replaceStrings` if this one is true, but this only runs during doc generation at build time so has no runtime impact. See https://github.com/NixOS/nix/issues/11085 for details.
207 lines
6.1 KiB
Nix
207 lines
6.1 KiB
Nix
let
|
|
inherit (builtins)
|
|
attrNames
|
|
attrValues
|
|
concatMap
|
|
concatStringsSep
|
|
fromJSON
|
|
groupBy
|
|
length
|
|
lessThan
|
|
listToAttrs
|
|
mapAttrs
|
|
match
|
|
replaceStrings
|
|
sort
|
|
;
|
|
inherit (import <nix/utils.nix>)
|
|
attrsToList
|
|
concatStrings
|
|
filterAttrs
|
|
optionalString
|
|
squash
|
|
trim
|
|
unique
|
|
;
|
|
showStoreDocs = import <nix/generate-store-info.nix>;
|
|
in
|
|
|
|
inlineHTML: commandDump:
|
|
|
|
let
|
|
|
|
commandInfo = fromJSON commandDump;
|
|
|
|
showCommand = { command, details, filename, toplevel }:
|
|
let
|
|
|
|
result = ''
|
|
> **Warning** \
|
|
> This program is
|
|
> [**experimental**](@docroot@/contributing/experimental-features.md#xp-feature-nix-command)
|
|
> and its interface is subject to change.
|
|
|
|
# Name
|
|
|
|
`${command}` - ${details.description}
|
|
|
|
# Synopsis
|
|
|
|
${showSynopsis command details.args}
|
|
|
|
${maybeSubcommands}
|
|
|
|
${maybeProse}
|
|
|
|
${maybeOptions}
|
|
'';
|
|
|
|
showSynopsis = command: args:
|
|
let
|
|
showArgument = arg: "*${arg.label}*" + optionalString (! arg ? arity) "...";
|
|
arguments = concatStringsSep " " (map showArgument args);
|
|
in ''
|
|
`${command}` [*option*...] ${arguments}
|
|
'';
|
|
|
|
maybeSubcommands = optionalString (details ? commands && details.commands != {})
|
|
''
|
|
where *subcommand* is one of the following:
|
|
|
|
${subcommands}
|
|
'';
|
|
|
|
subcommands = if length categories > 1
|
|
then listCategories
|
|
else listSubcommands details.commands;
|
|
|
|
categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues details.commands)));
|
|
|
|
listCategories = concatStrings (map showCategory categories);
|
|
|
|
showCategory = cat: ''
|
|
**${toString cat.description}:**
|
|
|
|
${listSubcommands (filterAttrs (n: v: v.category == cat) details.commands)}
|
|
'';
|
|
|
|
listSubcommands = cmds: concatStrings (attrValues (mapAttrs showSubcommand cmds));
|
|
|
|
showSubcommand = name: subcmd: ''
|
|
* [`${command} ${name}`](./${appendName filename name}.md) - ${subcmd.description}
|
|
'';
|
|
|
|
maybeProse =
|
|
# FIXME: this is a horrible hack to keep `nix help-stores` working.
|
|
let
|
|
help-stores = ''
|
|
${index}
|
|
|
|
${allStores}
|
|
'';
|
|
index = replaceStrings
|
|
[ "@store-types@" "./local-store.md" "./local-daemon-store.md" ]
|
|
[ storesOverview "#local-store" "#local-daemon-store" ]
|
|
details.doc;
|
|
storesOverview =
|
|
let
|
|
showEntry = store:
|
|
"- [${store.name}](#${store.slug})";
|
|
in
|
|
concatStringsSep "\n" (map showEntry storesList) + "\n";
|
|
allStores = concatStringsSep "\n" (attrValues storePages);
|
|
storePages = listToAttrs
|
|
(map (s: { name = s.filename; value = s.page; }) storesList);
|
|
storesList = showStoreDocs {
|
|
storeInfo = commandInfo.stores;
|
|
inherit inlineHTML;
|
|
};
|
|
hasInfix = infix: content:
|
|
builtins.stringLength content != builtins.stringLength (replaceStrings [ infix ] [ "" ] content);
|
|
in
|
|
optionalString (details ? doc) (
|
|
# An alternate implementation with builtins.match stack overflowed on some systems.
|
|
if hasInfix "@store-types@" details.doc
|
|
then help-stores
|
|
else details.doc
|
|
);
|
|
|
|
maybeOptions =
|
|
let
|
|
allVisibleOptions = filterAttrs
|
|
(_: o: ! o.hiddenCategory)
|
|
(details.flags // toplevel.flags);
|
|
in
|
|
optionalString (allVisibleOptions != { }) ''
|
|
# Options
|
|
|
|
${showOptions inlineHTML allVisibleOptions}
|
|
|
|
> **Note**
|
|
>
|
|
> See [`man nix.conf`](@docroot@/command-ref/conf-file.md#command-line-flags) for overriding configuration settings with command line flags.
|
|
'';
|
|
|
|
showOptions = inlineHTML: allOptions:
|
|
let
|
|
showCategory = cat: opts: ''
|
|
${optionalString (cat != "") "## ${cat}"}
|
|
|
|
${concatStringsSep "\n" (attrValues (mapAttrs showOption opts))}
|
|
'';
|
|
showOption = name: option:
|
|
let
|
|
result = trim ''
|
|
- ${item}
|
|
|
|
${option.description}
|
|
'';
|
|
item = if inlineHTML
|
|
then ''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}''
|
|
else "`--${name}` ${shortName} ${labels}";
|
|
shortName = optionalString
|
|
(option ? shortName)
|
|
("/ `-${option.shortName}`");
|
|
labels = optionalString
|
|
(option ? labels)
|
|
(concatStringsSep " " (map (s: "*${s}*") option.labels));
|
|
in result;
|
|
categories = mapAttrs
|
|
# Convert each group from a list of key-value pairs back to an attrset
|
|
(_: listToAttrs)
|
|
(groupBy
|
|
(cmd: cmd.value.category)
|
|
(attrsToList allOptions));
|
|
in concatStrings (attrValues (mapAttrs showCategory categories));
|
|
in squash result;
|
|
|
|
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
|
|
|
|
processCommand = { command, details, filename, toplevel }:
|
|
let
|
|
cmd = {
|
|
inherit command;
|
|
name = filename + ".md";
|
|
value = showCommand { inherit command details filename toplevel; };
|
|
};
|
|
subcommand = subCmd: processCommand {
|
|
command = command + " " + subCmd;
|
|
details = details.commands.${subCmd};
|
|
filename = appendName filename subCmd;
|
|
inherit toplevel;
|
|
};
|
|
in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {});
|
|
|
|
manpages = processCommand {
|
|
command = "nix";
|
|
details = commandInfo.args;
|
|
filename = "nix";
|
|
toplevel = commandInfo.args;
|
|
};
|
|
|
|
tableOfContents = let
|
|
showEntry = page:
|
|
" - [${page.command}](command-ref/new-cli/${page.name})";
|
|
in concatStringsSep "\n" (map showEntry manpages) + "\n";
|
|
|
|
in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; }
|