From bc5c19d1a9b335ae5b08925caf29d1358ad2fe59 Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Wed, 22 Nov 2023 15:29:06 +0100 Subject: [PATCH] Return the help output structured if requested. (#42) --- examples/main.toit | 2 +- src/help-generator_.toit | 63 +++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/examples/main.toit b/examples/main.toit index 3a794d5..3cbbbea 100644 --- a/examples/main.toit +++ b/examples/main.toit @@ -88,7 +88,7 @@ main arguments: create-status-command -> cli.Command: return cli.Command "status" - --help="Shows the status of the fleet:" + --help="Shows the status of the fleet." --options=[ cli.OptionInt "max-lines" --help="Maximum number of lines to show." --default=10, ] diff --git a/src/help-generator_.toit b/src/help-generator_.toit index 4cc778b..4936613 100644 --- a/src/help-generator_.toit +++ b/src/help-generator_.toit @@ -33,18 +33,67 @@ help-command_ path/List arguments/List --invoked-command/string --ui/Ui: command = subcommand path.add command - print-help_ path --invoked-command=invoked-command --ui=ui + emit-help_ path --invoked-command=invoked-command --ui=ui /** -Prints the help for the given command. +Emits the help for the given command. The command is identified by the $path where the command is the last element. */ -print-help_ path --invoked-command/string --ui/Ui: - generator := HelpGenerator path --invoked-command=invoked-command - generator.build-all - help := generator.to-string - ui.print help +emit-help_ path/List --invoked-command/string --ui/Ui: + ui.do --kind=Ui.RESULT: | printer/Printer | + printer.emit-structured + --json=: build-json-help_ path --invoked-command=invoked-command + --stdout=: + generator := HelpGenerator path --invoked-command=invoked-command + generator.build-all + help := generator.to-string + printer.emit help + +build-json-help_ path/List --invoked-command/string -> Map: + + extract-options := : | command/Command out-map/Map | + options := command.options_.filter: | option/Option | not option.is-hidden + command.options_.do: | option/Option | + if not out-map.contains option.name: + default := option.default + if default != null and default is not bool and default is not num and default is not string and + default is not List and default is not Map: + default = "$default" + json-option := { + "type": option.type, + "is-flag": option.is-flag, + "is-multi": option.is-multi, + "is-required": option.is-required, + } + if not option.is-required: json-option["default"] = default + if option.help: json-option["help"] = option.help + if option.short-name: json-option["short-name"] = option.short-name + out-map[option.name] = json-option + out-map + + command/Command := path.last + + global-options := {:} + for i := path.size - 2; i >= 0; i--: + parent-command := path[i] + extract-options.call parent-command global-options + + json-examples := command.examples_.map: | example/Example | { + "description": example.description, + "arguments": example.arguments, + "global-priority": example.global-priority, + } + + return { + "name": command.name, + "path": path.map: | command/Command | command.name, + "help": command.help_, + "aliases": command.aliases_, + "options": extract-options.call command {:}, + "global-options": global-options, + "examples": json-examples, + } /** Generates the help for a command.