From 4655563470b59e0ef50a33af003058c2b54db778 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Fri, 26 Aug 2022 17:40:34 +0200 Subject: [PATCH] refactor rendering command documentation to markdown idea: - make document structure visible, like in a template - order functions by descending abstraction - avoid nested let bindings --- doc/manual/generate-manpage.nix | 138 ++++++++++++++++---------------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/doc/manual/generate-manpage.nix b/doc/manual/generate-manpage.nix index 7b1ca8c11..c8290685a 100644 --- a/doc/manual/generate-manpage.nix +++ b/doc/manual/generate-manpage.nix @@ -5,10 +5,70 @@ with import ./utils.nix; let - showCommand = - { command, def, filename }: - '' - > **Warning** + showCommand = { command, def, filename }: + let + showSynopsis = command: args: + let + showArgument = arg: "*${arg.label}*" + (if arg ? arity then "" else "..."); + arguments = concatStringsSep " " (map showArgument args); + in '' + `${command}` [*option*...] ${arguments} + ''; + maybeSubcommands = if def ? commands && def.commands != {} + then '' + where *subcommand* is one of the following: + + ${subcommands} + '' + else ""; + subcommands = if length categories > 1 + then listCategories + else listSubcommands def.commands; + categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues def.commands))); + listCategories = concatStrings (map showCategory categories); + showCategory = cat: '' + **${toString cat.description}:** + + ${listSubcommands (filterAttrs (n: v: v.category == cat) def.commands)} + ''; + listSubcommands = cmds: concatStrings (attrValues (mapAttrs showSubcommand cmds)); + showSubcommand = name: subcmd: '' + * [`${command} ${name}`](./${appendName filename name}.md) - ${subcmd.description} + ''; + maybeDocumentation = if def ? doc then def.doc else ""; + maybeOptions = if def.flags == {} then "" else '' + # Options + + ${showOptions def.flags} + ''; + showOptions = flags: + let + categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues flags))); + in + concatStrings (map + (cat: + (if cat != "" + then "**${cat}:**\n\n" + else "") + + concatStrings + (map (longName: + let + flag = flags.${longName}; + in + " - `--${longName}`" + + (if flag ? shortName then " / `-${flag.shortName}`" else "") + + (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "") + + " \n" + + " " + flag.description + "\n\n" + ) (attrNames (filterAttrs (n: v: v.category == cat) flags)))) + categories); + squash = string: # squash more than two repeated newlines + let + replaced = replaceStrings [ "\n\n\n" ] [ "\n\n" ] string; + in + if replaced == string then string else squash replaced; + in squash '' + > **Warning** \ > This program is **experimental** and its interface is subject to change. # Name @@ -17,75 +77,17 @@ let # Synopsis - ${showSynopsis { inherit command; args = def.args; }} + ${showSynopsis command def.args} - '' - + (if def.commands or {} != {} - then - let - categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues def.commands))); - listCommands = cmds: - concatStrings (map (name: - "* " - + "[`${command} ${name}`](./${appendName filename name}.md)" - + " - ${cmds.${name}.description}\n") - (attrNames cmds)); - in '' - where *subcommand* is one of the following: + ${maybeSubcommands} - '' - # FIXME: group by category - + (if length categories > 1 - then - concatStrings (map - (cat: - "**${toString cat.description}:**\n\n" - + listCommands (filterAttrs (n: v: v.category == cat) def.commands) - + "\n" - ) categories) - + "\n" - else - listCommands def.commands - + "\n") - else "") - + (if def ? doc - then def.doc + "\n\n" - else "") - + (let s = showOptions def.flags; in - if s != "" - then "# Options\n\n${s}" - else "") - ; + ${maybeDocumentation} + + ${maybeOptions} + ''; appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name; - showOptions = flags: - let - categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues flags))); - in - concatStrings (map - (cat: - (if cat != "" - then "**${cat}:**\n\n" - else "") - + concatStrings - (map (longName: - let - flag = flags.${longName}; - in - " - `--${longName}`" - + (if flag ? shortName then " / `-${flag.shortName}`" else "") - + (if flag ? labels then " " + (concatStringsSep " " (map (s: "*${s}*") flag.labels)) else "") - + " \n" - + " " + flag.description + "\n\n" - ) (attrNames (filterAttrs (n: v: v.category == cat) flags)))) - categories); - - showSynopsis = - { command, args }: - "`${command}` [*option*...] ${concatStringsSep " " - (map (arg: "*${arg.label}*" + (if arg ? arity then "" else "...")) args)}"; - processCommand = { command, def, filename }: [ { name = filename + ".md"; value = showCommand { inherit command def filename; }; inherit command; } ] ++ concatMap